9

In bash, I press ctrl+v to start verbatim insert. In the verbatim mode, I press the Esc key and bash shows ^[. I redirect it to file esc.

Also in the verbatim mode, I press ctrl key with [ key, and bash shows ^[. I redirect it to file ctrl.

Next, I compare the two files, and they are the same!

$ echo '^[' > esc
$ echo '^[' > ctrl
$ diff esc ctrl
$

Why do Ctrl+[ and Esc produce the same content?

Is ^[ here the C0 and C1 control codes? If so, the wiki article says ^[ is Escape, so why is ctrl+[ also Escape?

The root problem is that I want to check and create a key binding.

(zsh)$ bindkey -L 
...
bindkey "^['" quote-line
...

So do I need to type ESC+' or ctrl+[+'?

terdon
  • 242,166
Gqqnbig
  • 239

3 Answers3

19

This looks to follow the same logic as Ctrl-A, or ^A being character code 1, and ^@ being used to represent the NUL byte. Here, the ^ is a common way of representing Ctrl with another key.

Namely, entering Ctrl-foo gives the character code of foo with bit 6 cleared, reducing the character code by 64. So, A is character code 65, and ^A is character code 1; @ is 64, and ^@ is 0, NUL; and also [ is 91, and ^[ is 27, ESC. It's just that for ESC you also have a separate key, but you do have the enter and tab keys too, which also produce control characters, so it's not that out of the ordinary.

Of course, how Ctrl-something works on modern systems probably depends on other things too, like how your keymaps and key bindings are set up. Also don't ask me how that works for character codes < 64, e.g. ^1. With the terminal I tried that on, Ctrl-space gave the NUL byte.

ilkkachu
  • 138,973
  • 3
    Isn't the key actually carriage return but gets translated to linefeed (unless in raw mode)? – Oskar Skog Oct 17 '22 at 07:46
  • @OskarSkog, nngh. I'm not sure, and anyway I think there's more layers there, starting with the keyboard sending scan codes that are distinct from any characters (or whatever it is over USB). Mostly I just meant that the application gets some control code when you hit Enter, never mind the exact details. – ilkkachu Oct 17 '22 at 09:18
  • backspace is Ctrl-H and you can (usually) press Ctrl-H to delete the last character you typed – user253751 Oct 17 '22 at 13:50
  • Ctl-Space = NUL is an old VT100 feature (it's easier to type than Ctl-@) that terminal emulators copied. – Barmar Oct 17 '22 at 14:24
  • @Barmar, ah ok, thanks! I hadn't encountered that one before. – ilkkachu Oct 17 '22 at 16:09
  • 1
    @OskarSkog: You are right. When you press Enter, the terminal emulator sends a CR character to the master pseudo-terminal. The terminal driver, then, translates that to LF, if it is set to canonical mode. You can see for yourself by typing the command od -a, then Ctrl-V Enter Enter Ctrl-D: you will see a “cr” (the verbatim Enter) followed by a “nl” (the translated Enter). – Edgar Bonet Oct 17 '22 at 21:20
  • 1
    @user253751: On Linux, the backspace key sends Ctrl-? (ASCII DEL), unless using an exotic terminal. Other Unices may prefer Ctrl-H. The “erase” item in the output of stty -a tells you what your terminal driver expects. Note that bash (and probably every program using libreadline) does not rely on the terminal driver (it sets it to raw mode), and accepts both Ctrl-? and Ctrl-H irrespective of the setting of the “erase” character. – Edgar Bonet Oct 17 '22 at 21:20
4

When using a text terminal with text terminal applications (like bash), you can't distinguish between special keys like Esc, Tab, Enter, and Backspace and their respective control characters ([ I M/J H/?). Similarly, you can't distinguish between the numbers on the number row and the numeric keypad. Some other keys (arrows, function keys, page up/down, etc.) produce multiple character sequences.

However, in a graphical environment (X11, wayland), keys produce events associated with the key that are separate from (but linked to) the character mapping, independent of it being a single or multiple character mapping. A graphical application can distinguish between most of these keys if it chooses to do so. (In some cases, keys may still have indistinguishable mappings, but this is rare, and depends on how keys are mapped.)

Basically, the graphical terminal application chooses to not distinguish these keys and key sequences, and through the text pty, there is not a way for it to communicate the difference to the underlying text application anyway.

For example, The Backspace key can traditionally be mapped to either Ctrl-H or to Ctrl-?. In the graphical terminal, there is a setting to choose which one it is mapped to. So the graphical terminal application can detect the difference and change the mapping, but the text application running in the terminal can't.

user10489
  • 6,740
4

TL;DR: history.

"Why" goes back to design decisions taken when ASCII was designed in the decade leading up to its standardization as ISO 646 in 1967.

Back then most terminals were the hard-copy printing kind, and their keyboards didn't typically have an ESC key at all. If someone wanted to send the ASCII ESC code 27, they did so by typing ctrl-[; though there would be little point in doing so.

When these new fangled "glass teletype" terminals became popular in the 1970'sr, they made more extensive use of code 27, and so most (but not all) had an ESC key.

It's important to emphasise that up to this point, the only use for ESC was to generate ASCII code 27, which terminals understood as "change to a mode where the next byte will be taken as a command rather than as something to display".

Move forward another ten years, to various kinds of Windowing systems, and an entirely new use for the ESC key emerged: the sense of cancel the current operation.

However this does not apply when you use a terminal, even within a windowing environment. Rather, you're still getting the same behaviour as dictated by ASCII in 1967.

As for why the ctrl key does what it does, the other answer by @user10489 explains that.

  • The Model 33 Teletype was pretty ubiquitous in 1967 and it had an ESC key. I used them a lot (you need strong fingers) but I don't remember what the ESC key was used for. – Michael Kay Oct 17 '22 at 08:15
  • @user32929 I also can't remember any ASCII terminals without an ESC key. As for what ESC was used for, it was generally application- and OS-dependent. – Barmar Oct 17 '22 at 14:27
  • @user32929 Ah, the 33 ASR I saw (in my uncle's office) had a key marked "alt mode", which I didn't realise was actually an ESC key. Thankyou for the update. – Martin Kealey Oct 21 '22 at 13:25