17

I've set the escape-time option in ~/.tmux.conf, since it's present in many Tmux configuration files.

However, I don't really see any effect after setting this option. In particular, if I set the escape-time to 10000 (10 seconds), everything still "works".

This is my current setting:

# ESC delay after prefix (ms)
set -sg escape-time 500

What exactly is meant by an "ESC delay", and when is it used?

Shuzheng
  • 4,411

1 Answers1

34

A terminal just sends a stream of characters to the host. For keys in the main alphanumeric section of the keyboard (in ISO 9995 terminology) this is fine and dandy, as they are usually sending ordinary printable characters or C0 control characters.

Things are different when it comes to cursor keys, function keys, editing keys and suchlike in the other sections of the keyboard, and also when it comes to key chords even in the main section that have no obvious control character associations, such as ⇧ Shift+⇥ Tab or the use of ⎇ Alt as an accelerator modifier.

ECMA-35 and ECMA-48 define a system of escape sequences, introduced by the ESC character (U+001B), and control sequences, introduced by the CSI character (U+009B, the abbreviation standing for Control Sequence Introducer). Terminals mainly use the latter; the ECMA-48 CUB (CUrsor Backwards) control sequence being sent for the key, for example.

This, too, would be fine and dandy, were it not that terminals (including emulated ones) still live in the 1970s, before the time when the world largely went 8-bit clean.

Terminals act as if the world still widely used 7-bit serial encodings with odd/even/no parity, something that the PC revolution, BBSes, and the likes of FidoNet et al. helped to dig the grave of in the 1980s, in favour of 8N1. So they use the 7-bit alias form for transmitting the C1 control characters such as CSI.

This form is for 7-bit transports incapable of transmitting 8-bit characters cleanly. It means that they actually transmit C1 control characters as the ESC character followed by the C1 character code minus 64 (ESC Fe for those reading ECMA-35). This in turn means that all of the control sequences that would nominally begin with a C1 control character that did not correspond to a key on the keyboard now instead begin with a C0 control character for which there is a key on the keyboard.

Those pesky users, you see, have an Esc key that sends the ESC character on its own, not as part of an escape sequence. They like to wield it in TUI programs to mean "change mode" or "cancel operation" or other things. They complained a bit when Apple stopped it from being a real physical key on Apple keyboards, some years ago.

So what is an application that is reading terminal input character-by-character, as do programs like vi and tmux (on its realized-upon outer terminal), to do? How does it distinguish a user with an ESC key, and happy to wield it, from a terminal sending control sequences over a 7-bit transport?

It sets a timeout. If the character following the ESC arrives quickly enough, then presumably this is a terminal sending an ECMA-48 control sequence, which it will be doing at machine speed. If the character following the ESC arrives after a minimum delay, then presumably this is a human typing that Esc key before typing something else.

This is what the escape-time setting is all about. tmux lets you configure that timeout (as do VIM and NeoVIM), which other programs often hardwire. Your setting it to 10 seconds is merely telling it that machines can be really slow, which is generally pointless. The more usual modification is to decrease it, because you are a human that can type that fast.

The major problem with this idea, nowadays, is that introducing SSH and network transmission delays into the proceedings introduces the possibility that human-generated input really can arrive that fast, because it has bunched up on the "local" end waiting for an acknowledgement from the remote host to move a transmission window along. And it also introduces the possibility of the network breaking up machine-generated control sequences, creating delays after the ESC character that make the program running on the remote host incorrectly guess that it is a human typing.

Perhaps the world will cotton on that TCP is also 8-bit clean (yes, officially; since 1981), as serial comms has been for some decades, and that terminals really can send a real CSI character instead of its 7-bit alias. Then there will be less ambiguity (setting aside accelerators) between control sequences generated by the terminal and single presses of the Esc key by those pesky users, and programs won't need to measure the time in between receiving characters to know whether they are dealing with a machine or a human.

After all, the real terminals cottoned on to the fact that the world went 8-bit clean in the 1980s … in the early 1980s. The DEC VT220, released in 1983, has a S8C1T control sequence that tells the terminal to stop using the 7-bit aliases and start sending the proper U+009B character. By the time of the VT320, in 1987, this was a set-up feature stored in non-volatile RAM in the terminal that could be on by default. The same set-up that factory defaulted to 8N1.

Further reading

JdeBP
  • 68,745
  • Thank you for an excellent answer. What would you recommend as the value for escape-time? After having read your answer, I have adjusted it to 50, since I guess that my system should be able to communicate the characters after ESCs at a rate faster than 50 ms. – Shuzheng Sep 06 '20 at 18:13
  • Also, I've set bind Escape copy-mode and noticed that tmux first interprets my ESC as input after escape-time ms have passed. According to your answer, shouldn't tmux instead wait for me to type another character after the ESC? – Shuzheng Sep 06 '20 at 18:16
  • @Shuzheng ESC + character is an escape sequence if it's fast enough. Waiting long enough after the ESC turns it into an input on its own – Fox Sep 06 '20 at 18:28
  • Many modern terminals do depend on channels being 8-bit clean for UTF-8. But apart from this problem with Escape, 8-bit C1 doesn't have any real advantages nowadays and next to nobody uses it, so I don't see it changing anytime soon. A more practical solution would be for other terminals to adopt mintty's "alternative Escape" option, but sadly few have done so yet. – Nicholas Marriott Sep 08 '20 at 10:53
  • @Fox - so by "then presumably this is a human typing that Esc key before typing something else.", it's meant that a stand-alone Esc is pressed, if escape-time passes without another character being read, otherwise, it's an escape sequence? – Shuzheng Sep 12 '20 at 09:47
  • 1
    @Shuzheng yes that is accurate – Fox Sep 12 '20 at 15:24
  • We can’t really use the C1 control characters any more because the channel isn’t 8–bit clean once you start using UTF–8, and UTF–8 is more important. – db48x Feb 12 '22 at 16:07