TIL: fzf Preview Options
Last updated: Sun Feb 18 2024
fzf is one of my all-time favourite pieces of software; it allows you to fuzzy-find entries in a list, which I use all over my dotfiles. It has an absurd amount of additional functionality, however, some of which I’ll explore now.
One of my favorite little command-line utilities, based off an example in the fzf docs, combines fzf and ripgrep to do fancy searching:
function rfv --description 'rg tui built with fzf and bat'
# https://github.com/junegunn/fzf/blob/master/ADVANCED.md#using-fzf-as-the-secondary-filter
rg --smart-case --color=always --line-number --no-heading "$argv" |
fzf -m --ansi \
--color 'hl:-1:underline,hl+:-1:underline:reverse' \
--delimiter ':' \
--preview "bat --color=always {1} --theme='Solarized (light)' --highlight-line {2}" \
--preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
--bind "enter:become(code_demux {+1..2})"
end
There’s a lot going on here, but basically it runs a regex with rg
and pipes the results into fzf
to multiselect.
Then it binds enter:become
to open the selected files in VS Code at the right line.
The part to focus on here is the bit inside enter:become(...)
.
fzf has a number of preview options that can also be used with bindings.
In particular, {}
contains the string representation of a single selection and {+}
contains a space-separated list of strings for multiselection.
You can also use {q}
for the query string and {n}
or {+n}
for the index numbers of selections.
You can go a step farther and parse the selection with field index expressions.
In particular, within this rfv
utility, fzf
will output the file name and the line number of the match, separated by a colon, along with further colon-separated metadata.
1..2
grabs the first two fields and leaves the rest, so {+1..2}
will provide a space-separated list of filename/line number pairs to open.
The last weird part here is code_demux
.
That’s necessary because, though VS Code’s command-line interface does have a flag to open a particular file at a particular line number (code -g file:line
), it only works for one file at a time.
So code_demux
is a fish function that just takes the space-separated list and makes a bunch of calls to code -g
:
function code_demux
for arg in $argv
code -g $arg
end
end
References
- “Preview”, fzf manpage