如何将自定义 git 命令添加到 zsh 自动补全中?

18

我已经阅读了一些关于zsh补全的指南,但仍感到困惑。在我们的开发环境中,我们有一个名为git new-branch的自定义Git命令。 我想在键入git neTab后,让zsh自动补全它。我该怎么做?


两年后,这将成为可能,使用Git 2.18(2018年第二季度),它将更好地考虑到/usr/share/bash-completion/completions。请参见下面的答案 - VonC
2个回答

14

默认的 git 自动补全可以扩展

比如说你有自己的 git 子命令(当你运行 "git foo" 时,git 将运行一个名为“git-foo”的程序),你希望 "git f" 自动补全这个子命令的名称。你可以通过用户命令样式将该子命令知名于自动补全:

% zstyle ':completion:*:*:git:*' user-commands foo:'description for foo'

`user-commands' 是一个列表样式,所以您可以在其中添加任意数量的程序。 :description 部分是可选的,因此您可以像这样添加 $path 中的所有 git-* 程序:

% zstyle ':completion:*:*:git:*' user-commands ${${(M)${(k)commands}:#git-*}/git-/}
那就是,只需要添加。
zstyle ':completion:*:*:git:*' user-commands new-branch:'custom new branch function'

将内容添加到您的 zshrc 文件中。

如果您还想处理自定义命令的参数,则使用自定义compdef文件是更好的解决方案。上面提到的文件也详细介绍了这一点:只需创建一个标准定义文件,定义一个 git- < yourcommand>函数,默认的git完成将在需要时自动使用它。


3

在Git 2.18(2018年第二季度)中,您有一个新的选择,这不仅适用于zsh:命令行完成机制(位于contrib/中)已经学会为"git $command"加载自定义完成文件,其中$command是用户在使用更新版本的bash时在$PATH上拥有的自定义"git-$command"。

请看 提交 085e2ee(2018年4月29日)由Florian Gamböck (FloGa)
(在提交fb3a0ca中由Junio C Hamano -- gitster --合并,于2018年5月23日)

completion: load completion file for external subcommand

Adding external subcommands to Git is as easy as to put an executable file git-foo into PATH.
Packaging such subcommands for a Linux distribution can be achieved by unpacking the executable into /usr/bin of the user's system.
Adding system-wide completion scripts for new subcommands, however, can be a bit tricky.

Since bash-completion started to use dynamical loading of completion scripts since v1.90 (preview of v2.0), it is no longer sufficient to drop a completion script of a subcommand into the standard completions path, /usr/share/bash-completion/completions, since this script will not be loaded if called as a git subcommand.

For example, look at https://bugs.gentoo.org/544722.
To give a short summary: The popular git-flow subcommand provides a completion script, which gets installed as /usr/share/bash-completion/completions/git-flow.

If you now type into a Bash shell:

git flow <TAB>

You will not get any completions, because bash-completion only loads completions for git and git has no idea that git-flow is defined in another file.
You have to load this script manually or trigger the dynamic loader with:

`git-flow <TAB>` # Please notice the dash instead of whitespace

This will not complete anything either, because it only defines a Bash function, without generating completions.
But now the correct completion script has been loaded and the first command can use the completions.

So, the goal is now to teach the git completion script to consider the possibility of external completion scripts for subcommands, but of course without breaking current workflows.

这是 Git 2.18 提出的方法:

我认为最简单的方法是使用由 bash-completion v1.90 定义的函数,即 _completion_loader。
它会负责加载正确的脚本(如果有的话)。
之后,git 完成脚本会像往常一样工作。

_completion_loader 是在 2011 年 提交 20c05b43scop/bash-completion(bash 的可编程完成函数)中引入的,因此即使在旧的 LTS 发行版中也应该可用。
该函数不仅在默认路径 /usr/share/bash-completion/completions 中搜索外部完成脚本,还通过 $XDG_DATA_HOME 在用户的主目录中以及通过 $BASH_COMPLETION_USER_DIR 在用户指定的目录中搜索。


univerio在评论中添加了以下内容

事实证明,有两个不同的完成函数:

univerio补充道:

  • 由zsh提供的函数是Debian(以及Ubuntu、Mint等)的默认值,并且
  • 由git提供的函数是macOS上安装homebrew的git的默认值。

非常令人困惑。不确定哪一个更好。

这个特定答案仅适用于由Git提供的函数,而被接受的答案仅适用于由zsh提供的函数。


我升级到了Git 2.19.1,希望能够利用它的优势,但是我的自定义git-foo命令没有自动完成,我一定是漏掉了什么。 - rtaft
@rtaft 奇怪,你是在哪个环境下尝试的?Linux?Windows?Mac? - VonC
我先尝试了Mint 18.3,然后又尝试了Mint 19.0。我将这两个版本都升级到了2.19.1。 - rtaft
@rtaft 我研究了一下,发现有两个不同的自动补全函数:一个是zsh提供的,另一个是git提供的。在Debian(以及Ubuntu、Mint等)上,默认使用zsh提供的函数;而在macOS上,homebrew安装的git默认使用git提供的函数。非常令人困惑。不确定哪一个更好。 - univerio
我还应该补充说明,这个特定的答案仅适用于git提供的函数,而被接受的答案仅适用于zsh提供的函数。 - univerio
@univerio 非常有趣的反馈,谢谢。我已经将您的评论包含在答案中以增加可见性。 - VonC

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