Posso pular para uma declaração ou definição de função em um projeto de vários arquivos de origem C ++?

15

Posso pular para uma declaração ou definição de função em um projeto de vários arquivos de origem C ++?

Digamos que eu tenho um arquivo de cabeçalho foo.hpp:

int bar();

e um arquivo de origem foo.cpp:

#include "foo.hpp"
int bar() { return 42; }

e um arquivo principal main.cpp:

#include "foo.hpp"
int main() { bar(); return 0; }

O vim pode encontrar a definição e a declaração da função a bar()partir da mainfunção?

Allan Hasegawa
fonte

Respostas:

14

As tags exuberantes são a maneira mais simples de conseguir isso. No GNU / Linux (por exemplo, Ubuntu ou Debian), você deve ser capaz de fazer

sudo apt-get install exuberant-ctags

(Para OSX, "$ brew install ctags" deve ser suficiente; para Windows, visite http://ctags.sourceforge.net/ e faça o download do executável independente)

Em seguida, navegue até a pasta raiz do seu projeto e execute

ctags -R --exclude=.git .

Isso varrerá todo o seu projeto e criará um arquivo ./tags que o vim usará automaticamente para fornecer a capacidade de ir para as funções pressionando uma tecla. Nomeadamente:

Ctrl + ]

com o cursor colocado na função para a qual você deseja ver a implementação. Existem outras combinações e muitas funções no modo de comando que permitem que você navegue pelo código também com ctags (por exemplo, Ctrl+ tpara pular para a entrada mais antiga da pilha de tags). Veja :help 29.1para uma visão geral.

Observe que você deve executar novamente as ctags para cada alteração significativa no código e permitir que ele re-indexe seu projeto. Você pode fazer isso manualmente ou ensinar o vim a fazê-lo na tecla de atalho ou na gravação.

Dica: se você fizer uso extensivo de ctags, talvez o plug-in vim-taglist ( http://vim-taglist.sourceforge.net ) também valha uma olhada. Ele fornece um esboço no estilo IDE com uma lista de todas as funções para essa classe / arquivo.

Rocha
fonte
Vale a pena conhecer duas coisas: o universal-ctags substituiu, de várias maneiras, o exuberante-ctags. Além disso, como deixar de sincronização git suas tags
D. Ben Knoble
4

Até agora, posso citar duas soluções para o problema de encontrar a declaração ou a definição de uma função. Sei que há outra solução bem conhecida baseada em tags, mas como não a uso, deixarei que outras pessoas a ofereçam.

O mais moderno primeiro: YouCompleteMe tem um :GoToDefinitione um :GoToDeclarationpar de comandos.

O que eu uso (é difícil mudar hábitos de 10 anos). Meu plugin lh-tags tem uma maneira de gerar um banco de dados ctags e atualizá-lo de forma incremental. E também oferece uma maneira ( CTRL+W Meta+Down) de apresentar todas as declarações e definições que correspondem ao que está sob o cursor (/ o que está selecionado). Como essa solução depende de ctags, não será possível saber qual sobrecarga o identificador sob o cursor também está realmente relacionado. Outras soluções baseadas em ctags devem ser ruins (/ boas) neste tópico. No entanto, o YCM deve ser muito melhor aqui.

Discl .: Eu implementei lh-tags como uma alternativa mais ergonômica para :tselect.

(Na verdade, lembro-me de uma terceira solução: eu havia iniciado um fork do clang-indexer e o plugin vim relacionado que o teria encapsulado. Mas com o YCM por perto, eu esqueci essa solução)

EDIT: A partir de 2019, a solução mais eficiente conta com servidores LSP . Estou usando COC + ccls para indexar, pular e fazer muitas outras coisas. Estou voltando às soluções baseadas em tags quando tenho preguiça de configurar o COC para um projeto no qual não vou gastar muito tempo ou onde não consigo instalar versões recentes de clang e ccls.

Luc Hermitte
fonte
1
Obrigado pela entrada, irá testar cada solução. Testei o YouCompleteMe e só GoToDeclarationfunciona com vários arquivos de origem. Aqui está uma citação dos documentos sobre GoToDefinition: For C-family languages this only works ... when the definition of the symbol is in the current translation unit.. Além disso, os comandos são :YcmCompleter GoTo*.
Allan Hasegawa
Eu perdi essa linha. Isso significa que o clang_indexer ainda pode ser útil. As outras soluções podem ser um pouco difíceis de instalar. Não hesite em me enviar um e-mail, se necessário.
Luc Hermitte
3

Existem poucas alternativas. O primeiro é ctags. Se você precisar de um indexador mais avançado, cscopeé uma alternativa melhor. Por exemplo, ele permitirá que você liste todos os chamadores de determinada função. Essas ferramentas indexarão seu código sem realmente entendê-lo corretamente (elas possuem uma definição gramatical simples para saber o que significa um símbolo). Também é relativamente fácil estender essa gramática. O taglistplug-in é essencial para eles e é possível estender a gramática do indexador para mostrar resultados na lista de tags.

Se você precisar de algo mais do que indexador, como a verificação de sintaxe, YouCompleteMeprovavelmente é o caminho a percorrer. Ele é construído em cima do llvme, portanto, possui um analisador adequado. Isso permite verificar a sintaxe e a semântica do código .

Então, se você trabalha com um código que possui uma linguagem específica de domínio ou código incorporado, geralmente acaba passando por arquivos. Alternativa é o Ackscript perl que tenta ajudar com esta tarefa.

nome
fonte
0

Eu acho que ctags é o que você precisa. O Vim é integrado com ctags nativamente e pode pular facilmente para definições e declarações de funções.

Dê uma olhada neste artigo http://andrew.stwrt.ca/posts/vim-ctags

David Carlos
fonte
Por favor, adicione um resumo da postagem vinculada. As respostas somente de link se tornam inúteis quando o link fica inoperante.
muru