January 15, 2015

Finding tags in free-form notes

Notes: There are industries built around keeping them, finding them and making them useful. After trying every option I could find, digital and analog, I recently started to keep a single notes file with a simple, free-form layout. Basically the notes follow this syntax:


Thu 15 Jan 2015 18:31:01 GMT
@hokey @pokey

You put your right hand in,
You put your right hand out,
You put your right hand in,
And you shake it all about.


I write the date in vim using :r !date, give the note some tags, finish with a === delimeter and I’m done. I use grep to find a relevant tag, then grep’s context options – -A for lines after, -B for lines before or -C for lines both before and after – to find the information I’m looking for. I’ve noticed over time that I tend to forget the tag or tags that I’ve put on a particular note so I wanted a way to find a list of all the tags in the file. Here’s what I’ve come up with:

grep -h '@[[:alnum:]]' ~/notes.txt | grep -v '[[:alnum:]]@' | tr '[[:space:]]' '\n' | sort | uniq

It looks a little unwieldy, but aliased to tags it does a great job so far. The first part, grep -h '@[[:alnum:]]' ~/notes.txt is pretty straightforward: find, without showing me the file name (-h), all text that has @ followed by any alphanumeric character. That was fine until some notes contained email addresses—ticket receipts, booking confirmations, etc. So grep -v '[[:alnum:]]@' removes items with any text before the @ symbol. tr '[[:space:]]' '\n' translates spaces in the resulting lists of tags into newlines, so grep’s result of @hokey @pokey becomes…


…and finally sort makes things nice and alphabetical and uniq removes duplicates. Now if I’m searching for a note the first thing I do is tags, pick the right one and then grep for context. It’s surprisingly efficient and means I can dump all sorts of stuff into the notes file, so long as I maintain the simple layout.