I've used complete -W 'firstdatabase databasetwo etc' mysql
to save a list of databases, so that I can autocomplete them using the mysql
command.
However, in many cases I would type mysql db < /tmp/script.sql
. How can I get bash to revert to traditional autocomplete (filenames) after seeing the first >
or <
?
Update: I pulled up a stock Ubuntu install, which comes with the bash-autocomplete package pre-installed. While simply installing that same package on our server is not an option for me, I can still learn from its implementation by examining the output of complete -p
and declare
. (alias -p
has some cool stuff as well)
On our server, I used complete -d cd
. I observe that it suffers from the same issue in that after <
or >
, the complete -d
functionality persists. However, bash-autocomplete has a more elaborate approach which solves this issue. Learning how they solved it for cd
(and a multitude of other commands) may show how to solve the same issue I'm having for mysql
.
So, here is their implementation for cd
: They use complete -o nospace -F _cd cd
, which basically calls function _cd
for the autocomplete query. Here is the function they use:
_cd ()
{
local cur prev words cword;
_init_completion || return;
local IFS='
' i j k;
compopt -o filenames;
if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
_filedir -d;
return 0;
fi;
local -r mark_dirs=$(_rl_enabled mark-directories && echo y);
local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y);
for i in ${CDPATH//:/'
'};
do
k="${#COMPREPLY[@]}";
for j in $( compgen -d $i/$cur );
do
if [[ ( -n $mark_symdirs && -h $j || -n $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
j+="/";
fi;
COMPREPLY[k++]=${j#$i/};
done;
done;
_filedir -d;
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
i=${COMPREPLY[0]};
if [[ "$i" == "$cur" && $i != "*/" ]]; then
COMPREPLY[0]="${i}/";
fi;
fi;
return 0
}
complete -o nospace -F _cd cd
Running the above code on a recent version of bash
gives the desired results for cd
. Now how can this be converted for mysql
? (or anything I'd normally use complete -W
for?)
Best Answer
The magic is in the
_init_completion
function which is defined in thebash_completion
file of the bash-completion package.There's no easy way out. If you want sensible fancy completion in bash, install the bash-completion package. Then define a function: