Is there anyway to get COMPREPLY to be output as a vertical list of words instead in a single line?

I'm the one that suggested changing the completion-display-width readline variable at /r/bash, but then you didn't specify you only wanted it to work on this one completion function.

Anyway, in a completion function, you can detect whether it's triggered by TAB (COMP_TYPE == 9) or by TABTAB (COMP_TYPE == 63), and if the latter is the case, you could pad the results with spaces so they fill the entire width of the terminal. It's the least hackish thing I can think of. It would look something like this:

_foo_complete() {
    local i file files
    files=( ~/work/dev/jobs/"$2"* )
    [[ -e ${files[0]} || -L ${files[0]} ]] || return 0
    if (( COMP_TYPE == 63 )); then
        for file in "${files[@]}"; do
            printf -v 'COMPREPLY[i++]' '%*s' "-$COLUMNS" "${file##*/}"
        done
    else
        COMPREPLY=( "${files[@]##*/}" )
    fi
}
complete -F _foo_complete foo

On a side note, you really shouldn't parse ls output.


To modify a readline variable for just a particular completion function, you can set the readline variable during function execution and then have $PROMPT_COMMAND change it back.

_foo_complete() {
    # retrieve the original value
    local width=$(bind -v | sed -n 's/^set completion-display-width //p')

    if [[ $width -ne 0 ]]; then
        # change the readline variable
        bind "set completion-display-width 0"

        # set up PROMPT_COMMAND to reset itself to its current value
        PROMPT_COMMAND="PROMPT_COMMAND=$(printf %q "$PROMPT_COMMAND")"

        # set up PROMPT_COMMAND to reset the readline variable
        PROMPT_COMMAND+="; bind 'set completion-display-width $width'"
    fi

    # whatever the function normally does follows
    COMPREPLY=(aa bb)
}
complete -F _foo_complete foo