bashcompgen

How to make bash autocomplete work in the middle of line?


How to write autocomplete in bash, so that if I have:

mycommand first_argument|garbage

where | denotes the cursor, it should pass "first_argument" and not "first_argumentgarbage" to compgen?

In the examples I have it behaves in the wrong way

COMPREPLY=( $(compgen -W "add remove list use current" -- "$cur") ) # buggy

Solution

  • Bash completion uses a lot of different variables. Some of them are used to process input and determine which parameter to complete.

    For the following explanation, I will use this test input (with | as the cursor) :

    ./test.sh ad re|garbage
    

    Still using the same data, doing cur=${COMP_WORDS[COMP_CWORD]} will return the element at index 2 in the ${COMP_WORD} array, which is regarbage.

    To circumvent this behaviour, you'll have to play around with the $COMP_LINE and $COMP_POINT variables as well. Here is what I came up with :

    # we truncate our line up to the position of our cursor
    # we transform the result into an array
    cur=(${COMP_LINE:0:$COMP_POINT})
    
    # we use ${cur} the same way we would use ${COMP_WORDS}
    COMPREPLY=( $( compgen -W "add remove list use current" -- "${cur[$COMP_CWORD]}" ) )
    

    Output :

    > ./test2.sh ad re|garbage
    # press TAB
    > ./test2.sh ad remove|garbage
    

    Note that by default, there will be no space between remove and garbage. You'll have to play around the completion mechanics if this is a behaviour you want.