Sorting FZF results in Vim by proximity to current buffer
8/30/2020
I work in a large monorepo, and I was pretty sick of typing my team’s project directory whenever I wanted to use fzf.vim to search for and open another file.
Enter proximity-sort. This tool will sort a list of files by the proximity to a given file.
Installing proximity-sort #
You’ll need Rust if you don’t have it:
brew install rustup
rustup-init -y
source $HOME/.cargo/env
# add Rust's cargo bin directory to your $PATH
echo '[ -f $HOME/.cargo/env ] && source $HOME/.cargo/env' > \
~/.bashrc # or ~/.zshrc, etc
Once you have Rust on your system, you just need:
cargo install proximity-sort
It’s not bad to use: you just pipe a list of files into it, and give it a target file to bias search results around. Something like:
$ rg --files | proximity-sort lib/project/current/file.rb
and proximity-sort
will reorder the search results based on distance to
lib/project/current
. Give it a try manually in your shell first so you can
understand how the output changes as a result.
Configuring vim #
You can add a function to give FZF the file list. When you’re in the root
directory, it will just use rg --files
. When you’re in a buffer containing a
file in a sub-directory, it will use that sub-directory to proximity sort.
function! g:FzfFilesSource()
let l:base = fnamemodify(expand('%'), ':h:.:S')
let l:proximity_sort_path = $HOME . '/.cargo/bin/proximity-sort'
if base == '.'
return 'rg --files'
else
return printf('rg --files | %s %s', l:proximity_sort_path, expand('%'))
endif
endfunction
The final thing you have to do is update your FZF shortcut to use the function. Mine looks like this:
" ctrl p brings up the file finder
noremap <C-p> :call fzf#vim#files('', {
\ 'source': g:FzfFilesSource(),
\ 'options': '--tiebreak=index'})<CR>
Reload your Vim config and try it out!