How to hide .gitignored Files from fzf.vim
Fuzzy finders find files that almost no developer would intentionally find via a fuzzy finder from paths
such as node_modules/
, deps/
, and dist/
. These tend to get in the way of the true power of fuzzy file
searching and ignoring these individually can be a pain. There are also files like .circleci/config.yml
,
.gitignore
, and .rubocop.yml
that are opened often enough to be included in the result set.
Luckily when working in a git repository, developers typically only care about the files they commit. When using fzf.vim, this technique returns files based on the git tree leaving out irrelevant files, including the hidden files that were shown before.
TL;DR: The Solution
" fzf file fuzzy search that respects .gitignore
" If in git directory, show only files that are committed, staged, or unstaged
" else use regular :Files
nnoremap <expr> <C-p> (len(system('git rev-parse')) ? ':Files' : ':GFiles --exclude-standard --others --cached')."\<cr>"
How does it work?
This single line provides an intelligent fallback whilst trying to be as efficient as possible.
It checks if we’re on a git repo by executing git rev-parse
(<1ms) to check if
vim is running within in a git repo. If the length of this command is > 0, which would
be the case if it spat out the fatal: not a git repository
error, then
we know we’re not in a git repo and we utilize :Files
instead.
If git rev-parse
doesn’t return anything, we know we’re in a git repo and can
utilize fzf.vim’s :GFiles
method which fuzzy finds utilizing git ls-files
.
Utilizing the following flags, this expression specifies the files we want more specifically:
--exclude-standard
: Add the standard Git exclusions: .git/info/exclude, .gitignore in each directory, and the user’s global exclusion file.--others
: Show other (i.e. untracked) files in the output--cached
: Show cached (AKA staged) files in the output (default)
I use ag -l
as my fzf command to be faster… How much slower is this?
It’s not! So long as you’re inside a repo, this will result in a much faster fuzzy finder load.
In a repo with ~5k files returned by git ls-files
, we experienced the following:
git rev-parse
consistently takes<1ms
to executeag -l
takes on average approximately250ms
to completegit ls-files
takes on average approximately16ms
to complete
This means that when control
+ p
is executed outside of a git repo, it is less than 1ms
slower than before, but if you’re inside a repository, it’s over 16x faster!