fzfのpreview関連のオプション調べてみた
どうも。えーたんです。
fzfのオプションについて調べたことを、備忘録として残しておきます。
プレビューウィンドウの話が中心です。
{}
の意味
fzfでの波括弧
{}
{}
はfzfの現在カーソルがある行の文字列です。
find . -name node_modules -prune -name .git -prune -o -type f -print \
| fzf --preview 'echo {}'
以下の画像の例では./.gitignore
の行にカーソルがあるため、previewのコマンドecho {}
はecho ./.gitignore
に置き換わって実行されます。
{q}
{q}
はfzfのプロンプトに入力している文字列です。
find . -name node_modules -prune -name .git -prune -o -type f -print \
| fzf --preview 'echo {q}'
以下の画像の例ではfzfのプロンプトにjs
を入力しているため、previewのコマンドecho {q}
はecho js
に置き換わって実行されます。
{数字}
{n}
のように数字を指定すると、「現在カーソルがある行の文字列」をスペースで区切ったときのインデックスnの文字列を切り出せます。このインデックスは1始まりです。
例を見てみましょう。
ls -l --time-style=+'%Y-%m-%d' \
| grep -v / \
| fzf --preview="echo user={3} when={-2}; cat {-1}" --header-lines=1
まず、最初の2行(lsとgrep)でファイルの一覧を取得しています。この時点での結果は以下のような形式です。
total 108
-rw-r--r-- 1 eetann eetann 364 2022-03-21 index.html
-rw-r--r-- 1 eetann eetann 366 2022-03-21 package.json
-rw-r--r-- 1 eetann eetann 86768 2022-03-21 package-lock.json
-rw-r--r-- 1 eetann eetann 162 2022-03-21 vite.config.js
最初の1行目は絞り込みには関係ないため、fzfのオプションで--header-lines=1
を指定してヘッダーとして扱います。
lsをgpepした結果を空白区切りとして扱い、3番目である所有者情報を{3}
、後ろから2番目である最終更新日を{-2}
、最後のファイル名を{-1}
のように指定しました。
区切りを変更したい場合、--delimiter :
のように--delimiter
オプションで指定します。
{+}
や{+数字}
{}
や{数字}
は「現在カーソルがある行」でしたが、{+}
や{+数字}
のように+
をつけると「現在選択している行」の文字列になります。
以下のような--multi
オプションで複数選択をするときに使います。
ls -l | grep -v / \
| fzf --multi \
--preview="cat {+-1}" \
--header-lines=1
以下の画像の例では、現在選択している2つのファイル(index.html
、vite.config.js
)が表示されています。
--preview-window
オプション
manにはどう書かれているか
man fzf
に書かれている--preview-window
の概要は以下です。(長い)。
--preview-window=[POSITION][,SIZE[%]][,border-BORDER_OPT][,[no]wrap][,[no]follow][,[no]cycle][,[no]hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)]
この中から一部を紹介します。
[,border-BORDER_OPT]
border-BORDER_OPT
では、プレビューウィンドウを区切るための線のスタイルを指定します。
以下はデフォルトのborder-rounded
の例です。
ls -l | grep -v / \
| fzf \
--preview="echo user={3}; cat {-1}" \
--header-lines=1 \
--preview-window=down
次にborder-top
の例です。
ls -l | grep -v / \
| fzf \
--preview="echo user={3}; cat {-1}" \
--header-lines=1 \
--preview-window=down,border-top
[,+SCROLL[OFFSETS][/DENOM]]
[,+SCROLL[OFFSETS][/DENOM]]
では、プレビューウィンドウのスクロールの位置を設定します。
+SCROLL
+SCROLL
には、プレビューウィンドウのスクロール開始位置を指定します。
以下は+5
(+SCROLL
の部分)を指定した例です。
ls | grep -v / \
| fzf \
--preview 'cat {}' \
--preview-window=down,+5
プレビューウィンドウは5行目から表示されます。
[OFFSETS]
以下は bat
コマンドを使って+{2}+3
(+SCROLL[OFFSETS]
の部分)を指定した例です。
少し区切って説明していきます。
rg --line-number --no-heading -g '!{.git,node_modules}' --invert-match '^\s*$' \
| fzf \
--delimiter : \
--preview 'bat --color=always {1} --highlight-line {2}' \
--preview-window=down,+{2}+3
まず、rg
による出力は以下のような形式です。
src/App.jsx:16: </div>
src/routes/invoices.jsx:66: </div>
index.html:10: <div id="root"></div>
src/App.jsx:4: <div>
src/routes/invoices.jsx:20: <div style={{ display: "flex" }}>
「ファイル名」「行番号」「該当箇所」が:
で区切られています。
「行番号」を前述の{数字}
の形式で切り出してプレビューで扱うため、--delimiter
オプションで区切りを:
に変更します。
これで{2}
と書くと行番号に置き換わります。
今回は「行番号」をプレビューウィンドウのスクロール開始位置とするため、--preview-window
に+{2}
を指定します。+{2}
は+SCROLL
と{数字}
の組み合わせです。
次に、bat
コマンドの例です。以下のように最初の3行はヘッダーです。
そのため、+{2}
のままだとスクロール開始位置が行番号よりも3行上にずれてしまいます。
このズレは[,+SCROLL[OFFSETS][/DENOM]]
の[OFFSETS]
の部分を使うことで修正できます。
今回は3行増えてほしいため、[OFFSETS]
として+3
を書き加えました。
[/DENOM]
[,+SCROLL[OFFSETS][/DENOM]]
の/DENOM
は、カーソルのある行とマッチするプレビューウィンドウの行の位置を調整してくれます。
具体的には、ウィンドウ上部から1/指定した数字
ぐらいの位置にカーソル行が来るように調整してくれます。
rg --line-number --no-heading -g '!{.git,node_modules}' --invert-match '^\s*$' \
| fzf \
--delimiter : \
--preview 'bat --color=always {1} --highlight-line {2}' \
--preview-window=+{2}+3/2
以下のように、カーソル行と一致する「プレビューウィンドウの行」が、1/2
ぐらいの位置に調整されています。
[,~HEADER_LINES]
[,~HEADER_LINES]
を使うことで、プレビューウィンドウにヘッダーを設定できます。
以下の例では、bat
のヘッダーである1〜3行目をfzfのプレビューウィンドウのヘッダーとして指定しています。
rg --line-number --no-heading -g '!{.git,node_modules}' --invert-match '^\s*$' \
| fzf \
--delimiter : \
--preview 'bat --color=always {1} --highlight-line {2}' \
--preview-window=+{2}+3/2,~3
ヘッダーを設定したため、以下の例ではスクロールしてもFile: src/favicon.svg
が表示されたままです。
テーマを変える
--color
オプションでfzfのテーマを色をテーマを変えることができます。
以下の例では、fzfの公式ドキュメントに掲載されているNord Themeをもとにした色と、プレビューで使っているbat
で--theme="Nord"
を指定しました。
rg --line-number --no-heading -g '!{.git,node_modules}' --invert-match '^\s*$' \
| fzf \
--delimiter : \
--preview 'bat --color=always {1} --theme="Nord" --highlight-line {2}' \
--preview-window=+{2}+3/2,~3 \
--color='bg+:#3B4252,bg:#2E3440,spinner:#81A1C1,hl:#616E88,fg:#D8DEE9,header:#616E88,info:#81A1C1,pointer:#81A1C1,marker:#81A1C1,fg+:#D8DEE9,prompt:#81A1C1,hl+:#81A1C1'
fzf
ならADVANCED.mdやWiki、bat
ならコマンドbat --list-themes
やコードを直接見ると、他のテーマも掲載されています。
筆者の設定
永遠に未完成ですが、2022-08-28現在の筆者の設定を一部掲載します。
以下のように環境変数を設定し、fzfをtmuxのポップアップで表示しています。
export FZF_TMUX=1
export FZF_TMUX_OPTS="-p 80%"
先に画像で表示例をまとめて紹介します。
CTRL + R
の例
プレビューウィンドウを下に配置しています。ワンライナーなどの長いコマンドでは折り返したり、(完全ではないですが)改行ありで実行したコマンドは改行して表示しています。bat
コマンドで色をつけています。
CTRL + T
の例
ワンライナーなどの長いコマンドでは折り返したり、(完全ではないですが)改行ありで実行したコマンドは改行して表示しています。本記事で登場した[,+SCROLL[OFFSETS][/DENOM]]
や[,~HEADER_LINES]
とbat
コマンドを組み合わせています。
ALT + C
の例
ディレクトリ名はあまり長くならないため、プレビューウィンドウを右に配置しています。
コードは以下です。
ZLEとの組み合わせ
ZLEを組み合わせて、入力途中の文字列をいい感じに拾ってfzfのクエリを開始するやつを書いて使ってます。
たとえば、nvim .config
の後にCTRL + k
を入力すると.config
をクエリにしてfzfを開始します。
nvim .config/i3/config zsh
の後にCTRL + k
を入力すると、.config/i3/config
はそのまま残し、zsh
をクエリにしてfzfを開始します。
参考
Discussion