15

This question is quite similar to this one, but I can't understand the solution. I also know this tutorial, but still I am unable to understand what I am doing wrong.

I am trying to autocomplete the list of directories that are placed in /something/:

$ ls /something/

One    Other    Three

in a way that this will happen:

$ hi [TAB]

One Other Three
$ hi O[TAB]

One Other

Only when the first word is hi and not only inside /something/.

This is what I am doing in .profile:

_codeComplete()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen `ls /something/` -- $cur) )

}
complete -F _codeComplete "hi "
15

Try:

_codeComplete()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "$(ls /something/)" -- $cur) )
}

complete -F _codeComplete hi

You need to specify the -W option in compgen and also quote the command which produces the wordlist.

More information on how to write completion functions on this blog: Writing your own Bash Completion Function

  • 6
    This will fail on file names containing whitespace and other special characters. – Gilles Jan 4 '12 at 23:39
  • 2
    It is weirdly difficult to find the name of the complete command if you don't already know it and are searching for autocomplete or tab-completion... This was the first place I found the command name, and what I needed to fix it for eject on upgrade to Ubuntu 14.04 ($ complete -p ls -> complete -F _longopt ls, so the fix was: complete -F _longopt eject) (Here's hoping this comment helps others find it!) – Izkata Sep 1 '14 at 20:10
1

Let me try to improve upon the accepted answer.

The original answer will fail with filenames containing whitespace. After some investigation I realize you can change the input separator to end-of-line:

IFS=$'\n'

making the function handle spaces correctly.

_codeComplete()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    IFS=$'\n' tmp=( $(compgen -W "$(ls ~/something/ )" -- $cur))
    COMPREPLY=( "${tmp[@]// /\ }" )
}

complete -F _codeComplete hi
0

Here's a version that not only handles spaces, but escapes them, too:

_codeComplete()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local AUTO_COMPLETE_DIRS=$(ls /something/)

    IFS=$'\n' COMPREPLY1=( $(compgen -W "$AUTO_COMPLETE_DIRS" -- $cur))
    COMPREPLY2=( "${COMPREPLY1[@]// /\ }" )
    COMPREPLY=($(printf "%q\n" "${COMPREPLY2[@]}"))

}
complete -F _codeComplete "hi "

(Based on dogbane's and Eduardo Almeida dos Santos' answers, but with escaping as provided by antak on SO: https://stackoverflow.com/a/11536437/1536933)

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.