There's basically no way to fix the problems you describe, because bash uses the values in COMPREPLY
directly in the display and then to replace the user's text - while to get what you want, you'd need to first generate the possible completions (just the additional server names, without the prefix) for bash to display, then when bash is about to replace the user text with the longest non-conflicting string, you'd need it to call your script again to generate the text with the prefix - and bash has no facility for that.
The best that I could come up with is to have the COMPREPLY
be generated with only the first word having the entire prefix (COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )
), so that if there is only one possible completion, it completes automatically correctly, while if there is more than one possible completion, then bash will not remove what was typed so far (because the first word in COMPREPLY
has the entire prefix and thus matches the currently typed text and will be selected by bash to replace the user's text) and will display the options without the prefix - except for that one word that already contains the prefix, so the output will look like this:
$ command -s banana,a
ananas apricot banana,apple
"apple" as sorted last in the completion options because it carries the prefix which starts with "b" - very confusing. So I don't recommend doing that.
Regarding the duplicates - in order to not show duplicates, you just need to break $prefix
into its part (easy: IFS="," prefix_parts=($prefix)
) and then iterate over them and only leave in $servers
the names that are not already listed. Its tedious to type, so I won't show it here, but relatively trivial so I'm sure you can manage :-).
To summarize, I don't think you should use comma separated values for input options, at least if you expect bash to help you with completion.
You can support an options format that like this: command -s <server> [<server> [..]]
and then for completion of entries other than the one immediately after the -s
option, just scan back through the $COMP_WORDS
array from $COMP_CWORD
until you find an option (string that matches -*
) and if its "-s" then you need to do the server name completion.
IFS=, LIST=("$VARIABLE")
where $VARIABLE contains your comma separated values.$VARIABLE
, otherwise word breaking doesn't happen. just useIFS=, LIST=($VARIABLE)
.