views:

142

answers:

5

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?

Thanks for your help.

[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  A: 

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

Daniel Velkov
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.
Donald Harvey
+4  A: 

Take a look at the Debian Administration An introduction to bash completion - it's fairly easy to understand - by the way, it also has a part two.

bnery
A: 

Here a simple but working example in bash :

function foo_completion()
{
    local currentWord=${COMP_WORDS[COMP_CWORD]}
    local completionList=""

    case "${COMP_CWORD}" in
        "1")
            completionList="command1 command2 command3";
            ;;
        "2")
            completionList="param1 param2 param3";
            ;;
    esac

    COMPREPLY=( $( compgen -W "${completionList}" -- ${currentWord} ) )
}

complete -F foo_completion foo

With this kind of code, you will get commandN completed when you type "foo c" + tab and paramN completed when you type "foo command1 p" + tab

You can compute the completion list from the command help.

my2c

neuro
A: 

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.

David Blevins
Great script, but not quite what I'm trying to achieve. Thanks anyway for linking to it though.
Donald Harvey
+1  A: 

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:

http://git.naquadah.org/?p=awesome.git;a=blob;f=lib/awful/completion.lua.in;h=db0391d73e9ebe5427971fe731dfbae44652dc45;hb=HEAD#l107

Edit: Bash completion for "git l".

  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.
  3. All together we use the following command:
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

Output: "log"

Uli Schlachter
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!
Donald Harvey
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'
Uli Schlachter
"_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).
Uli Schlachter
Thanks, this'll be perfect. I was thinking of answering the question myself to provide the Bash code and abstract way of doing this, but you've done it for me :P. Anyway, I've awarded you the bounty - thanks again for your help!
Donald Harvey