Ruby の 定番対話ツール pry 徹底攻略 | Accessing the system 🐚 shell #pry #ruby

# Ruby の 定番対話ツール pry 徹底攻略 | :shell: Accessing the system shell
## <i class="fa fa-cubes" style="font-size:1em;"></i> 概要
Ruby の 定番対話ツール pry 徹底攻略
:shell: System Shell へのアクセスについて

## :shell: Accessing the system shell
REPL 環境から System Shell にアクセスできると便利です。
Pry では任意の Shell Command を実行できます。

## :shell::runner: Execute arbitrary shell commands
### Shell Command の実行
Pry では、コマンドの先頭にドット ( . ) をつけることで、
任意の Shell Command を実行できます。

これにより、 Pry の RPEL 環境の中で

* ディレクトリを作成したり
* git に commit したり
* diff を使ったり

ということができます。

~~~
[1] pry(main)> .ls
hoge.rb  ls.rb
[2] pry(main)> .mkdir hoge
[3] pry(main)> .ls
hoge  hoge.rb  ls.rb
[4] pry(main)> .tree
.
├── hoge
├── hoge.rb
└── ls.rb
~~~

### Ruby のコードの処理結果を Shell に書き入れる
`#{}` を利用することで、 Pry で実行した Ruby の処理結果を Shell に書き入れる事ができます

※下記の例の実行前に `figlet` , `sl` のインストールが必要です

* Ruby で 20 番目の素数を取得して、 shell の figlet command で AA に変換する

~~~
[24] pry(main)> .echo #{Prime.take(20).last} | figlet
 _____ _ 
|___  / |
   / /| |
  / / | |
 /_/  |_|
~~~

* sl コマンドで SL を呼び出す。オプションは Ruby でランダムに選択する

~~~
[3] pry(main)> .sl #{['', '-l', '-a', '-F'].sample}
                          (@@) (  ) (@)  ( )  @@    ()    @     O     @     O
                     (   )
                 (@@@@)
              (    )

            (@@@)
            ++      +------ ____          _      __________ _________ __________
            ||      |+-+ |  |   \@@@@@@@\@@@     |  ___ ___ ___ ___ | |  ___ ___
          /-------/-|| | |  |    \@@@@@@@\@@@@@_ |  |_| |_| |_| |_| | |  |_| |_|
         + ========  +-+ |  |          |       | |__________|_______| |_________
        _|--O========O~\-+  |__________|_______| |__________|_______| |________
       //// \_/      \_/   ==/ (O)   (O) (O)   (O)  (O)   (O)  (O)   (O) (O)
~~~

## :point_right::shell: Shell mode
ファイルやディレクトリの操作を連続で行う際などに、 Shell mode が便利です。
`shell-mode` コマンドで、 Shell mode になり、

* プロンプトにディレクトリパスが表示される
* ファイルやフォルダの入力補完が有効になる

などの支援を受けることができます。
再度 `shell-mode` コマンドを実行すると、 Shell mode を終了します。

~~~
# カレントディレクトリにあるファイルを確認
[25] pry(main)> .ls -1
hoge
hoge.rb
ls.rb

# 通常のモードだと、 hoge.rb の補完がきかない
[26] pry(main)> .cat hoge.rb
require 'pry'
class Hoge
  def hoge
    puts "hoge"
    binding.pry
    puts "hoge2"
  end
end

Hoge.new.hoge

# Shell mode 開始
[27] pry(main)> shell-mode

# 補完・サジェストが有効になりました
pry main:/path/to/current/dir $ .cat hoge
hoge     hoge.rb  

pry main:/path/to/current/dir $ .cat hoge.rb
require 'pry'
class Hoge
  def hoge
    puts "hoge"
    binding.pry
    puts "hoge2"
  end
end

Hoge.new.hoge

# Shell mode 終了
pry main:/path/to/current/dir $ shell-mode
[30] pry(main)> 

~~~

## :cat: The cat command
他の Shell command と異なり、 cat はドット ( . ) 抜きで呼び出すことができます。
また、 Pry の cat は以下のファイルのシンタックス・ハイライトに対応しています。

`.rb, .py, .cpp, .java, .json, .php, .xml`

### :cat2: cat 試行

![cat1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/552e2cc1-bfc9-0ff7-02e4-fbc2cb06c6a4.png)

### <i class="fa fa-sort-numeric-asc" style="font-size:1em;"></i>:cat2: cat 試行( -l option )
Pry の cat は様々な option を提供しています。
ここでは、行番号を表示する -l option を使用します。
その他のオプションについては、 `cat -h` でご確認ください。

