無効化されたnull globを持つzsh glob修飾子は、null globを使用するのと同じように機能します。

無効化されたnull globを持つzsh glob修飾子は、null globを使用するのと同じように機能します。

注:これがXY状況であると応答しないでください。私は特定の結果を得ようとするのではなく、ワイルドカードパターンがどのように機能するかを理解しようとしています。また、zstyleなどを使用してこれを達成する他の方法にも興味がありません。

最近私は私が望む状況に直面していました。特定のディレクトリのシンボリックリンクのみを完了してください。関数パラメータとして。*(@)ディレクトリに1つ以上のシンボリックリンクがある限り、同様のパターンを引数として使用できます。ディレクトリにシンボリックリンクがない場合は、通常のファイル(非シンボリックリンク)を完了するため、完成フィルタは失敗します。モードを次に変更してもシンボリックリンクがない場合は、通常のファイルを返します。驚くべきことに、N(パターン)の前に否定を追加すると、すべての場合に正しく機能します。しかし、これがzshのバグに遭遇したか(そしてこのモードは今後動作が中断される予定です)、またはこのモードが実際に意味があり、頼る価値があるかどうかは少し確信できません。-g_filesN*(@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

スピード:

  1. foocomp.zshファイルをディレクトリに保存
  2. mkdir foodir && cd foodir
  3. hello && ln -s hello world && cd ..をタッチします。
  4. 源泉foocomp.zsh
  5. fooまたはbarと入力してTabキーを押すと、ワールドが完成します。
  6. シンボリックリンクワールドの削除
  7. fooと入力してTabをもう一度押すと、何もしません(必要な動作です)。
  8. bar と入力して Tab をもう一度押すと、hello が完了します。

答え1

関数_filesはラッパーであり、コード_path_files_path_filesはglobだけでなく、さまざまな他のロジックとzstyle設定も含まれています。 aを追加すると、配列に含まれる内容-g globに影響を与え、さまざまなブランチにヒットするフラグを設定し、glob 修飾子を含めます。さまざまなパラメータで何が起こるのか、そしてglob修飾子が以下のコードにどのような影響を与えるかを確認するには、この関数呼び出しを実際に追跡する必要があります。patsgoptspats

% 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つの場合があります。だからいくつかのキーを押した後...barfoodir

% 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ソリューションを使用します。

関連情報