zshでfzfを使ってぼやけたxdg-openを取得する方法は?

zshでfzfを使ってぼやけたxdg-openを取得する方法は?

質問

試してみました。富士ショートカット(好ましくはCtrl+ o)をバインドしてファイルを対話的に検索し、xdg-openzshにパイプします。fzfソースファイルが次の場所にある限り、多くのショートカットはすでにユーティリティの一部です。fzf/シェル/keybinding.zsh。ここでは、バインディングCtrl+rコマンド履歴のファジィ検索とCtrl+t現在のコマンドラインのファジーコンプリートのスニペットを見つけることができます。 fzfソースコードの最初のショートカットは次のとおりです。

# CTRL-R - Paste the selected command from history into the command line
fzf-history-widget() {
  local selected num
  setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2> /dev/null
  selected=( $(fc -rl 1 | perl -ne 'print if !$seen{(/^\s*[0-9]+\**\s+(.*)/, $1)}++' |
    FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS --query=${(qqq)LBUFFER} +m" $(__fzfcmd)) )
  local ret=$?
  if [ -n "$selected" ]; then
    num=$selected[1]
    if [ -n "$num" ]; then
      zle vi-fetch-history -n $num
    fi
  fi
  zle reset-prompt
  return $ret
}
zle     -N   fzf-history-widget
bindkey '^R' fzf-history-widget

もちろん、選択した結果をコマンドに直接リンクするのではなく、コマンドラインに貼り付けるので、私が望むものとは少し異なります。しかし、以下のbashスクリプトはまさに私が期待する動作を持っており、これを実行すると私が直接できるよりもよく解釈することができます。

bind -x '"\C-o": file="$(fzf --height 40% --reverse)" && [ -f "$file" ] && xdg-open "$file"'

私もこれを見つけました。魚の機能動作は同じですが、Fishの構文はzshやbashなどのPOSIX互換シェルとは非常に異なるため、これがどのように役立つかわかりません。

それでは、+を対話型fzf検索にCtrlバインドし、結果をzshに直接パイプする方法を知っている人はいますか?oxdg-open

よろしくお願いします!


回答

以下は私が書いた作業スクリプトです。これスタックオーバーフローの答え。

fuzzy-xdg-open() {
  local output
  output=$(fzf --height 40% --reverse </dev/tty) && xdg-open ${(q-)output}
  zle reset-prompt
}

zle -N fuzzy-xdg-open
bindkey '^o' fuzzy-xdg-open

ベストアンサー1

zshキーまたはキーの組み合わせ(使用bindkey)をバインドします。小さな部品、行エディタで特別な操作を実行するウィジェットです。

組み込み関数を使用してカスタムウィジェットを定義できますzle

このカスタムウィジェット内で任意のコマンドを実行できますが、数値引数の処理方法を検討することもできます。

たとえば、ユーザーが++を入力した場合、ほとんどAlt3 Ctrlウィジェットの規則に従ってコマンドを3回実行しますか?o

また、コマンドを実行した後にラインエディタバッファ(これまで入力した内容)やプロンプトを再描画する必要があるのか​​、または実行したコマンドがターミナルの内容に書き込まれる場合に備えて、コマンドを実行する前に非表示にする必要も考慮する必要があります。さらに、コマンドの終了ステータスは、ウィジェットが成功したかどうかを決定する必要があります(たとえば、視覚的または聴覚的な通知が発生するなど)。

ユーザー入力が必要なウィジェットでツールを実行している場合は、ZLEリダイレクト時にttyから標準入力を復元して、行エディタの一般的な/dev/null入力フローを妨げないようにする必要があります。コマンドが端末を検出したときと同じ状態に保つことを確認する必要がありますfzf

たとえば、次のようになります。

my-open-widget() {
  zle -I # invalidate current zle display
  local file ret=0
  repeat ${NUMERIC-1} {
    file="$(fzf --height 40% --reverse)" &&
      [ -f "$file" ] &&
      xdg-open "$file" ||
      ret=$?
  } < /dev/tty
  return $ret
}

zle -N my-open-widget
bindkey '^o' my-open-widget

要求に応じてコードを複数回実行し、失敗時に失敗を返すには、プレビューを無効にして、コード出力がプロンプトを複雑にしないようにします。

または、インスタンスが失敗した場合はすぐに中断(|| ret=$?に置き換え)することもできます|| return。または、コードがディスプレイをめちゃくちゃにせず、より一般的にttyと対話しないことを知っている場合はスキップしてくださいzle -I。あるいは、数値引数を無視して無条件コードを一度だけ実行すると、最終的に機能します。ウィジェット関数の本文も同様に簡単です。

おすすめ記事