programming (and other) musings
19 Jun 2022

simple note taking

I was just watching Prot's explanation of his new package denote, a very elegant note-taking system with a stress on simplicity and, as the author puts it, low-tech requirements. Now, those are excellent qualities in my book, and i think i'd quickly become a denote user if it weren't for the fact that i already have a homegrown set of utilities following a similar philosophy. Inevitably, they differ in some details, as is to be expected from software that has grown with me, as Prot's with him, during more than a decade, but they are similar in important ways.

I've had in mind writing a brief note on my notes utilities for a while, so i guess this is a good time for it: i can, after showing you mine, point you to a polished package following a similar philosophy and sidestep any temptation of doing anything similar with my little functions :)


As you'll see in a moment, in some ways, my note taking system is even simpler than Prot's, while in others i rely on more sophisticated software, essentially meaning that where denote is happy to use dired and filenames, i am using grep over the front-matter of the notes. So if you loved the filename-as-metadata idea in denote, you can skip the rest of this post!

These are the main ideas around which i built my note-taking workflow:

Turns out that i was able to write a little emacs lisp library doing all the above, thanks to the magic of org-mode and consult: you can find it over at my repo by the name of jao-org-notes.el. The implementation is quite simple and is based on having all note files in a parent directory (jao-org-notes-dir) with a subfolder for each of the main top-level categories, and, inside each of them, note files in org mode with a preamble that has the structure of this example:

#+title: magit tips
#+date: <2021-07-22 Thu>
#+filetags: git tips

The header above corresponds to the note in the file emacs/ Now, it's very easy to write a new command to ask for a top-level category and a list of tags and insert a header like that in a new file: it's called jao-org-notes-open-or-create in my little lib, and with it one can define a new org template:

("N" "Note" plain (file jao-org-notes-open-or-create)
 "\n- %a\n  %i"
 :jump-to-captured t)

that one can then add to org-capture-templates (above, i'm using "N" as its shortcut; in the package, this is done by jao-org-notes-setup, which takes the desired shortcut as a parameter). I maintain a simple list of possible tags in the variable jao-org-notes--tags, whose value is persisted in the file denoted by the value jao-org-notes-tags-cache-file, so that we can remember newly-added tags; with that and the magic of emacs's completing read, handling tags is a breeze.

Now for search. These are text files, so if i want to search for contents, i just need grepping, for instance with M-x rgrep or, even better, M-x consult-ripgrep. That is what the command jao-org-notes-grep does.

But it is also very useful to be able to limit searches to the title and tags of the notes: that's what the command jao-org-notes-open does using consult and ripgrep by the very simple device of searching for regular expressions in the first few lines of each file that start with either #+title: or #+filetags: followed by the terms we're looking for. That's something one could already do with rgrep alone; what consult adds to the party is the ability of displaying the matching results nicely formatted:


Links between notes are simply org file: links, and having a simple "backlinks" command is, well, simple if you don't want anything fancy3. A command to insert a new link to another note is so boring to almost not meriting mention (okay, almost: jao-org-notes-insert-link).

And that's about it. With those simple commands and in about 160 lines of code i find myself comfortably managing plain text notes, and easily finding contents within them. I add a bit of icing by asking Recoll to index my notes directory (as well as my email and PDFs): it is clever enough to parse org files, and give you back pointers to the sections in the files, and then issue queries with the comfort of a consult asynchronous command thanks to consult-recoll (the screenshot in the introduction is just me using it). It's a nice use case of how having little, uncomplicated packages that don't try to be too sophisticated and center on the functionality one really needs makes it very easy to combine solutions in beatiful ways4.



I also hate with a passion those :PROPERTIES: drawers and other metadata embellishments so often used in org files, and wanted to avoid them as much as possible, so i settled with the only mildly annoying #+title and friends at the beginning of the files and nothing more. The usual caveat that that makes it more difficult to have unique names has proven a non-problem to me over the years.


Currently i use work, books, computers, emacs, letters, maths, and physics: as you see, i am not making a great effort on finding the perfect ontology of all knowledge; rather, i just use the first broad breakdown of the themes that interest me most at the moment.


Just look for the regular expression matching "[[file:" followed by the name of the current file. I find myself seldom needing this apparently very popular functionality, but it should be pretty easy to present the search results in a separate buffer if needed.


Another example would be how easy it becomes to incorporate web contents nicely formatted as text when one uses eww as a browser. Or how how seamless it is taking notes on PDFs one's reading in emacs, or even externally zathura (that's for a future blog post though! :)).

Tags: emacs
Creative Commons License by jao is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.