トップ «前の日記(2005-01-12 (Wed)) 最新 次の日記(2005-01-23 (Sun))» 編集 RSS feed

継続にっき

2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
2009|01|05|12|
2010|04|05|11|
2011|01|09|12|
2012|02|03|05|09|12|
2013|02|03|
2014|05|09|
2015|12|
2017|09|

2005-01-15 (Sat)

))) Emacs with PuTTYにおいてC-/でundoするには

現在のPuTTYはC-/(slash)がC-_として送られている。このために日常使っているC-/でundo、 C-_でredoという使い分けが出来ないので何とかならないかやってみた。

そもそもなぜC-/がデフォルトで送られないのかというと、C-/に対応するASCIIコードというものが存在しないからだ *1。 そういうわけでC-/を送るというプロセスはF1やHomeなんかを送ることに近いものになる。つまり当初の目的を実現するには C-/を押すことでC-_でなくC-/を表すエスケープシーケンスを送るようPuTTYをいじればよい。

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-/はどうやっても表現できないという結論になる。

Emacs

と、あきらめるのはまだ早い。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-/])

2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
2009|01|05|12|
2010|04|05|11|
2011|01|09|12|
2012|02|03|05|09|12|
2013|02|03|
2014|05|09|
2015|12|
2017|09|
トップ «前の日記(2005-01-12 (Wed)) 最新 次の日記(2005-01-23 (Sun))» 編集 RSS feed