Bashシェルを使用するとき(マウスを使用する代わりに)Shift+を使用して入力したコマンドを強調表示してコピーしてみました。LEFTところでCをたくさん受けました。後で、私はShift+UPが作成しA
、Shift+DOWNが作成しB
、Shift+RIGHTも作成することに気づきましたD
。
なぜこれが起こるのですか?
^[[A
生のキー入力データ(、、、^[[B
および^[[C
)から来たと思いましたが、大文字にすぎません^[[D
(^[[
最初は何もありません)。
答え1
これは1980年代にさかのぼるキーボード入力プロトコルであり、シェルはいいえM. Vazquez-Abramsの答えが示すように、「ターミナルドライバ」(何でも)は正しく処理されません。さらに、これは完全に有効な制御シーケンスです。
背景
端末は、ファンクションキーと拡張キーの制御シーケンスを発行します。 CSIが導入した制御シーケンスであるDECFNK制御シーケンス、CSIが導入した3番目のタイプのシーケンスであるSCOコンソールファンクションキー制御シーケンスであるLinuxファンクションキー制御シーケンスを実行できます。 ; Shift SS3が前に付ける単一文字、またはこの例のようなさまざまな項目のECMA-48標準シーケンス。
(SS3 と CSI は C1 の範囲の制御文字です.Single Shift 3 と制御シーケンスリーダーです.)
IBM Model M などのキーボードには、電卓キーボードとカーソルキーボードの 2 つの特定のキーボードがあります。 DEC VTスタイルのターミナルエミュレータ(カーネル内のターミナルエミュレータからunicode-rxvtまでアクセス可能なほとんどのターミナルエミュレータ)は、両方のキーボードが個別に切り替え可能なアプリケーション/一般モデルを持つモデルに従います。フルスクリーンTUIアプリケーション、libeditまたはGNU readlineライブラリ(またはZLE)(シェルなど)を使用するアプリケーション、および他の種類のアプリケーションは、目的のモードを指定してバースト番号を読み取り、端末から制御シーケンス文字を受け取ります。人間は端末と同じくらい速く完全なECMA-48制御シーケンスを入力できないか、端末エミュレータが制御シーケンスを送信する可能性があるため、すべての偶発的な状況は、ユーザーキー入力とEsc␛文字で始まる制御シーケンスを送信する端末エミュレータとの違いです。
- アプリケーションモードでは、キーボードの各矢印キーは、SS3というプレフィックスが付いた移動した単一文字を生成します。 ECMA-35とECMA-48は単一の後続の文字でのみ機能するようにSS2とSS3を定義するため、修飾子は実際には何の効果も持てません(XTermは問題を引き起こしますが)。ただし、電卓とカーソルキーボードは異なるSS3移動文字を生成するため、2つのキーボードを区別できます。
- 通常モードでは、キーボードの各矢印キーは次のように生成します。同じCSIによって導入された制御シーケンスはECMA-48から来ました。DEC VTによって強化。特にカーソルキーは、ECMA-48制御シーケンスCUU、CUD、CUR、およびCUL(CUrsor Up、CUrsor Down、CUrsor Right、およびCUrsor Left)を送信します。 ECMA-48制御シーケンスに対するDECの機能強化は、制御シーケンスが現在の修飾子状態を含むことである。
したがって、どの修飾子キーが押されたかはわかりませんが、2つの左矢印キーを区別できるアプリケーションモードと2つの矢印キーの違いは不明ですが、どの修飾子キーが押されたかを知るための通常モードから選択できます。 。押しました。
さらに詳しく説明すると、ECMA-48制御シーケンスのDEC改善点は、制御シーケンスに2つのパラメータがあることです。
- ECMA-48によると、最初のパラメータは、CUU、CUD、CUR、またはCULが実際に持つことができる最初のパラメータと似ています。発生回数なので常に1
- 2番目のパラメータは興味深いです。これには、さまざまな修飾キーのビットフラグセットに1を加えた10進数でエンコードされた修飾キーの状態が含まれます。
これがDEC VT Terminalが1980年代からやってきたことです。近年、いくつかの端末エミュレータがついに同じ機能を導入しました。前述のように、XTermはこの機能をかなり誤って実行します。
どうやって過ごすの?
問題は、GNU readlineライブラリ、libedit、ZLEなどにあります。実際にプロトコルを正しく処理しない。彼らに完全に責任があるわけではありません。彼らはtermcapとterminfoシステムに依存しますが、これはここでの作業には適していません。 termcapとterminfoには、実際には入力制御シーケンスの概念はありません。異なる場合があります、マルチモードキーボードは言うまでもありません。
:help xterm-modifier-keys
これを行うには、上記のプロトコル(Vimを参照)に従って制御シーケンスを指定するためにterminfoを特別にオーバーライドしてプログラムできるVimや、以下を使用するNeoVIMなどのツールを見つける必要があります。Paul EvansのlibtermkeyそしてそのCSIドライバ。 libtermkey用のCSIドライバは、DEC VTなどの端末エミュレータのキーボード入力を正しく処理する方法です。制御シーケンスを正しく復号する実際のECMA-48ステートマシンパーサー。
しかし、シェルが行うことは、terminfoで矢印キーエントリを見つけることです。対応する特定の制御シーケンスのみ一致。
具体的には:
kcub1
シェルはterminfoレコードで端末機能を探しています。これはから来たものですteken
記録、例えば:% tput -T teken kcub1|hexdump -C 00000000 1b 5b 44 |.[D| 00000003 %
- これはただ対応する特定の入力シーケンスを← Left Arrow。
- ⇧ Level 2 Shift+を押すと、← Left Arrow端末エミュレータは制御シーケンスCSIを送信します
1
;
2
D
。代わりに7ビットの代替を使用し、7ビットの文字エンコーディングでCSIを送信します␛
[
1
;
2
D
。␛
[
- シェルはそれをterminfoの既知の固定入力シーケンスと一致させることはできず、処理を中断します。私のBourne Againシェルでは、最終的に最初の2文字を食べてを押したかのように動作します; 2 D。 Bourne Againシェルでは、最終的に最初の4文字を食べて、まるで押したかのように動作しますD。
失敗モードは、パターンマッチングを試みる正確な入力シーケンスのセットに依存する。これは、可能な一致がないと判断する前に飲み込む文字数を決定するためです。もちろん、これは端末のterminfo / termcapレコードに実際に含まれている内容と、シェルで使用するように指示した端末の種類によって異なります。
修理する
このタイプの問題の基本的な解決策は、シェルでキーバインディングを使用して創造性を発揮することです。たとえば、sでZシェルを使用してこの種のタスクを実行している人を見つける理由は次のとおりです.zshrc
。
バインドキー "\e[1;5D" リバースワード バインドキー "\e[1;5C" 今後の単語
残念ながら、デフォルト以外の修正はありません。これには、シェルの入力処理を書き換える作業が含まれます。この再構成はずっと前に行われた。 (ネオビームを目撃してください。)しかし、まだこの問題を解決した人は誰もいません。
追加読書
- 文字コード構造と拡張技術 。 ECMA-35。 6版。 1994. ECMAインターナショナル。
- 文字セットエンコーディングのための制御機能。 ECMA-48。 5版。 1991. ECMAインターナショナル。
- 「ANSI、ショートANSI、PCキーボードコード」。 VT420プログラマリファレンスマニュアル。 EK-VT420-RM-002. 1992年2月。数字。
DECFNK
。 「ANSI制御機能」。 VT510ターミナルプログラマー情報。 EK-VT510-RM。 1993年11月。数字。- VT520/VT525 ビデオ端末プログラマ情報。 EK-VT520-RM。 1994年7月。数字。
- https://github.com/fish-shell/fish-shell/issues/2139#issuecomment-388706768
- https://unix.stackexchange.com/a/238932/5132
答え2
Ctrl+を押すと、V次のキー入力が文字通り入力されます。Shift+ の場合、↑結果は "^[[1;2A"] です。端末ドライバは「^[[1;2」」を誤ったエスケープシーケンスとして使用し、「A」のみを残します。