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

时间:2016-08-26 08:28:16

标签: bash symfony autocomplete

我正在使用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//:}

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

为什么?怎么解决?

修改

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

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

1 个答案:

答案 0 :(得分:5)

这可能与您的robo compspec无关。也不是与_scp相关联的scp完成功能。

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

您从分隔符列表中删除了:。显然,_scp非常强大,可以使用:作为单词分隔符,但行为相同。它返回相同的候选完成列表。但是当_scp仅返回一个完成的候选者时,替换的令牌,例如scp host:public_hthost:public_ht,而非public_ht。证明:

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

如果您尝试完成foobar host:public_ht,则会获得foobar host:bazcux,因为替换的令牌只是public_ht。同时:

$ COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
$ echo $COMP_WORDBREAKS
"'><=;|&(

如果您尝试完成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

一个(显然)更简单的解决方案包括用_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

所有这些可能都不是你想要的。我不知道robo.il并且可能有许多改进需要考虑更多背景来提出具体的完成情况。但这可能是一个起点。