I've always had fzf and ripgrep on my radar, and I've finally gotten around to using them together. Good lord it makes a world of difference, especially when added to Vim as well as Bash.

Add the following snippet to your ~/.bashrc, this add's fzf keybindings to bash and gets fzf to use ripgrep by default for faster searching.

[ -f ~/.fzf.bash ] && source ~/.fzf.bash
export FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden --follow -g "!{.git,node_modules}/*" 2> /dev/null'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
bind -x '"\C-p": vim $(fzf);'

Okay now what can you do?

  • Ctrl + r - search through bash history with fzf
  • Ctrl + p - edit a file in vim from fzf
  • mv dir/** - expand a directory with (**) and select from fzf
  • Alt + c - change directory from fzf - see the update at the bottom for faster search with bfs.
  • Ctrl + t - insert file from fzf into command

Neat right! Now if you are a vim user there is more, add the fzf plugin to your ~/.vimrc, along with this snippet. Obviously customise the bindings, and excludes / includes to your workflows!

let g:rg_command = '
  \ rg --column --line-number --no-heading --fixed-strings --ignore-case --no-ignore --hidden --follow --color "always"
  \ -g "*.{js,json,php,md,styl,jade,html,config,py,cpp,c,go,hs,rb,conf}"
  \ -g "!{.git,node_modules,vendor}/*" '

command! -bang -nargs=* F call fzf#vim#grep(g:rg_command .shellescape(<q-args>), 1, <bang>0)

You now have a killer free text search with :F that uses ripgrep and is faster than any I've seen before.

I've done more with this, but want to leave it there for now. There are even more goodies in my .vimrc, and in my .bashrc, including auto installing fzf and ripgrep (admittedly hackily) from the .vimrc and a nice snippet that uses fzf for git logs.

Update

Just made this nice snippet for tmux:

tm() {
  [[ -n "$TMUX" ]] && change="switch-client" || change="attach-session"
  if [ $1 ]; then 
     tmux $change -t "$1" 2>/dev/null || (tmux new-session -d -s $1 && tmux $change -t "$1"); return
  fi
  session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --exit-0) &&  tmux $change -t "$session" || echo "No sessions found."
}
  • tm irc it will attach to the irc session (if it exists), else it will create it.
  • tm will open fzf and let you select the session

What is awesome is this lets you switch and create sessions from inside of other sessions.

And here is a nice snippet for looking through git logs:

fzf_log() {  
  hash=$(git log --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" |  fzf | awk '{print $1}')
  echo $hash | xclip
  git showtool $hash
}

It will let you select a commit, and display the diff off it, and put the commit hash on your clipboard using xclip. I also have it set to use icdiff via git showtool.

Update update...

A few people have pointed out that doing this doesn't work for fzf's Ctrl+T completion or the Alt+C completion. Thanks to @mikepqr, for letting me know the work around for Ctrl+T. I have updated the configurations at the top of the post with what he sent me.

Alt+C has proved a bit tricky to get working with ripgrep, as rg doesn't natively support searching just for directories. Instead I have been using bfs by adding the following to me config.

export FZF_ALT_C_COMMAND="cd ~/; bfs -type d -nohidden | sed s/^\./~/"  

After a bit of quick testing it appears to run faster and give slightly nicer results that the ripgrep solutions I've tried, although it does mean installing another tool!

:wq

BTC | 15FYeMgQsETViUcc8JtSmoHmCAmADy2Ymn
LTC | LVdVyd3R1S719ZRApaAY1RgLJ5vYgEGGxW
ARK | ANKmYTHV7QdkcLz2R65uMzEvcRRdz2iRQm