Pragmatism in the real world

Autocomplete Composer script names on the command line

As I add more and more of my own script targets to my composer.json files, I find that it would be helpful to have tab autocomplete in bash. I asked on Twitter and didn’t get an immediate solution and as I had already done something similar for Phing, I rolled up my sleeves and wrote my own.

Start by creating a new bash completion file called composer in the bash_completion.d directory. This file needs executable permission. This directory can usually be found at /etc/bash_completion.d/, but on OS X using Homebrew, it’s at /usr/local/etc/bash_completion.d/ (assuming you have already installed with brew install bash-completion).

This is the file:

# Store this file in /etc/bash_completion.d/composer

_composer_scripts() {
    local cur prev
    _get_comp_words_by_ref -n : cur

    COMPREPLY=()
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    #
    #  Complete the arguments to some of the commands.
    #
    if [ "$prev" != "composer" ] ; then
        local opts=$(composer $prev -h --no-ansi | tr -cs '[=-=][:alpha:]_' '[\n*]' | grep '^-')
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi


    if [[ "$cur" == -* ]]; then
        COMPREPLY=( $( compgen -W '-h -q -v -V -n -d \
            --help --quiet --verbose --version --ansi --no-ansi \
            --no-interaction --profile --working-dir' -- "$cur" ) )
    else
        local scripts=$(composer --no-ansi 2> /dev/null |  awk '/^ +[a-z]+/ { print $1 }')
        COMPREPLY=( $(compgen -W "${scripts}" -- ${cur}) )
    fi

    __ltrim_colon_completions "$cur"
    return 0
}

complete -F _composer_scripts composer

(Note that __ltrim_colon_completions is only in recent versions of bash-completion, so you may need to remove this line.)

Reading from the bottom, to get the list of commands to composer, we create a list of words for the -W option to compgen by running composer --no-ansi and then manipulating the output to remove everything that isn’t a command using awk. We also create a separate list of flag arguments when the user types a hyphen and then presses tab.

Finally, we also autocomplete flags for any subcommand by running composer {cmd} -h --no-ansi and using tr and grep to limit the list to just words starting with a hyphen.

That’s it. Now composer {tab} will autocomplete both built-in composer commands and also custom scripts!

Composer autocomplete

As you can see, in this example, in addition to the built-in commands like dump-autoload and show, you can also see my custom scripts, including apiary-fetch and .

This is very helpful for when my memory fails me!

9 thoughts on “Autocomplete Composer script names on the command line

  1. This is a very helpful script.

    For macOS users: don't forget to install Bash Completion by running "brew install bash-completion".

    1. I installed bash-completion on OSX, restarted my terminal, but for some reason it is still not working.

      jkeppens$ brew ls –versions bash-completion
      bash-completion 1.3_2

      The file has executable rights:

      jkeppens$ ls -al /usr/local/etc/bash_completion.d/composer
      -rwxr-xr-x 1 jkeppens admin 962 Jun 9 13:49 /usr/local/etc/bash_completion.d/composer

      Anything I need to do to activate bash-completion apart from installing it?

  2. Thanks for this Rob! How great that this feature of Bash is so extensible and thanks for taking the time to share this.

    But I'm having a philosophical crisis with composer scripts – as soon as I need a bit of complexity, I find myself creating a plain ol' Bash script stored in ../bin. So that means I have some things as composer scripts, and some things in ../bin. Not very nice for Future Me (or a teammate someday) to have to look in two places.

    Do you have that same issue?

    1. Greg,

      When it's not a trivial call to something like PHPUnit, I usually create a script in bin and then reference it as a composer script.

Comments are closed.