15

When a completion function takes a long time, I can interrupt it by pressing Ctrl+C (terminal interrupt key, sends SIGINT) or Ctrl+G (bound to send-break). I am then left with the uncompleted word.

However, if I happen to hit Ctrl+C or Ctrl+G just as the completion function finishes, my key press may cancel the command line and give me a fresh prompt instead of cancelling the completion.

How can I set up zsh so that a certain key will cancel an ongoing completion but do nothing if no completion function is active?

asked Sep 17, 2013 at 23:43

2 Answers 2

5

Here's a solution that sets up a SIGINT handler that makes Ctrl+C only interrupt when completion is active.

# 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
}
answered Oct 2, 2013 at 6:39
0

I don't know if this is an acceptable solution or not, but sending a SIGSTOP (Ctrl+S) seems to have the desired effect, with the added benefit that you can start up the autocomplete again if you send a SIGSTART (Ctrl+Q) before typing anything else. I'm not an expert on job control though, so this may leave some additional clutter related to the stopped job.

answered Sep 25, 2013 at 17:09
2
  • 1
    Ctrl+S and Ctrl+Q are flow control commands. They only affect output to the terminal, which is irrelevant here. Predictably, Ctrl+S has no effect during completion (zsh disables the terminal setting anyway, it grabs the key combination). Pressing Ctrl+Z (which sends SIGTOP) has no effect either. Commented Sep 25, 2013 at 19:40
  • Thanks! I wasn't entirely sure what was going on in the background. All I saw was that I got control of the terminal back. Commented Sep 26, 2013 at 2:21

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.