Gostaria de criar uma regra de conclusão para a lista de parâmetros separados por vírgula. Por exemplo, eu tenho um comando que recebe a lista de nomes de servidores:
myscript -s name1,name2,name3
Neste momento, consegui escrever a seguinte conclusão:
_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
}
Mas tem pelo menos 2 problemas:
- As sugestões para o valor atual incluem todos os valores anteriores em seu prefixo.
- Não considera valores duplicados.
Quais são as melhores práticas para esses casos? Talvez o bash-completeions tenha algumas funções incluídas no csv-lists?
bash
autocomplete
diffycat
fonte
fonte
IFS=, LIST=("$VARIABLE")
onde $ VARIABLE contém seus valores separados por vírgula.$VARIABLE
, caso contrário a quebra de palavras não acontece. apenas useIFS=, LIST=($VARIABLE)
.Respostas:
Basicamente, não há como corrigir os problemas que você descreve, porque o bash usa os valores
COMPREPLY
diretamente na tela e, em seguida, substitui o texto do usuário - enquanto, para obter o que deseja, você precisa primeiro gerar as possíveis conclusões (apenas as informações adicionais). nomes de servidor, sem o prefixo) para que o bash seja exibido; quando o bash estiver prestes a substituir o texto do usuário pela string mais longa e sem conflito, você precisará chamar o script novamente para gerar o texto com o prefixo - e bash não tem facilidade para isso.O melhor que pude sugerir é que
COMPREPLY
seja gerado apenas a primeira palavra com o prefixo inteiro (COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )
), para que, se houver apenas uma conclusão possível, ela seja concluída automaticamente corretamente, enquanto se houver mais de uma conclusão possível , o bash não removerá o que foi digitado até o momento (porque a primeira palavraCOMPREPLY
tem o prefixo inteiro e, portanto, corresponde ao texto digitado no momento e será selecionado pelo bash para substituir o texto do usuário) e exibirá as opções sem o prefixo - exceto para aquela palavra que já contém o prefixo, a saída terá a seguinte aparência:"apple", conforme classificado pela última vez nas opções de conclusão, pois contém o prefixo que começa com "b" - muito confuso. Então, eu não recomendo fazer isso.
Com relação às duplicatas - para não mostrar duplicatas, você só precisa dividir
$prefix
sua parte (easyIFS="," prefix_parts=($prefix)
:) e iterar sobre elas e deixar apenas$servers
os nomes que ainda não estão listados. É tedioso digitar, então não vou mostrá-lo aqui, mas relativamente trivial, então tenho certeza que você pode gerenciar :-).Para resumir, não acho que você deva usar valores separados por vírgula para opções de entrada, pelo menos se você espera que o bash o ajude na conclusão.
Você pode oferecer suporte a um formato de opções como este:
command -s <server> [<server> [..]]
e, em seguida, para a conclusão de entradas diferentes daquela imediatamente após a-s
opção, basta percorrer a$COMP_WORDS
matriz$COMP_CWORD
até encontrar uma opção (sequência que corresponda-*
) e, se for "-s", você precisa concluir o nome do servidor.fonte