[Python][Vim] VimでPythonをリファクタリング出来るよ

最近会社ではPyCharmというIDEが流行ってきているようです。
個人的にはIDEのように裏で何かいらない事をするプログラムはあまり好きではなく、またVimキーバインドに慣れすぎて抜けれない状態です。
不思議な事に会社ではVimに比べたらEmacs派は少なめな気がします。何故ですかね?
ともかく、PyCharmは素晴らしい素晴らしい、Vimリファクタリング出来ないとか言われてカッときてググった所、RopeというPythonリファクタリングライブラリを発見しました。
しかもこれ、VimEmacsからも使えるようになっているようです。早速使わなくちゃと色々設定にハマって何とか使えるようになったのでメモって置こうかと思った次第です。

インストール

まずは、VimPythonに対応している必要があります。
このように、"+python"が表示されればOKです。"-python"となっていれば自分でコンパイルする等してください。
MacだとデフォルトのVimPython非対応です。Linuxはパッケージ探したら何とかなるかも。

$ vim --version|grep python
 +python


次はRopeのインストールです。本家だとソースダウンロードして色々必要そうですが、easy_installでインストールできます。
virtualenvでも可能ですが、ちょっと面倒なので割愛します。

$ easy_install rope ropemode ropevim


次に、rope-vimというvimスクリプトをインストールします。
ただ、rope-vim内でコメント文が間違っていてエラーでますので、ここでforkしてから修正されているバージョンがあります。こっちを使った方が良いでしょう。

virtualenvな人へ

自分はグローバルが汚れるのは嫌なのでvirtualenv使っていますが。virtualenvな人は、vim-virtualenvで幸せになれます。
当然virtualenvの場合、ropeがimport出来ない状況もある訳ですが、その場合rope-vimがimportできないぜーってエラーを吐きます。
あまりにもウザいので自分でrope-vimをforkして修正いれました。vimスクリプトはほとんど書かないので正しい修正かは分かりませんが、必要な人は使ってください。できれば慣れている人に修正してもらえればなぁと思ったり。

.vimrc

.vimrcですが、自分はこのように設定しています。

"for ropevim
nnoremap [rope] <Nop>
vnoremap [vrope] <Nop>
nmap <Space>r [rope]
vmap <Space>r [vrope]
nnoremap <silent> [rope]r :RopeRename<CR>
nnoremap <silent> [rope]u :RopeUndo<CR>
"メソッド切り出し
vnoremap <silent> [vrope]f :RopeExtractMethod<CR>

RopeRename、RopeUndo、RopeExtractMethodがRopeのコマンドです。
まだ、使い始めたばかりなのでひとまず理解しているこの3つだけです。
コマンドとその動作の一覧はRope本家からダウンロードしてきて、docs/overview.txtに書いてあるのですが機能が多すぎてまだまださっぱりです。
コマンド一覧ならばRope CheatSheetがあります。

使い方

まず、どのコマンドを叩いても初めの場合内部的にRopeOpenProjectというコマンドが呼ばれるようです。
これはRopeの初期化を行い、デフォルトでは現在のディレクトリに管理用の".ropeproject"というディレクトリを作成します。
あとは普通にVimPythonコードを書いていきます。

リネーム

変数やクラス名などのリネームはRopeRenameで行います。
このようなソースコードでクラスAをCに変更したい場合、Aにカーソルを移動させ":RopeRename"を行うと(もちろん.vimrcにmapしたコマンドでもOK)変更名を聞いてくるのでCと入力するとリネームされます。

class A(objet):
    pass

class B(objet):
    pass

a = A()
b = B()

リネームするとこのようになるはず。

class C(objet):
    pass

class B(objet):
    pass

a = C()
b = B()
メソッドへの切り出し

次はメソッドへの切り出しです。
次のようなコードで"c = a + b"の行に移動しビュジュアルモードで選択を行います。
その後、":RopeExtractMethod"を入力するとメソッド名を聞かれてメソッドを作成してくれます。

a = 1
b = 2
c = a + b
print c

関数名をhogeと入力すると以下のように修正されます。戻り値の処理もきちんと行われています。
class内で":RopeExtractMethod"した場合クラスのメソッドとして定義されます。

a = 1
b = 2

def hoge():  
    c = a + b
    return c

c = hoge()
print c


ちなみに、RopeUndoは上記のような操作の取り消しを行ってくれます。

まとめ

PyCharmのようなIDEが無くてもしっかりとリファクタリングが出来たので個人的には満足です。
まだまだコマンドがあるのであとは使い方を調べ無いとダメですが。


あとまだ試していませんが、Rubyだとhttps://github.com/ecomba/vim-ruby-refactoringというのも見つけました。
いずれ試すつもりです。