무효화된 null glob이 있는 zsh glob 한정자는 null glob을 사용하는 것과 동일하게 작동합니다.

무효화된 null glob이 있는 zsh glob 한정자는 null glob을 사용하는 것과 동일하게 작동합니다.

참고: 이것이 XY 상황이라고 응답하지 마십시오. 저는 특정 결과를 얻으려고 하기보다는 와일드카드 패턴이 어떻게 작동하는지 이해하려고 노력하고 있습니다. 또한 zstyle 등을 사용하여 이를 달성하는 다른 방법에도 관심이 없습니다.

최근에 나는 내가 원하는 상황에 처해 있었다.특정 디렉토리의 심볼릭 링크만 완료하세요.함수 매개변수로. *(@)디렉토리에 하나 이상의 기호 링크가 있는 한 유사한 패턴을 인수로 사용할 수 있습니다 . 디렉터리에 심볼릭 링크가 없으면 이제 일반 파일(비심볼릭 링크)을 완료하기 때문에 완성 필터가 실패합니다... 그래서 문서를 살펴보니 (NULL GLOB) 한정자를 추가하는 것이 답인 것 같습니다. 모드를 다음으로 변경했지만 심볼릭 링크가 없으면 여전히 일반 파일을 반환합니다. 놀랍게도 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 솔루션을 사용할 것입니다.

관련 정보