Friday, August 31, 2007

org-mode

In my previous post on the problems with GTD, I mentioned a bit about using emacs' org-mode to implement a GTD-like system. I've been using it for a while now, with good success.

I've previously used kGTD, as well as iGTD, but I like org-mode the best. With any other application, you are quite limited in what you can do. You can basically do what they want you to, maybe modulo a few scripts or preferences. With org-mode, the basic functionality is extremely flexible, and since it's all just a bunch of lisp code, you can rewrite and alter it to your heart's content.

org-mode, at it's simplest, presents an outline. You can expand and collapse it. Like other programs, you can put all sorts of stuff in the outline, in a very natural matter. For example:

* Fix bug 1919
** Reproduce the bug
This only breaks for very old users
** Write test case for bug
The stars here represent the indentation level. It's all just text, folks. This is emacs, what else would you expect? But notice that I can just add random text anywhere. It will be collapsed along with the "Reproduce the bug" header. This is very convenient place to put notes when you are working. As other programs do, you can have links. When I write "Fix bug 1919", the "1919" can link to my work's bug tracking system. More impressively, this being emacs, I can link to a specific location in a buffer. Opening it takes me right there, and off I go to do whatever work I need to.

I also use TODO tags, which are states associated with each work item. So, if this is an item that can become, in the GTD sense, a "next action", then it has a tag. There are four tags I use:
  1. TODO: An item which is still to be done, but is not yet actionable.
  2. NEXT: A "next action", which should be done.
  3. WAITING: An action that is waiting on some outside signal to either go back to NEXT or DONE.
  4. DONE: Finished. Hooray!

So, the above outline is more like:

* Fix bug 1919
** NEXT Reproduce the bug
This only breaks for very old users
** TODO Write test case for bug

Here is some customization code to enable this, as well as to enable useful agenda commands:

(setq org-todo-keywords '("TODO" "NEXT" "WAITING" "DONE"))
(setq org-agenda-custom-commands
'(("w" todo "WAITING" nil)
("n" todo "NEXT" nil)))

I like to, with one keystroke, mark an entry done and change the next one to NEXT. I wrote the following lisp code to do it:

(defun ash-org-todo-item-p ()
(save-excursion
(beginning-of-line)
(looking-at "\\*+[ \t]+TODO\\>")))

(defun ash-org-mark-done ()
(interactive)
(save-excursion
;; org-entry-is-done-p has a bug where if you are at the first
;; char of a line it doesn't always work. Let's work around it
;; here.
(end-of-line)
(when (not (org-entry-is-done-p))
(org-todo 'done)
(outline-forward-same-level 1)
(when (ash-org-todo-item-p)
(org-todo "NEXT")))))

(define-key global-map "\C-c\C-x\C-c" 'ash-org-mark-done)

The preceding code gives me a pretty nice, basic GTD system. On top of this I've been adding my own tweaks. One thing I like to do is to keep track of what I'm working on at the current time. This helps me keep focused. Org-mode has a way for keeping track of what you are doing at any one time, which is a clock which you can start or stop on any particular entry. Using this as a basis, I wrote the following nifty function for binding the F9 key to go back to the last current item. I know an item is current if I use the clock-in feature.

(defvar ash-org-current-task-loc nil
"A cons of the buffer & location of the current task")

(defadvice org-clock-in (after ash-org-mark-task activate)
"When the user clocks in, bind F9 to go back to the worked on task."

(setq ash-org-current-task-loc (cons (current-buffer)
(point)))
(define-key global-map [f9] (lambda ()
(interactive)
(switch-to-buffer
(car ash-org-current-task-loc))
(goto-char
(cdr ash-org-current-task-loc)))))

This helps me mark a task as complete, I just hit F9, then C-c C-x C-c, which closes it out (stopping the clock and printing elapsed time), and marks the next item done. Pretty nifty!

This isn't enough, yet. I'm still tweaking the system, trying to perfect it to suit the particular problems I have. I may post more on this in the future.

No comments: