Search code examples
bashdirectorybash-completion

custom directory completion appends whitespace


I have the following directory structure:

/home/tichy/xxx/yyy/aaa
/home/tichy/xxx/yyy/aab
/home/tichy/xxx/yyy/aac

I would like to enter cdw y<TAB> and get cdw yyy/<CURSOR> as a result, so I could add cdw yyy/a<TAB> and get cdw yyy/aa<CURSOR>

The solution I came up with gives me the following:
cdw y<TAB> => cdw yyy<SPACE><CURSOR>

Following code I have so far:

_cdw () {
    local cur prev dirs
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    COMPREPLY=($(compgen -d -- /home/tichy/xxx/${cur}|perl -pe 's{^/home/tichy/xxx/}{}'))
    # no difference, a bit more logical:
    dirs=$(compgen -o nospace -d /home/tichy/xxx/${cur}|perl -pe 's/{^/home/tichy/xxx/}{}')
    COMPREPLY=($(compgen -d -W ${dir} ${cur}|perl -pe 's{^/home/tichy/xxx/}{}'))
    return 0
}
complete -F _cdw cdw
cdw () {
    cd /home/tichy/xxx/$@
}

Any ideas what's wrong? It seems to me that the completion process seems to be finished and isn't expecting any more input.


Solution

  • How about something like this:

    COMPREPLY=( $(cdw; compgen -W "$(for d in ${cur}* ${cur}*/*; do [[ -d "$d" ]] && echo $d/; done)" -- ${cur}) )
    

    (I'm not sure if you can call your shell function from here or not, otherwise you may have to duplicate it a bit.)

    This also gets rid of your perl hack :-)