TT (Template-Toolkit) で値にフィルタを掛ける時に
[% value | replace('x','y') | uri | html %]
みたいに書きますが、Text::MicroTemplate だと仮に replace(), uri() という関数を用意しても
<?= uri( replace($value,'x','y') ) ?>
こんな感じ。なんか読みにくい気がする。(まあ PHP だってそうだといえばそうなんだけど)
<?= $value | replace('x','y') | uri ?>
こんな風に書けたら素敵ですよね。ということでこんなのを書いてみた。
package Filter; use strict; require Exporter; our @ISA = qw/ Exporter /; our @EXPORT_OK = qw/ html uri replace html_line_break /; our %EXPORT_TAGS = ( all => \@EXPORT_OK ); use overload '|' => sub { my ($self, $arg) = @_; $self->($arg); }; sub html() { bless sub { local $_ = $_[0]; s{&}{&}g; s{<}{<}g; s{>}{>}g; s{"}{"}g; s{'}{'}g; $_; }, __PACKAGE__; } sub uri() { use URI::Escape; bless sub { uri_escape_utf8($_[0]); }, __PACKAGE__; } sub replace($$) { my ($regexp, $replace) = @_; bless sub { local $_ = $_[0]; s{$regexp}{$replace}g; $_; }, __PACKAGE__; } sub html_line_break() { bless sub { local $_ = $_[0]; s{\r*\n}{<br/>}g; $_; }, __PACKAGE__; } 1;
要は、
というやり方です。
これで以下のようなコードが動きます。
use Filter qw/:all/; print "<a>" | html; # <a> print "a&b" | uri; # a%26b print "foo" | replace('f','b'); # boo print "\n" | html_line_break | uri; # %3Cbr%2F%3E
複数つなげて連鎖もできる。すばらしい。
ただ、同じようなものが CPAN にあるような気がしてならないんだけど、見つけられませんでした。ご存知の方は教えてください。