Simple Note-Taking with fzf and Vim

Improve your life with fuzzy finding

TL;DR: Install fzf (`brew install fzf`), then download this bash script for a nice little note-taking app.

I recently found fzf, a great utility for general-purpose fuzzy finding on the command line. I’ve been using it — along with Vim and a little bash script — as a fast, simple note-taking tool, and I wanted to share my setup.

Fuzzy Finding

I first learned about fuzzy file finding from Destroy All Software. Gary used the Command-T Vim plugin for file navigation, and it was kind of mind-blowing to see how fast he was able to switch between files. I was accustomed to laboriously typing out full file paths or clicking through directory trees in my editor, and finding out that I could instead simply type a hotkey and 4 or 5 letters changed how I approached navigating file trees.

(Fuzzy file finding in action (this is CtrlP, not Command-T, but same idea)

The basic idea of fuzzy finding goes like this: given many possible choices, narrow down the options based on a user-entered string. Unlike traditional text search, the characters in the search string don’t have to appear contiguously in the result to count as a match — only in order. So, by searching for acurc, app/controllers/user_registration_controller.rb is found. The bolded letters are the ones that the fuzzy finder matched on.

fzf

In my daily life, I pretty much only use fuzzy finding for navigating files. That’s not all it can be used for, though, and fzf was built to generalize the idea. fzf is a command-line tool that accepts any input you want to throw at it, presents an interactive fuzzy-finder, then prints whatever you picked on stdout. It has all kinds of options and customizations, and it is blazingly fast. It can handle very large input sets with no trouble at all.

Install fzf

If you’re on a Mac, it’s easy to install fzf:

brew install fzf

It is also available for Windows and Linux, as well as in non-Homebrew form on Mac; check the official docs if you need one of those.

fzf Basic Usage

If you run it without any arguments, fzf will default to recursively finding all files in the current directory.

fzf default behavior — find files

You can also pipe a list of things into it, for example the results from a big grep search:

grep -r animal . | fzf
fzf with piped stdin

There are plenty of other possibilities, but those are the two main use cases: run standalone to search filenames, or pipe a list of stuff into it.

A Barebones Note-Taking App

The way I’ve been using fzf is as a lo-fi replacement for Notational Velocity (or, more accurately, as a lo-fi replacement for a hi-fi replacement for Notational Velocity, nvAlt). I keep a folder of Markdown files in Dropbox as my personal wiki. Everything goes in there, from dates and names I need to remember to cheat sheets for programming languages.

fzf accepts a --preview argument which lets you provide a command to run against the currently selected result line. This lets us do something like this (I’ve also added some preview-window options for cosmetic changes):

fzf --preview="cat {}" --preview-window=right:70%:wrap

and get this result:

fzf with preview and some presentation options

So that’s a nice little interface over my notes folder. But I want to edit the notes, too, which is where the output from fzf comes in. Since pressing <enter> exits fzf and sends the selected filename to stdout, I can pass that to my editor to open.

vim `fzf --preview="cat {}" --preview-window=right:70%:wrap`
Give fzf result to Vim

That’s better, but I’m used to notes apps that just stay open all day. I don’t want to retype the fzf command after every edit. After thinking about it for a minute, I realized I could write a bash script that loops forever between these two states — fuzzy file selector and text editor — and here’s what I came up with:

fuz.sh

You can put this script in the root of your notes folder, or do what I did and place it in your PATH so that it’s globally accessible. I also renamed it to just fuz on my machine so it feels more like a normal Unix command.

And the whole thing looks like this:

fuz.sh in action

But What About…

There’s already an fzf plugin for Vim as well as a Notational Velocity clone that does pretty much what I just showed, so why would I bother writing my own wrapper? The main reason is on line 9 of the script: by referencing $EDITOR instead of vim specifically, this supports whatever editor you’d like to use, which I think is a bit more UNIX-y than the plugin approach. Even if you’re a devoted Vim fan, fzf only works in a terminal, so GVim users can’t make use of the existing plugins.

Conclusion

fzf is a really flexible tool, and I’m sure I’ll find other ways to fit it into my workflow in the future, but for now I’m happy with it just as a notes app. If you’re using fzf in some particularly clever way, I’d love to hear from you!

Like what you read? Give Casey Brant a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.