File Coverage

lib/Template/Directive.pm
Criterion Covered Total %
statement 282 292 96.5
branch 103 140 73.5
condition 24 32 75.0
subroutine 44 48 91.6
pod 1 42 2.3
total 454 554 81.9


line stmt bran cond sub pod time code
1             #================================================================= -*-Perl-*-
2             #
3             # Template::Directive
4             #
5             # DESCRIPTION
6             # Factory module for constructing templates from Perl code.
7             #
8             # AUTHOR
9             # Andy Wardley
10             #
11             # WARNING
12             # Much of this module is hairy, even furry in places. It needs
13             # a lot of tidying up and may even be moved into a different place
14             # altogether. The generator code is often inefficient, particularly in
15             # being very anal about pretty-printing the Perl code all neatly, but
16             # at the moment, that's still high priority for the sake of easier
17             # debugging.
18             #
19             # COPYRIGHT
20             # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
21             #
22             # This module is free software; you can redistribute it and/or
23             # modify it under the same terms as Perl itself.
24             #
25             #============================================================================
26              
27             package Template::Directive;
28              
29 85     85   1811 use strict;
  85         101  
  85         1856  
30 85     85   245 use warnings;
  85         78  
  85         1732  
31 85     85   270 use base 'Template::Base';
  85         134  
  85         4464  
32 85     85   360 use Template::Constants;
  85         159  
  85         2484  
33 85     85   312 use Template::Exception;
  85         105  
  85         265631  
34              
35             our $VERSION = 2.20;
36             our $DEBUG = 0 unless defined $DEBUG;
37             our $WHILE_MAX = 1000 unless defined $WHILE_MAX;
38             our $PRETTY = 0 unless defined $PRETTY;
39             our $OUTPUT = '$output .= ';
40              
41              
42             sub _init {
43 143     143   260 my ($self, $config) = @_;
44 143         412 $self->{ NAMESPACE } = $config->{ NAMESPACE };
45 143         1018 return $self;
46             }
47              
48             sub trace_vars {
49 1     1 0 1 my $self = shift;
50             return @_
51             ? ($self->{ TRACE_VARS } = shift)
52 1 50       3 : $self->{ TRACE_VARS };
53             }
54              
55             sub pad {
56 0     0 0 0 my ($text, $pad) = @_;
57 0         0 $pad = ' ' x ($pad * 4);
58 0         0 $text =~ s/^(?!#line)/$pad/gm;
59 0         0 $text;
60             }
61              
62             #========================================================================
63             # FACTORY METHODS
64             #
65             # These methods are called by the parser to construct directive instances.
66             #========================================================================
67              
68             #------------------------------------------------------------------------
69             # template($block)
70             #------------------------------------------------------------------------
71              
72             sub template {
73 1465     1465 0 3175 my ($self, $block) = @_;
74 1465 50       2246 $block = pad($block, 2) if $PRETTY;
75              
76 1465 100       4598 return "sub { return '' }" unless $block =~ /\S/;
77              
78 1454         4791 return <
79             sub {
80             my \$context = shift || die "template sub called without context\\n";
81             my \$stash = \$context->stash;
82             my \$output = '';
83             my \$_tt_error;
84            
85             eval { BLOCK: {
86             $block
87             } };
88             if (\$@) {
89             \$_tt_error = \$context->catch(\$@, \\\$output);
90             die \$_tt_error unless \$_tt_error->type eq 'return';
91             }
92              
93             return \$output;
94             }
95             EOF
96             }
97              
98              
99             #------------------------------------------------------------------------
100             # anon_block($block) [% BLOCK %] ... [% END %]
101             #------------------------------------------------------------------------
102              
103             sub anon_block {
104 0     0 0 0 my ($self, $block) = @_;
105 0 0       0 $block = pad($block, 2) if $PRETTY;
106              
107 0         0 return <
108              
109             # BLOCK
110             $OUTPUT do {
111             my \$output = '';
112             my \$_tt_error;
113            
114             eval { BLOCK: {
115             $block
116             } };
117             if (\$@) {
118             \$_tt_error = \$context->catch(\$@, \\\$output);
119             die \$_tt_error unless \$_tt_error->type eq 'return';
120             }
121              
122             \$output;
123             };
124             EOF
125             }
126              
127              
128             #------------------------------------------------------------------------
129             # block($blocktext)
130             #------------------------------------------------------------------------
131              
132             sub block {
133 2175     2175 0 4558 my ($self, $block) = @_;
134 2175 100       1720 return join("\n", @{ $block || [] });
  2175         8374  
135             }
136              
137              
138             #------------------------------------------------------------------------
139             # textblock($text)
140             #------------------------------------------------------------------------
141              
142             sub textblock {
143 3178     3178 0 7102 my ($self, $text) = @_;
144 3178         4917 return "$OUTPUT " . &text($self, $text) . ';';
145             }
146              
147              
148             #------------------------------------------------------------------------
149             # text($text)
150             #------------------------------------------------------------------------
151              
152             sub text {
153 3437     3437 0 3203 my ($self, $text) = @_;
154 3437         3765 for ($text) {
155 3437         5403 s/(["\$\@\\])/\\$1/g;
156 3437         6980 s/\n/\\n/g;
157             }
158 3437         8553 return '"' . $text . '"';
159             }
160              
161              
162             #------------------------------------------------------------------------
163             # quoted(\@items) "foo$bar"
164             #------------------------------------------------------------------------
165              
166             sub quoted {
167 172     172 0 464 my ($self, $items) = @_;
168 172 50       340 return '' unless @$items;
169 172 100       400 return ("('' . " . $items->[0] . ')') if scalar @$items == 1;
170 121         405 return '(' . join(' . ', @$items) . ')';
171             # my $r = '(' . join(' . ', @$items) . ' . "")';
172             # print STDERR "[$r]\n";
173             # return $r;
174             }
175              
176              
177             #------------------------------------------------------------------------
178             # ident(\@ident) foo.bar(baz)
179             #------------------------------------------------------------------------
180              
181             sub ident {
182 3077     3077 0 6907 my ($self, $ident) = @_;
183 3077 50       4227 return "''" unless @$ident;
184 3077         2154 my $ns;
185              
186             # Careful! Template::Parser always creates a Template::Directive object
187             # (as of v2.22_1) so $self is usually an object. However, we used to
188             # allow Template::Directive methods to be called as class methods and
189             # Template::Namespace::Constants module takes advantage of this fact
190             # by calling Template::Directive->ident() when it needs to generate an
191             # identifier. This hack guards against Mr Fuckup from coming to town
192             # when that happens.
193            
194 3077 100       4808 if (ref $self) {
195             # trace variable usage
196 3075 100       4443 if ($self->{ TRACE_VARS }) {
197 9         9 my $root = $self->{ TRACE_VARS };
198 9         7 my $n = 0;
199 9         3 my $v;
200 9         13 while ($n < @$ident) {
201 13         11 $v = $ident->[$n];
202 13         15 for ($v) { s/^'//; s/'$// };
  13         26  
  13         25  
203 13   50     42 $root = $root->{ $v } ||= { };
204 13         23 $n += 2;
205             }
206             }
207              
208             # does the first element of the identifier have a NAMESPACE
209             # handler defined?
210 3075 100 100     7475 if (@$ident > 2 && ($ns = $self->{ NAMESPACE })) {
211 46         46 my $key = $ident->[0];
212 46         202 $key =~ s/^'(.+)'$/$1/s;
213 46 100       104 if ($ns = $ns->{ $key }) {
214 31         77 return $ns->ident($ident);
215             }
216             }
217             }
218            
219 3046 100 100     7528 if (scalar @$ident <= 2 && ! $ident->[1]) {
220 1667         1639 $ident = $ident->[0];
221             }
222             else {
223 1379         3326 $ident = '[' . join(', ', @$ident) . ']';
224             }
225 3046         5931 return "\$stash->get($ident)";
226             }
227              
228             #------------------------------------------------------------------------
229             # identref(\@ident) \foo.bar(baz)
230             #------------------------------------------------------------------------
231              
232             sub identref {
233 6     6 0 24 my ($self, $ident) = @_;
234 6 50       15 return "''" unless @$ident;
235 6 100 100     21 if (scalar @$ident <= 2 && ! $ident->[1]) {
236 3         5 $ident = $ident->[0];
237             }
238             else {
239 3         13 $ident = '[' . join(', ', @$ident) . ']';
240             }
241 6         16 return "\$stash->getref($ident)";
242             }
243              
244              
245             #------------------------------------------------------------------------
246             # assign(\@ident, $value, $default) foo = bar
247             #------------------------------------------------------------------------
248              
249             sub assign {
250 512     512 0 624 my ($self, $var, $val, $default) = @_;
251              
252 512 100       869 if (ref $var) {
253 508 100 66     1717 if (scalar @$var == 2 && ! $var->[1]) {
254 442         477 $var = $var->[0];
255             }
256             else {
257 66         206 $var = '[' . join(', ', @$var) . ']';
258             }
259             }
260 512 100       760 $val .= ', 1' if $default;
261 512         2274 return "\$stash->set($var, $val)";
262             }
263              
264              
265             #------------------------------------------------------------------------
266             # args(\@args) foo, bar, baz = qux
267             #------------------------------------------------------------------------
268              
269             sub args {
270 872     872 0 1638 my ($self, $args) = @_;
271 872         783 my $hash = shift @$args;
272 872 100       1632 push(@$args, '{ ' . join(', ', @$hash) . ' }')
273             if @$hash;
274              
275 872 100       1365 return '0' unless @$args;
276 725         2184 return '[ ' . join(', ', @$args) . ' ]';
277             }
278              
279             #------------------------------------------------------------------------
280             # filenames(\@names)
281             #------------------------------------------------------------------------
282              
283             sub filenames {
284 206     206 0 241 my ($self, $names) = @_;
285 206 100       348 if (@$names > 1) {
286 4         10 $names = '[ ' . join(', ', @$names) . ' ]';
287             }
288             else {
289 202         212 $names = shift @$names;
290             }
291 206         551 return $names;
292             }
293              
294              
295             #------------------------------------------------------------------------
296             # get($expr) [% foo %]
297             #------------------------------------------------------------------------
298              
299             sub get {
300 2112     2112 0 4745 my ($self, $expr) = @_;
301 2112         4206 return "$OUTPUT $expr;";
302             }
303              
304              
305             #------------------------------------------------------------------------
306             # call($expr) [% CALL bar %]
307             #------------------------------------------------------------------------
308              
309             sub call {
310 24     24 0 62 my ($self, $expr) = @_;
311 24         28 $expr .= ';';
312 24         42 return $expr;
313             }
314              
315              
316             #------------------------------------------------------------------------
317             # set(\@setlist) [% foo = bar, baz = qux %]
318             #------------------------------------------------------------------------
319              
320             sub set {
321 413     413 0 1494 my ($self, $setlist) = @_;
322 413         347 my $output;
323 413         1820 while (my ($var, $val) = splice(@$setlist, 0, 2)) {
324 475         820 $output .= &assign($self, $var, $val) . ";\n";
325             }
326 413         537 chomp $output;
327 413         691 return $output;
328             }
329              
330              
331             #------------------------------------------------------------------------
332             # default(\@setlist) [% DEFAULT foo = bar, baz = qux %]
333             #------------------------------------------------------------------------
334              
335             sub default {
336 24     24 0 87 my ($self, $setlist) = @_;
337 24         26 my $output;
338 24         89 while (my ($var, $val) = splice(@$setlist, 0, 2)) {
339 31         62 $output .= &assign($self, $var, $val, 1) . ";\n";
340             }
341 24         36 chomp $output;
342 24         48 return $output;
343             }
344              
345              
346             #------------------------------------------------------------------------
347             # insert(\@nameargs) [% INSERT file %]
348             # # => [ [ $file, ... ], \@args ]
349             #------------------------------------------------------------------------
350              
351             sub insert {
352 15     15 0 43 my ($self, $nameargs) = @_;
353 15         15 my ($file, $args) = @$nameargs;
354 15         26 $file = $self->filenames($file);
355 15         35 return "$OUTPUT \$context->insert($file);";
356             }
357              
358              
359             #------------------------------------------------------------------------
360             # include(\@nameargs) [% INCLUDE template foo = bar %]
361             # # => [ [ $file, ... ], \@args ]
362             #------------------------------------------------------------------------
363              
364             sub include {
365 155     155 0 503 my ($self, $nameargs) = @_;
366 155         197 my ($file, $args) = @$nameargs;
367 155         171 my $hash = shift @$args;
368 155         297 $file = $self->filenames($file);
369 155 100       345 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
370 155         429 return "$OUTPUT \$context->include($file);";
371             }
372              
373              
374             #------------------------------------------------------------------------
375             # process(\@nameargs) [% PROCESS template foo = bar %]
376             # # => [ [ $file, ... ], \@args ]
377             #------------------------------------------------------------------------
378              
379             sub process {
380 36     36 0 131 my ($self, $nameargs) = @_;
381 36         56 my ($file, $args) = @$nameargs;
382 36         53 my $hash = shift @$args;
383 36         67 $file = $self->filenames($file);
384 36 100       91 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
385 36         116 return "$OUTPUT \$context->process($file);";
386             }
387              
388              
389             #------------------------------------------------------------------------
390             # if($expr, $block, $else) [% IF foo < bar %]
391             # ...
392             # [% ELSE %]
393             # ...
394             # [% END %]
395             #------------------------------------------------------------------------
396              
397             sub if {
398 84     84 0 281 my ($self, $expr, $block, $else) = @_;
399 84 100       166 my @else = $else ? @$else : ();
400 84         102 $else = pop @else;
401 84 50       153 $block = pad($block, 1) if $PRETTY;
402              
403 84         167 my $output = "if ($expr) {\n$block\n}\n";
404              
405 84         125 foreach my $elsif (@else) {
406 8         10 ($expr, $block) = @$elsif;
407 8 50       15 $block = pad($block, 1) if $PRETTY;
408 8         22 $output .= "elsif ($expr) {\n$block\n}\n";
409             }
410 84 100       138 if (defined $else) {
411 38 50       58 $else = pad($else, 1) if $PRETTY;
412 38         78 $output .= "else {\n$else\n}\n";
413             }
414              
415 84         152 return $output;
416             }
417              
418              
419             #------------------------------------------------------------------------
420             # foreach($target, $list, $args, $block) [% FOREACH x = [ foo bar ] %]
421             # ...
422             # [% END %]
423             #------------------------------------------------------------------------
424              
425             sub foreach {
426 151     151 0 334 my ($self, $target, $list, $args, $block, $label) = @_;
427 151         156 $args = shift @$args;
428 151 50       281 $args = @$args ? ', { ' . join(', ', @$args) . ' }' : '';
429 151   100     327 $label ||= 'LOOP';
430              
431 151         132 my ($loop_save, $loop_set, $loop_restore, $setiter);
432 151 100       215 if ($target) {
433 139         260 $loop_save = 'eval { $_tt_oldloop = ' . &ident($self, ["'loop'"]) . ' }';
434 139         250 $loop_set = "\$stash->{'$target'} = \$_tt_value";
435 139         132 $loop_restore = "\$stash->set('loop', \$_tt_oldloop)";
436             }
437             else {
438 12         18 $loop_save = '$stash = $context->localise()';
439             # $loop_set = "\$stash->set('import', \$_tt_value) "
440             # . "if ref \$value eq 'HASH'";
441 12         21 $loop_set = "\$stash->get(['import', [\$_tt_value]]) "
442             . "if ref \$_tt_value eq 'HASH'";
443 12         13 $loop_restore = '$stash = $context->delocalise()';
444             }
445 151 50       270 $block = pad($block, 3) if $PRETTY;
446              
447 151         749 return <
448              
449             # FOREACH
450             do {
451             my (\$_tt_value, \$_tt_error, \$_tt_oldloop);
452             my \$_tt_list = $list;
453            
454             unless (UNIVERSAL::isa(\$_tt_list, 'Template::Iterator')) {
455             \$_tt_list = Template::Config->iterator(\$_tt_list)
456             || die \$Template::Config::ERROR, "\\n";
457             }
458              
459             (\$_tt_value, \$_tt_error) = \$_tt_list->get_first();
460             $loop_save;
461             \$stash->set('loop', \$_tt_list);
462             eval {
463             $label: while (! \$_tt_error) {
464             $loop_set;
465             $block;
466             (\$_tt_value, \$_tt_error) = \$_tt_list->get_next();
467             }
468             };
469             $loop_restore;
470             die \$@ if \$@;
471             \$_tt_error = 0 if \$_tt_error && \$_tt_error eq Template::Constants::STATUS_DONE;
472             die \$_tt_error if \$_tt_error;
473             };
474             EOF
475             }
476              
477             #------------------------------------------------------------------------
478             # next() [% NEXT %]
479             #
480             # Next iteration of a FOREACH loop (experimental)
481             #------------------------------------------------------------------------
482              
483             sub next {
484 10     10 0 11 my ($self, $label) = @_;
485 10   50     17 $label ||= 'LOOP';
486 10         21 return <
487             (\$_tt_value, \$_tt_error) = \$_tt_list->get_next();
488             next $label;
489             EOF
490             }
491              
492              
493             #------------------------------------------------------------------------
494             # wrapper(\@nameargs, $block) [% WRAPPER template foo = bar %]
495             # # => [ [$file,...], \@args ]
496             #------------------------------------------------------------------------
497              
498             sub wrapper {
499 13     13 0 40 my ($self, $nameargs, $block) = @_;
500 13         18 my ($file, $args) = @$nameargs;
501 13         13 my $hash = shift @$args;
502              
503 13         14 local $" = ', ';
504             # print STDERR "wrapper([@$file], { @$hash })\n";
505              
506 13 100       28 return $self->multi_wrapper($file, $hash, $block)
507             if @$file > 1;
508 11         13 $file = shift @$file;
509              
510 11 50       28 $block = pad($block, 1) if $PRETTY;
511 11         12 push(@$hash, "'content'", '$output');
512 11 50       35 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
513              
514 11         41 return <
515              
516             # WRAPPER
517             $OUTPUT do {
518             my \$output = '';
519             $block
520             \$context->include($file);
521             };
522             EOF
523             }
524              
525              
526             sub multi_wrapper {
527 2     2 0 5 my ($self, $file, $hash, $block) = @_;
528 2 50       7 $block = pad($block, 1) if $PRETTY;
529              
530 2         4 push(@$hash, "'content'", '$output');
531 2 50       11 $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
532              
533 2         5 $file = join(', ', reverse @$file);
534             # print STDERR "multi wrapper: $file\n";
535              
536 2         14 return <
537              
538             # WRAPPER
539             $OUTPUT do {
540             my \$output = '';
541             $block
542             foreach ($file) {
543             \$output = \$context->include(\$_$hash);
544             }
545             \$output;
546             };
547             EOF
548             }
549              
550              
551             #------------------------------------------------------------------------
552             # while($expr, $block) [% WHILE x < 10 %]
553             # ...
554             # [% END %]
555             #------------------------------------------------------------------------
556              
557             sub while {
558 16     16 0 25 my ($self, $expr, $block, $label) = @_;
559 16 50       31 $block = pad($block, 2) if $PRETTY;
560 16   100     27 $label ||= 'LOOP';
561              
562 16         62 return <
563              
564             # WHILE
565             do {
566             my \$_tt_failsafe = $WHILE_MAX;
567             $label:
568             while (--\$_tt_failsafe && ($expr)) {
569             $block
570             }
571             die "WHILE loop terminated (> $WHILE_MAX iterations)\\n"
572             unless \$_tt_failsafe;
573             };
574             EOF
575             }
576              
577              
578             #------------------------------------------------------------------------
579             # switch($expr, \@case) [% SWITCH %]
580             # [% CASE foo %]
581             # ...
582             # [% END %]
583             #------------------------------------------------------------------------
584              
585             sub switch {
586 20     20 0 67 my ($self, $expr, $case) = @_;
587 20         24 my @case = @$case;
588 20         21 my ($match, $block, $default);
589 20         19 my $caseblock = '';
590              
591 20         16 $default = pop @case;
592              
593 20         26 foreach $case (@case) {
594 31         24 $match = $case->[0];
595 31         20 $block = $case->[1];
596 31 50       45 $block = pad($block, 1) if $PRETTY;
597 31         58 $caseblock .= <
598             \$_tt_match = $match;
599             \$_tt_match = [ \$_tt_match ] unless ref \$_tt_match eq 'ARRAY';
600             if (grep(/^\\Q\$_tt_result\\E\$/, \@\$_tt_match)) {
601             $block
602             last SWITCH;
603             }
604             EOF
605             }
606              
607 20 100       30 $caseblock .= $default
608             if defined $default;
609 20 50       27 $caseblock = pad($caseblock, 2) if $PRETTY;
610              
611 20         64 return <
612              
613             # SWITCH
614             do {
615             my \$_tt_result = $expr;
616             my \$_tt_match;
617             SWITCH: {
618             $caseblock
619             }
620             };
621             EOF
622             }
623              
624              
625             #------------------------------------------------------------------------
626             # try($block, \@catch) [% TRY %]
627             # ...
628             # [% CATCH %]
629             # ...
630             # [% END %]
631             #------------------------------------------------------------------------
632              
633             sub try {
634 131     131 0 561 my ($self, $block, $catch) = @_;
635 131         209 my @catch = @$catch;
636 131         152 my ($match, $mblock, $default, $final, $n);
637 131         139 my $catchblock = '';
638 131         159 my $handlers = [];
639              
640 131 50       266 $block = pad($block, 2) if $PRETTY;
641 131         161 $final = pop @catch;
642 131 100       357 $final = "# FINAL\n" . ($final ? "$final\n" : '')
643             . 'die $_tt_error if $_tt_error;' . "\n" . '$output;';
644 131 50       205 $final = pad($final, 1) if $PRETTY;
645              
646 131         129 $n = 0;
647 131         201 foreach $catch (@catch) {
648 175   66     372 $match = $catch->[0] || do {
649             $default ||= $catch->[1];
650             next;
651             };
652 67         56 $mblock = $catch->[1];
653 67 50       93 $mblock = pad($mblock, 1) if $PRETTY;
654 67         97 push(@$handlers, "'$match'");
655 67 100       158 $catchblock .= $n++
656             ? "elsif (\$_tt_handler eq '$match') {\n$mblock\n}\n"
657             : "if (\$_tt_handler eq '$match') {\n$mblock\n}\n";
658             }
659 131         172 $catchblock .= "\$_tt_error = 0;";
660 131 50       235 $catchblock = pad($catchblock, 3) if $PRETTY;
661 131 100       197 if ($default) {
662 108 50       186 $default = pad($default, 1) if $PRETTY;
663 108         207 $default = "else {\n # DEFAULT\n$default\n \$_tt_error = '';\n}";
664             }
665             else {
666 23         32 $default = '# NO DEFAULT';
667             }
668 131 50       224 $default = pad($default, 2) if $PRETTY;
669              
670 131         216 $handlers = join(', ', @$handlers);
671 131         725 return <
672              
673             # TRY
674             $OUTPUT do {
675             my \$output = '';
676             my (\$_tt_error, \$_tt_handler);
677             eval {
678             $block
679             };
680             if (\$@) {
681             \$_tt_error = \$context->catch(\$@, \\\$output);
682             die \$_tt_error if \$_tt_error->type =~ /^return|stop\$/;
683             \$stash->set('error', \$_tt_error);
684             \$stash->set('e', \$_tt_error);
685             if (defined (\$_tt_handler = \$_tt_error->select_handler($handlers))) {
686             $catchblock
687             }
688             $default
689             }
690             $final
691             };
692             EOF
693             }
694              
695              
696             #------------------------------------------------------------------------
697             # throw(\@nameargs) [% THROW foo "bar error" %]
698             # # => [ [$type], \@args ]
699             #------------------------------------------------------------------------
700              
701             sub throw {
702 37     37 0 96 my ($self, $nameargs) = @_;
703 37         42 my ($type, $args) = @$nameargs;
704 37         33 my $hash = shift(@$args);
705 37         38 my $info = shift(@$args);
706 37         35 $type = shift @$type; # uses same parser production as INCLUDE
707             # etc., which allow multiple names
708             # e.g. INCLUDE foo+bar+baz
709              
710 37 100 66     129 if (! $info) {
    100          
711 5         7 $args = "$type, undef";
712             }
713             elsif (@$hash || @$args) {
714 4         4 local $" = ', ';
715 4         3 my $i = 0;
716             $args = "$type, { args => [ "
717             . join(', ', $info, @$args)
718             . ' ], '
719             . join(', ',
720 4         12 (map { "'" . $i++ . "' => $_" } ($info, @$args)),
  8         19  
721             @$hash)
722             . ' }';
723             }
724             else {
725 28         48 $args = "$type, $info";
726             }
727            
728 37         83 return "\$context->throw($args, \\\$output);";
729             }
730              
731              
732             #------------------------------------------------------------------------
733             # clear() [% CLEAR %]
734             #
735             # NOTE: this is redundant, being hard-coded (for now) into Parser.yp
736             #------------------------------------------------------------------------
737              
738             sub clear {
739 0     0 0 0 return "\$output = '';";
740             }
741              
742             #------------------------------------------------------------------------
743             # break() [% BREAK %]
744             #
745             # NOTE: this is redundant, being hard-coded (for now) into Parser.yp
746             #------------------------------------------------------------------------
747              
748             sub OLD_break {
749 0     0 0 0 return 'last LOOP;';
750             }
751              
752             #------------------------------------------------------------------------
753             # return() [% RETURN %]
754             #------------------------------------------------------------------------
755              
756             sub return {
757 2     2 0 10 return "\$context->throw('return', '', \\\$output);";
758             }
759              
760             #------------------------------------------------------------------------
761             # stop() [% STOP %]
762             #------------------------------------------------------------------------
763              
764             sub stop {
765 4     4 0 10 return "\$context->throw('stop', '', \\\$output);";
766             }
767              
768              
769             #------------------------------------------------------------------------
770             # use(\@lnameargs) [% USE alias = plugin(args) %]
771             # # => [ [$file, ...], \@args, $alias ]
772             #------------------------------------------------------------------------
773              
774             sub use {
775 209     209 0 612 my ($self, $lnameargs) = @_;
776 209         263 my ($file, $args, $alias) = @$lnameargs;
777 209         211 $file = shift @$file; # same production rule as INCLUDE
778 209   66     568 $alias ||= $file;
779 209         334 $args = &args($self, $args);
780 209 100       456 $file .= ", $args" if $args;
781             # my $set = &assign($self, $alias, '$plugin');
782 209         589 return "# USE\n"
783             . "\$stash->set($alias,\n"
784             . " \$context->plugin($file));";
785             }
786              
787             #------------------------------------------------------------------------
788             # view(\@nameargs, $block) [% VIEW name args %]
789             # # => [ [$file, ... ], \@args ]
790             #------------------------------------------------------------------------
791              
792             sub view {
793 30     30 0 50 my ($self, $nameargs, $block, $defblocks) = @_;
794 30         36 my ($name, $args) = @$nameargs;
795 30         33 my $hash = shift @$args;
796 30         35 $name = shift @$name; # same production rule as INCLUDE
797 30 50       48 $block = pad($block, 1) if $PRETTY;
798              
799 30 100       54 if (%$defblocks) {
800 16         35 $defblocks = join(",\n", map { "'$_' => $defblocks->{ $_ }" }
  21         77  
801             keys %$defblocks);
802 16 50       33 $defblocks = pad($defblocks, 1) if $PRETTY;
803 16         37 $defblocks = "{\n$defblocks\n}";
804 16         28 push(@$hash, "'blocks'", $defblocks);
805             }
806 30 100       87 $hash = @$hash ? '{ ' . join(', ', @$hash) . ' }' : '';
807              
808 30         119 return <
809             # VIEW
810             do {
811             my \$output = '';
812             my \$_tt_oldv = \$stash->get('view');
813             my \$_tt_view = \$context->view($hash);
814             \$stash->set($name, \$_tt_view);
815             \$stash->set('view', \$_tt_view);
816              
817             $block
818              
819             \$stash->set('view', \$_tt_oldv);
820             \$_tt_view->seal();
821             # \$output; # not used - commented out to avoid warning
822             };
823             EOF
824             }
825              
826              
827             #------------------------------------------------------------------------
828             # perl($block)
829             #------------------------------------------------------------------------
830              
831             sub perl {
832 12     12 0 73 my ($self, $block) = @_;
833 12 50       22 $block = pad($block, 1) if $PRETTY;
834              
835 12         46 return <
836              
837             # PERL
838             \$context->throw('perl', 'EVAL_PERL not set')
839             unless \$context->eval_perl();
840              
841             $OUTPUT do {
842             my \$output = "package Template::Perl;\\n";
843              
844             $block
845              
846             local(\$Template::Perl::context) = \$context;
847             local(\$Template::Perl::stash) = \$stash;
848              
849             my \$_tt_result = '';
850             tie *Template::Perl::PERLOUT, 'Template::TieString', \\\$_tt_result;
851             my \$_tt_save_stdout = select *Template::Perl::PERLOUT;
852              
853             eval \$output;
854             select \$_tt_save_stdout;
855             \$context->throw(\$@) if \$@;
856             \$_tt_result;
857             };
858             EOF
859             }
860              
861              
862             #------------------------------------------------------------------------
863             # no_perl()
864             #------------------------------------------------------------------------
865              
866             sub no_perl {
867 4     4 0 29 my $self = shift;
868 4         8 return "\$context->throw('perl', 'EVAL_PERL not set');";
869             }
870              
871              
872             #------------------------------------------------------------------------
873             # rawperl($block)
874             #
875             # NOTE: perhaps test context EVAL_PERL switch at compile time rather than
876             # runtime?
877             #------------------------------------------------------------------------
878              
879             sub rawperl {
880 2     2 0 18 my ($self, $block, $line) = @_;
881 2         5 for ($block) {
882 2         3 s/^\n+//;
883 2         11 s/\n+$//;
884             }
885 2 50       5 $block = pad($block, 1) if $PRETTY;
886 2 50       9 $line = $line ? " (starting line $line)" : '';
887              
888 2         7 return <
889             # RAWPERL
890             #line 1 "RAWPERL block$line"
891             $block
892             EOF
893             }
894              
895              
896              
897             #------------------------------------------------------------------------
898             # filter()
899             #------------------------------------------------------------------------
900              
901             sub filter {
902 134     134 0 439 my ($self, $lnameargs, $block) = @_;
903 134         179 my ($name, $args, $alias) = @$lnameargs;
904 134         141 $name = shift @$name;
905 134         231 $args = &args($self, $args);
906 134 50       210 $args = $args ? "$args, $alias" : ", undef, $alias"
    100          
907             if $alias;
908 134 100       235 $name .= ", $args" if $args;
909 134 50       208 $block = pad($block, 1) if $PRETTY;
910            
911 134         434 return <
912              
913             # FILTER
914             $OUTPUT do {
915             my \$output = '';
916             my \$_tt_filter = \$context->filter($name)
917             || \$context->throw(\$context->error);
918              
919             $block
920            
921             &\$_tt_filter(\$output);
922             };
923             EOF
924             }
925              
926              
927             #------------------------------------------------------------------------
928             # capture($name, $block)
929             #------------------------------------------------------------------------
930              
931             sub capture {
932 11     11 0 37 my ($self, $name, $block) = @_;
933              
934 11 50       23 if (ref $name) {
935 11 50 33     52 if (scalar @$name == 2 && ! $name->[1]) {
936 11         14 $name = $name->[0];
937             }
938             else {
939 0         0 $name = '[' . join(', ', @$name) . ']';
940             }
941             }
942 11 50       22 $block = pad($block, 1) if $PRETTY;
943              
944 11         40 return <
945              
946             # CAPTURE
947             \$stash->set($name, do {
948             my \$output = '';
949             $block
950             \$output;
951             });
952             EOF
953              
954             }
955              
956              
957             #------------------------------------------------------------------------
958             # macro($name, $block, \@args)
959             #------------------------------------------------------------------------
960              
961             sub macro {
962 10     10 0 29 my ($self, $ident, $block, $args) = @_;
963 10 50       17 $block = pad($block, 2) if $PRETTY;
964              
965 10 100       11 if ($args) {
966 3         4 my $nargs = scalar @$args;
967 3         3 $args = join(', ', map { "'$_'" } @$args);
  3         9  
968 3 50       9 $args = $nargs > 1
969             ? "\@_tt_args{ $args } = splice(\@_, 0, $nargs)"
970             : "\$_tt_args{ $args } = shift";
971              
972 3         15 return <
973              
974             # MACRO
975             \$stash->set('$ident', sub {
976             my \$output = '';
977             my (%_tt_args, \$_tt_params);
978             $args;
979             \$_tt_params = shift;
980             \$_tt_params = { } unless ref(\$_tt_params) eq 'HASH';
981             \$_tt_params = { \%_tt_args, %\$_tt_params };
982              
983             my \$stash = \$context->localise(\$_tt_params);
984             eval {
985             $block
986             };
987             \$stash = \$context->delocalise();
988             die \$@ if \$@;
989             return \$output;
990             });
991             EOF
992              
993             }
994             else {
995 7         24 return <
996              
997             # MACRO
998             \$stash->set('$ident', sub {
999             my \$_tt_params = \$_[0] if ref(\$_[0]) eq 'HASH';
1000             my \$output = '';
1001              
1002             my \$stash = \$context->localise(\$_tt_params);
1003             eval {
1004             $block
1005             };
1006             \$stash = \$context->delocalise();
1007             die \$@ if \$@;
1008             return \$output;
1009             });
1010             EOF
1011             }
1012             }
1013              
1014              
1015             sub debug {
1016 15     15 1 100 my ($self, $nameargs) = @_;
1017 15         16 my ($file, $args) = @$nameargs;
1018 15         12 my $hash = shift @$args;
1019 15         21 $args = join(', ', @$file, @$args);
1020 15 100       32 $args .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
1021 15         41 return "$OUTPUT \$context->debugging($args); ## DEBUG ##";
1022             }
1023              
1024              
1025             1;
1026              
1027             __END__