Book Description
From the Publisher
About the Author
Simon Cozens is an Open Source programmer and author. He has released over a hundred Perl modules including Email::Simple, Mail::Audit, Maypole, Plucene, and B::Generate. He's the co-author of Beginning Perl (Wrox) and Extending and Embedding Perl (Manning) and was the managing editor of Perl.com from 2001 to 2004. A graduate in Japanese from Oxford University, he now lives in Wales and enjoys Japanese and Greek food, bizarre music and fine typography.
Excerpt. © Reprinted by permission. All rights reserved.
A recent thread on comp.lang.perl.moderated enumerated the Perl rites of passage the perfectly good wheels that every journeyman Perl programmer reinvents. These were found to be a templating system, a database abstraction layer, an HTML parser, a processor for command-line arguments, and a time/date handling module.
See if you recognize yourself in the following story: you need to produce a form letter of some description. Youve got a certain amount of fixed content, and a certainamount that changes. So you set up a template a little like this:
my $template = q{
Dear $name,
We have received your request for a quote for $product, and have
calculated that it can be delivered to you by $date at a cost of
approximately $cost.
Thank you for your interest,
Acme Integrated Foocorp.
};
Then you struggle with some disgusting regular expression along the lines of s/(\$\w+)/$1/eeg, and eventually you get something that more or less does the job.
As with all projects, the specifications change two days after it goes live, so you suddenly need to extend your simple template to handle looping over arrays, conditionals, and eventually executing Perl code in the middle of the template itself. Before you realize whats happened, youve created your own templating language.
Dont worry if thats you. Nearly everyones done it at least once. Thats why theres a wide selection of modules on CPAN for templating text and HTML output, ranging from being only slightly more complex than s/(\$\w+)/$1/eeg to complete independent templating languages.
Before we start looking at these modules, though, lets consider the built-in solutionthe humble Perl format.
Formats and Text::Autoformat
Formats have been in Perl since version 1.0. Theyre not used very much these days, but for a lot of what people want from text formatting, theyre precisely the right thing.
Perl formats allow you to draw up a picture of the data you want to output, and then paint the data into the format. For instance, in a recent application, I needed to display a set of IDs, dates, email addresses, and email subjects with one line per mail. If we assume that the line is fixed at 80 columns, we may need to truncate some of those fields and pad others to wider than their natural width. In pure Perl, there are basically three ways to get this sort of formatted output. Theres sprintf (or printf) and substr:
for (@mails) {
printf "%5i %10s %40s %21s\n",
$_->id,
substr($_->received,0,10),
substr($_->from_address,-40,40),
substr($_->subject,0,21);
}
Then theres pack, which everyone forgets about (and which doesnt give as much control over truncation):
for (@mails) {
print pack("A5 A10 A40 A21\n",
$_->id, $_->received, $_->from_address, $_->subject);
}
And then theres the format:
format STDOUT =
@id $_->received $_->from_address $_->subject
.
for (@mails) {
write;
}
Personally, I think this is much neater and more intuitive than the other two solutions and has the bonus that it takes the formatting away from the main loop, making the code less cluttered.*
* As it happens, I didnt actually use formats in my code, because I wanted to have a variable-width instead of a fixed-width display. But for cases where a fixed-width output is acceptable, this solution is perfect
Formats are associated with a particular filehandle; as you can see from the example, weve determined that this format should apply to anything we write on standard output. The picture language of formats is pretty simple: fields begin with @ or ^ and are followed by characters specifying left, center, and right justified respectively. After each line of fields comes a line of expressions that fill those fields, one expression for each field. If we like, we could change the format to multiple lines of fields and expressions:
format STDOUT =
Id : @id
Date : @<<
Subject : @<<<<<<<<<<<<<<<<<<<<<<