Ruby のクラスやメソッドのドキュメントを見れる ri コマンドが便利な件


Ruby をインストールすると付いてくる ri コマンドを使うと, Ruby のクラスやメソッドのドキュメントをコマンドラインからオフラインで見ることができてしまうので利便性高すぎワロタです.

この記事のサンプルコードは次の環境での動作を確認しております:

  • macOS 10.13.6
  • Ruby 2.5.1
  • Neovim 0.3.1

ri コマンドの確認

Ruby がインストールされていると:

$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]

ri コマンドも使えます:

$ ri -v
ri 6.0.4

ちなみに ri コマンドは “Ruby Interactive” という意味になります.

irb コマンドの “Interactive Ruby Shell” と名前が似ているので混同に注意が必要ですね.

ri コマンドの使い方

この ri コマンドを使うと, なんと Ruby のクラスやメソッド, もっと詳しく言いますと, 次のドキュメントを見ることができます:

  • Class – クラス
  • Class::method – 指定のクラスのクラスメソッド
  • Class#method – 指定のクラスのインスタンスメソッド
  • Class.method – 指定のクラスのクラスメソッドもしくはインスタンスメソッド
  • method – クラスメソッドもしくはインスタンスメソッド
  • Module – モジュール
  • Module::Class – 名前空間付きのクラス

例えば String クラスのドキュメントを見る場合, 次のようになります:

ri String

String クラスのクラスメソッド new のドキュメントを見る場合, 次のようになります:

ri String::new

String クラスのインスタンスメソッド chomp のドキュメントを見る場合, 次のようになります:

ri String#chomp

Stringnew というメソッド名はクラスメソッドしか存在しないので, 次のようにもできます:

ri String.new

同じように Stringchomp というメソッド名はインスタンスメソッドしか存在しないので, 次のようにもできます:

ri String.chomp

もし Array クラスの [] というメソッド名の場合, クラスメソッドの Array::[] と, インスタンスメソッドの Array#[] の両方が存在するので, Array.[] とするとその両方が表示されます:

ri 'Array.[]'

さらっと 'Array.[]''' で囲んでエスケープしてしまいましたが, メソッド名が記号の場合, あくまでコマンドラインからの入力なので, このようにエスケープする必要がある場合があります.

このように Class::method, Class#method, Class.method とすると, 表示されるメソッドは指定される Class のメソッドに限定されます.

もしクラスを何も指定しないで method とすると, インストールされている全てのクラスから同じ名前のメソッドを表示します:

ri new

僕の場合, 上記のコマンドを入力したら, ありとあらゆるクラスの new メソッドが表示されて, ドキュメントが表示されるまで数秒かかってしまいました.

あとモジュールもクラス同様に指定できます:

ri Digest

モジュールの名前空間下にあるクラスも指定できます:

ri Digest::SHA1

中途半端な入力でも示唆してくれる

もし次のようにクラスやメソッド名を完全に入力しなかったり, 間違えて入力して Enter を押したとしても, 入力者の意図を汲み取って示唆してくれます:

$ ri Stri
Nothing known about Stri
Did you mean?  String

$ ri Strong
Nothing known about Strong
Did you mean?  String

$ ri String#cho
String#cho not found, maybe you meant:

String#chomp
String#chomp!
String#chop
String#chop!
String#chown

$ ri String#champ
Nothing known about String#champ
Did you mean?  chomp
               chomp!

いやぁ賢いですね.

インタラクティブモードの場合

次のように -i オプションを付けて実行すると:

$ ri -i

Enter the method name you want to look up.
You can use tab to autocomplete.
Enter a blank line to exit.

>>

インタラクティブモードになり, 連続してクラスやメソッドのドキュメントを見れるようになります.

また ri と実行するだけでも, そのようになります:

$ ri

Enter the method name you want to look up.
You can use tab to autocomplete.
Enter a blank line to exit.

>>

インタラクティブモードの良いところは, >> というプロンプトにクラスやメソッド名を入力して, ドキュメントがページャの less などで表示されて, ドキュメントを見て, q で終了すると, また >> というプロンプトに戻ることができるので, テンポよく次から次へとドキュメントを開いていくことができます. (ri コマンドを先頭につける必要がないので)

また Array.[] など, メソッド名が記号の場合でも先ほどのようにエスケープする必要がなく, そのまま入力できる点も良いです:

>> Array.[]

インタラクティブモードを終了する場合, 何も入力せずに空欄のままで Enter を押すか, Control + D で終了できます.

フォーマッタを変更する

ri コマンドの -f オプションで, ドキュメントを表示する際に使用するフォーマッタを指定できます.

デフォルトでは bs もしくは ansi となるようで, 他にも markdownrdoc というものがあります.

参考までに, 僕が String#chomp というインスタンスメソッドを ansi, bs, markdown, rdoc というそれぞれのフォーマッタを指定して, ページャの less を通して表示した時の画面になります:

ri -f ansi String#chomp の場合:

Ri f ansi string chomp

ri -f bs String#chomp の場合:

Ri f bs string chomp

ri -f markdown String#chomp の場合:

Ri f markdown string chomp

ri -f rdoc String#chomp の場合:

Ri f rdoc string chomp

ri コマンドで less を通してドキュメントを見る場合, この 4 つのフォーマッタの中では ansi が一番見やすいのでしょうか.

デフォルトのフォーマッタを指定する場合, 環境変数 RI.bashrc.zshrc などに設定します.

例えば ansi をデフォルトとする場合, 次のようになります:

export RI="-f ansi"

環境変数 RI はデフォルトのオプションを設定できるので, -f 以外のオプションも同様に指定できます.

ページャを設定する

