vim-refact icon indicating copy to clipboard operation
vim-refact copied to clipboard

Some refactoring stuff for Vim

Refactor plugin for Vim.

You can use this plugin to make some refactoring on your code. It was originally written to work with the Ruby language, but it's flexible (I hope, I'll add some more languages later) to work with another languages.

Examples

Extracting a method

Let's say we have this Ruby code:

  1. module Test
  2. puts "bye"
  3. puts "tchau"
  4. puts "hasta la vista"
  5. test class

  6. class Test
  7.  puts "hi"
    
  8.  puts "oi"
    
  9.  puts "hola"
    
  10.  def initialize
    
  11.     @foo = "bar"
    
  12.  end
    
  13.  # test method
    
  14.  def test
    
  15.     puts "test!"
    
  16.     puts "bye!"
    
  17.     c = 0
    
  18.     while c < 10
    
  19.        puts "c = #{c}"
    
  20.        c += 1
    
  21.     end 
    
  22.  end
    
  23. end
  24. end

If the cursor is positioned over the line 2, and the lines are selected till the line 4, we can type:

:Rem (, )

or, in visual mode, typing the new method name when asked

rem

to extract those lines to a with some optionally parameters. So,

:Rem say_bye<CR>

or on visual mode

rem (typing say_bye)

will turn our code to this:

  1. module Test
  2. test class

  3. class Test
  4.   puts "hi"
    
  5.   puts "oi"
    
  6.   puts "hola"
    
  7.   def initialize
    
  8.      @foo = "bar"
    
  9.   end
    
  10.   # test method
    
  11.   def test
    
  12.      puts "test!"
    
  13.      puts "bye!"
    
  14.      c = 0
    
  15.      while c < 10
    
  16.         puts "c = #{c}"
    
  17.         c += 1
    
  18.      end 
    
  19.   end
    
  20. end
  21. def say_bye
  22.   puts "bye"
    
  23.   puts "tchau"
    
  24.   puts "hasta la vista"
    
  25. end
  26. end

where a module method was created with the selected content.

Now, selecting from line 4 to 6, extracting the code to a method inside the class Test, called say_hi, with

:Rem say_hi

or, in visual mode, typing say_hi when asked for a new method name

rem

and the code now is

  1. module Test
  2. test class

  3. class Test
  4.   def initialize
    
  5.      @foo = "bar"
    
  6.   end
    
  7.   # test method
    
  8.   def test
    
  9.      puts "test!"
    
  10.      puts "bye!"
    
  11.      c = 0
    
  12.      while c < 10
    
  13.         puts "c = #{c}"
    
  14.         c += 1
    
  15.      end 
    
  16.   end
    
  17.   def say_hi
    
  18.      puts "hi"
    
  19.      puts "oi"
    
  20.      puts "hola"
    
  21.   end
    
  22. end
  23. def say_bye
  24.   puts "bye"
    
  25.   puts "tchau"
    
  26.   puts "hasta la vista"
    
  27. end
  28. end

We can remove content from inside a method to another one. Let's say we want to remove lines 8 and 9 to a method called another_test. Select those 2 lines and

:Rem another_test

or, in visual mode, typing another_test when asked about the new method name

rem

and now the code is

  1. module Test
  2. test class

  3. class Test
  4.   def initialize
    
  5.      @foo = "bar"
    
  6.   end
    
  7.   # test method
    
  8.   def test
    
  9.      another_test
    
  10.      c = 0
    
  11.      while c < 10
    
  12.         puts "c = #{c}"
    
  13.         c += 1
    
  14.      end 
    
  15.   end
    
  16.   def another_test
    
  17.      puts "test!"
    
  18.      puts "bye!"
    
  19.   end
    
  20.   def say_hi
    
  21.      puts "hi"
    
  22.      puts "oi"
    
  23.      puts "hola"
    
  24.   end
    
  25. end
  26. def say_bye
  27.   puts "bye"
    
  28.   puts "tchau"
    
  29.   puts "hasta la vista"
    
  30. end
  31. end

