小部件只能在 ZLE 处于活动状态时调用

widgets can only be called when ZLE is active

我已经处理这个问题将近一个月了,我感到很沮丧,任何帮助将不胜感激。

我正在尝试为我的 takenote 命令编写一个小部件。该小部件的目的是将 ~/notes 文件夹中的所有降价文件提供给 fzf 以便用户可以 select 其中之一并开始编辑它。 在用户键入 takenote 并按下 <tab> 之后,我希望小部件 运行.

这里是 _takenote.zsh 小部件定义:

#compdef takenote
local file=$( find -L "$HOME/notes/" -print 2> /dev/null | fzf-tmux +m )
zle reset-prompt
compadd $file
return 1

不幸的是,由于 zle reset-prompt,上面的代码不起作用,如果我删除它,那么结果将是这样的:

在 selecting 文件后,它将变成:

如您所见,这会破坏提示符和命令本身。 在我看来,我需要做的是 zle reset-prompt 在调用 compadd 之前,但这只有在我将函数绑定到一个键时才有效,否则,我将收到以下错误:

只有在 ZLE 处于活动状态时才能调用小部件

我终于找到了解决该问题的方法。虽然我对该策略不满意,因为它不是自包含在小部件本身中的,但它确实有效。解决方案涉及在调用 fzf-completion 后捕获它并调用 zle reset-prompt.

为了注册陷阱,将以下代码片段添加到您的 .zshrc 文件中(参见 Zsh 菜单完成在 zle 重置提示后导致问题 ):

TMOUT=1
TRAPALRM() {
   if [[ "$WIDGET" =~ ^(complete-word|fzf-completion)$ ]]; then
      # limit the reset-prompt functionality to the `takenote` script
      if [[ "$LBUFFER" == "takenote "* ]]; then
         zle reset-prompt
      fi
   fi
}

_takenote 小部件:

#compdef takenote
local file=$( find -L "$HOME/notes/" -print 2> /dev/null | fzf-tmux +m )
compadd $file
return 0

p.s:我仍然喜欢将陷阱移到小部件中,并避免在初始化脚本中注册它(.zshrc)

当我尝试使用 bindkey 小部件以使用 vim 打开 fzf 选定文件时,我遇到了同样的错误。结果我必须在 function1 中打开文件,然后有一个 function2 调用 function1 然后 reset-prompt 以避免这个 widgets can only be called when ZLE is active 错误。就像你说的,真的令人沮丧,我花了将近一天的时间才弄明白!

示例代码:

## use rg to get file list
export FZF_DEFAULT_COMMAND='rg --files --hidden'

## file open (function1)
__my-fo() (
  setopt localoptions pipefail no_aliases 2> /dev/null
  local file=$(eval "${FZF_DEFAULT_COMMAND}" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS --preview 'bat --color=always --line-range :500 {}'" $(__fzfcmd) -m "$@" | while read item; do
    echo -n "${(q)item}"
  done)
  local ret=$?
  if [[ -n $file ]]; then
    $EDITOR $file
  fi
  return $ret
)

## define zsh widget(function2)
__my-fo-widget(){
  __my-fo
  local ret=$?
  zle reset-prompt
  return $ret
}

zle -N __my-fo-widget
bindkey ^p __my-fo-widget