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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(defun deft-find-all-files (directory)
  "List the deft-extension files in DIRECTORY and in its sub-directories."
  ;; cpbotha found this on http://www.gnu.org/software/emacs/manual/html_node/eintr/Files-List.html
  ;; and adapted for deft
  (let (el-files-list
        (current-directory-list
         (directory-files-and-attributes directory t)))
    ;; while we are in the current directory
    (while current-directory-list
      (cond
       ;; 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
        (if
            (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
                (append
                 (deft-find-all-files
                   (car (car current-directory-list)))
                 el-files-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
    el-files-list))

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

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

1
(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)