Reputation: 1722
I am creating a shell program which is a command line tool. I want to create my own auto-completion for this tool.
I want to do two different things (maybe should I post two questions):
--install
and -i
, I want to auto-complete on file paths, like the ls
command do.--unit-test
and -t
, I want to auto-complete on file paths from a particular directory which I can get running my_app --directory
.my_app_autocomplete
file
__my_app_autocomplete()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--help -h --install -i --run -r --rebuild -rb --show-running-containers -ps --stop -s --remove -rm --logs -l --bash -b --sass -css --unit-tests -t"
containers="nginx php mysql mongo node"
sass="watch"
# By default, autocomplete with options
if [[ ${prev} == my_app ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# By default, autocomplete with options
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# For --install and -i options, autocomplete with folder
if [ ${prev} == --install ] || [ ${prev} == -i ] ; then
COMPREPLY=( $(compgen -d -- ${cur}) )
return 0
fi
# For --stop --remove --logs and --bash, autocomplete with containers
if [ ${prev} == --stop ] || [ ${prev} == -s ] || [ ${prev} == --remove ] || [ ${prev} == -rm ] || [ ${prev} == --logs ] || [ ${prev} == -l ] || [ ${prev} == --bash ] || [ ${prev} == -b ] ; then
COMPREPLY=( $(compgen -W "${containers}" -- ${cur}) )
return 0
fi
# For --sass and -css, complete with sass options
if [ ${prev} == --sass ] || [ ${prev} == -css ] ; then
COMPREPLY=( $(compgen -W "${sass}" -- ${cur}) )
return 0
fi
# For --unit-tests and -t, complete with relative to my_app folder paths
if [ ${prev} == --unit-tests ] || [ ${prev} == -t ] ; then
COMPREPLY=( $(compgen -d -- ${cur}) )
return 0
fi
}
complete -F __my_app_autocomplete my_app
I struggle on a particular point: auto-complete file paths.
I don't understand compgen
options and how to do things with it. Maybe I could try to run a subcommand but I don't know the syntax and I can't find any useful information except man of bash - Programmable completion builtins which does not give much information about compgen
.
In this case, when I do:
user@computer:~$ my_app --install D[TAB][TAB]
I would like:
user@computer:~$ my_app --install Documents/
I obtain:
user@computer:~$ myapp --install Documents
with a blank space at the end of the line, which is a problem because I have to erase it and add a /
to be able to redo [TAB][TAB]
to auto-complete for sub-directories.
With the option -o nospace
applied on complete
as:
complete -o nospace -F __my_app_autocomplete my_app
the behavior is:
user@computer:~$ myapp --i[TAB][TAB]
user@computer:~$ myapp --install
without space.
user@computer:~$ myapp --install D[TAB][TAB]
user@computer:~$ myapp --install Documents
without space.
Problems:
--install
)/
to navigate into sub directoriesWith the option -o filenames
applied on complete
as:
complete -o filenames -F __my_app_autocomplete my_app
the behavior is:
user@computer:~$ myapp --i[TAB][TAB]
user@computer:~$ myapp --install
with a space
user@computer:~$ myapp --install D[TAB][TAB]
user@computer:~$ myapp --install Documents/
with a /
and without space if it's a directory
user@computer:~$ myapp --install f[TAB][TAB]
user@computer:~$ myapp --install file
with a space if it's a file
It seems to set paths only for completion not defined in an list of words, so it does not affect other completions, I think it's the first part of what I need.
I will open another question to avoid mixing things: How to autocomplete a bash commandline with file paths from a specific directory without displaying this directory?
Upvotes: 2
Views: 3057
Reputation: 196
Substitute
complete -F __my_app_autocomplete my_app
with
complete -o filenames -F __my_app_autocomplete my_app
Here you can find all the compgen options explained:
https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
Upvotes: 1