26

There is something confuse me when I implement a bash auto-completion function which I'll put it in /etc/bash_completion.d/

In order to achieve some feature, I want to remove the word break characters colon (:) from variable $COMP_WORDBREAKS and add a slash (/) at begin of $COMP_WORDBREAKS.

COMP_WORDBREAKS=" /'><=;|&("
_mytool()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    compopt -o nospace

    # my implement here

    COMPREPLY=( $(compgen ..........my_implement......... -- $cur) )
}
complete -F _mytool mytool

However, I can't reset COMP_WORDBREAKS directly because the value is shared with other completion scripts. By the time the completion function gets called, variable COMP_WORDS array has already been populated, so locally changes COMP_WORDBREAKS have no effect.

Is there any solution for changing COMP_WORDBREAKS in one completion script and no effect to other script?

$ echo $BASH_VERSION
4.2.10(1)-release
Cœur
  • 37,241
  • 25
  • 195
  • 267
Raymond
  • 375
  • 4
  • 8

1 Answers1

29

Modifying $COMP_WORDBREAKS in your completion script is not the recommended way (as it is a global variable and it could affect the behavior of other completion scripts - for example ssh).

However, bash completion offers some helper methods which you can use to achieve your goal.

The recommended way to handle non-word-breaking characters in completion words is by using the two helper methods:

  • _get_comp_words_by_ref with the -n EXCLUDE option
    • gets the word-to-complete without considering the characters in EXCLUDE as word breaks
  • __ltrim_colon_completions

So, here is a basic example of how to a handle a colon (:) in completion words:

_mytool()
{
    local cur
    _get_comp_words_by_ref -n : cur

    # my implementation here

    COMPREPLY=( $(compgen ..........my_implement......... -- $cur) )

    __ltrim_colon_completions "$cur"
}
complete -F _mytool mytool

As a final tip, the helper methods are located in /etc/bash_completion. Take a look inside to read a detailed description of each method and to discover more helper methods.

Radu Gasler
  • 1,006
  • 14
  • 17
  • 1
    Thank you so much, this was really useful for my rake task completions in Ruby on Rails! Also, thanks for pointing out section E13 in the docs. – ndbroadbent Oct 11 '12 at 09:55
  • 1
    this only worked properly, when I put this line `cur="${COMP_WORDS[COMP_CWORD]}"` before `_get_comp_words_by_ref -n : cur` also good to know, if you use the prev too, you can add it at the end `_get_comp_words_by_ref -n : cur prev` – jmk Dec 04 '14 at 12:39
  • When I have ambiguous completions and hit tab twice I get incorrect suggestions based on what I have typed when I use this solution. See http://stackoverflow.com/questions/28479216/how-to-give-correct-suggestions-to-tab-complete-when-my-words-contains-colons – toftis Feb 26 '15 at 08:48
  • 1
    Content of `/etc/bash_completion` tells in the heading comment for `__ltrim_colon_completions`: "The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in your .bashrc" – jarno Dec 04 '16 at 14:44
  • How does ssh's bash completion break, if COMP_WORDBREAKS is trimed? I suppose ssh's autocompletion could be fixed to work in both cases. – jarno Dec 05 '16 at 18:25
  • 1
    With the solution, completion works somewhat differently: Prefix ending with : is trimmed off from shown completions. – jarno Dec 05 '16 at 18:27
  • 3
    Instead of using `_get_comp_words_by_ref` you could use `_init_completion -n :`, but you have to declare more local variables then. – jarno Oct 21 '19 at 15:51
  • to add to @jarno `local cur prev words cword` then `_init_completion -n :` and you get a COMP_WORDS array in `words` without the colon breaking words – Piotr Feb 07 '23 at 19:35
  • `_init_completion` is nicer, but it still requires `__ltrim_colon_completions` (otherwise the completion includes extra text) – Tim Potapov Mar 09 '23 at 17:58