O autocompletar é uma das funcionalidades mais poderosas e subutilizadas do shell Bash. Ele permite que você digite comandos, caminhos, opções e argumentos de forma mais rápida e com menos erros, simplesmente pressionando a tecla Tab. Nesta aula, vamos explorar desde o mecanismo básico de tab completion até a criação de completações personalizadas usando o programmable completion do Bash.

Dominar o autocompletar pode transformar sua experiência no terminal, reduzindo drasticamente o tempo gasto digitando e evitando erros de digitação. Além disso, entender como o Bash decide o que completar é fundamental para personalizar seu ambiente de trabalho e criar ferramentas mais amigáveis.

Tab completion

O tab completion é o recurso mais antigo e básico do autocompletar. Quando você digita parte de um comando, nome de arquivo, diretório, variável de ambiente ou usuário, e pressiona Tab, o Bash tenta completar automaticamente o que você digitou. Se houver múltiplas possibilidades, o Bash exibe uma lista de opções e aguarda que você digite mais caracteres para refinar a busca.

O comportamento do tab completion depende do contexto. Por exemplo:

  • No início de um comando, ele completa nomes de comandos (executáveis no PATH).
  • Em argumentos, ele completa nomes de arquivos e diretórios.
  • Após o símbolo $, ele completa variáveis de ambiente.
  • Após ~, ele completa nomes de usuários.

Vamos ver alguns exemplos práticos. Suponha que você queira executar o comando systemctl. Em vez de digitar tudo, você pode digitar sys e pressionar Tab. O Bash completará para systemctl (se for o único comando começando com sys) ou mostrará uma lista de comandos que começam com sys.

$ sys[Tab]
$ systemctl[Tab]

Para arquivos, se você tiver um diretório com os arquivos relatorio.txt, relatorio_final.txt e dados.csv, e digitar cat r e pressionar Tab, o Bash completará para cat relatorio e mostrará as três opções possíveis. Você pode então digitar mais caracteres para selecionar um.

$ cat r[Tab]
relatorio.txt  relatorio_final.txt  dados.csv
$ cat relatorio[Tab]
relatorio.txt  relatorio_final.txt

Uma dica importante: pressionar Tab duas vezes em sequência exibe todas as opções possíveis, mesmo que você não tenha digitado nada. Isso é útil para explorar o que está disponível.

Programmable completion (visão geral)

O programmable completion (ou completação programável) é um recurso avançado do Bash que permite definir regras de completação específicas para cada comando. Com ele, você pode especificar quais opções, argumentos, valores ou até mesmo padrões são válidos para um determinado comando, e o Bash usará essas regras ao pressionar Tab.

Isso é feito através do comando complete e de funções de completação. O Bash também oferece a função compgen para gerar listas de candidatos, e você pode usar COMPREPLY para armazenar as respostas. O programmable completion é amplamente utilizado por ferramentas como git, docker e kubectl para oferecer autocompletar inteligente de subcomandos, opções e argumentos.

Para entender como funciona, imagine que você quer criar uma completação para um script chamado meuscript que aceita os comandos start, stop e restart. Sem programmable completion, o Bash apenas completaria nomes de arquivos. Com ele, você pode fazer com que o Bash sugira apenas essas três palavras.

Configuração

Para configurar o programmable completion, você pode usar o comando complete no seu arquivo ~/.bashrc ou em um arquivo separado carregado pelo Bash. A sintaxe básica é:

complete [opções] comando

Por exemplo, para definir que o comando meuscript deve completar com uma lista fixa de palavras, você pode usar:

complete -W "start stop restart" meuscript

A opção -W especifica uma lista de palavras separadas por espaços. Agora, ao digitar meuscript s e pressionar Tab, o Bash completará para start e stop.

Para algo mais complexo, você pode definir uma função de completação. A função deve preencher a variável global COMPREPLY com uma lista de possíveis completações. O Bash fornece variáveis como COMP_WORDS (array de palavras na linha de comando), COMP_CWORD (índice da palavra atual) e COMP_LINE (a linha inteira).

Um exemplo simples de função de completação para um comando que aceita arquivos .txt ou .md seria:

_meuscript_completions() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(compgen -W "start stop restart" -- "$cur") )
}
complete -F _meuscript_completions meuscript

Nesse exemplo, compgen gera as palavras que começam com $cur e as coloca em COMPREPLY.

