24

For switching back from Insert mode I'm used to <Esc>. Now I'm looking to retrain myself to <C-[> instead of <Esc>. For that i need to disable <Esc> to help with the retraining.

The problems is

:inoremap <Esc> <Nop>

also disables <C-[>. For vim they seem to be the same thing.

Is there any way to disable one without the other?

  • 13
    It depends in what environment you're working. Most text terminals send the same information to the application when you press Esc or C-[, so you're out of luck, but you may be able to do something with a GUI version of Vim or by reconfiguring your terminal. – Gilles 'SO- stop being evil' May 11 '15 at 20:35
  • Right! Not a vim issue. I'll find a workaround with the keyboard mappings. Thanks – mxlian May 11 '15 at 20:49
  • 3
    @Gilles why don't you put that in an answer? It's better for Googlers and our site stats. – Robbie Wxyz Jun 11 '15 at 19:01
  • 2
    @SuperScript I've researched this a bit more and posted an answer. – Gilles 'SO- stop being evil' Jun 12 '15 at 0:08
35

First, a bit of history. In the old days, when you typed some text on a terminal, each key sent a character to the application. As the machines that the terminal was connected to became more powerful, terminals standardized on a control key, which would send some special characters, which were not printed but had some kind of function. The eventually triumphant character set was ASCII, with 128 characters out of which 32 are control characters. Pressing Ctrl together with a letter or other symbol written 10xxxxx₂ (binary notation) sends the control character whose code is 00xxxxx₂, e.g. Ctrl+[ sends character number 27₁₀ = 0011011₂ because [ is 91₁₀ = 1011011₂.

A few function keys on terminals sent control characters:

  • Backspace = Ctrl-H (BS = BackSpace)¹
  • Tab = Ctrl-I (HT = Horizontal Tab)
  • Linefeed = Ctrl-J (LF = Line Feed) (few terminals ever had this key)
  • Return or Enter = Ctrl-M (CR = Carriage Return)
  • Escape = Ctrl-[ (ESC = Escape)

When terminals had more function keys, there weren't enough control characters to represent them all. So they sent sequences of character, and the universal convention is that these character sequences begin with the escape character, Ctrl-[.

As time went by, hardware terminals became rarer and rarer; nowadays there are many levels of translation between the keyboard and the application. The limitation in numbers of available characters and the hard-coded correspondences between certain key combinations and certain control characters is no longer relevant. However, applications have remained compatible with existing terminals, and terminals have remained compatible with existing applications, which made it difficult to change anything.

So even today, on Unix-like systems, applications running in a terminal emulator receive the character Ctrl-I when the user presses the Tab key, the character Ctrl-[ when the user presses Esc, etc. If Vim is running in a Unix terminal, it can't distinguish between <Esc> and <Ctrl-[> because the terminal sends the same information.

Vim running in other environments doesn't have this limitation, so in principle it would be possible for them to send different information. Given that Vim uses the Ctrl-[ character to represent <Esc> in a lot of places, changing that would be impractical; instead Ctrl+[ could be made to send a different input event.

I'm not aware of any version of Vim itself that does differentiate between Esc and Ctrl+[ (but it isn't like I'd ever used any). Gvim, for one, seems to emulate a garden variety terminal.

Ironically, your best bet may be Vim running in a terminal emulator. Some terminal emulators allow you to customize escape sequences sent by keys and keychords. So you might arrange for Ctrl+[ to send not the ␛ (Ctrl-[) character, but some escape sequence. Xterm, the “reference” terminal emulator for Unix-like systems, supports two such schemes. For example:

  • Esc sends and Tab sends , in all configurations.
  • With ?.VT100.modifyOtherKeys: 0 (default) or ?.VT100.modifyOtherKeys: 1, Ctrl+[ sends and Ctrl+I sends . ?.VT100.modifyOtherKeys: 1 only affects meta combinations and control combinations that lack an ASCII character.
  • With ?.VT100.modifyOtherKeys: 2 and ?.VT100.formatOtherKeys: 0 (default), Ctrl+[ sends ␛[27;5;91~ and Ctrl+I sends ␛[27;5;105~.
  • With ?.VT100.modifyOtherKeys: 2 and ?.VT100.formatOtherKeys: 1, Ctrl+[ sends ␛[91;5u and Ctrl+I sends ␛[105;5u.

Support can be turned on by setting the modifyOtherKeys resource when starting xterm (and formatOtherKeys to select between the two schemes), or it can be turned on and off dynamically by the application.

Vim has no built-in support that I know of. You can write your own bindings for these escape sequences. It may be possible to get Vim to automatically set the terminal in the modifyOtherKeys mode by feeding it a modified terminal definition, but doing so is beyond the scope of this answer.

Neovim has built-in support for one of the variants. As far as I understand, it doesn't switch support on if the terminal supports it, that's up to the user to do.

¹ Increasingly and most commonly nowadays, Backspace sends character 127.

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.