28

I'm trying to write a small command launcher application, and would like to use bash's tab completions in my own completion system. I've been able to get a list of completions for general commands using compgen -abck.
However, I would also like to get completions for specific commands: for instance, the input git p should display completion for git's commands.

Is there any way I can use compgen to do this? If not, are there any other ways I can get a list of completions programmatically?

[EDIT: To clarify, I'm not trying to provide completion to bash - my app is a GUI command launcher. I'd simply like to use bash's existing completions in my own app.]

2
  • I hacked up this script a while back which gives you pretty accurate Man-page Bash Completion I know other people have done similar things with parsing --help option output. Commented Sep 3, 2010 at 19:25
  • Great script, but not quite what I'm trying to achieve. Thanks anyway for linking to it though. Commented Sep 3, 2010 at 22:51

3 Answers 3

16
+50

I don't really know how it works, but the awesome window manager uses the following Lua code for getting access to bash completion's result:

https://github.com/awesomeWM/awesome/blob/master/lib/awful/completion.lua#L119

  1. Via complete -p we find complete -o bashdefault -o default -o nospace -F _git git. We remember "_git" for later.
  2. The length of "git l" is 5, so we set COMP_COUNT=6. We are completing the first argument to "git", so COMP_CWORD=1.

All together we use the following script:

__print_completions() {
    printf '%s\n' "${COMPREPLY[@]}"
}

# load bash-completion functions
source /etc/bash_completion

# load git's completion function
_completion_loader git

COMP_WORDS=(git l)
COMP_LINE='git l'
COMP_POINT=6
COMP_CWORD=1
_git
__print_completions

Output: "log"

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

7 Comments

The code appears to do pretty much exactly what I want to do with my app. I'll need to port it to regular Bash, but it's still very helpful. Thanks a lot!
I did some testing and this is what is run to complete "git l": /usr/bin/env bash -c 'source /etc/bash_completion; __print_completions() { for ((i=0;i<${#COMPREPLY[*]};i++)); do echo ${COMPREPLY[i]}; done }; COMP_WORDS=(git l); COMP_LINE="git l"; COMP_COUNT=6; COMP_CWORD=1; _git; __print_completions'
"_git" is found via "complete -p" which prints "complete -o bashdefault -o default -o nospace -F _git git". So if the first word is "git", call "_git". COMP_COUNT is the length of the string so far plus one. COMP_CWORD is the word to complete (first one is index 0).
Hey great! Thanks for working this out. Note that for the sake for readability/convenience, you can replace the for ((..;..;..)) statement with for reply in "${COMP_REPLY[@]}" (and then echo "$reply" inside the loop). Also: i in your example, or reply in my proposal, should be declared as local to avoid clobbering identically named globals.
FYI Bash now uses dynamic completion loading, which requires the use of _completion_loader git to load git's completion function _git. Also I was unable to find any reference to COMP_COUNT. The correct var is COMP_POINT. Note, COMP_POINT is not used directly in completion scripts, but is used indirectly via commonly-used helper functions in /usr/share/bash-completion/bash_completion.
|
2

Check in the /etc/bash_completion.d/ directory. This is where the different command completion scripts stay.

1 Comment

I have had a poke around in /etc/bash_completion.d/, but haven't yet worked out an easy way to get the completions contained within yet very easily. (I'm using Python to access the completions, making things slightly more complicated.) I was hoping there might be a simpler way of accessing command-specific completions.
1

Quite an old question, but in the mean time I've implemented a script that handles this to reuse completions with ZSH

Comments

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.