UbuntuとArchの両方でデフォルトのシェルとしてzshシェルを使用しています。
.zshrc
の次の行を使用して、zshシェルの履歴からオートコンプリートするショートカット(上矢印)を構成しました。
bindkey "^[[A" history-beginning-search-backward
ただし、.zshrc
を入手したり、Ubuntuで再起動したりすると、ショートカットは機能しません(入力を開始したかどうかに関係なく、前のコマンドしか取得できません)が、Archでは正常に機能します(入力したものから始まる最後のコマンド)。
誰かがこれを解決する方法を知っていますか?
ほとんどの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
参照:
キーの編集ほど楽しくはありませんが、本当に楽しいです。
キーボードには2セットのカーソルキー、カーソルキーパッドに1つ、電卓キーパッドに1つあります。
ほとんどのターミナルエミュレータは、DEC VTのモデルを採用しようとします。このモデルでは、キーの各セットは、プライベートモード設定を使用してアプリケーションモードと通常モードの間で個別に切り替え可能です。それぞれDECCKM
(カーソルキーパッドモード)とDECNKM
(テンキーモード)。アプリケーションモードの考え方は、基本的に、関連するキーパッドのキーが追加のアプリケーションファンクションキーに変わることです。
CUB
、CUF
、CUU
、およびCUD
制御シーケンスを送信します。 ⎇ Alt 修飾子が有効になっている場合、それらはDECFNK
制御シーケンスを送信します。SS3
シングルシフト3シーケンスを送信します。CUB
、CUF
、CUU
、およびCUD
制御シーケンスを送信します。 ⎇ Alt 修飾子が有効な場合、その場合、または数値ロックとシフトの組み合わせによって数字が送信されない限り、DECFNK
制御シーケンスが送信されます。SS3
シングルシフト3シーケンスを送信します(ここでも、数値ロックとシフトの組み合わせによって数字が送信される場合を除きます)。ZLEにウィジェットにバインドするように指示した␛
[
A
シーケンスは、CSI
A
コントロールシーケンスの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制御シーケンスパーサー(入力用)はかなり遅れています。しかし、まだ誰もそれに取り組んでいません。