XやWindowsやCocoa上のEmacsでは、Control+ReturnだろうがControl+,だろうがCtrl+Shift+Spaceだろうが、好きな機能を割り当てることができる。これらのGUI環境ではアプリケーションが検出できる修飾キーの組合せに制約がほとんどないためだ。
ところが、ターミナル(エミュレータ)上では原則として一つのキー入力は一つのASCIIコードとしてアプリケーションに渡されるため、上記のように対応するASCIIコードのないキーの組合せはEmacsなどでそれとして認識することができない。Meta+XをEscape Xの二ストロークに置換する仕掛けがせいぜいだ。
…と思いきや、実はEmacsにはいわゆるスティッキー修飾キーに相当するevent-apply-*-modifierというギミック的関数が用意されており、たとえばC-x @ c(event-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のような組合せはすんなりとはいかない。CとS-SPCに分解してみても、依然としてS-SPCにはASCIIコードがないのだ。CとSとSPCに分解しようと思っても、event-apply-*-modifierは直後の一ストロークに作用するので、C-x @ c C-x @ s SPCのC-x @ cの効用は直後のC-xに食われ、そこで連鎖が終了してしまう。ならばとSとC-SPCに分解してみても、C-SPCはASCIIコードでは00すなわちC-@であるため、C-S-@という組合せになってC-S-SPCとは認識されない。(ところでinput-decode-mapやkey-translation-mapを使う別解もあるが、ここでは詳しくは触れない)
解決策としては、「スティッキーControl+Shiftキー」を自作すれば良い。つまり、こんな関数を作り:
|
1 2 3 4 5 6 7 |
(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-%などというターミナル住民にとっては鬼畜なキーに割り当てられているわけだが、これも次のような関数を作り:
|
1 2 3 4 5 6 7 |
(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に機能を割り当てるには
|
1 |
bindkey '^X@c^M' accept-line |
でOK。(上記はC-RETをRETと同じにする設定)