Escape not idempotent in zsh's vi emulation?

Solution 1:

I get that as well. Hadn't noticed it before, since I generally use emacs bindings in my shell. It seems that with the default bindings, using the escape key in vicmd mode eats the next character. This seems like it may be a bug in handling of undefined keys.

I was able to work around this issue by defining a noop binding for the escape key in vicmd mode using:

noop () { }
zle -N noop
bindkey -M vicmd '\e' noop

Solution 2:

I don't have enough reputation here to reply to qqx's answer, so I'll just have to file a separate answer:

It's not a bug; what happens is the following: When you hit ESC the first time, you switch from vi insert mode to vi command mode (obviously). Then you hit ESC again in vi command mode. The problem is that, by default, ESC is not bound to anything in command mode, however, there are multi-key widgets starting with ESC which are bound — notably, the control sequences sent by the arrow keys.

Hence, if you hit ESC in vi command mode, ZLE sits there waiting for the second keystroke of the widget. That is why, if you hit 'i' (or any character), it gets silently consumed by ZLE.

The answer is to bind ESC to something — anything — in vi command mode, exactly as qqx stated in his answer.