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.ofProc を渡すことでメタ情報を取得する事が出来るので、そこからソースファイルを読み込み必要な部分だけ切り出しています。
なので、irb とかから呼び出した場合には未対応。
そっちもやりたいんですけどねえ。