基于Symfony的自动完成功能会破坏SCP自动完成功能

Ale*_*lex 9 bash autocomplete symfony

我正在使用PHP工具http://robo.li和n98-magerun.phar - 两者都基于Sympfony的CLI组件.

当我使用这样的自动完成脚本时:

https://gist.github.com/caseyfw/51bdbcb37e5dfb91b74e

#!/bin/sh
function __robo_list_cmds ()
{
      robo list --raw | awk '{print $1}' | sort
}

function __robo_list_opts ()
{
    robo list --no-ansi | sed -e '1,/Options:/d' -e '/^$/,$d' -e 's/^ *//' -e 's/ .*//' | sort
}

_robo()
{
    local cur="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=($(compgen -W "$(__robo_list_opts) $(__robo_list_cmds)" -- ${cur}))
    return 0;
}

complete -o default -F _robo robo
COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
Run Code Online (Sandbox Code Playgroud)

它打破了scp命令的自动完成(通常完成远程服务器上的文件 - 但是这与 - 无关 - robo完成到位,scp从命令中删除主机名)

这是为什么?怎么修?

编辑

根据答案,固定版本在这里:

https://gist.github.com/amenk/d68f1fe54b156952ced621f771ff48ba

Ren*_*let 5

这可能与您的robocompspec 没有关系。也没有与_scp关联的完成功能scp

这可能是由于您的COMP_WORDBREAKS=${COMP_WORDBREAKS//:}

您已从:分隔符列表中删除。显然,_scp它足够健壮,无论是否:使用单词分隔符,其行为都相同。它返回相同的候选完成列表。但是,当_scp仅返回一位候选人来完成时被替换的令牌,例如scp host:public_htis host:public_ht,而不是just public_ht。证明:

$ _foobar () { COMPREPLY=bazcux; return 0; }
$ complete -o default -F _foobar foobar
$ echo $COMP_WORDBREAKS
"'><=;|&(:
Run Code Online (Sandbox Code Playgroud)

如果尝试完成foobar host:public_ht,则会得到您的帮助,foobar host:bazcux因为替换的令牌是just public_ht。同时使用:

$ COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
$ echo $COMP_WORDBREAKS
"'><=;|&(
Run Code Online (Sandbox Code Playgroud)

如果尝试完成foobar host:public_ht,则会得到成功,foobar bazcux因为它是用host:public_ht代替的完整bazcux

解决您的问题的方法可能是调整您的_robo完成功能,使其不需要不是:单词分隔符。就像是:

_stem () {
    local lcur lprev
    lcur="$cur"
    stem="$lcur"
    for (( i = cword - 1; i >= 0; i -= 1 )); do
        lprev="${words[i]}"
        [[ $lcur == ":" ]] && [[ $lprev == ":" ]] && break
        [[ $lcur != ":" ]] && [[ $lprev != ":" ]] && break
        stem="$lprev$stem"
        lcur="$lprev"
    done
}

_robo () {
    local cur prev words cword
    _init_completion || return
    local stem options
    options=($(__robo_list_opts) $(__robo_list_cmds))
    COMPREPLY=()
    _stem
    COMPREPLY=($(compgen -W '${options[@]}' -- "$stem"))
    [[ $stem =~ : ]] && stem=${stem%:*}: && COMPREPLY=(${COMPREPLY[@]#"$stem"})
    return 0
}

complete -o default -F _robo robo
Run Code Online (Sandbox Code Playgroud)

一个(显然)更简单的解决方案是将上述_stem函数替换__reassemble_comp_words_by_ref为该bash_completion库的现有函数:

_robo () {
    local cur prev words cword
    _init_completion || return
    __reassemble_comp_words_by_ref ":" words cword
    options=($(__robo_list_opts) $(__robo_list_cmds))
    COMPREPLY=($(compgen -W '${options[@]}' -- "$cur"))
    return 0
}

complete -o default -F _robo robo
Run Code Online (Sandbox Code Playgroud)

所有这些可能都不完全是您想要的。我不知道robo.il,可能会有很多改进,这些改进将考虑更多上下文以提出具体的完成。但这可能是一个起点。