Zsh

在 zle 鍵綁定中使用 fzf

  • June 27, 2020

我有以下功能.zshrc

function foo() {
   filename="$(fzf)"
}
zle -N foo
bindkey '^X' foo

現在,如果我foo通過鍵入它來呼叫它,它會按預期工作,但是如果我通過鍵綁定呼叫它^X,則fzf緩衝區是空的。

任何人都可以重現這個嗎?我怎樣才能解決這個問題?

如果要點是fzf在目前游標位置插入輸出,正確引用,它應該是這樣的:

insert-quoted-fzf-output() {
 local output
 output=$(fzf</dev/tty) && LBUFFER+=${(q-)output}
}

zle -N insert-quoted-fzf-output
bindkey '^X' insert-quoted-fzf-output

也就是說,您需要在$LBUFFER(游標左側的編輯緩衝區部分)的末尾插入該輸出,引用(這裡使用q-參數擴展標誌以最小化引用量),並且您需要fzf從終端。fzf如果失敗,您可能希望小元件返回非零退出狀態。

您在這里關於空fzf緩衝區的具體問題是關於缺少</dev/tty重定向。

如果將fzf其作為fzf < /dev/null.

如果你執行info zsh widgets(假設你有zsh可用info格式的文件;在某些系統上,你可能需要安裝一個zsh-doc包),你會看到(強調我的):

18.5 使用者定義的小元件

使用者定義的小元件,被實現為 shell 函式,可以執行任何普通的 shell 命令。zle他們還可以使用內置命令 執行其他小元件(無論是內置的還是使用者定義的) 。該函式的標準輸入從 /dev/null 重定向,以防止外部命令通過從終端讀取無意中阻塞 ZLE,但read -kread -q可用於讀取字元。

當它的標準輸入不是終端時,fzf讀取它以建構提供給使用者的選項列表。/dev/null是一種特殊的設備,任何讀取任何內容的嘗試都會返回任何內容,這解釋了為什麼會得到一個空緩衝區。在那裡恢復終端使其切換回模式,在該模式下,它不是讀取 stdin 以獲取選項列表,而是讀取 $FZF_DEFAULT_COMMAND命令的輸出(預設為某些find命令)。

另一種選擇是自己實際執行該find命令。如果您使用的是 GNU 系統,您甚至可以對其進行改進以增加更多的可靠性和效率:

output=$(
 LC_ALL=C find -L . -name . -o '(' \
   -name '.*' -o \
   -fstype sysfs -o \
   -fstype devfs -o \
   -fstype devtmpfs -o \
   -fstype proc ')' -prune -o -type f -printf '%P\0' 2> /dev/null |
   fzf --read0 --print0
) && output=${output%$'\0'}

引用自:https://unix.stackexchange.com/questions/595350