在Zsh中禁用远程分支的自动补全?

14
5个回答

12
zstyle :completion::complete:git-checkout:argument-rest:headrefs command "git for-each-ref --format='%(refname)' refs/heads 2>/dev/null"

说明:

输入git checkout <Control-x><h>会调用_complete_help函数,它能够显示zsh在当前上下文中按下TAB键时会采取的补全操作(而不是按下<Control-x><h>)。从中可以看到zsh将调用__git_heads函数来完成git分支头的名称。如果您输入which __git_heads,则可以看到这些分支头名称是通过以下方式获取的:

_call_program headrefs git for-each-ref --format='"%(refname)"' refs/heads refs/remotes 2>/dev/null

幸运的是,_call_program 是专门设计用来允许用户更改默认行为的。因此,上面的 zstyle 命令指示 zsh 使用替代的 git for-each-ref ... 调用而不是内置的调用,并且你可以在上面的调用中看到我删除了 refs/remotes 参数。 zstyle 的第一个参数是完成上下文,在这里它的意思是“每当完成系统在用户为 git checkout 的参数完成时请求 headrefs 标记的完成。因此,这个 zstyle 只会影响 git checkout,而不影响任何其他 git 子命令。


如何在自动完成中将远程和本地分成两个单独的部分?比如,我想要有特殊的头(HEADORIG_HEADFETCH_HEAD等),然后是本地分支,再然后是远程分支。我不知道应该怎么做。如果你能进一步扩展你的答案,那就太好了。如果不行,我会另外提一个问题。 - Bo Jeanes
很可能有一种方法可以做到这一点 - 毕竟,手册中有一个分组机制(搜索group-namegroup-order),但我不知道如何将各个标题拆分成这些组 - 所以最好提出一个单独的问题。 - Adam Spiers
1
有人知道如何在prezto中使这个工作吗?可能,命令应该以 ':prezto:module:completion:git-checkout 开头,但我还没有弄清楚剩下的部分。 - Jimothy

4
通过输入git checkout <Ctrl-X><H>,您将看到一堆标签,其中一些似乎很相关,包括:
$ git checkout
tags in context :completion::complete:git-checkout:argument-rest:
    remote-branch-names-noprefix              (__git_describe_branch __git_describe_commit __git_remote_branch_names_noprefix _git-checkout _git) 
    heads-remote                              (__git_describe_branch __git_describe_commit __git_heads_remote __git_heads __git_commits __git_tree_ishs _git-checkout _git) 
    [...]

乍一看,我们需要改变remote-branch-names-noprefix的行为,以停止提供没有前缀的远程分支名称。

为了再次检查,让我们看看这些标签与哪些条目相关联,使用:

$ zstyle ':completion:*' group-name ''
$ zstyle ':completion:*' format 'Completing "%d":'
$ git checkout T<Tab>
Completing "remote branch name":
T3522-plugins_and_stuff  T7482
Completing "local head":
T7626-async

在上面标签名称后面的括号中,有一系列命令导致自动完成条目被生成。在remote-branch-names-noprefix的链中,你可以看到__git_remote_branch_names_noprefix似乎是相关的。请查看/usr/share/zsh/functions/Completion/Unix/_git
(( $+functions[__git_remote_branch_names_noprefix] )) ||
__git_remote_branch_names_noprefix () {
  declare -a heads

  branch_names=(${${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/}#*/}:#HEAD})
  __git_command_successful $pipestatus || return 1

  __git_describe_commit branch_names remote-branch-names-noprefix 'remote branch name' "$@"
}

你可以看到如何使用_call_program来定义remote-branch-refs-noprefix。我们希望在git-checkout的情况下更改此定义。通过用"echo"替换它,它将停止提供自动完成条目。
zstyle ':completion::complete:git-checkout:argument-rest:remote-branch-refs-noprefix' command "echo"

1
似乎现在__git_heads只检查本地分支,但是完成文件调用了__git_refs。我通过将此补丁应用于git-completion.bash来解决这个问题,该补丁通过zsh _git命令进行代理。
--- git-completion.bash.old 2015-04-02 16:09:38.000000000 -0700
+++ git-completion.bash     2015-04-02 16:10:24.000000000 -0700
@@ -1032,13 +1032,7 @@
                    "
            ;;
    *)
-           # check if --track, --no-track, or --no-guess was specified
-           # if so, disable DWIM mode
-           local flags="--track --no-track --no-guess" track=1
-           if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
-                   track=''
-           fi
-           __gitcomp_nl "$(__git_refs '' $track)"
+           __gitcomp_nl "$(__git_heads)"
            ;;
    esac
 }

这不是一个完美的解决方案,但它适用于我的使用情况,并使完成变为瞬间而非10秒钟。


代码似乎自2015年以来已经发生了很大的变化,补丁无法应用。请问您能告诉我们这是哪个函数定义吗? - John Y

0

没有一个答案能帮助我。试试这个:

$ git checkout <Ctrl+X><H>
tags in context :completion::complete:git::
    argument-rest  (_arguments _git)
tags in context :completion::complete:git-checkout::
    argument-rest options  (_arguments _git-checkout _call_function _git)
tags in context :completion::complete:git-checkout:argument-rest:
    remote branches tree-ishs modified-files  (_alternative _git-checkout _call_function _git) 
    remote-branch-names-noprefix              (__git_remote_branch_names_noprefix _alternative _git-checkout _call_function _git) 
    heads commit-tags commit-objects          (_alternative __git_commits __git_tree_ishs _alternative _git-checkout _call_function _git) 
    heads-local                               (__git_heads_local __git_heads _alternative __git_commits __git_tree_ishs _alternative _git-checkout _call_function _git) 
    commit-tags                               (__git_tags_of_type __git_commit_tags _alternative __git_commits __git_tree_ishs _alternative _git-checkout _call_function _git) 
    modified-files                            (__git_files __git_modified_files _alternative _git-checkout _call_function _git)

在这个输出中,您可以找到生成命令完成的函数。您可以在.zshrc文件中覆盖任何一个函数。将此内容放置在配置文件非常顶部
__git_heads_remote() {}

之后,您将不会在自动完成中看到远程头。您可以对任何函数执行此操作。


-2

您可以通过在.zshrc文件中添加以下行来禁用git checkout的自动完成功能:

compdef -d git checkout

1
我正在寻找一种避免远程分支自动补全的方法。但我想保留本地分支的自动补全功能。 - Galder Zamarreño
@GalderZamarreño 恐怕这超出了我的 zsh 知识范围;你可以尝试联系 zsh 列表,他们似乎是很乐于助人的人。 - Christopher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接