Watson's Blog

短いメソッドは Grep で探すの大変ですよね

| Comments

この記事は RubyMotion Advent Calendar 2012 の 9 日目の記事です。

タイトルそのままなのですが、短いメソッドなどを探すのって大変ですよね。デバッグのために仕込んだ p メソッドを取り外そうと検索すると、いろいろなものに紛れ込んでしまいますよね。

grep で検索すると・・・

grep で検索するといろいろなノイズに紛れ込んでしまいます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ grep "p" -r **/*.rb
app/app_delegate.rb:1:class AppDelegate
app/app_delegate.rb:2:  def application(application, didFinishLaunchingWithOptions:launchOptions)
app/controllers/camera_controller.rb:4:    super
app/controllers/camera_controller.rb:8:    @library = UIButton.buttonWithType(UIButtonTypeRoundedRect)
app/controllers/camera_controller.rb:11:    @library.when UIControlEventTouchUpInside do
app/controllers/camera_controller.rb:12:      BW::Device.camera.any.picture(media_types: [:image]) do |result|
app/controllers/camera_controller.rb:21:      @front = UIButton.buttonWithType(UIButtonTypeRoundedRect)
app/controllers/camera_controller.rb:26:      @front.when UIControlEventTouchUpInside do
app/controllers/camera_controller.rb:27:        BW::Device.camera.front.picture(media_types: [:image]) do |result|
app/controllers/camera_controller.rb:33:      p @front
app/controllers/camera_controller.rb:38:      @rear = UIButton.buttonWithType(UIButtonTypeRoundedRect)
app/controllers/camera_controller.rb:43:      @rear.when UIControlEventTouchUpInside do
app/controllers/camera_controller.rb:44:        BW::Device.camera.rear.picture(media_types: [:image]) do |result|
spec/main_spec.rb:1:describe "Application 'google_location'" do
spec/main_spec.rb:3:    @app = UIApplication.sharedApplication
spec/main_spec.rb:7:    @app.windows.size.should == 1

検索するツールを作りました

rbfind
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env macruby
# -*- coding: UTF-8 -*-
require 'ripper'

class Discovery < Ripper::SexpBuilder
  def initialize(path, find_name, matcher = :==)
    @path      = path
    @find_name = find_name
    source     = File.read(path)
    @lines     = source.lines.to_a
    @matcher   = matcher
    super(source)
  end

  SCANNER_EVENTS.each do |event|
    define_method("on_#{event}") do |token|
      if token && token.send(@matcher, @find_name)
        line = lineno()
        puts "#{@path}:#{line}:#{@lines[line-1]}"
      end
    end
  end
end

if $0 == __FILE__
  find_name = ARGV[0]
  files = Dir.glob("**/*.rb").delete_if{|x| x == $0}
  files.each do |path|
    Discovery.new(path, find_name).parse
  end
end

RubyMotion はキーワード付き引数をサポートしているため、それを扱える MacRuby か Ruby 2.0 で実行してください。(CRuby 向けのコードでしたら、Ruby 1.9 でも動作するはずです)

Rubyのソースコードをトークン単位で検索します。実行すると、以下のような感じになります。

1
2
$ rbfind p           
app/controllers/camera_controller.rb:33:      p @front

完全に一致した場合に表示しているので、インスタンス変数を調べるときには @front のように ワードを指定します。

短いメソッドなどを探すのが楽になるかなと思っていますが、いかがでしたでしょうか。

Comments