Understanding the modifier keys in the terminal

I'm sure everyone reading this has ran a curses-based program in their terminal. And most likely this program has taken use of a ctrl- (⎈), alt- (⎇), or meta- (◆), or super-key. Unfortunately the implementation is pretty quirky.

We can check how these keys are interpreted in the terminal by running tee. The following is the output of Ctrl - a, Alt - a, Alt + Shift - a, Esc, Enter (to flush) and Ctrl - c (to exit)

$ tee output
^A^[a^[A^[
^C

As we can see, all the key combinations are prefixed by a caret symbol, which is called caret notation; used to denote that the character is an ASCII-encoded control character.

If we check out the hex values of the characters we stored in the output file

$ hexdump -C <output
00000000  01 1b 61 1b 41 1b 0a                              |..a.A..|
00000007

we see that the first character is 01.

To check which character that is, we can open up the ASCII table;

$ man ascii
ASCII(7)             BSD Miscellaneous Information Manual             ASCII(7)

[...]

The hexadecimal set:

00 nul   01 soh   02 stx   03 etx   04 eot   05 enq   06 ack   07 bel
08 bs    09 ht    0a nl    0b vt    0c np    0d cr    0e so    0f si
10 dle   11 dc1   12 dc2   13 dc3   14 dc4   15 nak   16 syn   17 etb
18 can   19 em    1a sub   1b esc   1c fs    1d gs    1e rs    1f us
20 sp    21  !    22  "    23  #    24  $    25  %    26  &    27  '
28  (    29  )    2a  *    2b  +    2c  ,    2d  -    2e  .    2f  /
30  0    31  1    32  2    33  3    34  4    35  5    36  6    37  7
38  8    39  9    3a  :    3b  ;    3c  <    3d  =    3e  >    3f  ?
40  @    41  A    42  B    43  C    44  D    45  E    46  F    47  G
48  H    49  I    4a  J    4b  K    4c  L    4d  M    4e  N    4f  O
50  P    51  Q    52  R    53  S    54  T    55  U    56  V    57  W
58  X    59  Y    5a  Z    5b  [    5c  \    5d  ]    5e  ^    5f  _
60  `    61  a    62  b    63  c    64  d    65  e    66  f    67  g
68  h    69  i    6a  j    6b  k    6c  l    6d  m    6e  n    6f  o
70  p    71  q    72  r    73  s    74  t    75  u    76  v    77  w
78  x    79  y    7a  z    7b  {    7c  |    7d  }    7e  ~    7f del

[...]

As we can see, 01 corresponds with SOH, short for Start Of Header, but is most often written as ^A - Control A. Pretty straightforward.

Then there's ^[a which was Alt and a. Instead of being a single character, it's composed of two characters; ^[ and a.

We actually see a lot of ^[/0x1b characters in the remaining key combos, the only difference in the next combo is that the a is an A due to us holding down the Shift key.

The escape key is from us actually pressing Esc. As you've might noticed, Alt and Esc seem to be very similar.

The short version of it is that you can use Esc instead of Alt, but not the other way round.

After understanding the difference between the way Alt and Control are handled in the terminal makes it apparent why you can't have combos like Control + Shift - a, but Alt + Shift - a works.