自定义git子命令的Bash自动补全?

4
假设我在PATH中有一个名为git-cc的可执行文件。如果git-cc支持--help,那么只需使用以下命令即可提供足够的自动完成功能:
complete -F _longopt git-cc

这使得$ git-cc --<TAB>可以自动补全(根据帮助输出)。但是git cc --<TAB>无法自动补全(尽管它可以正常运行)。更重要的是,如果我创建一个git别名到自定义子命令,例如cc-sensible-defaults = cc --opt1 ...,这也不起作用,在这种情况下,简单地删除空格(git-cc而不是git cc)不是一种选项。
怎么办?我尝试过使用__git_complete [git-]cc _longopt进行调整,但各种组合都没有产生良好的效果。它似乎只能用于完成bash别名(如gl = git-log),而不能用于子命令。在git/git-completion.bash中的介绍并没有很有帮助,其中包含令人困惑的内容。
# If you have a command that is not part of git, but you would still
# like completion, you can use __git_complete:
#
#   __git_complete gl git_log
#
# Or if it's a main command (i.e. git or gitk):
#
#   __git_complete gk gitk

(_git_log是什么?他们是不是指的_git_log这个函数?这是一种约定吗?)
1个回答

6

更新:

对于我来说,这个解决方案只是让 <tab> 每次列出所有备选项,没有自动完成,为什么?我尝试了 _git_jump() { COMPREPLY=(diff merge grep); }git jump d<tab> 但输出只是列表:diff grep merge –  Moberg

你需要做的是,从 COMPREPLY 中移除单词,只留下以 $cur 开头的单词。如果给定3个备选项,Bash将显示出列表。如果减少 COMPREPLY=(diff) ,那么Bash会自动完成它。

受到https://github.com/git/git/blob/master/contrib/completion/git-completion.bash#L2445的启发,以下代码可以很好地工作:

_git_jump() { __gitcomp "diff merge grep" "" "$cur"; }

我认为最好自己编写类似的代码,而不是依赖于 git

_git_jump() { COMPREPLY=( $(compgen -W "diff merge grep" -- "${COMP_WORDS[COMP_CWORD]}") ); }

对我而言,https://devmanual.gentoo.org/tasks-reference/completion/index.html 是介绍如何完成它的最佳入门材料。


该怎么做?

只需定义一个以 _git_ 前缀为前导的函数来完成编译。

# you should rather use COMPREPLY+=(..) or call `__gitcomp` to append
$ _git_cc() { COMPREPLY=(-a -b); }
$ git cc <tab>
-a  -b  
$ git cc -

请查看__git_complete_command

__git_complete_command () {
    local command="$1"
    local completion_func="_git_${command//-/_}"
    ...
    if __git_have_func $completion_func
        then
            $completion_func
            return 0

我已经试过操作 __git_complete。

据我所知,__git_complete 是另一种方式 - 您需要正常的命令自动完成,就像 Git 子命令一样。例如:

$ _git_cc() { COMPREPLY=(-a -b); }
$ alias mycommand='git cc'
$ __git_complete mycommand git_cc                  # or __git_complete mycommand _git_cc
$ mycommand <tab>
-a  -b  
$ mycommand -

_git_log是一个生成git log命令补全的函数。可以在此链接中查看具体实现。
是的,他们确实指的是_git_log这个函数。可以在此链接中查看__git_complete对于存在以"_main"后缀或"_"前缀或没有前后缀的函数的测试。
是的,这是一种约定俗成的做法。

好的。你知道我怎样可以重复使用_longopt,而不是重新解析“git-cc --help”,或者复制它当前的长选项吗? - usretc
可以尝试使用 _git_cc() { _longopt git-cc "${@:2}"; } 这段代码来开始实现。 - KamilCuk
对我来说,这个解决方案只是让<tab>每次列出所有备选项,没有自动完成,为什么?我尝试了_git_jump() { COMPREPLY=(diff merge grep); }git jump d<tab>,但输出只是列出:diff grep merge - Moberg

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