みんな大好きfzf
fzfは結果をインタラクティブに絞り込むだけのコマンドだが、組み合わせ次第でかなり使えるコマンドだ。日本ではpecoの方が有名だが海外ではfzfの方が人気らしい。
筆者が思うpecoと比較したときのfzfのメリットを述べる。
- 画面クリアがなく目に優しい
- fuzzy search(曖昧検索)が可能
- 絞り込んだものをパイプつなぎでコマンドを適用でき、結果をpreviewとして画面に表示できる
- カスタマイズが豊富
特にfuzzy searchとpreviewできる点が素晴らしい。またfzfの絞り込み結果の画面サイズを指定できたりとカスタマイズ性が高いのもGOOD。
以下はgit logの結果をfzfで絞り込み、previewにgit diffを表示、ENTERで詳細をless表示させているもの。(ちなみに別で全く同じ動作をするtiggコマンドというものがあるらしい)
私のfzfのデフォルトの設定は以下。複数選択と色合いを変化、あとデフォルトだと絞り込み画面が下からでるのでreverseで直下に出している。
# fzfの設定 export FZF_DEFAULT_OPTS='--color=fg+:11 --height 70% --reverse --select-1 --exit-0 --multi'
実際に業務でも使っているコマンド一覧をつらつらと紹介していく。
爆速でディレクトリの移動をするfzf-cdr
これがない時のTerminalの移動はもう考えられない。cdrで過去に行ったことのあるディレクトリを表示し、fzfで絞り込んでディレクトリに移動する。 ちなみに私は「change directory direct」という意味で「cdd」というaliasをつけている。
# fzf-cdr alias cdd='fzf-cdr' function fzf-cdr() { target_dir=`cdr -l | sed 's/^[^ ][^ ]* *//' | fzf` target_dir=`echo ${target_dir/\~/$HOME}` if [ -n "$target_dir" ]; then cd $target_dir fi }
cdrの設定は以下のようにしている。ココらへんちょっと適当かもしれない(いつ書いたか忘れてた)。
# cdrの設定 autoload -Uz is-at-least if is-at-least 4.3.11 then autoload -Uz chpwd_recent_dirs cdr add-zsh-hook add-zsh-hook chpwd chpwd_recent_dirs zstyle ':chpwd:*' recent-dirs-max 500 zstyle ':chpwd:*' recent-dirs-default yes zstyle ':completion:*' recent-dirs-insert both fi
ctrl+zでストレスなくバックグラウンドに入れる&出す
vimでファイルを開いていて、ふとterminalに戻って操作をしたくなる時があります。そんなときは大体ctrl+zで一旦バックに入れてfgで戻ってくる、という動作をすると思います。 ただ戻るのに一々fgを打つのも面倒くさいのでctrl+zで行ったり来たりするように設定しています。
# fgを使わずctrl+zで行ったり来たりする fancy-ctrl-z () { if [[ $#BUFFER -eq 0 ]]; then BUFFER="fg" zle accept-line else zle push-input zle clear-screen fi } zle -N fancy-ctrl-z bindkey '^Z' fancy-ctrl-z
ただ、これだと直前のバックグランドに入れたものとしか行き来できないので、2個前のプロセスに戻りたい時などはfzfで選択しています。
# fgをfzfで alias fgg='_fgg' function _fgg() { wc=$(jobs | wc -l | tr -d ' ') if [ $wc -ne 0 ]; then job=$(jobs | awk -F "suspended" "{print $1 $2}"|sed -e "s/\-//g" -e "s/\+//g" -e "s/\[//g" -e "s/\]//g" | grep -v pwd | fzf | awk "{print $1}") wc_grep=$(echo $job | grep -v grep | grep 'suspended') if [ "$wc_grep" != "" ]; then fg %$job fi fi }
agでヒットした行をvimで開く
これは最近vimのプラグインで完結するようになったから使わなくなってしまったが、一時期はNOTE:とかFIXME:を探して修正しに行くのに結構使ってた。
# agの結果をfzfで絞り込み選択するとvimで開く alias agg="_agAndVim" function _agAndVim() { if [ -z "$1" ]; then echo 'Usage: agg PATTERN' return 0 fi result=`ag $1 | fzf` line=`echo "$result" | awk -F ':' '{print $2}'` file=`echo "$result" | awk -F ':' '{print $1}'` if [ -n "$file" ]; then vim $file +$line fi }
各ブランチのgit logを見ながらcheckoutする
これももはや定番かもしれない、gitの操作をfzfに食わせるものだ。 gitの操作は手打ちでやると面倒くさいものも多いので、絞り込みで曖昧に覚えているものを打ち込んで選択するのがすごい楽。
# git checkout branchをfzfで選択 alias co='git checkout $(git branch -a | tr -d " " |fzf --height 100% --prompt "CHECKOUT BRANCH>" --preview "git log --color=always {}" | head -n 1 | sed -e "s/^\*\s*//g" | perl -pe "s/remotes\/origin\///g")'
ちなみに「co」は「CheckOut」の略だ。 git checkoutの他にも
- git add -pをfzfでdiffを見ながら選択
- git checkout fileをfzfで選択
- git resetをfzfでdiffを見ながら選択
といった操作をすべてfzfでやっている。
終わり
fzfのREADMEにあるExample集にもかなりの数があるので参考にしたい。 fzf最高。