Fuzzy Finder
Intro
I’ll start by stating that I don’t like fuzziness. It’s the main reason I didn’t stick to machine learning and data science at the beginning of my career. Instead I’ve transitioned to programming and data engineering.
And here I am writing about fuzzy finder in Vim. That’s because of fzf.vim Vim package. It has some very convenient feature that I have been looking for. More on this later in the post. I still believe you should know (at least try to know) file tree structure of a project your working on. Fuzzy finders might pull you away from this practice very quickly. And I do think it’s a bad idea.
However let’s assume you have a firm grasp of your project’s structure tree but it’s large project with very deep tree. In this case, when you know what you are looking for, it might saves you time for typing long file paths.
Before I jump to fzf.vim package let’s discuss fzf first.
fzf
Fuzzy finders in general helps you to look for a file or directory, usually in an interactive manner, by just taking search phrases. They are usually search down the tree of files recursively beginning from current catalog.
At I stated before I try to know the file tree. But in case I want to open file
in ./this/very/deep/file/path/location/project/sub/MyFile.cs
it is really
convenient to feed MyFile
phrase to fuzzy finder to quickly go to that
location.
In case of fzf I mostly use two aliases which uses fzf to fuzzy find file and open it in Vim and the other one is for jumping to found directory.
alias vf='vim $(fzf --height 40%)'
alias cdf='cd $(find . -type directory | fzf --height 60%)'
A little demo of the those aliases:
fzf.vim
As the name suggests fzf.vim is a Vim package which wraps fzf in very comfy form. It takes advantage of Vim pop-up windows to run fzf. It can perform fuzzy search on files, git commits, Vim help, snippets and many more. But what was the most crucial feature for me was integration of fzf with ripgrep.
For years I’ve been using the following mapping for using grep while working in
Vim (I used spaces instead of <space>
for readability) to grep the word under
the cursor
noremap <leader>f :!grep --color=always -iran <C-r><C-w> .<CR>
Once I’ve glanced over the grep result I had to manually open the desired file. It was a bit tedious.
Using fzf.vim I can use :Rg
command to use ripgrep
interactively and
preview fragment of files for matched results. Because of great performance of
both ripgrep and fzf browsing through results is extremely smooth.
Once you find a result you can open it in new tab (Ctrl + t
), new split
(Ctrl + x
) or vertical split (Ctrl + v
).
The following cast should express more than few paragraphs.
There is one technical caveat in :Rg
command. The ripgrep query is performed
once at the beginning and all filters on results are done by fzf. Therefore
you might think that using regular expressions doesn’t work. Fortunately author
gives an
example
how to fire up ripgrep on every query change. I have set this under :RB
command.
My settings
Make sure you have fzf and ripgrep installed before setting up Vim plugins.
Plugin 'junegunn/fzf'
Plugin 'junegunn/fzf.vim'
...
let g:fzf_preview_window = ['down:40%', 'ctrl-/']
function! RipgrepFzf(query, fullscreen)
let command_fmt = 'rg --line-number --no-heading --color=always -- %s || true'
let initial_command = printf(command_fmt, shellescape(a:query))
let reload_command = printf(command_fmt, '{q}')
let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]}
call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen)
endfunction
command! -nargs=* -bang RG call RipgrepFzf(<q-args>, <bang>0)
Summary
In a very long time I have not been this excited about Vim plugin. Regular
fuzzy finder for files via fzf.vim is a pleasant feature but if it would be
the only feature of this plugin I would stick with standard Vim’s find
.
But using this smooth usage of ripgrep inside Vim has really light a spark of joy for me. That is it. It is the main reason for this post.