I recently had the pleasure of trying to figure out a friend’s terminal woes. His function keys weren’t behaving properly. It turns out that his terminal was sending escape codes that differed from the terminfo definition his terminal was using. I set out to find what the correct solution was. These are my results. (Note that I use Debian GNU/Linux. Some of this may be Debian-specific.)
Most terminal emulators these days emulate some superset of a DEC
VT100. (Not all of them emulate a VT100 exactly, though. cf.
vttest.) The VT100 didn’t have function keys in the sense that it
didn’t have keys labeled F1, F2, F3, etc. It did, however, have four keys
over the numeric keypad labeled PF1 through PF4. These keys are generally
regarded as analogous to F1 through F4 on a modern keyboard. They
generated escape codes ^[OP
through ^[OS
. The appropriate $TERM type
for a VT100 is vt100
.
One of the best well known terminal emulators around, xterm, actually
emulates (or strives to emulate) a DEC VT220. I’ll get to xterm in a bit,
but the VT220 was a more advanced terminal than the VT100. Among other
things, it had twenty function keys, labeled F1 through F20. The first
five were strictly for local terminal functions; the host never saw any
escape codes from them. The remainder (F6 through F20) sent escape codes
^[[17~
to ^[[21~
, ^[[23~
to ^[[26~
, ^[[28~
, ^[[29~
, and
^[[31~
to ^[[34~
. The appropriate $TERM type for a VT220 is vt220
.
(Note that, on my system, the vt220 $TERM type actually defines VT100
escape codes for F1 through F4. There’s no definition for F5.)
This brings me to xterm. xterm has a long history, and the function
key definitions have changed over time. The original xterm from the X
Consortium (even before they became the Open Group) used escape codes
based on the VT220, but extended to cover the range from F1 to F48. F1
through F12 generated, respectively, codes ^[[11~
to ^[[15~
, ^[[17~
to ^[[21~
, ^[[23~
, and ^[[24~
. Shift-F1 through Shift-F12 were used
for F13 through F24, and generated codes from ^[[11;2~
to ^[[24;2~
.
Similarly Ctrl-F1 through Ctrl-F12 were used for F25 through F36 and
generated codes ^[[11;5~
to ^[[24;5~
, and Ctrl-Shift-F1 through
Ctrl-Shift-F12 were used for F37 through F48 and generated codes
^[[11;6~
to ^[[24;6~
. None of the base xterm $TERM types on my system
correspond to this series of escape codes, though you can still get xterm
to exhibit the old behavior by setting the OldXtermFKeys resource to
‘true
’.
The current XFree86 xterm mixes VT100 and VT220. Since the original VT220
didn’t have F1 through F5, the XFree86 xterm uses the escape sequences
from the VT100’s PF1 through PF4 for F1 through F4 while retaining the
VT220-based escape sequences from the X Consortium xterm for F5 through
F12. So the differences from the earlier xterms are: F1 through F4
generate escape codes ^[OP
through ^[OS
, F13 to F16 generate ^[O2P
to ^[O2S
, F25 to F28 generate ^[O5P
to ^[O5S
, and F37 to F40
generate ^[O6P
to ^[O6S
. On my system, the $TERM types that have the
appropriate function key definitions are xterm
, xterm-debian
,
xterm-mono
, and xterm-xfree86
.
The GNOME project’s terminal emulator is gnome-terminal. It generates the exact same escape codes as the XFree86 xterm and will work with the same $TERM settings. Note, however, that some function keys are bound to gnome-terminal actions and will not be passed through to applications running in the terminal. (For example, F1 calls up the GNOME help browser to view the gnome-terminal documentation.)
multi-gnome-terminal is based on gnome-terminal, but it implements
multiple tabbed terminal sessions in a single window. It also does the
function keys a little differently, though it’s a bit more like the
original VT220. F1 through F12 behave exactly the same as the XFree86
xterm. Shift-F1 through Shift-F10 function as F11 through F20 and
generate escape codes from ^[[23~
to ^[[34~
, just like the VT220.
Note that this means there are two ways to get F11 and F12. (Actually,
there are three, since Shift-F11 and Shift-F12 are also equivalent to
F11 and F12.) On my system, the $TERM types with the appropriate function
key definitions are xterm-color
, xterm-r6
, and xterm-vt220
. xterm
can be made to behave like this by setting the SunKeyboard resource to
‘true
’. Note that, like gnome-terminal, multi-gnome-terminal binds some
function keys for its own use and may not pass then through to the
programs in the terminal.
rxvt is a very popular xterm replacement. It uses the same escape
sequences at the X11R6 xterm for F1 through F12. Shift-F1 through
Shift-F12 work similarly to multi-gnome-terminal; they add ten to the
number on the key (so there are again two ways to get F11 and F12). rxvt
generates the same escape sequences as multi-gnome-terminal for F11
through F20, and uses ^[[23$
and ^[[24$
for F21 and F22, respectively.
The sequence continues with Ctrl-F1 through Ctrl-F12 generating ^[[11^
through ^[[24^
for F23 through F34 (no overlap with previous sequences),
Ctrl-Shift-F1 through Ctrl-Shift-F10 generating ^[[23^
through ^[[34^
for F33 through F42 (two-key overlap), and Ctrl-Shift-F11 and
Ctrl-Shift-F12 generating ^[[23@
and ^[[24@
for F43 and F44. The base
$TERM type for rxvt is rxvt
, though it ships with several types for
different circumstances, including rxvt-basic
and rxvt-m
. It also
comes with rxvt-unicode
, but on my system that definition only lists
function keys up to F20.
GNU screen is also a terminal emulator, though it expects to run
within another terminal environment (as opposed to displaying text in a
graphical environment like xterm or displaying text on physical hardware
like an actual terminal). As such, it translates many escape sequences
from its containing terminal environment to the VT100-like environment it
provides. It will recognize and translate the sequences for F1 through
F12. For those, it will generate the same escape codes as the XFree86
xterm. It does not recognize F13 and above; those escape codes will pass
through unchanged to the programs running within screen. (Note that the
screen ‘bindkey’ command has a -k option that uses termcap capabilities to
represent keys. It understands k1 through FA, which correspond to F1
through F20.) The $TERM type for screen is screen
.
key | VT100 | VT220 | X11R6 xterm | XFree86 xterm | rxvt | MGT | screen |
---|---|---|---|---|---|---|---|
F1 | ^[OP |
^[[11~ |
^[OP |
^[[11~ |
^[OP |
^[OP |
|
F2 | ^[OQ |
^[[12~ |
^[OQ |
^[[12~ |
^[OQ |
^[OQ |
|
F3 | ^[OR |
^[[13~ |
^[OR |
^[[13~ |
^[OR |
^[OR |
|
F4 | ^[OS |
^[[14~ |
^[OS |
^[[14~ |
^[OS |
^[OS |
|
F5 | ^[[15~ |
^[[15~ |
^[[15~ |
^[[15~ |
^[[15~ |
||
F6 | ^[[17~ |
^[[17~ |
^[[17~ |
^[[17~ |
^[[17~ |
^[[17~ |
|
F7 | ^[[18~ |
^[[18~ |
^[[18~ |
^[[18~ |
^[[18~ |
^[[18~ |
|
F8 | ^[[19~ |
^[[19~ |
^[[19~ |
^[[19~ |
^[[19~ |
^[[19~ |
|
F9 | ^[[20~ |
^[[20~ |
^[[20~ |
^[[20~ |
^[[20~ |
^[[20~ |
|
F10 | ^[[21~ |
^[[21~ |
^[[21~ |
^[[21~ |
^[[21~ |
^[[21~ |
|
F11 | ^[[23~ |
^[[23~ |
^[[23~ |
^[[23~ |
^[[23~ |
^[[23~ |
|
F12 | ^[[24~ |
^[[24~ |
^[[24~ |
^[[24~ |
^[[24~ |
^[[24~ |
|
F13 | ^[[25~ |
^[[11;2~ |
^[O2P |
^[[25~ |
^[[25~ |
||
F14 | ^[[26~ |
^[[12;2~ |
^[O2Q |
^[[26~ |
^[[26~ |
||
F15 | ^[[28~ |
^[[13;2~ |
^[O2R |
^[[28~ |
^[[28~ |
||
F16 | ^[[29~ |
^[[14;2~ |
^[O2S |
^[[29~ |
^[[29~ |
||
F17 | ^[[31~ |
^[[15;2~ |
^[[15;2~ |
^[[31~ |
^[[31~ |
||
F18 | ^[[32~ |
^[[17;2~ |
^[[17;2~ |
^[[32~ |
^[[32~ |
||
F19 | ^[[33~ |
^[[18;2~ |
^[[18;2~ |
^[[33~ |
^[[33~ |
||
F20 | ^[[34~ |
^[[19;2~ |
^[[19;2~ |
^[[34~ |
^[[34~ |
||
F21 | ^[[20;2~ |
^[[20;2~ |
^[[23$ |
||||
F22 | ^[[21;2~ |
^[[21;2~ |
^[[24$ |
||||
F23 | ^[[23;2~ |
^[[23;2~ |
^[[11^ |
||||
F24 | ^[[24;2~ |
^[[24;2~ |
^[[12^ |
||||
F25 | ^[[11;5~ |
^[O5P |
^[[13^ |
||||
F26 | ^[[12;5~ |
^[O5Q |
^[[14^ |
||||
F27 | ^[[13;5~ |
^[O5R |
^[[15^ |
||||
F28 | ^[[14;5~ |
^[O5S |
^[[17^ |
||||
F29 | ^[[15;5~ |
^[[15;5~ |
^[[18^ |
||||
F30 | ^[[17;5~ |
^[[17;5~ |
^[[19^ |
||||
F31 | ^[[18;5~ |
^[[18;5~ |
^[[20^ |
||||
F32 | ^[[19;5~ |
^[[19;5~ |
^[[21^ |
||||
F33 | ^[[20;5~ |
^[[20;5~ |
^[[23^ |
||||
F34 | ^[[21;5~ |
^[[21;5~ |
^[[24^ |
||||
F35 | ^[[23;5~ |
^[[23;5~ |
^[[25^ |
||||
F36 | ^[[24;5~ |
^[[24;5~ |
^[[26^ |
||||
F37 | ^[[11;6~ |
^[O6P |
^[[28^ |
||||
F38 | ^[[12;6~ |
^[O6Q |
^[[29^ |
||||
F39 | ^[[13;6~ |
^[O6R |
^[[31^ |
||||
F40 | ^[[14;6~ |
^[O6S |
^[[32^ |
||||
F41 | ^[[15;6~ |
^[[15;6~ |
^[[33^ |
||||
F42 | ^[[17;6~ |
^[[17;6~ |
^[[34^ |
||||
F43 | ^[[18;6~ |
^[[18;6~ |
^[[23@ |
||||
F44 | ^[[19;6~ |
^[[19;6~ |
^[[24@ |
||||
F45 | ^[[20;6~ |
^[[20;6~ |
|||||
F46 | ^[[21;6~ |
^[[21;6~ |
|||||
F47 | ^[[23;6~ |
^[[23;6~ |
|||||
F48 | ^[[24;6~ |
^[[24;6~ |