うう、こまったな、無性に Ruby のコードが書きたくなってきた。 こんなことをやっている余裕はまだないのだが……
[ruby-core:04345] [BUG?] Ripper
もちろん、バグではない。
しかしこれは、どう答えたものかなあ。 この人が求めているものを簡単に実現する方法はまだ存在しないのだが。 いや、tstring_content だけを取り出せばいいのなら簡単だけど、 それだと他の (ヒアドキュメントじゃない) 文字列も拾ってしまう。
まず前提として、トークンはこうなっている。
~ % ruby -rpp -rripper -e 'pp Ripper.scan(%(<<HERE\nstring\nHERE))' [[[1, 0], :on_heredoc_beg, "<<HERE"], [[1, 6], :on_nl, "\n"], [[2, 0], :on_tstring_content, "string\n"], [[3, 0], :on_heredoc_end, "HERE"]]
heredoc_beg と heredoc_end の間にある tstring_content だけを取りたいというのが求める解だろう。 正規表現マッチみたいなことができればいいわけだよな。
pattern = 'heredoc nl $(tstring_content*) heredoc_end'
と、いう感じにパターンを記述し、
Ripper.slice("<<HERE\nstring\nHERE", pattern, 1)
てな感じで $(...) にマッチする部分を取れる、というのはどうだろう。 をー、なんかいい感じがしてきたぜ。
実装はどうすっか。自分でエンジンを書くのはだるいな。
よし、考えついたぞ。 パターンは正規表現にコンパイルし、 対象は文字列にコンパイルして、普通に正規表現マッチを行う。 で、インデックスで両者の対応を取ればよい。
あー、実装したくなってきたけど、がまんしよう。
(01:43)
おれは誘惑に弱すぎると思った。
~/c/ruby/ext/ripper % ruby -I./lib -rripper -e ' p Ripper.slice(%Q(<<HERE\nstring\nHERE), "heredoc_beg nl $(tstring_content *) heredoc_end", 1) ' "string\n"
意図していなかったが、こんなこともできるようだ。
~/c/ruby/ext/ripper % ruby -I./lib -rripper -e ' p Ripper.slice(%(<<HERE\nstring\#{nil}\nHERE), "heredoc_beg nl $(.*?) heredoc_end", 1) ' "string\#{nil}\n"
これって、もしかしてすごく便利なのでは……
(02:40)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.