Awesome Template Engine / Framework ぽいの
今日の日記はネタなのでマジレス禁止 (;-P
Awesome Template Engine とか Awesome Framework*1 とか読むと PHP ってのはテンプレートエンジンを内包してるのが強みだなぁと思うわけです。Code Igniter のドキュメントにもそんな感じのことが書いてあったような。
ERB なんかも PHP ぽい構文で書けますよね。コーダーのためのプロトタイピング環境としてうらやましい。
- それ HTML::Mason
- それなんて eperl ?
という声も聞こえてきますが,遊びで書いてみました。
package ATE; use strict; use v5.8; use Carp; my %cache; our $stash = {}; sub include { my $file = shift; $cache{$file} = _compile_file($file) if ! exists $cache{$file}; return &{ $cache{$file} }(@_); } sub fetch { my $buffer = ''; open my $handle, '>', \$buffer or die $!; { local *STDOUT = $handle; include(@_); } close $handle; return $buffer; } sub escape_html { local $_ = shift; s'&'&'go; s'"'"'go; s'<'<'go; s'>'>'go; return $_; } sub _compile_file { my ($file) = @_; open my $handle, '<', $file or croak "$!: '$file'"; my $src = _compile_text( do { local $/; <$handle> } ); close $handle; my $code = eval "sub { $src }"; die if $@; return $code; } sub _compile_text { my ($text) = @_; my @tokens = split(m/ <\? ( .*? ) \?> /xmso, $text); my $i = 0; for (@tokens) { if ($i ++ % 2 == 0) { # Literal s'^\n+''o; # trim heading \n s'~'\~'go; # escape quote chars $_ = "print q~$_~;\n" if $_; } else { # Code if (s'^=''o) { # <?= CODE ?> Syntax $_ = (s'^raw\s+''o) ? "print do { $_ };\n" : "print escape_html(do { $_ });\n" ; } else { # <? CODE ?> Syntax s'^perl\s+''io; # <?perl CODE ?> Syntax # AS-IS } } } return join('', @tokens); } 1;
ぜんぜん短くねぇ〜&スマートじゃねぇ……
こいつで
% perl -MATE -e "print ATE::fetch('index.html')"
と起動することにすると,あとは index.html をいじるだけでロジックとビューをどちらも触ることができます。分業ハンタイ!
たとえば,
<?perl # index.html use DBIx::Simple; use DBIx::Simple::OO; my $db = DBIx::Simple->connect('dbi:SQLite:sample.db'); my @authors = $db->select( 'authors', '*', { id => { '>', 2 } }, [ 'id DESC' ], )->objects; ?> <html> <? include('header.html', 'hello'); ?> <body> <table> <?perl foreach my $author (@authors) { ?> <tr> <td><?= $author->id ?></td> <td><?= $author->name ?></td> </tr> <?perl } ?> </table> </body> </html>
みたく書けます。include されてる header.html は,
<?perl my $title = shift; ?> <head> <title><?= $title ?></title> </head>
こんな感じで,引数もとれます(グローバル変数 $stash を使ってもいいです)。
あとは,
- セキュリティ甘甘
- utf8 フラグ考慮してないー
なところを直して
- DETACH 例外イベント送出&トラップによる forward() の実装
- CGI.pm によるクエリの取得
- クエリや PATH_INFO ベースのルーティング
- CGI::Session あたりにセッションをおまかせ
を実装すれば,ようやく Awesome Framework においつけるかな……