繰り返すが、システムを直そうとする人々が混乱する主な原因は、 たいてい間違った箇所を直そうとしているからだ。正常に作動しているように 見える部分は偶然そう見えるだけなことも多いので、ある箇所が壊れていると 思って修理をすすめると、正しい設定を間違った設定に変更してしまう ことがよく起こりがちだ。
綺麗な解決法への最初のステップは、まずどの端末が異常で どれが正常かをはっきりと知ることだ。普通、端末は全てコンソールのように 振る舞うので、その場合は全体を正常にするための変更は最小で済む。 だがもしアレゲ端末 (例えばアレゲバージョンの gnome-terminal) を使っている場合は、 特殊な扱いが必要となる。
次の C の一行プログラム
void main(void) {int c; while(c = getchar()) printf("%d 0x%02X\n", c, c);} |
アレゲ端末エミュレータを使っている場合は、それらを 標準的なものと区別せねばならない。理論上はこれは可能なはずだ。 なぜなら端末データベースには異なったシーケンスを持つ端末のためのエントリが 数種類あるからだ。
ここで我々が取るアプローチは、gnome エントリを すべてのアレゲ端末に、xterm エントリをすべての 標準端末に用いる、というものである。このやり方は大抵のディストリビューションで うまくいく (5.0 以前の Red Hat のような xterm エントリがアレゲな一部例外を除く)。
だが、gnome-terminal はデフォルトで xterm と同じエントリを使用する。 よってもし一方がアレゲで、もう一方がそうでない場合、 それらを分離するための方法を探す必要がある。理論的には gnome-terminal の termname オプションでユーザは TERM 変数をより相応しい名前に 変更することが可能なはずだが、現在 gnome-terminal 1.2.1 においてこのオプションは動作しない。
ここで一つよいアイデアを。gnome-terminal は COLORTERM 変数を gnome-terminal に設定することを利用するのだ。 だから、簡単なテストをシェルの設定ファイルに追加すれば、 TERM 変数を修正することが可能だ。
次の問題は端末データベースにアレゲ端末向けの gnome エントリが存在しない可能性があることだ (これは termcap と terminfo のいくつものバージョンで起こりうる)。 最近の terminfo データベースには gnome エントリがあるはずだが、いずれにせよ gnome-terminal は基本的には xterm で、例のキー二つが違うだけだ。 だから、ちょっとした仕掛けで正しいエントリを新たに生成することは 可能なはずだ。
bash など多くのプログラムで入力行を 読むのに使用されている readline ライブラリは、 指定したシーケンスを認識するようにカスタマイズすることが可能だ。 この変更は TERM 変数によって制御することも可能なので、 一度端末の分別が済めば、より細かいチューニングをキーボードに 施すことができる。
さらに、もし less などの raw 行入力を 行うアプリケーションを正常に動作させたければ、 アレゲ端末エミュレータでは削除文字は BS であり、 DELではないのだとシェルに理解させなければならない (標準端末なら Backspace キーは既に DEL を発信しているから、何もする必要はない)。 これは stty コマンドを用いることで実現可能だ。
注意 |
これらの修正方法には幾つか欠点がある。まず、これらは特定の 端末でしか機能しない。また、理論上 (実際に起こることは稀なのだが) これらは他の端末の readline ライブラリを 混乱させる可能性がある。 もっとも、これらの制限はほとんどの場合は問題にならない。 |
まず infocmp gnome として、既に gnome エントリが terminfo データベースに 存在しているかどうかを確認する (termcap は後で修正する)。エントリが存在しなければ、以下のコマンド
bash$ tic <(infocmp xterm |\ sed 's/xterm|/gnome|/' |\ sed 's/kbs=\\177,/kbs=^H,/' |\ sed 's/kdch1=\\E\[3~,/kdch1=\\177,/') |
次に以下の一行を ~/.inputrc [1] に追加する。
"\e[3~": delete-char |
$if term=gnome DEL: delete-char $endif |
TERM 変数が正しく設定されていれば、 条件付き割り当てを使うことでアレゲ端末を正しく動作させることは可能だ。 これを確かめるにはいくつもの方法がある。まず gnome-terminal での TERM 変数の デフォルト値は xterm だから、もしアレゲ端末が 存在しないければ、我々は何もしないでよい。だが、もし xterm をデフォルトにしているアレゲ端末が存在する場合、TERM 変数を 正しく設定する方法を見つけなければならない - gnome-terminal がこれに当てはまるとしよう。
もっとも簡単に TERM 変数の設定を行うには、 gnome-terminal を --termname=gnome 引数付きで起動すればよい。これは GNOME パネル上のラウンチャーに正しいコマンドラインを 設定することなどで可能だ。もし古いバージョンを使っている場合、 この方法は動作しないかもしれない。その場合以下の数行を
if [ "$COLORTERM" = "gnome-terminal" ] then export TERM=gnome fi |
注意: 端末を gnome に設定すると、 ls は色表示を行わなくなる。 多くのバージョンの ls は gnome-terminal の色特性を知らないためだ。 これを避けるには、 ~/.dircolors 設定ファイルを dircolors --print-database >~/.dircolors として作成し、 設定ファイルに TERM=gnome という一行を追加すればよい。
アレゲな端末エミュレータ向けの termcap エントリを動的に作成させることもできる。以下に手順を説明する。 いつものように、 ~/.bashrc に追加する:
if [ "$TERM" = "gnome" ] then export TERMCAP=$(infocmp -C gnome | grep -v '^#' | \ tr '\n\t' ' ' | sed 's/\\ //g' | sed s/::/:/g) fi |
最後に、削除キーにより生成される文字を端末デバイスに 教えてやらねばならない。削除キーは通常バックスペースであると期待されているために、 標準的な端末エミュレータではこれは DEL 文字になる。 だからまずそのようにセットしてから、各アレゲ端末用の条件文を追加していく。 いつも通り ~/.bashrc に追加する:
stty erase ^? if [ "$TERM" = "gnome" ] then stty erase ^H fi |
注意: 一部のディストリビューションは、既にこの修正をシステムワイドな /etc/inputrc 設定ファイルなどに施していることがある。 この場合 ~/.inputrc から不要になった行を 削除することもできる。
tcsh の場合、修正は全部 ~/.tcshrc に施す必要がある。 以下のように bash の場合と似ている -
bindkey "^[[3~" delete-char if ($?COLORTERM) then if ($COLORTERM == "gnome-terminal") then setenv TERM gnome endif endif stty erase ^? if ($?TERM) then if ($TERM == "gnome") then setenv TERMCAP \ "`infocmp -C gnome | grep -v '^#' | tr '\n\t' ' ' | sed 's/\\ //g' | sed s/::/:/g`" bindkey "\177" delete-char stty erase ^H endif endif |
[1] | 古いバージョンの bash では、 INPUTRC を正しく設定する必要があることを覚えておこう。 例えば
| |
[2] | より正確には、ログインシェルだけでなく全てのシェルに読み込まれる シェル設定ファイルに、だ。どれが正しいファイルかは、 bash のスタートアップシーケンスに依存する。 |