Vim Tips Wiki
No edit summary
(indent fix)
(14 intermediate revisions by 8 users not shown)
Line 1: Line 1:
 
{{review}}
 
{{review}}
  +
{{TipImported
{{Tip
 
 
|id=589
 
|id=589
  +
|previous=588
|title=Vim as refactoring tool (with examples in C__HASH__)
 
  +
|next=590
|created=October 16, 2003 9:52
 
  +
|created=2003
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Klaus Horsten
 
|author=Klaus Horsten
 
|version=6.0
 
|version=6.0
 
|rating=225/77
 
|rating=225/77
  +
|category1=Automated Text Insertion
|text=
 
  +
|category2=C sharp
You can use vim as a refactoring tool.
 
  +
|category3=LanguageSpecific
  +
}}
  +
You can use Vim as a refactoring tool. The advantages are:
  +
#You automate repetitive writing tasks.
  +
#You learn refactoring.
   
  +
You can expect much from a refactoring tool but if you have a look at the commercial refactoring tools there is much (not all!) Vim can do too.
   
  +
I give you three examples, all in C#.
   
  +
===Example 1: The ''Extract Method'' refactoring===
The advantages are:
 
  +
Sphagetti code example:
  +
<pre>
  +
public string CreateMenu(string startMenu,string file)
  +
{
  +
string strOutput = "";
  +
int i = 0;
  +
ArrayList startArray = new ArrayList();
  +
string strVariable = "";
  +
string strTemp = "";
  +
XmlDocument XMLDoc = new XmlDocument();
  +
try {
  +
XMLDoc.Load(file);
  +
}
  +
catch (Exception e) {
  +
strOutput = e.GetBaseException().ToString();
  +
return strOutput;
  +
}
  +
XmlNodeList nodeList = XMLDoc.DocumentElement.ChildNodes;
  +
...
  +
</pre>
   
  +
Imagine 50 lines of code here.
1. You automatisate repetitive writing tasks
 
2. You learn refactoring
 
   
You can expect much from a refactoring tool but if you have a look at the
+
Use the ''extract method refactoring'' to make a ''composed method''.
commercial refactoring tools there is much (not all!) vim can do too.
 
   
  +
I use a Vim function (see below) to build the exracted method.
Whatever your opinion is, my experience is that vim helps to refactor.
 
   
  +
I highlight the code part I want to extract and press <code>\em</code> (for '''e'''xtract '''m'''ethod).
I give you three examples, all in C&#35;.
 
   
  +
A dialog appears and asks me how to name the new method.
* Example 1:
 
   
  +
I type in "GetXmlDocumentFrom" and do get this:
Anti-sphagetti code weapon or the "Extract Method" refactoring.
 
  +
<pre>
 
  +
// = GetXmlDocumentFrom();
Sphagetti code example:
 
  +
private GetXmlDocumentFrom()
 
  +
{
public string CreateMenu(string startMenu,string file)
 
  +
XmlDocument XMLDoc = new XmlDocument();
{
 
  +
try {
string strOutput = "";
 
int i = 0;
+
XMLDoc.Load(file);
  +
}
ArrayList startArray = new ArrayList();
 
  +
catch (Exception e)
string strVariable = "";
 
  +
{
string strTemp = "";
 
XmlDocument XMLDoc = new XmlDocument();
 
try {
 
XMLDoc.Load(file);
 
}
 
catch (Exception e) {
 
 
strOutput = e.GetBaseException().ToString();
 
strOutput = e.GetBaseException().ToString();
 
return strOutput;
 
return strOutput;
 
}
 
}
  +
// return ;
XmlNodeList nodeList = XMLDoc.DocumentElement.ChildNodes;
 
  +
}
...
 
  +
</pre>
   
  +
Now I have time to think what parameters the method needs and what to return.
   
  +
I end up with the following function and remove it from the original function:
  +
<pre>
  +
private XmlDocument GetXmlDocumentFrom(string XmlFile)
  +
{
  +
XmlDocument XMLDoc = new XmlDocument();
  +
string strOutput = "";
  +
try
  +
{
  +
XMLDoc.Load(XmlFile);
  +
}
  +
catch (Exception e)
  +
{
  +
strOutput = e.GetBaseException().ToString();
  +
ErrorMessage(strOutput);
  +
}
  +
return XMLDoc;
  +
}
  +
</pre>
   
  +
In the original code I put two lines.
Imagine 50 lines of code here.
 
  +
<pre>
  +
XmlDocument XMLDoc = new XmlDocument();
  +
XMLDoc = GetXmlDocumentFrom(XmlFile);
  +
</pre>
   
  +
So I reduced the original code for 8 lines and made it clearer what the code does.
   
  +
I do this with the rest of the code again and again.
   
  +
Since the class gets bloated because of the many new methods I later will use the ''Extract Class'' refactoring to put this method in an own XmlDocument-class.
Use the "extract method refactoring" to make a "composed method".
 
   
  +
This has the advantage that our new function is also available for other similar purposes.
   
  +
I will create the new class also with the help of Vim, the actual extracting of the method into the new class is just a matter of copy & paste.
   
  +
Here is the Vim code:
I use a vim function (see below) to build the exracted method.
 
  +
<pre>
  +
vmap \em :call ExtractMethod()<CR>
  +
function! ExtractMethod() range
  +
let name = inputdialog("Name of new method:")
  +
'<
  +
exe "normal! O\<BS>private " . name ."()\<CR>{\<Esc>"
  +
'>
  +
exe "normal! oreturn ;\<CR>}\<Esc>k"
  +
s/return/\/\/ return/ge
  +
normal! j%
  +
normal! kf(
  +
exe "normal! yyPi// = \<Esc>wdwA;\<Esc>"
  +
normal! ==
  +
normal! j0w
  +
endfunction
  +
</pre>
   
  +
===Example 2: The ''Self Encapsulate Field'' refactoring===
  +
I have heard a programmer who just uses Visual Studio (nothing against Visual Studio, it's a great tool!) say: "I do not use properties. It's too much work." He just uses fields instead.
   
  +
With Vim it is no problem to write a property, that is, to use the ''Self Encapsulate Field'' refactoring.
   
  +
I write a name e.g. <code>Name</code> press <code>CTRL-C CTRL-P CTRL-S</code> ('''c'''reate '''p'''roperty with '''s'''tring). Voila, the new property appears in just a second:
I highlight the code part I want to extract and press \em (for e-xtract m-ethod).
 
  +
<pre>
  +
private string m_Name;
  +
public string Name
  +
{
  +
get
  +
{
  +
return m_Name;
  +
}
  +
set
  +
{
  +
m_Name = value;
  +
}
  +
}
  +
</pre>
   
  +
Here are the Vim mappings and the underlying function:
  +
<pre>
  +
"Create property
  +
imap <C-c><C-p><C-s> <Esc>:call CreateProperty("string")<CR>a
  +
imap <C-c><C-p><C-i> <Esc>:call CreateProperty("int")<CR>a
  +
function! CreateProperty(type)
  +
exe "normal bim_\<Esc>b\"yywiprivate ".a:type." \<Esc>A;\<CR>public ".a:type.
  +
\ " \<Esc>\"ypb2xea\<CR>{\<Esc>oget\<CR>{\<CR>return " .
  +
\ "\<Esc>\"ypa;\<CR>}\<CR>set\<CR>{\<CR>\<Tab>\<Esc>\"yPa = value;\<CR>}\<CR>}\<CR>\<Esc>"
  +
normal! 12k2wi
  +
endfunction
  +
</pre>
   
  +
You can combine Visual Studio and Vim. You can work in Visual Studio and load the file in Vim for refactoring. I have made a menu entry in Visual Studio that loads the actual file I am writing in Vim (cf. [[Integrate gvim with Visual Studio#Vim as an External Tool|Vim as an External Tool]]).
   
  +
===Example 3: The ''Replace Conditional with Polymorphism'' refactoring===
A dialog appears and asks me how to name the new method.
 
  +
Imagine a switch and you want to replace it with an abstract class and some concrete classes which inherit from this parent class.
   
  +
You may think "Why should I replace this switch? It's too much work. Writing all these classes ..."
   
  +
With Vim it's just a question of a few seconds.
   
  +
To build the abstract class I type, say <code>Fruit</code>.
I type in "GetXmlDocumentFrom" and do get this:
 
   
  +
Then I press <code>CTRL-C CTRL-A CTRL-C</code> ('''c'''reate '''a'''bstract '''c'''lass) and get
  +
<pre>
  +
public abstract class Fruit
  +
{
  +
public abstract void |();
  +
}
  +
| is the cursor position
  +
</pre>
   
  +
Now I fill in the methods.
  +
<pre>
  +
public abstract class Fruit
  +
{
  +
public abstract void Taste();
  +
public abstract void Color();
  +
public abstract string GetSize();
  +
}
  +
</pre>
   
  +
Now I go on the first letter of <code>Fruit</code> and type <code>CTRL-C CTRL-C CTRL-C</code> ('''c'''reate '''c'''oncrete '''c'''lass).
// = GetXmlDocumentFrom();
 
   
  +
A dialog appears and asks me for the new name of the concrete class. I type in <code>Apple</code> and get
private GetXmlDocumentFrom()
 
  +
<pre>
  +
public class Apple : Fruit
  +
{
  +
public override void Taste()
  +
{
  +
}
  +
public override void Color()
  +
{
  +
}
  +
public override string GetSize()
  +
{
  +
}
  +
}
  +
</pre>
   
  +
I continue doing so with all the child classes of the abstract class.
{
 
   
  +
In this way I get code templates that I can implement now.
XmlDocument XMLDoc = new XmlDocument();
 
   
  +
Here are my mappings and the underlying funtion.
try {
 
  +
<pre>
  +
"Create abstract class
  +
imap <C-c><C-a><C-c> <Esc>bipublic abstract class <Esc>A<CR>{<CR>public abstract void X();<CR>}<Esc>:?X<CR>0fXs
  +
"Create concrete class
  +
map <C-c><C-c><C-c> :silent! call ImplementAbstractClass()<CR>
  +
function! ImplementAbstractClass() range
  +
exe "normal \<Esc>\"yyw"
  +
/{
  +
normal "xy%
  +
normal %o
  +
exe "normal! \<Esc>o"
  +
let name = inputdialog("Name of new method:")
  +
exe "normal! ipublic class " .name." : \<Esc>\"yp\"xp"
  +
exe "normal! }O}\<Esc>=="
  +
normal %v%
  +
normal! gv
  +
'<,'>s/abstract/override/g
  +
normal! gv
  +
'<,'>s/;/\r{\r}\r/g
  +
normal! ==
  +
normal %kdd%k
  +
endfunction
  +
</pre>
   
  +
==Comments==
XMLDoc.Load(file);
 
  +
These are amazing! I never thought of doing this, but I have to say your tips are quite amazing! I have begun to use hints 1 and 2 religiously, especially when I have to dig around through code that others have written! Thank you!!
   
}
 
 
catch (Exception e)
 
 
{
 
 
strOutput = e.GetBaseException().ToString();
 
 
return strOutput;
 
 
}
 
 
// return ;
 
 
}
 
 
 
 
Now I have time to think what parameters the method needs and what to return.
 
 
 
 
I end up with the following function and remove it from the original function:
 
 
 
 
private XmlDocument GetXmlDocumentFrom(string XmlFile)
 
 
{
 
 
XmlDocument XMLDoc = new XmlDocument();
 
 
string strOutput = "";
 
 
try
 
 
{
 
 
XMLDoc.Load(XmlFile);
 
 
}
 
 
catch (Exception e)
 
 
{
 
 
strOutput = e.GetBaseException().ToString();
 
 
ErrorMessage(strOutput);
 
 
}
 
 
return XMLDoc;
 
 
}
 
 
 
 
In the original code I put two lines.
 
 
 
 
XmlDocument XMLDoc = new XmlDocument();
 
 
XMLDoc = GetXmlDocumentFrom(XmlFile);
 
 
 
 
So I reduced the original code for 8 lines and made it clearer what the code does.
 
 
 
 
I do this with the rest of the code again and again.
 
 
 
 
Since the class gets bloated because of the many new methods I later will use
 
 
the "Extract Class" refactoring to put this method in an own XmlDocument-class.
 
 
 
 
This has the advantage that our new function is also available for other
 
 
similar purposes.
 
 
 
 
I will create the new class also with the help of vim, the actual extracting of
 
 
the method into the new class is just a matter of copy &amp; paste.
 
 
 
 
Here is the vim-code:
 
 
 
 
vmap \em :call ExtractMethod()&lt;cr&gt;
 
 
function! ExtractMethod() range
 
 
let name = inputdialog("Name of new method:")
 
 
'&lt;
 
 
exe "normal O\&lt;bs&gt;private " . name ."()\&lt;cr&gt;{\&lt;esc&gt;"
 
 
'&gt;
 
 
exe "normal oreturn ;\&lt;cr&gt;}\&lt;esc&gt;k"
 
 
s/return/\/\/ return/ge
 
 
normal j%
 
 
normal kf(
 
 
exe "normal yyPi// = \&lt;esc&gt;wdwA;\&lt;esc&gt;"
 
 
normal ==
 
 
normal j0w
 
 
endfunction
 
 
 
 
 
 
Example 2:
 
 
 
 
The "Self Encapsulate Field" refactoring.
 
 
 
 
I have heard a programmer who just uses Visual Studio (nothing against Visual
 
 
Studio, it's a great tool!) say: "I do not use properties. It's too much
 
 
work." He just uses fields instead.
 
 
 
 
With vim it is no problem to write a property, id est to use the "Self
 
 
Encapsulate Field" refactoring.
 
 
 
 
I write a name e.g. "Name" press CTRL-C CTRL-P CTRL-S (c-reate p-roperty with
 
 
s-tring). Voila, the new property appears in just a second:
 
 
 
 
private string m_Name;
 
 
public string Name
 
 
{
 
 
get
 
 
{
 
 
return m_Name;
 
 
}
 
 
set
 
 
{
 
 
m_Name = value;
 
 
}
 
 
}
 
 
 
 
Here are the vim mappings and the underlying function:
 
 
 
 
"Create property
 
 
imap &lt;C-c&gt;&lt;C-p&gt;&lt;C-s&gt; &lt;esc&gt;:call CreateProperty("string")&lt;cr&gt;a
 
 
imap &lt;C-c&gt;&lt;C-p&gt;&lt;C-i&gt; &lt;esc&gt;:call CreateProperty("int")&lt;cr&gt;a
 
 
 
 
function! CreateProperty(type)
 
 
exe "normal bim_\&lt;esc&gt;b\"yywiprivate ".a:type." \&lt;esc&gt;A;\&lt;cr&gt;public ".a:type." \&lt;esc&gt;\"ypb2xea\&lt;cr&gt;{\&lt;esc&gt;oget\&lt;cr&gt;{\&lt;cr&gt;return \&lt;esc&gt;\"ypa;\&lt;cr&gt;}\&lt;cr&gt;set\&lt;cr&gt;{\&lt;cr&gt;\&lt;tab&gt;\&lt;esc&gt;\"yPa = value;\&lt;cr&gt;}\&lt;cr&gt;}\&lt;cr&gt;\&lt;esc&gt;"
 
 
normal 12k2wi
 
 
endfunction
 
 
 
 
You can combine Visual Studio and vim. You can work in Visual Studio and load
 
 
the file in vim for refactoring. I have made a menu entry in Visual Studio that
 
 
loads the actual file I am writing in vim (cf. Tip &#35;580 [[VimTip580]]).
 
 
 
 
 
 
Example 3:
 
 
 
 
The "Replace Conditional with Polymorphism" refactoring.
 
 
 
 
Imagine a switch and you want to replace it with an abstract class and some
 
 
concrete classes which inherit from this parent class.
 
 
 
 
You may think "Why should I replace this switch? It's too much work. Writing
 
 
all these classes ..."
 
 
 
 
With vim it's just a question of a few seconds.
 
 
 
 
To build the abstract class I type, say "Fruit".
 
 
Then I press CTRL-C CTRL-A CTRL-C (c-reate a-bstract c-lass) and get
 
 
 
 
public abstract class Fruit
 
 
{
 
 
public abstract void |();
 
 
}
 
 
 
 
| means the Cursor position.
 
 
 
 
Now I fill in the methods.
 
 
 
 
public abstract class Fruit
 
 
{
 
 
public abstract void Taste();
 
 
public abstract void Color();
 
 
public abstract string GetSize();
 
 
}
 
 
 
 
 
 
Now I go on the first letter of "Fruit" and type CTRL-C CTRL-C CTRL-C (c-reate c-oncrete c-lass).
 
 
 
 
A dialog appears and asks me for the new name of the concrete class. I type in Apple and get
 
 
 
 
public class Apple : Fruit
 
 
{
 
 
public override void Taste()
 
 
{
 
 
}
 
 
 
 
public override void Color()
 
 
{
 
 
}
 
 
 
 
public override string GetSize()
 
 
{
 
 
}
 
 
}
 
 
 
 
I continue doing so with all the child classes of the abstract class.
 
 
In this way I get code templates that I can implement now.
 
 
 
 
Here are my mappings and the underlying funtion.
 
 
 
 
"Create abstract class
 
 
imap &lt;C-c&gt;&lt;C-a&gt;&lt;C-c&gt; &lt;esc&gt;bipublic abstract class &lt;esc&gt;A&lt;cr&gt;{&lt;cr&gt;public abstract void X();&lt;cr&gt;}&lt;esc&gt;:?X&lt;cr&gt;0fXs
 
 
"Create concrete class
 
 
map &lt;C-c&gt;&lt;C-c&gt;&lt;C-c&gt; :silent! call ImplementAbstractClass()&lt;cr&gt;
 
 
 
 
function! ImplementAbstractClass() range
 
 
exe "normal \&lt;esc&gt;\"yyw"
 
 
/{
 
 
normal "xy%
 
 
normal %o
 
 
exe "normal \&lt;esc&gt;o"
 
 
let name = inputdialog("Name of new method:")
 
 
exe "normal ipublic class " .name." : \&lt;esc&gt;\"yp\"xp"
 
 
exe "normal }O}\&lt;esc&gt;=="
 
 
normal %v%
 
 
normal gv
 
 
'&lt;,'&gt;s/abstract/override/g
 
 
normal gv
 
 
'&lt;,'&gt;s/;/\r{\r}\r/g
 
 
normal ==
 
 
normal %kdd%k
 
 
endfunction
 
 
 
 
 
 
Happy vimming ... and happy refactoring!
 
 
 
 
 
 
Klaus
 
 
 
 
 
 
 
 
 
 
 
}}
 
 
== Comments ==
 
These are amazing! I never thought of doing this, but I have to say your tips are quite amazing! I have not begun to use hints 1 and 2 religiously, especially when I have to dig around through code that others have written! Thank you!!
 
 
phaitour--AT--gmail.com
 
, December 2, 2005 2:41
 
 
----
 
----
  +
Here is a variation
The only thing I don't understand in C&#35; programming is the piece of code:
 
  +
<pre>
XMLDoc xmldoc = new XMLDoc();
 
  +
imap <C-c><C-p> <Esc>:call CreateProperty()<CR>a
xmldoc = GetXMLDocument();
 
  +
function! CreateProperty()
What purpose stays the first line for???
 
  +
exe "normal bim_\<Esc>b\"yyybiprivate \<Esc>A;\<CR>\<Esc>\"ypw\"xyw\<Esc>2xbipublic \<Esc>$a\<CR>{\<Esc>oget\<CR>{\<CR>return \<Esc>\"xpa;\<CR>}\<CR>set\<CR>{\<CR>\<Tab>\<Esc>\"xPa = value;\<CR>}\<CR>}\<CR>\<Esc>"
  +
normal 12k2wi
  +
endfunction
  +
</pre>
   
  +
This will create a property from a ''<type> <Field Name>''. This alleviates the need for multiple mappings for each data type in the vimrc file
sakhnik at gmail dot com
 
, January 20, 2006 1:58
 
----
 
Here is a variation
 
   
  +
So if you want to create a property from <code>Rectangle Box</code> just press <code><C-c><C-p></code> and you get
imap &lt;C-c&gt;&lt;C-p&gt; &lt;esc&gt;:call CreateProperty()&lt;cr&gt;a
 
  +
<pre>
 
  +
private Rectangle m_Box;
function! CreateProperty()
 
  +
public Rectangle Box
exe "normal bim_\&lt;esc&gt;b\"yyybiprivate \&lt;esc&gt;A;\&lt;cr&gt;\&lt;esc&gt;\"ypw\"xyw\&lt;esc&gt;2xbipublic \&lt;esc&gt;$a\&lt;cr&gt;{\&lt;esc&gt;oget\&lt;cr&gt;{\&lt;cr&gt;return \&lt;esc&gt;\"xpa;\&lt;cr&gt;}\&lt;cr&gt;set\&lt;cr&gt;{\&lt;cr&gt;\&lt;tab&gt;\&lt;esc&gt;\"xPa = value;\&lt;cr&gt;}\&lt;cr&gt;}\&lt;cr&gt;\&lt;esc&gt;"
 
  +
{
normal 12k2wi
 
  +
get
endfunction
 
  +
{
 
  +
return m_Box;
This will create a property from a &lt;type&gt; &lt;Field Name&gt;. This alleviates the need for multiple mappings for each data type in the vimrc file
 
  +
}
 
  +
set
So if you want to create a property from "Rectangle Box" just press "&lt;C-c&gt;&lt;C-p&gt;" and you get
 
  +
{
 
private Rectangle m_Box;
+
m_Box = value;
  +
}
public Rectangle Box
 
  +
}
{
 
  +
</pre>
get
 
{
 
return m_Box;
 
}
 
set
 
{
 
m_Box = value;
 
}
 
}
 
 
I am still trying to get rid of some extra spaces in property name but I hope this helps
 
 
 
jendave--AT--yahoo.com
 
, May 10, 2006 8:42
 
----
 
this is great !
 
I did the extract method in python .
 
   
  +
I am still trying to get rid of some extra spaces in property name but I hope this helps.
   
'''Anonymous'''
 
, November 12, 2006 8:18
 
 
----
 
----
<!-- parsed by vimtips.py in 0.571460 seconds-->
 

Revision as of 22:09, 28 July 2013

Tip 589 Printable Monobook Previous Next

created 2003 · complexity intermediate · author Klaus Horsten · version 6.0


You can use Vim as a refactoring tool. The advantages are:

  1. You automate repetitive writing tasks.
  2. You learn refactoring.

You can expect much from a refactoring tool but if you have a look at the commercial refactoring tools there is much (not all!) Vim can do too.

I give you three examples, all in C#.

Example 1: The Extract Method refactoring

Sphagetti code example:

public string CreateMenu(string startMenu,string file)
{
     string strOutput = "";
     int i = 0;
     ArrayList startArray = new ArrayList();
     string strVariable = "";
     string strTemp = "";
     XmlDocument XMLDoc = new XmlDocument();
     try {
         XMLDoc.Load(file);
     }
     catch (Exception e) {
     strOutput = e.GetBaseException().ToString();
     return strOutput;
     }
     XmlNodeList nodeList = XMLDoc.DocumentElement.ChildNodes;
     ...

Imagine 50 lines of code here.

Use the extract method refactoring to make a composed method.

I use a Vim function (see below) to build the exracted method.

I highlight the code part I want to extract and press \em (for extract method).

A dialog appears and asks me how to name the new method.

I type in "GetXmlDocumentFrom" and do get this:

// = GetXmlDocumentFrom();
private GetXmlDocumentFrom()
{
    XmlDocument XMLDoc = new XmlDocument();
    try {
        XMLDoc.Load(file);
    }
    catch (Exception e)
    {
        strOutput = e.GetBaseException().ToString();
        return strOutput;
    }
    // return ;
}

Now I have time to think what parameters the method needs and what to return.

I end up with the following function and remove it from the original function:

private XmlDocument GetXmlDocumentFrom(string XmlFile)
{
    XmlDocument XMLDoc = new XmlDocument();
    string strOutput = "";
    try
    {
        XMLDoc.Load(XmlFile);
    }
    catch (Exception e)
    {
        strOutput = e.GetBaseException().ToString();
        ErrorMessage(strOutput);
    }
    return XMLDoc;
}

In the original code I put two lines.

XmlDocument XMLDoc = new XmlDocument();
XMLDoc = GetXmlDocumentFrom(XmlFile);

So I reduced the original code for 8 lines and made it clearer what the code does.

I do this with the rest of the code again and again.

Since the class gets bloated because of the many new methods I later will use the Extract Class refactoring to put this method in an own XmlDocument-class.

This has the advantage that our new function is also available for other similar purposes.

I will create the new class also with the help of Vim, the actual extracting of the method into the new class is just a matter of copy & paste.

Here is the Vim code:

vmap \em :call ExtractMethod()<CR>
function! ExtractMethod() range
  let name = inputdialog("Name of new method:")
  '<
  exe "normal! O\<BS>private " . name ."()\<CR>{\<Esc>"
  '>
  exe "normal! oreturn ;\<CR>}\<Esc>k"
  s/return/\/\/ return/ge
  normal! j%
  normal! kf(
  exe "normal! yyPi// = \<Esc>wdwA;\<Esc>"
  normal! ==
  normal! j0w
endfunction

Example 2: The Self Encapsulate Field refactoring

I have heard a programmer who just uses Visual Studio (nothing against Visual Studio, it's a great tool!) say: "I do not use properties. It's too much work." He just uses fields instead.

With Vim it is no problem to write a property, that is, to use the Self Encapsulate Field refactoring.

I write a name e.g. Name press CTRL-C CTRL-P CTRL-S (create property with string). Voila, the new property appears in just a second:

private string m_Name;
public string Name
{
    get
    {
        return m_Name;
    }
    set
    {
        m_Name = value;
    }
}

Here are the Vim mappings and the underlying function:

"Create property
imap <C-c><C-p><C-s> <Esc>:call CreateProperty("string")<CR>a
imap <C-c><C-p><C-i> <Esc>:call CreateProperty("int")<CR>a
function! CreateProperty(type)
  exe "normal bim_\<Esc>b\"yywiprivate ".a:type." \<Esc>A;\<CR>public ".a:type.
        \ " \<Esc>\"ypb2xea\<CR>{\<Esc>oget\<CR>{\<CR>return " .
        \ "\<Esc>\"ypa;\<CR>}\<CR>set\<CR>{\<CR>\<Tab>\<Esc>\"yPa = value;\<CR>}\<CR>}\<CR>\<Esc>"
  normal! 12k2wi
endfunction

You can combine Visual Studio and Vim. You can work in Visual Studio and load the file in Vim for refactoring. I have made a menu entry in Visual Studio that loads the actual file I am writing in Vim (cf. Vim as an External Tool).

Example 3: The Replace Conditional with Polymorphism refactoring

Imagine a switch and you want to replace it with an abstract class and some concrete classes which inherit from this parent class.

You may think "Why should I replace this switch? It's too much work. Writing all these classes ..."

With Vim it's just a question of a few seconds.

To build the abstract class I type, say Fruit.

Then I press CTRL-C CTRL-A CTRL-C (create abstract class) and get

public abstract class Fruit
{
    public abstract void |();
}
                         | is the cursor position

Now I fill in the methods.

public abstract class Fruit
{
    public abstract void Taste();
    public abstract void Color();
    public abstract string GetSize();
}

Now I go on the first letter of Fruit and type CTRL-C CTRL-C CTRL-C (create concrete class).

A dialog appears and asks me for the new name of the concrete class. I type in Apple and get

public class Apple : Fruit
{
    public override void Taste()
    {
    }
    public override void Color()
    {
    }
    public override string GetSize()
    {
    }
}

I continue doing so with all the child classes of the abstract class.

In this way I get code templates that I can implement now.

Here are my mappings and the underlying funtion.

"Create abstract class
imap <C-c><C-a><C-c> <Esc>bipublic abstract class <Esc>A<CR>{<CR>public abstract void X();<CR>}<Esc>:?X<CR>0fXs
"Create concrete class
map <C-c><C-c><C-c> :silent! call ImplementAbstractClass()<CR>
function! ImplementAbstractClass() range
  exe "normal \<Esc>\"yyw"
  /{
  normal "xy%
  normal %o
  exe "normal! \<Esc>o"
  let name = inputdialog("Name of new method:")
  exe "normal! ipublic class " .name." : \<Esc>\"yp\"xp"
  exe "normal! }O}\<Esc>=="
  normal %v%
  normal! gv
  '<,'>s/abstract/override/g
  normal! gv
  '<,'>s/;/\r{\r}\r/g
  normal! ==
  normal %kdd%k
endfunction

Comments

These are amazing! I never thought of doing this, but I have to say your tips are quite amazing! I have begun to use hints 1 and 2 religiously, especially when I have to dig around through code that others have written! Thank you!!


Here is a variation

imap <C-c><C-p> <Esc>:call CreateProperty()<CR>a
function! CreateProperty()
  exe "normal bim_\<Esc>b\"yyybiprivate \<Esc>A;\<CR>\<Esc>\"ypw\"xyw\<Esc>2xbipublic \<Esc>$a\<CR>{\<Esc>oget\<CR>{\<CR>return \<Esc>\"xpa;\<CR>}\<CR>set\<CR>{\<CR>\<Tab>\<Esc>\"xPa = value;\<CR>}\<CR>}\<CR>\<Esc>"
  normal 12k2wi
endfunction

This will create a property from a <type> <Field Name>. This alleviates the need for multiple mappings for each data type in the vimrc file

So if you want to create a property from Rectangle Box just press <C-c><C-p> and you get

private Rectangle m_Box;
public Rectangle Box
{
    get
    {
        return m_Box;
    }
    set
    {
        m_Box = value;
    }
}

I am still trying to get rid of some extra spaces in property name but I hope this helps.