How to create script with auto-complete?
Solution 1
You can use the Programmable Completion. Have look at /etc/bash_completion
and /etc/bash_completion.d/*
for some examples.
Solution 2
You'll have to create a new file:
/etc/bash_completion.d/foo
For a static autocompletion (--help
/ --verbose
for instance) add this:
_foo()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--help --verbose --version"
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _foo foo
-
COMP_WORDS
is an array containing all individual words in the current command line. -
COMP_CWORD
is an index of the word containing the current cursor position. -
COMPREPLY
is an array variable from which Bash reads the possible completions.
And the compgen
command returns the array of elements from --help
, --verbose
and --version
matching the current word "${cur}"
:
compgen -W "--help --verbose --version" -- "<userinput>"
Solution 3
Here is a complete tutorial.
Let's have an example of script called admin.sh
to which you would like to have autocomplete working.
#!/bin/bash
while [ $# -gt 0 ]; do
arg=$1
case $arg in
option_1)
# do_option_1
;;
option_2)
# do_option_2
;;
shortlist)
echo option_1 option_2 shortlist
;;
*)
echo Wrong option
;;
esac
shift
done
Note the option shortlist
. Calling the script with this option will print out all possible options for this script.
And here you have the autocomplete script:
_script()
{
_script_commands=$(/path/to/your/script.sh shortlist)
local cur
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $(compgen -W "${_script_commands}" -- ${cur}) )
return 0
}
complete -o nospace -F _script ./admin.sh
Note that the last argument to complete is the name of the script you want to add autocompletion to. All you need to do is to add your autocomplete script to bashrc as :
source /path/to/your/autocomplete.sh
or copy it to :
/etc/bash_completion.d
Solution 4
All of the bash completions are stored in /etc/bash_completion.d/
. So if you're building software with bash_completion it would be worthwhile to have the deb/make install drop a file with the name of the software in that directory. Here's an example bash completion script for Rsync:
# bash completion for rsync
have rsync &&
_rsync()
{
# TODO: _split_longopt
local cur prev shell i userhost path
COMPREPLY=()
cur=`_get_cword`
prev=${COMP_WORDS[COMP_CWORD-1]}
_expand || return 0
case "$prev" in
--@(config|password-file|include-from|exclude-from))
_filedir
return 0
;;
-@(T|-temp-dir|-compare-dest))
_filedir -d
return 0
;;
-@(e|-rsh))
COMPREPLY=( $( compgen -W 'rsh ssh' -- "$cur" ) )
return 0
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W '-v -q -c -a -r -R -b -u -l -L -H \
-p -o -g -D -t -S -n -W -x -B -e -C -I -T -P \
-z -h -4 -6 --verbose --quiet --checksum \
--archive --recursive --relative --backup \
--backup-dir --suffix= --update --links \
--copy-links --copy-unsafe-links --safe-links \
--hard-links --perms --owner --group --devices\
--times --sparse --dry-run --whole-file \
--no-whole-file --one-file-system \
--block-size= --rsh= --rsync-path= \
--cvs-exclude --existing --ignore-existing \
--delete --delete-excluded --delete-after \
--ignore-errors --max-delete= --partial \
--force --numeric-ids --timeout= \
--ignore-times --size-only --modify-window= \
--temp-dir= --compare-dest= --compress \
--exclude= --exclude-from= --include= \
--include-from= --version --daemon --no-detach\
--address= --config= --port= --blocking-io \
--no-blocking-io --stats --progress \
--log-format= --password-file= --bwlimit= \
--write-batch= --read-batch= --help' -- "$cur" ))
;;
*:*)
# find which remote shell is used
shell=ssh
for (( i=1; i < COMP_CWORD; i++ )); do
if [[ "${COMP_WORDS[i]}" == -@(e|-rsh) ]]; then
shell=${COMP_WORDS[i+1]}
break
fi
done
if [[ "$shell" == ssh ]]; then
# remove backslash escape from :
cur=${cur/\\:/:}
userhost=${cur%%?(\\):*}
path=${cur#*:}
# unescape spaces
path=${path//\\\\\\\\ / }
if [ -z "$path" ]; then
# default to home dir of specified
# user on remote host
path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
fi
# escape spaces; remove executables, aliases, pipes
# and sockets; add space at end of file names
COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
command ls -aF1d "$path*" 2>/dev/null | \
sed -e 's/ /\\\\\\\ /g' -e 's/[*@|=]$//g' \
-e 's/[^\/]$/& /g' ) )
fi
;;
*)
_known_hosts_real -c -a "$cur"
_filedir
;;
esac
return 0
} &&
complete -F _rsync $nospace $filenames rsync
# Local variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indent-comment: t
# indent-tabs-mode: nil
# End:
# ex: ts=4 sw=4 et filetype=sh
It would likely be worthwhile to review one of the bash completion files in there that most closely matches your program. One of the simplest examples is the rrdtool
file.
Solution 5
If all you want is a simple word based auto-completion (so no subcommand completion or anything), the complete
command has a -W
option that just does the right thing.
For example, I have the following lines in my .bashrc
to autocomplete a program called jupyter:
# gleaned from `jupyter --help`
_jupyter_options='console qtconsole notebook' # shortened for this answer
complete -W "${_jupyter_options}" 'jupyter'
Now jupyter <TAB> <TAB>
autocompletes for me.
The docs at gnu.org are helpful.
It does seem to rely on the IFS
variable being set correctly, but that hasn't caused any issues for me.
To add filename completion and default BASH completion, use the -o
option:
complete -W "${_jupyter_options}" -o bashdefault -o default 'jupyter'
To use this in zsh, add the following code before running the complete
command in your ~/.zshrc
:
# make zsh emulate bash if necessary
if [[ -n "$ZSH_VERSION" ]]; then
autoload bashcompinit
bashcompinit
fi
Related videos on Youtube
UAdapter
Updated on September 18, 2022Comments
-
UAdapter almost 2 years
When I use program like
svn
and I type in Gnome Terminal:svn upd
and hit Tab it's autocompleted to:
svn update
Is it possible to do something like that in my custom bash script?
-
Bruno Pereira over 12 yearsexplain "bash script", you mean when editing a script? what do you want to do with it?
-
UAdapter over 12 yearswhen using script in console
-
jarno over 5 yearsAs for place where to put your completions, see this question and also the comments for the accepted answer there.
-
-
MountainX about 11 yearsHow about including a simple example directly related to the question?
-
Chris almost 10 yearsCan we configure completions to load from other locations? IE. ~/.local
-
Cedric Reichenbach almost 9 yearsTip: If someone wants suggestions for words not starting with
-
and show them without having to start typing the target word, just remove theif [...] then
andfi
lines. -
flo over 8 yearsYes, you can put a file like this wherever you want and then put
source ~/.local/mycrazycompletion
in your~/.bashrc
-
Peter Chaula about 7 yearsThe provided link already has that already. :D
-
Peter Chaula almost 7 yearsThe actual scripts for Ubuntu 16 are located in
/usr/share/bash-completion/completions/<program>
-
Andrew Lamarra over 6 yearsWhat does the
-o nospace
option do? -
Lazarus Lazaridis over 6 yearsTutorial - Creating a bash completion script
-
Eaten by a Grue over 6 yearsImo, examples should be included in the answer, not in a link.
-
timuçin about 6 yearsI believe this platform is supposed to be a more practical alternative to full documentations that could be found with a simple google search. Dumping a documentation link doesn't help that. The link containing an anchor surely doesn't make much difference.
-
GMan over 5 yearsHow do I make this work with
bash jupyter <TAB><TAB>
? -
Ben over 5 years@papampi, I think it only works with one level of completion - I think to do it with 2 layers you'd need one of the more complicated answers above. Also, I recently read a pretty decent tutorial about bash completion. It doesn't do exactly what you need, but maybe it'll help you out. Good luck!
-
snowe2010 over 5 yearsafter days of searching this has so far been the only link that helped me. thanks!
-
Liam Dawson over 5 years
The provided link has that already
- it might today, but it mightn't tomorrow. Or next year. Or in a decade. Whatever you might suggest about the documentation still being relevant, Stack Overflow discourages link-only answers for these reasons. -
jarno over 5 years@Chris see instructions at Bash Completion FAQ
-
jarno over 5 yearsNowadays most completions are located in the directory given by command
pkg-c
onfig --variable=completionsdir bash-completion` and that directory is the recommendation given by Bash Completion FAQ linked above. -
pbhj over 5 years@LiamDawson, I found over 200 copies currently and there are over 400 copies in the WBM at archive.org. It seems as likely to exist as this site is. But just edit it yourself and add a pertinent quote, no harm done.
-
Jus12 about 4 yearsLooks like we need a PhD degree in compilers to understand. I gave up after 5 minutes.
-
Asclepius over 3 years@Jus12 You don't need to understand all of it to make it work, just enough for your use case. Try this simpler tutorial.
-
Asclepius over 3 yearsThe paths noted in the answer look to be obsolete. User completion scripts can be stored in
~/.local/share/bash-completion/completions/
after creating it. System completion scripts are generally stored in/usr/share/bash-completion/completions/
. -
Asclepius over 3 yearsThe path in the answer looks to be obsolete. User completion scripts can be stored in
~/.local/share/bash-completion/completions/
after creating it. System completion scripts are generally stored in/usr/share/bash-completion/completions/
. -
Asclepius over 3 years@AndrewLamarra
-o nospace
prevents the insertion of a space after a successful completion. (ref) -
Asclepius over 3 yearsThe path in the answer looks to be obsolete, and the sourcing is largely unnecessary. User completion scripts are sourced from
~/.local/share/bash-completion/completions/
; this directory can be created by the user. System completion scripts are generally stored in/usr/share/bash-completion/completions/
. -
Asclepius over 3 yearsThe path in the answer looks to be obsolete. As per this FAQ, user completion scripts are sourced from
~/.local/share/bash-completion/completions/
; this directory can be created by the user. System completion scripts are generally stored in/usr/share/bash-completion/completions/
. -
Ari Sweedler over 2 yearsCan you help me understand why the path in the answer is obsolete? Is it technology or convention that is evolving. From my .. "experiment" it seems like it is just convention evolving. What convention is it, so I can read about the history of it so I can understand why they made those decisions? The "experiment": even when I place my completion scripts in
~/.local/share/bash-completion/completions/
, they do not automatically get sourced. It's no different than if they're at~/my/completion/dir
. Not a big deal, I just source them manually either way. -
Ari Sweedler over 2 yearsI see
/etc/bash_completion.d/
gets automatically loaded according to other links here, but I don't see anything about~/.local
. I know that's an XDG thing, but I guess I just suck at google-fu because I cannot find anything about automatic sourcing from theshare/bash-completion/completions
directory. -
Admin about 2 years