6

Say I have a git-cc executable in PATH. If git-cc supports --help, then it is easy to provide adequate completion with

complete -F _longopt git-cc

This makes $ git-cc --<TAB> complete (as per help output). But git cc --<TAB> won't complete (even though it runs fine). More importantly if I create a git alias to the custom subcommand, e.g. cc-sensible-defaults = cc --opt1 ..., that also won't work, and in this case simply deleting the space (git-cc instead of git cc) isn't an option.

What to do? I've tried messing around with __git_complete [git-]cc _longopt, but none of the various combinations do anything good. It seems to be for completing bash aliases (like gl = git-log), not sub-commands. The intro in git/git-completion.bash is, as expected, not very helpful, containing the confusing

# 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

(WTH is _git_log? Did they mean _git_log, which is indeed a function? Is it some convention?)

1 Answer 1

7

Update:

For me, this solution just makes <tab> list all the alternatives every time, no completion, why? I tried _git_jump() { COMPREPLY=(diff merge grep); } and git jump d<tab> but the output is just listing: diff grep merge –  Moberg

What you have to do, is remove from COMPREPLY the words so that only one that starts with $cur is left. If you give 3, bash will show you the list. If you reduce COMPREPLY=(diff) then it will be auto-completed by Bash.

Taking inspiration of https://github.com/git/git/blob/master/contrib/completion/git-completion.bash#L2445 , the following works nicely:

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

Or I think it's better to write similar code yourself, not to depend on git:

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

For me https://devmanual.gentoo.org/tasks-reference/completion/index.html is the best introduction how to do it.


What to do?

Just define a function that does the compiletion with leading _git_ prefix.

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

See __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

I've tried messing around with __git_complete

As far as I understand the __git_complete it's the other way round - you want a normal command complete like git subcommand. For example:

$ _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 -

WTH is _git_log?

_git_log is a function the generates completion for git log.

Did they mean _git_log, which is indeed a function?

Yes. See __git_complete tests for existence of a function with _main suffix or _ prefix or without any prefix/suffix.

Is it some convention?)

Yes.

Sign up to request clarification or add additional context in comments.

3 Comments

Ah good. Do you know how I can reuse _longopt, instead of re-parsing git-cc --help, or copying it's current longopts?
Something along _git_cc() { _longopt git-cc "${@:2}"; } may get you started.
For me, this solution just makes <tab> list all the alternatives every time, no completion, why? I tried _git_jump() { COMPREPLY=(diff merge grep); } and git jump d<tab but the output is just listing: diff grep merge

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.