You can find a related question here: How to autocomplete a bash commandline with file paths?
Context
I am creating a shell program which is a command line tool. I want to create my own auto-completion for this tool.
For the options --unit-test and -t, I want to auto-complete on file paths from a particular directory which I can get running my_app --directory.
e.G.
Run:
user@computer:~$ my_app --install [TAB][TAB]
would do:
Public/ bin/ Desktop/
Documents/ Music/ Downloads/
user@computer:~$ my_app --install
(display the current directory)
Run:
user@computer:~$ my_app --unit-tests [TAB][TAB]
would do:
folder/ folder2/ folder3/
.hidden_file file.extension file2.extension
user@computer:~$ my_app --unit-tests
(display suggestions for specific directory without complete with it)
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 from a specific folder
if [ ${prev} == --unit-tests ] || [ ${prev} == -t ] ; then
COMPREPLY=( $(compgen -d -- ${cur}) )
return 0
fi
}
complete -o filenames -F __my_app_autocomplete my_app
Problem
I can't find a way to do it. Do you have any ideas?
Investigations
Using a variable containing the specific directory
Suggested by @D'Arcy Nader
Adding at the beginning of my_app_autocomplete
_directory=/absolute/path/to/the/directory/
and then substitute the variable in the compgen command
# For --unit-tests and -t, complete with relative to my_app folder paths
if [ ${prev} == --unit-tests ] || [ ${prev} == -t ] ; then
COMPREPLY=( $(compgen -d -- "${_directory}") )
return 0
fi
Behavior:
Run
user@computer:~$ my_app --unit-tests [TAB][TAB]
do
user@computer:~$ my_app --unit-tests /absolute/path/to/the/directory/
It adds the path to the directory.
Run
user@computer:~$ my_app --unit-tests /absolute/path/to/the/directory/file.ext[TAB][TAB]
do
user@computer:~$ my_app --unit-tests /absolute/path/to/the/directory/
It removes the file.ext
part.
Problems:
- I don't want to add the specific path in the command line
- It removes what I add after the specific directory instead of auto-complete it.