Home や End キーが機能しない
コマンドラインプログラムでは、Home や End キーがうまく動作しないということがよくあります。キーが押されたときにターミナルエミュレータはマルチ文字エスケープコードを送信しているわけですが、(シェルなどの) プログラムがエスケープコードを正しく解釈できていないためです。問題が起こっているプログラムの設定を変更して、特定のエスケープコードを受信したときに適切な動作をするように設定することで問題は解決します。したがって、解決方法はプログラムによってそれぞれ異なります。
多数のプログラムに影響を与える問題から順々に確認していってください。
TERM
キーが機能しない理由としては TERM 環境変数の上書きが一番トップにきます。近代的なターミナルは TERM 変数を勝手に設定してくれるので、プログラムの設定に入る前に、間違って TERM 変数を上書きしてしまってないか確認してください (例えば、~/.bashrc
など)。TERM を手動で設定してはいけません。ターミナルに任せましょう。
ターミナルによって設定される TERM の値が気にくわない場合 (例えば 'xterm-256color' と設定して欲しいのに 'xterm' となってしまう場合)、TERM 変数を変えなくても上書きできる方法がターミナルに用意されていることがあります。
xterm や urxvt の場合、X resources で設定できます:
XTerm*termName: xterm-256color ... URxvt*termName: rxvt-unicode
Screen の場合、~/.screenrc
で設定できます:
term screen-256color
Tmux の場合、~/.tmux.conf
で設定できます:
set -g default-terminal screen-256color
Shell プロンプト
Home キーと End キーの動作不良のもう一つの原因として、カスタムシェルプロンプトの不正な変更が考えられます。シェルは PS1
環境変数に含まれるプロンプトの実際の長さを計算しようとしますが、PS1
にいくつかのエスケープシーケンス (例: 色付きテキスト) が含まれている場合、シェルはそれらを 0 ではない長さの実際の印刷可能文字であると見なすことがあります。これは明らかにテキストのレンダリングミスにつながる。
それを避けるために、PS1
では、印刷可能でないものを、shell が印刷可能でないことを理解できるように、 \[
や \]
で囲む必要があります。例えば、.bashrc
の次の行は
PS1="\e[32m\u \e[34m\w \e[37m\$ \e[0m"
これになるはずです
PS1="\[\e[32m\]\u \[\e[34m\]\w \[\e[37m\]\$ \[\e[0m\]"
詳細については Bash/プロンプトのカスタマイズ を参照してください。
Readline
コマンドラインアプリケーションはキーボード入力を読み込むために大抵 Readline ライブラリを使っています。よって、多くの場合 Readline を正しく設定すれば Home と End の問題は解決です。Readline は曖昧なキーのマッピングを /etc/inputrc
(全ユーザー共通) と ~/.inputrc
(各ユーザー個別) で管理しています。
デフォルトの /etc/inputrc
では、Home/End のエスケープコードを処理するように以下の記述がされています:
"\e[1~": beginning-of-line "\e[4~": end-of-line "\e[7~": beginning-of-line "\e[8~": end-of-line "\eOH": beginning-of-line "\eOF": end-of-line "\e[H": beginning-of-line "\e[F": end-of-line
キーが機能しない場合、おそらくターミナルが送信しているエスケープコードが上記のリストに含まれていません。まずは送信されているエスケープコードを確認してください。Readline の "quoted-insert" というコマンドを使ったり showkey --scancodes
コマンドを実行することで確認できます。quoted-insert を呼び出すデフォルトのキーバインドは Ctrl+V です。
例えば、ターミナルの中で、以下の順番でキーボードから入力を行えば:
- Ctrl+V
- Home
- Spacebar
- Ctrl+V
- End
以下のような出力が得られます:
$ ^[[1~ ^[[4~
^[
はエスケープ文字です。つまり、上記の場合、Home キーのエスケープコードは [1~
で End キーのエスケープコードは [4~
です。Readline のデフォルト設定にエスケープコードが記述されていない場合、以下のように追加してください:
"\e[1~": beginning-of-line "\e[4~": end-of-line
Readline ではエスケープ文字を表すのに \e
を使用するので注意してください。
Terminfo
Readline を使用しないプログラム (例: ncurses) については、terminfo を編集することでターミナルに送信されるエスケープコードを変更することができます。
まず既存の terminfo をファイルに保存:
infocmp $TERM >terminfo.src
そして作成されたファイルを編集してエスケープコードを変更。例えば khome と kend を変更した場合:
khome=\E[1~, kend=\E[4~,
その後新しい terminfo をコンパイル (~/.terminfo
ディレクトリに保存されます):
tic terminfo.src
最後にシェルの環境変数を使って新しい terminfo を指定:
export TERMINFO=~/.terminfo
他のアプリケーション
上記の方法で問題が解決しない場合、おそらくシステム共通の問題というよりは特定のプログラム限定の問題です。それぞれのプログラムのドキュメントを参照して対処してください。以下はよく使われているプログラムにおける修正方法です。
Lynx
Readline で使用するのと同じ quoted-insert 文字列を使ってキーバインドを追加できます。ただしエスケープ文字として \033
を使用します:
lynx.cfg
setkey "\033[1~" HOME setkey "\033[4~" END
URxvt/Rxvt
Lynx と同じフォーマットのエスケープシーケンスを使って X resources にエスケープコードのバインドを追加:
URxvt.keysym.Home: \033[1~ URxvt.keysym.End: \033[4~ URxvt.keysym.KP_Home: \033[1~ URxvt.keysym.KP_End: \033[4~
KP_Home と KP_End はテンキーの Home と End キーです。上記の設定で URxvt の中で動作するプログラム (例: Nano) の問題が解決されることもあります。
また、/etc/inputrc
に以下のセクションを追加することでも修正できます:
# those two are for rxvt "\e[7~":beginning-of-line "\e[8~":end-of-line
Zsh
terminfo データベースを使って正しいキーバインドを設定してください。
~/.zshrc
bindkey "${terminfo[khome]}" beginning-of-line bindkey "${terminfo[kend]}" end-of-line
詳しくは Zsh#キーバインド や zshwiki: bindkeys を参照。
Less
lesskey
を使って設定ファイルを作成し Readline の時と同じエスケープコードを設定してください:
$ lesskey -o .less -
#command \e[4~ goto-end \e[1~ goto-line
あるいは xterm の場合、別のエスケープコードを使う必要があります:
$ lesskey -o .less -
#command \eOF goto-end \eOH goto-line