-
Notifications
You must be signed in to change notification settings - Fork 786
Key names and escape sequences
In late summer and autumn 2023 we conducted a reasonably comprehensive review of terminal emulators and the escape sequences they produce for various keys; this was primarily done with a tool that helped record recognised triggered keys as well as unknown sequences (using a small hook inside Textual to get the unknown sequences).
The most common issue found amongst the terminals was modified F3, which was subsequently handled. Aide from that, no other clear issue was seen. Things that did stand out though was that:
- Pretty much every terminal tested had some keys that had sequences currently unknown to Textual.
- Few, if any, had any significant overlap between terminals.
- Some forms of modified function key were off limits on macOS, mainly due to those key combinations having default meanings there.
The following is the notes recorded while looking at each terminal/environment combination.
Ctrl+number keys is just the number.
Higher Ctrl+Shift+Fn keys work okay, lower ones don't. macOS getting in the way?
Expected keys (14)
Just 0
Just 1
Just 2
Just 3
Just 4
Just 5
Just 6
Just 7
Just 8
Just 9
Backspace
Tab
Enter
Doesn't do anything
Ctrl and home/end just result in home/end.
Shift home/end/pageup/pagedown seem to navigate the terminal scrollback history, even in a fullscreen application.
Shift up and down just result in up and down.
Shift f1 through f4 just cause a terminal bell, with nothing else appearing to turn up in the terminal.
No ctrl and function key combination does anything; most just terminal bell.
No ctrl and number combination does anything; they all seem to just terminal bell.
Overall, keys that aren't handled seem to sound the terminal bell.
Expected keys (18)
Just does down
Just end
Backspace
Just home
Tab
Enter
Just does page up.
Just does page down.
Does ctrl+@ AKA NUL
Seems to scroll the terminal history buffer
Seems to scrol the terminal history buffer
Just does up.
Just down
Seems to scroll the terminal history buffer
Seems to scroll the terminal history buffer
Seems to scroll the terminal history buffer
Seems to scroll the terminal history buffer.
Just up
Control and number keys just seem to do the number itself.
Shift up and down don't seem to do anything.
F3 doesn't work.
Expected keys (10)
Backspace
Tab
Enter
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Unknown keys (3)
Shift f2
Ignore this, just an accidental press of shift f2 followed by some tabs.
Shift f4
F11 and Ctrl+F11 toggle fullscreen mode.
Shift pageup/down seem to do a version of a history buffer scrollback; but behaves weirdly in a Textual app.
Ctrl and number keys do nothing.
Ctrl+, opens a text editor with the configuration.
Ctrl+Shift+F5 is a full reload of the terminal; killing your application (and whole session).
Unknown keys (7)
Shift f3
Ctrl+f3
Pressed ctrl+home
Apparently fallout from pressing ctrl+home and trying to get control back.
Also after pressing ctrl+home, then escape.
Pressing ctrl+end seems to result in a B (uppercase) followed by this.
Ctrl+shift+f3, I seem to recall.
Few core changes made to how iTerm handles keys.
Control and section sign results in a '0'.
Control and Fn do nothing (actually they seem to do things in my desktop, so an OS thing?).
Expected keys (5)
Backspace
Tab
Enter
Scrolls the terminal itself
Scrolls the terminal itself
Control and number keys don't produce ctrl+0 through ctrl+9, generally producing other things.
Control, shift and number keys don't produce anything at all.
Out of the box Ctrl+Shift+Fn seems to be reserved by kitty for some default bindings.
Lots of ctrl+cmd+ combinations seem to generate sequences, ctrl+cmd+, is used by kitty out of the box.
Expected keys (26)
Just 0
Just 1
Ctrl+@
Produces escape
Ctrl+backslash
Ctrl+right_square_bracket
ctrl+circumflex_accent
ctrl+underscore
backspace
Just 9
This registers as backspace
.
This registers a tab.
This registers as enter
.
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Seems to wipe the terminal, for some reason. Moving around again makes it draw back in.
Pressing insert does nothing.
This doesn't register anything.
Unknown keys (30)
This was shift F3
This was ctrl+F3
I missed where this came from
This is ctrl+§
Not sure how I got this one; It was while I was annotating another key so I think it may have happened while inside the dialog.
Actually, it can't have been while I was in the dialog, beause it's only when we're in the key recording widget that this is a thing?
On the third hand... the unknown sequence capture code is in place all the time. Perhaps I should remove it when not in the relevant widget?
Ctrl+shift+f3
Ctrl+cmd+del
ctrl+cmd+home
ctrl+cmd+end
ctrl+cmd+pgup
ctrl+cmd+pgdn
ctrl+cmd+1
ctrl+cmd+2
ctrl+cmd+3
ctrl+cmd+4
ctrl+cmd+5
ctrl+cmd+6
ctrl+cmd+7
ctrl+cmd+8
ctrl+cmd+9
ctrl+cmd+0
ctrl+cmd+-
ctrl+cmd++
ctrl+cmd+[
ctrl+cmd+]
ctrl+cmd+\
ctrl+cmd+'
ctrl+cmd+;
ctrl+cmd+/
ctrl+cmd+.
Triggered keys (5)
This was produced by ctrl+4.
Produced by ctrl+7.
Produced by ctrl+6.
This doesn't work; no key press is registered.
Pressing ctrl+f8 doesn't register a key.
Anything to do with function keys seems to produce unicode characters rather than escape seqeunces.
Unexpected keys (16)
Ctrl+home
Ctrl+end
Ctrl+pgup
Ctrl+pgdn
f1
f2
f3
f4
f5
f6
f7
f8
f9
f10
f11
f12
Ctrl+fn keys don't appear to do anything.
Ctrl+number emits just the number.
Expected keys (12)
Emits shift+ instead
Emits shift+ instead
Emits shift+ instead
Backspace
Emits shift+ instead.
Tab
Emits shift+ instead.
Enter
Emits shift+ instead
Emits shift+ instead
Emits shift+ instead
Emits shift+ instead
Unknown keys (3)
Shift+f3
But I need to update Textual and this should then work.
Ignore
Shift+insert
Triggered keys (10)
This was actually ctrl+insert
Ctrl+delete too, it seems
ctrl+home too
ctrl+end too
ctrl+pageup too
ctrl+pagedn too
ctrl+left too
ctrl+right too
ctrl+up too
ctrl+down too
Ctrl Fn keys seem to do nothing.
Pressing Ctrl+Shift together seems to pop up some sort of tab description.
Expected keys (5)
Backspace
Tab
Enter
Does nothing
Does nothing
Unknown keys (2)
Shift f3
Not sure what I pressed to kick this off, but then I was tabbing a few times afterwards.
Triggered keys (2)
Invoked by ctrl+5 too.
Actually pressed ctrl+4
Running under XQuartz.
F1 pulls up the help for the terminal (in a web browser). F11 toggles full screeen. Shift+F10 pulls up a context menu (perhpas an XQuartz thing?) Ctrl+PgUp/Dn don't seem to do anything. Many Ctrl+Shift+ keys are reserved for use by the emulator itself (c+s+Q quits, for example)
Expected keys (5)
Backspace
Tab
Enter
Loads help in the web browser
Toggles full screen
Ctrl+Fn keys don't seem to work at all.
Shift pgup/pgdn don't work.
Ctrl pgup/pgdn change tabs (in Chrome anyway, no special configuration).
Ctrl and number keys don't result in those expected names; but some give other keys.
Ctrl shift and pgdn/pgup does nothing.
Expected keys (9)
Backspace
Tab
Enter
Changes tabs in the browser
Changes tabs in the browser
Does nothing
Does nothing
Doesn't work
Doesn't work
Triggered keys (4)
Caused by opt-backspace
Ctrl+5
Ctrl+6
Ctrl+shift+2
Shift+pgup/dn seem to scroll the scrollback buffer.
Ctrl+shift puts the terminal into "Keycap picture insert mode", which then lets you type in all sorts of other characters! See things like upwards_white_arrow
, etc.
Unknown keys (35)
Shift-F11
Shift-F12
Ctrl+F1
Ctrl+F2
Ctrl+F3
Ctrl+F4
Ctrl+F5
Ctrl+F6
Ctrl+F7
Ctrl+F8
Ctrl+F9
Ctrl+F10
Ctrl+F11
Ctrl+F12
Shift+delete
Shift+home
Shift+end
Ctrl+del
Ctrl+home
Ctrl+end
Ctrl+pgup
Ctrl+pgdn
Shift+minus on the numeric keypad
Shift+plus on the numeric keypad
Shift+home/7 on the numeric keypad
Shift+8 on the numeric keyboard
Shift+/ on the numeric keypad.
Shift+* on the numeric keypad
Shift+up
Shift+down
Shift+left
Shift+right
Ctrl+up
Ctrl+down
Shift+5 on the numeric keypad
Triggered keys (4)
Ctrl+2
Ctrl+4
Ctrl+6
Ctrl+7
Unknown keys (12)
Shift delete
Shift home
Shift end
Shift left
Shift right
ctrl del
Ctrl home
Ctrl end
Ctrl pgup
Ctrl pgdn
Shift f11
Shift f12
Ctrl+Fn do things on my desktop, so likely a macOS default.
Expected keys (7)
Results in backspace
Tab
Results in enter
Just produces escape
Does not work
Does not work
Does not work
Unknown keys (16)
Shift f3
Opt+secton sign
Opt+1
Opt+2
Ignore, just noise from testing
Ignore, just noise from testing
Opt+3
Opt+4
Opt+5
Opt+6
Opt+7
Opt+8
Opt+9
Opt+0
Opt+minus
Opt+=
F11 toggles full screen (at least without any config changes).
Only some Ctrl+Fn keys work. It's not clear what the pattern is; perhaps used by the terminal?
Some keys work fine but generate an unexpected ctrl+@ before them; this is a known issue.
Ctrl+Shift+number seems to be used for opening ip fresh tabs; perhaps hot-keyed shells?
Expected keys (12)
Backspace
Tab
Enter
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Does nothing (detectable). Presumably this is paste?
This seems to be used by the terminal to toggle fullscreen mode.
Triggered keys (6)
This was the section sign, but I imagine this is a Windows vs Mac keyboard issue.
Fired by ctrl+4
Fired by ctrl+3 too.
Fired by ctrl+5
Fired by ctrl+6
Fired by ctrl+7
shift and pgup/pgdn do nothing. ctrl and shift and pgup/pgdn do nothing.
Ctrl+Fn don't seem to do anything.
Expected keys (17)
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Does nothing
Backspace
Tab
Enter
Does nothing
Does nothing
Does nothing
Does nothing
Unknown keys (4)
After pressing shift+delete
Ctrl+F3 (fixed in later Textual).
ctrl+shift+insert
Ctrl+insert
The following is a breakdown of sequences encountered, which were unknown to Textual. Some of these may go on to be handled following this writeup. The main guidance we'll follow here is that a new binding name that might not be common to all terminals should be avoided (because it may encourage developers to bind keys that aren't very portable, thus resulting in a degraded user experience); on the other hand, if an escape sequence is encountered for a particular terminal that maps to a very common binding, unless we can find a good reason to not do so (so checking for any sort of sequence clash would be a good idea here), we should add support for that sequence.
Sequence | Notes |
---|---|
\x1bd |
Pressed ctrl-home (Hyper (3.4.1)-Windows) |
\x1bw |
Also after pressing ctrl-home, then escape. (Hyper (3.4.1)-Windows) |
\x1b[28;2~ |
After pressing shift-delete (XTerm(378)-Darwin) |
\x1b[28;6~ |
ctrl-shift-insert (XTerm(378)-Darwin) |
\x1b[28;5~ |
ctrl-insert (XTerm(378)-Darwin) |
\x1b[23$ |
shift-f11 (urxvt-Linux) |
shift-F11 (urxvt-Darwin) | |
\x1b[24$ |
shift-F12 (urxvt-Darwin) |
shift-f12 (urxvt-Linux) | |
\x1b[11^ |
ctrl-F1 (urxvt-Darwin) |
\x1b[12^ |
ctrl-F2 (urxvt-Darwin) |
\x1b[14^ |
ctrl-F4 (urxvt-Darwin) |
\x1b[15^ |
ctrl-F5 (urxvt-Darwin) |
\x1b[17^ |
ctrl-F6 (urxvt-Darwin) |
\x1b[18^ |
ctrl-F7 (urxvt-Darwin) |
\x1b[19^ |
ctrl-F8 (urxvt-Darwin) |
\x1b[20^ |
ctrl-F9 (urxvt-Darwin) |
\x1b[21^ |
ctrl-F10 (urxvt-Darwin) |
\x1b[23^ |
ctrl-F11 (urxvt-Darwin) |
\x1b[24^ |
ctrl-F12 (urxvt-Darwin) |
\x1b[3$ |
shift-delete (urxvt-Darwin) |
shift-delete (urxvt-Linux) | |
\x1b[7$ |
shift-home (urxvt-Darwin) |
shift-home (urxvt-Linux) | |
\x1b[8$ |
shift-end (urxvt-Linux) |
shift-end (urxvt-Darwin) | |
\x1b[3^ |
ctrl-del (urxvt-Linux) |
ctrl-del (urxvt-Darwin) | |
\x1b[7^ |
ctrl-home (urxvt-Linux) |
ctrl-home (urxvt-Darwin) | |
\x1b[8^ |
ctrl-end (urxvt-Darwin) |
ctrl-end (urxvt-Linux) | |
\x1b[5^ |
ctrl-pgup (urxvt-Linux) |
ctrl-pgup (urxvt-Darwin) | |
\x1b[6^ |
ctrl-pgdn (urxvt-Darwin) |
ctrl-pgdn (urxvt-Linux) | |
\x1bOm |
shift-minus on the numeric keypad (urxvt-Darwin) |
\x1bOk |
shift-plus on the numeric keypad (urxvt-Darwin) |
\x1bOw |
shift-home/7 on the numeric keypad (urxvt-Darwin) |
\x1bOx |
shift-8 on the numeric keyboard (urxvt-Darwin) |
\x1bOo |
shift-/ on the numeric keypad. (urxvt-Darwin) |
\x1bOj |
shift-* on the numeric keypad (urxvt-Darwin) |
\x1b[a |
shift-up (urxvt-Darwin) |
\x1b[b |
shift-down (urxvt-Darwin) |
\x1b[d |
shift-left (urxvt-Darwin) |
shift-left (urxvt-Linux) | |
\x1b[c |
shift-right (urxvt-Linux) |
shift-right (urxvt-Darwin) | |
\x1bOa |
ctrl-up (urxvt-Darwin) |
\x1bOb |
ctrl-down (urxvt-Darwin) |
\x1bOu |
shift-5 on the numeric keypad (urxvt-Darwin) |
\x1b§ |
Opt+secton sign (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b1 |
Opt+1 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b2 |
Opt+2 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b3 |
Opt+3 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b4 |
Opt+4 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b5 |
Opt+5 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b6 |
Opt+6 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b7 |
Opt+7 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b8 |
Opt+8 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b9 |
Opt+9 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b0 |
Opt+0 (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b- |
Opt+minus (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b= |
Opt+= (WezTerm (20230712-072601-f4abf8fd)-Darwin) |
\x1b[1;9P11 |
I missed where this came from (Kitty-Darwin) |
\x1b[167;5u |
This is ctrl-§ (Kitty-Darwin) |
\x1b[97;9u |
Not sure how I got this one; It was while I was annotating another key so I think it may have happened while inside the dialog. Actually, it can't have been while I was in the dialog, beause it's only when we're in the key recording widget that this is a thing? On the third hand... the unknown sequence capture code is in place all the time. Perhaps I should remove it when not in the relevant widget? (Kitty-Darwin) |
\x1b[3;13~ |
ctrl-cmd-del (Kitty-Darwin) |
\x1b[1;13H |
ctrl-cmd-home (Kitty-Darwin) |
\x1b[1;13F |
ctrl-cmd-end (Kitty-Darwin) |
\x1b[5;13~ |
ctrl-cmd-pgup (Kitty-Darwin) |
\x1b[6;13~ |
ctrl-cmd-pgdn (Kitty-Darwin) |
\x1b[49;13u |
ctrl-cmd-1 (Kitty-Darwin) |
\x1b[50;13u |
ctrl-cmd-2 (Kitty-Darwin) |
\x1b[51;13u |
ctrl-cmd-3 (Kitty-Darwin) |
\x1b[52;13u |
ctrl-cmd-4 (Kitty-Darwin) |
\x1b[53;13u |
ctrl-cmd-5 (Kitty-Darwin) |
\x1b[54;13u |
ctrl-cmd-6 (Kitty-Darwin) |
\x1b[55;13u |
ctrl-cmd-7 (Kitty-Darwin) |
\x1b[56;13u |
ctrl-cmd-8 (Kitty-Darwin) |
\x1b[57;13u |
ctrl-cmd-9 (Kitty-Darwin) |
\x1b[48;13u |
ctrl-cmd-0 (Kitty-Darwin) |
\x1b[45;13u |
ctrl-cmd-- (Kitty-Darwin) |
\x1b[61;13u |
ctrl-cmd-+ (Kitty-Darwin) |
\x1b[91;13u |
ctrl-cmd-[ (Kitty-Darwin) |
\x1b[93;13u |
ctrl-cmd-] (Kitty-Darwin) |
\x1b[92;13u |
ctrl-cmd-\ (Kitty-Darwin) |
\x1b[39;13u |
ctrl-cmd-' (Kitty-Darwin) |
\x1b[59;13u |
ctrl-cmd-; (Kitty-Darwin) |
\x1b[47;13u |
ctrl-cmd-/ (Kitty-Darwin) |
\x1b[46;13u |
ctrl-cmd-. (Kitty-Darwin) |
\x1b[2;2~ |
shift-insert (rio (0.0.26)-Darwin) |
\x1bO2P |
shift-f2 (contour (0.3.12.262)-Darwin) |
\x1bO2S |
shift-f4 (contour (0.3.12.262)-Darwin) |