fzfを導入してterminalでの作業効率を爆上げする
概要
今更ながら,コマンドラインで曖昧検索を行えるfzfを導入してみました.
fzfを活用することで,様々なコマンドをより便利にすることができます.
今回はその設定に関して,こちらにメモを残しておきます.
- 概要
- fzfとは
- fzfを使ってできることの例
- fzfをインストールする
- fzfを使ってみる
- fzfの設定を行う
- 便利な関数を定義する
- fgc: インタラクティブにgit checkoutする
- flog: gitのコミットログをインタラクティブに見る
- fcd: インタラクティブにcdする
- fadd: インタラクティブにgit addするファイルを選択したり,diffを確認する
- fvim: カレントディレクトリから編集可能なファイルを選択してvimで開く
- Ctrl + z: かつて訪れたディレクトリに移動する
- fkill: インタラクティブにプロセスをkillする
- fdcnte: 実行中のコンテナを選択して,シェルにログインする
- fdl: dockerコンテナを選択し,ログを見る
- fcntre: dockerコンテナを選択して,再起動する
- fdcntrm: dockerコンテナを選択して,削除する
- fdimgrm: dockerイメージを選択して,削除する
- まとめ
- 参考
fzfとは
fzfは,コマンドラインでインタラクティブに曖昧検索を行えるツールです.
ファイルやディレクトリに限らず,コマンド履歴やプロセス,ホストネームやgitのコミットなど,あらゆるものをフィルタリングできます.
fzfを使ってできることの例
fzfを使うと様々なことができるようになります!
以下一例ですが,fzfを使用して設定した便利な機能について紹介します
プレビュー付きでファイルの検索
ファイル名をあいまい検索しつつ,プレビューも同時に見ることができます.
過去に訪れたディレクトリに移動
過去に訪れたことのあるディレクトリをあいまい検索し,そのディレクトリに移動することができます
プロセスを検索してkill
プロセスを曖昧検索してインタラクティブにkillすることができます.
Dockerイメージをインタラクティブに削除
Dockerイメージの名前をあいまい検索して,インタラクティブに削除できます
fzfをインストールする
それでは,fzfをインストールしていきましょう.
Macを使用している場合は以下を実行します.
brew install fzf # To install useful key bindings and fuzzy completion: $(brew --prefix)/opt/fzf/install
Ubuntuの場合はapt-get
でインストールできます.
sudo apt-get install fzf
その他のOSに関しては,こちらを参照してください.
また,他に一緒に追加しておくと便利なbat, ripgrepも追加しておきます.
brew install ripgrep brew install bat
いずれもcat
, grep
コマンドを進化系のようなツールとなっています.
その他のOSでのインストール方法やパッケージの詳細については,公式のページをご覧ください.
fzfを使ってみる
それではfzfを使ってみましょう.
あるコマンドの標準出力をパイプで渡すだけで,それらに対してあいまい検索を行うことができます.
この際カーソルの上下移動はそれぞれCtrl + k
とCtrl + j
で,選択はEnter
でできます.
find . | fzf
これを応用することで,カレントディレクトリからファイルをあいまい検索し,選択したファイルをvimで開くということもできます.
vim `find . -type f | fzf`
またこの際にfzf
コマンドのオプションを追加することで,プレビューを表示することも可能です.
vim `find . -type f | fzf --preview 'bat --color=always --style=header,grid {}' --preview-window=right:60%`
このように,fzfを使うことで,様々なコマンドをより便利に使用することができます.
またfzfの使い方として,入力の途中で**
を使用して,その続きを検索することもできます.
こちらはファイル名に限らず,プロセスなどにも使用できます.
fzfの設定を行う
fzfでは,fzf
実行時のデフォルトのコマンドやオプションを設定することができ,
レイアウトのオプションを固定することができます.(参考
また,Ctrl + r
, CTR + z
を実行時のコマンドやオプションも設定できます.
詳しくはこちらをご参照ください.
自分は以下のような設定を.zshrc
に記述しました.
【2022.4.20 追記】
FZF_DEFAULT_OPTS
に--preview
オプションを追加するとうまく機能しないことがあります.
詳しくは以下をご参照ください.
export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --glob "!**/.git/*"' export FZF_DEFAULT_OPTS=" --height 40% --reverse --border=sharp --margin=0,1 --prompt=' ' --color=light " # for finding files in current directories export FZF_CTRL_T_COMMAND='rg --files --hidden --follow --glob "!**/.git/*"' export FZF_CTRL_T_OPTS=" --preview 'bat --color=always --style=header,grid {}' --preview-window=right:60% " # Ref: https://wonderwall.hatenablog.com/entry/2017/10/06/063000 # コマンドが長すぎる時に?を押すと,全コマンドが見れる export FZF_CTRL_R_OPTS=" --preview 'echo {}' --preview-window down:3:hidden:wrap --bind '?:toggle-preview' "
便利な関数を定義する
それではfzfを使用した便利な関数を定義していきます.
自分はfzfを使った関数は,全てf
から始まる名前にしていますが,好みに合わせて適宜名前は変更してください
多くは他のサイトからの引用してきたものですので,詳細に関しては元のサイトをご覧ください.
fgc
: インタラクティブにgit checkout
する
# fgc (git checkout) - checkout git branch including remote branches # ref: https://qiita.com/kamykn/items/aa9920f07487559c0c7e fgc() { local branches branch branches=$(git branch --all | grep -v HEAD) && branch=$(echo "$branches" | fzf-tmux -d $(( 2 + $(wc -l <<< "$branches") )) +m) && git checkout $(echo "$branch" | sed "s/.* //" | sed "s#remotes/[^/]*/##") }
flog
: gitのコミットログをインタラクティブに見る
# flog - git commit browser # ref: https://qiita.com/kamykn/items/aa9920f07487559c0c7e flog() { git log --graph --color=always \ --format="%C(auto)%h%d %s %C(#C0C0C0)%C(bold)%cr" "$@" | fzf --ansi --no-sort --reverse --tiebreak=index --bind=ctrl-s:toggle-sort \ --bind "ctrl-m:execute: (grep -o '[a-f0-9]\{7\}' | head -1 | xargs -I % sh -c 'git show --color=always % | less -R') << 'FZF-EOF' {} FZF-EOF " }
fcd
: インタラクティブにcd
する
# fd - cd to selected directory # https://qiita.com/kamykn/items/aa9920f07487559c0c7e fcd() { local dir dir=$(find ${1:-.} -path '*/\.*' -prune \ -o -type d -print 2> /dev/null | fzf +m) && cd "$dir" }
fadd
: インタラクティブにgit add
するファイルを選択したり,diffを確認する
# fadd: git add / diff をインタラクティブに.Ctrl-d で diff, Enter で add # https://qiita.com/reviry/items/e798da034955c2af84c5 fadd() { local out q n addfiles while out=$( git status --short | awk '{if (substr($0,2,1) !~ / /) print $2}' | fzf-tmux --multi --exit-0 --expect=ctrl-d); do q=$(head -1 <<< "$out") n=$[$(wc -l <<< "$out") - 1] addfiles=(`echo $(tail "-$n" <<< "$out")`) [[ -z "$addfiles" ]] && continue if [ "$q" = ctrl-d ]; then git diff --color=always $addfiles | less -R else git add $addfiles fi done }
fvim
: カレントディレクトリから編集可能なファイルを選択してvimで開く
自分は,fv
というエイリアスも追加しています
# fvim: ファイル名検索+Vimで開くファイルをカレントディレクトリからfzfで検索可能に # ref: https://momozo.tech/2021/03/10/fzf%E3%81%A7zsh%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E4%BD%9C%E6%A5%AD%E3%82%92%E5%8A%B9%E7%8E%87%E5%8C%96/ fvim() { local file file=$( rg --files --hidden --follow --glob "!**/.git/*" | fzf \ --preview 'bat --color=always --style=header,grid {}' --preview-window=right:60% ) vi "$file" } alias fv="fvim"
Ctrl + z
: かつて訪れたディレクトリに移動する
# かつていたことのあるディレクトリに移動する # https://qiita.com/kamykn/items/aa9920f07487559c0c7e fzf-z-search() { local res=$(z | sort -rn | cut -c 12- | fzf) if [ -n "$res" ]; then BUFFER+="cd $res" zle accept-line else return 1 fi } zle -N fzf-z-search bindkey '^z' fzf-z-search
fkill
: インタラクティブにプロセスをkillする
# プロセスをkill fkill() { local pid pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}') if [ "x$pid" != "x" ] then echo $pid | xargs kill -${1:-9} fi }
fdcnte
: 実行中のコンテナを選択して,シェルにログインする
dcnte
はdocker container exec
の略です.
# fzfでdockerコンテナに入る # ref: https://momozo.tech/2021/03/10/fzf%E3%81%A7zsh%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E4%BD%9C%E6%A5%AD%E3%82%92%E5%8A%B9%E7%8E%87%E5%8C%96/ fdcnte() { local cid cid=$(docker ps | sed 1d | fzf -q "$1" | awk '{print $1}') [ -n "$cid" ] && docker exec -it "$cid" /bin/bash }
fdl
: dockerコンテナを選択し,ログを見る
# fzfでdockerのログを取得 # ref: https://momozo.tech/2021/03/10/fzf%E3%81%A7zsh%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E4%BD%9C%E6%A5%AD%E3%82%92%E5%8A%B9%E7%8E%87%E5%8C%96/ fdl() { local cid cid=$(docker ps -a | sed 1d | fzf -q "$1" | awk '{print $1}') [ -n "$cid" ] && docker logs -f --tail=200 "$cid" }
fcntre
: dockerコンテナを選択して,再起動する
# fzfでDockerコンテナ再起動 # ref: https://momozo.tech/2021/03/10/fzf%E3%81%A7zsh%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E4%BD%9C%E6%A5%AD%E3%82%92%E5%8A%B9%E7%8E%87%E5%8C%96/ fdcntre() { local cid cid=$(docker ps -a | sed 1d | fzf -m -q "$1" | awk '{print $1}') [ -n "$cid" ] && echo $cid | xargs docker container restart }
fdcntrm
: dockerコンテナを選択して,削除する
# docker container rm # ref: https://momozo.tech/2021/03/10/fzf%E3%81%A7zsh%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E4%BD%9C%E6%A5%AD%E3%82%92%E5%8A%B9%E7%8E%87%E5%8C%96/ fdcntrm() { local cid cid=$(docker ps -a | sed 1d | fzf -m -q "$1" | awk '{print $1}') [ -n "$cid" ] && echo $cid | xargs docker container rm -f }
fdimgrm
: dockerイメージを選択して,削除する
# docker image rm fdimgrm() { local cid cid=$(docker image ls -a | sed 1d | fzf -m -q "$1" | awk '{print $1}') [ -n "$cid" ] && echo $cid | xargs docker image rm -f }
まとめ
今回はfzfを使ってみました.
非常に便利で,カスタマイズのしがいもあるので,今後もより良い使い方を模索していきたいです.
参考
- fzf
- fzfを活用してTerminalの作業効率を高める - Qiita
- gitのdiff, addをfzf でインタラクティブに - Qiita
- fzfを使おう - Qiita
- fzf(fuzzy finder)の便利な使い方をREADME, Wikiを読んで学ぶ - もた日記
- fzfでターミナル作業を効率化 – 百蔵の部屋
- sharkdp/bat: A cat(1) clone with wings.
- BurntSushi/ripgrep: ripgrep recursively searches directories for a regex pattern while respecting your gitignore