Ruby の 定番対話ツール pry 徹底攻略 | 👓 Source browsing #pry #ruby

# Ruby の 定番対話ツール pry 徹底攻略 | <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i> Source browsing
## <i class="fa fa-cubes" style="font-size:1em;"></i> 概要
Ruby の 定番対話ツール pry 徹底攻略
ソースコードの表示について

## <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i> Source browsing
pry の killer feature の1つはクラスやメソッドのソースコード表示です。

pry は外部ユーティリティに依存することなくソースコードの表示機能を提供しています。
ソースコード表示の機能は、ドキュメントが少ないライブラリのような、新たなコードベースを
探索する際に、非常に重宝する機能です。

## <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i> View method and class source code
### show-source
`show-source` でクラスやメソッドのソースコードをシンタックスハイライト付きで表示できます。

* クラスの表示

~~~
[17] pry(main)> require 'prime'
=> true
[18] pry(main)> show-source Prime

From: /path/to/ruby/lib/ruby/2.0.0/prime.rb @ line 91:
Class name: Prime
Number of lines: 419

class Prime
  include Enumerable
  @the_instance = Prime.new

  # obsolete. Use +Prime+::+instance+ or class methods of +Prime+.
  def initialize
    @generator = EratosthenesGenerator.new
    extend OldCompatibility
    warn "Prime::new is obsolete. use Prime::instance or class methods of Prime.
  end
# 以下略
~~~

* クラスメソッドの表示（ l オプションで行数表示付き ）

~~~
# Prime.each クラスメソッドのソースコードを表示。 l オプションで行数表示
[28] pry(main)> show-source Prime.each -l

From: /path/to/ruby/lib/ruby/lib/ruby/2.0.0/forwardable.rb @ line 169:
Owner: #<Class:Prime>
Visibility: public
Number of lines: 7

169: def #{ali}(*args, &block)
170:   begin
171:     #{accessor}.__send__(:#{method}, *args, &block)
172:   rescue Exception
173:     $@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug
174:     ::Kernel::raise
175:   end
~~~

* インスタンスメソッドの表示（ l オプションで行数表示付き ）

~~~
[35] pry(main)> show-source Prime#each -l

From: /path/to/ruby/lib/ruby/lib/ruby/2.0.0/prime.rb @ line 147:
Owner: Prime
Visibility: public
Number of lines: 4

147: def each(ubound = nil, generator = EratosthenesGenerator.new, &block)
148:   generator.upper_bound = ubound
149:   generator.each(&block)
150: end
~~~

* 画像でシンタックスハイライトを確認

![show-source.png](https://qiita-image-store.s3.amazonaws.com/0/43480/2d236faf-e254-aeb7-b1aa-376c84e68340.png)

* `show-source` のその他の機能
help で確認し、各自試してみてください

~~~
[38] pry(main)> show-source -h
Usage:   show-source [OPTIONS] [METH|CLASS]
Aliases: $, show-method

Show the source for a method or class. Tries instance methods first and then
methods by default.

show-source hi_method
show-source hi_method
show-source Pry#rep     # source for Pry#rep method
show-source Pry         # for Pry class
show-source Pry -a      # for all Pry class definitions (all monkey patches)
show-source Pry --super # for superclass of Pry (Object class)

https://github.com/pry/pry/wiki/Source-browsing#wiki-Show_method

    -s, --super             Select the 'super' method. Can be repeated to traverse the ancestors
    -l, --line-numbers      Show line numbers
    -b, --base-one          Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)
    -a, --all               Show all definitions and monkeypatches of the module/class
    -h, --help              Show this message.
~~~

### ri
`ri` で、 pry 上から `ri` コマンドを実行します。
ri によって、クラスやメソッドに関する利用コンテキストや用法、利用例などを表示します。
ri は独立したツールなので、詳細は別途 Google 等でご確認ください。

## <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i>  View the source code for Pry commands
Pry 自身のソースコードですら表示できます。

* `show-source` のソースコードを表示

~~~
[42] pry(main)> show-source show-source

From: /path/to/ruby/lib/ruby/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/commands/show_source.rb 
Number of lines: 30

class Command::ShowSource < Command::ShowInfo
  match 'show-source'
  group 'Introspection'
  description 'Show the source for a method or class.'

  banner <<-'BANNER'
    Usage:   show-source [OPTIONS] [METH|CLASS]
    Aliases: $, show-method

    Show the source for a method or class. Tries instance methods first and then
    methods by default.

    show-source hi_method
    show-source hi_method
    show-source Pry#rep     # source for Pry#rep method
    show-source Pry         # for Pry class
    show-source Pry -a      # for all Pry class definitions (all monkey patches)
    show-source Pry --super # for superclass of Pry (Object class)

    https://github.com/pry/pry/wiki/Source-browsing#wiki-Show_method
  BANNER

  # The source for code_object prepared for display.
  def content_for(code_object)
    cannot_locate_source_error if !code_object.source

    Code.new(code_object.source, start_line_for(code_object)).
      with_line_numbers(use_line_numbers?).to_s
  end
end
~~~

## <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i>:gem::heartbeat: View source for Ruby Core (MRI C code)

pry の Plugin である pry-doc をインストールしていれば、
Ruby の core method の C のソースコードを表示できます。

* prepare

~~~bash
$ gem install pry-doc
~~~

