Fast Project Finding With fzf
fzf is a fantastic utility, written by an author with a history of writing useful things. He’s also a vim user, and in addition to his other vim plugins he has created an “enhancement” plugin called fzf.vim.
One of the neat things fzf.vim
does is make it easy to create new commands
for fuzzy searches. If you’re like me, you probably have some absurd number of project
repositories you keep around and jump to, as necessary. Not everything is in
the same directory (e.g. ~/work/
), naturally, and with a laptop, desktop,
and a couple other machines the less-frequently used repos may be where one
least expects them to be — or not present at all.
It’s not hugely annoying, just a sort of mild pain to have to spend several
extra seconds doing a fuzzy search manually, rather than having fzf
do it.
But we do have fzf
, and it’s not difficult at all to build out a new search,
so there’s really no reason to keep on inflicting that pain.
Create a :Projects
command
Let’s create a new command in my vimrc,
:Projects
, that invokes fzf
to search through all the different work
directories I have.
|
|
What does this do?
-
Defines a new vim command,
:Projects
No surprises here.
-
Invokes
fzf#run()
to run afzf
searchfzf#run()
handles the actual execution and presentation offzf
, as well has dispatching the results back to thesink
.fzf#wrap()
is neat. It allows a command to take advantage offzf.vim
’s option handling – or not, by simply omitting it. -
Uses
find
to look for repositoriesWe know roughly where to look(
~/work/
,~/.vim/plugged
) and how deep to look. Just about everything I do is backed by git, so we can look for repositories and return the parent of the found.git
back tofzf
.Note that the
find
invocation deliberately omits a-type d
argument. I do use git worktrees, meaning.git
may well be a file (a “gitlink”). -
Calls out to
rsrchboy#fzf#FindOrOpenTab()
with the project selectedThe
sink
option tellsfzf#run()
what to do with the results. In our case we have providedfzf#run()
with a callback function, but you can also use built-ins as sinks.
The callback “sink” function
|
|
In general, I use one tab per project (repository) in vim. For me, this is a
nice balance of utility and sanity. It also allows me to do things like set
t:git_dir
and t:git_workdir
to the git and workdir, respectively, of the
repository associated with the tab.
Our callback function first attempts to find an open tab with the workdir
requested; if found, it just switches to it and returns. (It should probably
admonish me to read the tab line before invoking :Projects
.)
If not found. the callback function invokes fzf#run()
again. This time we
use git ls-files
to generate the source list for fzf
, allowing us to pick
a file to be opened by the given sink
: tabe
.
Hey, that wasn’t too hard!
Easier than writing this post, I’d say ;)
Happy hacking!