Modify Emacs Deft for recursive directory search

Update 2014-11-18 I’ve forked the original Deft, added this recursive directory listing feature as well as support for multiple different file extensions, and pushed it all to github as deft-turbo!

Deft is a neat Emacs mode for the Notational Velocity-inspired searching, browsing and editing of a directory of text files. In short, this means that simply start typing, and Deft finds the note that you were looking for. It supports straight text searching and regular expression searching, almost like my own baby nvpy.

When your text files are of a structured type that Emacs supports, such as Markdown, orgmode or something else, you can attain note-taking nirvana.

It looks like this:

Emacs Deft on my setup. I had to carefully pick a search string so you wouldn’t see all of my top secret notes! (Yes, you’re seeing notes from two different nested directories!)

However, I keep my personal text notes in a nested directory structure. I have general notes at the top level, daily journals in their own subdirectory, and projects each in their own subdirectory. Deft unfortunately does not support this out of the box; it only searches in the top-level directory you configure it with.

Fortunately I ran into this bit of example code in the Emacs documentation of all places. After a few small tweaks, it looked like this:

(defun deft-find-all-files (directory)
"List the deft-extension files in DIRECTORY and in its sub-directories."
;; cpbotha found this on
;; and adapted for deft
(let (el-files-list
(directory-files-and-attributes directory t)))
;; while we are in the current directory
(while current-directory-list
;; check to see whether filename ends in `.deft-extension’
;; and if so, append its name to a list.
((equal (concat "\." deft-extension) (substring (car (car current-directory-list)) -3))
(setq el-files-list
(cons (car (car current-directory-list)) el-files-list)))
;; check whether filename is that of a directory
((eq t (car (cdr (car current-directory-list))))
;; decide whether to skip or recurse
(equal "."
(substring (car (car current-directory-list)) -1))
;; then do nothing since filename is that of
;; current directory or parent, "." or ".."
;; else descend into the directory and repeat the process
(setq el-files-list
(car (car current-directory-list)))
;; move to the next filename in the list; this also
;; shortens the list so the while loop eventually comes to an end
(setq current-directory-list (cdr current-directory-list)))
;; return the filenames

Note that deft-find-all-files() takes one argument now, instead of none.

If you copy that function into your deft.l, replacing the deft-find-all-files() that’s already there, and modify deft-cache-initialize() so that the first code line reads:

(setq deft-all-files (deft-find-all-files deft-directory)) ; List all files

… your Deft can support nested note directories too!

(I have sent the author this snippet of code (he’s not on github, so no pull request) – we’ll see what happens)

3 thoughts on “Modify Emacs Deft for recursive directory search”

  1. I’m looking for a new note-taking solution, and this would be great! Still lacking a good Markdown editor on Android, and Dropbox on Android can’t keep directories in sync yet (but there are workarounds).

    1. With regard to a good Markdown syncing solution I have given up on Android. It’s hard to believe that the official Simplenote app is so bad.

      A few weeks ago I decided that I would just have my Gollum/Emacs/NextGen nested directory of markdown notes on my laptops (this is synced with unison via my Synology at home), and on Android I would use Google Keep for capturing on the road (it works REALLY well for that) and deal with the fact that I don’t always have my full notes database with me.

      (BTW, it was late last night, and I had hot-loaded a bunch of Emacs lisp code, so there were issues with my modifications. Now fixed in this post!)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.