Everyone who works in the shell needs a faster way to get around. fzf and rg in zsh makes for a great combination. I’ve been using this setup for a while now and it allows me to jump around my filesystem.
$ brew install fzf rg
To install useful key bindings and fuzzy completion:
$ $(brew --prefix)/opt/fzf/install
Adding a couple of lines to .zshrc
# Setting rg as the default source for fzf
export FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden --follow -g "!{.git,node_modules}/*" 2> /dev/null'
# To apply the command to CTRL-T as well
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
And we’re done!
Fuzzy history search
$ <crtl> + r
$
7063 bundle
7064 bundle exec middleman build
7065 time bundle exec middleman build
7066 bundle install
7067 bundle purge
7068 bundle --help
7069 bundle clean
7070 bundle clean --force
7071 bundle exec middleman server
7115 bundle exec middleman
7161 bundle exec middleman version
7186 bundle exec middleman server
7196 bundle install
7197 bundle exec middleman server
7265 bundle install
7266 bundle update
7267 gem install bundler --pre
7269 bundle exec middleman build
> 7409 bundle exec middleman server
129/7409 +S
> bundle
Fuzzy file search
$ <ctrl> + t
$
> zshrc
\ 1678/972367
> .zshrc
.zshrc.zwc
dotfiles/zsh/.zshrc
.oh-my-zsh/templates/zshrc.zsh-template
.oh-my-zsh/plugins/redis-cli/_redis-cli
.oh-my-zsh/themes/crcandy.zsh-theme
.oh-my-zsh/plugins/react-native/README.md
.oh-my-zsh/plugins/react-native/_react-native
.oh-my-zsh/plugins/react-native/react-native.plugin.zsh
.oh-my-zsh/plugins/arcanist/README.md
.oh-my-zsh/plugins/archlinux/README.md
.oh-my-zsh/plugins/rsync/rsync.plugin.zsh
.oh-my-zsh/plugins/arcanist/arcanist.plugin.zsh
.oh-my-zsh/plugins/archlinux/archlinux.plugin.zsh
.oh-my-zsh/plugins/mercurial/README.md
.oh-my-zsh/plugins/dircycle/dircycle.plugin.zsh
.oh-my-zsh/plugins/mercurial/mercurial.plugin.zsh
.oh-my-zsh/themes/tjkirch.zsh-theme
Fuzzy directory go to
$ <alt> + c
$
> chrome
| 16635/70115
> Library/Caches/Google/Chrome
Applications/Chrome Apps.localized
Library/Caches/Google/Chrome/Default
Applications/Chrome Canary Apps.localized
Library/Application Support/Google/Chrome
Library/Caches/Google/Chrome/Default/Cache
Library/Application Support/Google/Chrome/pnacl
Library/Application Support/Google/Chrome Canary
Library/Caches/Google/Chrome/Default/Media Cache
Library/Caches/Google/Chrome/Default
Library/Caches/Google/Chrome/Crashpad
Library/Caches/Google/Chrome/Default/PnaclTranslationCache
Library/Application Support/Google/Chrome/EVWhitelist
Library/Application Support/Google/Chrome/PepperFlash
Library/Caches/Google/Chrome/ShaderCache
Library/Caches/Google/Chrome/WidevineCDM
Applications/Chrome Canary Apps.localized/app_list.app
Library/Caches/Google/Chrome/Crashpad/new
Library/Caches/Google/Chrome/OriginTrials
rg earned its spot by being fast in the cases that matter: it walks directories in parallel, respects .gitignore so a search inside a repository skips node_modules instead of drowning you in it, and passes over binary files without being asked. It assumes you are searching a source tree, which you almost always are.
fzf earns its spot by being the universal picker. It reads candidate lines from stdin, shows a fuzzy-matched list, and prints your selection to stdout. That contract means it composes with everything.
The two config lines above weld them together. FZF_DEFAULT_COMMAND tells fzf how to gather candidates when invoked bare, and rg --files is a better gatherer than the stock find: list every file (--files), include dotfiles (--hidden), skip the ignore rules so nothing is invisible (--no-ignore), follow symlinks (--follow), but keep .git and node_modules out (-g "!{.git,node_modules}/*"). Pointing FZF_CTRL_T_COMMAND at the same command puts CTRL-T into that same pool of candidates.
Once both tools speak stdin and stdout, the combinations are free:
$ rg --line-number TODO | fzf # pick a match, get the file and line
$ vim "$(fzf)" # open whichever file you fuzzy-pick
$ git log --oneline | fzf # find a commit without scrolling
The three bindings cover most of the daily use: CTRL-R over shell history with a preview of the full command, CTRL-T to drop a path into the command you are typing, and ALT-C to cd into a fuzzy-picked directory, which is each of the transcripts above in a single keystroke.
Published on by Stanley