Виджеты могут вызываться только при активной ZLE

Я занимаюсь этой проблемой уже почти месяц, и я расстроен, любая помощь будет принята с благодарностью.

Я пытаюсь написать виджет для моего takenote команда. Цель виджета состоит в том, чтобы кормить все файлы уценки в ~/notes папка в fzf чтобы пользователь мог выбрать один из них и начать его редактирование. После того, как пользователь вводит 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Если я удалю его, то результат будет следующим:

до выбора

И после выбора файла это превратится в:

После выбора файла

Который, как вы видите, повредит подсказку и саму команду. Мне кажется, что мне нужно сделать, это сделать zle reset-promptперед звонком compadd но это может работать только тогда, когда я связываю функцию с клавишей, в противном случае я получу следующую ошибку:

виджеты могут вызываться только при активной ZLE

3 ответа

Решение

Я наконец нашел решение этой проблемы. Хотя я не удовлетворен стратегией, поскольку она не содержится в самом виджете, но она работает. Решение включает в себя ловушку fzf-completion после того, как он вызывается и вызывает zle reset-prompt,

Для регистрации ловушки добавьте следующий фрагмент в свой .zshrc файл (см. завершение меню Zsh вызывает проблемы после zle reset-prompt):

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

ps: я все еще хотел бы переместить ловушку в виджете, и избежать регистрации в сценарии инициализации (.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

Через два дня мне наконец удалось найти подсказку, как этого добиться благодаря отличному проекту fzf-tab-completion:

https://github.com/lincheney/fzf-tab-completion/blob/c91959d81320935ae88c090fedde8dcf1ca70a6f/zsh/fzf-zsh-completion.sh#L120

Итак, на самом деле все, что вам нужно сделать, это:

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

И это, наконец, работает. Ваше здоровье!

Другие вопросы по тегам