6

I have zsh configured to use vi keybindings. I've noticed some unexpected behavior with "escape". In vim (I haven't tested vanilla vi) if I hit escape twice, I can hit 'i' once to return to insert mode. In zsh if I happen to hit escape twice, hitting 'i' won't return me to insert mode, I have to hit it twice. Another example of this comes up in navigation. If I hit escape once, I can use '^' and '$' as expected. But if I've accidentally hit escape twice (or more) they fail to work until I return to insert mode and escape again.

Do I somehow have zsh configured incorrectly, or is this just a known difference in zsh's vi emulation?

3

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
| improve this answer | |
  • Thanks! I had kind of expected that I could perhaps do something by binding escape in vicmd mode, but wasn't sure if there was something more going on here. I'm surprised other users haven't made an issue of it. Maybe I'm just too absent minded of a vi user, hitting escape all the time. – user1063042 Dec 8 '12 at 4:00
  • This has been plaguing me for days, thank you! – cchamberlain Jul 24 '15 at 2:51
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.

| improve this answer | |
0

This doesn't seem to be a problem with zsh 5.6.2.

Something to consider would be setting KEYTIMEOUT=1 in your ~/.zshrc.

KEYTIMEOUT

The time the shell waits, in hundredths of seconds, for another key to be pressed when reading bound multi-character sequences.

See the zsh PARAMETERS documentation

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.