注:これがXY状況であると応答しないでください。私は特定の結果を得ようとするのではなく、ワイルドカードパターンがどのように機能するかを理解しようとしています。また、zstyleなどを使用してこれを達成する他の方法にも興味がありません。
最近私は私が望む状況に直面していました。特定のディレクトリのシンボリックリンクのみを完了してください。関数パラメータとして。*(@)
ディレクトリに1つ以上のシンボリックリンクがある限り、同様のパターンを引数として使用できます。ディレクトリにシンボリックリンクがない場合は、通常のファイル(非シンボリックリンク)を完了するため、完成フィルタは失敗します。モードを次に変更してもシンボリックリンクがない場合は、通常のファイルを返します。驚くべきことに、N(パターン)の前に否定を追加すると、すべての場合に正しく機能します。しかし、これがzshのバグに遭遇したか(そしてこのモードは今後動作が中断される予定です)、またはこのモードが実際に意味があり、頼る価値があるかどうかは少し確信できません。-g
_files
N
*(@N)
*(@^N)
誰かが以下のパターンが機能しているかどうかを確認できればいいでしょう。 zshのバグのためではなく、その意味が何であるかを確認できれば良いでしょう。以下はテストファイルですfoocomp.zsh
。
function foo {
echo "foo called with $1"
}
function _foo {
_files -g '*(@^N)' -W $PWD/foodir/
}
function bar {
echo "bar called with $1"
}
function _bar {
_files -g '*(@N)' -W $PWD/foodir/
}
compdef _foo foo
compdef _bar bar
スピード:
foocomp.zsh
ファイルをディレクトリに保存- mkdir foodir && cd foodir
- hello && ln -s hello world && cd ..をタッチします。
- 源泉
foocomp.zsh
- fooまたはbarと入力してTabキーを押すと、ワールドが完成します。
- シンボリックリンクワールドの削除
- fooと入力してTabをもう一度押すと、何もしません(必要な動作です)。
- bar と入力して Tab をもう一度押すと、hello が完了します。
答え1
関数_files
はラッパーであり、コード_path_files
に
_path_files
はglobだけでなく、さまざまな他のロジックとzstyle設定も含まれています。 aを追加すると、配列に含まれる内容-g glob
に影響を与え、さまざまなブランチにヒットするフラグを設定し、glob 修飾子を含めます。さまざまなパラメータで何が起こるのか、そしてglob修飾子が以下のコードにどのような影響を与えるかを確認するには、この関数呼び出しを実際に追跡する必要があります。pats
gopts
pats
% less ${^fpath}/_path_files(N)
_path_files
グローバルzstyleは、予期しないデバッグが困難な方法でコードを妨げる可能性があります。たとえば、コマンド*(@^N)
にglobを設定してfoo
から数ヶ月後にユーザーまたはランダムプラグインがクラッシュするzstyle変更を実行し、数ヶ月後に期待どおりに機能*(@^N)
しなくなり、その理由がわからないことがわかります。追跡により、私たちは何が起こっているのかを確認し、非公式の推論が正しいかどうかをテストできます。
% functions -t _path_files
これは実際に非常に面倒なことです。_complete_debug
代わりに、完了トレースは一時ファイル(control+ x ?)に保存されます。
% bindkey | grep _debug
"^X?" _complete_debug
そのため、リンクがある場合とリンクがない場合foo
など4つの場合があります。だからいくつかのキーを押した後...bar
foodir
% mv zsh3827foo2 withlink-foo
% mv zsh3827bar3 withlink-bar
% mv zsh3827foo4 nolink-foo
% mv zsh3827bar5 nolink-bar
呼び出し間で変更が行われると、実際に区別が容易になる可能性があるため、_complete_debug
コマンド名の違いによって問題が複雑になりません。とにかく最終的に重要な違いは
- +_path_files:468> compfiles -p tmp1 accex '' ' ' .. fake '*(#q@^N)'
- +_path_files:472> tmp1=
+ +_path_files:468> compfiles -p tmp1 accex '' ' ' .. fake '*(#q@N)'
+ +_path_files:472> tmp1=( )
^
正しいfoo
セットtmp1=
と無効なセットの場合は、空のbar
配列を設定し、共有完了tmp1=( )
トラックに再参加する前に、他の場所で長いブランチを実行します。したがって、これはやや微妙な点であり、通常、エラーメッセージは
compfiles
どこかに飲み込まれます。コマンドラインに示すように、^@
シンボリックリンクが存在しないディレクトリでのみ閉じます。NULL_GLOB
% a=( *(#q@^N) )
zsh: no matches found: *(#q@^N)
% a=( *(#q@N) )
Src/Zle/computil.c
関数からcompfiles
配列を返す方法が文書化されていますparnam1
。
* SYNOPSIS:
* 1. compfiles -p parnam1 parnam2 skipped matcher sdirs parnam3 varargs [.
.varargs]
...
* 1. Set parnam1 to an array of patterns....
* ${(P)parnam1} is an in/out parameter.
compfiles
したがって、配列が常に返される必要がある場合は、これがバグかもしれないと思います。しかし、これはおそらくZSH開発者と話し合うべきことです。それ以外の場合は、この完了コードに影響を与える可能性があるグローバルzstyleの変更を避けるために、この場合もzstyleソリューションを使用します。