Praggerプラグインの作成方法について説明します.
* 単純なプラグイン
プラグインはrubyプログラムです.{{{プラグイン名.rb}}}というファイル名でプラグインを記述し,適当なディレクトリに保存します.それでは,入力に含まれる{{{Plagger}}}というテキストを{{{Pragger}}}に置換するプラグインを作成してみましょう.
次のようなプログラムを記述して,{{{private_plugin/sample_plugin.rb}}}として保存します.
<@code filename="config.yaml">
def sample_plugin(config, data)
data.collect {|x| x.to_s.gsub(/Plagger/, 'Pragger') }
end
</@code>
プラグイン名と同じ名前のメソッドが,プラグインを実行した場合に呼び出されます.それ以外には,いかなる制約もありません.クラスを定義してもかまいませんし自由にメソッドを定義してもかまいません.
このプラグインを使ってみましょう.{{{config.yaml}}}に次のように書きます.
<@code filename="config.yaml">
- module: stdin
- module: sample_plugin
- module: stdout
</@code>
{{{stdin}}}プラグインによって標準入力を読みとり,{{{sample_plugin}}}プラグインによってPlaggerをPraggerに置換したあとで,{{{stdout}}}プラグインによって標準出力に出力します.さて実行してみましょう.
<@code>
$ ./pragger -p private_plugin
</@code>
例えば「それPlaggerでできるよ」と入力して{{{Ctrl-D}}}(Windowsだと{{{Ctrl-Z + Enter}}})を入力すると,「それPraggerでできるよ」と表示されるはずです.
簡単ですね!
* もうちょっと詳しく
{{{sample_plugin.rb}}}に定義した{{{sample_plugin}}}メソッドは,引数を二つとります.{{{config}}}と{{{data}}}です.
{{{config}}}には{{{config.yaml}}}に設定した{{{config:}}}以下をRubyプログラムとして解釈したものが渡されます.例えば{{{config.yaml}}}に次のように書いてみます.
<@code filename="config.yaml">
- module: sample_plugin
config:
abc: abcdefg
xyz:
- 1
- 2
- 3
</@code>
この場合は,{{{config}}}は次のようなRubyのハッシュになります.
<@code>
{ "abc" => "abcdefg"; "xyz" => [1, 2, 3] }
</@code>
プラグインに設定項目が必要な場合は,ここに書いてプラグインに渡します.ちなみに{{{config:}}}が{{{config.yaml}}}に記述されていなかった場合は(最初の例とか),{{{config}}}は{{{nil}}}になります.
{{{data}}}は「プラグインが処理するデータ」です.またメソッドの返り値が「プラグインが処理した後のデータ」になります.この{{{data}}}は「Arrayクラスのインスタンス」です.Plaggerではこのプラグインが処理するデータはRSS Feedと決まっているようですが,Praggerでは配列の要素がなにかということはわかりません(プラグインによってどのようにも変化します).
* プラグインのメタ情報について
どういった設定項目が必要か,だれが作ったプラグインか,といった情報を表現する統一的な方法は,現時点では定義されていません.
一応,プラグインの説明として,{{{##}}}で始まるコメントを書いておくと,{{{./pragger -u plugin_name}}}としたときに表示されるようになっています.
これは今後変更される可能性があります(というかsoutaroとしては変更したいと思っています).
* 注意
** {{{require}}}をどこに書くべきか
プラグインが依存するライブラリは{{{require}}}によってロードします.{{{require}}}は,メソッドの外側,つまり普通にRubyプログラムを書く場合と同じ場所に書いてかまいません(最近変更になりました).{{{require}}}に失敗した場合は,そのプラグインはロードされません.
今後は推奨される{{{require}}}のスタイルとしては「一番外側に書く」となります.その方が,依存ライブラリが無くて実行できないプラグインをロードすることがなくなりますからね.({{{./pragger -l}}}として,利用できるプラグインのリストを確認することができます)
**プラグインはstate lessに
プラグインが状態を持つ場合に,意図と異なる動作をする可能性があります.プラグインは{{{Plugin}}}クラスのオブジェクトとして,それぞれのプラグインについて一つずつインスタンスが作成されます(プラグインのメソッドは,そのオブジェクトの特異メソッドとして定義されます).
** 他のプラグインを使う場合
あるプラグインから他のプラグインを使う場合には{{{eval_pragger}}}メソッドを使います.
つぎのプラグインは,{{{save_rss}}}プラグインに入力をそのまま引き渡すものです.
<@code filename="save_rss2.rb">
def save_rss2(config, data)
eval_pragger([{"module" => "save_rss", "config" => config}], data)
end
</@code>
{{{eval_pragger}}}メソッドは,入力としてハッシュの配列と,配列を受け取ります.
** プラグイン名
プラグイン名は,プラグインの存在するパスのパス区切りを{{{::}}}に置き換えたものです.例えば,{{{private_plugin/hoge.rb}}}というプラグインの名前は{{{./pragger -p private_plugin}}}とした場合には{{{hoge}}}になります.あるいは{{{private_plugin/Publish/your_plugin.rb}}}というプラグインの名前は{{{./pragger -p private_plugin}}}とした場合には{{{Publish::your_plugin}}}となります.
もし他の人が作ったプラグインと名前が衝突してしまった場合は,プラグインを保存するディレクトリを深く掘ってみてください.{{{bar}}}というプラグインが二つあった場合は,片方を{{{Your_plugin/bar.rb}}}として保存し,もう片方を{{{My_plugin/bar.rb}}}として保存することによって,{{{Your_plugin::bar}}}と{{{My_plugin::bar}}}として区別することができます.
Praggerは,同名のプラグインが二つあった場合には,あとからロードしたプラグインのほうを優先します.プラグインをロードする順番は
<@list order="1">
標準のプラグイン
{{{-p}}}オプションで指定されたディレクトリに含まれるプラグイン
{{{-p}}}オプションが複数あった場合には,前のほうに指定されたディレクトリのプラグインから順
</@list>
です.
--soutaro
* プラグインの投稿
プラグインをBlog等で公開する時に、同時に「本家統合希望」と書いていただければ、PraggerのSubversionに取り込まさせていただきます。
取り込まさせて頂いたプラグインは、Praggerと同じライセンスで配布させて頂きます。
また、コミッターになりたい人は、[[チャットルーム>http://lingr.com/room/pragger]]などで、話しかけていただければと思います。