現在のPuTTYはC-/(slash)がC-_として送られている。このために日常使っているC-/でundo、 C-_でredoという使い分けが出来ないので何とかならないかやってみた。
そもそもなぜC-/がデフォルトで送られないのかというと、C-/に対応するASCIIコードというものが存在しないからだ *1。 そういうわけでC-/を送るというプロセスはF1やHomeなんかを送ることに近いものになる。つまり当初の目的を実現するには C-/を押すことでC-_でなくC-/を表すエスケープシーケンスを送るようPuTTYをいじればよい。
まずはPuTTYをビルドするところまで持って行く必要があるが、PuTTY ごった煮版にビルドの仕方があるのでパッチと合わせてありがたく頂戴する。 これで最低限の準備は完了。いかにも、な感じがするwindow.cから読んでみる。
Windowsプログラミングはほとんど分からないものの、キー入力を処理していそうなところを探してみると
// window.c 2616 case WM_KEYDOWN: 2617 case WM_SYSKEYDOWN: 2618 case WM_KEYUP: 2619 case WM_SYSKEYUP: 2645 len = TranslateKey(message, wParam, lParam, buf);
というのが見つかるのでこいつをキーワードにぐぐってみると Re: emacsのキーバンド設定につい てというものがヒット。
これらを割り当てるには WINDOW.C の TranslateKey() あたりに手 をいれる必要があると思います。
私は C-@ とか C-/ などが使えなくて困ったのでちょっと手をいれ ました。
残念ながらこれ以上の情報はなかったが方向としてはこれでよいっぽいな。
ここでTranslateKeyをすらすら読めるだけの知識があればよいのだが、あいにくそのようなものは持ち合わせていないので どうしようかしばし考える。'/'とか47とか0x2fとかで検索してはみるものの該当なし。こういうときはドキュメントから攻めるべし、というわけで再び情報を集め始めたらありましたよ。PuTTYの公式サイトのWishlistよりCtrl+/ should send the same as Ctrl+_。「fixed-in: 2003-01-14」なのでその時に何が行われたかを見れば良いはず。
$ svn log svn://ixion.tartarus.org/main/putty ------------------------------------------------------------------------ r2576 | owen | 2003-01-14 00:06:56 +0900 (Tue, 14 Jan 2003) | 2 lines Make ^/ do the same as ^_ (wish control-slash) ------------------------------------------------------------------------ $ svn di -r2575:2576 svn://ixion.tartarus.org/main/putty Index: window.c =================================================================== --- window.c (revision 2575) +++ window.c (revision 2576) @@ -3488,7 +3488,7 @@ *p++ = "\000\033\034\035\036\037\177"[wParam - '2']; return p - output; } - if (shift_state == 2 && wParam == 0xBD) { + if (shift_state == 2 && (wParam == 0xBD || wParam == 0xBF)) { *p++ = 0x1F; return p - output; }
これ以上ないほど明快だ。この前後を見ればTranslateKeyはpに出力したいコードを書き込んでその長さを返せば良いことが分かるので、結局次のようなコードを適当に加えればC-/を押したときに任意のコードが送れることになる。
if (shift_state == 2 && wParam == 0xBF) { p += sprintf((char *) p, "code"); return p - output; }
問題は何を送るか、だ。
ここでの話のキモは端末機能データベースであるterminfoだ。terminfoの概略についてはいろいろなところで読めるので ここでは省くが、それを踏まえた上でもう一歩進もうとすると結構詰まる。自分の場合はscreenのtermcapinfoの意味を 調べようとして苦労した記憶がある。
といったものを見れば、どういう形で端末上でエスケープシーケンスが処理されていくのかを追うことが出来るようになる。 例えばF1に着目すると
$ man 5 terminfo Variable Cap‐ TCap Description String name Code key_f1 kf1 k1 F1 function key $ infocmp xterm kf1=\EOP, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~,
見つかった\EOPの根拠は、Xterm Control Sequencesから探せば
Key Numeric Application Terminfo Termcap -------------------------------------------------------------- PF1 SS3 P SS3 P kf1 k1 ESC O Single Shift Select of G3 Character Set (SS3: 0x8f): affects next character only
となっていることが分かる。bash上でC-v F1すれば実際にこのコードを送っていることも確認できる。
同じ流れで「C-/を表すもの」を探すと見つからない。つまりC-/はどうやっても表現できないという結論になる。
と、あきらめるのはまだ早い。C-/が使いたいのはあくまでEmacs上に限った話で、それならばEmacsが 適当なエスケープシーケンスをC-/として理解してくれるようになってくれれば問題ないはず。そしてそれに対する答えが これ。
lisp/term/iris-ansi.el:219:(define-key function-key-map "\e[112q" [?\C-/]) lisp/term/iris-ansi.el:271:(define-key function-key-map "\e[179q" [?\C-/])