![cat2.png](https://qiita-image-store.s3.amazonaws.com/0/43480/46d7bcd7-b93b-4af3-4cb0-1a2928dfa480.png)

## <i class="fa fa-file-text-o" style="font-size:1em;"></i>:file_folder: The \_file\_ and \_dir\_ locals
`show-method, show-doc, show-source, stat and cat` のような command は、
ローカル変数 `_file_` と `_dir_` の値を書き換えます。

~~~
[5] pry(main)> cat hoge.rb
require 'pry'
class Hoge
  def hoge
    puts "hoge"
    binding.pry
    puts "hoge2"
  end
end

Hoge.new.hoge
[6] pry(main)> _dir_
=> "/path/to/current/dir"
[7] pry(main)> _file_
=> "/path/to/current/dir/hoge.rb"
[8] pry(main)> 
[9] pry(main)> 
[10] pry(main)> show-source Prime.each
Error: Couldn't locate a definition for Prime.each!
[11] pry(main)> require 'prime'
=> true
[12] pry(main)> show-source Prime.each

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

def #{ali}(*args, &block)
  begin
    #{accessor}.__send__(:#{method}, *args, &block)
  rescue Exception
    $@.delete_if{|s| %r"#{Regexp.quote(__FILE__)}"o =~ s} unless Forwardable::debug
    ::Kernel::raise
  end
[13] pry(main)> _file_
=> "/path/to/ruby/install/dir/forwardable.rb"
[14] pry(main)> _dir_
=> "/path/to/ruby/install/dir"
~~~

## :gem: The gem-cd command
`gem-cd` で任意の gem のディレクトリに移動できます。
gem のソースを `cat` を利用して表示したい場合など、 Shell command と組み合わせると便利です。

~~~
$ pry
[1] pry(main)> .pwd
/path/to/current/dir
[2] pry(main)> gem-cd ruboty
/path/to/ruboty/install/dir/ruboty-1.1.2
[3] pry(main)> .pwd
/path/to/ruboty/install/dir/ruboty-1.1.2
[4] pry(main)> .tree
.
├── CHANGELOG.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin
│   └── ruboty
├── lib
│   ├── ruboty
│   │   ├── action.rb
│   │   ├── actions
│   │   │   ├── base.rb
│   │   │   ├── help.rb
│   │   │   ├── ping.rb
│   │   │   └── whoami.rb
│   │   ├── adapter_builder.rb
│   │   ├── adapters
│   │   │   ├── base.rb
│   │   │   └── shell.rb
│   │   ├── brains
│   │   │   ├── base.rb
│   │   │   └── memory.rb
│   │   ├── command_builder.rb
│   │   ├── commands
│   │   │   ├── base.rb
│   │   │   ├── generate.rb
│   │   │   └── run.rb
│   │   ├── env
│   │   │   ├── missing_required_key_error.rb
│   │   │   ├── validatable.rb
│   │   │   └── validation_error.rb
│   │   ├── env.rb
│   │   ├── handlers
│   │   │   ├── base.rb
│   │   │   ├── help.rb
│   │   │   ├── ping.rb
│   │   │   └── whoami.rb
│   │   ├── logger.rb
│   │   ├── message.rb
│   │   ├── robot.rb
│   │   └── version.rb
│   └── ruboty.rb
├── ruboty.gemspec
├── spec
│   ├── ruboty
│   │   ├── adapter_builder_spec.rb
│   │   ├── adapters
│   │   │   └── shell_spec.rb
│   │   ├── commands
│   │   │   ├── generate_spec.rb
│   │   │   └── run_spec.rb
│   │   ├── env
│   │   │   └── validatable_spec.rb
│   │   ├── handlers
│   │   │   ├── base_spec.rb
│   │   │   ├── help_spec.rb
│   │   │   ├── ping_spec.rb
│   │   │   └── whoami_spec.rb
│   │   └── robot_spec.rb
│   └── spec_helper.rb
└── templates
    └── Gemfile

16 directories, 46 files

# Ruboty の Action の基底クラスである lib/action/base.rb を表示
[5] pry(main)> cat lib/ruboty/actions/base.rb
module Ruboty
  module Actions
    class Base
      attr_reader :message

      def initialize(message)
        @message = message
      end
    end
  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 | Accessing the system shell](https://github.com/pry/pry/wiki/Shell-Integration)