* Kernel#puts を表示

~~~
[43] pry(main)> show-source Kernel#puts

From: io.c (C Method):
Owner: Kernel
Visibility: private
Number of lines: 8

static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
    if (recv == rb_stdout) {
	return rb_io_puts(argc, argv, recv);
    }
    return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
}
~~~

## <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i><i class="fa fa-plus" style="font-size:1em;"></i>:gem: View Rubinius core source code
pry は Rubinius core のソースコードを表示できます。[^1]

## <i class="fa fa-eye" style="font-size:1em;"></i><i class="fa fa-code" style="font-size:1em;"></i> View the source of ..
### :clock1: the current method
`binding.pry` を利用した場合、
単に `show-source` のみでメソッドのソースコードを表示できます。

~~~
$ cat hoge.rb 
require 'pry'
class Hoge
  def hoge
    puts "hoge"
    binding.pry
    puts "hoge2"
  end
end

Hoge.new.hoge
$ ruby hoge.rb 
hoge

From: /path/to/current/dir/hoge.rb @ line 5 Hoge#hoge:

    3: def hoge
    4:   puts "hoge"
 => 5:   binding.pry
    6:   puts "hoge2"
    7: end

[1] pry(#<Hoge>)> show-source

From: hoge.rb @ line 3:
Owner: Hoge
Visibility: public
Number of lines: 5

def hoge
  puts "hoge"
  binding.pry
  puts "hoge2"
end
~~~

### :arrow_right: the Lambdas and Procs
pry は lambda や proc のソースコードも表示できます。

* lambda

~~~
[1] pry(main)> double = lambda { |e|e * 2 }
=> #<Proc:0xb9696f2c@(pry):1 (lambda)>
[2] pry(main)> double[2]
=> 4
[3] pry(main)> double[4]
=> 8
[4] pry(main)> show-source double

From: (pry) 
Number of lines: 1

double = lambda { |e|e * 2 }
[6] pry(main)> triple =->(e){ e*3 }
=> #<Proc:0xb96f6cb0@(pry):5 (lambda)>
[7] pry(main)> triple[2]
=> 6
[8] pry(main)> triple[4]
=> 12
[9] pry(main)> show-source triple

From: (pry) 
Number of lines: 1

triple =->(e){ e*3 }
~~~

* proc

~~~
[12] pry(main)> double = proc { |e|e*2 }
=> #<Proc:0xb9769fa8@(pry):8>
[13] pry(main)> double[2]
=> 4
[14] pry(main)> double[4]
=> 8
[15] pry(main)> show-source double

From: (pry) 
Number of lines: 1

double = proc { |e|e*2 }
[16] pry(main)> triple = Proc.new {|e|e*3}
=> #<Proc:0xb97d968c@(pry):11>
[17] pry(main)> triple[2]
=> 6
[18] pry(main)> triple[4]
=> 12
[19] pry(main)> show-source triple

From: (pry) 
Number of lines: 1

triple = Proc.new {|e|e*3}
~~~

### :mailbox_with_no_mail: classes of arbitrary objects
pry はほぼすべてのクラスのソースコードを表示できるが、例外は空のクラスです。
少なくともひとつのメソッド（クラスメソッド、インスタンスメソッドを問わず）を実装している必要があります。

* class source

~~~
[28] pry(main)> class Hige
[28] pry(main)* end  
=> nil
[29] pry(main)> show-source Hige
Error: Couldn't locate a definition for Hige!
[30] pry(main)> class Hige
[30] pry(main)*   HIGE = "hige"
[30] pry(main)* end  
=> "hige"
~~~

* arbitrary objects
<i class="fa fa-external-link" style="font-size:1em;"></i> [公式ドキュメントのサンプル参照](http://showterm.io/3aefa17ac44984b156048)

### :monkey: all definitions and monkey-patches of classes or modules
`show-source` の `a` オプションで、全てのモンキーパッチをまとめて表示します。

~~~
$ cat monkey1.rb 
class Monkey
  def monkey1
  end
end

$ cat monkey2.rb 
class Monkey
  def monkey2
  end
end

$ pry
[3] pry(main)> require './monkey1'
=> true
[4] pry(main)> require './monkey2'
=> true
[5] pry(main)> show-source Monkey

From: /path/to/current/dir/monkey1.rb @ line 1:
Class name: Monkey
Number of monkeypatches: 2. Use the `-a` option to display all available monkeypatches
Number of lines: 4

class Monkey
  def monkey1
  end
end
[6] pry(main)> show-source Monkey -a
Found 2 candidates for `Monkey` definition:

Candidate 1/2: /path/to/current/dir/monkey1.rb @ line 1:
Number of lines: 4

class Monkey
  def monkey1
  end
end

Candidate 2/2: /path/to/current/dir/monkey2.rb @ line 1:
Number of lines: 4

class Monkey
  def monkey2
  end
end
~~~

## :man::woman: 親記事
<i class="fa fa-external-link-square" style="font-size:1em;"></i> [Ruby の 定番対話ツール pry 徹底攻略](http://qiita.com/tbpgr/items/12a60f2f9e3de61517b5)

## :books: 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [pry Wiki | Source browsing](https://github.com/pry/pry/wiki/Source-browsing)

## :books: 脚注
[^1]: [Rubinius](https://github.com/rubinius/rubinius)