I've been tooling around w/ this input reader lately. Currently it only prints a report to stdout for each key pressed while it runs, but I would like to graduate it to a higher purpose sooner than later, as it seems to be coming along ok. So far it has a few things going for it:

  1. All its output is the result of a few concurrent processes in a single pipeline.
  2. It interprets and reports on each keypress as soon as it is made.
  3. It (to the best of my knowledge) reports on as many bytes per keypress as are sent for each keypress.

For example, if I run it and press the following keys/key-combinations in order ...

  1. a
  2. CTRL+J
  4. UP
  5. ALT+UP

...it prints the following to the terminal screen, a line per keypress and as soon as each keypress is made:

 \e:27 [:91 A:65
 \e:27 [:91 1:49 ;:59 5:53 A:65

...where each byte in each keypress is printed like...

<space>(printable char|\C-escape|\octal-escape):[decimal byte value]

... as I considered appropriate.

Some of it confuses me though:

  1. Though I think I've tried all of the keys, and though I've definitely set stty to send 8-bit chars (w/ cs8), the ALT+SPACE combo seems to be the only one reporting any constituent byte higher than ASCII decimal 127.
    • This is especially confusing as I assume it has something to do with the ALT modifier metafying (a concept which I admittedly understand very little about) the key sequence, but in seemingly every other case ALT+anykey just prefixes an ESC to the sequence, or otherwise subtly modifies an already escaped sequence.
    • Should ALT not be shifting the sent sequence into the higher 128 - 255 range?
    • (in a comment below derobert indicates the reader successfully interpreted and reported on multi-byte UTF-8 compose sequence) Note: locale reports all LC_* categories are set to en_US.UTF-8
  2. Also concerning is that while I seem to get all of the bytes for each keypress, in its current form my script will delimit keypresses at 8 now 32 bytes maximum.
    • I previously thought 8 bytes sufficient, but I grow doubtful now when I consider whether multibyte chars in other locales might be combined with some of the longer escape sequences I'm seeing. And so I have extended the buffer - but with less certainty than 8 bytes initially provided me.
    • Is there an upper-limit to how many bytes might be sent in a single keypress?
  • compose - - . got me \342:226 \200:128 \223:147. You can of course map – to one keypress, instead of the many I used...
    – derobert
    Commented Mar 31, 2015 at 15:25
  • @derobert - hmm... is that a good thing? Oh, right - so that's supposed to send the one sequence, right? Or...? Sorry, man, I asked this question because I'm really lacking in understanding in the not-painted-on-my-keyboard department. By the way, if you just ran it straight out of copy-paste, you might want to make sure those ^key portions of the script are actually some non-printable char rather than just the literal ^char printables.
    – mikeserv
    Commented Mar 31, 2015 at 15:28
  • Yeah, I did a copy and paste, from a browser. You might want to post a link where someone can just curl it w/o it being corrupted... I'm not sure what it should print. UTF8 characters are multiple octets. Certainly a single keypress can produce a UTF8 character. (But with macros, a single keypress could also produce many plain ASCII characters.)
    – derobert
    Commented Mar 31, 2015 at 15:36
  • @derobert - right. So did you get three lines or just three bytes? By the way, though, there shouldn't have been any issue with those - those would just be octal escapes which are used when those non-printables are not matched.
    – mikeserv
    Commented Mar 31, 2015 at 15:36
  • It was all on one line. But I probably corrupted your script when copying & pasting.
    – derobert
    Commented Mar 31, 2015 at 15:37

1 Answer 1


That's actually several questions. Some deal with terminal-specific behavior and some deal with compose.

First, there is a question regarding the expected behavior of Alt used as a modifier. Some people equate the Alt key (which is labeled on many keyboards) with Meta (which is rarely labeled as such on terminal keyboards). And some go further, equating it with the escape character. Call that a conventional use. In xterm, at least, the association is configurable (since patch #122 in 1999, it has the metaSendsEscape resource, and patch #225 in 2007 added altIsNotMeta and altSendsEscape resources). Other terminal emulators (and their users, perhaps) are not so flexible. So there's a convention which equates escape and meta. Conventions are not standards.

The documented behavior of the meta key is in the terminfo(5) manual page:

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 as smm and rmm.

There's no standard behavior for the case where meta mode is off (just convention).

Depending on the eightBitInput resource in xterm, it may construct codes higher than 128 using the meta key. For instance, in patch #183 in 2003, this change was made to avoid making the meta mode produce illegal UTF-8:

  • modify handling of eightBitInput resource in UTF-8 mode to translate the value into UTF-8. Otherwise an illegal UTF-8 code is sent to the application (report by Bram Moolenaar).

Generally speaking, however, most of the escape sequences that you might use with terminals and the conventional escape sequences that their keyboards return use 7-bit ASCII. VT100s are no exception to this; that was the point of this change from patch #177 in 2002:

  • modify parser tables to improve detection of malformed control sequences, making xterm behave more like a real DEC terminal (patch by Paul Williams).

That is, the parser tables are mostly organized to ignore the eighth bit of the input characters. Other terminals may ignore that aspect, but still copy the escape sequences used for xterm's keyboard. The result is that you mostly see 7-bit ASCII.

I'm using xterm as an example since most of the behavior you're likely to see started with xterm (and most of the remainder came from rxvt). With xterm, you could have several cases where you get fairly long escape sequences from a key, e.g.,

  • using the modifyOtherKeys mode, which assigns an escape sequence to (most of) the keys on the keyboard,
  • using the translations resource, which let you send "any" sequence of characters, and
  • using the DECUDK feature, which sends an application-defined string (as a sequence of hexadecimal digits).

Other terminals (such as OSX Terminal.app and iTerm2) also can send user-configurable strings. From that standpoint, there's no well-defined limit on the number of bytes sent by a key.

On the other hand, compose is more well-defined: its result is a character (or could that be multiple characters?) in a given encoding. Assume just a single character. The maximum standard length of a UTF-8 encoded character is 4 bytes. While you could see a user-configured key sending this data, mostly (because of compatibility and conventions) you won't see the two (escape sequences and encoded-characters) mixed together.

Further reading:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .