Search code examples
bashshellterminalkeyboardxterm

Bash: detecting key-presses: how to read special key hex sequence(like Insert) and why it is '\x1b\x5b\x32\x7e'(Insert)?


In the book Advanced Bash-Scripting Guide Section 5.2 Example 5-3. Detecting key-presses. The whole code can be viewed at detecting_key-presses.sh. In the example, there is some code snippet which I can't understand.

First snippets:

# Convert the separate home-key to home-key_num_7:
if [ "$key" = $'\x1b\x4f\x48' ]; then
    key=$'\x1b\x5b\x31\x7e'
    #   Quoted string-expansion construct.
fi

# Convert the separate end-key to end-key_num_1.
if [ "$key" = $'\x1b\x4f\x46' ]; then
    key=$'\x1b\x5b\x34\x7e'
fi

$'\x1b\x5b\x32\x7e')  # Insert
    echo Insert Key
    ;;

In the above snippet, for example, when I press Home key and Insert key,

  1. Why it will produce \x1b\x4f\x48 sequences for Home and \x1b\x5b\x32\x7e sequences for Insert?
  2. And the comment says that "Convert the separate home-key to home-key_num_7" and "Convert the separate end-key to end-key_num_1", what does the conversion, "key_num_7" and "key_num_1" means?

Second snippet:

unset K1 K2 K3
read -s -N1 -p "Press a key: "
K1="$REPLY"
read -s -N2 -t 0.001
K2="$REPLY"
read -s -N1 -t 0.001
K3="$REPLY"
key="$K1$K2$K3"

In the above snippet, every time I pressed one key,

  1. Why it read 3 variable to construct a key hex sequences?
  2. The second read -s -N2 -t 0.001, why should specify the -t(timeout) option and -N2(nchars) to read 2 characters not 1?

Solution

  • There are several questions asked...

    The script is expecting escape sequences to be sent by special keys. On a typical keyboard, those are all of the keys which have a name or graphic symbol (such as ←, for left-cursor). By convention (there is no applicable standard) those keys send sequences of characters beginning with escape, with the second character often [. For just those two characters, the hexadecimal codes are 0x1b and 0x5b, respectively (see ASCII table). The 0x4f is the letter O, and would be sent by a terminal's special keys in application mode.

    The particular sequences sent by your Home and End keys use a slightly different convention from some of the other special keys, referred to a PC-style (see the xterm FAQ Why can't I use the home/end keys? for the background on that). Apparently the developer of the script decided to solve a problem related to that FAQ by ensuring that both variations of the sequences sent by Home and End would be translated into the VT220-style sequence.

    The last question asks why it is necessary to do separate reads and use separate variables. That is because the sequence of characters sent by a special key may be transmitted over a network, and take more time than one of those read operations allows. So only part of the sequence may be read at each try. The script collects the pieces and puts them together as one sequence of characters.