zshでGnu screen実行中のHome/Endキーの割り当てがおかしい
以前書いた「zshでHome/End/Delキーを設定 」でzsh上でのHome/End/Delキーの動作を設定した。しかし、zsh上でgnu screenコマンドを実行するとこれがうまく反映されていなかった。zsh上でgnu screenコマンドを実行しているとHomeキーやEndキー、Delキーを入力するとすべてチルダ(~)になってしまった。原因は次の2つだった。
- gnu screenコマンドの起動時に.zshenvファイルを実行するため。
- screen実行中のキーの割り当ての変化のため。
前者について説明する。以前書いた記事の設定は.zshrcに書いていたのだが、どうやらgnu screenの起動時には.zshrcは読み込まれず、.zshenvのみが読み込まれるようだった。
後者について説明する。OSや端末が変わることによってどうやらキーボードからの入力と端末によって内部で割り当てられている制御文字コードが変化しているようだった。制御文字とはタブだとかビープ音だとか改行・改ページといった制御にかかる文字を表すコードらしい。制御文字コードとキーの一覧(全部は網羅していない)は例えば以下のサイトで見れる。
制御コード表: http://ash.jp/code/ctrltbl.htm
そこで、端末によって制御文字コードがどのように対応付けられているのか調査した。
調査環境: 調査とした環境は以下の2種類。
- Cygwin
- Linux (CentOS 6系統)
それぞれの環境でshellをbash, tcsh, zshの3通りでGnu screen実行/未実行で対応がどうなっているか調べた。
調査方法
- 端末からC-vかC-q(Ctrlキーを押しながらvかq)を入力すると次に入力する文字が文字コードがそのまま文字として入力されることを利用する。C-vキーを入力した後に以下のキーをそれぞれ入力して表示される文字を確認してキーと実際に割り当てられている制御文字コードの対応を見た。
対象キー: 調査したキーは以下の6つ。
- Home
- End
- PageUp
- PageDown
- BackSpace
- Del
結果: 調査結果を以下の表にまとめた。
$OSTYPE $TERM Home End PageUp PageDown BackSpace Del cygwin xterm ^[[H ^[[F ^[[5~ ^[[6~ ^? ^[[3~ linux xterm ^[OH ^[OF cygwin, linux screen ^[[1~ ^[[4~
概説
制御文字コードの割り当ては、使用しているshell(bash, tcsh, zsh)に依存せず大きく以下の3つに環境に依存することがわかった。
- Cygwin
- Linux
- Gnu screen起動中
PageUp, PageDown, BackSpace, Delキーは上記3環境で共通の制御文字コードだった。また、Home、Endキーのみが環境によって割り当てが変化していることがわかった。
対処
以上の調査で環境ごとに割り当てられる文字コードがわかったので、これをキーバインドに対応させて改善する。以下のようにキーバインドを記述してどの環境でもHome End PaUp PgDn BS Delキーが正常に動作するように設定する(ただし、PgUpとPgDnは適切な割り当てが思いつかなかったので割り当てていない)。なお、以下の内容は.zshenvに記入すること。.zshrcに記入してもどうやらgnu screenの起動時には読み込まれないので注意。
#bindkey "^[[5~" # PageUp #bindkey "^[[6~" # PageDown bindkey "^[[3~" delete-char ## Home and End key mapping # for cygwin bindkey "^[[H" beginning-of-line bindkey "^[[F" end-of-line # for linux bindkey "^[OH" beginning-of-line bindkey "^[OF" end-of-line # for screen bindkey "^[[1~" beginning-of-line bindkey "^[[4~" end-of-line
以前書いた「zshでHome/End/Delキーを設定 」の設定でなくこちらの設定のほうがわかりやすくてよいと思う。
bash環境ではgnu screenを使っても、同じ文字コードではあるがHomeやEndキーに何も問題がなかった(きちんと機能割り当てられていた)のでzsh固有の問題だと思う。
冒頭で挙げた以下の最初の問題の解決策があった。
* gnu screenコマンドの起動時に.zshenvファイル を実行するため。
以下のコマンドを~/.screenrcに追記すればよい。
shell “zsh”
これによりscreenの起動時に自動的にzshを新しく起動する。そのため,~/.zshrcの設定も反映される。
Linuxの標準のshellはbashであることが多い。これを変更するには管理者権限が必要で外部のPCで作業するときはできないことがある。そのため,ログインシェルはbashにしておき,そこからzsh on GNU screenを起動するのが汎用的であり安全だと思う。