Criando funções automaticamente a partir de protótipos de função a partir de arquivos de cabeçalho

10

Introdução

Ao programar em C e C ++ você costuma dividir seus protótipos de função e funções reais em um .h/ .hppe .c/ .cpparquivo. Infelizmente, é muito entediante transferir os protótipos de função de um arquivo para outro e requer a abertura de ambos os arquivos ao mesmo tempo (ou uma boa memória), além de muitas digitações desnecessárias, especialmente quando são feitas alterações nos argumentos ou nomes de membros. feito.

Exemplo

foo.hpp:

int someFunction(int someArgument);

class someClass
{
     public:
     someClass();
     ~someClass();

     int anotherFunction(int anotherArgument);
};

foo.cpp:

#include "foo.hpp"

int someFunction(int someArgument)
{
    // Code goes here
}

someClass::someClass()
{
    // Code goes here
}

someClass::~someClass()
{
    // Code goes here   
}

int someClass::anotherFunction(int anotherArgument)
{
    // Code goes here
}

Questão

Existe uma maneira de criar e atualizar automaticamente as funções foo.cppusando as definições e protótipos foo.hpp?

Lukas
fonte

Respostas:

3

Uau, este foi divertido!

:g/.*\n^{/yank A<cr>:bn<cr>pkdd:%s/$/;/<cr>:g/::/d B<cr>A<cr><cr>class <cr>{<cr>};<esc>"BP:%s/[^ ]\+:://<cr>j%jyt(kk$p=ipjA<cr>public:<esc>

Você pode ir em frente e mapear isso para uma única tecla pressionada no seu .vimrc:

nnoremap <C-b> :g/.*\n^{/yank A<cr>:bn<cr>pkdd:%s/$/;/<cr>:g/::/d B<cr>A<cr><cr>class <cr>{<cr>};<esc>"BP:%s/[^ ]\+:://<cr>j%jyt(kk$p=ipjA<cr>public:<esc>

Observe que isso pressupõe que o construtor seja o primeiro método de classe a aparecer. (Eu poderia consertar isso, mas prefiro mantê-lo simples. Por favor, mencione em um comentário se você precisar desse conserto.)

Isso também pressupõe que o buffer do arquivo de cabeçalho esteja vazio e localizado diretamente após o buffer do arquivo de origem.

Explicação passo a passo:

:g/.*\n^{/yank A<cr>            Yank all the function definitions (power of g!)
:bn<cr>                         Move to the header file buffer
pkdd                            Put in the function definitions
:%s/$/;/<cr>                    Add semicolons
:g/::/d B<cr>                   Grab the class methods and put them in register B
A<cr><cr>class <cr>{<cr>};<esc> Self-explanatory, add class skeleton
"BP                             Put the class methods in the class
:%s/[^ ]\+:://<cr>              Remove someClass::
j%jyt(kk$p                      Add the actual class name
=ip                             Fix indentation
jA<cr>public:<esc>              Add the `public:' modifier
Maçaneta
fonte
11
Embora isso seja impressionante (eu sou novo no vim, então estou descobrindo coisas novas todos os dias!), Receio que isso não seja o que eu preciso. Talvez eu deva procurar criar meu próprio plugin? Parece uma coisa divertida de se fazer.
Lukas
2
@ Lucas De que maneira um mapeamento no seu .vimrc não resolve o problema? Basta pressionar Ctrl-B para preencher automaticamente o arquivo de cabeçalho para você. (Eu provavelmente devo deixar claro o arquivo do cabeçalho antes de substituí-lo por uma versão atualizada, mas tenho que dormir para poder fazer isso mais tarde.) Um plug-in parece interessante; mantenha-me atualizado se você decidir fazer um. E obrigado pelo desafio interessante de aprimorar minhas habilidades em Vim! ;)
Maçaneta da porta
2
Isso parece funcionar na direção oposta à solicitação: ele cria um arquivo de cabeçalho a partir do arquivo .cpp.
200_success
... o que também seria bom, na verdade, mas acho que há algumas coisas que não podem ser conhecidas a partir da definição: por exemplo, a declaração deveria ser inline? Existem argumentos padrão? Os nomes dos argumentos devem ser elididos?
Kyle Strand
@ 200_success Ah, você está certo (não sei por que não respondi ao seu comentário anteriormente). Quando tiver tempo, tentarei editar minha resposta para o outro lado.
Doorknob
2

O :GOTOIMPLcomando do lh-cpp é capaz de pular para uma definição de função a partir de sua declaração ou fornecer uma definição vazia padrão, caso nenhuma foi encontrada.

Alguns recursos que eu posso pensar:

  • O comando já entende comentários, especificações de exceção, palavras-chave que não podem ser copiados (mas possivelmente copiados nos comentários) ( virtual, static...).
  • O escopo atual da função é decodificado (namespaces :: classes :: ...) e relatado corretamente (ou seja, não será um prefixo ns::se estiver dentro namespace ns{ou dentro de um using namespace ns;contexto.

Contudo:

  • Modelos ainda não são compreendidos.
  • O corpo da função deve ser construído manualmente, um após o outro - ou seja, ainda não tomei tempo para executar: GOTOIMPL em todas as declarações de funções que ctags poderiam me indicar.
Luc Hermitte
fonte