2306


Bashの対話環境はキーバインドの設定(特定のキー入力に対して特定のコマンドを実行)を行うことができます。現在の設定は`bind
-P`で確認することができます。

しかし、この時のキーの表示(character sequence)はわかりにくいものになっています。 例えば、↑キーのcharacter
sequenceは、`[A`です。 これは以下の手順で確認できます:

  1. 端末上でCtrl+Vを押す。
  2. 続けて↑を押すと、^[[Aと表示される。
  3. ^[はエスケープを表す記号なので気にしない。[Aが↑のcharacter sequenceである。

**質問** : 逆に、与えられたcharacter sequenceがどのようなキー入力に対応するのかを調べるにはどうすればよいのでしょうか?

* * *

動機: なぜこれが知りたいのかというと、私の`.bashrc`には

[code]

    bind '"\e[0A": history-search-backward'
    
[/code]

と書いてあるのですが、この`"\e[0A"`が何のcharacter
sequenceに相当するのかわからなくて困っています。あまり意味がないものなら消してしまいたいのですが....


CC BY-SA 3.0
2014-12-21T02:15:13.260
2305
2014-12-22T03:27:06.980
2014-12-21T02:55:24.383
848
848
question
bash
Character Sequenceに対応するキー入力を調べたい

[code]

    bind '"\e[0A": history-search-backward'
    
[/code]

まず、`\e[0A` はもしかして `\e[OA` ではないでしょうか？

キー入力の確認についてですが、terminal(端末)の制御に terminfo を使用されているとして話を進めます。まず、infocmp
コマンドを実行して現在使用中の端末の設定を確認します。

[code]

    $ infocmp | less
    
[/code]

表示されている内容から、`[A` か `OA` を検索します。

[code]

    cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
    kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
    
[/code]

対応する制御シーケンス名が、`cuu1` か `kcuu1` だと分かるかと思います。

次に、terminfo の man を確認します。

[code]

    $ man terminfo
    
[/code]

そこで `cuu1` を検索すると、カーソルキー(↑)だと分かります。

[code]

    Variable   Cap-  TCap   Description
    String     name  Code
    
    cursor_up  cuu1  up     up one line
    key_up     kcuu1 ku     up-arrow key
    
[/code]

もっとも、この調べ方はかなり煩雑かと思います。また、terminfo ではなく termcap
を使われている場合には当てはまりませんので、ご参考程度までにどうぞ。


CC BY-SA 3.0
2014-12-21T03:35:09.987
2306
2014-12-21T03:35:09.987
2305
answer


手順としては、 heliac2001 さんのものと同じで

  * `infocmp` で、設定エントリを検索
  * `man 5 terminfo` のなかで、対応する行を見つける

です。一行で書けば、

[code]

    $ infocmp -1x | grep 'OA' \
       | sed 's/^ *//' | tee /dev/tty | sed 's/=.*$//' \
       | xargs -l sh -c 'man 5 terminfo | grep -F "  $0  "'
    
[/code]

となりますが、面倒。ですので逆引きを行うスクリプトを作成してみました。

ファイル: `terminfo_lookup.sh`

[code]

    #!/bin/sh
    # Reverse terminfo lookup command.
    
    param_code=$1
    param_term=$2
    
    if [ -z "$1" ]; then
      echo "Usage: $0 [part of a terminfo entry] [termname]"
      echo "Example:"
      echo "        $0 kent"
      echo "        $0 OA xterm"
      echo "        $0 kcuu1 putty"
      echo "        $0 \\\\EA rxvt"
      echo "        $0 kf1= xterm"
      exit 1
    fi
    
    echo "Searching for \"$param_code\"."
    if [ -z "$2" ]; then
      echo "TERM value is \"$TERM (default)\"."
    else
      echo "TERM value is \"$param_term\"."
    fi
    
    entries=`infocmp -1x $param_term \
      | grep '=' | grep -F $param_code \
      | sed 's/=^ *//' | sed 's/,$//'`
    
    if [ -z "$entries" ]; then
      echo "No entry found"
      exit 1
    fi
    
    for entry in $entries
    do
     echo ---
     echo "entry :" $entry
    
     code=`echo $entry | sed 's/=.*$//'`
     hint=`man 5 terminfo 2> /dev/null | grep "  $code  " `
     echo "hint  :" $hint
    done
    
[/code]

使うときは、コマンドの引数に terminfo の設定エントリの一部を渡してください。

質問内容に沿う調査ならば、

[code]

    $ terminfo_lookup.sh [OA
    
[/code]

で必要な情報を確認し、

[code]

    $ terminfo_lookup.sh cuu
    $ terminfo_lookup.sh cuu rxvt
    
[/code]

で関連情報や環境による差異を掘り下げて調査します。学習には使えるかと思います。


CC BY-SA 3.0
2014-12-22T03:27:06.980
2354
2014-12-22T03:27:06.980
4978
2305
answer