XやWindowsやCocoa上のEmacsでは、Control+ReturnだろうがControl+,だろうがCtrl+Shift+Spaceだろうが、好きな機能を割り当てることができる。これらのGUI環境ではアプリケーションが検出できる修飾キーの組合せに制約がほとんどないためだ。

ところが、ターミナル(エミュレータ)上では原則として一つのキー入力は一つのASCIIコードとしてアプリケーションに渡されるため、上記のように対応するASCIIコードのないキーの組合せはEmacsなどでそれとして認識することができない。Meta+XEscape Xの二ストロークに置換する仕掛けがせいぜいだ。

…と思いきや、実はEmacsにはいわゆるスティッキー修飾キーに相当するevent-apply-*-modifierというギミック的関数が用意されており、たとえばC-x @ cevent-apply-control-modifier)と押してからRETを押すと、C-RETを押したのと同じことになる。つまり、たとえばiTermであればPreferences→Keys→Global Shortcut Keysで+を押し、

Shortcut Keyboard: ^↩
Action: Send Hex Code
18 40 63 0d

のように設定すれば、EmacsでC-RETが効くようになる。もちろん、「18 40 63 0d」とはC-x @ c RETをASCIIコードに置き換えたものだ。C-,なども同様に設定すればいい。

ところが、C-S-SPCのような組合せはすんなりとはいかない。CS-SPCに分解してみても、依然としてS-SPCにはASCIIコードがないのだ。CSSPCに分解しようと思っても、event-apply-*-modifierは直後の一ストロークに作用するので、C-x @ c C-x @ s SPCC-x @ cの効用は直後のC-xに食われ、そこで連鎖が終了してしまう。ならばとSC-SPCに分解してみても、C-SPCはASCIIコードでは00すなわちC-@であるため、C-S-@という組合せになってC-S-SPCとは認識されない。(ところでinput-decode-mapkey-translation-mapを使う別解もあるが、ここでは詳しくは触れない)

解決策としては、「スティッキーControl+Shiftキー」を自作すれば良い。つまり、こんな関数を作り:

(defun event-apply-control-shift-modifier (ignore-prompt)
  "\\Add the Control+Shift modifier to the following event.
For example, type \\[event-apply-control-shift-modifier] SPC to enter Control-Shift-SPC."
  (vector (event-apply-modifier
           (event-apply-modifier (read-event) 'shift 25 "S-")
           'control 26 "C-")))
(define-key function-key-map (kbd "C-x @ C") 'event-apply-control-shift-modifier)

次のような設定を加える。

Shortcut Keyboard: ^⇧Space
Action: Send Hex Code
18 40 43 20

同様に、たくさん使いたいquery-replace-regexp(正規表現による文字列置換)はEmacsの標準ではC-M-%などというターミナル住民にとっては鬼畜なキーに割り当てられているわけだが、これも次のような関数を作り:

(defun event-apply-meta-control-modifier (ignore-prompt)
  "\\Add the Meta-Control modifier to the following event.
For example, type \\[event-apply-meta-control-modifier] % to enter Meta-Control-%."
  (vector (event-apply-modifier
           (event-apply-modifier (read-event) 'control 26 "C-")
           'meta 27 "M-")))
(define-key function-key-map (kbd "C-x @ M") 'event-apply-meta-control-modifier)

下のようなキー設定を加えれば良い。

Shortcut Keyboard: ^⌥⇧%
Action: Send Hex Code
18 40 4d 25

世の中、カビくさい道具であってもやりようはあるもんです。どんなところでも、妥協せずに使えるものを何でも使って自らを足らしむる。それがハック。

追記:zshもマルチストロークのキーバインディングに対応しているので、たとえば上記のように設定したC-RETに機能を割り当てるには

bindkey '^X@c^M' accept-line

でOK。(上記はC-RETRETと同じにする設定)

Tags :
Categories : Tech