Você também pode combinar -F (função) com outras opções, como -o filenames para tratar as respostas como nomes de arquivos, o que permite que o Bash adicione uma barra após diretórios, por exemplo.

Exemplos

Vamos explorar alguns exemplos práticos de configuração de programmable completion.

Exemplo 1: Comando com subcomandos fixos

Suponha que você tenha um script deploy que aceita os subcomandos staging, production e rollback. Você pode configurar:

complete -W "staging production rollback" deploy

Teste no terminal:

$ deploy [Tab]
staging  production  rollback
$ deploy prod[Tab]
$ deploy production

Exemplo 2: Completar com arquivos de um diretório específico

Se um comando backup espera um arquivo de configuração em /etc/backup, você pode usar uma função que lista apenas os arquivos desse diretório:

_backup_completions() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(compgen -f /etc/backup/ -- "$cur") )
}
complete -F _backup_completions backup

Note que compgen -f lista arquivos e diretórios. Se quiser apenas arquivos, use -f; para diretórios, use -d.

Exemplo 3: Completar com opções longas de um comando

Muitos comandos têm opções longas como --verbose, --help, etc. Você pode criar uma completação que sugira essas opções. Vamos supor que seu comando mytool aceita --verbose, --quiet, --output e --config.

_mytool_completions() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local opts="--verbose --quiet --output --config"
    COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
}
complete -F _mytool_completions mytool

Assim, ao digitar mytool -- e pressionar Tab, o Bash mostrará as quatro opções.

Exemplo 4: Completar com valores de um comando anterior

Às vezes, a completação depende da palavra anterior. Por exemplo, se o comando git tem subcomandos e, após git checkout, você quer completar com nomes de branches. Isso é mais complexo e geralmente é feito por scripts prontos, mas você pode fazer uma versão simples:

_git_completions() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local prev="${COMP_WORDS[COMP_CWORD-1]}"
    if [[ "$prev" == "checkout" ]]; then
        COMPREPLY=( $(compgen -W "$(git branch --format='%(refname:short)')" -- "$cur") )
    fi
}
complete -F _git_completions git

Esse exemplo usa git branch para obter a lista de branches e completa somente se o comando anterior for checkout.

Boas práticas e observações finais

Ao criar completações personalizadas, comece com casos simples e vá incrementando. Use compgen para filtrar candidatos de forma eficiente. Teste suas funções em um shell interativo antes de adicioná-las ao ~/.bashrc. Lembre-se de que o programmable completion é carregado sob demanda, então você pode colocar suas definições em um arquivo separado e carregá-lo com source quando necessário.

Outra dica: muitos projetos open source fornecem scripts de completação prontos. Você pode instalá-los em /etc/bash_completion.d/ ou /usr/share/bash-completion/completions/ (dependendo da distribuição) e eles são carregados automaticamente. Para o seu próprio uso, o diretório ~/.bash_completion é uma boa prática.

Referências

Exercícios

  1. Crie uma completação para o comando meuapp que aceite as palavras iniciar, parar e reiniciar. Use complete -W.

    ✓ Resposta: Adicione ao seu ~/.bashrc:
    complete -W "iniciar parar reiniciar" meuapp
  2. Escreva uma função de completação para o comando log que sugira apenas arquivos com extensão .log no diretório atual. Use compgen com -f e filtre por extensão.

    ✓ Resposta:
    _log_completions() {
        local cur="${COMP_WORDS[COMP_CWORD]}"
        COMPREPLY=( $(compgen -f -- "$cur" | grep '\.log$') )
    }
    complete -F _log_completions log
  3. Explique o papel da variável COMPREPLY no programmable completion.

    ✓ Resposta: COMPREPLY é um array que a função de completação deve preencher com as possíveis completações. O Bash lê esse array para exibir as opções ou completar automaticamente. Se ele estiver vazio, nenhuma completação é oferecida.
  4. Como você pode carregar automaticamente suas funções de completação quando o Bash inicia? Cite duas formas.

    ✓ Resposta: 1) Colocando as definições diretamente no ~/.bashrc. 2) Criando um arquivo separado (por exemplo, ~/.bash_completion) e adicionando source ~/.bash_completion no ~/.bashrc.
  5. Diferencie complete -W e complete -F.

    ✓ Resposta: -W fornece uma lista fixa de palavras como candidatas, enquanto -F especifica uma função que gera dinamicamente as candidatas (preenchendo COMPREPLY). A função permite lógica mais complexa, como depender de outras palavras da linha de comando.