Favorite Apps & Tools #4 - fzf
What is fzf
Again starting with quotes by the developer, Junegunn Choi.
fzf is a general-purpose command-line fuzzy finder.
It’s an interactive Unix filter for command-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc.
However with this one, I will take a shot at explaining some aspects together with some examples.
fzf takes in a list of stuff through the stdin
, gives you an interface to fuzzy match (a) line(s) and spits out the result(s) to the stdout
. The delimiter for the list should be a new line \n
.
A fantastic example of a tool that does one thing brilliantly. Unix philosophy and all.
This does not sound like much at first, but with the tool being on the command-line one can imagine what one can do with it in a pipeline.
fzf
has of course a few options to make it even more appealing. File preview, multi selector and sorting to name a few.
Few Examples of mine
For illustration purposes these are some examples that I use myself.
My gitlab dotfiles repository should have more of the stuff that I use fzf
for if you like to go fishing there.
Now if you want to get even more inspiration. There are a whole bunch of community examples in the git repository of the author.
Find & open files
This finds files with fd, pipes the list into fzf
and the fuzzy matched results get opened with Vim. It also uses bat for file previews.
function fv() (
export FZF_DEFAULT_COMMAND="fd -p -i -H -L -t f -t l -t x \
-E 'icloud/*' \
-E 'Library/*' \
-E 'Pictures/Photos Library.photoslibrary/*' \
-E '.git'"
IFS=$'\n' \
files=($(fzf --reverse \
--preview "bat --theme=timu-spacegrey --color=always {}" \
--query="$1" --multi --select-1 --exit-0))
[[ -n "$files" ]] && vim "${files[@]}"
)
Change directory
This uses fzf
, fd
and cd
in the pipeline.
function fcd() {
export FZF_DEFAULT_COMMAND="fd -p -i -H -L -t d \
-E 'icloud/*' \
-E 'Library/*' \
-E 'Pictures/Photos Library.photoslibrary/*' \
-E '.git'"
local dir
dir=$(cd && fzf --reverse +m) && cd && cd "$dir"
}
Find & install Homebrew cask
This one is fairly wonky but quite self-explanatory.
function bcinst() {
curl -s https://formulae.brew.sh/cask/ | \
grep '<td>' | \
grep href | \
awk -F '/' '{print $3}' | \
awk -F '"' '{print $1}' | \
fzf -m | \
xargs brew install --cask
}
Switch folders in neomutt
I use NeoMutt as a fallback from Mu4e in Emacs for my emails. But I have gotten so used to the fuzzy matching interface in Emacs (ivy) to jump to emails folders that I need it here as well. fzf
to the rescue:
match_folder() {
find $HOME/.maildir -name '*' -type d \
-mindepth 2 -maxdepth 2 |\
grep -v '.git' | grep -v '\/mu' |\
fzf --reverse
}
folder=$(match_folder)
echo "push 'c$folder<enter>'"
Ranger integration
Admittedly and exactly because of the awesomeness of fzf
I don’t use ranger as a file manager anymore. But while tinkering, I managed to integrate fzf
in ranger
as a command.
class fzfcd(Command):
def execute(self):
command = "cd && fd -p -i -H -L -t d \
-E 'icloud/*' \
-E 'Library/*' \
-E 'Pictures/Photos Library.photoslibrary/*' \
--no-ignore-vcs --exclude '.git' | fzf"
fzf = self.fm.execute_command(command, stdout=PIPE)
stdout, stderr = fzf.communicate()
directory = stdout.decode('utf-8').rstrip('\n')
directory = os.path.join(os.environ['HOME'], directory)
self.fm.cd(directory)
Fzf in Vim
The author of fzf
created fzf.vim as well. An awesome plugin for Vim that implements great fuzzy matching for a whole host of commands.
:Files
[PATH]- Fuzzy match and switch to files.
:GFiles
- Fuzzy match and switch to files in a git repository.
:Buffers
- Fuzzy match and switch to buffer.
:Ag
or:Rg
[PATTERN]- Fuzzy match and switch to search results with The Silver Searcher,
ag
or ripgrep,rg
.
This are just a few of the available commands. :h Files
in Vim will get you to the help section with an exhaustive list.
Conclusion
There is an argument to be made that fuzzy finding/matching is the best user interface out there. Not just for the CLI, but for any kind of navigation, period.
This is somewhat evident by the popularity of such programs as Alfred in macOS, completion frameworks in Emacs (vertico, ivy, helm, etc.), rofi & dmenu for Gnu/Linux users and vast number of other tools, utilities and applications.
As I believe to have shown here with just the few examples, fzf
masters the fuzzy matching/finding on the command-line like a champ. Enough said!