views:

48

answers:

1

I have directories full of files with the same prefix, which I want to be able to quickly open in vim. For example, I might have:

$ ls *
bar:
bar_10  bar_20  bar_30

foo:
foo_10  foo_20  foo_30

What I want is to be able to be in one of these directories and type:

$ vim <TAB>

and it autocomplete to:

$ vim bar_

To achieve this I am happy to have a file per directory called ".completion" which has "bar_" in it.

The issue I have is I would like the following behaviour:

  * "vim <TAB>"  -->  "vim bar_"           // no space
  * "vim bar_1"  -->  "vim bar_10 "        // space

Where | is the cursor, so if a file matches, add the space on the end. If we're matching the prefix, don't add a space.

The best I have so far is this behaviour minus the adding a space at the end. I've tried all sorts of things, all to no avail. The following is what I have:

_vim()
{
    local cur opts
    local -a toks

    cur="${COMP_WORDS[COMP_CWORD]}"

    if [ -f .completion ]; then
        opts=`cat .completion`

        if [[ ${opts} = ${cur} ]]; then
            toks=( $(compgen -f ${cur} | sed -e 's/$/ /') )
        else
            if [[ -z ${cur} ]]; then
                toks=( $(compgen -W "${opts}" -- ${cur}) )
            else
                toks=( $(compgen -f ${cur} | sed -e 's/$/ /') )
            fi
        fi
    else
        toks=( $(compgen -f ${cur} | sed -e 's/$/ /') )
    fi

    COMPREPLY=( "${toks[@]}" )
}

complete -F _vim -o nospace vim

Any ideas on how I can get it to add the space after the file name completion, but not after the prefix completion would be greatly appreciated.

A: 

The trailing space that sed is adding is getting dropped. Try this:

saveIFS=$IFS
IFS=$'\n'    # this will allow filenames with spaces (but not filenames with newlines)
toks=( $(compgen -f -- "${cur}" ))    # the -- protects against filenames that start with a hyphen
toks=("${toks[@]/%/ }")    # add a trailing space to each element
IFS=$saveIFS
Dennis Williamson
This doesn't seem to quite work. It seems to flatten toks to be a single element array.
d.haresign
@d.haresign: I edited my answer to fix a missing `)`. Once I did that, the array works fine for me.
Dennis Williamson
You're quite right, it does work... but only with bash 4. In bash 3 it seems to flatten the array. I've upgraded to bash 4. Thanks.
d.haresign
@d.haresign: In Bash 3 (and 4) it works if you don't change `IFS` (but you don't get protection for filenames with spaces). **However** instead of having a separate step to add the space, let `compgen` do it for you: `saveIFS=$IFS; IFS=$'\n'l toks=( $(compgen -S " " -f -- "${cur}")); IFS=$saveIFS`. That will work in Bash 3 or 4.
Dennis Williamson
@dennis: I just came back to say the very same thing :-)
d.haresign