Zsh菜单自动完成在执行zle reset-prompt后出现问题

13

我在我的.zshrc文件中有以下代码:

TMOUT=1
TRAPALRM() { zle reset-prompt }

在触发菜单完成后,除了突出显示的项目之外,菜单中的所有项目都会在TRAPALRM触发后消失,在菜单中导航一段时间后,zsh就会崩溃。

是否有任何修复或解决方法?

编辑:Linux Mint 17上的zsh版本为5.0.2

编辑:在Gentoo上的zsh版本5.0.7中我观察到相同的情况


你使用的是哪个版本的zsh?我可以确认,除了所选的项目外,其他项目都会消失,但仅当选择了任何内容时才会消失(在Ubuntu 14.04上使用zsh 5.0.5和在Arch上使用zsh 5.0.7,均为amd64)。但是,即使我不断按<kbd>Tab</kbd>键,也不会出现分段错误。因此,这两件事可能并不那么密切相关。 - Adaephon
1
我也遇到了这个问题。有没有办法在不清除完成项的情况下刷新屏幕?看起来像是一个错误 - 为什么完成项会从视图中清除,但仍然可选择? - Jim Greenleaf
3个回答

13

我发现了这个解决方法,基本上可以防止在菜单选择时调用“reset-prompt”:

TRAPALRM() {
    if [ "$WIDGET" != "complete-word" ]; then
        zle reset-prompt
    fi
}

请注意,complete-word 可能与您的不同;我是通过在 TRAPALRM 调用中使用 echo $WIDGET 找到它的。


这与我的解决方法类似,即为每个补全小部件创建一个新的小部件,关闭TRAPALRM,调用该补全小部件,然后再次打开TRAPALRM,但这个解决方案似乎更简单和清晰。 - Ryba
然而,在 zsh 5.0.5 上似乎出现了段错误,但在 5.0.7 上却可以完美运行。 - Drasill
2
哇!你救了我的一天!谢谢!我正在使用 fzf-completion,所以在我的情况下,这个条件是有效的:if ! [[ "$WIDGET" =~ ^(complete-word|fzf-completion)$ ]]; then - grundic
为了将上述内容扩展到_fzf_的CTRL-R、CTRL-T和ALT-C,可以设置如下:TRAPALRM() { ! [[ "$WIDGET" =~ ^(complete-word|fzf-completion|fzf-.*-widget)$ ]] && zle reset-prompt }。请注意,Zsh函数和小部件可以列出,例如:functions + | grep -i fzf - Faxopita

3

对于这个问题,我的解决方案是同时检查$WIDGET和$_lastcomp[insert]的值,以更精确地了解菜单选择是否处于活动状态。

autoload -U is-at-least
TMOUT=1
if is-at-least 5.1; then
    # avoid menuselect to be cleared by reset-prompt
    redraw_tmout() {
        [ "$WIDGET" = "expand-or-complete" ] && [[ "$_lastcomp[insert]" =~ "^automenu$|^menu:" ]] || zle reset-prompt
    }
else
    # evaluating $WIDGET in TMOUT may crash :(
    redraw_tmout() { zle reset-prompt }
fi
TRAPALRM() { redraw_tmout }

“expand-or-complete”可能是“complete-word”或其他内容,取决于您的Tab键绑定的按键。可以通过bindkey "^I"命令进行检查。


除了源代码之外,有没有关于$_lastcomp[insert]文档的指针? - Linus Arver

0
一个让你在所有情况下使用“reset-prompt”的解决方法是根本不使用中断。我想要ctrl-c来清除命令行,在.zshrc文件中:
function _clear-line {
    zle -K viins
    zle reset-prompt
    zle kill-whole-line
}
zle -N _clear-line
precmd() {
    # Bind ctrl-b to the interrupt signal.
    stty intr \^b
    bindkey '^C' _clear-line
    bindkey -M vicmd '^C' _clear-line
    # Optionally, react differently from inside menuselect :
    #bindkey -M menuselect '^C' undo
}
preexec() {
    # Restore the ctrl-c binding.
    stty intr \^c
}

您需要找出如何调用stty来适应您的用例中的ALRM信号。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接