Getting started with fzf on Arch Linux

Default bash key bindings

Using whereis fzf, I found fzf's files for bash integration in usr/share/fzf:


After sourceing both files, this enables a couple of keybindings for bash: For example, I can hit Ctrl + t to search files in the current directory and Ctrl + r to search my command history.

For finding and changing to a directory, there's Alt + c.

To make these key bindings persistent, I added them to my .bashrc:

source /usr/share/fzf/completion.bash && source /usr/share/fzf/key-bindings.bash


A customization I find useful is showing a file preview when using fzf (I put that in my .bashrc as well):

# When selecting files with fzf, we show file content with syntax highlighting,
# or without highlighting if it's not a source file. If the file is a directory,
# we use tree to show the directory's contents.
# We only load the first 200 lines of the file which enables fast previews
# of large text files.
# Requires highlight and tree: pacman -S highlight tree
export FZF_DEFAULT_OPTS="--preview '(highlight -O ansi -l {} 2> /dev/null ||
cat {} || tree -C {}) 2> /dev/null | head -200'"

Path completion

Out of the box, fzf supports fuzzy path completion for a couple of hard-coded commands like cd, ls, and vim.

For example, entering vim ** Tab on bash starts a fuzzy search in the current directory and opens the selected file with Vim1.

This is pretty useful, but I'd like to open, for example, PDFs the same way. You can enable this by adding the following line to .bashrc:

complete -o bashdefault -o default -F _fzf_path_completion zathura

Here, zathura is my PDF viewer; you can substitute it with the document viewer of your choice.

Note that fuzzy path completion works for all paths, not only the current directory:

vim ~/**

and then hitting Tab will fuzzy-search a file under your home directory and then open it in Vim.

Vim integration

Here are some keybindings from my .vimrc to use fzf inside a Vim session:

" Search and switch buffers
nmap <leader>b :Buffers<cr>
" Find files by name under the current directory
nmap <leader>f :Files<cr>
" Find files by name under the home directory
nmap <leader>h :Files ~/<cr>
" Search content in the current file
nmap <leader>l :BLines<cr>
" Search content in the current file and in files under the current directory
nmap <leader>g :Ag<cr>

Prerequisite for all that is the fzf Vim plugin; I installed it with Plug by putting this in my .vimrc:

Plug 'junegunn/fzf.vim'

and then calling :PlugInstall from Vim.

Here is a list of fzf commands you can call from Vim.

Search files of project

Especially when working on software, I like to switch between files of a given project. Assuming that the project is versioned using Git, here's a binding that will fuzzy-search files inside the project and open the selected file:

nmap <leader>R :Files `=GetGitRoot()`<cr>

function! GetGitRoot()
  " Get the dir of the current file
  let currentDir = expand("%:p:h")
  " We stop when we find the .git/ dir or hit root
  while !isdirectory(currentDir . "/.git/") && currentDir !=# "/"
    " Make the parent the current dir
    let currentDir = fnamemodify(currentDir, ':h')
  return currentDir

Going further

For a powerful combination of fzf, Vim, and Tmux, check out Keegan Lowenstein's blog post (I got the --preview configuration from there).

Here are some ideas on how to configure fzf's shell integration.

You can find more examples of fzf configuration in fzf's readme and in its wiki.

1 If you find yourself fuzzy-searching files and then opening them in Vim a lot, you can create a keybinding for that using this piece of .bashrc.