Creación automática de funciones a partir de prototipos de funciones a partir de archivos de encabezado

10

Introducción

Al programar en C y C ++, generalmente divide los prototipos de funciones y las funciones reales en un archivo .h/ .hppy .c/ .cpp. Lamentablemente, es muy tedioso transferir los prototipos de funciones de un archivo a otro, y requiere abrir ambos archivos al mismo tiempo (o una buena memoria), así como una gran cantidad de tipeo innecesario, especialmente cuando se realizan cambios en los argumentos o nombres de miembros hecho.

Ejemplo

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
}

Pregunta

¿Hay alguna manera de crear y actualizar automáticamente las funciones al foo.cppusar las definiciones y prototipos foo.hpp?

Lukas
fuente

Respuestas:

3

¡Vaya, este fue 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>

Puede continuar y asignar eso a una sola pulsación de tecla en su .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>

Tenga en cuenta que esto supone que el constructor es el método de primera clase en aparecer. (Podría arreglar eso, pero prefiero que sea simple. Mencione en un comentario si necesita que lo arreglen).

Esto también supone que el búfer del archivo de encabezado está vacío y ubicado directamente después del búfer del archivo de origen.

Explicación paso a paso:

: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
Perilla de la puerta
fuente
1
Si bien esto es impresionante (soy bastante nuevo en vim, ¡así que descubro cosas nuevas todos los días!), Me temo que esto no es lo que necesito. ¿Tal vez debería considerar hacer mi propio complemento? Parece una cosa divertida de hacer.
Lukas
2
@Lukas ¿De qué manera un mapeo en su .vimrc no resuelve el problema? Simplemente presionando Ctrl-B completará automáticamente el archivo de encabezado por usted. (Probablemente debería aclarar el archivo de encabezado antes de reemplazarlo con una versión actualizada, pero tengo que dormir para poder hacerlo más tarde). Un complemento suena interesante; mantenme actualizado si decides hacer uno. ¡Y gracias por el interesante desafío de agudizar mis habilidades de Vim! ;)
Pomo de la puerta
2
Esto parece funcionar en la dirección opuesta a la solicitud: crea un archivo de encabezado a partir del archivo .cpp.
200_success
... lo que también sería bueno, en realidad, pero creo que hay algunas cosas que no se pueden saber de la definición: por ejemplo, ¿se supone que debe ser la declaración inline? ¿Hay argumentos por defecto? ¿Deben elidirse los nombres de argumento?
Kyle Strand
@ 200_success Ah, tienes razón (no sé por qué no respondí a tu comentario antes). Cuando tenga tiempo, intentaré editar mi respuesta para ir a otro lado.
Pomo
2

El :GOTOIMPLcomando de lh-cpp puede saltar a una definición de función desde su declaración, o proporcionar una definición vacía predeterminada en caso de que no se encuentre ninguna.

Algunas características que se me ocurren:

  • El comando ya entiende los comentarios, especificaciones de excepción, las palabras clave que no haya de ser copiados (pero posiblemente copiados dentro comentarios) ( virtual, static, ...).
  • El alcance actual de la función se decodifica (espacios de nombres :: clases :: ...) y se informa correctamente (es decir, no tendrá un prefijo ns::si estamos dentro namespace ns{o dentro de un using namespace ns;contexto.

Sin embargo:

  • Las plantillas no se entienden (todavía).
  • El cuerpo de la función debe construirse manualmente uno tras otro, es decir, aún no me he tomado el tiempo de ejecutar: GOTOIMPL en todas las declaraciones de funciones que ctags podrían señalarme.
Luc Hermitte
fuente