Emacs, Org, and BBDB: Hyperlinking names to blogs

| bbdb, emacs, org

Back when I used Planner for Emacs, I coded some shortcuts to make it easier to write about the people I met and the conversations I had. I used the hippie-expand module to complete names from my Big Brother Database addressbook, and I wrote a function that converted those names into links to people’s blogs or websites whenever I published my blog posts as HTML.

I switched to WordPress for my blog because I got tired of trying to figure out a way to enable comments without getting mired in spam-fighting. That meant I could explore other Emacs personal information managers like Org, which I turned into my main task manager. I often used the WordPress interface to write blog posts. I sometimes used Windows Live Writer to write posts about books (there’s a good book review plugin that makes this easy). I also sometimes used Emacs and Org to draft blog posts using Org’s friendlier markup, exporting snippets to HTML that I then pasted into my blog posts.

Reading the posts on Planet Emacsen reminded me that my customized configuration was pretty darn sweet. That and the conversation notes I’ve been blogging lately encouraged me to dust off my configuration files and get them to work under Org. So here’s the code:

 (defun sacha/org-bbdb-get (path)
   "Return BBDB record for PATH."
   (car (bbdb-search (bbdb-records) path path path)))
 
 (defun sacha/org-bbdb-export (path desc format)
   "Create the export version of a BBDB link specified by PATH or DESC.
 If exporting to HTML, it will be linked to the person's blog,
 www, or web address. If exporting to LaTeX FORMAT the link will be
 italicised. In all other cases, it is left unchanged."
     (cond
      ((eq format 'html)
       (let* ((record
             (sacha/org-bbdb-get path))
            url)
       (setq url (and record
                      (or (bbdb-record-getprop record 'blog)
                          (bbdb-record-getprop record 'www)
                          (bbdb-record-getprop record 'web))))
       (if url
           (format "<a href=\"%s\">%s</a>"
                   url (or desc path))
         (format "<em>%s</em>"
                 (or desc path)))))
      ((eq format 'latex) (format "\\textit{%s}" (or desc path)))
      (t (or desc path))))
 
 (defadvice org-bbdb-export (around sacha activate)
   "Override org-bbdb-export."
   (setq ad-return-value (sacha/org-bbdb-export path desc format)))
 
 ;;;_+ Hippie expansion for BBDB; map M-/ to hippie-expand for most fun
 (add-to-list 'hippie-expand-try-functions-list 'sacha/try-expand-bbdb-annotation)
 (defun sacha/try-expand-bbdb-annotation (old)
   "Expand from BBDB. If OLD is non-nil, cycle through other possibilities."
   (unless old
     ;; First time, so search through BBDB records for the name
     (he-init-string (he-dabbrev-beg) (point))
     (when (> (length he-search-string) 0)
       (setq he-expand-list nil)
       (mapcar
        (lambda (item)
        (let ((name (bbdb-record-name item)))
          (when name
            (setq he-expand-list
                  (cons (org-make-link-string
                       (org-make-link "bbdb:" name)
                       name)
                        he-expand-list)))))
        (bbdb-search (bbdb-records)
                     he-search-string
                     he-search-string
                     he-search-string
                     nil nil))))
   (while (and he-expand-list
               (or (not (car he-expand-list))
                   (he-string-member (car he-expand-list) he-tried-table t)))
     (setq he-expand-list (cdr he-expand-list)))
   (if (null he-expand-list)
       (progn
         (if old (he-reset-string))
         nil)
     (progn
       (he-substitute-string (car he-expand-list) t)
       (setq he-expand-list (cdr he-expand-list))
       t)))

If you’ve got Org and BBDB, drop this into your ~/.emacs and fiddle with it. =)

You can comment with Disqus or you can e-mail me at sacha@sachachua.com.