Org-Mode: Returning to Previous Task on Clock-out
I've been getting into org-mode over the last couple years, using it to organize my work and as many other things as possible. Org-mode is an organizer (and much more) that runs in Emacs, which I use for many other things, so it's a great fit. I owe a great deal of thanks to Bernt Hansen, who put his complete org-mode configuration online with detailed explanation and instructions. He uses it in a very GTD-style way, which is exactly what I wanted, so I cut-and-pasted much of his base configuration at first, but since then I've done some tinkering of my own.
One of the great features of org-mode is clocking. I can clock into any task with C-c C-x C-i (or hitting I on it in the agenda), and then org-mode logs the time I spend on that task until I clock out, either with C-c C-x C-o (or O in the agenda) or by marking the task DONE. Each task has a LOGBOOK which collects all the time spent on it, so I can print invoices, productivity reports, or anything else I want out of that data.
Thanks to some of Bernt's customizations, once I punch in to start the day, org-mode is always clocking something until I punch out. Anytime I clock-out of one task, it switches to clocking something else, so my time is always accounted for somewhere.
But which task should it switch to? In Bernt's configuration, when you close one task, it switches to that task's parent. To explain what a parent task is, here's a very simplified example org-mode file:
* Garden ** TODO Plant Vegetables *** NEXT Peas *** TODO Beans *** TODO Corn * Blogging ** TODO Write a post on clocking in org-mode * TODO Write Novel ** NEXT Write outline ** TODO Write preface ** TODO Write chapter 1 ** TODO Write chapter 2
Org-mode is based on an outline type of format. Every line starting with one or more asterisks is a heading, and the number of asterisks determines the level. Here there are three top-level (1 asterisk) headings, and each one has some sub-headings. So "Garden" is the parent of "Plant Vegetables," which is the parent of "Peas," "Beans," and "Corn." Likewise, "Write Novel" is the parent of "Write outline," "Write preface," and so on. (If you're curious about what TODO and NEXT mean, they both signify tasks that are waiting for me to act on them. The difference is that NEXT tasks are the next one I intend to do for their project, and they shouldn't have to wait on any other tasks.)
In Bernt's configuration, when you close one task, the clock switches to that task's parent. If I'm working on my novel, that might make sense. When I finish the outline, I mark that task done, and the clock switches to its parent, "Write Novel." I still have some more time to write, so I move down and clock into "Write preface" and continue writing. All the time gets clocked into either one of the sub-tasks or the parent.
However, that doesn't work so well when I'm not likely to move right from one sub-task to another, which is usually the case for me. For instance, let's say I'm working on this blog post, so I have that task clocked in. I hear thunder outside, and realize I should run out and plant my peas before the rain starts. I quickly clock into "Peas" (which clocks me out of the blogging task), and run out to plant them. When I come back in and mark "Peas" DONE, I don't want it to switch to the parent task "Plant Vegetables." I want it to switch back to the blogging task I was working on before.
I find that that's usually the way my work-flow goes. I can do that manually with a few keystrokes, but it'd be nicer to have it happen automatically, and not have that few moments clocked into a task I didn't intend. So I tracked this functionality down to the bh/clock-out-maybe function. Here's the original:
(defun bh/clock-out-maybe () (when (and bh/keep-clock-running (not org-clock-clocking-in) (marker-buffer org-clock-default-task) (not org-clock-resolving-clocks-due-to-idleness)) (bh/clock-in-parent-task)))
This checks a few things, and if they all are true, it clocks in the parent task. So I want it to clock in the previously clocked task instead. I changed it to this:
(defun bh/clock-out-maybe () (when (and bh/keep-clock-running (not org-clock-clocking-in) (marker-buffer org-clock-default-task) (not org-clock-resolving-clocks-due-to-idleness)) (if (marker-buffer org-clock-interrupted-task) (org-with-point-at org-clock-interrupted-task (org-clock-in)) (bh/clock-in-parent-task))))
As you can see, it's not a huge change. When it runs, it first checks to see if there's a marker for a task that was interrupted by the current task, which org-mode handily keeps track of. If there is, it switches to that mark and clocks in there. If there's not -- if the current task is my first task of the day, for instance -- then it uses the previous behavior of switching to the parent. Either way, the clock keeps running.
This works better for me, and I also like the fact that it better matches the way org-mode's capture mode works, which also switches back to the interrupted task after capturing something. Although it's a very small change code-wise, it taught me a lot about the internals of org-mode as I tracked this down.
Posted on: 2015-06-13