2016-08-26 2 views
9

Я использую инструменты PHP http://robo.li и n98-magerun.phar - оба они основаны на компонентах CLI Sympfony.Symfony autocomplete breaks SCP autocomplete

Когда я использую такое автозаполнение сценарий:

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 (который обычно завершает файлы на удаленном сервере - но с этим - несвязанным - завершение робо на месте, УППЫ Снимают имя хоста из команды)

Почему это? Как исправить?

EDIT

на основе ответа, фиксированная версия здесь:

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

+2

Это не решит вашу проблему, но обратите внимание на то, что скрипты завершения: * sourced * (обычно в '~/.bashrc' или'/etc/bash.bashrc'), поэтому строка shebang несущественна. Если бы это было * не * проигнорировано, все бы ломалось, потому что 'sh' не знает о массивах, но вы их используете. –

ответ

3

Это не имеет, вероятно, ничего общего с robo compspec. Также не выполняется функция завершения _scp, связанная с scp.

Возможно, это связано с вашим COMP_WORDBREAKS=${COMP_WORDBREAKS//:}.

Вы удалили : из списка разделителей. Очевидно, _scp достаточно прочен, чтобы вести себя с : или без него в качестве разделителя слов. Он возвращает тот же список доработок кандидата. Но токен, который заменяется, когда _scp возвращает только один кандидат для завершения, например. scp host:public_ht, is host: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, и, вероятно, есть много улучшений, которые учитывают больше контекста, чтобы предложить конкретные доработки. Но это может быть отправной точкой.

+0

«Решение вашей проблемы, вероятно, заключается в том, чтобы адаптировать вашу функцию завершения _robo таким образом, чтобы она не требовала: не является разделителем слов». как это будет работать? примерно? Где это требуется для этих слов? – Alex

+0

Ах, дело в том, что команды robo/symfony выглядят следующим образом: 'robo main: sub: subsubcommand', поэтому, возможно, именно поэтому словоseperator приходит на место. Можно ли активировать этот разделитель слов только для 'robo' &' magerun', а не для 'scp'? – Alex

+1

@Alex Нет, я не думаю, что вы можете специализировать 'COMP_WORDBREAKS' за команду, к сожалению. Вам действительно нужно реализовать более сложную функцию '_robo' для 1) проанализировать массив' COMP_WORDS' назад, начиная с 'COMP_CWORD', чтобы построить' main: sub: subsu' stem, 2) вызов 'compgen', чтобы получить все возможные пополнения, 3) удалите из них стержень и верните результат. Обратите внимание, что это две возможности: завершение слово-уровня (остановка в ':' как завершение пути заканчивается на '/') или полное заполнение группы. Это твой выбор. –