O poder da Exuberant Ctags aliada ao Vim

Em: 09/02/2008 Tags: Referencie do seu blog (Trackback)

Ao codificar um grande projeto é muito útil ter a possibilidade de posicionar o cursor sobre um nome de função ou classe e conseguir, com um simples comando, descobrir onde esse “objeto de código” foi definido.

Exemplo: você está em um grande projeto, que organiza os diferentes arquivos de código-fonte em uma dúzia de diretórios. Estamos no arquivo que define a classe Foo. Dentro da definição dessa classe vemos muitas referências à classe Bar, como em um trecho (código PHP):

$bar = new Bar();

Não seria ótimo se pudessémos posicionar o cursor sobre Bar, digitar um comando e então o arquivo onde Bar foi definida fosse carregado, com a linha class Bar sob o cursor? E não seria ótimo se, também com um comando, pudéssemos voltar para onde estávamos (editando o código da classe Foo)? Pois é, com a Exuberant Ctags isso é possível.

De acordo com o site:

A Ctags gera um arquivo de índice (ou de tags) de objetos de linguagem encontrados em códigos-fonte, o que permite que esses itens sejam localizados rapidamente e facilmente por um editor de textos ou outro utilitário. Uma tag é um objeto de linguagem para o qual uma entrada no índice está disponível (ou, em outras palavras, a entrada no índice criada para aquele objeto).

A Ctags gera o índice de tags não apenas para C, mas também outras linguagens populares (veja a lista completa).

Vamos agora para a instalação da biblioteca e sua integração ao Vim.

Instalando o pacote Exuberant Ctags

Se você está em ambiente Linux utilize o gerenciador de pacotes para auxiliá-lo - essa biblioteca é muito popular e certamente estará disponível. Para usuários das distribuições baseadas em apt basta fazer:

sudo apt-get install exuberant-ctags

Gerando o índice de tags

Vamos considerar o exemplo de um projeto PHP. Para gerar o índice de tags entramos no diretório onde o código-fonte está localizado e em seguida digitamos, na linha de comando:

ctags -R

O programa ctags tentará gerar o índice para todas as linguagens suportadas que ele encontrar nos diretórios filhos do diretório corrente. Caso seu projeto inclua código de terceiros (como um framework JavaScript, por exemplo), esse processo poderá tornar-se longo. Consulte o manual para saber como evitar certos diretórios.

Um exemplo prático é forçar o programa a analisar apenas os arquivos de código-fonte PHP, e de nenhuma outra linguagem. O parâmetro --languages dá conta do recado, como mostra o exemplo:

ctags -R --languages=PHP 

Note que agora teremos um novo arquivo dentro do diretório raíz do nosso projeto, com o nome tags. Se seu código está sob controle de versão então é uma boa alternativa configurá-lo para ignorar esse arquivo.

Tirando proveito das tags dentro do Vim

Vamos considerar a seguinte estrutura para o nosso projeto, para o qual já geramos o arquivo de tags:

lib/foo.php (declara a classe Foo)
lib/bar.php (declara a classe Bar)

Considerando que estamos dentro do diretório raíz do projeto, podemos abrir o arquivo onde está a classe Foo digitando:

vim -t Foo

Muito bom, não? Esse arquivo tem a seguinte estrutura:

class Foo {

    //...
    function my_func() {
        //...
        $bar = new Bar();
    }
}

A linha que inicia com $bar é o que nos interessa neste momento. Se deixarmos o cursor sobre a palavra Bar e usarmos o comando Ctrl^] (digitar Ctrl e ] ao mesmo tempo) em modo de edição, então iremos para o arquivo lib/bar.php, com o cursor parado sobre a linha class Bar. Para voltar, utilizamos Ctrl^t também em modo de edição.

Você verá que não apenas nomes de funções ou classes são indexados, mas também definições de variáveis, constantes e tudo que possa ser útil. Só testando para descobrir todas as possibilidades e entender o ganho de produtividade.

Re-gerando o arquivo de tags a partir do Vim

Uma vez gerado o arquivo de tags ele não será atualizado automaticamente conforme modificamos o código-fonte. Isso precisa ser feito explicitamente, e para tornar esse processo mais ágil podemos adicionar um atalho ao nosso .vimrc:

nmap <silent> <F9> :!ctags -R --languages=PHP <return>

Agora podemos, dentro do código-fonte, re-gerar esse arquivo a qualquer momento teclando F9 (modifique o exemplo caso deseja associar o atalho com outra tecla ou conjunto de comandos). Como especificamos a opção <silent> para esse comando o Vim não imprimará a saída gerada pela execução do comando ctags. Então, após digitar F9 o Vim nos colocará em modo terminal, nenhuma saída será impressa, e precisaremos apertar Enter para voltar para o arquivo que estávamos editando. Muito simples.

Note que o atalho F9 executa o comando a partir do diretório onde abrimos o arquivo. Ou seja, abra sempre seus arquivos a partir do diretório raíz do seu projeto, para que o arquivo de tags sempre seja gerado nesse local.

Conclusão

Meu amigo Daniel Neis já havia descoberto o poder das tags há muito tempo quando trabalhávamos juntos em um projeto PHP. A preguiça não me deixava correr atrás e descobrir como integrar tudo isso ao Vim de forma simples, incluindo a re-geração do arquivo de tags. Porém, no meu novo local de trabalho entrei em um projeto que já estava próximo de ser colocado em produção, e tive que mexer em muitas classes que nunca havia visto antes e nem sabia onde estavam. Ter a ctags para lhe ajudar nessas horas é realmente excelente (evita termos que sair do Vim para mandar o famoso comando grep encontrar a definição daquela classe/função/método/constante/etc). A ctags elimina a necessidade de pensar onde está determinado trecho de código: você manda ela procurar e ela encontrará.

Portanto, recomendo que façam o passo-a-passo que apresentei e aproveitem a agilidade que vocês irão ganhar!

Referências

Para maiores informações, leia o help da Ctags dentro do Vim:

:help ctags

O manual da Ctags também é uma boa:

man ctags

Artigos relacionados:

Uma resposta para “O poder da Exuberant Ctags aliada ao Vim”

  1. Source code browser para o Vim | Caio Moritz Ronchi disse:

    [...] você já configurou o Vim com suporte ao Exuberante Ctags (aprenda neste post como fazê-lo), provavelmente vai se interessar pelo plugin Tag List (é o mais votado e mais [...]

Escreva um comentário (utilize o formato Markdown)