Zsh menu completion causes problems after zle reset-prompt
Asked Answered
T

3

13

I have following code in my .zshrc:

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

After triggering menu completion all items from menu, except highlighted one disappear after TRAPALRM triggers and when i keep navigating in menu zsh segvaults after a short time

Is there any fix or workaround for this?

EDIT: zsh version is 5.0.2 on Linux Mint 17

EDIT: i observe same thing on zsh version 5.0.7 on Gentoo

Taxis answered 23/10, 2014 at 10:30 Comment(2)
What version of zsh are you using? I can confirm that the items with exeption of the selected one vanish but only if anything is selected (zsh 5.0.5 on Ubuntu 14.04 and zsh 5.0.7 on Arch, both amd64). But I do not get segmentation faults even if I keep pressing <kbd>Tab</kbd>. So these two things might not be that closely related.Terrazas
Running into this as well. Is there any way to refresh the screen without clearing completion items? Seems like a bug - why would completion items be cleared from view, but still be selectable?Lewin
B
13

I found this workaround, to basically prevent calling "reset-prompt" when in a menu selection :

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

Note that complete-word may be different for you; I found it with an echo $WIDGET in the TRAPALRM call.

Brittanybritte answered 26/5, 2015 at 10:39 Comment(4)
This is similar to my workaround for this, which was to make new widget for each completion widget, which turns off TRAPALRM, calls that completion widget and turns TRAPALRM on again, but this solution seems simpler and cleanerTaxis
It seems, though, this is producing a segfault on zsh 5.0.5 - while it works flawlessly with 5.0.7.Brittanybritte
Maann! You saved my day! Thank you! I was using fzf-completion, so in my case this condition worked: if ! [[ "$WIDGET" =~ ^(complete-word|fzf-completion)$ ]]; thenSnowclad
To extend the above to fzf's CTRL–R, CTRL–T and ALT–C, set this instead: TRAPALRM() { ! [[ "$WIDGET" =~ ^(complete-word|fzf-completion|fzf-.*-widget)$ ]] && zle reset-prompt }. Note that Zsh functions and widgets can be listed, e.g.: functions + | grep -i fzfHarmless
K
3

My solution for this issue is to check both $WIDGET and $_lastcomp[insert] values to know if menu-select is active at the moment more precisely.

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 }

The "expand-or-complete" might be "complete-word" or something, based on the key bind to your tab key. It can be checked by the bindkey "^I" command.

Kippie answered 23/3, 2017 at 16:45 Comment(1)
Any pointers to where is $_lastcomp[insert] documented, other than the source code?Okeechobee
L
0

A workaround that lets you have reset-prompt in all situations is to not use interrupts at all. I wanted ctrl-c to clear the command line ; in .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
}

You'll need to find out how stty calls your ALRM signal to adapt that to your use case.

Lipson answered 15/3, 2023 at 13:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.