Auto-complete command line arguments

2019-01-10 16:55发布

问题:

In bash, executables such as mplayer and imagemagick's "convert" have a cool auto-complete functionality on their command line arguments. For instance, if I type

mplayer <tab><tab>

in one of my video folders, then mplayer will list all media files located in that folder, and only the media files.

Similarly, if I type

convert -<tab><tab>

then I will see all the possible options of the convert script, which is great.

My question is how to achieve a similar functionality, using bash, ruby or python scripts?

回答1:

This is an example of BASH's smart completion. A basic description is here, a guide to writing your own extensions is here and another (Debian-based) guide is here. And here's a fuller featured introduction to the complete command (the command that facilitates this behaviour).

EDIT: fixed dead links



回答2:

This functionality in bash is provided by bash-completion and similar functionality is included in zsh. If you want to add support for some program not currently supported by one of these tools, you need to write your own extensions for them.



回答3:

The link to writing your own extension in the accepted answer has gone dead. Quoting here from http://web.archive.org/web/20090409201619/http://ifacethoughts.net/2009/04/06/extending-bash-auto-completion/

Bash provides you a way of specifying your keywords, and using them to auto complete command line arguments for your application. I use vim as a wiki, task managemer and contacts. The vim helptags system lets me index the content instead of searching through it, and the speed shows it. One feature I wanted to add to this was to access these tags from outside vim.

This can be done in a straight forward way:

$ vim -t tagname

This takes me directly to specific content marked using this tag. However, this will be more productive if I can provide auto-completion for the tags.

I first defined a Bash function for the vim commandline. I added the following code to my .bashrc file:

function get {
    vim -t $1
} Now I can use get tagname command to get to the content.

Bash programmable completion is done by sourcing the /etc/bash-completion script. The script lets us add our auto-completion script /etc/bash-completion.d/ directory and executes it whenever it is called. So I added a script file called get with the following code in that directory.

_get()
{
    local cur
    COMPREPLY=()
    #Variable to hold the current word
    cur="${COMP_WORDS[COMP_CWORD]}"

    #Build a list of our keywords for auto-completion using
    #the tags file
    local tags=$(for t in `cat /home/anadgouda/wiki/tags | \
                      awk '{print $1}'`; do echo ${t}; done)

    #Generate possible matches and store them in the
    #array variable COMPREPLY
    COMPREPLY=($(compgen -W "${tags}" $cur))
}

#Assign the auto-completion function _get for our command get.
complete -F _get get Once the /etc/bash-completion is sourced, you will get auto-completion for the tags when you use the get command.

Along with my wiki I use it for all the documentation work and at times the code too. I also use the tags file created from my code. The indexing system lets me remember the context instead of the filenames and directories.

You can tweak this system for any of the tools you use. All you need to do is get a list of the keywords for your command and give it to the Bash programmable completion system.