git의 ZSH 완성이 자동으로 절대 경로를 완성하지 않나요?

git의 ZSH 완성이 자동으로 절대 경로를 완성하지 않나요?

/.git내 파일 시스템의 루트인 git 저장소가 있습니다 .

내가 들어가서 /etc/foo/실행 하면 git statusgit은 파일이 ../fstab변경되었음을 알려줍니다.

zsh명령 완성 (아직 /etc/foo/에 있음)을 사용하려는 경우는 git다음과 같습니다.

git diff ../fs<TAB>

이것은 작동합니다. 하지만 절대 경로를 사용하면 다음과 같습니다.

git diff /etc/fs<TAB>

그러면 zsh절대 경로가 불완전합니다.

zsh전체 절대 경로와 상대 경로를 어떻게 알 수 있나요 ?

저는 Debian Buster 버전을 사용하고 있습니다 zsh.5.7.1-1

답변1

ZSH 완료:

Zsh 완성은 /usr/share/zsh/5.5/functions/Completion/Unix일반적으로 (배포판에 따라 다를 수 있음)에 있는 스크립트를 사용하여 수행되며, 각 명령 완성을 위한 스크립트는 이름이 지정되고 , Zsh는 Variables와 유사한 _commandName환경 변수를 포함/처리합니다 . 이 경우 스크립트는 Yes , Zsh 때문에 위치 순서가 중요합니다. 찾은 첫 번째 스크립트를 사용 하고 다른 스크립트가 있으면 무시합니다(또한 유사함) .$fpath$PATH_git$fpath_git$PATH

스크립트:

이것에 설명된 대로품질 보증그리고예를 들어, 다음 함수는 파일의 일반적인 완성 함수인 $PWD/에 전달하기 전에 상대 경로에 추가합니다 ._files

_absolute_files () {
  local expansion=$PREFIX$SUFFIX; expansion=${(e)expansion}
  if [[ "${expansion%%/#}" != "${expansion:a}" ]]; then
    PREFIX="\$PWD/$PREFIX"
  fi
  _files "$@";
}

~/이는 절대와 같이 및 로 시작하는 경로 식별을 포함하여 많은 일반적인 경우에 작동합니다 .

해결책:

기본 git완료 동작에는 상대 경로가 포함되지 않습니다. 스크립트를 편집하고 위에서 설명한 것과 유사한 기능을 추가하여 상대 경로에 대한 지원을 추가할 수 있습니다.또는git기본 완성을 다음의 완성 플러그인으로 간단하게 바꿀 수 있습니다.gitfast오메지쉬다음 단계를 수행하십시오.

클론오메지쉬특정 위치(예 /location: )로:

git clone https://github.com/ohmyzsh/ohmyzsh.git

~/.zshrc구성 파일 맨 아래에 다음을 편집 하고 추가합니다 gitfast.

fpath=( /location/ohmyzsh/plugins/gitfast $fpath ) 

앞서 설명했듯이 순서가 중요합니다여기.

~/.zcompdump*실행 중인 항목을 제거하여 완료 캐시를 업데이트합니다 compinit.

대체 솔루션:

함수에 다음 패치를 적용하여 /usr/share/zsh/5.5/functions/Completion/Unix/_git편집합니다 ._git-diff

--- _git
+++ _git
@@ -766,6 +766,12 @@

   case $state in
     (from-to-file)
+  
+      if [[ $line[1] == *\/* ]]; then
+        _alternative 'files::_files' && ret=0
+        return ret
+      fi
+      
       # If "--" is part of $opt_args, this means it was specified before any
       # $words arguments. This means that no heads are specified in front, so
       # we need to complete *changed* files only.

답변2

Zsh는 절대 경로를 매우 잘 수행합니다. 한번 시도해 보세요 ls /etc/fsTab.

문제는 _git사용하는 완성기에 있습니다. (아래 각주를 참조하세요.)

다음과 같이 테스트할 수 있습니다.

  1. 초기화했는지 확인하세요 compinit.
autoload -Uz compinit && compinit
  1. git diff(끝에 공백 있음)을 입력 CtrlX하고 문자 를 누릅니다 H.

다음과 같은 결과가 나타납니다.

tags in context :completion::complete:git-diff::
    argument-rest options  (_arguments _git-diff _git)
tags in context :completion::complete:git-diff:argument-rest:
    commit-ranges blobs-and-trees-in-treeish files blobs  (_git-diff _git) 
    heads commit-tags commit-objects                      (__git_commits __git_commit_ranges _git-diff _git) 
    heads-local heads-remote                              (__git_heads __git_commits __git_commit_ranges _git-diff _git) 
    messages                                              (_message __git_command_successful __git_heads_local __git_heads __git_commits __git_commit_ranges _git-diff _git) 
    heads-local                                           (__git_describe_branch __git_describe_commit __git_heads_local __git_heads __git_commits __git_commit_ranges _git-diff _git) 
    heads-remote                                          (__git_describe_branch __git_describe_commit __git_heads_remote __git_heads __git_commits __git_commit_ranges _git-diff _git) 
    messages                                              (_message __git_command_successful __git_tags_of_type __git_commit_tags __git_commits __git_commit_ranges _git-diff _git) 
    messages                                              (_message __git_command_successful __git_recent_commits __git_commit_objects_prefer_recent __git_commits __git_commit_ranges _git-diff _git) 
    changed-in-working-tree-files                         (__git_changed-in-working-tree_files _git-diff _git) 
    blob-tags blob-objects                                (__git_blobs _git-diff _git) 
    messages                                              (_message __git_command_successful __git_tags_of_type __git_blob_tags __git_blobs _git-diff _git)
tags in context :completion::complete:git::
    argument-rest  (_arguments _git)

이렇게 되니 참고하세요아니요files, 또는 ( directories입력할 때 표시되고 그 뒤에 +가 globbed-files표시됨)이 포함됩니다 . 그것이 포함하는 것은 그것들이 만들어졌다는 것입니다(보시다시피lsCtrlXHchanged-in-working-tree-filesgit diff -z --name-only --no-color여기) - 절대 경로가 아닌 저장소 루트에 대한 상대 경로를 생성합니다.

git따라서 절대 경로 에는 수행할 정보가 없기 때문에 컨텍스트에서 완료되지 않습니다 .


각주: Zsh 자체 _git완성 프로그램을 사용하고 있습니까, 아니면 Git이 설치했을 수 있는 완성 프로그램을 사용하고 있습니까? 나는 강력히 추천한다아니요Git이 설치된 버전을 사용하는데, Zsh 표준에 따라 올바르게 구현되지 않아 일부 부분에 버그가 많습니다. (Git의 Bash 완성 프로그램에서 자동으로 이식된 것으로 보이지만 버그가 있습니다.) fpathZsh 설치의 일부가 아닌 이름의 완성 파일이 있는지 확인 하고 삭제하세요._git

관련 정보