Como criar uma autocompletação por Tab simples no Bash e no Zsh
(mill-build.org)- Introdução de como implementar, no Bash e no Zsh, um recurso de autocompletação por Tab que exibe descrições até mesmo para palavras já completas
- Bash e Zsh usam APIs de autocompletação diferentes, e apenas o Zsh oferece nativamente a função de mostrar descrições na autocompletação
- A estrutura implementa a geração de candidatos com
_generate_foo_completionse o retorno viaCOMPREPLYno Bash ecompaddno Zsh - Para implementar no Bash o recurso de descrições do Zsh, o texto da descrição é incluído na string candidata, e removido apenas quando há um único candidato
- Mesmo no caso de um único candidato, a solução melhora a experiência ao adicionar ambiguidade intencionalmente para que a descrição apareça ao pressionar
<TAB> - O script final oferece a mesma experiência de uso nos dois shells, com suporte a completação parcial, completação total e exibição de descrições dos candidatos
Contexto do problema
- A autocompletação por Tab (tab-completion) é útil para explorar comandos e flags, especialmente ao usar uma API ou ferramenta de CLI pela primeira vez
- O Zsh, por padrão, mostra descrições apenas quando há vários candidatos, enquanto o Bash só permite isso com configuração adicional
- Porém, para palavras já completas, os dois shells não exibem descrições
- Isso obriga o usuário a passar por um processo incômodo como este para ver a descrição
- apagar alguns caracteres para que vários candidatos passem a corresponder
- pressionar a tecla
<TAB>para ver a lista de candidatos - localizar visualmente a descrição desejada
- digitar novamente os caracteres apagados para executar o comando
Visão geral da solução
- Mesmo quando há apenas um candidato, adiciona-se um candidato fictício (dummy completion) para tornar a lista ambígua
- Assim, tanto o Bash quanto o Zsh passam a mostrar a lista de candidatos junto com as descrições
- É preciso, no entanto, tomar cuidado para que o texto da descrição não seja inserido no comando real
Conceitos básicos
- A autocompletação por Tab funciona recebendo a palavra atual e a posição do cursor ao pressionar
<TAB>, e retornando uma lista de candidatos possíveis - Bash: atribui os candidatos ao array
COMPREPLY - Zsh: registra os candidatos com o comando
compadd - A função
_generate_foo_completionsimprime as strings candidatas e, em uso real, pode gerá-las dinamicamente com base no estado da CLI
Suporte simultâneo a Bash e Zsh
- Implementação específica para cada shell com as funções
_complete_foo_bashe_complete_foo_zsh - Distinção com
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi - O usuário registra o script no
.bashrcou.zshrce então o aplica
Exibição de descrições no Zsh
- Usa-se o formato
nome: descriçãonas strings candidatas - Zsh:
compadd -d raw -- $trimmedpara passar nome e descrição em arrays paralelos - Bash: apenas os candidatos com a parte da descrição removida são passados para
COMPREPLY(sem suporte nativo a descrições)
Implementando descrições no Bash
- Quando há vários candidatos, expõem-se diretamente as strings com descrição incluída
- Quando há apenas um candidato, a descrição é removida
- Isso aproveita o comportamento de autocompletação do Bash, que insere apenas o prefixo comum, evitando que a descrição seja incluída na entrada real
Exibir descrição mesmo com um único candidato
- Para mostrar a descrição mesmo ao pressionar
<TAB>sobre uma palavra completa, adiciona-se um candidato fictício para induzir ambiguidade - Zsh: adiciona-se o candidato fictício em ambos os arrays paralelos (
raw,trimmed) - Bash: quando há apenas um candidato, adiciona-se apenas o nome em
trimmed
Resultado final
- Com vários candidatos, nome + descrição são exibidos
- Mesmo com um único candidato, é possível ver a descrição com
<TAB> - Bash e Zsh oferecem a mesma experiência
- Exemplo de uso:
$ foo <TAB> apple: a common fruit banana: starchy and high in potassium apricot: sour fruit... cherry: small and sweet...
1 comentários
Comentário no Hacker News
fish_update_completions~/.cache/fish/generated_completions/curlcom-L→ 'Follow redirects',-O→ 'Write output to file named as remote file'car TABexpande parablkdiscardpor causa do autocompletar sem prefixo, então o cargo pode falhar mesmo sem estar no PATH--help, fico curioso se o fish tem algo como o_gnu_genericdo zsh ou ocomplete -F _longoptdo bashzypper search fish-completion, aparecem mais de 200 pacotes, então senti que havia algo estranhocomplete-filename, ligada a M-/, que completa só nomes de arquivo ignorando o contextolse depois trocando o comandocomplete -r, parece que o problema está nos scripts do bash-completion$fpathfaz com que ele seja armazenado em cache e melhora a velocidade de inicialização_gnu_genericpermite uma completion simples baseada em--help--generatedo ripgrep e a geração de completion em tempo de execução do PHP Symfony--completionque bibliotecas de parser comuns implementassem automaticamentecomplete_kill_1, o comandokillpassa a oferecer completion para o primeiro argumentoset-java-home, uso_describepara completar as versões a partir da lista~/apps/java/*