How to prevent bash completion from replacing a character when tab completing How to prevent bash completion from replacing a character when tab completing bash bash

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