From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bernt Hansen Subject: [PATCH] Add org-clock-clocking-in for hooks Date: Thu, 20 May 2010 11:14:01 -0400 Message-ID: <1274368441-4727-1-git-send-email-bernt@norang.ca> Return-path: Received: from [140.186.70.92] (port=54737 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OF7SJ-0006nW-9F for emacs-orgmode@gnu.org; Thu, 20 May 2010 11:20:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OF7Rw-0002sQ-42 for emacs-orgmode@gnu.org; Thu, 20 May 2010 11:14:26 -0400 Received: from mho-01-ewr.mailhop.org ([204.13.248.71]:60138) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OF7Ru-0002rb-2G for emacs-orgmode@gnu.org; Thu, 20 May 2010 11:14:14 -0400 Received: from cpe000102d0fe75-cm0012256ecbde.cpe.net.cable.rogers.com ([99.239.148.180] helo=mail.norang.ca) by mho-01-ewr.mailhop.org with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.68) (envelope-from ) id 1OF7Rt-000Enj-C7 for emacs-orgmode@gnu.org; Thu, 20 May 2010 15:14:13 +0000 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 Cc: Bernt Hansen org-clock-out-hook can now query org-clock-clocking-in to see if org-clock-out is being called inside org-clock-in. This allows the hook to selectively clock in another task without leaving clocks open. --- I've radically changed my clocking setup and needed the following patch to make it work. This basically just wraps the entire org-clock-in function in a let statement that sets org-clock-clocking-in to true for the duration of the org-clock-in call. I'm testing a new org-clock-out-hook which automatically clocks in the default task when clocking time in a context. After things settle I'll be updating my http://doc.norang.ca/org-mode.html setup information to include these changes. This patch is available at git://git.norang.ca/org-mode.git persistent-clocking lisp/org-clock.el | 311 +++++++++++++++++++++++++++-------------------------- 1 files changed, 157 insertions(+), 154 deletions(-) diff --git a/lisp/org-clock.el b/lisp/org-clock.el index 68a40ce..e24300d 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -911,6 +911,8 @@ so long." 60.0)))) org-clock-user-idle-start))))) +(setq org-clock-clocking-in nil) + (defun org-clock-in (&optional select start-time) "Start the clock on the current item. If necessary, clock-out of the currently active clock. @@ -919,31 +921,32 @@ clock into. When SELECT is `C-u C-u', clock into the current task and mark is as the default task, a special task that will always be offered in the clocking selection, associated with the letter `d'." (interactive "P") - (setq org-clock-notification-was-shown nil) - (catch 'abort - (let ((interrupting (and (not org-clock-resolving-clocks-due-to-idleness) - (org-clocking-p))) - ts selected-task target-pos (msg-extra "") - (leftover (and (not org-clock-resolving-clocks) - org-clock-leftover-time))) - (when (and org-clock-auto-clock-resolution - (or (not interrupting) - (eq t org-clock-auto-clock-resolution)) - (not org-clock-clocking-in) - (not org-clock-resolving-clocks)) - (setq org-clock-leftover-time nil) - (let ((org-clock-clocking-in t)) - (org-resolve-clocks))) ; check if any clocks are dangling - (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 different task. - ;; Save a marker to this task, so that we can go back. - ;; First check if we are trying to clock into the same task! - (if (save-excursion + (let ((org-clock-clocking-in t)) + (setq org-clock-notification-was-shown nil) + (catch 'abort + (let ((interrupting (and (not org-clock-resolving-clocks-due-to-idleness) + (org-clocking-p))) + ts selected-task target-pos (msg-extra "") + (leftover (and (not org-clock-resolving-clocks) + org-clock-leftover-time))) + (when (and org-clock-auto-clock-resolution + (or (not interrupting) + (eq t org-clock-auto-clock-resolution)) + (not org-clock-clocking-in) + (not org-clock-resolving-clocks)) + (setq org-clock-leftover-time nil) + (let ((org-clock-clocking-in t)) + (org-resolve-clocks))) ; check if any clocks are dangling + (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 different task. + ;; Save a marker to this task, so that we can go back. + ;; First check if we are trying to clock into the same task! + (if (save-excursion (unless selected-task (org-back-to-heading t)) (and (equal (marker-buffer org-clock-hd-marker) @@ -954,136 +957,136 @@ the clocking selection, associated with the letter `d'." (if selected-task (marker-position selected-task) (point))))) - (message "Clock continues in \"%s\"" org-clock-heading) - (progn - (move-marker org-clock-interrupted-task - (marker-position org-clock-marker) - (org-clocking-buffer)) - (org-clock-out t)))) - - (when (equal select '(16)) - ;; Mark as default clocking task - (org-clock-mark-default-task)) - - ;; Clock in at which position? - (setq target-pos - (if (and (eobp) (not (org-on-heading-p))) - (point-at-bol 0) - (point))) - (run-hooks 'org-clock-in-prepare-hook) - (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)) + (message "Clock continues in \"%s\"" org-clock-heading) + (progn + (move-marker org-clock-interrupted-task + (marker-position org-clock-marker) + (org-clocking-buffer)) + (org-clock-out t)))) + + (when (equal select '(16)) + ;; Mark as default clocking task + (org-clock-mark-default-task)) + + ;; Clock in at which position? + (setq target-pos + (if (and (eobp) (not (org-on-heading-p))) + (point-at-bol 0) + (point))) + (run-hooks 'org-clock-in-prepare-hook) (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) - (org-clock-set-current) - (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) - (replace-regexp-in-string - "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1" - (match-string 4))) - (t "???"))) - (setq org-clock-heading (org-propertize org-clock-heading - 'face nil)) - (org-clock-find-position org-clock-in-resume) - (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)))) - (setq org-clock-effort (org-get-effort)) - (setq org-clock-total-time (org-clock-sum-current-item - (org-clock-get-sum-start)))) - ((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-before-markers "\n") - (backward-char 1) - (org-indent-line-function) - (when (and (save-excursion - (end-of-line 0) - (org-in-item-p))) - (beginning-of-line 1) - (org-indent-line-to (- (org-get-indentation) 2))) - (insert org-clock-string " ") - (setq org-clock-effort (org-get-effort)) - (setq org-clock-total-time (org-clock-sum-current-item - (org-clock-get-sum-start))) - (setq org-clock-start-time - (or (and leftover - (y-or-n-p - (format - "You stopped another clock %d mins ago; start this one from then? " - (/ (- (org-float-time (current-time)) - (org-float-time leftover)) 60))) - leftover) - 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)) - (move-marker org-clock-hd-marker - (save-excursion (org-back-to-heading t) (point)) - (buffer-base-buffer)) - (setq org-clock-has-been-used t) - (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-clock-update-mode-line) - (when org-clock-mode-line-timer - (cancel-timer org-clock-mode-line-timer) - (setq org-clock-mode-line-timer nil)) - (setq org-clock-mode-line-timer - (run-with-timer org-clock-update-period - org-clock-update-period - 'org-clock-update-mode-line)) - (when org-clock-idle-timer - (cancel-timer org-clock-idle-timer) - (setq org-clock-idle-timer nil)) - (setq org-clock-idle-timer - (run-with-timer 60 60 'org-resolve-clocks-if-idle)) - (message "Clock starts at %s - %s" ts msg-extra) - (run-hooks 'org-clock-in-hook))))))) + (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) + (org-clock-set-current) + (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) + (replace-regexp-in-string + "\\[\\[.*?\\]\\[\\(.*?\\)\\]\\]" "\\1" + (match-string 4))) + (t "???"))) + (setq org-clock-heading (org-propertize org-clock-heading + 'face nil)) + (org-clock-find-position org-clock-in-resume) + (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)))) + (setq org-clock-effort (org-get-effort)) + (setq org-clock-total-time (org-clock-sum-current-item + (org-clock-get-sum-start)))) + ((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-before-markers "\n") + (backward-char 1) + (org-indent-line-function) + (when (and (save-excursion + (end-of-line 0) + (org-in-item-p))) + (beginning-of-line 1) + (org-indent-line-to (- (org-get-indentation) 2))) + (insert org-clock-string " ") + (setq org-clock-effort (org-get-effort)) + (setq org-clock-total-time (org-clock-sum-current-item + (org-clock-get-sum-start))) + (setq org-clock-start-time + (or (and leftover + (y-or-n-p + (format + "You stopped another clock %d mins ago; start this one from then? " + (/ (- (org-float-time (current-time)) + (org-float-time leftover)) 60))) + leftover) + 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)) + (move-marker org-clock-hd-marker + (save-excursion (org-back-to-heading t) (point)) + (buffer-base-buffer)) + (setq org-clock-has-been-used t) + (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-clock-update-mode-line) + (when org-clock-mode-line-timer + (cancel-timer org-clock-mode-line-timer) + (setq org-clock-mode-line-timer nil)) + (setq org-clock-mode-line-timer + (run-with-timer org-clock-update-period + org-clock-update-period + 'org-clock-update-mode-line)) + (when org-clock-idle-timer + (cancel-timer org-clock-idle-timer) + (setq org-clock-idle-timer nil)) + (setq org-clock-idle-timer + (run-with-timer 60 60 'org-resolve-clocks-if-idle)) + (message "Clock starts at %s - %s" ts msg-extra) + (run-hooks 'org-clock-in-hook)))))))) (defvar org-clock-current-task nil "Task currently clocked in.") -- 1.7.1.86.g0e460