Autocompletar em Bash e zsh: criar um script simples de conclusão

TL;DR
Autocompletar economiza tempo e torna comandos personalizados mais descobríveis. Este artigo ensina como adicionar conclusão por Tab para scripts em zsh e Bash, cobre um exemplo passo a passo, mostra um script compatível com ambas as shells e oferece checklists, casos de teste e armadilhas comuns.
Importante: autocompletar é ativado pela shell do usuário (onde o Tab é pressionado), não pela linguagem do script.
O que é autocompletar
Autocompletar (completar) preenche automaticamente palavras ou caminhos com base no que você começou a digitar. Em shells, ele aparece quando você pressiona Tab. Define-se rápido:
- Tab completion: interação que sugere ou completa comandos, opções, subcomandos e nomes de ficheiros quando o usuário pressiona Tab.
Este recurso existe no Unix desde os anos 80 e hoje é suportado por shells amplamente usados, como Bash e zsh.
Por que adicionar conclusão para seus scripts
- Facilita descobrimento de subcomandos numa ferramenta caseira.
- Reduz erros de digitação.
- Melhora a experiência de colaboradores e usuários finais.
A seguir há um exemplo simples que mostra como implementar autocompletar para um utilitário fictício chamado todos.
Exemplo: comando simples todos
Este exemplo usa um script que guarda tarefas em um ficheiro. O script em si não é o foco; o objetivo é demonstrar apenas como oferecer sugestões de subcomandos.
Código de exemplo (zsh):
#!/usr/bin/env zsh
FILE="$HOME/.local/state/todos/data"
if [ "$#" -eq "1" ] && [ "$1" = "edit" ] ; then
"${EDITOR:-vi}" "$FILE"
elif [ "$#" -eq "1" ] && [ "$1" = "help" ] ; then
echo "Usage: $(basename $0) [ edit | help ]"
else
<"$FILE" grep -v ^~
fi
Se o ficheiro for executável e estiver no PATH, você terá estes comandos:
- todos — mostrar conteúdo (linhas que não começam com ~)
- todos help — mostrar ajuda
- todos edit — abrir o ficheiro no editor
A conclusão ajuda a descobrir os subcomandos sem memorizar a sintaxe.
Como criar um script de conclusão em zsh
Em zsh a API é simples. Você registra uma função que usa compadd para listar as sugestões.
Exemplo mínimo para zsh:
_complete_todos() {
compadd help edit
}
autoload -Uz compinit
compinit
compdef _complete_todos todos
- compadd: adiciona sugestões ao sistema de conclusão da zsh.
- compinit: inicializa o sistema de completions.
- compdef: associa a função de conclusão ao comando todos.
Onde colocar o código: no seu .zshrc, num ficheiro carregado por .zshrc, ou usando fpath com um nome começando por underline (por exemplo _todos).
Teste rápido: carregue o bloco no shell atual e pressione Tab após digitar todos.
Diferenças no Bash
Bash usa uma abordagem distinta. Você escreve uma função que preenche a variável COMPREPLY com as sugestões. Bash não adivinha tanto — a função precisa considerar o estado atual da linha de comando.
Exemplo mínimo (inicial, ingênuo):
_complete_todos_bash() {
COMPREPLY=(help edit)
}
complete -F _complete_todos_bash todos
Isso funciona, mas é permissivo demais: ao digitar “he
- COMP_WORDS: array com as palavras da linha de comando.
- COMP_CWORD: índice da palavra sendo completada.
Uma função melhor usa compgen para filtrar sugestões baseadas no texto parcial:
_complete_todos_bash() {
COMPREPLY=( $( compgen -W "edit help" -- "${COMP_WORDS[$COMP_CWORD]}" ) )
}
complete -F _complete_todos_bash todos
compgen -W “lista” – “prefixo” retorna as palavras que começam com o prefixo.
Script universal: suportando zsh e Bash
Para compartilhar um script com colegas, detecte a shell e registre a função apropriada. Aqui está um exemplo que funciona em ambas as shells:
SUBCOMMANDS=(help edit halt)
_complete_todos_zsh() {
compadd $SUBCOMMANDS
}
_complete_todos_bash() {
COMPREPLY=( $( compgen -W "${SUBCOMMANDS[*]}" -- "${COMP_WORDS[$COMP_CWORD]}" ) )
}
if [ -n "${ZSH_VERSION:-}" ]; then
autoload -Uz compinit
compinit
compdef _complete_todos_zsh todos
elif [ -n "${BASH_VERSION:-}" ]; then
complete -F _complete_todos_bash todos
fi
Dicas de distribuição:
- Salve num ficheiro, por exemplo completion.sh.
- No .bashrc e/ou .zshrc: . /path/to/completion.sh
- Para zsh, considere colocar o ficheiro em fpath como _todos para integração automática.
Boas práticas e considerações
- Use arrays/deslocamentos para evitar problemas com palavras com espaços.
- Projete autocompletar para ser idempotente e rápida; não faça chamadas de rede bloqueantes.
- Se as sugestões dependem do ambiente (por exemplo ficheiros presentes), calcule-as dinamicamente.
- Não exponha segredos; evite inserir valores sensíveis nas listas de sugestões.
Quando a conclusão falha (exemplos e causas comuns)
- O ficheiro não é carregado pelo .bashrc/.zshrc: verifique sourcing.
- O comando não está no PATH: a associação dependa do nome do comando no PATH.
- Conflito com outras definições: outra função de completion pode ter precedência.
- Problemas de escape: strings com espaços precisam de tratamento correto.
- Performance: gerar milhares de sugestões pode bloquear a shell.
Abordagens alternativas
- Usar utilitários como argparse-completions ou argcomplete (para Python) que geram automaticamente completions a partir da definição de argumentos.
- Gerar scripts de completion durante a instalação (make install) e colocá-los em /etc/bash_completion.d/ ou diretórios equivalentes para zsh.
- Para projetos mais complexos, manter um subcomando –completion que gera output estruturado lido pelo handler de completion.
Mental model (heurística rápida)
- Pense em três camadas: lista fonte (onde as possíveis palavras vêm), filtro (prefixo e contexto) e registro (associar a função ao comando).
- Priorize filtros simples e rápidos; apenas liste tudo quando for aceitável em termos de desempenho.
Checklist por papel
- Desenvolvedor:
- Implementar função de completion mínima.
- Tratar espaços e caracteres especiais.
- Fornecer suporte a Bash e zsh quando necessário.
- Mantenedor do pacote:
- Colocar ficheiro de completion em diretório padrão da distro.
- Adicionar step de instalação que registre a completion.
- Usuário final:
- Verificar se .bashrc/.zshrc faz source do script.
- Reabrir a shell ou executar source manualmente.
Casos de teste e critérios de aceitação
- Ao digitar “todos
”, devem aparecer todas as subcomandos registradas. - Ao digitar “todos he
”, somente “help” deve ser sugerido. - O script não deve travar a shell ao listar 1000+ sugestões (critério de performance dependente do ambiente).
- O script deve funcionar quando os ficheiros estiverem com espaços no nome.
Mini metodologia para implementar completions robustas
- Liste as fontes de sugestões (subcomandos, ficheiros, comandos externos).
- Escreva uma função de completition mínima que retorne um conjunto estático.
- Adicione filtragem baseada no prefixo do usuário.
- Teste em ambientes com diferentes shells.
- Simule grandes conjuntos de sugestões para testar performance.
- Consolide o script para suportar Bash e zsh se for necessário compartilhar.
Exemplo avançado: completar argumentos condicionais
Imagine que o subcomando “deploy” aceita um ambiente (staging|prod). A conclusão deve sugerir ambientes apenas quando o primeiro argumento for deploy.
Estratégia:
- Olhe para COMP_CWORD/COMP_WORDS (Bash) ou use widgets/contextos em zsh.
- Baseie decisões no conteúdo das palavras anteriores.
Pseudocódigo (Bash):
# se a primeira palavra for 'deploy', sugerir ambientes
if [ "${COMP_WORDS[1]}" = "deploy" ]; then
COMPREPLY=( $( compgen -W "staging prod" -- "${COMP_WORDS[$COMP_CWORD]}" ) )
fi
No zsh, você faria lógica similar dentro da função de completion, usando compadd para o conjunto apropriado.
Segurança e privacidade
- Não exponha IDs ou caminhos sensíveis nas sugestões.
- Não gere listas que revelam informações restritas (por exemplo nomes de ficheiros internos) sem verificar permissões.
- Considere trabalhar com permissões reduzidas se o comando que gera sugestões precisa ler dados sensíveis.
Compatibilidade e migração
- Zsh tem compadd e compdef; Bash usa complete e COMPREPLY.
- Para distribuição em sistemas diversos, documente a necessidade de sourcing e os caminhos de instalação.
- Em distribuições que usam bash-completion, prefira instalar o ficheiro em /etc/bash_completion.d/ para ativação automática.
Guia de implantação (SOP rápido)
- Coloque completion.sh no repositório em scripts/completion.sh.
- No instalador (Makefile ou setup), copie para /usr/local/share/mytool/completion.sh.
- No postinstall, adicione instrução para que o utilizador faça source no .bashrc/.zshrc, ou copie as definições para /etc/bash_completion.d/ e os equivalentes de zsh.
- Teste em um sistema limpo.
Exemplos de snippets e cheatsheet
- Registrar para Bash:
complete -F _myfunc mycmd
- Registrar para zsh (após compinit):
compdef _myfunc mycmd
- Usar compgen para filtrar:
compgen -W "one two three" -- "prefix"
Resumo
Adicionar autocompletar aos seus scripts melhora usabilidade e reduz erros. Zsh oferece helpers mais diretos (compadd), enquanto Bash exige um pouco mais de código (COMPREPLY e compgen). Se precisar distribuir para múltiplas shells, detecte a shell e registre as funções adequadas. Teste os casos de prefixo, espaços e performance.
Perguntas frequentes
Como carrego o script sem reiniciar a shell?
Use source /path/to/completion.sh ou . /path/to/completion.sh.
Posso completar ficheiros e subcomandos ao mesmo tempo?
Sim. Gere a lista combinada ou implemente lógica condicional que avalie a posição do cursor.
Devo instalar o script globalmente?
Se for parte de uma ferramenta usada por muitos utilizadores, instale em diretórios padrão (/etc/bash_completion.d/ ou diretórios de completions do zsh).
Anexos úteis
Checklist de lançamento
- Script testado em zsh
- Script testado em Bash
- Documentação de instalação adicionada
- Política de privacidade verificada (nenhuma informação sensível sugerida)
Critérios finais de aceitação
- Completar subcomandos básicos conforme esperado.
- Filtragem por prefixo funcionando em Bash.
- Sem regressões em shells dos colaboradores.
Materiais semelhantes
Reduzir array RAID degradado com mdadm e LVM

Consertar som ausente em Stories do Instagram no iPhone

Rastrear e evitar números de telefone falsos

Autocompletar Bash e zsh: criar um script

Formulários no Numbers para iPad e iPhone
