Sending correct escape sequences in terminal

ansibashescape-characterskeyboardterminal

Issue

To scroll a few lines up in WeeChat one is supposed to press <Alt> + <PgUp>. When I press these keys, the program thinks I'm pressing <Alt> + , instead.

Debugging

In my terminal, typing <PgUp> is received as meta2-5~. This works fine and represents the <PgUp> escape sequence: <Esc>[5~. (So, it is my understanding that meta2 is <Esc>[.)

Typing <Alt> + <PgUp> is received as meta-, instead of meta-meta2-5~. (Typing <Alt> + , is also received as meta-,, so it is my understanding that <Alt> corresponds to meta here.) The reasons <Alt> is received as meta- is because I've checked "Send Alt as Meta" in Terminal.app settings.

Now (hold on for such strange behaviour), if I press <Esc>, this guy is received as meta! So, to scroll up a few lines I can press <Esc> + <PgUp> a few times. (I cannot simply keep <Esc> pressed and hit a few <PgUp>s. I need to repress <Esc> as well.)

TL;DR

  • <PgUp> is escaped correctly as meta2-5~.
  • <Alt> + <PgUp> is escaped incorrectly as meta-, (should be meta-meta2-5~).
  • <Alt> + , is escaped correctly as meta-,.
  • <Esc> + <PgUp> is escaped incorrectly (?) as meta-meta2-5~.

Setup

I'm sitting on a Mac, using Terminal.app, ssh-ing into a CentOS 7.6.1810, connected to a tmux session, running WeeChat in one window.

Additional info

Here the whole list of ANSI escape sequences can be found. Strangely, <PgUp> seems to be encoded as 0;73, and not the expected <Esc>[5~. So, I'm not sure what's going on in this website as well.

Additional context for sawdust answer

You seem to be misunderstanding the required keystrokes and which keys generate characters.

Point taken.


So did you hold down the <Alt> key, type the <PgUp> key, and then release the <Alt> key?
If the program responds as if you are "pressing <Alt> + ,", then you apparently did something else.

I indeed did "hold down the <Alt> key, type the <PgUp> key, and then release the <Alt> key".

I'm wondering whether MacOS caught that key combination and did send something else to my terminal, like that <Alt> + ,.


The <Esc> key is not a modifier key, and should not be kept "pressed".

Got it.


The two-byte code for the <PgUp> key is 0x0 0x49 or decimal 0 73.

Do you understand what <Esc>[5~ may refer to, then?
This answer points out that sometimes it's necessary to enforce Mac's Terminal.app to send correct escape sequences, and precisely <PgUp> as \033[5~, which it's what is already happening on my machine. I'm wondering now what sequence should be sent when <Alt> + <PgUp> is pressed instead.

These are "bindings" between keystrokes and… ?

Thanks for clearing my confusion.

Best Answer

You seem to be misunderstanding the required keystrokes and which keys generate characters.

Key concepts about standard terminal keyboards:
The <Shift>, <Ctrl>, and <Alt> keys do not generate any characters (by themselves).
These keys generate an alternate character code when combined with another key.
The notation used for describing such a combination of keys is:

 <modifier_key> + <char_key>  

The notation means that you should hold down the <modifier_key>, type (i.e. press and release) the <char_key>, and then release the <modifier_key>.
The plus sign, +, as used in this notation indicates the key combination, and does not indicate a key that should be typed or pressed as a keystroke for this combination.


... one is supposed to press <Alt> + <PgUp>. When I press these keys, the program thinks I'm pressing <Alt> + , instead

So did you hold down the <Alt> key, type the <PgUp> key, and then release the <Alt> key?
If the program responds as if you are "pressing <Alt> + ,", then you apparently did something else.

Note that (contrary to your assumptions), a modifier key does not necessarily prepend characters to form an escape sequence. The modifier key can generate a unique character code based on the type key.
For instance <Shift> + <A> generates an upper-case A character. Without the <Shift> modifier key, a low-case a character would be generated. Whereas <Ctrl> + <A> generates an ASCII SOH (start of header) character.


The reasons <Alt> is received as meta- is because I've checked "Send Alt as Meta" in Terminal.app settings.

On a PC the keyboard hardware generates scancodes so that every keypress (and release) can be detected.
It is up to software to translate and remap the keypresses.
That means that the previous comments on how the <Shift>, <Ctrl>, and <Alt> keys behave on a standard terminal may not apply in all cases.
You seem to be describing such a nonstandard, customized handling of keyboard scancodes.

On PCs compound modified keys can be defined, i.e. <Ctrl> + <Shift> + <A>. On Teletype terminals only a few such key combinations generated actual character codes.

Apparently this option you describe is to replace the functionality of the <Alt> key. Per Wikipedia:

The Meta key is a modifier key on certain keyboards.
...
Generally the Meta key worked similar to Macintosh's Command key, in that when held down it modified letters and symbols into immediate commands (shortcuts). On these keyboards you could get many commands per letter by combinations of Meta with other modifier keys such as Hyper and Super.


... if I press <Esc>, this guy is received as meta!

The <Esc> key is a key that generates a (control) character. It is not a modifier key like the <Shift>, <Ctrl>, and <Alt> keys.

So a sequence such as <Esc> + <PgUp> needs to be entered by typing the <Esc> key, and then typing the <PgUp> key. (The plus sign is actually superfluous in this case, if not incorrect, and the keystrokes should be written simply as <Esc> <PgUp>.

I cannot simply keep <Esc> pressed and hit a few <PgUp>s. I need to repress <Esc> as well.

The <Esc> key is not a modifier key, and should not be kept "pressed".


Here the whole list of ANSI escape sequences can be found. Strangely, <PgUp> seems to be encoded as 0;73, and not the expected <Esc>[5~. So, I'm not sure what's going on in this website as well.

You seem to be misunderstanding that web page.
The data generated by key presses and key releases on a PC keyboard undergo several mappings or translations before being "read" by an application program.
Initially the keyboard hardware generates scancodes.
The Keyboard Service Routine of the OS will convert the scancode to a two-byte value or Auxiliary byte values. Many of these values were established by register AL and AH contents returned by the keyboard service routine of the original IBM PC BIOS.
The two-byte code for the <PgUp> key is 0x0 0x49 or decimal 0 73.
If you expect <PgUp> to generate an escape character sequence, then you could use the Set Keyboard Strings command described on that web page you cited.

The ANSI escape sequences (in general) are for the control of the display side of the terminal.
In general the terminal keyboard does not generate escape sequences (unless there is no ASCII character for that key, or the key has been reprogrammed).


ADDENDUM

Do you understand what <Esc>[5~ may refer to, then?

Not really.
Your question is complicated since it's a mashup of how keystrokes translate to (ANSI) Escape code sequences. The problems are that:

  • (a) software can translate the received keyboard scancodes into anything it chooses,

For examples of how various scancode sequences (i.e. key presses and releases) can be translated/interpreted for different software environments, see JavaScript Keyboard Events.
The takeaway is stated in the conclusion:

It's truely impressive what a hash has been made of a simple thing like recognizing a key pressed on the keyboard. You'd think computer technology would have advanced far enough by now to have this all worked out better.

Additionally, the ANSI terminal standard(s) provides user-capability to redefine what character(s) individual keys will generate (i.e. the Set Keyboard Strings command described on that web page you cited).

  • and (b) <Esc>[5~ could be classified as an ANSI Control Sequence for "private use" (by the defining terminal).

ANSI standards define the two-character sequence of ESC and [ as the "Prefix to an ESCape sequence" and "Control Sequence Introducer", aka CSI.
The terminating ~, or 0x7E, character would seem to categorize this sequence as a "private" one that the terminal (or terminal emulation program) can define for its own use.


Apparently the "Send Alt as Meta" option you mention is to replace the functionality of the <Alt> key. Per Wikipedia:

The Meta key is a modifier key on certain keyboards.
...
Generally the Meta key worked similar to Macintosh's Command key, in that when held down it modified letters and symbols into immediate commands (shortcuts). On these keyboards you could get many commands per letter by combinations of Meta with other modifier keys such as Hyper and Super.
...
Software often provided another workaround, such as using the Alt key

So presumably there would be configuration capability to define the strings that these Meta key combinations would respond with (e.g. similar to the ANSI Set Keyboard Strings command described on that web page you cited).


Typing <Alt> + <PgUp> is received as meta-, instead of meta-meta2-5~.

Modifier keys can actually generate entirely new character sequences for the key combinations, and may not simply prepend a fixed substring.
So just because "<PgUp> is received as [or generates] meta2-5~", you cannot use that to predict what the Meta version of <PgUp> is.

So I'm guessing that somewhere in that terminal emulation program there's a definition for <Meta> + <PgUp> that is not what you expect.

Related Question