Better fuzzy-finding in Vim

David Stosik
Source Diving
Published in
4 min readJun 22, 2020

--

CtrlP

I’ve been using Vim as my main code editor (and even sometimes to write just text!) for years, and the first time I discovered CtrlP, it really blew my mind. No need to type a complete file path anymore to open a deeply nested file!

Nice.

In recent years though, I noticed I wasn’t using CtrlP that much anymore, because the projects I’m working on are so big, have so many files, that it takes a few seconds for CtrlP to generate the file list it will use. Files also present name similarities that often make CtrlP’s first guesses wrong.

Not so nice…

Improving CtrlP

There are ways to improve how CtrlP works by, for example, ignoring paths for which you don’t need fuzzy finding (eg. tmp/, .git/, etc), or changing the command that CtrlP uses to generate the list of file candidates. If you’re using Git for example, the setting below will use the git command to list files, when in a git repository, which is considerably faster:

let g:ctrlp_user_command = ['.git', 'cd %s && git ls-files . -co - exclude-standard', 'find %s -type f']
Faster! But not so much better…

The given suggestions are unfortunately not better. They even got worse!

In some cases, sorting the list of file paths by length can slightly improve the suggestions:

let g:ctrlp_user_command = {
\ 'types': {
\ 1: [
\ '.git',
\ 'cd %s &&
\ git ls-files . -co --exclude-standard
\ | awk ''{ print length, $0 }''
\ | sort -n -s
\ | cut -d" " -f2-'
\ ],
\ },
\ 'fallback': 'find %s -type f'
\ }

The command uses git to get a list of files, then awk and sort to sort that list by length.

Nice again.

This is the result of trial and error, and your mileage may vary.

However, it feels like one should not have to do this kind of tweaking to get good results all the time.

Enter FZF

fzf is a general-purpose command-line fuzzy finder.

The install process is very straightforward, and I had the new command-line tool available in seconds. On Mac:

brew install fzf
$(brew --prefix)/opt/fzf/install
Very nice.

FZF also provides a Vim integration run via :FZF.

Cool.

We can easily map this command to the Ctrl+P shortcut, so that we don’t have to break our habits:

nmap <C-P> :FZF<CR>

(Don’t forget to uninstall CtrlP if you are not planning to use it anymore.)

FZF’s author also provides an additional Vim plugin, fzf ❤️ vim (I’m not sure if its name is fzf-heart-vim, or fzf-dot-vim, … 😅).

This plugin is a bundle of commands and mappings based on fzf. It is not necessary, as we were able to replace CtrlP already, but it introduces a few very useful commands. One of my favorites is :Ag, which makes use of the Silver Searcher (another great tool I strongly recommend).

The Silver Searcher in action.

In a few minutes, we were able to install additional tools and setup Vim to (fuzzy-)find files in a project very quickly! fzf appears to work as expected, out of the box, without restrictions, nor the need to tweak some settings to get acceptable results.

--

--