web-dev-qa-db-ja.com

ターミナルで実行されているEmacsがCtrl +を区別できないのはなぜですか。 「;」から?

この質問は私の emacsベータに関する前の質問 から生じました。要するに、ターミナルのEmacs関数にC-;をバインドしたいのですが、Emacsに到達する前に何かがこのキーをキャプチャしているようです。Emacsは;を押したと思っています。

明らかな容疑者はターミナルエミュレータですが、私はそれらの多く(xterm、gnome-terminal、terminator、terminology)をチェックしましたが、どれも機能しません。おそらく私はウィンドウマネージャーを除外することができます。なぜなら、GUIバージョンのEmacsでは、キーC-;は問題なく機能するからです。 bashとzshの2つの異なるシェルも試しましたが、やはり成功しませんでした。

他に何を試すことができますか?

おそらくあなたの混乱は実際の端末を使用しなかったことから生じます。本格的なコンピューターがいくつかの直立した冷蔵庫のサイズであったとき、端末は文字と文字のみを使用してシリアルケーブルを介して中央コンピューターと通信していました。文字は、いくつかの標準化された文字セットの一部でした。 ASCIIまたはEBCDIC、ただし通常はASCII。ASCIIには33の制御文字があり、端末オペレーターは特別なキー(DELなど)を押すか、を押してそれらを送信します。 Ctrlキーを押しながら別のキーを押すと、中央コンピューターは結果の制御文字のみを認識し、文字を生成するためにどのキーが押されたかを認識しませんでした。

Xtermなどのターミナルエミュレーションプログラムは、その動作を模倣します。ターミナルエミュレータは、33個すべてのASCII制御文字を送信する方法を提供し、Emacsはそれらが送信されるとそれらの文字を受信します。しかし、Emacsは上記の説明の中央コンピュータのようなものです---それはありませんターミナルエミュレータで実行したときに実際に押されたキーを知る方法。したがって、CTRLとセミコロンを押すと、ターミナルエミュレーションプログラムがそれらのキーの押下をいくつかのASCII文字にマップしない限り、Emacsは何かが入力されたことを知りません。

ターミナルエミュレータは通常、次のマッピングを使用して制御文字を生成します

キーを押すASCII 
 -------------------- 
 ESCAPE 27 
 DELETE 127 
 BACKSPACE 8 
 CTRL + SPACE 0 
 CTRL + @ 0 
 CTRL + A 1 
 CTRL + B 2 
 CTRL + C 3 
 etc ... 
 CTRL + X 24 
 CTRL + Y 25 
 CTRL + Z 26 
 CTRL + [27 
 CTRL +\28 
 CTRL +] 29 
 CTRL + ^ 30 
 CTRL + _ 31 

CTRL +に注意してください。そのリストには表示されません。 CTRL + keyが制御文字にマップされていない場合、端末は通常、keyに割り当てられた印刷可能な文字を送信するだけです。つまり、ターミナルエミュレータが送信することで何を伝えているのか。単独では、CTRL +;を押したときに何をすべきかわからないということです。

これはすべて、端末または端末エミュレーションプログラムを使用している場合にのみ適用されます。一部のウィンドウシステムでネイティブアプリケーションとしてEmacsを実行している場合、Emacsは文字だけでなくキーストロークイベントに完全にアクセスできます。したがって、Emacsは、Ctrlキーとセミコロンを同時に押したことを確認し、そのキーストロークペアにアクションを割り当てることができます。

多くの場合、端末にはファンクションキーと矢印キーがあり、制御文字を含む文字のシーケンスも生成します。これらのシーケンスは通常、ASCIIコード27(ESCAPE)で始まります。

11
Kyle Jones

端末は、キーではなく文字(より正確にはバイト)を送信します。キーまたは次のようなキーコードを押すと Ctrl+;、この情報はバイトのシーケンスにエンコードする必要があります。のようなキャラクターを表すキーコード A または Shift+A または À、はその文字として送信されます:aAà(最後の1つは端末の文字エンコードに応じて1バイトまたは2バイトです)。

ファンクションキーを含むキーコードには対応する文字がないため、エスケープシーケンスとして送信されます。エスケープ文字で始まるバイトのシーケンス(Emacs文字列では\e、文字通りに入力された場合はシアン^[として表示されます)バッファ)。いくつかのファンクションキーには、対応するバイトがあります 制御文字

キーコード Ctrl+; 標準のエスケープシーケンスがないため、ほとんどのターミナルエミュレータは文字;を生成します。これにより、 Ctrl 修飾子が押されました。

のバインディングを定義するため Ctrl+;、別のエスケープシーケンスを送信するようにターミナルエミュレータを構成する必要があります。 Gnomeターミナルでこれを行うことはできないと思います(Gnomeが構成できることはめったにありません)。 Xtermでそれを行うことができます。手順については、 すべてのキーの組み合わせを処理できるLinux端末はありますか? を参照してください。

ターミナルで実行できるシェルは関係ありません。 GUI(X11)は、単なる文字のシーケンスとしてではなく、キーと修飾子をエンコードする形式で入力イベントを送信するため、GUIEmacsは問題ありません。

入力がキーボードからアプリケーションにどのように届くかについてのより詳細な背景については、 キーボード入力とテキスト出力はどのように機能しますか? を参照してください。