Re: [O] Triggering clock in/out from org state change and progress logging
Hi list, after struggling a bit with edebug (too many things to learn) I have traced what the problem is. For the archives: State-change logging is deferred until the command finishes and is implemented by the function 'org-add-log-setup' adding the function 'org-add-log-note' to the hook 'post-command-hook'. The details of the note are stored in global variables 'org-log-note-xxx'. That implementation prevents recursive calls to 'org-todo' (that's what my code does in order the pause the active task) from logging both the paused and the started log messages. 'org-add-log-note' will be called only once since the hook won't accept duplicated entries. Anyway, the innermost call to 'org-add-log-setup' will overwrite the variables 'org-log-note-xxx' with the details of the note being paused. The outcome is that only the state change for the paused note is being logged. Now that I know what the problem is I only have to figure a workaround. Any clue? Regards
[O] Triggering clock in/out from org state change and progress logging
Hi list, as part of learning org I'm trying to configure it so that state changes trigger clocking in/out tasks. Why testing workflow is: #+TODO: TODO(t) STRT(s!) PAUS(p!) WAIT(w!) | DONE(d!) CANC(c!) What I try to accomplish: * entering STRT pauses the active task (if any) and clocks-in the current task. * entering PAUS or WAIT clocks-out the current task (if clocking the current task). * entering TODO probably should reset the current task but I don't care at that point. Changing state and clocking in/out works great but logging is weird: * Tasks ** STRT first task - State "STRT" from "TODO" [2014-08-26 dt 12:27] :20: CLOCK: [2014-08-26 dt 12:27] :END: ** TODO second task Now I change "second task" from TODO to STRT: * Tasks ** PAUS first task - State "PAUS" from "STRT" [2014-08-26 dt 12:28] - State "STRT" from "TODO" [2014-08-26 dt 12:27] :20: CLOCK: [2014-08-26 dt 12:27]--[2014-08-26 dt 12:28] => 0:01 :END: ** STRT second task :20: CLOCK: [2014-08-26 dt 12:28] :END: "first taks" gets paused and "second task" is started and clocking but no logging "State 'STRT' from 'TODO' ..." is added to "second task". Starting a task only logs in the other task. After 6 hours struggling with that (clocked with org :) ) I can't figure why that's happening. Any clue? Thanks in advance Here's the code: (defvar arv/org-todo-entering-state-clocking-actions '(("STRT" . start) ("PAUS" . stop) ("WAIT" . stop))) (defvar arv/org-todo-state-change-triggers-clocking-enabled t) (defvar arv/org-todo-paused-state "PAUS") (defun arv/org-todo--pause-other-task () (when (org-clock-is-active) (save-excursion (org-clock-goto) (org-clock-out) (let ((arv/org-todo-state-change-triggers-clocking-enabled nil)) ; avoid recursion (org-todo arv/org-todo-paused-state) (defun arv/org-todo--state-change (from to) (when (and arv/org-todo-state-change-triggers-clocking-enabled (not (string= from to))) (let ((action (cdr (assoc to arv/org-todo-entering-state-clocking-actions (unless (null action) (cond ((eq action 'start) (arv/org-todo--pause-other-task) (org-clock-in)) ((eq action 'stop) (let ((org-state "DONE") ; hackish, review (org-clock-out-when-done t)) (org-clock-out-if-current))) (t (user-error "Unknown action."))) (defun arv/org-todo--state-change-trigger (p) (let ((type (plist-get p :type)) (from (plist-get p :from)) (to (plist-get p :to))) (when (eq type 'todo-state-change) (arv/org-todo--state-change from to (add-hook 'org-trigger-hook 'arv/org-todo--state-change-trigger)