vim-ruby-refactoringで面倒なリファクタリング作業を自動化


vim-ruby-refactoring とは

読んで字のごとく Ruby のリファクタリングを補助する Vim プラグインです。
ちょっと使ってみて便利っぽかったのと、日本語記事がなさそうだったので初 Qiita してみます。

導入方法

Vim に neobundle.vim が入っている場合は ~/.vimrc に以下の設定を追加します。

NeoBundle 'tsaleh/vim-matchit'
NeoBundle 'ecomba/vim-ruby-refactoring'

あとは :NeoBundleInstall でインストール完了です。
vim-ruby-refactoring の一部コマンドが vim-matchit に依存するようなので一緒に入れておくのが良さそうです。

機能一覧

主な機能を挙げていきます。

" メソッドに引数を追加する
:nnoremap <leader>rap  :RAddParameter<cr>

" 一行で書かれた条件文(e.g. "hoge if fuga?" のようなもの)を伝統的な複数行の形式に変換する
:nnoremap <leader>rcpc :RConvertPostConditional<cr>

" 選択部分を RSpec の "let(:hoge) { fuga }" の形式に切り出す
:nnoremap <leader>rel  :RExtractLet<cr>

" 選択部分を定数として切り出す
:vnoremap <leader>rec  :RExtractConstant<cr>

" 選択部分を変数として切り出す
:vnoremap <leader>relv :RExtractLocalVariable<cr>

" 一時変数を取り除く
:nnoremap <leader>rit  :RInlineTemp<cr>

" ローカル変数をリネームする
:vnoremap <leader>rrlv :RRenameLocalVariable<cr>

" インスタンス変数をリネームする
:vnoremap <leader>rriv :RRenameInstanceVariable<cr>

" 選択部分をメソッドに切り出す
:vnoremap <leader>rem  :RExtractMethod<cr>

備考:
<leader> のデフォルト値は \ です。
ほかの値に設定されている場合は :let mapleader で確認できます。

使い方

ローカル変数のリネーム

この場合は <leader>rrlv を使います。
text-object のキーバインドと組み合わせると便利です。

たとえば下記のようなメソッドがあったとします。

def sample(hoge)
  hoge.foo = 1
  hoge.bar = 2
end

適当な hoge の上にカーソルを置き viw と入力すると hoge が選択できます。
続いて \rrlv と入力すると次のプロンプトが表示されます。

Rename to:

このプロンプトにリネームしたい変数名を入力します。
試しに piyo と入力し Enter を押すと次のような結果になります。

def sample(piyo)
  piyo.foo = 1
  piyo.bar = 2
end

いちいち %s などの置換コマンドを入力しなくて済むので非常に良い感じです。

選択範囲をメソッドに切り出す

個人的にこれが一番感動しました。
ただ単にメソッドに切り出すだけでなく、引数や返り値も自動で設定してくれるんです。こやつ・・・できる・・!

def sample2(piyo)
  foo, bar = piyo.split(',')
  return nil if foo.nil? || bar.nil?
  "Foo is #{foo}, Bar is #{bar}."
end

3~4行目を選択した状態で \remと入力すると次のプロンプトが表示されます。

Method name:

このプロンプトに適当なメソッド名を入力してやります。
試しに hoge と入力し Enter を押すと次のような結果になります。

def hoge(foo, bar)
  return nil if foo.nil? || bar.nil?
  "Foo is #{foo}, Bar is #{bar}."
end 
def sample2(piyo)
  foo, bar = piyo.split(',')
  hoge(foo, bar)
end 

注意点:
切り出す内容によっては必要な値が引数に設定されなかったり、引数にすべきではない値が設定されたりするようです。
また選択の仕方にもクセがあって、切り出したいテキストの「改行文字」まで選択してやる必要があるようです。
(この辺はまだまだ改良の余地あり、といった感じですね)

今後の展望

ざっと使ってみた感じ、少し荒削りな部分が見受けられましたが、十分実用できるレベルだと思いました。
ただちょっともの足りないな・・・と思うところもあったので以下に列挙しておきます。

  • Ruby on Rails への対応(モデルに定義した属性のリネームなど)
  • ファイルを越えたリネーム
  • メソッド切り出しの正確さ向上

ひとまずこのままもう少し使ってみます。

参考文献