NAME
Text::Template - Expand template text with embedded Perl
SYNOPSIS
use Text::Template;
$template = new Text::Template ('type' => FILE, 'source' => 'f.tmpl');
# or
$template = new Text::Template ('type' => ARRAY,
'source' => [ ... ] );
# or
$template = new Text::Template ('type' => FILEHANDLE,
'source' => $fh );
$recipient = 'King';
$text = $template->fill_in();
print $text;
$T::recipient = 'Josh';
$text = $template->fill_in('package' => T);
print $text;
$text = $template->fill_in('broken' => \&callback);
use Text::Template fill_this_in;
$text = fill_this_in( <<EOM, 'package' => T);
Dear {$recipient},
Pay me at once.
Love,
G.V.
EOM
print Text::Template->Version;
OVERVIEW
This is a library for printing form letters! This is a library for playing Mad Libs!
A `template' is a piece of text that has little Perl programs embedded in it here and there. When you `fill in' a template, you evaluate the little programs and replace them with their values.
This is a good way to generate many kinds of output, such as error messages and HTML pages. Here is one way I use it: I am a freelance computer consultant; I write world-wide web applications. Usually I work with an HTML designer who designs the pages for me.
Often these pages change a lot over the life of the project: The client's legal department takes several tries to get the disclaimer just right; the client changes the background GIF a few times; the text moves around, and soforth. These are all changes that are easy to make. Anyone proficient with the editor can go and make them. But if the page is embedded inside a Perl program, I don't want the designer to change it because you never know what they might muck up. I'd like to put the page in an external file instead.
The trouble with that is that parts of the page really are generated by the program; it needs to fill in certani values in some places, maybe conditionally include some text somewhere else. The page can't just be a simple static file that the program reads in and prints out.
A template has blanks, and when you print one out, the blanks are filled in automatically, so this is no trouble. And because the blanks are small and easy to recognize, it's easy to tell the page designer to stay away from them.
Here's a sample template:
Dear {$title} {$lastname},
It has come to our attention that you are delinquent in your
{$last_paid_month} payment. Please remit ${$amount} immediately,
or your patellae may be needlessly endangered.
Love,
Mark "Vizopteryx" Dominus
Pretty simple, isn't it? Items in curly braces {
}
get filled in; everything else stays the same. Anyone can understand that. You can totally believe that the art director isn't going to screw this up while editing it.
You can put any perl code you want into the braces, so instead of {$amount}
, you might want to use {sprintf("%.2f", $amount)}
, to print the amount rounded off to the nearest cent.
This is good for generating form letters, HTML pages, error messages, and probably a lot of other things.
Detailed documentation follows:
Constructor: new
new Text::Template ( attribute => value, ... );
This creates a new template object. You specify the source of the template with a set of attribute-value pairs in the arguments.
At present, there are only two attributes. One is type
; the other is source
. type
can be FILEHANDLE
, FILE
, or ARRAY
. If type
is FILE
, then the source
is interpreted as the name of a file that contains the template to fill out. If type
is FILEHANDLE
, then the source
is interpreted as the name of a filehandle, which, when read, will deliver the template to fill out. A type
of ARRAY
means that the source
is a reference to an array of strings; the template is the concatentation of these strings.
Neither type
nor source
are optional yet.
Here are some examples of how to call new
:
$template = new Text::Template
('type' => 'ARRAY',
'source' => [ "Dear {\$recipient}\n",
"Up your {\$nose}.\n",
"Love, {\$me}.\n" ]);
$template = new Text::Template
('type' => 'FILE',
'source' => '/home/mjd/src/game/youlose.tmpl');
new
returns a template object on success, and undef
on failure. On an error, it puts an error message in the variable $Text::Template::ERROR
.
fill_in
Fills in a template. Returns the resulting text.
Like new
, fill_in
accepts a set of attribute-value pairs. At present, the only attributes are package
and broken
.
Here's an example: Suppose that $template
contains a template object that we created with this template:
Dear {$name},
You owe me ${sprintf("%.2f", $amount)}.
Pay or I will break your {$part}.
Love,
Uncle Dominus.
Here's how you might fill it in:
$name = 'Donald';
$amount = 141.61;
$part = 'hyoid bone';
$text = $template->fill_in();
Here's another example:
Your Royal Highness,
Enclosed please find a list of things I have gotten
for you since 1907:
{ $list = '';
foreach $item (@things) {
$list .= " o \u$item\n";
}
$list
}
Signed,
Lord High Chamberlain
We want to pass in an array which will be assigned to the array @things
. Here's how to do that:
@the_things = ('ivory', 'apes', 'peacocks', );
$template->fill_in();
This is not very safe. The reason this isn't as safe is that if you had any variables named $list
or $item
in scope in your program at the point you called fill_in
, their values would be clobbered by the act of filling out the template.
The next section will show how to make this safer.
package
-
The value of the
package
attribute names a package which contains the variables that should be used to fill in the template. If you omit thepackage
attribute,fill_in
uses the package that was active when it was called.Here's a safer version of the `Lord High Chamberlain' example from the previous section:
@VARS::the_things = ('ivory', 'apes', 'peacocks', ); $template->fill_in('package' => VARS);
This call to
fill_in
clobbers$VARS::list
and$VARS::item
instead of clobbering$list
and$item
. If your program didn't use anything in theVARS
package, you don't have to worry that filling out the template is altering on your variables. broken
-
If you specify a value for the
broken
attribute, it should be a reference to a function thatfill_in
can call if one of the little programs fails to evaluate.fill_in
will pass an associative array to thebroken
function. The associative array will have at least these two members:text => (The full text of the little program that failed) error => (The text of the error message (C<$@>) generated by eval)
If the
broken
function returns a text string,fill_in
will insert it into the template in place of the broken program, just as though the broken program had evaluated successfully and yielded that same string. If thebroken
function returnsundef
,fill_in
will stop filling in the template, and will immediately return undef itself.If you don't specify a
broken
function, you get a default one that inserts something like this:Warning This part of the template: 1/0 Returned the following errors: Illegal division by zero at (eval 7) line 2.
fill_this_in
Maybe it's not worth your trouble to put the template into a file; maybe it's a small file, and you want to leave it inline in the code. Maybe you don't want to have to worry about managing template objects. In that case, use fill_this_in
. You give it the entire template as a string argument, follow with variable substitutions just like in fill_in
, and it gives you back the filled-in text.
An example:
$Q::name = 'Donald';
$Q::amount = 141.61;
$Q::part = 'hyoid bone';
$text = fill_this_in Text::Template ( <<EOM, 'package' => Q);
Dear {\$name},
You owe me {sprintf('%.2f', \$amount)}.
Pay or I will break your {\$part}.
Love,
Grand Vizopteryx of Irkutsk.
EOM
Version Version Text::Template ();
Returns the current version of the Text::Template
package. The current version is 'Text::Template 0.1 beta $Revision: 1.4 $ $Date: 1996/01/25 19:31:12 $'
.
Template Format
Here's the deal with templates: Anything in braces is a little program, which is evaluated, and replaced with its perl value. A backslashed character has no special meaning, so to include a literal {
in your template, use \{
, and to include a literal \
, use \\
.
A little program starts at an open brace and ends at the matching close brace. This means that your little programs can include braces and you don't need to worry about it. See the example below for an example of braces inside a little program.
If an expression at the beginning of the template has side effects, the side effects carry over to the subsequent expressions. For example:
{$x = @things; ''} The Lord High Chamberlain has gotten {$x}
things for me this year.
{ $diff = $x - 17;
$more = 'more'
if ($diff == 0) {
$diff = 'no';
} elsif ($diff < 0) {
$more = 'fewer';
}
}
That is {$diff} {$more} than he gave me last year.
Notice that after we set $x in the first little program, its value carries over to the second little program, and that we can set $diff
and $more
on one place and use their values again later.
All variables are evaluated in the package you specify as an argument to fill_in
. This means that if your templates don't do anything egregiously stupid, you don't have to worry that evaluation of the little programs will creep out into the rest of your program and wreck something. On the other hand, there's really no way to protect against a template that says
{ $Important::Secret::Security::Enable = 0;
# Disable security checks in this program
}
or even
{ system("rm -rf /") }
so don't go filling in templates unless you're sure you know what's in them. This package may eventually use Perl's Safe
extension to fill in templates in a safe compartment.
AUTHOR
Mark-Jason Dominus, Plover Systems
mjd@pobox.com
SUPPORT?
This software is version 0.1 beta. It probably has bugs. It is inadequately tested. Suggestions and bug reports are always welcome.
BUGS AND CAVEATS
This package is in beta testing and should not be used in critical applications.
This package should fill in templates in a Safe
compartment.
The callback function that fill_in
calls when a template contains an error should be eble to return an error message to the rest of the program.
my
variables in fill_in
are still susceptible to being clobbered by template evaluation. Perhaps it will be safer to make them local
variables.
Maybe there should be a utility method for emptying out a package?
Maybe there should be a utility function for doing #include
. It would be easy. (John Cavanaugh, sdd@hp.com
)
Maybe there should be a control item for doing #if. Perl's `if' is sufficient, but a little cumbersome to handle the quoting.
2 POD Errors
The following errors were encountered while parsing the POD:
- Around line 226:
'=item' outside of any '=over'
- Around line 334:
You forgot a '=back' before '=head2'