web-dev-qa-db-ja.com

.zshrcショートカットはArchでは機能しますがUbuntuでは機能しません

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

.zshrcの次の行を使用して、zshシェルの履歴からオートコンプリートするショートカット(上矢印)を構成しました。

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

ただし、.zshrcを入手したり、Ubuntuで再起動したりすると、ショートカットは機能しません(入力を開始したかどうかに関係なく、前のコマンドしか取得できません)が、Archでは正常に機能します(入力したものから始まる最後のコマンド)。

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

3
Ul Tome

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

kcuu1(キーカーソルを1つ上に移動)terminfoエントリは、によって送信されたシーケンスを記述します Upキーパッド送信モードの場合、つまり␛OAです。

Debianとその派生物には/etc/zsh/zshrcファイルがあります。

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

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

このファイルは、terminfoエントリに基づいて $key連想配列を定義します ウィジェットにマップするのに役立ちます。したがって、これらのシステムでは、次のことができます。

(($+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

参照:

4

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

キーの編集ほど楽しくはありませんが、本当に楽しいです。

キーボードには2セットのカーソルキー、カーソルキーパッドに1つ、電卓キーパッドに1つあります。

ほとんどのターミナルエミュレータは、DEC VTのモデルを採用しようとします。このモデルでは、キーの各セットは、プライベートモード設定を使用してアプリケーションモード通常モードの間で個別に切り替え可能です。それぞれDECCKM(カーソルキーパッドモード)とDECNKM(テンキーモード)。アプリケーションモードの考え方は、基本的に、関連するキーパッドのキーが追加のアプリケーションファンクションキーに変わることです。

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

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

Terminfoデータベースは、ターミナルI/Oにこのモデルを採用していないため、水を濁し、ここでさらに楽しいものになります。むしろ、「ローカル」キーと「リモート」キーの概念を具体化する独自のdifferentモデルを採用しています。これは、DECVTアプリケーション/通常モードの切り替えに実際に含まれるものではありません。また、ローカル/リモートの切り替えメカニズムが1つあり、アプリケーション/通常モード間でキーパッドを個別に切り替えることができます両方

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

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

しかし、さらに悪化します。terminfoは一貫性がありません。単一の制御シーケンスは、 PuTTY端末タイプ のterminfoレコードとしてのDEC VTアプリケーションモードシーケンスである場合もあり、 のterminfoレコードとしてのDECVT通常モードシーケンスである場合もあります。 ] rxvt端末タイプ ですが、DECFNKシーケンスはありません。そのため、特定の端末または端末エミュレーターでアプリケーションに切り替える必要があるのか​​、通常モードに切り替える必要があるのか​​を知る方法はありません。ある人にとっては正しく機能するものが、別の人にとってはうまくいかないでしょう。

したがって、もう1つのアプローチは、terminfoを無視して、自分がすでにであることを認識し、端末が常に元のbindkeyコマンドを使用したDECVTのようになると想定することです。端末がアプリケーションモードであるか通常モードであるかにかかわらず、端末が送信する制御シーケンスが一致することを確認するには、そのうちの2つが必要です。

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

ただし、これは修飾キーが押されても対処できません。これにより、CUP制御シーケンスに追加のパラメーターが追加され、ZLEが探しているのが単純な古いパラメーターのないCUPである場合に、ZLEが使用する単純な文字列照合が失敗します。修飾子の可能な組み合わせごとに生じる可能性のあるbindkey制御シーケンスごとに、追加のCUPコマンドを手動で発行する必要があります。

seq 1 8 | 
 while read -r i 
 do 
 bindkey "^ [[1; $ {i} A" history-beginning-search-backward 
 done

ここでは、ZLEだけではありません。 fish Shellなどの他のterminfoベースのプログラムも、同じように影響を受けます。 (fish Shellの人々も、ある端末エミュレーターで正しく機能するアプリケーション/通常モードの選択が別の端末エミュレーターではうまくいかないことを発見しました。)これを再設計します( libtermkey と比較してください。これらのプログラムの実際のECMA-48制御シーケンスパーサー(入力用)はかなり遅れています。しかし、まだ誰もそれに取り組んでいません。

参考文献

2
JdeBP