LoginSignup
9
8

More than 3 years have passed since last update.

【fzf】ターミナル上でファイル名検索と全文検索をPreview付でやりたい

Posted at

エディタ・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-0.22.0 zsh-5.8

その前に :tea:

私のfzf default optionです。
--height は指定ありのほうが見やすくて好きです。

.zshrc
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の設定については :point_right_tone2: こちら

改行ありTextが個人的に嫌だったので実際には配列、連想配列を使って記述してます
つまりこう↓

.zshrc
# 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

見た目はこんな感じ
image.png

ファイル名検索 :pencil:

デフォルトの動きは「カレントディレクトリ配下のファイル・ディレクトリを検索」です

今回は以下のようにカスタマイズしたいと思います

  • デフォルトコマンドをfdに変更。検索対象はファイルのみに
  • 選択なかったら自動終了、1件のみの場合は自動で選択
  • プレビューの表示 (batコマンド使う)
  • 開く (できれば別ペインで)
  • 隠しファイルの表示切替

記述がこちら

.zshrc
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 {}'"

こんな具合になります
ctrl-t.gif

全文検索 :mag:

カレントディレクトリ配下のファイルを全文検索。選択したファイルをコマンドラインに貼り付ける

manにある記述を参考にしてます
queryを変更するたび rg で検索が走ります

作ったもの

fzf-ripgrep-widget
#!/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 
.zshrc
autoload -Uz fzf-ripgrep-widget

zle -N fzf-ripgrep-widget
bindkey '\ef' fzf-ripgrep-widget

動き
alt-f.gif

検索結果がpreview内で追えて満足
ただハイライトが少し微妙なのと、 検索結果windowのformatが残念

感想 :speech_balloon:

いくつか課題が残ってますが、これが現状MAX :grimacing:
Rust関連のコマンドに触れてRustすげーとなっております

:wave_tone1:

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8