前回
コマンドラインで文字化けしてたのは\M-c
を.inputrc
で設定してたからだ、
という話を書きましたが、
ついでにメタキーやらエスケープ入力やらを少し調べたので
まとめておきたいと思います。
- MacのiTerm(ターミナル)でのメタキー、エスケープシーケンスの設定
- メタプレフィックスとエスケープシーケンス、それから
Alt
キー - Emacsでのキーバインド
- Happy Hacking Keyboardのメタキー?
MacのiTerm(ターミナル)でのメタキー、エスケープシーケンスの設定
まず、Macの場合ちょっと特殊なので、iTerm(ここではiTerm2)等で メタキープレフィックス状態やエスケープシーケンスを送る方法をまとめておきます。
iTerm(ターミナル.appでも一緒) ではCommandキー(⌘)との同時押しはターミナルに直接送られないで、 アプリケーションのショートカットとなるので ⌘+f はサーチウィンドウが開いてしまいます。
これに対処するにはいくつか方法がありますが、 まずはiTerm自体でキー直接送るよう、設定をする方法があります。
Preferences
Profiles
Keys
の項目で、上の図の様に
⌘+f
に対して
Send Escape Sequence
+f
と言う様に設定します。
これで⌘+f
を押すとESC fが送らる様になるので
コマンドライン上で1単語進める様になります。
ターミナル.appでも
環境設定
設定
キーボード
に
同じ様な設定項目があるので、同様に設定出来ます。
また、上の図の下の方を見るとOption(⌥)の設定が
Normal
、Meta
、+Esc
のうちから選べる様になっているので、
Meta
を選べばメタキー、+Esc
を選べば入力キーと共にエスケープシーケンス
(上のCommandに対するのと同様の働き)、
として働かす事が出来ます。
また、もしKeyRemap4MacBook1 を使っているなら下のような設定を入れておけば直接 ⌘+∗ をESC ∗ に置き換えてやることもできます。 (沢山入れたい時はこちらの方が楽。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
メタプレフィックスとエスケープシーケンス、それからAlt
キー
前置きが長くなりましたが、本題へ。
そもそもメタプレフィックス(\M-
、メタキーと同時押し)と
エスケープシーケンス(\e
、ESCを押して一旦離して次のキーを押す)
が全く一緒だと思ってたんですが
基本的には区別されます。
以下に行く前に取り敢えず前回の設定の
set convert-meta off
set input-meta on
set output-meta on
は設定してあることを前提とします。(convert-meta
はすぐに変えますが。)
convert-meta
がon
の場合
前回で設定したconvert-meta
がoff
でなくon
になっていると
メタキープレフィックスがエスケープシーケンスと区別されなくなります。
これは、まず
- メタキーが8bit目を1にするためのキーであること。
一方
convert-meta
がon
である場合、8bit目が1のキー入力が来た時は 8bit目を落として、ESC
を先に1回押した状態、と同じにする。- さらにこのような
ESC+*
の状態をメタキープレフィックス状態と同値とみなす様になる。
ということから結果的に\M-f
と\ef
の様なキーを全く同一とみなす様になります。
(この辺理解がちょっと怪しい…)
実際にset convert-meta on
と.inputrc
で設定した場合、
まず、bind -p
等とすると設定されている項目は\C-
等Control関係のものなどのものに混じって
\M-f
等、メタキープレフィックスな状態だけが表示されます。
MacのiTerm上では、
⌘+f、
⌥+f
(これらについては上にあるように設定してあるとします)、
及びESCf
は全て初期設定の1単語進む(forward-word
)、の動きをします。
Windows/Linuxでも
Altf、
ESCf
が同様に動作します。
ここで、
$ bind '"\ef":backward-word'
としても
$ bind '"\M-f":backward-word'
としても、いずれの場合でも全てのキーが1単語戻る、の動作をするように変更されます。
また、bind -p|grep backward-word
で確認すると、上記両方共設定した場合でも
$ bind '"\M-f":backward-word'
$ bind '"\ef":backward-word'
$ `bind -p|grep backward`
"\M-f": backward-word
の様に\M-f
しか表示されません。試しに違う設定を入れてみれば
$ bind '"\M-f":backward-char'
$ bind '"\ef":backward-word'
$ `bind -p|grep backward`
"\M-f": backward-word
$ bind '"\ef":backward-word'
$ bind '"\M-f":backward-char'
$ `bind -p|grep backward`
"\M-f": backward-char
の様に\ef
、\M-f
のいずれか後で設定した物がbindの\M-f
の結果として
表示される事が分かります(上の表示は必要ない出力は省いています。)。
convert-meta
がoff
の場合
convert-meta
がoff
の場合、\M-f
とESC f
は区別されます。
まず、bind -p
などとすると\e
の項目だけで\M-
となっているものはありません。
ここでキーを試して見ると、Macでの
⌘+f、
ESCf、
また
Windows/Linuxでの
Altf、
ESCf
は1単語進む(forward-word
)、の動きをします。
一方、Macでメタキーとして設定した
⌥+f
だけは
forward-word
の動きはせず文字化けしたものを表示したりします。
従ってメタキープレフィックスな状態とエスケープシーケンスが区別されていて、
さらにAlt
キーはメタキーとしてではなく、エスケープシーケンスを作る様に
働く事が分かります。
Alt
についてはCygwinやらLinuxでのxterm等で試しましたが、
試した限りでは全てエスケープシーケンス的に動いています。
(ここが意外だった所。ターミナルやその他の環境によって
もしかしたら違うのかもしれません。)
次に、bindでキー変更してみると、
$ bind '"\ef":backward-word'
とした場合は⌥+f以外のキーが
$ bind '"\M-f":backward-word'
とした場合は⌥+fだけが変更されます。
bind -P
とすると
$ bind -P |grep backword-word
"\eb": backward-word
"\ef": backward-word
"*": backward-word
の様な感じで、最後の文字化け(*としてある)部分が\M-f
です。
(文字化け部分はfのコード(01100110)の8bit目が1になったもの。)
input-meta
/output-meta
について
input-meta
がoff
の場合、端末がサポートして居ない場合、
8bit目を落とします。on
だと端末の状況関係なく8bit目も受け入れます。
手元の環境ではこの設定はoff
にしても影響が出るものはありませんでした。
この値は古くはmeta-flag
と言う名前で定義されていましたが、
この名前は現在はinput-meta
と同義で、
input-meta
で定義してもbind -v
等で見るとき等はinput-meta
の値として反映されます。
output-meta
はon
の時には出力時に8bit目が1の入力を直接表示し、
off
の時はメタプレフィックスエスケープシーケンスとして表示します。
output-meta
をoff
にしてさらにconvert-meta
をoff
にした状態で
⌘+f
を打つと\346
と表示され、
これは11100110(fのコードの8bit目を1にしたもの)の8進法表示になってる
事が確認出来ます。(メタキーが8bit目を1にしたことを確認出来る。)
Emacsでのキーバインド
Emacsにおいては少なくとも初期設定のままでは エスケープシーケンスのみが有効でメタキーは効きませんでした。
キーバインドで
(define-key global-map "\M-f" 'backward-word)
と書こうが、
(define-key global-map "\ef" 'backward-word)
と書こうが⌘+f
は1単語戻る、になりましたが、
⌥+f
は何故かA
を出力するだけでした
2。
Happy Hacking Keyboardのメタキー?
HHKにはモードを変更してスペースの両端にあるキーを変更できたりするんですが、 両端にあるダイヤモンド型のマークの有るキーが Wikipediaの メタキーのページ で紹介されているので違いがあるかな、と思ったんですが、 このキーは何も機能しない様でした。
HHKモード
にして、キー自体が送られていることはyamyの
スキャンコードの機能で確かめました。
コード自体は以前も調べたのですが、左右がそれぞれ0x7b
、0x79
です。
これらは日本語配列キーボードの無変換、変換に当たるキーコードなので、
この部分だけは日本語配列と同じ
Alt-無変換-Space-変換
Alt
の状態になっているわけですね。
というわけで、未だメタキーを直接送れるキーボードがあるかどうか自体が謎。 (WikiのAltの歴史 なんかを見てもメタキーの存在はもう無い感じですかね…?)
-
現在は Karabiner-Elements に名前が変わっています。 ↩
.emacs
を数年ぶりにいじる上、昔の設定を消していたのでどうやるか 分からなくて調べた… ↩