Automatyczne tworzenie funkcji na podstawie prototypów funkcji z plików nagłówkowych

10

Wprowadzenie

Podczas programowania w C i C ++ zwykle dzielisz prototypy funkcji i funkcje rzeczywiste na plik .h/ .hppi .c/ .cpp. Niestety przenoszenie prototypów funkcji z jednego pliku do drugiego jest bardzo żmudne i wymaga otwierania obu plików jednocześnie (lub dobrej pamięci), a także dużej ilości niepotrzebnego pisania, zwłaszcza gdy zmiany w argumentach lub nazwach członków są zrobiony.

Przykład

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
}

Pytanie

Czy istnieje sposób automatycznego tworzenia i aktualizacji funkcji przy foo.cppużyciu definicji i prototypów foo.hpp?

Lukas
źródło

Odpowiedzi:

3

Uff, ten był zabawny!

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

Możesz śmiało zamapować to na jedno naciśnięcie klawisza w swoim .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>

Zauważ, że zakłada to, że konstruktor jest pierwszą metodą, która się pojawi. (Mógłbym to naprawić, ale wolę to uprościć. Jeśli to konieczne, proszę wspomnieć w komentarzu).

Zakłada się również, że bufor pliku nagłówkowego jest pusty i znajduje się bezpośrednio za buforem pliku źródłowego.

Wyjaśnienie krok po kroku:

: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
Klamka
źródło
1
Chociaż jest to imponujące (jestem raczej nowy w vimie, więc odkrywam nowe rzeczy każdego dnia!), Obawiam się, że to wcale nie jest to, czego potrzebuję. Może powinienem spróbować stworzyć własną wtyczkę? To wydaje się zabawne.
Lukas
2
@Lukas W jaki sposób mapowanie w twoim .vimrc nie rozwiązuje problemu? Wystarczy nacisnąć Ctrl-B, a następnie automatycznie wypełni plik nagłówka. (Prawdopodobnie powinienem wyczyścić plik nagłówka przed zastąpieniem go zaktualizowaną wersją, ale muszę spać, aby to zrobić później). Wtyczka brzmi interesująco; informuj mnie na bieżąco, jeśli zdecydujesz się go stworzyć. I dziękuję za interesujące wyzwanie, aby ulepszyć moje umiejętności Vima! ;)
Klamka
2
Wydaje się, że działa to w przeciwnym kierunku niż żądanie: tworzy plik nagłówkowy z pliku .cpp.
200_success
... co też byłoby fajne, ale myślę, że z definicji nie można się dowiedzieć, na przykład: czy ma to być deklaracja inline? Czy istnieją domyślne argumenty? Czy należy wymieniać nazwy argumentów?
Kyle Strand,
@ 200_success Ach, masz rację (nie wiem, dlaczego wcześniej nie odpowiedziałem na twój komentarz). Kiedy będę miał czas, spróbuję edytować swoją odpowiedź, aby przejść w drugą stronę.
Klamka
3

:GOTOIMPLPolecenie od LH-CPP jest w stanie przeskoczyć do definicji funkcji ze swojej deklaracji, lub dostarczyć domyślny pusty definicja w przypadku równych został znaleziony.

Niektóre funkcje, o których mogę myśleć:

  • Komenda już rozumie, komentarze, specyfikacji wyjątków, słów kluczowych, które nie mogą być kopiowane (ale prawdopodobnie skopiowane w komentarzach) ( virtual, static...).
  • Bieżący zakres funkcji jest dekodowany (przestrzenie nazw :: class :: ...) i poprawnie zgłaszany (tzn. Nie będzie poprzedzony prefiksem, ns::jeśli jesteśmy w kontekście namespace ns{lub w using namespace ns;kontekście.

Jednak:

  • Szablony nie są (jeszcze) zrozumiane.
  • Treść funkcji należy budować ręcznie jedna po drugiej - tzn. Nie poświęciłem jeszcze czasu na wykonanie: GOTOIMPL na wszystkich deklaracjach funkcji, które ctags mogłyby mnie wskazać.
Luc Hermitte
źródło