0

我无法弄清楚我做错了什么。我的 bash_completion 文件设置如下:

_bcd()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "$(back_directory.pl --complete $cur)" -- $cur) )
}
complete -o filenames -o nospace -F _bcd bcd

back_directory.pl 是一个程序,它将返回树上的目录路径: back_directory.pl --complete Th产生:This\ test/ 但是:

22:50:24-Josh@Joshuas-MacBook-Air:~/Desktop/bcd/This test/more    white/t$ bcd Th<TAB><TAB>
This   test/

如上所示,它不会自动完成其中包含空格的目录(但它会显示完成选项)。

它应该如下所示:bcd This\ test/

我认为-o filenames应该添加反斜杠来转义空格。谢谢你的帮助 :)

4

2 回答 2

3

您的单次调用会compgen产生一个单词(包含嵌入的换行符),因此您只需将一个可能的完成添加到COMPREPLY. 相反,您需要一次处理back_directory.pl一项的输出。每个项目都作为可能的匹配项进行测试,如果compgen返回非空字符串,则将其添加到COMPREPLY.

_bcd() {
    local cur=${COMP_WORDS[COMP_CWORD]}
    IFS=: read -a matches < <(back_directory.pl --complete "$cur")
    for match in "${matches[@]}"; do
        possible=$(IFS= compgen -W "$match" -- "$cur")
        [[ $possible ] && COMPREPLY+=( "$possible" )
    done
}

(注意:我假设back_directory.pl会产生单行输出,类似于

directory1:directory two:directory three:directory4

)

于 2014-11-27T14:32:03.520 回答
1

为了完整起见,这是最终文件:

_bcd()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    IFS=: read -a matches < <(back_directory.pl --complete "$cur")
    for match in "${matches[@]}"; do
        possible=$(IFS= compgen -W "$match" -- "${cur#/}")
        [[ $possible ]] && COMPREPLY+=( "$possible" )
    done

    longest=""
    for e in "${COMPREPLY[@]}"; do
        if [[ "$longest" == "" ]]; then
            longest="$e"
        fi
        while [[ ! "$e" =~ ^$longest ]]; do
            longest=${longest%?}
        done
    done

    if [[ $longest != "$input" && "$cur" =~ ^/ ]]; then
        for ((i=0; i<${#COMPREPLY[@]}; i++))
        do
            COMPREPLY[$i]="/${COMPREPLY[$i]}"
        done
    fi
}
complete -o filenames -o nospace -F _bcd bcd

该脚本back_directory.pl --complete将返回由冒号分隔的单行路径。

我的解决方案似乎很糟糕,但它确实有效。

基本上它从当前单词中删除一个开始斜杠,创建所有匹配项(不包含开始斜杠),然后检查是否$longest与 不同$input,这意味着 bash 会将您当前的单词更改为不同的东西——在这种情况下,我们添加回一个开始的斜线。

于 2014-11-27T17:16:05.623 回答