カーソルキーは楽しいです。

カーソルキーは楽しいです。

私は Ubuntu と Arch の両方でデフォルトのシェルとして zsh シェルを使用しています。

私は、次の行を使用して、zsh シェルの履歴から自動補完するためのショートカット (上矢印) を設定しました.zshrc

bindkey "^[[A" history-beginning-search-backward

ただし、.zshrcUbuntu でソースを実行して再起動すると、ショートカットは機能しません (入力を開始した内容に関係なく、前のコマンドしか取得されません)。一方、Arch では正常に機能します (入力した内容で始まる最後のコマンドしか取得されません)。

これを解決する方法を誰か知っていますか?

答え1

ほとんどのxtermのような端末では、Up(ほとんどのナビゲーションキーでも同様です)端末が設定されているかどうかに応じて␛[A、またはを送信します。␛OAキーパッド送信モードかどうか。terminfoエントリsmkxrmkxエントリを使用して、端末をそのモードにしたり、そのモードから外したりできます。

kcuu1(キーカーソルを1つ上げる) terminfoエントリはUpキーパッド送信モード、つまり␛OA

Debianとその派生製品には/etc/zsh/zshrc

function zle-line-init () {
   emulate -L zsh
   printf > /dev/tty '%s' ${terminfo[smkx]}
}

これにより、zle がアクティブなときに端末がそのモードになり、キーが送信する文字シーケンスを知るために terminfo データベースを利用できるようになります。

このファイルには$key連想配列を定義するterminfo エントリに基づいてウィジェットにマッピングします。これらのシステムでは、次の操作を実行できます。

(($+key[Up])) && bindkey $key[Up] history-beginning-search-backward

端末がキーパッド送信モードとそうでないもの、またはハッシュがない場合は$key、次のようにします。

bindkey $terminfo[kcuu1] history-beginning-search-backward
bindkey ${terminfo[kcuu1]/O/[} history-beginning-search-backward

参照:

答え2

カーソルキーは楽しいです。

編集キーほど楽しいものではないが、本当に楽しい。

あなたが持っている2セットキーボードのカーソルキー、カーソルキーパッドそして、電卓キーパッド

ほとんどの端末エミュレータは、DEC VTのモデルを採用しようとしますが(時には非常にうまくいきません)、各キーセットは個別に切り替え可能です。アプリケーションモードそしてノーマルモードそれぞれプライベート モード設定 DECCKM(カーソル キーパッド モード) とDECNKM(数字キーパッド モード) を使用します。アプリケーション モードの考え方は、基本的に、関連するキーパッドのキーが追加のアプリケーション機能キーに変わるというものです。

⇐ これはカーソルキーパッドです。
  • 通常モードでは、矢印キーは、修飾子が有効になっていない限り、ECMA-48 CUB、、および制御シーケンスを送信します。修飾子が有効になっている場合は、制御シーケンスを送信します。CUFCUUCUD⎇ AltDECFNK
  • アプリケーション モードでは、矢印キーはSS3シングル シフト 3 シーケンスを送信します。
⇐ これは電卓のキーパッドです。
  • 通常モードでは、矢印キーは、修飾子が有効になっていて制御シーケンスを送信する場合を除き、または、数値ロックとシフトの組み合わせによって数字を送信する場合を除き、ECMA-48 CUB、、CUFおよび制御シーケンスを送信します。CUUCUD⎇ AltDECFNK
  • アプリケーションモードでは、矢印キーで別のセットの SS3シングルシフト 3 シーケンス (ただし、数値ロックとシフトの組み合わせによって数字が送信される場合は除きます)。

ZLE にウィジェットにバインドするように指示したシーケンスは、制御シーケンス [ Aの ECMA-48 7 ビット エイリアスであり、これは("カーソル UP") 制御シーケンスです。この制御シーケンスは、キーパッドが通常モードで、修飾子が有効になっていない場合にのみ、DEC VT とその模倣端末エミュレータによって生成されます。関連するキーパッドがアプリケーション モードのときに送信されるシフト シーケンスとは一致しません。CSI ACUP⎇ Alt

terminfoデータベースは、端末I/Oにこのモデルを採用していないため、混乱を招き、さらに面白くなります。代わりに、独自のモデルを採用しています。違う「ローカル」キーと「リモート」キーの概念を具体化したモデルですが、これはDEC VTのアプリケーション/通常モードの切り替えにはまったく関係ありません。また、単一のローカル/リモート切り替えメカニズムがあり、切り替えは両方キーパッドはアプリケーションモードと通常モードの間で切り離せません。

terminfo は、DEC VT を模倣しない端末または端末エミュレーターを使用している場合に備えて、ZLE を構成する方法を特定の端末タイプに固定しない方法です。また、Z シェルは、データベース レコードから必要な機能エントリにアクセスする方法を提供します。そのため、terminfo から、terminfo が上下左右のカーソル キーで生成すると想定する制御シーケンスを読み取り、bindkeyそれらの制御シーケンスをウィジェットにマップする適切なコマンドを発行できます。

問題は、terminfoがこの仕事には不十分だということです。terminfoには記録する方法しかありません。1つキーごとに制御シーケンスを送信できますが、ご覧のとおり、キーは少なくともモードと押された修飾子によって異なる 3 つの異なるシーケンス。(修飾子は、DEC VT モデルでは送信される制御シーケンスにかなり大きな影響を与える可能性があります。) したがって、terminfo で予測されるものを生成するモードに端末を切り替える必要があります。

しかし、さらに悪いことに、terminfoは一貫性がありません。terminfoが記録する単一の制御シーケンスは、DEC VTアプリケーションモードシーケンスである場合があります。端末puttyタイプ、時にはDEC VT通常モードシーケンス、terminfoの記録として端末rxvtタイプただし、シーケンスはわかりませんDECFNK。したがって、特定の端末または端末エミュレータで、アプリケーション モードに切り替えるべきか、通常モードに切り替えるべきかを知る方法はありません。1 つの端末または端末エミュレータで正しく機能するものが、別の端末では正しく機能しないことがあります。

したがって、もう1つのアプローチは、terminfoを無視して、すでにそして、あなたの端末が常に元のコマンドで DEC VT のようになることを前提としていますbindkey。端末がアプリケーション モードか通常モードかに関係なく、送信される制御シーケンスが一致するようにするには、次の 2 つが必要です。

bindkey "^[OA" 履歴先頭後方検索

ただし、これは修飾キーが押された場合には対応できず、CUP制御シーケンスに余分なパラメータが追加され、ZLE が使用する単純な文字列マッチングが、単純にパラメータなしの文字列だけを探している場合には失敗します。修飾キーの可能な組み合わせごとに、可能な制御シーケンスごとに追加のコマンドCUPを手動で発行する必要があります。bindkeyCUP

1 8 番目 |
読み取り中 -ri
する
    bindkey "^[[1;${i}A" 履歴先頭後方検索
終わり

ZLE だけが問題なのではありません。シェルなどの他の terminfo ベースのプログラムもfish同様の問題を抱えています。(fishシェルの開発者も、ある端末エミュレータで正しく機能するアプリケーション/通常モードの選択が、別の端末エミュレータでは正しく機能しないことに気付きました。) これを再設計すると (比較すると、libtermkeyこれらのプログラムに、入力用の実際の ECMA-48 制御シーケンス パーサーが搭載されるのは、ずっと前から望まれていたことです。しかし、まだ誰もそれに取り組んでいません。

参考文献

関連情報