Annuler l'achèvement, mais uniquement l'achèvement, en zsh

13

Lorsqu'une fonction d'achèvement prend beaucoup de temps, je peux l'interrompre en appuyant sur Ctrl+ C(touche d'interruption du terminal, envoie SIGINT) ou Ctrl+ G(lié à send-break). Je me retrouve alors avec le mot inachevé.

Cependant, s'il m'arrive d' appuyer sur Ctrl+ Cou Ctrl+ Gjuste au moment où la fonction d'achèvement se termine, mon appui sur une touche peut annuler la ligne de commande et me donner une nouvelle invite au lieu d'annuler l'achèvement.

Comment puis-je configurer zsh pour qu'une certaine touche annule une fin en cours mais ne fasse rien si aucune fonction de fin n'est active?

Gilles 'SO- arrête d'être méchant'
la source

Réponses:

5

Voici une solution qui configure un gestionnaire SIGINT qui fait Ctrl+ Cinterrompre uniquement lorsque l'achèvement est actif.

# A completer widget that sets a flag for the duration of
# the completion so the SIGINT handler knows whether completion
# is active. It would be better if we could check some internal
# zsh parameter to determine if completion is running, but as 
# far as I'm aware that isn't possible.
function interruptible-expand-or-complete {
    COMPLETION_ACTIVE=1

    # Bonus feature: automatically interrupt completion
    # after a three second timeout.
    # ( sleep 3; kill -INT $$ ) &!

    zle expand-or-complete

    COMPLETION_ACTIVE=0
}

# Bind our completer widget to tab.
zle -N interruptible-expand-or-complete
bindkey '^I' interruptible-expand-or-complete

# Interrupt only if completion is active.
function TRAPINT {
    if [[ $COMPLETION_ACTIVE == 1 ]]; then
        COMPLETION_ACTIVE=0
        zle -M "Completion canceled."            

        # Returning non-zero tells zsh to handle SIGINT,
        # which will interrupt the completion function. 
        return 1
    else
        # Returning zero tells zsh that we handled SIGINT;
        # don't interrupt whatever is currently running.
        return 0
    fi
}
Mat
la source
0

Je ne sais pas si c'est une solution acceptable ou non, mais l'envoi d'un SIGSTOP ( Ctrl+ S) semble avoir l'effet souhaité, avec l'avantage supplémentaire que vous pouvez redémarrer la saisie semi-automatique si vous envoyez un SIGSTART ( Ctrl+ Q) avant de taper rien d'autre. Cependant, je ne suis pas un expert en contrôle des tâches, ce qui peut laisser un encombrement supplémentaire lié au travail interrompu.

Aaron Okano
la source
1
Ctrl + S et Ctrl + Q sont des commandes de contrôle de flux. Ils n'affectent que la sortie vers le terminal, ce qui n'est pas pertinent ici. On pouvait s'y attendre, Ctrl + S n'a aucun effet pendant l'achèvement (zsh désactive de toute façon le réglage du terminal, il saisit la combinaison de touches). Appuyer sur Ctrl + Z (qui envoie SIGTOP) n'a aucun effet non plus.
Gilles 'SO- arrête d'être méchant'
Merci! Je n'étais pas tout à fait sûr de ce qui se passait en arrière-plan. Tout ce que j'ai vu, c'est que j'ai repris le contrôle du terminal.
Aaron Okano