Atualmente estou trabalhando em um script de shell que chamei makeyourself.sh
(vinculado a /usr/bin/mys
) que instala automaticamente um pacote debian da fonte (via apt-get source -b $1
).
Então decidi adicionar uma função de preenchimento automático para o nome do pacote que é fornecido como primeiro parâmetro: sudo mys panth<tab><tab>
deveria então listar todos os pacotes começando com panth
- minha tentativa foi a seguinte:
complete -C "apt-cache --no-generate pkgnames" mys
Mas parece que não funciona: quando pressiono a tecla tab como mencionado acima, at muda o parâmetro para mys
, que me retorna sudo mys mys
.
O que estou fazendo de errado? Devo especificar o local no comando onde complete
devo inserir a string que deve ser preenchida, como {}
ou $1
?
Eu uso ElementaryOS, uma distribuição Linux baseada no Ubuntu. O script é um script de shell *.sh padrão que usa o padrão#!/bin/bash
Responder1
Como você suspeita, o comando recebe algumas informações sobre o que fazer. Isso está documentado no manual, mas não nodocumentação do complete
builtin, você precisa ler oseção introdutória sobre conclusão programável.
qualquer função ou comando shell especificado com as opções
-F
e-C
é invocado. Quando o comando ou função é invocado, as variáveisCOMP_LINE
,COMP_POINT
,COMP_KEY
eCOMP_TYPE
recebem valores conforme descrito acima (consulteVariáveis Bash). Se uma função shell estiver sendo invocada, as variáveisCOMP_WORDS
eCOMP_CWORD
também serão definidas. Quando a função ou comando é invocado, o primeiro argumento é o nome do comando cujos argumentos estão sendo concluídos, o segundo argumento é a palavra que está sendo concluída e o terceiro argumento é a palavra que precede a palavra que está sendo concluída na linha de comando atual. Nenhuma filtragem das conclusões geradas em relação à palavra que está sendo concluída é executada; a função ou comando tem total liberdade na geração das partidas.
Portanto o comando é chamado com três parâmetros:
- O nome do comando — para que você possa combinar conclusões de comandos semelhantes em um script.
- A palavra a ser completada — para que você possa limitar a saída ao prefixo que será filtrado de qualquer maneira.
- A palavra anterior — útil, por exemplo, para completar opções.
Os mesmos parâmetros são passados para funções de conclusão ( complete -F somefunction
). Observe que, quer você use uma função ou um comando, é sua função filtrar as correspondências desejadas.
Com o que você tentou, o comando que acaba sendo executado é o apt-cache --no-generate pkgnames mys '' mys
. Isso imprime uma lista de nomes de pacotes que começam com mys
( apt-cache pkgnames
olha apenas o primeiro operando). O prefixo comum mais longo é mys
, então o bash começa a completar mys
e espera que você selecione a próxima letra.
Dado que os argumentos são anexados ao comando (não passados como parâmetros posicionais — o argumento para -C
é analisado como um comando shell), não há uma maneira fácil de analisá-los. A solução mais simples é usar uma função wrapper.
_mys () {
COMPREPLY=$(apt-cache --no-generate pkgnames "$2")
}
complete -F _mys mys