Création automatique de fonctions à partir de prototypes de fonction à partir de fichiers d'en-tête

10

Intro

Lors de la programmation en C et C ++, vous divisez généralement vos prototypes de fonctions et les fonctions réelles en un fichier .h/ .hppet .c/ .cpp. Malheureusement, il est très fastidieux de transférer les prototypes de fonction d'un fichier à un autre, et nécessite d'ouvrir les deux fichiers en même temps (ou une bonne mémoire), ainsi que beaucoup de saisie inutile, en particulier lorsque des modifications des arguments ou des noms de membres sont fabriqué.

Exemple

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
}

Question

Existe-t-il un moyen de créer et de mettre à jour automatiquement les fonctions en foo.cpputilisant les définitions et les prototypes de foo.hpp?

Lukas
la source

Réponses:

3

Ouf, celui-ci était amusant!

: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>

Vous pouvez continuer et mapper cela à une seule touche dans votre .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>

Notez que cela suppose que le constructeur est la première méthode de classe à apparaître. (Je pourrais résoudre ce problème, mais je préfère rester simple. Veuillez mentionner dans un commentaire si vous avez besoin que cela soit corrigé.)

Cela suppose également que votre tampon de fichier d'en-tête est vide et situé directement après votre tampon de fichier source.

Explication étape par étape:

: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
Poignée de porte
la source
1
Bien que ce soit impressionnant (je suis plutôt nouveau sur vim, donc je découvre de nouvelles choses tous les jours!), Je crains que ce ne soit pas du tout ce dont j'ai besoin. Peut-être que je devrais envisager de créer mon propre plugin? Cela semble être une chose amusante à faire.
Lukas
2
@Lukas De quelle manière un mappage dans votre .vimrc ne résout-il pas le problème? Une simple pression sur Ctrl-B remplira alors automatiquement le fichier d'en-tête pour vous. (Je devrais probablement clarifier le fichier d'en-tête avant de le remplacer par une version mise à jour, mais je dois dormir donc je pourrais le faire plus tard.) Un plugin semble intéressant; tenez-moi au courant si vous décidez d'en faire un. Et merci pour le défi intéressant d'affiner mes compétences Vim! ;)
Poignée de porte
2
Cela semble fonctionner dans le sens inverse de la demande: il crée un fichier d'en-tête à partir du fichier .cpp.
200_success
... ce qui serait aussi bien, en fait, mais je pense qu'il y a certaines choses qui ne peuvent pas être connues à partir de la définition: par exemple, la déclaration est-elle censée être inline? Y a-t-il des arguments par défaut? Faut-il éluder les noms des arguments?
Kyle Strand
@ 200_success Ah, vous avez raison (je ne sais pas pourquoi je n'ai pas répondu à votre commentaire plus tôt). Quand j'aurai le temps, j'essaierai de modifier ma réponse pour aller dans l'autre sens.
Poignée de porte
2

La :GOTOIMPLcommande de lh-cpp est capable de passer à une définition de fonction à partir de sa déclaration, ou de fournir une définition vide par défaut dans le cas où aucune n'a été trouvée.

Quelques fonctionnalités auxquelles je peux penser:

  • La commande comprend déjà des commentaires, des spécifications d'exception, mots - clés qui ne doivent pas être copiés (mais peut - être copiés dans les commentaires) ( virtual, static...).
  • La portée actuelle de la fonction est décodée (namespaces :: classes :: ...) et correctement signalée (c'est-à-dire qu'elle ne préfixera pas ns::si nous sommes dans namespace ns{ou dans un using namespace ns;contexte.

Toutefois:

  • Les modèles ne sont pas (encore) compris.
  • Les corps de fonctions doivent être construits manuellement les uns après les autres - c'est-à-dire que je n'ai pas encore pris le temps d'exécuter: GOTOIMPL sur toutes les déclarations de fonctions que ctags pourrait me pointer.
Luc Hermitte
la source