Rubyで遊んだ日々の記録。あくまで著者視点の私的な記録なので、正確さを求めないように。
Rubyと関係ない話題にはその旨注記しているはず。なので、一見関係無いように見える話題もどこかで関係あるのかもしれません。または、注記の書き忘れかもしれません...
_ 先日、ここに引用するRubyスクリプトにちろっと色をつけたりしてましたが、ripperが入ったので真面目にやってみることにしました。
require 'cgi' require 'ripper.so' class ColorParser < ::Ripper def self.define_event(ev, action) eval <<-EOM def on__#{ev}(token) add(token, '#{action}') end EOM end def parse @klass = nil @nl = '' @script = '' super @script << '</span>' if @klass @script << @nl end private def add(str, klass = nil) if @klass && (!klass || (klass && @klass != klass)) @script << '</span>' @klass = nil end @script << @nl @nl = '' if klass && !@klass @script << %Q!<span class="#{klass}">! @klass = klass end nstr = str.sub(/((\r?\n)+)$/) do @nl = $1 '' end @script << CGI.escapeHTML(nstr) str end def method_missing(mid, *args) raise NoMethodError, mid.to_s unless /^on__/ =~ mid.to_s add(args[0]) if args[0].is_a?(String) args[0] end define_event('comment', 'comment') define_event('embdoc_beg', 'comment') define_event('embdoc', 'comment') define_event('embdoc_end', 'comment') define_event('kw', 'reserved') define_event('tstring_beg', 'string') define_event('tstring_content', 'string') define_event('tstring_end', 'string') define_event('words_beg', 'string') define_event('qwords_beg', 'string') define_event('qwords_sep', 'string') define_event('regexp_beg', 'string') define_event('regexp_end', 'string') define_event('heredoc_content', 'string') def on__heredoc_beg(token) add(' ') add(token) add("\n") end def on__heredoc_end(token) add(token.chomp) end def on__ident(token) if @script[-1, 1] != '.' && (::Kernel.methods.include?(token) || ::Module.private_methods.include?(token)) add(token, 'keyword') else add(token) end end end
ってぜんぜん真面目にやってないじゃん!
(実際に使ってるコードとはたぶん微妙に違います)
_ えーと、on__heredoc_begで変なことしてますが、つまりtoken前後の空白文字類が失踪してる気がします。なんでだろ。
そしてon__heredoc_endには謎の改行文字が出現します。なんでだろ。
というわけなので、ちょっとprint(<<EOP)とか書いたとたんに破綻しますが気にしちゃ駄目だ。サンプルなんだから!
_ この日記の話題というより、Ripperを試行錯誤(ある意味思考錯誤)しながら使ってみよう話題だなこりゃ。
_ さて、青木さんからon__scanのがよさそうというお言葉をいただいたのだけど、method_missingを使ってる最大の理由はon__spがないからだよママン!
ま、それはHEADではもう直ったはずなので、method_missingは追放。
_ あ、method_missing使うのをやめてon__scanで「その他全てのtoken」を扱うようにすれば、素直にripper.soじゃなくてripper.rbをrequireしてもよくなるな。
_ 問題は、on__scanでは「その他全てのtoken」じゃなくて、ほんとに「全てのtoken」を拾ってしまうことか。
うーん、on__scanは他のon__*よりはおおよそ先に呼ばれるわけで、それがその後別のon__*で処理されるかどうかはon__scan時にはわからんじゃん。
そういえば、連続する同一の<span>を統合するために変なことしてるのも含めて、まとめて整理すると...
require 'cgi' require 'ripper' class ColorParser < ::Ripper def self.define_event(ev, action) eval <<-EOM def on__#{ev}(token) @tokens.pop @tokens.push([token, '#{action}']) end EOM end def parse @tokens = [] super script = '' preklass = nil @tokens.to_a.each do |token, klass| if preklass && klass != preklass script << '</span>' preklass = nil end if klass && !preklass script << %Q!<span class="#{klass}">! end script << CGI.escapeHTML(token) preklass = klass end script end private def on__scan(mid, token) @tokens.push(token) end define_event('comment', 'comment') define_event('embdoc_beg', 'comment') define_event('embdoc', 'comment') define_event('embdoc_end', 'comment') define_event('kw', 'reserved') define_event('tstring_beg', 'string') define_event('tstring_content', 'string') define_event('tstring_end', 'string') define_event('words_beg', 'string') define_event('qwords_beg', 'string') define_event('qwords_sep', 'string') define_event('regexp_beg', 'string') define_event('regexp_end', 'string') define_event('heredoc_content', 'string') def on__heredoc_beg(token) @tokens.pop @tokens.push(' ') @tokens.push(token) @tokens.push("\n") end def on__heredoc_end(token) @tokens.pop @tokens.push(token.chomp) end def on__ident(token) @tokens.pop if @tokens.empty? || (@tokens[-1].to_a[0][-1,1] != '.' && (::Kernel.methods.include?(token) || ::Module.private_methods.include?(token))) @tokens.push([token, 'keyword']) else @tokens.push(token) end end end
_ そういや、evalキライなのはかねてから公言してるけど、method_missingもけっこうキライだなあ。
ってどっちも使ってたのかよ前回は!(今回もevalは残ってます)
_ ところで、MoonWolfさんもおっしゃってますが、ヒアドキュメントもちゃんと扱えるのがRipperの強みだと思います。
だから、そこでトークンをロストしてる場合じゃないですよ青木さん!(とかいう
_ 名指しされていたので該当スレッドを斜め読みしてみましたが、別にWindowsと関係なくて、しかも単にバグってただけでもう解決した、のかなあ。そういうことにしておこう。
_ というわけで、ruby-talkは普段読んでませんのであしからず。
あれを読んでたら生活が成り立たないです、私の英語力では。
被捕捉アンテナ類
[\ay antenna (testing)]
[Ant]
[Antenna-Julia]
[LayserあんてなV2]
[nAntenna]
[nuance de Antenna]
[Rabbit's Antenna]
[Read List]
[Ruby hotlinks 五月雨版 (るるりん。)]
[してたま (私的アンテナ with たまてばこ)]
[ただのあんてな]
[ちゃらんぽらん]
[でこぽんリンク]
[なよろアンテナ]
[にっきトレーサー]
[偽善者あんてな - 2nd season -]
[湘南日記放送局(SDB)]
[はてなの各アンテナ]