Using Emacs To Convert Notes For Deft

Yesterday I wrote about Vivek Haldar’s Deft patch that allowed him to integrate his previous notes into Deft. Recall that Deft uses the first line of a note as its subject and names the file for a note deft-XXX whereas Haldar used the filename to describe the subject of the note. After I published that post I thought that it might have been easier to simply convert the existing notes to Deft format by making the file name the first line of the note.

It turns out that it is pretty simple to do that. Let’s assume that the file names are something like /Users/jcs/notes/ideas-for-Hercules-project.txt. We want to take the file name and convert it into a subject line by removing the directory information, removing the extension, changing the dashes to spaces and inserting the result as the first line of the file. Here’s a bit of Emacs Lisp that does that for one file:

(defun file-to-subject (filen)
  (let ((subject (replace-regexp-in-string
                  "-" " "
                  (file-name-sans-extension (file-name-nondirectory filen)))))
    (with-temp-buffer
      (insert-file-contents filen)
      (goto-char 1)
      (insert (concat subject "\n"))
      (write-file filen))))

The let at the beginning of the function converts the file name to a subject line. Then the file is read into a temporary buffer and the subject line is inserted at the beginning of the buffer. Finally the new file is written over the old.

To process all the files in, say, the ~/notes directory we could use the line

(mapc 'file-to-subject (directory-file "~/notes" nil "\\.txt$"))

or for more complicated directory structures we could use Dired to mark the files we want to convert and then use 【w】 (bound to dired-copy-filename-as-kill) to put the file names in the kill ring. Then we could just yank them right into the mapc in place of the (directory-file "~/notes" nil "\\.txt$").

That leaves changing ideas-for-Hercules-project.txt to deft-XXX. That could be done in several ways, with or without Emacs, but if you want to do it in Emacs here’s what you need for one file

(defvar deft-num 0)

(defun deft-name (filen)
  (rename-file filen (format "deft-%03d" (incf deft-num))))

The incf function1 increments deft-num and returns the incremented value so that the first time deft-name is called the format will return deft-001 and then deft-002 and so on.

You can do all the files with a mapc similar to what we used above. Alternatively, we could place the call to deft-name after the call to write-file in the file-to-subject function.

Footnotes:

1 incf is part of the Common Lisp package so you’ll need a (require 'cl) if you don’t already have it.

This entry was posted in Programming and tagged . Bookmark the permalink.