4

I'm trying to figure out how autocompletion works. I read this and the whole bash reference on complete, compgen and compopt, but this doesn't tell me how they really work together.

I'm trying to create an auto-completion for a command that takes a verb (from a rather small set) followed by the name of an existing file. So far I have this:

verbs=(upload download delete)

function ac_complete {
    printf "COMP_WORDS[%d/%d]: "  ${COMP_CWORD} ${#COMP_WORDS[@]}
    printf "[%s] " "${COMP_WORDS[@]}"
    printf "\n"
    
    if [[ COMP_CWORD -eq 1 ]] 
    then 
        COMPREPLY=( "${verbs[@]}" )
    else
        compopt -o default
    fi
}

complete -F ac_complete testit

but it doesn't work, I never see bash completing the verb.

  • How are possible completions returned?
  • What should be returned? Only those still valid at that point (ie, after a "d", should the set be "upload"/"download"/"delete" or only "download"/"delete" (if so there is a quick way to apply that restriction?)?

The completion for the file works, but I'd like to restrict it to few filetypes...

2
  • You could try zsh or fish, they both have IMHO an even better autocompletion than bash Commented Jun 12, 2020 at 12:14
  • On my target system I'm lucky I'm allowed to use bash...
    – xenoid
    Commented Jun 12, 2020 at 12:18

1 Answer 1

5

Look at the bash_completion package for examples.

The most common way to generate completions is to call compgen to build the COMPREPLY array. Figure out what arguments are valid this particular context, then translate that a compgen call. The compgen builtin filters arguments that aren't completions of the specified prefix. For example:

COMPREPLY=( $(compgen -W "${verbs[*]}" -- "${COMP_WORDS[COMP_CWORD]}") )

compgen is the step that figures out that to complete d, only download and delete are valid.

For files, use compgen -G "*.ext" to restrict the completion to files with the extension .ext. This simple idiom breaks on file names with spaces (or wildcard characters). The _filedir function from bash_completion handles file names in a more robust way (which still breaks on newlines and wildcard characters): _filedir '*.ext'.

4
  • So the gist of autocompletion is that COMPREPLY is an array of possible completions, and the comp* buil-ins are mostlly easy ways to generate these completions? How are spaced handled? Your answer doesn't seem to support spaces in verbs (curve ball, I know). Your file completion woudl also list all the files, I had to change it to compgen -G "${COMP_WORDS[COMP_CWORD]}*.txt" to have the expected completions, but this still doesn't work if there are files with spaces in the filename.
    – xenoid
    Commented Jun 12, 2020 at 12:11
  • @xenoid Sorry, that's more advanced than my bash knowledge (I use zsh). As far as I can tell, to deal with spaces in file names, use local IFS=$'\n' in your completion function. To deal with newlines or wildcard characters in file names, use zsh. Commented Jun 12, 2020 at 12:23
  • @xenoid Ah, looking at examples from bash_completion: use its _filedir function. Commented Jun 12, 2020 at 12:24
  • OK works great. Thx
    – xenoid
    Commented Jun 12, 2020 at 12:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .