bash - 当我的单词包含冒号时如何给出正确的选项卡完成建议

标签 bash bash-completion

我正在为一个有时需要完整 URL 的实用程序编写一个 bash 选项卡完成文件:protocol://host:port。这包含两个冒号,已被证明对制表符完成有问题。这是因为冒号被视为分词符。我读到我不应该直接更改 COMP_WORDBREAKS,所以我想按照此处的建议使用 _get_comp_words_by_ref__ltrim_colon_completions:How to reset COMP_WORDBREAKS without effecting other completion script?

这适用于单个冒号,但第二个冒号会导致一个小问题,如这个最小示例所示:

这个例子说明了问题。它出现在建议中的任意数量的冒号上。

[root@2e3e8853cc0c /]# cat /etc/bash_completion.d/foo 
_foo()
{
    local cur
    COMPREPLY=()
    _get_comp_words_by_ref -n : -c cur

    COMPREPLY=( $(compgen -W "http://host:1234/aaa http://host:1234/bbb http://host:1234/ccc" -- ${cur}) )
    __ltrim_colon_completions "$cur"
    return 0
}
complete -F _foo foo

foo 成功完成公共(public)部分后点击 tab。之后点击 Tab 键两次,会产生以下建议:

[root@2e3e8853cc0c /]# foo http://host:1234/
1234/aaa  1234/bbb  1234/ccc

想要的结果当然是:

[root@2e3e8853cc0c /]# foo http://host:1234/
http://host:1234/aaa  http://host:1234/bbb  http://host:1234/ccc

之后,点击 a、b 或 c 加选项卡按预期工作,它完成了完整的 URL。

关于如何生成正确输出的任何建议?我是否需要手动更改 COMPREPLY 变量,还是我只是使用了错误的函数?

最佳答案

基于我一直使用的一个技巧,我想出了一个解决方案。希望对您有所帮助。

_bar()
{
    local CUR=$2
    local cur
    local -a compreply=()
    local -a urls=(ftp://gnu.org \
                   http://host1:1234/aaa \
                   http://host2:1234/bbb \
                   http://host2:1234/ccc)

    _get_comp_words_by_ref -n : -c cur

    compreply=( $(compgen -W "${urls[*]}" -- "$cur") )
    COMPREPLY=( "${compreply[@]}" )
    __ltrim_colon_completions "$cur"

    if [[ ${#COMPREPLY[@]} -gt 1 ]]; then
        local common_prefix
        common_prefix=$( printf '%s\n' "${COMPREPLY[@]}" \
                         | sed '$q;N;s/^\(.*\).*\n\1.*$/\1/;h;G;D' )
        if [[ $common_prefix == "$CUR" ]]; then
            COMPREPLY=( "${compreply[@]}" " " )
        fi
    fi

    return 0
}

complete -F _bar bar

下面是它的样子(使用 Bash 4.3.33 测试):

[STEP 101] $ bar <TAB><TAB>
                       http://host1:1234/aaa  http://host2:1234/ccc
ftp://gnu.org          http://host2:1234/bbb
[STEP 101] $ bar f<TAB>
[STEP 101] $ bar ftp://gnu.org␣
[STEP 101] $ bar ftp://gnu.org <ENTER>
bash: bar: command not found
[STEP 102] $ bar h<TAB>
[STEP 102] $ bar http://host
[STEP 102] $ bar http://host<TAB><TAB>
                       http://host2:1234/bbb
http://host1:1234/aaa  http://host2:1234/ccc
[STEP 102] $ bar http://host2<TAB>
[STEP 102] $ bar http://host2:1234/
[STEP 102] $ bar http://host2:1234/<TAB><TAB>
                       http://host2:1234/bbb  http://host2:1234/ccc
[STEP 102] $ bar http://host2:1234/b<TAB>
[STEP 102] $ bar http://host2:1234/bbb␣
[STEP 102] $ bar http://host2:1234/bbb <ENTER>
bash: bar: command not found
[STEP 103] $

实际上这个问题并不特定于两个或多个冒号。一个冒号也有类似的问题。

关于bash - 当我的单词包含冒号时如何给出正确的选项卡完成建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28479216/

相关文章:

linux - 将 laravel 添加到路径(Linux Mint 18.2 sonya)

bash - 在bash中生成脚本并保存到需要sudo的位置

bash - 我可以在 Cygwin 中使用类似 UNIX 的路径使用什么文件资源管理器?

bash - 如何使用 xargs 替换 2 个参数

bash - 在 bash 中,如何在键入命令行时扩展 !$?

bash - Shell脚本对编码和行尾敏感吗?

bash - 如何使用即时定义的 bash 完成函数?

git - 分支自动完成不适用于推送的 git 别名

linux - 在 shell 中自定义制表符补全

bash - 如何自动完成特定目录下的文件?