Chciałbym utworzyć regułę uzupełniania dla listy parametrów oddzielonych przecinkami. Np. Mam polecenie, które otrzymuje listę nazw serwerów:
myscript -s name1,name2,name3
W tej chwili udało mi się napisać następujące uzupełnienie:
_myscript () {
local cur prev opts
_get_comp_words_by_ref cur prev
opts='-s'
servers='name1 name2 name3'
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
else
case "${prev}" in
-s)
if [[ "$cur" == *,* ]]; then
local realcur prefix
realcur=${cur##*,}
prefix=${cur%,*}
COMPREPLY=( $(compgen -W "${servers}" -P "${prefix}," -- ${realcur}) )
else
COMPREPLY=( $(compgen -W "${servers}" -- ${cur}) )
fi
;;
*)
# do nothing
;;
esac
fi
}
Ale ma co najmniej 2 problemy:
- Sugestie dotyczące bieżącej wartości zawierają wszystkie poprzednie wartości w swoich przedrostkach.
- Nie uwzględnia zduplikowanych wartości.
Jakie są najlepsze praktyki w takich przypadkach? Może bash-complete ma jakieś funkcje w pakiecie dla list csv?
bash
autocomplete
diffycat
źródło
źródło
IFS=, LIST=("$VARIABLE")
gdzie $ VARIABLE zawiera wartości oddzielone przecinkami.$VARIABLE
, w przeciwnym razie nie dojdzie do dzielenia słów. po prostu użyjIFS=, LIST=($VARIABLE)
.Odpowiedzi:
Zasadniczo nie ma sposobu, aby rozwiązać opisywane problemy, ponieważ bash używa wartości
COMPREPLY
bezpośrednio na wyświetlaczu, a następnie zamienia tekst użytkownika - podczas gdy aby uzyskać to, czego chcesz, musisz najpierw wygenerować możliwe uzupełnienia (tylko dodatkowe nazwy serwerów bez prefiksu), aby wyświetlić bash, a gdy bash zamierza zastąpić tekst użytkownika najdłuższym nie powodującym konfliktu łańcuchem, konieczne będzie ponowne wywołanie skryptu w celu wygenerowania tekstu z prefiksem - i bash nie ma na to możliwości.Najlepsze, co mogłem wymyślić, to
COMPREPLY
wygenerować tylko pierwsze słowo z całym prefiksem (COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )
), aby jeśli było tylko jedno możliwe uzupełnienie, kończy się ono automatycznie, a jeśli jest więcej niż jedno możliwe uzupełnienie , wtedy bash nie usunie tego, co zostało wpisane do tej pory (ponieważ pierwsze słowoCOMPREPLY
ma cały prefiks, a zatem pasuje do aktualnie wpisanego tekstu i zostanie wybrane przez bash, aby zastąpić tekst użytkownika) i wyświetli opcje bez prefiksu - z wyjątkiem dla tego jednego słowa, które już zawiera prefiks, więc wynik będzie wyglądał następująco:„jabłko” posortowane jako ostatnie w opcjach uzupełniania, ponieważ zawiera przedrostek zaczynający się na „b” - bardzo mylące. Więc nie polecam tego robić.
Jeśli chodzi o duplikaty - aby nie pokazywać duplikatów, wystarczy włamać się
$prefix
do jego części (łatweIFS="," prefix_parts=($prefix)
:), a następnie iterować nad nimi i pozostawić tylko w$servers
nazwach, które nie są jeszcze wymienione. To żmudne pisanie, więc nie pokażę go tutaj, ale stosunkowo trywialne, więc jestem pewien, że dasz radę :-).Podsumowując, nie sądzę, że powinieneś używać wartości oddzielonych przecinkami dla opcji wprowadzania, przynajmniej jeśli oczekujesz, że bash pomoże ci w zakończeniu.
Możesz obsługiwać format opcji podobny do tego:
command -s <server> [<server> [..]]
a następnie w celu uzupełnienia wpisów innych niż ten bezpośrednio po-s
opcji, po prostu zeskanuj z powrotem$COMP_WORDS
tablicę od,$COMP_CWORD
aż znajdziesz opcję (pasujący łańcuch-*
), a jeśli jej „-s” to musisz uzupełnić nazwę serwera.źródło