Autocompletion for custom git commands¶
Custom git commands, or git extensions, can be used to make highly specialized commands for the project you are currently working in. This is great and all, but they do not have autocompletion as normal git commands.
So let us fix that.
complete & compgen utilities¶
compgen
is responsible for generating a list of matches given some options,
while complete
specifies how any argument to a given match should be completed.
Essentially compgen
says, hey dude, I got this list of matches for you, and then complete
say, oh really?
Well for that match I have the following arguments for you to begin matching against.
complete
and compgen
share the following options abcdefgjksuv]
.
-a
Names of Alias-b
Names of Builtins (shell)-c
Names of Commands (all available commands in your path)-d
Names of Directory-e
Names of Exported shell variables-f
Names of Files and Functions-g
Names of Groups-j
Names of Job-k
Names of Keywords reserved by the shell-s
Names of Services-u
Names of Users-v
Names of Variables (none exported shell variables)
compgen¶
From the little intro we have learned that compgen
somehow creates some list of matches.
With the options staring us in or face it becomes rather easy. For example, compgen -b
will return the complete
list of all builtin shell commands, one item per line. That’s it. It is yours, to do what every you wish to do with.
For example filter it.
complete¶
Let us start simple and with an example.
complete -W '-a -b ..' compgen
From the manual [1] we see that -W
causes any word in the following string to be used as completions.
So in the above example when we type compgen <TAB><TAB> the following line get printed in the console.
.. -a -b
If we type - then .. is removed from the line. Perfect, we have autocompletion. But that isn’t very interesting. Instead we are going to register a function that will return the matches for us.
Before that, there are some things we should know. In the environment the function is run, there are some environmental variables available for us. These are:
Variable |
Description |
---|---|
|
A bash array containing each individual word of the current line |
|
The index in |
|
Word under the cursor |
|
Returns the possible completions back to |
Now we have our building blocks. So let us do something silly. Everytime compgen is the command. Return the previously written word when pressing tab.
_previous()
{
COMPREPLY=(${COMP_WORDS[COMP_CWORD-1]})
}
complete -F _previous compgen
But how do we signal that its time to stop?
One way is to return a non zero exit status. This will however inform bash that something is wrong, ie probably not
what we want to do. Instead we need to return an empty COMPREPLY
. So a simple if something, else something would
suffice.
Clearing completions for a certain command¶
In order to clear the completions for a command, it needs to be registered with the -r
option.
So to clear completions for compgen
, do
complete -r compgen
Listing all registered completions¶
What if we forgot or are interested in knowing how a certain command performs autocompletion.
Well that is also simple, just run the complete
command without any arguments, like so
complete
This is the same as supplying the -p
option, p for print.
git comlete wrappers¶
Git is extensible and modular, so it already have a way to map your “git custom command”. Git essentially searches
for any command in PATH (or current directory) starting with git- and registers the function
_git_YOUR_CUSTOM_COMMAND
with complete
if you have created that function. This is done
on the fly (in one or more subshells), so we never actually see these registration.
But this is really nice, since all we need to do is ensure that git finds your script and your bash function.
And voila! autocompletions in git is here.
To show this, let’s create an empty executable in a temporary folder, add it to our path and re-read the git completion file. Then simply define a ridicolous function with any dashes replaced with an underscore. Voila! git autocompletion for a custom command
TMP=`mktemp -d` # Create tmp dir
touch $TMP/git-custom-command # In tmp dir add file git-custom-command
chmod u+x $TMP/git-custom-command # Make it executable
export PATH=$TMP:$PATH # Place it in your path
source /usr/share/bash-completion/completions/git # Re-read completions (or start a subshell)
_git_custom_command() { COMPREPLY=("c1 c2"); } # Create your autocompletion function
git custom-command<TAB><TAB> # Autocomplete !
rm -rf $TMP # Clean up your mess
git compgen wrappers¶
If you type __git<TAB><TAB> and you will find a list of a number of internal git functions. Generated by git completions script. There are a lot of them here. So let us focus on a few of them.
git bash function |
Description |
---|---|
|
Generates a |
|
Creates an empty |
|
Creates custom command completions, as shown in previous example |
|
Gives the path to current repository .git folder |
|
Returns subcommand if it is present on the command line |
|
List all available branches |
|
Ask git to tell us which commands exists |
|
Filter out plumbing commands and return the user friendly ones |
|
Bind everything together to generate proper autocompletions for git |
|
List all references (heads, remotes, tags etc) |
|
List all remotes |
|
List all tags |
|
This is the function that gets mapped to |
Final notes¶
Finally I would like to thank the authors of the bash manual. It helps a lot in understanding everything. We all have our own way to learn, and I do not believe this guide could have been written in 4 hours without the help of the others behind the references [1], [2], [3], [4], [5]
_git_YOUR_CUSTOM_GIT_COMMAND ()
{
COMPREPLY("Hello world")
}
Let your imagination take you away to that magic place.
References