![在 zle 键绑定中使用 fzf](https://linux22.com/image/175946/%E5%9C%A8%20zle%20%E9%94%AE%E7%BB%91%E5%AE%9A%E4%B8%AD%E4%BD%BF%E7%94%A8%20fzf.png)
我的中有以下功能.zshrc
function foo() {
filename="$(fzf)"
}
zle -N foo
bindkey '^X' foo
现在,如果我foo
通过键入来调用它,它会按预期工作,但如果我通过 键绑定 with 来调用它^X
,则fzf
缓冲区为空。
任何人都可以复制这个吗?我怎样才能解决这个问题?
答案1
如果要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 -k
orread -q
可用于读取字符。
当其标准输入不是终端时,fzf
读取它以构建提供给用户的选择列表。/dev/null
是一种特殊的设备,任何读取任何内容的尝试都不会返回任何内容,这解释了为什么您会得到一个空缓冲区。在那里恢复终端会使其切换回模式,在该模式下,它不会读取标准输入以获取选择列表,而是读取命令的输出 (默认情况下是$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'}