Text::Templateを使ってみた
Text::Templateというのを使ってみたのでメモ。
これの特徴は、「テンプレートの記述にPerlをそのまま書ける」ということにあるらしい。
- 独自のテンプレート言語を覚えなくてよい
- 記述力が高い
というのがメリット。そのかわり、デメリットとしては
- 何でも書けるからテンプレートに書きすぎてしまう可能性がある
というのがあるかと思われる。使い方次第だと思うけど。
使い方
基本的な使い方は以下のような感じ。
use strict; use warnings; use utf8; use Encode; use Text::Template; use IO::File; # 日本語を扱うときなどは自分でファイルを開く必要があるっぽい my $fh_in = new IO::File("template.txt", "r") or die "$!"; $fh_in->binmode(":utf8"); my $template = Text::Template->new(TYPE => 'FILEHANDLE', SOURCE => $fh_in) or die "$Text::Template::ERROR"; # 入力はここでcloseして問題ない $fh_in->close; # テンプレートで展開される変数 my $name = "名無し"; # テンプレート展開 my $result = $template->fill_in(HASH => {name => $name}); # 出力 if (defined $result) { print encode("utf8", $result); } else { die "couldn't fill in template : $Text::Template::ERROR"; }
fill_inという関数に与えるnameでテンプレートで展開する用の変数を渡す。テンプレートのファイルはtemplate.txtとした。例えば内容は以下のようになっているとする。
ハロー {$name} さん!
{}で囲まれている部分にPerlプログラムを記述できる(ただしデリミタの変更は可能らしい)。この例の場合は、$nameが展開されて以下のような出力が得られる。
ハロー 名無し さん!
一応だけど、ここでそれぞれのファイルの文字コードはutf8。
関数を使う
テンプレートから関数を使うことも出来る。最初の例のfill_in関数の引数のHASHで関数を渡せばよい。
# 関数を渡す my $result = $template->fill_in(HASH => {name => $name, hello => \&hello}); sub hello { my $name = shift; return "ハロー $name さん。"; }
テンプレートファイル(template.txt)には以下のように書く。
{hello($name)}
クラスを使う
テンプレートにクラスのオブジェクトを渡すことも出来る。普通に変数を渡すのとは違い、参照渡しをするのがポイント。
# サンプルのクラス package Sample; use strict; use warnings; use utf8; sub new { my ($class) = @_; my $self = { NAME => "" }; bless $self, $class; return $self; } sub set_name { my ($self, $name) = @_; $self->{NAME} = $name; } sub hello { my $self = shift; return "ハロー $self->{NAME} さん。"; } package main; use strict; use warnings; use utf8; use Encode; use Text::Template; use IO::File; # 日本語を扱うときなどは自分でファイルを開く必要があるっぽい my $fh_in = new IO::File("template.txt", "r") or die "$!"; $fh_in->binmode(":utf8"); my $template = Text::Template->new(TYPE => 'FILEHANDLE', SOURCE => $fh_in) or die "$Text::Template::ERROR"; # 入力はここでcloseして問題ない $fh_in->close; # テンプレートで展開される変数 my $name = "名無し"; my $sample = new Sample; # テンプレート展開。オブジェクトを渡す my $result = $template->fill_in(HASH => {name => $name, sample => \$sample}); # 出力 if (defined $result) { print encode("utf8", $result); } else { die "couldn't fill in template : $Text::Template::ERROR"; }
テンプレートファイルには以下のように書く。
{$sample->set_name($name); $sample->hello}
クラスを使う2
fill_inするところで、クラスが使えるようになっていれば、テンプレートの中でクラスをnew出来る。つまり、テンプレートファイルに以下のように書けるということ。
{$obj = new Sample; $obj->set_name($name); $obj->hello}
どうもここまでくると、テンプレートでやり過ぎてしまっているような感は拭えないが、使いどころはあるかもしれない。
だいたいこんな感じ。あと以下のようなところが分かってないが気になっている。気が向いたら調べる。
- テンプレート側とプログラム側の名前空間の扱い方
- 後ろの改行を消すやり方はあるか?(M4のdnl的なもの)