0

I am trying to write a Bash completion function for completing long command line options like --param1=value1. This works fine if value1 is not quoted. But in many cases value1 needs to be quoted, for example, --param1='Hello world'. In this case, Bash completion stops working. For example:

_myprog()
{
    local cur="${COMP_WORDS[$COMP_CWORD]}"
    local words=(--param1 --param2)
    COMPREPLY=( $(compgen -W "${words[*]}" -- "$cur") )
}

complete -F _myprog myprog

If I source this source script.sh and then type myprog --param1='hello' <tab><tab> nothing happens. It works fine if I start the quote before the double dashes, like myprog '--param1=hello' <tab><tab>..

Any suggestions?

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • The glib answer would be "Don't use quotes like that". The problem is that the single quote tells `bash` that you are starting a new word, even though the two words `--param1=` and `hello` will be passed as a single word once the command line is finished. This is enough, however, to confuse the completion code; `hello'` is not in the value of `words`, so there's technically nothing to complete. – chepner Apr 19 '15 at 18:37
  • @chepner But why does it not respect the second quote? and why does it work with `'--param1=hello'` but not with `--param1='hello'`? Double quotes have the same problem. – Håkon Hægland Apr 19 '15 at 18:43
  • 1
    The `bash` parser treats `'--param1=hello'` as a single word, and `--param1='hello'` as two words. It's not until after the entire line is complete and `bash` applies quote removal that the two are treated identically as a single word. I'm afraid I don't have a good suggestion as to how to work around this, other than "put quotes around the entire option". – chepner Apr 19 '15 at 18:45

1 Answers1

0

This can be done using COMP_LINE instead of COMP_WORDS:

_myprog()
{
    local comp_line=( $COMP_LINE )
    local cur
    if [[ ${COMP_LINE: -1} == ' ' ]] ; then
        cur=""
    else
        cur="${comp_line[@]: -1}"
    fi
    local words=(--param1 --param2)
    COMPREPLY=( $(compgen -W "${words[*]}" -- "$cur") )
}
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174