エディタ・IDE等によくある検索機能をfzfでつくってみよう記事
ファイル名検索は fzfで用意されているKeyBind(Ctrl+T)をカスタマイズします
$(brew --prefix)/opt/fzf/install
したときに自動で設定してくれるあれです
widget関数の詳細は /usr/local/opt/fzf/shell/key-bindings.zsh
で確認できます
注書きみたいなの
- 記事内で外部コマンド(
bat
,rg
,fd
)使ってます -
macOS
,zsh
での動作しか確認してないです
junegunn/fzf: A command-line fuzzy finder
man page
その前に
私のfzf default optionです。
--height
は指定ありのほうが見やすくて好きです。
export FZF_DEFAULT_OPTS="
--height 90% --reverse --border
--prompt='➜ ' --margin=0,1 --inline-info
--tiebreak=index --no-mouse --filepath-word
--color fg:-1,bg:-1,hl:33,fg+:250,bg+:235,hl+:33
--color info:37,prompt:37,pointer:230,marker:230,spinner:37
--bind='ctrl-w:backward-kill-word,ctrl-x:jump,down:preview-page-down'
--bind='ctrl-z:ignore,ctrl-]:replace-query,up:preview-page-up'
--bind='ctrl-a:toggle-all,?:toggle-preview'
"
bindkeyの設定については こちら
改行ありTextが個人的に嫌だったので実際には配列、連想配列を使って記述してます
つまりこう↓
# fzf
export FZF_COMPLETION_TRIGGER=','
typeset -Tgx FZF_DEFAULT_OPTS fzf_default_opts " "
fzf_default_opts=(
'--height=90%'
'--reverse'
'--border'
'--inline-info'
'--prompt="➜ "'
'--margin=0,2'
'--tiebreak=index'
'--no-mouse'
'--filepath-word'
)
() {
local -A color_map=(
[fg]='-1'
[bg]='-1'
[hl]='33'
[fg+]='250'
[bg+]='235'
[hl+]='33'
[info]='37'
[prompt]='37'
[pointer]='230'
[marker]='230'
[spinner]='37'
)
for x in "${(k)color_map[@]}"; do
fzf_color_opts+=("${x}:${color_map[${x}]}")
done
fzf_default_opts+=( '--color="'"${(j.,.)fzf_color_opts}"'"' )
}
() {
local -a fzf_bind_opts=()
local -A bind_map=(
[?]='toggle-preview'
[ctrl-a]='toggle-all'
['ctrl-]']='replace-query'
[ctrl-w]='backward-kill-word'
[ctrl-x]='jump'
[ctrl-z]='ignore'
[up]='preview-page-up'
[down]='preview-page-down'
)
for x in "${(k)bind_map[@]}"; do
fzf_bind_opts+=("${x}:${bind_map[${x}]}")
done
fzf_default_opts+=( '--bind="'"${(j:,:)fzf_bind_opts}"'"' )
}
連想配列の記述がversion5.5以上のzshじゃないと読み込めないです
普通に平文でもおk
ファイル名検索
デフォルトの動きは「カレントディレクトリ配下のファイル・ディレクトリを検索」です
今回は以下のようにカスタマイズしたいと思います
- デフォルトコマンドを
fd
に変更。検索対象はファイルのみに - 選択なかったら自動終了、1件のみの場合は自動で選択
- プレビューの表示 (
bat
コマンド使う) - 開く (できれば別ペインで)
- 隠しファイルの表示切替
記述がこちら
export FZF_CTRL_T_COMMAND="fd --type f "
export FZF_CTRL_T_OPTS="
--select-1 --exit-0
--bind 'ctrl-l:execute(tmux splitw -h -- nvim {})'
--bind '>:reload($FZF_ALT_C_COMMAND -H -E .git )'
--bind '<:reload($FZF_ALT_C_COMMAND)'
--preview 'bat -r :100 --color=always --style=header,grid {}'"
全文検索
カレントディレクトリ配下のファイルを全文検索。選択したファイルをコマンドラインに貼り付ける
manにある記述を参考にしてます
queryを変更するたび rg
で検索が走ります
作ったもの
#!/usr/bin/env zsh
main() {
LBUFFER="${LBUFFER}$(__fzf_ripgrep)"
local ret=$?
zle reset-prompt
return $ret
}
__fzf_ripgrep() {
emulate -L zsh
rg_cmd="rg --smart-case --line-number --color=always --trim"
selected=$(FZF_DEFAULT_COMMAND=":" \
fzf --bind="change:top+reload($rg_cmd {q} || true)" \
--bind="ctrl-l:execute(tmux splitw -h -- nvim +/{q} {1} +{2})" \
--ansi --phony \
--delimiter=":" \
--preview="bat -H {2} --color=always --style=header,grid {1}" \
--preview-window='down:60%:+{2}-10')
local ret=$?
[[ -n "$selected" ]] && echo ${${(@s/:/)selected}[1]}
return $ret
}
main
autoload -Uz fzf-ripgrep-widget
zle -N fzf-ripgrep-widget
bindkey '\ef' fzf-ripgrep-widget
検索結果がpreview内で追えて満足
ただハイライトが少し微妙なのと、 検索結果windowのformatが残念
感想
いくつか課題が残ってますが、これが現状MAX
Rust関連のコマンドに触れてRustすげーとなっております