2016-08-26 23 views
9

Używam narzędzi PHP http://robo.li i n98-magerun.phar - oba oparte są na składnikach CLI Sympfony.Autouzupełnianie oparte na symfony zrywa autouzupełnianie SCP

Kiedy użyć takiego skryptu autouzupełniania:

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//:} 

To łamie autouzupełniania dowodzenia w scp (który zwykle wypełnia plików na zdalnym serwerze - ale z tym - niepowiązanych - Zakończenie robo w miejscu, usuwa SCP nazwa hosta z polecenia)

Dlaczego tak jest? Jak naprawić?

EDIT

na podstawie odpowiedzi, wersja ustalona jest tutaj:

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

+2

To nie rozwiąże twojego problemu, ale uwaga boczna: skrypty ukończenia * pochodzą *, (zazwyczaj w '~/.bashrc' lub'/etc/bash.bashrc'), więc linia shebang jest nieistotna. Gdyby to * nie * zostało zignorowane, wszystko by się zepsuło, ponieważ 'sh' nie wie o tablicach, ale używasz ich. –

Odpowiedz

3

Ma to prawdopodobnie nic wspólnego z robo compspec. Ani z funkcją uzupełniania _scp powiązaną z scp.

Jest to prawdopodobnie spowodowane Twoim COMP_WORDBREAKS=${COMP_WORDBREAKS//:}.

Usunąłeś : z listy separatorów. Najwyraźniej _scp jest wystarczająco odporny, aby zachowywać się tak samo z lub bez : jako separatora słów. Zwraca tę samą listę kandydujących uzupełnień. Ale token, który zostaje zastąpiony, gdy _scp zwraca tylko jednego kandydata do ukończenia, np. scp host:public_ht, to host:public_ht, zamiast tylko public_ht. Dowód:

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

Jeśli spróbować wypełnić foobar host:public_ht, masz foobar host:bazcux ponieważ podstawione Token jest tylko public_ht. Choć z:

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

jeśli spróbować wypełnić foobar host:public_ht, masz foobar bazcux ponieważ pełna host:public_ht że otrzymuje bazcux.

Rozwiązaniem problemu jest prawdopodobnie dostosowanie funkcji uzupełniania _robo w taki sposób, aby nie wymagać, aby : nie był separatorem słów. Coś jak:

_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 

Znacznie (podobno) prostsze rozwiązanie polega na zastąpieniu funkcji _stem powyżej istniejącego __reassemble_comp_words_by_ref funkcji bash_completion Biblioteka:

_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 

Wszystko to prawdopodobnie nie jest to dokładnie to, co chcesz . Nie wiem, robo.il i prawdopodobnie istnieje wiele ulepszeń, które wymagałyby większego kontekstu, aby zaproponować konkretne uzupełnienia. Ale może to być punkt wyjścia.

+0

"Rozwiązaniem twojego problemu jest prawdopodobnie dostosowanie funkcji _robo completion tak, aby nie wymagała ona: nie jest separatorem słów." jak by to działało? w przybliżeniu? Gdzie to jest potrzebne? – Alex

+0

Ach, chodzi o to, że komendy robo/symfony wyglądają tak: 'robo main: sub: subsubcommand', więc może właśnie dlatego program wordisperator przychodzi na miejsce. Czy jest możliwe aktywowanie tego separatora słów tylko dla 'robo' i' magerun', a nie dla 'scp'? – Alex

+1

@Alex Nie, nie sądzę, że możesz specjalizować 'COMP_WORDBREAKS' na polecenie, niestety. Naprawdę będziesz musiał zaimplementować nieco bardziej złożoną funkcję '_robo' do 1) parsować tablicę' COMP_WORDS' wstecz, zaczynając od 'COMP_CWORD', aby zbudować' main: sub: subsu' stem, 2) wywołać 'compgen', aby uzyskać wszystkie możliwe uzupełnienia, 3) usuń z nich łodygę i zwróć wynik. Zauważ, że są to dwie możliwości: uzupełnianie na poziomie słowa (zatrzymywanie w ':' jak kończenie ścieżki zatrzymuje się na '/') lub pełne uzupełnienie grupy. To jest twój wybór. –