From mboxrd@z Thu Jan 1 00:00:00 1970 From: James TD Smith Subject: [PATCH] Allow storing clock status between emacs sessions. Date: Sun, 19 Oct 2008 17:22:18 +0100 Message-ID: <1224433338-16661-2-git-send-email-ahktenzero@mohorovi.cc> References: <1224433338-16661-1-git-send-email-ahktenzero@mohorovi.cc> Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Krb2x-0000Bp-SR for emacs-orgmode@gnu.org; Sun, 19 Oct 2008 12:22:27 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Krb2x-0000BJ-0n for emacs-orgmode@gnu.org; Sun, 19 Oct 2008 12:22:27 -0400 Received: from [199.232.76.173] (port=42888 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Krb2w-0000BE-Q5 for emacs-orgmode@gnu.org; Sun, 19 Oct 2008 12:22:26 -0400 Received: from 81-86-40-42.dsl.pipex.com ([81.86.40.42]:60098 helo=yog-sothoth.mohorovi.cc) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Krb2w-00054j-1g for emacs-orgmode@gnu.org; Sun, 19 Oct 2008 12:22:26 -0400 In-Reply-To: <1224433338-16661-1-git-send-email-ahktenzero@mohorovi.cc> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org Clock-related data are saved when exiting emacs ands restored when emacs is restarted. The data saved include the contents of `org-clock-history', and the running clock, if there is one. To use this, you will need to add (require 'org-clock) (org-clock-persistence-insinuate) to your .emacs and either add (setq org-clock-persist t) (setq org-clock-in-resume t) or set those options to t in custom. The patch also optionally changes the behaviour of `org-clock-in'; if `org-clock-in-resume' is set, and you clock into a task with an open clock line, org will resume the clock from that time. Also fix a couple of typos in the changelog --- lisp/ChangeLog | 31 +++++++++++++- lisp/org-clock.el | 117 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 138 insertions(+), 10 deletions(-) mode change 100755 => 100644 lisp/ChangeLog diff --git a/lisp/ChangeLog b/lisp/ChangeLog old mode 100755 new mode 100644 index ad7c9fe..8b836eb --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,27 @@ 2008-10-19 James TD Smith + * org-clock.el (org-clock-persist): Add a custom option to toggle + clock persistence. + (org-clock-persist-query-save): Add a custom option to toggle + asking the user if they want to save the running clock when + exiting. + (org-clock-persist-query-resume): Add a custom option to toggle + asking the user if they want to resume the saved clock when Emacs + is restarted. + (org-clock-save): Add a function to save clock data. + This includes the contents of `org-clock-history' and the buffer + and position of the currently clocked task, if any. + (org-clock-load): Add a function to load clock data. + This populates `org-clock-history', and resumes the saved clocked + task if there is one. + (org-clock-persistence-insinuate): Add a method to set up the + hooks for clock persistence. + (org-clock-in-resume): Add a custom option to toggle starting the + clock from an open clock line. + (org-clock-in): When clocking in to an entry, if + `org-clock-in-resume' is set, check if the first clock line is + open and if so, start the clock from the time in the clock line. + * org.el (org-add-log-setup): Bugfix; code to find insertion point after drawers was skipping ahead one line too many, so notes were inserted after the first note instead of before it. @@ -21,7 +43,7 @@ * org.el (org-clock-update-time-maybe): Compute negative clock intervals correctly. -2008-10-15 James TD Smith +2008-10-16 James TD Smith * org.el (org-add-log-setup): Only skip drawers if the are immediately after the scheduling keywords. @@ -34,6 +56,9 @@ (org-clock-in): Use org-indent-line-function to indent clock lines. (org-clock-find-position): Fix indentation of empty clock drawers. + * org.el (org-add-log-setup): Only skip drawers if the are + immediately after the scheduling keywords. + 2008-10-16 Carsten Dominik * org.el (org-add-log-setup): Respect @@ -125,7 +150,7 @@ * org-clock.el (org-clock-heading-for-remember): New variable. (org-clock-in): Set `org-clock-heading-for-remember'. -2008-10-01 James TD Smith +2008-10-01 James TD Smith * org-remember.el (org-remember-apply-template): Add new expansions: %k, %K for currently clocked task and a link to the @@ -234,7 +259,7 @@ * org-export-latex.el (org-export-latex-keywords-maybe): Bug fix. -2008-09-22 James TA Smith +2008-09-22 James TD Smith * org-plot.el (org-plot/gnuplot): Make tables starting with a hline work correctly. diff --git a/lisp/org-clock.el b/lisp/org-clock.el index 56894cc..d932f02 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -95,6 +95,34 @@ The function is called with point at the beginning of the headline." :group 'org-clock :type 'integer) +(defcustom org-clock-persist nil + "When non-nil, save the running clock when emacs is closed, and + resume it next time emacs is started." + :group 'org-clock + :type 'boolean) + +(defcustom org-clock-persist-file "~/.emacs.d/org-clock-save.el" + "File to save clock data to" + :group 'org-clock + :type 'string) + +(defcustom org-clock-persist-query-save nil + "When non-nil, ask before saving the current clock on exit" + :group 'org-clock + :type 'boolean) + +(defcustom org-clock-persist-query-resume t + "When non-nil, ask before resuming any stored clock during +load." + :group 'org-clock + :type 'boolean) + +(defcustom org-clock-in-resume nil + "If non-nil, when clocking into a task with a clock entry which +has not been closed, resume the clock from that point" + :group 'org-clock + :type 'boolean) + ;;; The clock for measuring work time. (defvar org-mode-line-string "") @@ -291,12 +319,20 @@ the clocking selection, associated with the letter `d'." (t "???"))) (setq org-clock-heading (org-propertize org-clock-heading 'face nil)) (org-clock-find-position) - - (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 (current-time) 'with-hm 'inactive)) + (setq open-clock-regex + (concat "^[ \\t]* " org-clock-string + " \\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +\\sw+ +[012][0-9]:[0-5][0-9]\\)\\]$")) + (if (and org-clock-in-resume (looking-at open-clock-regex)) + (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 + (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) @@ -962,7 +998,6 @@ the currently selected interval size." (re-search-forward "#\\+END:") (end-of-line 0)))) - (defun org-clocktable-add-file (file table) (if table (let ((lines (org-split-string table "\n")) @@ -975,6 +1010,74 @@ the currently selected interval size." lines) "\n")))) +(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 (time-stamp-string))) + (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) + +(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 "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))))) + (message "Not restoring clock data; %s not found" + org-clock-persist-file))))) + +(defun org-clock-persistence-insinuate () + "Set up hooks for clock persistence" + (add-hook 'org-mode-hook 'org-clock-load) + (add-hook 'kill-emacs-hook 'org-clock-save)) + (provide 'org-clock) ;; arch-tag: 7b42c5d4-9b36-48be-97c0-66a869daed4c -- 1.5.6.5