2

I'm failing to get complete to offer full suggestions when the options in ${COMPREPLY[@]} contain a : character. Instead, it only offers the prefix that is common to all suggestions.

Here's an example that works fine:

_foo() { local cur=${COMP_WORDS[$COMP_CWORD]} COMPREPLY=( $(compgen -W "bart baze" -- "$cur" ) ) } complete -F _foo foo 

And here's how it is used (I never press Enter, only TAB where indicated)

$ foo <tab> $ foo ba <-- Autocompletes common prefix, good $ foo ba<tab> bart baze <-- Suggests options, good $ foo bar<tab> $ foo bart <-- Autocompletes the only option, good 

But if I prepend something with a :, like http://, it fails to provide full suggestions (only the prefix common to all options):

$ _foo() { local cur=${COMP_WORDS[$COMP_CWORD]} COMPREPLY=( $(compgen -W "h:bart h:baze" -- "$cur" ) ) } $ complete -F _foo foo 
$ foo <tab> $ foo h:ba <-- Autocompletes common prefix, good $ foo h:ba<tab> $ foo h:ba <-- No effect 

The manual suggests something about -I working with delimiters, but complete -I -F _foo foo doesn't change anything.


If I inspect deeper, it seems to be with how complete -F interprets ${COMPREPLY[@]}. compgen seems to set COMPREPLY just fine.

$ COMPREPLY=( $(compgen -W "h:bart h:baze" -- h) ) $ for i in "${COMPREPLY[@]}"; do echo "$i"; done h:bart h:baze 
1
  • 1
    Try removing ":" from var $COMP_WORDBREAKS if it is in there. Commented Aug 8, 2024 at 9:50

1 Answer 1

2

@meuh's comment led me to https://stackoverflow.com/questions/10528695/how-to-reset-comp-wordbreaks-without-affecting-other-completion-script which led me to the answer.

Bash provides a number of macros to help in /etc/bash_completion. In debian, this sources /usr/share/bash-completion/bash_completion.

Browsing in this file there are some ways to handle the colon:

  • _init_completion -n : will remove : from $COMP_WORDBREAKS. But calling only this isn't enough, or you'll find ^.*: gets repeated in your auto-complete result

    $ _foo() { local cur=${COMP_WORDS[$COMP_CWORD]} _init_completion -n : cur COMPREPLY=( $(compgen -W "h:bart h:baze" -- "$cur" ) ) } $ complete -F _foo foo $ foo <tab> $ foo h:h:ba 
  • __ltrim_colon_completions will remove leading ^.*: from the completion, which fixes the previous problem a bit.

    The result is:

    $ _foo() { local cur=${COMP_WORDS[$COMP_CWORD]} _init_completion -n : cur COMPREPLY=( $(compgen -W "h:bart h:baze" -- "$cur" ) ) __ltrim_colon_completions "$cur" } $ complete -F _foo foo $ foo <tab> $ foo h:ba <-- It got the common part right! $ foo h:ba<tab> bart baze <-- It removed the prefix? $ foo h:baz<tab> $ foo h:baze <-- The final completion is correct 

The suggestions are a bit strange, especially if you were expecting http://example.com and get //example.com, but it does work.

But the documentation for __ltrim_colon_completions() says:

The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in your .bashrc:

# Remove colon (:) from list of word completion separators COMP_WORDBREAKS=${COMP_WORDBREAKS//:} 

See also: Bash FAQ - E13) Why does filename completion misbehave if a colon appears in the filename? - https://tiswww.case.edu/php/chet/bash/FAQ

I'm not really a fan of imposing on /etc/bash.bashrc, especially since this completion script will be deployed in a package, and I'm not making local edits. This change could also change the behaviour of other completion scripts that actually rely on the : separator for parsing things like $PATH.


The solution I ended up with is to set this in my /usr/share/bash-completion/completions/foo script:

#!/usr/bin/env bash _foo() { COMP_WORDBREAKS=${COMP_WORDBREAKS//:} local cur=${COMP_WORDS[$COMP_CWORD]} COMPREPLY=( $(compgen -W "h:bart h:baze" -- "$cur" ) ) } complete -F _foo foo 

It's hard to tell if this has a global impact. A new shell doesn't have $COMP_WORDBREAKS defined, but I'm not sure if bash-completion reset it between completions.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.