How to prevent bash completion from replacing a character when tab completing
So, this intrigued me, so I've been reading through the bash completion source (available at /etc/bash_completion).
I came across this variable: ${COMP_WORDBREAKS}
, which appears to allow control over what characters are used to delimit words.
I also came across this function, _get_cword
and the complementary _get_pword
, both recommended for use in place of ${COMP_WORDS[COMP_CWORD]}
and ${COMP_WORDS[COMP_CWORD-1]}
respectively.
So, putting all this together, I did some testing and here's what I've come up with: this seems to work for me, at least, hopefully it will for you too:
# maintain the old value, so that we only affect ourselves with thisOLD_COMP_WORDBREAKS=${COMP_WORDBREAKS}COMP_WORDBREAKS="${COMP_WORDBREAKS}@"cur="$(_get_cword)"prev="$(_get_pword)"if [[ "$cur" == '=@' ]]; then COMPREPLY=( $(compgen -f ${cur:2}) ) # restore the old value COMP_WORDBREAKS=${OLD_COMP_WORDBREAKS} return 0fiif [[ "$prev" == '=@' ]]; then COMPREPLY=( $(compgen -f ${cur}) ) # restore the old value COMP_WORDBREAKS=${OLD_COMP_WORDBREAKS} return 0fi
Now, I'll admit that the split if
cases are a little dirty, there's definitely a better way to do it but I need more caffeine.
Further, for whatever it's worth to you I also discovered along the way the -P <prefix>
argument to compgen
, which would prevent you from having to loop over the $COMPREPLY[*]}
array after calling compgen
, like so
COMPREPLY=( $(compgen -P @ -f ${cur:1}) )
That's a little redundant in the face of a full solution, though.
Try this ....
function test{ COMPREPLY=() local cur="${COMP_WORDS[COMP_CWORD]}" local opts="Whatever sort of tabbing options you want to have!" COMPREPLY=($(compgen -W "${opts}" -- ${cur}))}complete -F "test" -o "default" "test"# complete -F "test" -o "nospace" "sd" ## Use this if you do not want a space after the completed word