CPANに Toolkit っていう粋なモジュールがあります。これは、emacsとかvimのカスタイズ性が持つ楽しさに近いラブリーなモジュールです。どういうモジュールなのか、順に説明してみます。
まず前提として、なんで Perl を使うの? というと、そこには中央ライブラリCPANがあるからさ、というのが大きいと思います。
ようするに、何やろうと思ってもたいていはなんかを use すればすんじゃうわけです。
ところが慣れてくると、useがずらーっと並んでしまうという弊害が。 例えばまあ最初に
use strict;
use warnings;
とかで始めるのは基本として、DBに問い合わせ処理をしつつ、ファイル変換をし、メールで最後通知を送りたいよみたいな場合、
use DBIx::Simple;
use File::Slurp;
use Template;
use MIME::Lite::TT::Japanese;
use List::MoreUtils;
とかみたいにするとほとんどスクリプト部分は十数行で済んでしまったり。楽
あとオプションをコマンドラインや設定ファイルで受けたり、デバッグを容易にしたいな、ということであれば、以下みたいなのを入れたりすることもあるでしょうね。
use Fatal qw(open close);
use Smart::Comments;
use Carp;
use IO::Prompt;
use App::Options (
values => \%ARGV,
option => {
debug => 'type=boolean; default=0',
date => 'type=date; default=1979-01-04; env=DATE; required=1;'
}
);
とすると、スクリプトの最初に use がならんでしまって、見た目はきれいかしれないけど、なんか重い感じでやなわけです。Perl Mongers としてこれで良いのか?と。
そんな DRY なあなたのために、 Toolkit の登場です。使い方は簡単で、上記の全 use 文を一つのファイルにして、適当な名前(Modules.pmとか)を付け、そいつを 適当なフォルダ/lib/Toolkit/Macros/DEFAULT/Modules.pm というような配置になるようにディレクトリを作って置きます。
そうしたら、あとはスクリプトでこう書くだけ。
use lib '上で決めた適当なフォルダ/lib';
use Toolkit;
このシンプルさ、キてる!でしょう。
からくりとしては、Toolkitはサーチパス @INC 内の Toolkit/Macros/ALWAYS/*、Toolkit/Macros/DEFAULT/* という配置にあるファイル全てを読み込み、use Toolkit; の場所に“挿入”されたものとしてくれます。
Catalyst は別の方法で use を並べないですむ工夫をしてるけど、処理系のスクリプトの場合、Toolkit っていう選択肢がスマートじゃないかな。
ちなみに、Macros以下の ALWAYS と DEFAULT は特殊なフォルダ。同じ階層に、別のフォルダを置くことができます。これは引数付きで Toolkit を use するときに関係してきて、
use Toolkit qw( MyFavorite ); と引数付きで use すると、読み込み対象は Toolkit/Macros/ALWAYS/* と、Toolkit/Macros/*MyFavorite*/* という配置にあるファイルとなるのです。
ALWAYS以下は常に読み込まれるファイルで、DEFAULTは引数を指定しなかった時、それ以外のディレクトリは指定した時用というわけです。
とすると、
Toolkit/Macros/ALWAYS/Modules.pm … use strict; と use warnings;Toolkit/Macros/DEFAULT/Modules.pm … 汎用的に使うお気に入りToolkit/Macros/File/Modules.pm … ファイル変換時用Toolkit/Macros/Mail/Modules.pm … メール時用Toolkit/Macros/DB/Modules.pm … DB接続処理時用みたいに仕込んでおいて、
use lib 'lib';
use Toolkit qw/File Mail DB/;
とやってみたりとか、いろいろ夢がひろがるわけです。
Toolkitの基本機能は「挿入」ですので、別にuse文しか書けないわけではなく、そのモジュールと連動して必ず使うぞっていうサブルーチンを書いておいたり、そのモジュールのインスタンスを作成しておいたり、アイディア次第。オレオレToolkitを作れます。
その自由に決めれるディレクトリを、Toolkit/Macros/*-ry*/Modules.pm みたいに、ハイフン付きで指定しておくと、以下みたく記号を使わなくても指定できて、きれいに見えるのでけっこう気にいってます。
use lib 'mylib';
use Toolkit -ry;
あと極めつけに、サブルーチンオートロード機能というのがついてます。(てか、これはなくてもいいんだけど)
これは、例えば以下のようなスクリプトがあったとして、
use Toolkit;
hello();
これ、まあ普通は hello サブルーチンが宣言されていないのでエラーになります。
ただし Toolkitは、そのタイミングで @INCのどこか/Toolkit/Runtime/*hello* というファイルを探し、もしあった場合それを読み込んで挿入し、そのあとで hello() を実行してくれます。
だから @INCのどこか/Toolkit/Runtime/hello を以下のようなファイルにしておけば、エラーは起きずに、Hello World が表示されます。
sub hello {
print "Hello World.\n";
}
これも上のモジュールを読み込む機能を補佐するものとして、アイディアを広げてくれます。
こんな、小粋な Filter::Simple ネタをしかも堂々と第一レベルのモジュール名で繰り出してくるのはもちろん、Damian Conway 氏。
一点、 Toolkit/Macros/ 以下のディレクトリをサブバージョンで管理している場合、Subversionが作る .svn フォルダの中にある XMLファイルとかも ToolkitがPerlスクリプトに挿入されてしまって、以下みたいなエラーが出ます。
syntax error at lib/Toolkit/Macros/ALWAYS/.svn/entries line 1, near "?xml version="1.0" encoding="utf-8"?>" Unterminated <> operator at lib/Toolkit/Macros/ALWAYS/.svn/entries line 2.
そこで、以下のようなパッチを当てるのはどうかと、rt.cpan.org でリクエストを投げています。
@@ -104,7 +104,9 @@
next ROOT if ! -e $root;
find(
sub {
- return if -d; push @files, $File::Find::name
+ return if -d;
+ return if $File::Find::name =~ m{/\.};
+ push @files, $File::Find::name
},
$root,
);
これにより、.svnも含めた、すべてのドットで始まるフォルダとディレクトリを挿入対象から除外します。ドットで始まるファイル・ディレクトリは特殊なものとして使われるから、除外することを多くの人が望むと思うよ、どう思うか?って投げています。Damian が賛同すれば、きっと将来更新されることでしょう。
Toolkit ドキュメント
http://search.cpan.org/perldoc?Toolkit
次期バージョンで対応してくれるとのこと。他にも若干便利度が増すのでお楽しみに。ダミアンさん、YAPC::Asia向けに?日本語おぼえているのか、ローマ字で日本語使ってくるのがおもしろいw