自定义目录完成附加空格

时间:2011-12-14 10:42:55

标签: bash directory bash-completion

我有以下目录结构:

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

我想输入 cdw y< TAB> 并获取 cdw yyy /< CURSOR> ,因此我可以添加 cdw yyy / a< TAB> 并获取 cdw yyy / aa< CURSOR>

我想出的解决方案给了我以下内容:
cdw y< TAB> => cdw yyy< SPACE>< CURSOR>

以下代码我到目前为止:

_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/$@
}

任何想法有什么不对?在我看来,完成过程似乎已经完成,并且不期待任何更多的输入。

4 个答案:

答案 0 :(得分:7)

到目前为止,我发现的最简单的解决方案是生成如下所示的完成:

COMPREPLY=$( compgen -W "file1 file2 file3 dir1/ dir2/ dir3/" )

并在返回

之前添加此行
[[ $COMPREPLY = */ ]] && compopt -o nospace

每当完成可以填写直到斜杠时设置nospace选项,以便用户最终得到:

cmd dir1/<cursorhere>

而不是:

cmd dir1/ <cursorhere>

并且只要完成可以填写直到完整文件名以便用户最终得到:

,它就不会设置nospace选项
cmd file1 <cursorhere>

而不是:

cmd file1<cursorhere>

答案 1 :(得分:5)

如果我理解正确,你想要bash-autocomplete一个目录名,而不是有额外的空间? (当我到达这个页面时,这就是我想要的)。

如果是这样,当您注册完成功能时,请使用“-o nospace”。

complete -o nospace -F _cdw cdw

我不知道nospace是否适用于compgen。

答案 2 :(得分:2)

这样的事情怎么样:

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

(我不确定你是否可以从这里调用你的shell函数,否则你可能需要复制一下。)

这也消除了你的perl hack: - )

答案 3 :(得分:0)

完成为此提供了一个解决方案,没有任何解决方法:在/ etc / bash_completion中定义了funciton _filedir:

 626 # This function performs file and directory completion. It's better than
 627 # simply using 'compgen -f', because it honours spaces in filenames.
 628 # @param $1  If `-d', complete only on directories.  Otherwise filter/pick only
 629 #            completions with `.$1' and the uppercase version of it as file
 630 #            extension.
 631 #
 632 _filedir()

然后,指定以下内容就足够了:

_cdw () {
    local cur prev dirs
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    _filedir # add -d at the end to complete only dirs, no files
    return 0
}