;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
-;; Version: 6.12a
+;; Version: 6.13
;;
;; This file is part of GNU Emacs.
;;
(defcustom org-clock-persist nil
"When non-nil, save the running clock when emacs is closed, and
- resume it next time emacs is started."
+ resume it next time emacs is started.
+When this is t, both the running clock, and the entire clock
+history are saved. When this is the symbol `clock', only the
+running clock is saved.
+
+When Emacs restarts with saved clock information, the file containing the
+running clock as well as all files mentioned in the clock history will
+be visited."
:group 'org-clock
- :type 'boolean)
+ :type '(choice
+ (const :tag "Just the running clock" clock)
+ (const :tag "Clock and history" t)
+ (const :tag "No persistence" nil)))
(defcustom org-clock-persist-file "~/.emacs.d/org-clock-save.el"
"File to save clock data to"
'help-echo (concat help-text ": " org-clock-heading))
(org-propertize clock-string 'help-echo help-text)))
'local-map org-clock-mode-map
- 'mouse-face '(face mode-line-highlight)))
+ 'mouse-face (if (featurep 'xemacs) 'highlight 'mode-line-highlight)))
(force-mode-line-update)))
(defvar org-clock-mode-line-entry nil
is as the default task, a special task that will always be offered in
the clocking selection, associated with the letter `d'."
(interactive "P")
- (let ((interrupting (marker-buffer org-clock-marker))
- ts selected-task target-pos)
- (when (equal select '(4))
- (setq selected-task (org-clock-select-task "Clock-in on task: "))
- (if selected-task
- (setq selected-task (copy-marker selected-task))
- (error "Abort")))
- (when interrupting
- ;; We are interrupting the clocking of a differnt task.
- ;; Save a marker to this task, so that we can go back.
- (move-marker org-clock-interrupted-task
- (marker-position org-clock-marker)
- (marker-buffer org-clock-marker))
- (org-clock-out t))
-
- (when (equal select '(16))
- ;; Mark as default clocking task
- (save-excursion
- (org-back-to-heading t)
- (move-marker org-clock-default-task (point))))
-
- (setq target-pos (point)) ;; we want to clock in at this location
- (save-excursion
- (when (and selected-task (marker-buffer selected-task))
- ;; There is a selected task, move to the correct buffer
- ;; and set the new target position.
- (set-buffer (org-base-buffer (marker-buffer selected-task)))
- (setq target-pos (marker-position selected-task))
- (move-marker selected-task nil))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char target-pos)
+ (catch 'abort
+ (let ((interrupting (marker-buffer org-clock-marker))
+ ts selected-task target-pos)
+ (when (equal select '(4))
+ (setq selected-task (org-clock-select-task "Clock-in on task: "))
+ (if selected-task
+ (setq selected-task (copy-marker selected-task))
+ (error "Abort")))
+ (when interrupting
+ ;; We are interrupting the clocking of a differnt task.
+ ;; Save a marker to this task, so that we can go back.
+ (move-marker org-clock-interrupted-task
+ (marker-position org-clock-marker)
+ (marker-buffer org-clock-marker))
+ (org-clock-out t))
+
+ (when (equal select '(16))
+ ;; Mark as default clocking task
+ (save-excursion
(org-back-to-heading t)
- (or interrupting (move-marker org-clock-interrupted-task nil))
- (org-clock-history-push)
- (cond ((functionp org-clock-in-switch-to-state)
- (looking-at org-complex-heading-regexp)
- (let ((newstate (funcall org-clock-in-switch-to-state (match-string 2))))
- (if newstate (org-todo newstate))))
- ((and org-clock-in-switch-to-state
- (not (looking-at (concat outline-regexp "[ \t]*"
- org-clock-in-switch-to-state
- "\\>"))))
- (org-todo org-clock-in-switch-to-state)))
- (setq org-clock-heading-for-remember
- (and (looking-at org-complex-heading-regexp)
- (match-end 4)
- (org-trim (buffer-substring (match-end 1) (match-end 4)))))
- (setq org-clock-heading
- (cond ((and org-clock-heading-function
- (functionp org-clock-heading-function))
- (funcall org-clock-heading-function))
- ((looking-at org-complex-heading-regexp)
- (match-string 4))
- (t "???")))
- (setq org-clock-heading (org-propertize org-clock-heading 'face nil))
- (org-clock-find-position)
- (if (and org-clock-in-resume
- (looking-at (concat "^[ \\t]* " org-clock-string
- " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}"
- " +\\sw+ +[012][0-9]:[0-5][0-9]\\)\\]$")))
- (progn (message "Matched %s" (match-string 1))
- (setq ts (concat "[" (match-string 1) "]"))
- (goto-char (match-end 1))
- (setq org-clock-start-time
- (apply 'encode-time (org-parse-time-string (match-string 1)))))
- (progn
+ (move-marker org-clock-default-task (point))))
+
+ (setq target-pos (point)) ;; we want to clock in at this location
+ (save-excursion
+ (when (and selected-task (marker-buffer selected-task))
+ ;; There is a selected task, move to the correct buffer
+ ;; and set the new target position.
+ (set-buffer (org-base-buffer (marker-buffer selected-task)))
+ (setq target-pos (marker-position selected-task))
+ (move-marker selected-task nil))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char target-pos)
+ (org-back-to-heading t)
+ (or interrupting (move-marker org-clock-interrupted-task nil))
+ (org-clock-history-push)
+ (cond ((functionp org-clock-in-switch-to-state)
+ (looking-at org-complex-heading-regexp)
+ (let ((newstate (funcall org-clock-in-switch-to-state
+ (match-string 2))))
+ (if newstate (org-todo newstate))))
+ ((and org-clock-in-switch-to-state
+ (not (looking-at (concat outline-regexp "[ \t]*"
+ org-clock-in-switch-to-state
+ "\\>"))))
+ (org-todo org-clock-in-switch-to-state)))
+ (setq org-clock-heading-for-remember
+ (and (looking-at org-complex-heading-regexp)
+ (match-end 4)
+ (org-trim (buffer-substring (match-end 1)
+ (match-end 4)))))
+ (setq org-clock-heading
+ (cond ((and org-clock-heading-function
+ (functionp org-clock-heading-function))
+ (funcall org-clock-heading-function))
+ ((looking-at org-complex-heading-regexp)
+ (match-string 4))
+ (t "???")))
+ (setq org-clock-heading (org-propertize org-clock-heading
+ 'face nil))
+ (org-clock-find-position)
+ (cond
+ ((and org-clock-in-resume
+ (looking-at
+ (concat "^[ \\t]* " org-clock-string
+ " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}"
+ " +\\sw+ +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$")))
+ (message "Matched %s" (match-string 1))
+ (setq ts (concat "[" (match-string 1) "]"))
+ (goto-char (match-end 1))
+ (setq org-clock-start-time
+ (apply 'encode-time
+ (org-parse-time-string (match-string 1)))))
+ ((eq org-clock-in-resume 'auto-restart)
+ ;; called from org-clock-load during startup,
+ ;; do not interrupt, but warn!
+ (message "Cannot restart clock because task does not contain unfinished clock")
+ (ding)
+ (sit-for 2)
+ (throw 'abort nil))
+ (t
(insert "\n") (backward-char 1)
(org-indent-line-function)
(insert org-clock-string " ")
(setq org-clock-start-time (current-time))
(setq ts (org-insert-time-stamp org-clock-start-time 'with-hm 'inactive))))
- (move-marker org-clock-marker (point) (buffer-base-buffer))
- (or global-mode-string (setq global-mode-string '("")))
- (or (memq 'org-mode-line-string global-mode-string)
- (setq global-mode-string
- (append global-mode-string '(org-mode-line-string))))
- (org-update-mode-line)
- (setq org-mode-line-timer
- (run-with-timer 60 60 'org-update-mode-line))
- (message "Clock started at %s" ts))))))
+ (move-marker org-clock-marker (point) (buffer-base-buffer))
+ (or global-mode-string (setq global-mode-string '("")))
+ (or (memq 'org-mode-line-string global-mode-string)
+ (setq global-mode-string
+ (append global-mode-string '(org-mode-line-string))))
+ (org-update-mode-line)
+ (setq org-mode-line-timer
+ (run-with-timer 60 60 'org-update-mode-line))
+ (message "Clock started at %s" ts)))))))
(defun org-clock-find-position ()
"Find the location where the next clock line should be inserted."
(block (plist-get params :block))
(link (plist-get params :link))
ipos time p level hlc hdl content recalc formula pcol
- cc beg end pos tbl tbl1 range-text rm-file-column scope-is-list)
+ cc beg end pos tbl tbl1 range-text rm-file-column scope-is-list st)
(setq org-clock-file-total-minutes nil)
(when step
(unless (or block (and ts te))
(unless scope-is-list
(org-clock-sum ts te)
(goto-char (point-min))
- (while (setq p (next-single-property-change (point) :org-clock-minutes))
+ (setq st t)
+ (while (or (and (bobp) (prog1 st (setq st nil))
+ (get-text-property (point) :org-clock-minutes)
+ (setq p (point-min)))
+ (setq p (next-single-property-change (point) :org-clock-minutes)))
(goto-char p)
(when (setq time (get-text-property p :org-clock-minutes))
(save-excursion
0))))
(defun org-clock-save ()
- "Persist various clock-related data to disk"
- (with-current-buffer (find-file (expand-file-name org-clock-persist-file))
- (progn (delete-region (point-min) (point-max))
- ;;Store clock
- (insert (format ";; org-persist.el - %s at %s\n"
- system-name (format-time-string
- (cdr org-time-stamp-formats))))
- (if (and org-clock-persist (marker-buffer org-clock-marker)
- (or (not org-clock-persist-query-save)
- (y-or-n-p (concat "Save current clock ("
- (substring-no-properties org-clock-heading)
- ")"))))
- (insert "(setq resume-clock '(\""
- (buffer-file-name (marker-buffer org-clock-marker))
- "\" . " (int-to-string (marker-position org-clock-marker))
- "))\n"))
- ;;Store clocked task history. Tasks are stored reversed to make
- ;;reading simpler
- (if org-clock-history
- (insert "(setq stored-clock-history '("
- (mapconcat
- (lambda (m)
- (when (marker-buffer m)
- (concat "(\"" (buffer-file-name (marker-buffer m))
- "\" . " (int-to-string (marker-position m))
- ")")))
- (reverse org-clock-history) " ") "))\n"))
- (save-buffer)
- (kill-buffer (current-buffer)))))
-
-(defvar org-clock-loaded nil)
+ "Persist various clock-related data to disk.
+The details of what will be saved are regulated by the variable
+`org-clock-persist'."
+ (when org-clock-persist
+ (let (b)
+ (with-current-buffer (find-file (expand-file-name org-clock-persist-file))
+ (progn
+ (delete-region (point-min) (point-max))
+ ;;Store clock
+ (insert (format ";; org-persist.el - %s at %s\n"
+ system-name (format-time-string
+ (cdr org-time-stamp-formats))))
+ (if (and (setq b (marker-buffer org-clock-marker))
+ (setq b (or (buffer-base-buffer b) b))
+ (buffer-live-p b)
+ (buffer-file-name b)
+ (or (not org-clock-persist-query-save)
+ (y-or-n-p (concat "Save current clock ("
+ (substring-no-properties org-clock-heading)
+ ") "))))
+ (insert "(setq resume-clock '(\""
+ (buffer-file-name (marker-buffer org-clock-marker))
+ "\" . " (int-to-string (marker-position org-clock-marker))
+ "))\n"))
+ ;; Store clocked task history. Tasks are stored reversed to make
+ ;; reading simpler
+ (when (and org-clock-history (eq org-clock-persist t))
+ (insert
+ "(setq stored-clock-history '("
+ (mapconcat
+ (lambda (m)
+ (when (and (setq b (marker-buffer m))
+ (setq b (or (buffer-base-buffer b) b))
+ (buffer-live-p b)
+ (buffer-file-name b))
+ (concat "(\"" (buffer-file-name b)
+ "\" . " (int-to-string (marker-position m))
+ ")")))
+ (reverse org-clock-history) " ") "))\n"))
+ (save-buffer)
+ (kill-buffer (current-buffer)))))))
+
+(defvar org-clock-loaded nil
+ "Was the clock file loaded?")
(defun org-clock-load ()
"Load various clock-related data from disk, optionally resuming
a stored clock"
- (if (not org-clock-loaded)
- (let ((filename (expand-file-name org-clock-persist-file))
- (org-clock-in-resume t))
- (if (file-readable-p filename)
- (progn
- (message "%s" "Restoring clock data")
- (setq org-clock-loaded t)
- (load-file filename)
- ;; load history
- (if (boundp 'stored-clock-history)
- (save-window-excursion
- (mapc (lambda (task)
- (org-clock-history-push (cdr task)
- (find-file (car task))))
- stored-clock-history)))
- ;; resume clock
- (if (and (boundp 'resume-clock) org-clock-persist
- (or (not org-clock-persist-query-resume)
- (y-or-n-p
- (concat
- "Resume clock ("
- (with-current-buffer (find-file (car resume-clock))
- (progn (goto-char (cdr resume-clock))
- (looking-at org-complex-heading-regexp)
- (match-string 4))) ")"))))
- (with-current-buffer (find-file (car resume-clock))
- (progn (goto-char (cdr resume-clock))
- (org-clock-in)))))
+ (when (and org-clock-persist (not org-clock-loaded))
+ (let ((filename (expand-file-name org-clock-persist-file))
+ (org-clock-in-resume 'auto-restart)
+ resume-clock stored-clock-history)
+ (if (not (file-readable-p filename))
(message "Not restoring clock data; %s not found"
- org-clock-persist-file)))))
+ org-clock-persist-file)
+ (message "%s" "Restoring clock data")
+ (setq org-clock-loaded t)
+ (load-file filename)
+ ;; load history
+ (when stored-clock-history
+ (save-window-excursion
+ (mapc (lambda (task)
+ (if (file-exists-p (car task))
+ (org-clock-history-push (cdr task)
+ (find-file (car task)))))
+ stored-clock-history)))
+ ;; resume clock
+ (when (and resume-clock org-clock-persist
+ (file-exists-p (car resume-clock))
+ (or (not org-clock-persist-query-resume)
+ (y-or-n-p
+ (concat
+ "Resume clock ("
+ (with-current-buffer (find-file (car resume-clock))
+ (save-excursion
+ (goto-char (cdr resume-clock))
+ (org-back-to-heading t)
+ (and (looking-at org-complex-heading-regexp)
+ (match-string 4))))
+ ") "))))
+ (when (file-exists-p (car resume-clock))
+ (with-current-buffer (find-file (car resume-clock))
+ (goto-char (cdr resume-clock))
+ (org-clock-in)
+ (if (org-invisible-p)
+ (org-show-context)))))))))
;;;###autoload
(defun org-clock-persistence-insinuate ()