1

Title is pretty self explanatory. I have implemented the below solution to 'clock in' when I change my org-todo state to IN-PROGRESS and 'clock out' when I leave that state.

(add-hook 'org-after-todo-state-change-hook
          'org-clock-todo-change)

(defun org-clock-todo-change ()
  (if (string= org-state "IN-PROGRESS")
      (org-clock-in)
      (org-clock-out)))

The problem is that when I make this change, my repeating tasks stop working correctly. e.g., if I have a repeating task

*** TODO Take vitamins
    SCHEDULED: <2022-03-31 Thu .+1d>

And mark it 'DONE', I would expect to see the behavior described here, so something like

*** TODO Take vitamins
    SCHEDULED: <2022-04-01 Fri .+1d>

But instead I see

*** DONE Take vitamins
    CLOSED: [2022-03-30 Wed 18:50] SCHEDULED: <2022-03-31 Thu .+1d>

Thanks for your help.

2
  • Are you sure that the reason is the change in the hook? What happens if you set the hook to nil?
    – NickD
    Mar 31 at 1:25
  • @NickD The first block of code is what's producing the bug. When I comment it out, there's normal behavior as specified in documentation.
    – ChasingUG
    Mar 31 at 2:38

1 Answer 1

1

If you call org-clock-out without any special precautions and there is no clock running, it will throw an error and not continue on. The doc string says:

(org-clock-out &optional SWITCH-TO-STATE FAIL-QUIETLY AT-TIME)

Stop the currently running clock. Throw an error if there is no running clock and FAIL-QUIETLY is nil.

So try calling it like this:

(defun org-clock-todo-change ()
  (if (string= org-state "IN-PROGRESS")
      (org-clock-in)
    (org-clock-out nil t)))

But do you really want to stop the clock if it's not running in the curren task? It seems to me that what you'd really want to do is (org-clock-out-if-current). So I would try

(defun org-clock-todo-change ()
  (if (string= org-state "IN-PROGRESS")
      (org-clock-in)
    (org-clock-out-if-current)))

instead. That way if you switch a task to IN-PROGRESS and start a clock on it (thereby stopping the clock on a different task that is IN-PROGRESS) and then you go to that other task and switch it to DONE, the clock on the original task will still be running. It's only when you switch that task to DONE that the clock will be stopped.

I should caution you that I don't know much about clocking, so take this with the appropriate grain of salt.

1
  • 1
    'org-clock-out-if-current' was what I was looking for. Nice spot on error. Cheers.
    – ChasingUG
    Mar 31 at 23:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.