前回
コマンドラインで文字化けしてたのは\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を数年ぶりにいじる上、昔の設定を消していたのでどうやるか 分からなくて調べた… ↩
