What are the characters printed when Alt+Arrow keys are pressed?
Depending on how the terminal is configured, typing Alt+Key is like typing the Esc and Key keys in sequence, so it sends the ESC character (aka \e
or ^[
or \033
) followed by the character or sequence of characters sent upon pressing that Key.
Upon pressing Up, most terminal emulators send either the three characters \033[A
or \033OA
depending on whether they're in application keypad mode or not.
The first one does correspond to the escape sequence which when output to the terminal, move the cursor up. If you do:
printf '\nfoo\033[Abar\n\n'
You'll see bar
written after foo
one row up. If you do:
stty -echoctl; tput rmkx; read foo
You'll see that the arrow keys do move the cursor around.
When an application like zsh
or vi
reads that sequence of characters from the terminal, it interprets it as the "Up" action, because it knows from the terminfo database (kcuu1
capability) that it is the escape sequence sent upon pressing Up.
Now, for Alt-Up, some terminals like rxvt
and its derivatives like eterm
send \033
followed by the escape sequence for Up (that is \033\033[A
or \033\033OA
), while some others like xterm
or gnome-terminal
have separate escape sequences for those types of keys when used with the combination keys like Alt, Shift, Ctrl.
Those will typically send \033[1;3A
upon Alt-Up.
When sent to the terminal, that sequence will also move the cursor up (the second parameter (3) is ignored). There's no corresponding keypad key, so it's the same sequence sent upon Alt-Up in or out of application keypad mode.
Now whether it's \033\033[A
or \033[1;3A
, many applications don't know what those sequences are for. The terminfo database won't help them, because there's no such capability that defines what characters those key combinations send.
They will try their best to interpret that sequence. bash
for instance will interpret \033[1;3
as an escape sequence, doesn't know anything about it, so does nothing, followed by A
. zsh
, will stop reading as soon as it finds out there's no known matching character sequence. There's no escape sequence that it knows that starts with \033[1
so it will skip that, and read the rest: ;3A
and insert that in the line editor.
Many applications like vi
, zsh
or readline
based ones like gdb
or bash
(though beware bash
uses a modified version of readline
) allow you to add bindings for any sequence of characters.
For instance, in zsh
, you may want to bind Alt-Up, Alt-Down like:
bindkey '\e[1;3A' history-beginning-search-backward
bindkey '\e[1;3B' history-beginning-search-forward
Those are to search the history backward and forward for command lines that start like the current one up to the current position of the cursor which is quite handy to recall previous commands.
You can use Crtl+v to return input codes of your keyboard. If you do that for arrow keys, you will get [[D^
, [[C^
, [[A^
, and [[B
values. There aren't any default bindings for Alt+arrow keys, so it seems that performed action is printing letter code alone. Hovewer, if you create your local version of readline library configuration file:
$ cp /etc/inputrc ~/.inputrc
And add a line:
"\e[1;3C": "sometexthere"
Where [1;3C
is input code of Alt+→ (you can get it same way as before using Crtl+v shortcut) and restart your terminal then Crtl+→ shortcut will return you text "sometexthere" and other Alt+arrow shortcuts will stop returning characters.
Instead text you can pass a bindable command from http://www.gnu.org/software/bash/manual/html_node/Bindable-Readline-Commands.html#Bindable-Readline-Commands like
"\e[1;3C": unix-line-discard
to have same effect like Crtl+u (delete line).
More information here: http://cnswww.cns.cwru.edu/php/chet/readline/readline.html
The Alt key is often used as a meta modifier. Cursor- and function-keys are referred to as special keys since they may send multiple characters — and the characters which are sent can be altered.
Some users, e.g., for bash
expect that pressing Alt will send a key prefixed by the escape character. The documented "meta" feature (see terminfo(5)
) deals with the eighth bit:
If the terminal has a "meta key" which acts as a shift key, setting the 8th bit of any character transmitted, this fact can be indicated with
km
. Otherwise, software will assume that the 8th bit is parity and it will usually be cleared. If strings exist to turn this "meta mode" on and off, they can be given assmm
andrmm
.
bash
knows about that, too (see ncurses FAQ), but few of its users are interested in the feature. Nonetheless, they're accustomed to referring to Alt as "meta", even though meta mode is turned off. Both rxvt and xterm have had this feature since (at least) the early 1990s.
Other users (since xterm
introduced the feature in patch #94, 1999) may expect the modifier information to be encoded as a parameter in the sequence of characters that a special key would send. XTerm's documentation referred to these modified keys as "PC-style" function keys to distinguish them from "VT220-style" (which did not have modifiers). An unmodified cursor key might send ESC[A, but it is also legal to have a parameter, e.g., ESC[5A, which an application should understand as repeating that five times. The first version of xterm
's PC-style keys used that "5" to denote control, and a later version changed it to avoid confusion with the repeat count. So...
ESC[5A
suggests that the application move the cursor up 5 rows, while
ESC[1;5A
suggests that it move up one row, telling the application that a control key was pressed.
The useful combinations have been in the ncurses terminfo database since 2004:
# 2004-07-17
# * add xterm-pc-fkeys -TD
The terminfo database shows the current version of xterm+pcfkeys with a comment showing how the modifiers are encoded:
# This fragment describes as much of XFree86 xterm's "pc-style" function
# keys as will fit into terminfo's 60 function keys.
# From ctlseqs.ms:
# Code Modifiers
# ---------------------------------
# 2 Shift
# 3 Alt
# 4 Shift + Alt
# 5 Control
# 6 Shift + Control
# 7 Alt + Control
# 8 Shift + Alt + Control
# ---------------------------------
# The meta key may also be used as a modifier in this scheme, adding another
# bit to the parameter.
(Alt and meta are not necessarily the same key). That is a building block (in turn composed of other building blocks) from which the xterm
terminal description is formed. It uses an extension provided in ncurses since 1999 which allows user-defined names. Since termcap supports only 2-character names, and 1023-byte descriptions, there was no reason to make these extended names available through the termcap interface. They're readily available to applications using the terminfo interface.
Now comes a difficulty: there are a few ways for an application to determine what a key sequence like that represents:
- analyze the sequence of characters completely
- partly analyze it and throw away the control modifier if not needed
- just compare the sequence of characters against a dictionary, hoping to determine the meaning that way.
Few programs would do the first; some text editors would do the second (actually, I did this for ded
in the late 1980s). Developers for applications such as bash
chose the third route by assuming that most of the information is in termcap. Alternatively, they could have chosen to make a table with termcap/terminfo information and use the interface which gave the best information. xterm
does this for the tcap-query feature, providing vim
with the actual function key assignments.
Since none of the strings that bash
compares against match the strings it receives, it can get confused, settling for partial matches (such as the escape character by itself).
Further reading:
- How to fix the shifted function keys in vim in xterm in gnome-terminal?