Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim Macro to generate C++ constructor

Tags:

c++

vim

macros

I am wondering if it is possible to define a macro in Vim that will let you do the following. Suppose you have a class definition

class CRectangle {
  int x;
  int y;
  _
};

where _ specifies the current cursor position.

Running the macro should automatically generate

class CRectangle {
  int x;
  int y;

public:
  CRectangle (int x, int y);
  ~CRectangle ();
};

CRectangle::(int x, int y) {
  this->x = x;
  this->y = y;
}

I have been thinking about this for a while but didn't get anywhere. Perhaps creating the constructor definition is a bit too much to ask. Is it feasible to get at least the constructor declaration?

====

As sftrabbit points out, it is perhaps more desirable to generate something like

CRectangle::(int _x, int _y) : x(_x), y(_y) {}
like image 398
Shitikanth Avatar asked Mar 23 '13 00:03

Shitikanth


1 Answers

Okay... I was bored...

qm           ; Gentlemen... start your macros (we'll call it 'm')
ma           ; Mark your current location as 'a'
v            ; switch to 'visual' mode
?{<cr>       ; Search back to the opening brace (actually hit 'enter' for that <cr>)
l"by         ; Go forward one character and yank the selection to buffer 'b'
b            ; Go back one word
"cyw         ; Copy the class name into buffer 'c'
'a           ; Jump back to the starting location
opublic:<cr> ; add "public:"
()<esc>B"cP  ; create an empty constructor
t)"bp        ; Paste the list of arguments in
             ; Rather complex reformatting regex on the next line
:.,/)/s/\s*\w\+\s+\(\w+\);\n/_\1, /<cr>
kJ:s/,\s*)/)/<cr> ; Simple cleanup
A : {}<esc>  ; Finish some of the basics
F:"bp        ; Paste in the fields again for generating the initialization
             ; Below: Another fairly complicated formatting regex
:.,/{}/s/\s*\w\+\s\+\(\w\+\);\n/\1(_\1),/<cr>
:s/,\s*{/ {/<cr>     ; Cleanup
kJ                   ; Finished with the constructor
q                    ; Finish macro (I'm going to omit the rather trivial destructor)

I'm sure this can be simplified... but as an answer to "can it be done?" yes... it certainly can.

Note that you'll also have to modify it somewhat to handle however your vim is configured for formatting (auto-indentation, and such).

If you've been a bit sloppy about assembling your variables in the class, you might have to swap /\s*\w\+\s\+\(\w\+\)\s*;\s*\n/ in for /\s*\w\+\s\+\(\w\+\);\n/ both places. (handling a few extra spaces around things)

like image 101
jkerian Avatar answered Sep 27 '22 21:09

jkerian