I'm trying to get my command (devmode2) auto-completing with bash working with compgen -W, my bashrc has:

_devmode2() {
    local sonames=$(devmode2 --auto --current "${COMP_CWORD}" -- ${COMP_WORDS[@]})
    COMPREPLY=($(compgen -W "${sonames}" -- ${COMP_WORDS[COMP_CWORD]}))
complete -F _devmode2 devmode2

An example auto-completion

$ devmode2 g<tab>

results in sonames having the following values:


but my auto-completion results in the following suggestions:

game-life-adv       game-life-sparse    getopt-alt          github-testers      git-workflow        git-workflow-extra  group-git           group-git-ivan

How can I get all the values I pass to compgen back?


As far as I know, compgen does not have an option to do case-insensitive filtering of the list of options you give it.

There is a readline variable which you can set to cause filename completion to be case-insensitive:

bind "set completion-ignore-case on"

but that doesn't affect the behaviour of compgen, so it probably won't apply to programmable completion. (Its behaviour is a bit odd with filenames, too.)

That leaves you with the possibility of doing your own filtering instead of using compgen (or in conjunction with compgen if you require features other than filtering, which is not the case in your example).

You could do that with a simple iteration over the list of alternatives, doing a case-insensitive prefix comparison, but the following little function should work:

_devmode2() {
  local sonames=($(devmode2 --auto --current "${COMP_CWORD}" -- ${COMP_WORDS[@]}))
  local prefix="${COMP_WORDS[COMP_CWORD]}"
  COMPREPLY=($(printf %s\\n "${sonames[@]}" |
               awk -v IGNORECASE=1 -v p="$prefix" \

If devmode2 outputs one alternative per line, it would be easier to just use it as the input to awk. Also, the second argument of the completion function is, as far as I know, always the same as ${COMP_WORDS[COMP_CWORD]}. So this might be simpler:

_devmode2() {
  COMPREPLY=($(devmode2 -auto --current "${COMP_CWORD}" -- "${COMP_WORDS[@]}" \
               awk -v IGNORECASE=1 -v p="$2" \
  • That worked although I didn't need to awk part. – Ivan Wills May 22 '15 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.