Capture Mode and Emacs


One of the "new" things in Emacs is something called Org mode. If you're an Emacs user and need an outliner, a calendar, a TODO list, or just a place to capture your thoughts, it's great. I've been using Org mode for a while and love it's features. A while back, I started using it with Remember mode to capture thoughts about a book I'm writing, notes in meetings, and a personal journal. I learned over the weekend about something called Org-capture, a Remember mode replacement and took a few minutes to get it set up. Since there were some rough spots, I thought I'd blog my experience for others.

First, you ought to do yourself a favor and download the latest org-mode.el files. The ones that come with your Emacs distro aren't likely to contain the Org-capture files. You can follow the standard instructions for setting up Org-mode. I like the following hook for turning on things like spell checking and turning off truncate-lines.

(add-hook 'org-mode-hook 
\t  (lambda ()
\t    'turn-on-font-lock
\t    (setq word-wrap 1)
\t    (setq truncate-lines nil)
\t    (flyspell-mode 1)))

I sent up Org-capture s that files are stored in my Dropbox and added several templates like so:

(setq org-directory "~/Dropbox/Documents/orgfiles/")
(setq org-default-notes-file (concat org-directory "notes.org"))
(define-key global-map "\\C-cr" 'org-capture)

(setq org-capture-templates 
  `(
    ("n" "Notes" entry (file+datetree 
\t\t        ,(concat org-directory "notes.org"))
\t"* %^{Description} %^g %? 
Added: %U") 

    ("b" "Book" entry (file+datetree 
\t  \t       ,(concat  
                         "~/Dropbox/Documents/KRL Book/krl.txt"))
        "* Topic: %^{Description}  %^g
%?
Added: %U") 

    ("j" "Journal" entry (file 
                          ,(concat org-directory "journal.org"))
        "** %^{Title} %U %(journal-google-weather \\"Lindon, UT\\")
%?
")
\t  ))

For more information on setting up templates, see this article on Capture mode and date trees and the manual entry. The file+datetree designation in the preceding templates creates a date tree outline in the Org file for easy reference.

I wanted to be able to access Org-capture from anywhere. I found this article on GTD capture in Org mode, but it's based on the old Remember mode, not the new Org-capture mode. Here's a screencast showing how this works:

With a simple keypress I'm able to fire up an Emacs window in capture mode from whatever application I'm then using, make my notes, and save the results. As I mentioned, the article on GTD capture in Org mode wasn't based on Org-capture, but the older Reember mode. I updated that code to use Org-capture. Here's the updated code:

 (defadvice org-capture-finalize 
  (after delete-capture-frame activate)  
   "Advise capture-finalize to close the frame"  
   (if (equal "capture" (frame-parameter nil 'name))  
       (delete-frame)))  
   
 (defadvice org-capture-destroy 
  (after delete-capture-frame activate)  
   "Advise capture-destroy to close the frame"  
   (if (equal "capture" (frame-parameter nil 'name))  
       (delete-frame)))  
   
 ;; make the frame contain a single window. by default org-capture  
 ;; splits the window.  
 (add-hook 'org-capture-mode-hook  
           'delete-other-windows)  
   
 (defun make-capture-frame ()  
   "Create a new frame and run org-capture."  
   (interactive)  
   (make-frame '((name . "capture") 
                 (width . 120) 
                 (height . 15)))  
   (select-frame-by-name "capture") 
   (setq word-wrap 1)
   (setq truncate-lines nil)
   (org-capture))  

I trigger this with Quicksilver. To do that I created a simple bash script called capture

#!/bin/bash
/usr/bin/emacsclient -n -e '(make-capture-frame)'

Setting up a Quicksilver trigger to call the script is trivial. I bound it to Command-Option-Backslash.

You might have noticed, that the template for my journal entries contains this little bit of magic:

%(journal-google-weather \\"Lindon, UT\\")

That tells the template to evaluate the function journal-google-weather. This is something I hacked together using the google-weather library:

(defun journal-google-weather (location)
  (let* ((data (ignore-errors
\t\t (google-weather-get-data location)))
\t (forecast 
            (when data 
              (caddr (google-weather-data->weather data)))))
    (when forecast
      (let ((condition (cdaadr (assoc 'condition forecast)))
            (low (cdaadr (assoc 'low forecast)))
            (high (cdaadr (assoc 'high forecast)))
            (city (google-weather-data->city data))
\t    )
\t(format-spec "%L | %c | High: %hF Low: %lF"
\t\t     `((?c . ,condition)
\t\t       (?L . ,location)
\t\t       (?l . ,low)
\t\t       (?h . ,high)))))))

When this runs, emacs contacts the Google weather API, parses the result for the given location, and inserts a formated string into my journal header like so:

... [2010-12-12 Sun 21:12]  Lindon, UT | Partly Cloudy | High: 52F Low: 30F

I'm loving the easy ability I have now to capture information from mail, the Web or anywhere else and put it into a notes file for later. Give it a try!