とりあえず trunk の HEAD を落としてくる。UsingPragger - PRagger - Trac に従って Pragger の Trac の Feed を取得する。追加モジュールを何もインストールしなくても使えるのがいいよね。
……。思ったより重いのは Q 上の Debian だからか? 結構 CPU パワーを食うなぁ。
ちょっと中を覗いてみる
pragger.rb の最後の行を以下のようにして
if ( __FILE__ == $0 )
eval_pragger( YAML.load( File.read(configFile).
toutf8.gsub( /base64::([\w+\/]+=*)/ ) {
Base64.decode64( $1 )
} ),
[] )
end
irb 上で
require 'pragger'
する。$plugins の中身はこんな感じ。
> pp $plugins.keys.sort
["Feed::custom_feed",
"Feed::lirs",
"Filter::Translations::yahoo",
"Filter::apply_text_html",
"Filter::average",
"Filter::deduped",
"Filter::find_num",
"Filter::find_regex",
"Filter::fresh",
"Filter::get_html",
"Filter::grep",
"Filter::invert",
"Filter::sort",
"Filter::subs",
"Filter::to_integer",
"Publish::lingr",
"RSS::load",
"RSS::save",
"Yaml::load",
"Yaml::save",
"argv",
"concat",
"const_list",
"first",
"head",
"load_path",
"plugin_from_uri",
"pluginbase",
"print",
"reverse",
"send_msg",
"stdin",
"stdout"]
=> nil
ディレクトリ構造に応じて自動的に名前を付けられた plugin 群が並んでいる。Mechanize とか入れてないのでそういうものに依存している plugin は出てきていない。はず。
もうちょっと読む
先ほどの $plugins の値の方には何が入っているのかと言うと Plugin オブジェクトが入っていて、それぞれ @source には File.read() した中身が入っている。で、class Plugin を読むと全部 instance_eval もしている。この @source 無駄じゃね?とか思うと実は -u で Usage を表示する際にこの中の行頭の ## で始まる行をそのまま利用しているので必要らしい。うーん。うーーん。うーーーーーーん。すげぇ富豪だ。要するに全コードを文字列で保持しつつ instance_eval しまくりだよ。オレには真似できない。
とまぁ変わった作りなので、plugin をどんな名前にしても通常の Ruby の名前空間と衝突することはない。(呼び出しは常に eval_pragger() を使う。)そこはいいな。まぁグローバルに
- $plugins
- Plugin
- opt
- eval_pragger()
は思いっきり消費してんだけど。
既存のツールと相性悪いな
plugin は通常の Ruby のオブジェクトとは異なる構造をしているので、上のように pragger を irb で実行して中身を確認したりとか、補完を使って使い方の当たりをつけようとか思ってもあんまりうまくいかない。まぁ基本的にはファイル名と同じメソッドを呼び出すだけ、そいつには Hash と Array が渡ってくるだけ、なんだけれども。テストどうすんだ、これ。完全に閉じている plugin ならグローバルなメソッドにそのまま Hash と Array を投げればいいだけだけど、他の plugin を利用するタイプのものをテストするのはしんどそうだ。
とりあえず起動が重いのはちょっとなんとかなんないかなぁ。この構造じゃ起動重くて当然なんだよな。せめて YAML のパースを先にやって必要な plugin だけ読むとかすればまだマシだろうけど、この pragger.rb、あまりにスキがない。
あと起動の重さを気にしなくていいように daemon 動作させるって手もあるかと思ったけど、pragger.rb はそれも考えてなさげだ。
うーむ。どう料理したらいいかなぁ。まーまずは使ってみんとな。