Command-line Fuzzy Finder (FZF) is a gem of a command-line tool.
It is like the old 4dos SELECT command that could prompt a user to choose a file, times a thousand. It works with any stream of items you pipe in, presenting an interactive UI that lets a user filter and select items for a given action.
Ever since I got my dotfiles repo going, I've been looking for ways to speed up even small tasks I find myself repeating, especially on the command-line.
🎺 Enter FZF 🎺
hat tip
Much of what follows was derived or sourced from work already done by the community around FZF, though I've tweaked and tuned a few things for my taste. I've tried to include references to the origin for each of the following items both here and in my commit comments as I added them to my dotfiles repo. We are all standing on the shoulders of giants after all.
Show me, Show me, Show me how you do that trick!
Fuzzy Change Directory - fcd
Change to any directory on disk with a few keystrokes. If you do not pass arguments to fcd, it defaults to a search root of the user home directory. Pass a base dir to limit scope.
Press enter to change directory.
Click to show fcd source
function -d "Fuzzy change directory" fcd
if set -q argv[1]
set searchdir $argv[1]
else
set searchdir $HOME
end
# https://github.com/fish-shell/fish-shell/issues/1362
set -l tmpfile (mktemp)
find $searchdir \( ! -regex '.*/\..*' \) ! -name __pycache__ -type d | fzf > $tmpfile
set -l destdir (cat $tmpfile)
rm -f $tmpfile
if test -z "$destdir"
return 1
end
cd $destdir
end
from: https://gist.github.com/rumpelsepp/b1b416f52d6790de1aee
fkill - fuzzy kill
Kill one or more processes. Multi-select with tab and then press enter to kill several.
Click to show fkill source
function fkill -d "Fuzzy kill"
set pid (ps -ef | sed 1d | fzf -m | awk '{print $2}')
if test -n "$pid"
echo $pid | xargs kill -9
end
end
from: https://gist.github.com/rumpelsepp/b1b416f52d6790de1aee
Deeper down the rabbit hole
The 4 wonderful things about FZF that make it so flexible are:
- You can feed anything in to populate a list of choices
- As the choices stream in, a user can fuzzy match type ahead to narrow matching items in the list.
- A preview window can be configured to show more context around a given choice when it is highlighted.
- Once a selection is made, you can trigger an action driven off that selection.
The default matching algorithm in FZF lets you type words or parts of words in any order.
Fish + FZF + Key Bindings
I'm a big fan of the fish shell. There's a great 3rd party package that provides some useful keybindings and scripts to integrate fish with fzf. Install that package, then set the environment var FZF_LEGACY_KEYBINDS
to 0
and FZF_COMPLETE
to 1
, and you'll get the following:
- Tab: use fzf for tab completion
- Ctrl-F: insert a file path
- Ctrl-R: search history w/fzf
- Alt-O: change into subdirectories
- Ctrl-O: open file using default editor
- Ctrl-G: open file using system bound app (pdf/img/etc)
Tab: Tab completion - replacement for default shell behavior
Tab complete a directory or file name w/preview pane of directory contents. The big difference between this and the typical baked in tab completion is that you get a preview pane view of what's in the directory you're selecting (see right half of screen during this interaction).
Ctrl-F: Find a file
The search root is based the word by the cursor, so you can hit control-F even with a partial path in place.
Ctrl-R: Search through history
Source . . . Added the preview window by setting FZF_REVERSE_ISEARCH_OPTS
to --preview-window=up:10 --preview="echo {}" --height 100%
Git + FZF
fstash - fuzzy stash management
Stashing changes is one of those things I do just rarely enough that I never get faster at managing it. Mostly I stash, then stash pop after a pull from remote and a rebase, but sometimes.... sometimes, something else distracts you and then the stashes pile up.
fstash provides a minimal interface for managing stashes in a git repo.
Consider the case where we have a repo, and we stash two seperate sets of changes, then need to kill off one of them, and check the other out as a branch:
You can bind keys other than enter to custom actions in FZF. In this case, fstash provides the following:
- Enter: print the diff of the stash
- Ctrl-B: checkout the stash as a branch and remove the stash
- del: drop the stash
fclone - select and clone a github repo
See more about fclone and fhub in detail: here.
git fco - fuzzy check out branch
git fza - fuzzy add multiple files
more fun
- git frebase: Select a past commit to start a rebase from. source
- git ffix - Select a past commit to fixup staged changed to. source
- git fed - Select untracked/modified files to edit. source
- git fedconflicts - Select files in conflict state to edit. source
- git fgrep [pattern] [pathspec] - git grep for a pattern in a pathspec (current or former state of repo) source
side-note: For insanely fast searching of the current state of large git repo's, check out ripgrep.
- git fedlog - Choose a file from a commit to edit. source
- git freset - Select a prior commi to soft reset to. source Undo this with
git reset ORIG_HEAD
or the appropriate'HEAD@{1}'
ref from the reflog. - fhub - Select and browse to a github repo.
Docker
enter - jump inside a running docker container
Let's say you started up the kanboard container some time ago . . .
docker run -d --name kanboard -p 80:80 -t kanboard/kanboard:v1.2.8
. . . and now you need to peek at the inside.
If you're docker savvy, you'll know there are a couple of ways to get in, but even so, there is often some trial and error identifying which shell, if available in a container you are not intimately familar with. enter
to the rescue: