Add built local::lib
[catagits/Gitalist.git] / local-lib5 / man / man3 / Template::Tutorial::Datafile.3pm
1 .\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3
2 .\"
3 .\" Standard preamble:
4 .\" ========================================================================
5 .de Sh \" Subsection heading
6 .br
7 .if t .Sp
8 .ne 5
9 .PP
10 \fB\\$1\fR
11 .PP
12 ..
13 .de Sp \" Vertical space (when we can't use .PP)
14 .if t .sp .5v
15 .if n .sp
16 ..
17 .de Vb \" Begin verbatim text
18 .ft CW
19 .nf
20 .ne \\$1
21 ..
22 .de Ve \" End verbatim text
23 .ft R
24 .fi
25 ..
26 .\" Set up some character translations and predefined strings.  \*(-- will
27 .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
28 .\" double quote, and \*(R" will give a right double quote.  | will give a
29 .\" real vertical bar.  \*(C+ will give a nicer C++.  Capital omega is used to
30 .\" do unbreakable dashes and therefore won't be available.  \*(C` and \*(C'
31 .\" expand to `' in nroff, nothing in troff, for use with C<>.
32 .tr \(*W-|\(bv\*(Tr
33 .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
34 .ie n \{\
35 .    ds -- \(*W-
36 .    ds PI pi
37 .    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
38 .    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
39 .    ds L" ""
40 .    ds R" ""
41 .    ds C` ""
42 .    ds C' ""
43 'br\}
44 .el\{\
45 .    ds -- \|\(em\|
46 .    ds PI \(*p
47 .    ds L" ``
48 .    ds R" ''
49 'br\}
50 .\"
51 .\" If the F register is turned on, we'll generate index entries on stderr for
52 .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
53 .\" entries marked with X<> in POD.  Of course, you'll have to process the
54 .\" output yourself in some meaningful fashion.
55 .if \nF \{\
56 .    de IX
57 .    tm Index:\\$1\t\\n%\t"\\$2"
58 ..
59 .    nr % 0
60 .    rr F
61 .\}
62 .\"
63 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
64 .\" way too many mistakes in technical documents.
65 .hy 0
66 .if n .na
67 .\"
68 .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
69 .\" Fear.  Run.  Save yourself.  No user-serviceable parts.
70 .    \" fudge factors for nroff and troff
71 .if n \{\
72 .    ds #H 0
73 .    ds #V .8m
74 .    ds #F .3m
75 .    ds #[ \f1
76 .    ds #] \fP
77 .\}
78 .if t \{\
79 .    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
80 .    ds #V .6m
81 .    ds #F 0
82 .    ds #[ \&
83 .    ds #] \&
84 .\}
85 .    \" simple accents for nroff and troff
86 .if n \{\
87 .    ds ' \&
88 .    ds ` \&
89 .    ds ^ \&
90 .    ds , \&
91 .    ds ~ ~
92 .    ds /
93 .\}
94 .if t \{\
95 .    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
96 .    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
97 .    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
98 .    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
99 .    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
100 .    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
101 .\}
102 .    \" troff and (daisy-wheel) nroff accents
103 .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
104 .ds 8 \h'\*(#H'\(*b\h'-\*(#H'
105 .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
106 .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
107 .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
108 .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
109 .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
110 .ds ae a\h'-(\w'a'u*4/10)'e
111 .ds Ae A\h'-(\w'A'u*4/10)'E
112 .    \" corrections for vroff
113 .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
114 .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
115 .    \" for low resolution devices (crt and lpr)
116 .if \n(.H>23 .if \n(.V>19 \
117 \{\
118 .    ds : e
119 .    ds 8 ss
120 .    ds o a
121 .    ds d- d\h'-1'\(ga
122 .    ds D- D\h'-1'\(hy
123 .    ds th \o'bp'
124 .    ds Th \o'LP'
125 .    ds ae ae
126 .    ds Ae AE
127 .\}
128 .rm #[ #] #H #V #F C
129 .\" ========================================================================
130 .\"
131 .IX Title "Template::Tutorial::Datafile 3"
132 .TH Template::Tutorial::Datafile 3 "2008-11-13" "perl v5.8.7" "User Contributed Perl Documentation"
133 .SH "NAME"
134 Template::Tutorial::Datafile \- Creating Data Output Files Using the Template Toolkit
135 .SH "DESCRIPTION"
136 .IX Header "DESCRIPTION"
137 .SH "Introducing the Template Toolkit"
138 .IX Header "Introducing the Template Toolkit"
139 There are a number of Perl modules that are universally 
140 recognised as The Right Thing To Use for certain tasks. If you 
141 accessed a database without using \s-1DBI\s0, pulled data from the \s-1WWW\s0 
142 without using one of the \s-1LWP\s0 modules or parsed \s-1XML\s0 without using 
143 XML::Parser or one of its subclasses then you'd run the risk of 
144 being shunned by polite Perl society.
145 .PP
146 I believe that the year 2000 saw the emergence of another 'must 
147 have' Perl module \- the Template Toolkit. I don't think I'm 
148 alone in this belief as the Template Toolkit won the 'Best New 
149 Module' award at the Perl Conference last summer. Version 2.0 of 
150 the Template Toolkit (known as \s-1TT2\s0 to its friends) was recently 
151 released to the \s-1CPAN\s0.
152 .PP
153 \&\s-1TT2\s0 was designed and written by Andy Wardley <abw@wardley.org>. 
154 It was born out of Andy's previous templating module, 
155 Text::Metatext, in best Fred Brooks 'plan to throw one away' 
156 manner; and aims to be the most useful (or, at least, the most 
157 \&\fIused\fR) Perl templating system.
158 .PP
159 \&\s-1TT2\s0 provides a way to take a file of fixed boilerplate text 
160 (the template) and embed variable data within it. One obvious 
161 use of this is in the creation of dynamic web pages and this is 
162 where a lot of the attention that \s-1TT2\s0 has received has been 
163 focussed. In this article, I hope to demonstrate that \s-1TT2\s0 is 
164 just as useful in non-web applications.
165 .SH "Using the Template Toolkit"
166 .IX Header "Using the Template Toolkit"
167 Let's look at how we'd use \s-1TT2\s0 to process a simple data file. 
168 \&\s-1TT2\s0 is an object oriented Perl module. Having downloaded it from 
169 \&\s-1CPAN\s0 and installed it in the usual manner, using it in your 
170 program is as easy as putting the lines
171 .PP
172 .Vb 2
173 \&    use Template;
174 \&    my $tt = Template\->new;
175 .Ve
176 .PP
177 in your code. The constructor function, \f(CW\*(C`new\*(C'\fR, takes 
178 a number of optional parameters which are documented in the 
179 copious manual pages that come with the module, but for the 
180 purposes of this article we'll keep things as simple as 
181 possible.
182 .PP
183 To process the template, you would call the \f(CW\*(C`process\*(C'\fR method 
184 like this
185 .PP
186 .Vb 2
187 \&    $tt\->process('my_template', \e%data)
188 \&        || die $tt\->error;
189 .Ve
190 .PP
191 We pass two parameters to \f(CW\*(C`process\*(C'\fR, the first is the name of 
192 the file containing the template to process (in this case, 
193 my_template) and the second is a reference to a hash which 
194 contains the data items that you want to use in the template. If 
195 processing the template gives  any kind of error, the program 
196 will die with a (hopefully) useful error message.
197 .PP
198 So what kinds of things can go in \f(CW%data\fR? The answer is just 
199 about anything. Here's an example showing data about English 
200 Premier League football teams.
201 .PP
202 .Vb 10
203 \&    my @teams = ({ name   => 'Man Utd',
204 \&                   played => 16,
205 \&                   won    => 12,
206 \&                   drawn  => 3,
207 \&                   lost   => 1 },
208 \&                 { name   => 'Bradford',
209 \&                   played => 16,
210 \&                   won    => 2,
211 \&                   drawn  => 5,
212 \&                   lost   => 9 });
213 .Ve
214 .PP
215 .Vb 3
216 \&    my %data = ( name   => 'English Premier League',
217 \&                 season => '2000/01',
218 \&                 teams  => \e@teams );
219 .Ve
220 .PP
221 This creates three data items which can be accessed within the 
222 template, called \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`season\*(C'\fR and \f(CW\*(C`teams\*(C'\fR. Notice that 
223 \&\f(CW\*(C`teams\*(C'\fR is a complex data structure.
224 .PP
225 Here is a template that we might use to process this data.
226 .PP
227 .Vb 1
228 \&    League Standings
229 .Ve
230 .PP
231 .Vb 2
232 \&    League Name: [% name %]
233 \&    Season     : [% season %]
234 .Ve
235 .PP
236 .Vb 5
237 \&    Teams:
238 \&    [% FOREACH team = teams \-%]
239 \&    [% team.name %] [% team.played \-%] 
240 \&     [% team.won %] [% team.drawn %] [% team.lost %]
241 \&    [% END %]
242 .Ve
243 .PP
244 Running this template with this data gives us the following 
245 output
246 .PP
247 .Vb 1
248 \&                League Standings
249 .Ve
250 .PP
251 .Vb 2
252 \&    League Name: English Premier League
253 \&    Season     : 2000/01
254 .Ve
255 .PP
256 .Vb 3
257 \&    Teams:
258 \&    Man Utd 16 12 3 1
259 \&    Bradford 16 2 5 9
260 .Ve
261 .PP
262 Hopefully the syntax of the template is simple enough to 
263 follow. There are a few points to note.
264 .IP "\(bu" 4
265 Template processing directives are written using a simple 
266 language which is not Perl.
267 .IP "\(bu" 4
268 The keys of the \f(CW%data\fR have become the names of the data 
269 variables within the template.
270 .IP "\(bu" 4
271 Template processing directives are surrounded by \f(CW\*(C`[%\*(C'\fR and 
272 \&\f(CW\*(C`%]\*(C'\fR sequences.
273 .IP "\(bu" 4
274 If these tags are replaced with \f(CW\*(C`[%\-\*(C'\fR \f(CW\*(C`\-%]\*(C'\fR then the preceding 
275 or following linefeed is suppressed.
276 .IP "\(bu" 4
277 In the \f(CW\*(C`FOREACH\*(C'\fR loop, each element of the \f(CW\*(C`teams\*(C'\fR list was 
278 assigned, in turn, to the temporary variable \f(CW\*(C`team\*(C'\fR.
279 .IP "\(bu" 4
280 Each item assigned to the \f(CW\*(C`team\*(C'\fR variable is a Perl hash. 
281 Individual values within the hash are accessed using a dot notation.
282 .PP
283 It's probably the first and last of these points which are the 
284 most important. The first point emphasises the separation of the 
285 data acquisition logic from the presentation logic. The person 
286 creating the presentation template doesn't need to know Perl, 
287 they only need to know the data items which will be passed into
288 the template.
289 .PP
290 The last point demonstrates the way that \s-1TT2\s0 protects the 
291 template designer from the implementation of the data structures.
292 The data objects passed to the template processor can be scalars,
293 arrays, hashes, objects or even subroutines. The template 
294 processor will just interpret your data correctly and Do The 
295 Right Thing to return the correct value to you. In this example 
296 each team was a hash, but in a larger system each team might be 
297 an object, in which case \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`played\*(C'\fR, etc. would be accessor 
298 methods to the underlying object attributes. No changes would be 
299 required to the template as the template processor would realise 
300 that it needed to call methods rather than access hash values.
301 .Sh "A more complex example"
302 .IX Subsection "A more complex example"
303 Stats about the English Football League are usually presented in
304 a slightly more complex format than the one we used above. A 
305 full set of stats will show the number of games that a team has 
306 won, lost or drawn, the number of goals scored for and against 
307 the team and the number of points that the team therefore has.
308 Teams gain three points for a win and one point for a draw. When
309 teams have the same number of points they are separated by the 
310 goal difference, that is the number of goals the team has scored
311 minus the number of team scored against them. To complicate 
312 things even further, the games won, drawn and lost and the goals 
313 for and against are often split between home and away games.
314 .PP
315 Therefore if you have a data source which lists the team name 
316 togther with the games won, drawn and lost and the goals for and 
317 against split into home and away (a total of eleven data items) 
318 you can calculate all of the other items (goal difference, 
319 points awarded and even position in the league). Let's take such 
320 a file, but we'll only look at the top three teams. It will look 
321 something like this:
322 .PP
323 .Vb 3
324 \&    Man Utd,7,1,0,26,4,5,2,1,15,6
325 \&    Arsenal,7,1,0,17,4,2,3,3,7,9
326 \&    Leicester,4,3,1,10,8,4,2,2,7,4
327 .Ve
328 .PP
329 A simple script to read this data into an array of hashes will 
330 look something like this (I've simplified the names of the data 
331 columns \- w, d, and l are games won, drawn and lost and f and a 
332 are goals scored for and against; h and a at the front of a data 
333 item name indicates whether it's a home or away statistic):
334 .PP
335 .Vb 1
336 \&    my @cols = qw(name hw hd hl hf ha aw ad al af aa);
337 .Ve
338 .PP
339 .Vb 3
340 \&    my @teams;
341 \&    while (<>) {
342 \&        chomp;
343 .Ve
344 .PP
345 .Vb 1
346 \&        my %team;
347 .Ve
348 .PP
349 .Vb 1
350 \&        @team{@cols} = split /,/;
351 .Ve
352 .PP
353 .Vb 2
354 \&        push @teams, \e%team;
355 \&    }
356 .Ve
357 .PP
358 We can then go thru the teams again and calculate all of the 
359 derived data items:
360 .PP
361 .Vb 4
362 \&    foreach (@teams) {
363 \&        $_\->{w} = $_\->{hw} + $_\->{aw};
364 \&        $_\->{d} = $_\->{hd} + $_\->{ad};
365 \&        $_\->{l} = $_\->{hl} + $_\->{al};
366 .Ve
367 .PP
368 .Vb 1
369 \&        $_\->{pl} = $_\->{w} + $_\->{d} + $_\->{l};
370 .Ve
371 .PP
372 .Vb 2
373 \&        $_\->{f} = $_\->{hf} + $_\->{af};
374 \&        $_\->{a} = $_\->{ha} + $_\->{aa};
375 .Ve
376 .PP
377 .Vb 3
378 \&        $_\->{gd} = $_\->{f} \- $_\->{a};
379 \&        $_\->{pt} = (3 * $_\->{w}) + $_\->{d};
380 \&    }
381 .Ve
382 .PP
383 And then produce a list sorted in descending order:
384 .PP
385 .Vb 3
386 \&    @teams = sort { 
387 \&        $b\->{pt} <=> $b\->{pt} || $b\->{gd} <=> $a\->{gd} 
388 \&    } @teams;
389 .Ve
390 .PP
391 And finally add the league position data item:
392 .PP
393 .Vb 2
394 \&    $teams[$_]\->{pos} = $_ + 1 
395 \&        foreach 0 .. $#teams;
396 .Ve
397 .PP
398 Having pulled all of our data into an internal data structure 
399 we can start to produce output using out templates. A template 
400 to create a \s-1CSV\s0 file containing the data split between home and 
401 away stats would look like this:
402 .PP
403 .Vb 6
404 \&    [% FOREACH team = teams \-%]
405 \&    [% team.pos %],[% team.name %],[% team.pl %],[% team.hw %],
406 \&    [%\- team.hd %],[% team.hl %],[% team.hf %],[% team.ha %],
407 \&    [%\- team.aw %],[% team.ad %],[% team.al %],[% team.af %],
408 \&    [%\- team.aa %],[% team.gd %],[% team.pt %]
409 \&    [%\- END %]
410 .Ve
411 .PP
412 And processing it like this:
413 .PP
414 .Vb 2
415 \&    $tt\->process('split.tt', { teams => \e@teams }, 'split.csv')
416 \&      || die $tt\->error;
417 .Ve
418 .PP
419 produces the following output:
420 .PP
421 .Vb 3
422 \&    1,Man Utd,16,7,1,0,26,4,5,2,1,15,6,31,39
423 \&    2,Arsenal,16,7,1,0,17,4,2,3,3,7,9,11,31
424 \&    3,Leicester,16,4,3,1,10,8,4,2,2,7,4,5,29
425 .Ve
426 .PP
427 Notice that we've introduced the third parameter to \f(CW\*(C`process\*(C'\fR. 
428 If this parameter is missing then the \s-1TT2\s0 sends its output to 
429 \&\f(CW\*(C`STDOUT\*(C'\fR. If this parameter is a scalar then it is taken as the 
430 name of a file to write the output to. This parameter can also be 
431 (amongst other things) a filehandle or a reference to an object w
432 hich is assumed to implement a \f(CW\*(C`print\*(C'\fR method.
433 .PP
434 If we weren't interested in the split between home and away games, 
435 then we could use a simpler template like this:
436 .PP
437 .Vb 5
438 \&    [% FOREACH team = teams \-%]
439 \&    [% team.pos %],[% team.name %],[% team.pl %],[% team.w %],
440 \&    [%\- team.d %],[% team.l %],[% team.f %],[% team.a %],
441 \&    [%\- team.aa %],[% team.gd %],[% team.pt %]
442 \&    [% END \-%]
443 .Ve
444 .PP
445 Which would produce output like this:
446 .PP
447 .Vb 3
448 \&    1,Man Utd,16,12,3,1,41,10,6,31,39
449 \&    2,Arsenal,16,9,4,3,24,13,9,11,31
450 \&    3,Leicester,16,8,5,3,17,12,4,5,29
451 .Ve
452 .SH "Producing XML"
453 .IX Header "Producing XML"
454 This is starting to show some of the power and flexibility of 
455 \&\s-1TT2\s0, but you may be thinking that you could just as easily produce 
456 this output with a \f(CW\*(C`foreach\*(C'\fR loop and a couple of \f(CW\*(C`print\*(C'\fR 
457 statements in your code. This is, of course, true; but that's 
458 because I've chosen a deliberately simple example to explain the 
459 concepts. What if we wanted to produce an \s-1XML\s0 file containing the 
460 data? And what if (as I mentioned earlier) the league data was held 
461 in an object? The code would then look even easier as most of the code 
462 we've written earlier would be hidden away in \f(CW\*(C`FootballLeague.pm\*(C'\fR.
463 .PP
464 .Vb 2
465 \&    use FootballLeague;
466 \&    use Template;
467 .Ve
468 .PP
469 .Vb 1
470 \&    my $league = FootballLeague\->new(name => 'English Premier');
471 .Ve
472 .PP
473 .Vb 1
474 \&    my $tt = Template\->new;
475 .Ve
476 .PP
477 .Vb 2
478 \&    $tt\->process('league_xml.tt', { league => $league })
479 \&        || die $tt\->error;
480 .Ve
481 .PP
482 And the template in \f(CW\*(C`league_xml.tt\*(C'\fR would look something like this:
483 .PP
484 .Vb 2
485 \&    <?xml version="1.0"?>
486 \&    <!DOCTYPE LEAGUE SYSTEM "league.dtd">
487 .Ve
488 .PP
489 .Vb 22
490 \&    <league name="[% league.name %]" season="[% league.season %]">
491 \&    [% FOREACH team = league.teams \-%]
492 \&      <team name="[% team.name %]"
493 \&            pos="[% team.pos %]"
494 \&            played="[% team.pl %]"
495 \&            goal_diff="[% team.gd %]"
496 \&            points="[% team.pt %]">
497 \&         <stats type="home">
498 \&                win="[% team.hw %]"
499 \&                draw="[%\- team.hd %]"
500 \&                lose="[% team.hl %]"
501 \&                for="[% team.hf %]"
502 \&                against="[% team.ha %]" />
503 \&         <stats type="away">
504 \&                win="[% team.aw %]"
505 \&                draw="[%\- team.ad %]"
506 \&                lose="[% team.al %]"
507 \&                for="[% team.af %]"
508 \&                against="[% team.aa %]" />
509 \&      </team>
510 \&    [% END \-%]
511 \&    &/league>
512 .Ve
513 .PP
514 Notice that as we've passed the whole object into \f(CW\*(C`process\*(C'\fR then 
515 we need to put an extra level of indirection on our template 
516 variables \- everything is now a component of the \f(CW\*(C`league\*(C'\fR variable. 
517 Other than that, everything in the template is very similar to what 
518 we've used before. Presumably now \f(CW\*(C`team.name\*(C'\fR calls an accessor 
519 function rather than carrying out a hash lookup, but all of this 
520 is transparent to our template designer.
521 .SH "Multiple Formats"
522 .IX Header "Multiple Formats"
523 As a final example, let's suppose that we need to create output
524 football league tables in a number of formats. Perhaps we are 
525 passing this data on to other people and they can't all use the 
526 same format. Some of our users need \s-1CSV\s0 files and others need 
527 \&\s-1XML\s0. Some require data split between home and away matches and 
528 other just want the totals. In total, then, we'll need four 
529 different templates, but the good news is that they can use the 
530 same data object. All the script needs to do is to establish 
531 which template is required and process it.
532 .PP
533 .Vb 2
534 \&    use FootballLeague;
535 \&    use Template;
536 .Ve
537 .PP
538 .Vb 1
539 \&    my ($name, $type, $stats) = @_;
540 .Ve
541 .PP
542 .Vb 1
543 \&    my $league = FootballLeague\->new(name => $name);
544 .Ve
545 .PP
546 .Vb 1
547 \&    my $tt = Template\->new;
548 .Ve
549 .PP
550 .Vb 4
551 \&    $tt\->process("league_${type}_$stats.tt", 
552 \&                 { league => $league }
553 \&                 "league_$stats.$type")
554 \&        || die $tt\->error;
555 .Ve
556 .PP
557 For example, you can call this script as
558 .PP
559 .Vb 1
560 \&    league.pl 'English Premier' xml split
561 .Ve
562 .PP
563 This will process a template called \f(CW\*(C`league_xml_split.tt\*(C'\fR 
564 and put the results in a file called \f(CW\*(C`league_split.xml\*(C'\fR.
565 .PP
566 This starts to show the true strength of the Template Toolkit. 
567 If we later wanted to add another file format \- perhaps we 
568 wanted to create a league table \s-1HTML\s0 page or even a LaTeX 
569 document \- then we would just need to create the appropriate 
570 template and name it according to our existing naming 
571 convention. We would need to make no changes to the code.
572 .PP
573 I hope you can now see why the Template Toolkit is fast becoming
574 an essential part of many people's Perl installation.
575 .SH "AUTHOR"
576 .IX Header "AUTHOR"
577 Dave Cross <dave@dave.org.uk>
578 .SH "VERSION"
579 .IX Header "VERSION"
580 Template Toolkit version 2.19, released on 27 April 2007.
581 .SH "COPYRIGHT"
582 .IX Header "COPYRIGHT"
583 Copyright (C) 2001 Dave Cross <dave@dave.org.uk>
584 .PP
585 This module is free software; you can redistribute it and/or
586 modify it under the same terms as Perl itself.