Bryan Grohman

All Writing

Plain Text Book Notes with Golang


I've collected quite a few notes and highlights from books I've read spread across an Amazon Kindle account and paper books. One of the features that originally drew me to the Kindle is the ability to have digital notes and highlights that are searchable and accessible without having the physical book present.

As part of a larger effort to move my personal computing outside of closed, proprietary systems, I decided to convert my Kindle notes and highlights to plain text. I'm also in the process of typing up all of the highlights from my paper books as well. The end result is a collection of text files that is easily searchable and should never become obsolete (I think we'll always have text editors). Plus, using vim for writing and reading is a better experience than using Amazon's web UI.

I use a single file per book with a short header section and individual notes separated by blank lines. For instance, the file the_signal_and_the_noise.txt looks something like this:

The Signal and the Noise
Why So Many Predictions Fail but Some Don't
by Nate Silver

"The major difference between a thing that might go wrong and a thing that
cannot possibly go wrong is that when a thing that cannot possibly go wrong goes
wrong it usually turns out to be impossible to get at or repair," wrote Douglas
Adams in The Hitchhiker's Guide to the Galaxy series.

In complex systems, however, mistakes are not measured in degrees but in whole
orders of magnitude.

If our ideas are worthwhile, we ought to be willing to test them by establishing
falsifiable hypotheses and subjecting them to a prediction.

It's nice enough to browse and search my notes and highlights using vim and grep, but I found myself wanting to see some other metadata such as a list of all the authors, word counts, and printing a random highlight. I've also been looking for a small project to use to start learning the Go programming language, so I wrote a small Go command line tool to parse the book notes.

Using Go felt familiar for me coming from languages like Java, Python, JavaScript, Clojure, and others. There were a few times it felt a little awkward, such as the need to create a new type that implements the sort interface with Swap, Len, and Less methods just so I could sort a map of string keys to int values by the values. In a language like JavaScript, you only need to provide a single comparison function as an argument to the sort function. The Go approach seemed a bit verbose.

The way Go handles "exported" properties from a package by capitalizing the names also seemed a bit odd. So did Go's insistence on organizing all of the source code and build artifacts under the GOPATH, typically ~/go, but I kind of like that convention the more I use it. I have GOPATH/bin on my PATH now, so every Go program I've installed with go install is automatically on my path.

Here are the help docs from my "booknotes" Go program to give you an idea of how I use it:

booknotes <command> [file]

list      Prints title, subtitle, author, and metadata for each book
full      Same as "list" but includes the full notes, too
authors   Prints all authors in alphabetical order
titles    Prints all titles in alphabetical order
words     Prints words and word counts
random    Prints a random note
help      Prints this help message

file      Optional file path to process instead of all books

Environment Variables:
BOOKNOTES_DIRECTORY        Path to directory containing book note files
BOOKNOTES_MAX_LINE_LENGTH  Maximum number of columns when printing notes

For a slightly more detailed description as well as the source code, take a look at the booknotes project on GitHub.