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

Ryba
  • 681
  • 4
  • 13
  • 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 Tab. So these two things might not be that closely related. – Adaephon Oct 23 '14 at 11:15
  • 1
    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? – Jim Greenleaf Nov 28 '14 at 16:08

3 Answers3

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.

Drasill
  • 3,917
  • 29
  • 30
  • 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 cleaner – Ryba May 27 '15 at 12:43
  • It seems, though, this is producing a segfault on zsh 5.0.5 - while it works flawlessly with 5.0.7. – Drasill May 27 '15 at 12:57
  • 2
    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)$ ]]; then` – grundic May 03 '18 at 08:15
  • 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 fzf` – Faxopita Apr 27 '23 at 14:04
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.

NeoCat
  • 31
  • 2
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.

la Fleur
  • 426
  • 3
  • 11