在 zle 键绑定中使用 fzf

在 zle 键绑定中使用 fzf

我的中有以下功能.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 -korread -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'}

相关内容