zshをnotに設定するにはどうすればよいのでしょうか。たとえば、次のような名前の数百のファイルのディレクトリがあります。
a.foo-bar a.foo b.foo-bar b.foo c.foo-bar c.foo
afterワイルドカードに一致するタブ補完を実行できるようにしたいので、
cat *.foo-< tab > => cat *.foo-bar
これは私が代わりに得るものです:
$ cat * .foo- => cat a.foo-bar ファイル a.foo-bar b.foo-bar c.foo-bar
1つのオプションは、TAB
キーのデフォルトのキーバインディングを置き換えることです。
bindkey "^I" expand-or-complete
と
bindkey "^I" complete-Word
これは、一致するすべてのファイルに*
を展開しませんが、星はそのままにします。このようにして、無限のリストを取り除きますが、それでもグロブ式は完成しません。
これを解決するには、はるかに注意が必要です。独自の完了ウィジェットを作成する必要があります(man zshcompwid
を参照)。
定義から始めましょう:
zle -C complete-glob menu-complete compglob
これにより、menu-completeのように動作する新しいウィジェットcomplete-globが導入されます。 )そしてシェル関数compglobを使用して一致を生成します。
[注:メニューの完成を望まない場合は、はるかに基本的なオプションcomplete-Wordまたはlist-choices]
この新しいウィジェットをCTRL+K
のような便利なショートカットにバインドします。
bindkey "^K" complete-glob
これをTAB
にバインドしないでください。現在の形式のウィジェットは、ファイルを完成させるだけです。
シェル関数compglobを次のように定義します。これにより、実際の作業が実行されます。
compglob () {
setopt localoptions globsubst
compset -P '*'
files=(${IPREFIX}*)
display=(${files/${IPREFIX}/${(q)IPREFIX}})
glob=(${files/${IPREFIX}/})
compadd -d display -- $glob
}
デモンストレーション:
$ touch a.foo-bar a.foo b.foo-bar b.foo c.foo-bar c.foo
$ cat *.f<CTRL+K>
$ cat *.foo
\*.foo \*.foo-bar
私が見る唯一の欠陥は、提示されたリストの星の前にある\
です。ただし、完了が正しいため、これは光学的な欠陥にすぎません:*.foo
または*.foo-bar
。
それは不可能だと思います。シェルに、実行するファイルを特定するだけでなく、「ワイルドカードの拡張に応じて有効」になりたくないだけでなく、拡張する「最良の」ワイルドカード式をシェルに認識させる必要があります。こちらです。 2番目の部分はNP完全であると思います。
自分が求めているものを完全に取得できる方法はまだわかりませんが、setopt GLOB_COMPLETE
を介して少し変更を加えることができます(これは役立つ場合と役に立たない場合があります)(これにより、展開は1つだけで、タブで移動できます...または、その1つだけを編集して*
に戻します。これは、少なくとも小さな改善になる可能性があります)。
man zshoptions
、man zshcompctl
、man zshcompwid
などを掘り下げることもできます。 zshの補完はかなり複雑なので、これを行う方法があるのではないかと思います。
また、やや関連する質問にも注意してください。