git 的 ZSH 补全不会自动补全绝对路径?

git 的 ZSH 补全不会自动补全绝对路径?

我有 git 存储库/.git,即我的文件系统的根目录。

当我进入/etc/foo/并执行时git status,git 告诉我文件../fstab已更改。

当我想使用命令zsh完成git(仍在 /etc/foo/ 中)时,即:

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(可能因发行版而异)的脚本完成的,每个命令完成的脚本被命名为_commandName,Zsh 包含/处理那些环境变量$fpath类似于变量的脚本$PATH,在这种情况下使用的脚本是_git,位置顺序on$fpath很重要,因为 Zsh 使用_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*通过删除任何then run来更新完成缓存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 完成程序中自动移植的,但有缺陷。)检查您是否有任何不属于 Zsh 安装的fpath名为的完成程序文件,并将其删除。_git

相关内容