Adicione autocompletar para script personalizado

5

Atualmente estou trabalhando em um shell script chamado makeyourself.sh (vinculado a /usr/bin/mys ) que instala automaticamente um pacote debian a partir da origem (via apt-get source -b $1 ).

Então eu decidi adicionar uma função autocomplete para o nome do pacote que é dado como o primeiro parâmetro: sudo mys panth<tab><tab> deve listar todos os pacotes que começam 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, altera o parâmetro para mys , o que me retorna sudo mys mys .

O que estou fazendo de errado? Preciso especificar a localização no comando em que complete precisa inserir a sequência que deve ser preenchida, como {} ou $1 ?

Eu uso o ElementaryOS, uma distribuição Linux baseada no Ubuntu. O script é um script padrão * .sh que usa o padrão #!/bin/bash

    
por Luke 07.05.2014 / 19:50

1 resposta

2

Como você suspeita, o comando recebe algumas informações sobre o que completar. Isso está documentado no manual, mas não na documentação do complete builtin , você precisa ler a seção introdutória sobre conclusão programável .

any shell function or command specified with the -F and -C options is invoked. When the command or function is invoked, the COMP_LINE, COMP_POINT, COMP_KEY, and COMP_TYPE variables are assigned values as described above (see Bash Variables). If a shell function is being invoked, the COMP_WORDS and COMP_CWORD variables are also set. When the function or command is invoked, the first argument is the name of the command whose arguments are being completed, the second argument is the word being completed, and the third argument is the word preceding the word being completed on the current command line. No filtering of the generated completions against the word being completed is performed; the function or command has complete freedom in generating the matches.

Então o comando é chamado com três parâmetros:

  • O nome do comando - para que você possa combinar conclusões para 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 ex. para completar opções.

Os mesmos parâmetros são passados para as funções de conclusão ( complete -F somefunction ). Observe que, independentemente de você usar uma função ou um comando, é sua tarefa filtrar correspondências desejadas.

Com o que você tentou, o comando que acaba sendo executado é apt-cache --no-generate pkgnames mys '' mys . Isso imprime uma lista de nomes de pacotes que começam com mys ( apt-cache pkgnames apenas examina 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 existe uma maneira fácil de analisá-los. A solução mais simples é usar uma função de wrapper.

_mys () {
  COMPREPLY=$(apt-cache --no-generate pkgnames "$2")
}
complete -F _mys mys
    
por 08.05.2014 / 03:20