Ruby のブロック構文の中身を文字列として取得する
using Module.new { refine RubyVM::InstructionSequence do def to_h %i( magic major_version minor_version format_type misc label path absolute_path first_lineno type locals args catch_table bytecode ).zip(to_a).to_h end end using self refine Proc do def body path, (start_lnum, start_col, end_lnum, end_col) = code_location raise "Unsupported file" if path.nil? File.readlines(path).then { |lines| start_line, end_line = lines[start_lnum-1], lines[end_lnum-1] if start_lnum == end_lnum start_line[(start_col+1)...(end_col-1)] elsif end_lnum - start_lnum == 1 start_line[(start_col+1)...] + end_line[...(end_col-1)] else start_line[(start_col+1)...] + lines[(start_lnum)...(end_lnum-1)].join + end_line[...(end_col-1)] end } end def code_location RubyVM::InstructionSequence.of(self).to_h .then { |iseq| [iseq[:absolute_path], iseq.dig(:misc, :code_location)] } end end } pp proc { hoge bar }.body # => " hoge bar " pp proc { hoge bar }.body # => " hoge\n" + " bar " pp proc { hoge foo1 foo2 bar }.body # => " hoge\n" + " foo1\n" + " foo2\n" + " bar "
RubyVM::InstructionSequence.of
に Proc
を渡すことでメタ情報を取得する事が出来るので、そこからソースファイルを読み込み必要な部分だけ切り出しています。
なので、irb とかから呼び出した場合には未対応。
そっちもやりたいんですけどねえ。