はじめに

この文章では、Ruby用のリファクタリングブラウザ、「Ruby Refactoring Browser」 の簡単な使いかたについて説明します。

インストール

ここでは、Emacs上から使うための設定を説明します。FreeRIDEでの使用については README.jaに書いてありますので、それを見てください。

まず、<URL:http://www.kmc.gr.jp/projects/rrb/>からRuby Refactoring Browser のソースアーカイブを取得します。そして、ファイルを展開します。 そこで生成された rrb-0.0.3 に移動し、README.jaを読んでください。

ruby setup.rb config
ruby setup.rb setup
(必要ならsu でルートユーザに移行)
ruby setup.rb install

で必要なライブラリがインストールされます。

あとはelisp/rrb.elをEmacsのロードパスの通った場所にコピーすればインストールは 終了します。OSやディストリビューションによって場所は異なりますが、おそらく /usr/local/share/emacs/site-lisp/という名前のディレクトリがあると思います ので、そこにコピーしてください。

設定

まずはアーカイブl(rrb-0.0.3.tar.gz)のdoc/rrbrc.sampleというファイルを ホームディレクトリに.rrbrcという名前でコピーしてください。 そしてファイルの内容を変更します。 RRB::CONF['TAB_WIDTH']でタブ文字1個分に相当するスペースの数を指定します。 RRB::CONF['INDENT_LEVEL']でインデント1個の深さに相当するスペースの数を 指定します。デフォルトはそれぞれ8、2です。

そして.emacsにrrb.elをロードするように記述します。

(load "rrb")

で良いでしょう。また、emacs側での設定は特に必要ないでしょう。

さらに細かい設定をしたい方は、rrb.elやrrbrc.sampleを調べてください。

まずはローカル変数名の変更から

まずは最もわかりやすいリファクタリングであるローカル変数名の変更をしましょう。 まず、sample.rbという名の以下の内容のファイルを用意します。

class Hello
  def initialize(people,greeting="Hello")
    @people = people
    @greeting = greeting
  end

  def hello
    @people.each do |p|
      print "#{@greeting} #{p}!\n"
    end
  end
end

if $0 == __FILE__
  h = Hello.new(["yoshida","ohbayashi","hara"])
  h.hello
end

そして、

emacs sample.rb

とし、emacsを起動します。その後、M-x rrb-rename-local-variableと入力します。

するとまずはどのメソッドのローカル変数を変更するかを聞いてきます。 ここではHello#helloを選択しましょう。TABによる入力の補完が利用できます。

次に、リネームする変数を指定しましょう。ここではpを指定します。

最後に、新しい変数名を指定します。personと指定しましょう。

すると以下のように変更されるはずです。

class Hello
  def initialize(people,greeting="Hello")
    @people = people
    @greeting = greeting
  end

  def hello
    @people.each do |person|
      print "#{@greeting} #{person}!\n"
    end
  end
end

if $0 == __FILE__
  h = Hello.new(["yoshida","ohbayashi","hara"])
  h.hello
end

さて、これで成功です。@peopleの「p」という文字が変わっていないのが単なる 置換をしているわけではないということを示しています。

次に、undoをしてみましょう。M-x rrb-undoで、今の変更がundoされます。

さて、次にHello#initializeのpeopleをgreetingに変更しようとしてみましょう。 上の場合と同じようにすれば良いです。すると、エラーが発生し、

fail to refactor: greeting: already used

と表示されます。このように、変更後の変数名が被る場合などは適切にエラーを 発生させます。

可能なリファクタリング

Ruby Refactoring Browserでは、ローカル変数名の変更の他に、以下のような リファクタリングが可能です。

[rename なんとか]というリファクタリングは、上で説明したのと同じようにして 動かすことができます。

Extract methodは、C-SPCなどでmarkした所と、カーソルの間が切り出す対象となります。 基本的にRuby Refactoring Browserは行単位の動作が基本なので、指定したリージョンを 適当に何行目から何行目を指定したと見なして動作します。

Pull up, Push down method, extract superclassは、現在カーソルがある行に新たな メソッド、クラスが生成されるということに注意してください。

簡単な動作原理

現在のRuby Refactoring Browserには、様々な制限があります。それは主に Ruby という 言語が非常に動的な性質を持つということによるものですが、それとは別に、 Ruby Refactoring Browserの実装によるものも多くあります。その内容を説明するため、 Ruby Refactoring Browserの実装について簡単に解説します。

全体的な構図は以下の通りです。

-----------------------------
|  emacs interface(rrb.el)  |
-----------------------------
      | pipeによるプロセス間通信
-----------------------------
|     bin/rrb               |
|---------------------------|
|     コアライブラリ        |
|            |--------------|
|            |   Ripper改   |
-----------------------------

emacs側では入力の処理などしかせず、メインの機能はすべてRubyで記述されています。 elisp上でする処理は以下の通りです。

  1. リファクタリングの対象となるファイルを特定する
  2. ユーザからの入力を受け付け、新しい変数名などの情報を得る
  3. bin/rrbにそれらの入力を渡し、リファクタリング後のファイルを得る

で、その中では以下のような手順で処理がなされます。

  1. Ripperで対象のスクリプトをパースする
  2. Rubyのリフレクション機能で対象のスクリプトの情報を得る
  3. (1)、(2)で得た情報を元に指定されたリファクタリングが可能かどうか調べる
  4. 実際にリファクタリング後の結果を生成、出力する

ここで重要なのが(2)です。Rubyのリフレクション機能を使うためには実際にその スクリプトをRubyのインタプリタで動かす必要があるのです。しかし、それを してしまうと、リファクタリング中にファイルの編集がされたりwindowが開いたり しかねません。ここでRubyで良く使われるイディオム、 if $0 == __FILE__ ... end というのを利用します。 これで囲まれた部分は、他のファイルからrequireやloadで読みこまれた場合は 実行されないようになります。それを利用し、リフレクション利用時に 動作してほしくない部分をこれで囲んでしまえば良いのです。

Ruby Refactoring Browserの制限

というわけで、Ruby Refactoring Browserには以下のような制限があります。

以上のことは、Ruby Refactoring Browserの基本的な設計やRubyの特徴上、 避けがたい機能制限です。開発が進んでもこのあたりの制限がなくなることはないでしょう。

その他、実装の不備等による以下の制限があります。

Tips

リフレクションのための実行時には、グローバル変数「$rrb_run_for_reflection」が trueになっています。if $0 == __FILE__ ... end ではうまく処理できない部分がある 場合は、この変数を使いましょう。ただ、これを使うとプログラムが不自然になるので あまり使いすぎるのも良くないでしょう。

おわりに

このツールは、まだまだ発展途上にあります。多くの人の要望、バグレポート、 patch、その他の開発に対する寄与を期待しています。新たな開発者も歓迎いたします。 RubyForgeを利用しており、CVSへのanonymous accessやBTSはここのを利用してください。 <URL:http://www.rubyforge.org/projects/rrb/>です。 また、私に直接メールを下さってもかまいません。

また、現在ではRubyRefactoringBroserを使えるのはemacsからとFreeRIDEからのみ です。vimから使えるようにしたり、コンソールからの利用をできるようにする 予定ですが、その他にも様々なエディタにも対応したいと思っています。ただ 我々だけではそれは大変なので、○○というエディタ(or IDE)に対応させよう、と いう人がいないかなあと思っています。そういうことに対する詳しい解説もその うち書きたいと思っています。