Key bindings table

key mappingkeyboardterminalzsh

Do we have a key bindings table that translates all the various ways of referring to a key press? I'm using zsh, but I presume that if there was such a table it would work for any shell.

The reason I ask is that I'd like to assign some keybindings and I have no way of knowing how to refer to them (unless I'm going to steal one that's already defined).

For example, in 'zbindkey' we have this sort of thing:

[[ "$terminfo[kend]"  == " O"* ]] && \
    bindkey -M emacs "${terminfo[kend]/O/[}"  end-of-line

… and I can guess that "kend" means that this refers to the End key.

Cross checking with bindkey I see these lines:

"^E" end-of-line
"^[OF" end-of-line
"^[[F" end-of-line

… so I trust that one of those lines refers to the End key. Which one?

We also have this in the "bindkey" file:

bindkey "\e[A" history-beginning-search-backward

Now, I happen to know that that's the Up Arrow key, but how could I find out if I didn't know?

$ bindkey (at CLI)

… gives us a different language for the same key:

"^[[A" history-beginning-search-backward

… but at least now I know that ^[[A in bindkey-at-CLI speak is the same thing as \e[A in bindkey-in-zbindkey speak. That's easy. In the old days in DOS, the Up Arrow was 0;72 — you could find the scan code of every legal keystroke and there was only the one language.

Is there a table? Or some other way of being able to pick a keystroke and know how to refer to it in terminfo[] … in " bindkey-in-zbindkey " … in "bindkey-at-CLI " and/or in whatever other languages there may happen to be?

Again, in DOS there was the scancode program — type a keystroke, and you got the scancode. It was sinfully easy.


From the answers I guess then that there is no way to print out a table of all possible bindings? Anyway 'bindkey' does almost what I want:

pts/2 HP-y5-10-Debian1 root /aWorking/Docs $ bindkey -L
bindkey "^@" set-mark-command
bindkey "^A" beginning-of-line
bindkey "^B" backward-char
bindkey "^D" delete-char-or-list
bindkey "^E" end-of-line
...

at least I can see all existing bindings, even if not all possible bindings. Now, if there was just some way of translating the key glyphs into 'regular' terms:

bindkey "Home" beginning-of-line

… then I'd be happy.

Best Answer

The interface between a terminal application and a terminal emulator (or hardware terminal) transmits bytes, not keys. Function keys such as cursor movement keys are translated into escape sequences (beginning with the escape character ESC a.k.a. \e a.k.a. \033 a.k.a. 0x1b a.k.a. ^[). The same goes for combinations of a function key or a character key with modifiers, though not all terminals send different sequences for all the different modifier combinations. A few keys are sent encoded as control characters (e.g. Tab → Ctrl-I = \t = \011).

As you can see, there are many ways to describe control characters. Some have a name, corresponding to their traditional function (e.g. Tab, Line feed); those tend to have a backslash+letter combination that you can use inside $'…' or in an argument to echo or print (as well as in sed regular expressions and in string literals in awk, C and other languages (note that different tools may have a slightly different set of escape sequences)). You can use backslash+octal (e.g. \033) in these contexts as well.

There is some variation as to which escape sequence terminals send for each key. Fortunately, there is almost no overlap: there are very few character sequences that mean different keys on different terminal. The main problem is character 127 = \177 = 0x7f which is most often Backspace nowadays but sometimes Delete.

^[OF and ^[[F (i.e. \eOF and \e[F) are the two common escape sequences sent by End. ^E (i.e. \005) is the Emacs key binding (Ctrl+E) for end-of-line.

To see what your terminal emulator sends for a particular key or key combination, press Ctrl+V and then the key in question. This inserts the first character of the escape sequence literally. Escape sequences normally consist of an escape character followed by printable characters, so the rest of the escape sequence is inserted literally too.

The Terminfo database contains the escape sequences for some keys. You'll find the list of Terminfo capabilities in the terminfo(5) man page on your system. In zsh, you can list the values in the database through the terminfo associative array. Beware when printing out values that they contain escape sequences which are also interpreted by the terminal when displayed, so print them in a quoted form.

% print -lr ${(q)terminfo[kend]}
$'\033'OF

See How do keyboard input and text output work? for a more complete overview of what happens when you press a key. It isn't necessary to understand key bindings in zsh.

Related Question