fparseln(3)もどき #2

灯台

id:ha-tan:20050727のなかださんのコメントを見て、クラスIOはEnumerableをインクルードしているとはじめて知りました(ソースは以下)。

io.c
...
    5311 void
    5312 Init_IO()
    5313 {
...
    5353     rb_cIO = rb_define_class("IO", rb_cObject);
    5354     rb_include_module(rb_cIO, rb_mEnumerable);
...

ということで、なかださんのコメントを反映した版を以下に貼っておきます。

module Enumerable
  def parseln(lineno = nil, delim = '\\\\#')
    esc = Regexp.escape(delim[0].chr)
    con = Regexp.escape(delim[1].chr)
    com = Regexp.escape(delim[2].chr)
    escre = /#{esc}(.)/
    conre = /(^|[^#{esc}])#{con}$/
    comre = /(^|[^#{esc}])#{com}/

    buf = ''
    self.each do |line|
      line.chomp!
      lineno += 1 unless lineno.nil?

      if line =~ comre
        line = $` + $1
        next if line.size == 0 and buf.size == 0
      end

      if line =~ conre
        buf += ($` + $1).gsub(escre, '\1')
        next
      end

      buf += line.gsub(escre, '\1')
      if lineno.nil?
        yield(buf)
      else
        yield(buf, lineno)
      end
      buf = ''
    end
  end
end

IOのメソッドにするよりもEnumerableのメソッドにした方が汎用でよいのですが、このメソッド本来の用途がぼけてしまいそうですね…