Now we have the option to extract lines 10 to 14 or 12 to 13. Let's try the first option, extracting the code to a method called count. Select from lines 10 to 14 and

:Rem count

or, on visual mode, typing count when asked about the new method name

rem

and now the code is

  1. module Test
  2. test class

  3. class Test
  4.   def initialize
    
  5.      @foo = "bar"
    
  6.   end
    
  7.   # test method
    
  8.   def test
    
  9.      another_test
    
  10.      count
    
  11.   end
    
  12.   def count
    
  13.      c = 0
    
  14.      while c < 10
    
  15.         puts "c = #{c}"
    
  16.         c += 1
    
  17.      end 
    
  18.   end
    
  19.   def another_test
    
  20.      puts "test!"
    
  21.      puts "bye!"
    
  22.   end
    
  23.   def say_hi
    
  24.      puts "hi"
    
  25.      puts "oi"
    
  26.      puts "hola"
    
  27.   end
    
  28. end
  29. def say_bye
  30.   puts "bye"
    
  31.   puts "tchau"
    
  32.   puts "hasta la vista"
    
  33. end
  34. end

Or we can extract only from line 12 (see code before the last change) to a method called show_count, creating a c parameter and sending the c variable to the method, selecting line 12 and

:Rem show_count c

or on visual mode, typing show_count c when asked about the new method name

rem

and now the code is

  1. module Test
  2. test class

  3. class Test
  4.   def initialize
    
  5.      @foo = "bar"
    
  6.   end
    
  7.   # test method
    
  8.   def test
    
  9.      another_test
    
  10.      c = 0
    
  11.      while c < 10
    
  12.         show_count(c)
    
  13.         c += 1
    
  14.      end 
    
  15.   end
    
  16.   def show_count(c)
    
  17.      puts "c = #{c}"
    
  18.   end
    
  19.   def another_test
    
  20.      puts "test!"
    
  21.      puts "bye!"
    
  22.   end
    
  23.   def say_hi
    
  24.      puts "hi"
    
  25.      puts "oi"
    
  26.      puts "hola"
    
  27.   end
    
  28. end
  29. def say_bye
  30.   puts "bye"
    
  31.   puts "tchau"
    
  32.   puts "hasta la vista"
    
  33. end
  34. end

Renaming a variable on method scope

If we have this piece of code:

  1. test method, with foo argument

  2. def some_method(foo)
  3. foo.inspect
  4. puts "foo converted to string: #{foo}"
  5. end

and position the cursor on rows 3 or 4 and use

:Rrv foo bar

or, more easier, put the cursor over the foo word and type

rrv (typing the new variable name when asked)

we changed all the ocurrences of foo to bar inside the method:

  1. test method, with foo argument

  2. def some_method(bar)
  3. bar.inspect
  4. puts "bar converted to string: #{bar}"
  5. end

if the cursor position is on line 1, all the other ocurrences of the foo var above (ok, we don't have more lines above here but you got the point) will be also changed.

Renaming an attribute

If we have this piece of code:

  1. class Test
  2.  def initialize
    
  3.     @foo = "bar"
    
  4.  end
    
  5.  def print_contents
    
  6.     # foo contents
    
  7.     puts "#{@foo}"
    
  8.  end
    
  9. end

and wants to change all the ocurrences of the foo attribute (@foo) to @bar, we can use, inside the class scope:

:Rra foo bar

or, more easier, put the cursor over the foo word and type

rra (typing the new attribute name when asked)

so we can get

  1. class Test
  2.  def initialize
    
  3.     @bar = "bar"
    
  4.  end
    
  5.  def print_contents
    
  6.     # foo contents
    
  7.     puts "#{@bar}"
    
  8.  end
    
  9. end

Align assigment operators

Suppose we have this code:

a = 1 ab += 2 abc -= 3 abcd *= 4 abcde /= 2 abcdef =~ /foo/ abcdefg != /bar/

Ugly, right? Select all the lines and type

raa

and then

a = 1 ab += 2 abc -= 3 abcd *= 4 abcde /= 2 abcdef =~ /foo/ abcdefg != /bar/

Better, uh?