ri コマンドで使用されるページャは環境変数 PAGERRI_PAGER に設定されているものになります.

less コマンドをページャとする場合, PAGER.bashrc.zshrc に設定するか:

export PAGER="less"

RI_PAGER を設定します:

export RI_PAGER="less"

次のように PAGERRI_PAGER を両方とも設定して, 設定している内容が異なる場合, RI_PAGER の設定が優先され, ri コマンドのページャとして more コマンドが使われます:

export PAGER="less"
export RI_PAGER="more"

ただ moreless の下位版という感じなので, 実際に moreRI_PAGER に指定する意味はあまりない気がします…

個人的な設定

かなり個人的な僕の現時点の設定を紹介させていただきたいと思います.

まず, デフォルトのフォーマッタを markdown にしています.

そして, 僕は Neovim を使っているので, それをページャとして使っています.

それらの .zshrc の設定内容は次のようになってます:

export RI="-f markdown"
export RI_PAGER="nvim -RM -c 'set ft=markdown cocu=nc cole=2' -c 'nn q :q<cr>' -"

RI の内容はいいとして, RI_PAGER="..."... の内容の意味は, まず nvim で Neovim をページャとして使うようにし, その Neovim のオプションとして, -R で読み取り専用モードにして, -M でバッファの編集と書き込みをできないようにし, -c '...'... の中のコマンドを実行させ, ... の中の set でオプションを設定し, ft=markdown でファイルタイプを markdown にし, cocu=nc で現在の行もノーマルモードとコマンドラインモードでコンシールさせ, cole=2 でコンシールレベルを 2 とし, もう一つの -c '...'nn q :q<cr> として, q を押すと現在のバッファを閉じるようにし, 最後の - で標準入力からのテキストを EOF まで読み込むようにしています. (- を付けなくても特に問題なく ri コマンドが使えるのですが, 保険の意味合いで付けています)

そして Neovim の Markdown 用プラグインとして vim-markdown を使用しているので, :Toc, :Toch, Toct, Tocv といったコマンドで, 開いている Markdown バッファのヘッダの目次が表示されるウィンドウを表示させることができます.

設定した cocu=nccole=2 というオプションは, このプラグインのおかげで設定する意味を持てています.

あと Neovim の設定ファイル ~/.config/nvim/init.vim に次のようなマッピングを設定しています:

au FileType markdown nn gO :Toch<cr>

この設定は ri コマンドに限らず, 全ての Markdown ファイルに適用されるのですが, ノーマルモードで gO と入力すると, :Toch コマンドを実行するようになります.

なぜ gO なのかというのは, :h:Man で表示されるファイルタイプのバッファで gO というコマンドでそれらのバッファの目次を見ることができるので, それに倣わせてもらっているという感じです.

ri String#chomp で表示されるドキュメントのスクリーンショットはこんな感じになります:

Ri string chomp via nvim

ri --no-gems Regexp で Ruby の組み込みクラスの Regexp のドキュメントのみ表示した場合です:

Ri no gems regexp via nvim

gO と入力して目次を表示した場合です:

Ri no gems regexp via nvim with go

かなり個人的というかモンキーパッチ感のある設定を紹介させていただいて恐縮ですが, 今現在, 僕はこんな感じで ri コマンドを使っています sweat_smile

RI データを生成する

RubyGem をインストールする時, gem install GEMNAME --no-document もしくは gem install GEMNAME --no-ri でインストールした RubyGem がある場合, その gem の RI データが生成されていないので, ri コマンドでその gem のドキュメントを見ることができません.

もしくは ~/.gemrc という gem コマンドの設定ファイルに次のいずれかの行を加えていた場合も同様です:

install: --no-document

もしくは

install: --no-ri

そのような場合, RI データが生成されていない gem の RI データを生成する方法として, 次のコマンドで可能です:

$ gem rdoc GEMNAME --ri

GEMNAME に RI データを生成したい gem の名前を指定します. 例) rails, sinatra, etc.

もし RI データが生成されていない全ての gem の RI データを生成する場合, 次のコマンドになります:

$ gem rdoc --all --ri

また gem rdoc コマンドで --ri オプションはデフォルトなので, そのデフォルトを変更していない限り, 次のように省略しても RI データは生成されます:

$ gem rdoc GEMNAME
$ gem rdoc --all

まとめ

ri コマンドは CLI なのでコマンドラインからの操作になり, 万人向けではないかと思いますが, コマンドラインからサッと目的のクラスやメソッドのドキュメントをオフラインで見れてしまうその利便性は素晴らしいです.

ただ正直 Ruby-Doc.orgRubyDoc.info などの Web のドキュメントの方がより詳細だったり, 検索しやすかったり, ソースコードも見れたりしますが, RI データが充実しているクラスやメソッドのドキュメントを見るときは, ri コマンドを使い, あまり RI データが充実していないクラスやメソッドを見るとき, もしくはより詳細な情報を見るときは, そのような Web のドキュメントを見るというように使い分けるといいのかもしれません.

Ruby の String, Array, Hash などの組み込みクラスやそのメソッドは RI データがとても充実しているので, ri コマンドを使う有用性がとても高いです.

僕の使用している PC は MacBook 一台のみで, ターミナルをメインで使っているということもあり, ri コマンドは本当に重宝しています.

まるで man コマンドで, シェルコマンドのマニュアルを見るかのように使えますので.

RI_PAGER という環境変数も設定できるので, 先ほどの自分の個人的な設定もそうですが, 自分の使いたいように使うことができるという点も良いです.

Ruby を使われている方で, 僕のように CLI マニアな方は, ri コマンドを使わない手はないでしょう stuck_out_tongue_closed_eyes

参考資料