File Coverage

lib/Template/Directive.pm
Criterion Covered Total %
statement 270 292 92.4
branch 101 140 72.1
condition 23 32 71.8
subroutine 43 48 89.5
pod 1 42 2.3
total 438 554 79.0


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 80     80   2940 use strict;
  80         184  
  80         3173  
30 80     80   452 use warnings;
  80         155  
  80         10069  
31 80     80   410 use base 'Template::Base';
  80         1551  
  80         6081  
32 80     80   460 use Template::Constants;
  80         333  
  80         3279  
33 80     80   663 use Template::Exception;
  80         164  
  80         464384  
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 133     133   402 my ($self, $config) = @_;
44 133         748 $self->{ NAMESPACE } = $config->{ NAMESPACE };
45 133         1359 return $self;
46             }
47              
48             sub trace_vars {
49 0     0 0 0 my $self = shift;
50             return @_
51             ? ($self->{ TRACE_VARS } = shift)
52 0 0       0 : $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 1433     1433 0 7458 my ($self, $block) = @_;
74 1433 50       4052 $block = pad($block, 2) if $PRETTY;
75              
76 1433 100       8596 return "sub { return '' }" unless $block =~ /\S/;
77              
78 1423         9310 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 2124     2124 0 10949 my ($self, $block) = @_;
134 2124 100       3224 return join("\n", @{ $block || [] });
  2124         24754  
135             }
136              
137              
138             #------------------------------------------------------------------------
139             # textblock($text)
140             #------------------------------------------------------------------------
141              
142             sub textblock {
143 3111     3111 0 19563 my ($self, $text) = @_;
144 3111         8589 return "$OUTPUT " . &text($self, $text) . ';';
145             }
146              
147              
148             #------------------------------------------------------------------------
149             # text($text)
150             #------------------------------------------------------------------------
151              
152             sub text {
153 3367     3367 0 6507 my ($self, $text) = @_;
154 3367         6345 for ($text) {
155 3367         9142 s/(["\$\@\\])/\\$1/g;
156 3367         18804 s/\n/\\n/g;
157             }
158 3367         29722 return '"' . $text . '"';
159             }
160              
161              
162             #------------------------------------------------------------------------
163             # quoted(\@items) "foo$bar"
164             #------------------------------------------------------------------------
165              
166             sub quoted {
167 171     171 0 919 my ($self, $items) = @_;
168 171 50       569 return '' unless @$items;
169 171 100       684 return ("('' . " . $items->[0] . ')') if scalar @$items == 1;
170 120         676 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 3028     3028 0 18021 my ($self, $ident) = @_;
183 3028 50       6973 return "''" unless @$ident;
184 3028         3704 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 3028 100       7697 if (ref $self) {
195             # trace variable usage
196 3026 50       7797 if ($self->{ TRACE_VARS }) {
197 0         0 my $root = $self->{ TRACE_VARS };
198 0         0 my $n = 0;
199 0         0 my $v;
200 0         0 while ($n < @$ident) {
201 0         0 $v = $ident->[$n];
202 0         0 for ($v) { s/^'//; s/'$// };
  0         0  
  0         0  
203 0   0     0 $root = $root->{ $v } ||= { };
204 0         0 $n += 2;
205             }
206             }
207              
208             # does the first element of the identifier have a NAMESPACE
209             # handler defined?
210 3026 100 100     12264 if (@$ident > 2 && ($ns = $self->{ NAMESPACE })) {
211 44         71 my $key = $ident->[0];
212 44         267 $key =~ s/^'(.+)'$/$1/s;
213 44 100       144 if ($ns = $ns->{ $key }) {
214 31         141 return $ns->ident($ident);
215             }
216             }
217             }
218            
219 2997 100 100     14333 if (scalar @$ident <= 2 && ! $ident->[1]) {
220 1635         3074 $ident = $ident->[0];
221             }
222             else {
223 1362         7322 $ident = '[' . join(', ', @$ident) . ']';
224             }
225 2997         12226 return "\$stash->get($ident)";
226             }
227              
228             #------------------------------------------------------------------------
229             # identref(\@ident) \foo.bar(baz)
230             #------------------------------------------------------------------------
231              
232             sub identref {
233 6     6 0 37 my ($self, $ident) = @_;
234 6 50       19 return "''" unless @$ident;
235 6 100 100     37 if (scalar @$ident <= 2 && ! $ident->[1]) {
236 3         9 $ident = $ident->[0];
237             }
238             else {
239 3         22 $ident = '[' . join(', ', @$ident) . ']';
240             }
241 6         27 return "\$stash->getref($ident)";
242             }
243              
244              
245             #------------------------------------------------------------------------
246             # assign(\@ident, $value, $default) foo = bar
247             #------------------------------------------------------------------------
248              
249             sub assign {
250 500     500 0 1190 my ($self, $var, $val, $default) = @_;
251              
252 500 100       1657 if (ref $var) {
253 496 100 66     2889 if (scalar @$var == 2 && ! $var->[1]) {
254 431         1261 $var = $var->[0];
255             }
256             else {
257 65         359 $var = '[' . join(', ', @$var) . ']';
258             }
259             }
260 500 100       1127 $val .= ', 1' if $default;
261 500         4276 return "\$stash->set($var, $val)";
262             }
263              
264              
265             #------------------------------------------------------------------------
266             # args(\@args) foo, bar, baz = qux
267             #------------------------------------------------------------------------
268              
269             sub args {
270 861     861 0 3801 my ($self, $args) = @_;
271 861         1592 my $hash = shift @$args;
272 861 100       2909 push(@$args, '{ ' . join(', ', @$hash) . ' }')
273             if @$hash;
274              
275 861 100       2379 return '0' unless @$args;
276 720         4471 return '[ ' . join(', ', @$args) . ' ]';
277             }
278              
279             #------------------------------------------------------------------------
280             # filenames(\@names)
281             #------------------------------------------------------------------------
282              
283             sub filenames {
284 201     201 0 380 my ($self, $names) = @_;
285 201 100       522 if (@$names > 1) {
286 4         16 $names = '[ ' . join(', ', @$names) . ' ]';
287             }
288             else {
289 197         370 $names = shift @$names;
290             }
291 201         500 return $names;
292             }
293              
294              
295             #------------------------------------------------------------------------
296             # get($expr) [% foo %]
297             #------------------------------------------------------------------------
298              
299             sub get {
300 2069     2069 0 11454 my ($self, $expr) = @_;
301 2069         20235 return "$OUTPUT $expr;";
302             }
303              
304              
305             #------------------------------------------------------------------------
306             # call($expr) [% CALL bar %]
307             #------------------------------------------------------------------------
308              
309             sub call {
310 24     24 0 123 my ($self, $expr) = @_;
311 24         49 $expr .= ';';
312 24         74 return $expr;
313             }
314              
315              
316             #------------------------------------------------------------------------
317             # set(\@setlist) [% foo = bar, baz = qux %]
318             #------------------------------------------------------------------------
319              
320             sub set {
321 401     401 0 3255 my ($self, $setlist) = @_;
322 401         614 my $output;
323 401         2494 while (my ($var, $val) = splice(@$setlist, 0, 2)) {
324 463         1583 $output .= &assign($self, $var, $val) . ";\n";
325             }
326 401         970 chomp $output;
327 401         1380 return $output;
328             }
329              
330              
331             #------------------------------------------------------------------------
332             # default(\@setlist) [% DEFAULT foo = bar, baz = qux %]
333             #------------------------------------------------------------------------
334              
335             sub default {
336 24     24 0 194 my ($self, $setlist) = @_;
337 24         44 my $output;
338 24         129 while (my ($var, $val) = splice(@$setlist, 0, 2)) {
339 31         119 $output .= &assign($self, $var, $val, 1) . ";\n";
340             }
341 24         66 chomp $output;
342 24         83 return $output;
343             }
344              
345              
346             #------------------------------------------------------------------------
347             # insert(\@nameargs) [% INSERT file %]
348             # # => [ [ $file, ... ], \@args ]
349             #------------------------------------------------------------------------
350              
351             sub insert {
352 15     15 0 91 my ($self, $nameargs) = @_;
353 15         37 my ($file, $args) = @$nameargs;
354 15         52 $file = $self->filenames($file);
355 15         67 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 153     153 0 1036 my ($self, $nameargs) = @_;
366 153         346 my ($file, $args) = @$nameargs;
367 153         288 my $hash = shift @$args;
368 153         557 $file = $self->filenames($file);
369 153 100       586 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
370 153         739 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 33     33 0 223 my ($self, $nameargs) = @_;
381 33         78 my ($file, $args) = @$nameargs;
382 33         279 my $hash = shift @$args;
383 33         188 $file = $self->filenames($file);
384 33 100       152 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
385 33         170 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 77     77 0 518 my ($self, $expr, $block, $else) = @_;
399 77 100       281 my @else = $else ? @$else : ();
400 77         140 $else = pop @else;
401 77 50       247 $block = pad($block, 1) if $PRETTY;
402              
403 77         287 my $output = "if ($expr) {\n$block\n}\n";
404              
405 77         209 foreach my $elsif (@else) {
406 8         20 ($expr, $block) = @$elsif;
407 8 50       24 $block = pad($block, 1) if $PRETTY;
408 8         39 $output .= "elsif ($expr) {\n$block\n}\n";
409             }
410 77 100       211 if (defined $else) {
411 33 50       88 $else = pad($else, 1) if $PRETTY;
412 33         93 $output .= "else {\n$else\n}\n";
413             }
414              
415 77         297 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 662 my ($self, $target, $list, $args, $block, $label) = @_;
427 151         291 $args = shift @$args;
428 151 50       476 $args = @$args ? ', { ' . join(', ', @$args) . ' }' : '';
429 151   100     502 $label ||= 'LOOP';
430              
431 151         224 my ($loop_save, $loop_set, $loop_restore, $setiter);
432 151 100       359 if ($target) {
433 139         486 $loop_save = 'eval { $_tt_oldloop = ' . &ident($self, ["'loop'"]) . ' }';
434 139         412 $loop_set = "\$stash->{'$target'} = \$_tt_value";
435 139         249 $loop_restore = "\$stash->set('loop', \$_tt_oldloop)";
436             }
437             else {
438 12         29 $loop_save = '$stash = $context->localise()';
439             # $loop_set = "\$stash->set('import', \$_tt_value) "
440             # . "if ref \$value eq 'HASH'";
441 12         27 $loop_set = "\$stash->get(['import', [\$_tt_value]]) "
442             . "if ref \$_tt_value eq 'HASH'";
443 12         27 $loop_restore = '$stash = $context->delocalise()';
444             }
445 151 50       424 $block = pad($block, 3) if $PRETTY;
446              
447 151         1375 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 29 my ($self, $label) = @_;
485 10   50     28 $label ||= 'LOOP';
486 10         43 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 11     11 0 71 my ($self, $nameargs, $block) = @_;
500 11         29 my ($file, $args) = @$nameargs;
501 11         20 my $hash = shift @$args;
502              
503 11         25 local $" = ', ';
504             # print STDERR "wrapper([@$file], { @$hash })\n";
505              
506 11 100       36 return $self->multi_wrapper($file, $hash, $block)
507             if @$file > 1;
508 9         12 $file = shift @$file;
509              
510 9 50       25 $block = pad($block, 1) if $PRETTY;
511 9         17 push(@$hash, "'content'", '$output');
512 9 50       41 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
513              
514 9         54 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       9 $block = pad($block, 1) if $PRETTY;
529              
530 2         6 push(@$hash, "'content'", '$output');
531 2 50       15 $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
532              
533 2         7 $file = join(', ', reverse @$file);
534             # print STDERR "multi wrapper: $file\n";
535              
536 2         17 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 56 my ($self, $expr, $block, $label) = @_;
559 16 50       209 $block = pad($block, 2) if $PRETTY;
560 16   100     45 $label ||= 'LOOP';
561              
562 16         277 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 108 my ($self, $expr, $case) = @_;
587 20         53 my @case = @$case;
588 20         26 my ($match, $block, $default);
589 20         30 my $caseblock = '';
590              
591 20         32 $default = pop @case;
592              
593 20         39 foreach $case (@case) {
594 31         52 $match = $case->[0];
595 31         37 $block = $case->[1];
596 31 50       67 $block = pad($block, 1) if $PRETTY;
597 31         123 $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       59 $caseblock .= $default
608             if defined $default;
609 20 50       49 $caseblock = pad($caseblock, 2) if $PRETTY;
610              
611 20         118 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 128     128 0 894 my ($self, $block, $catch) = @_;
635 128         385 my @catch = @$catch;
636 128         219 my ($match, $mblock, $default, $final, $n);
637 128         250 my $catchblock = '';
638 128         275 my $handlers = [];
639              
640 128 50       411 $block = pad($block, 2) if $PRETTY;
641 128         369 $final = pop @catch;
642 128 100       773 $final = "# FINAL\n" . ($final ? "$final\n" : '')
643             . 'die $_tt_error if $_tt_error;' . "\n" . '$output;';
644 128 50       361 $final = pad($final, 1) if $PRETTY;
645              
646 128         203 $n = 0;
647 128         310 foreach $catch (@catch) {
648 172   66     627 $match = $catch->[0] || do {
649             $default ||= $catch->[1];
650             next;
651             };
652 64         111 $mblock = $catch->[1];
653 64 50       165 $mblock = pad($mblock, 1) if $PRETTY;
654 64         158 push(@$handlers, "'$match'");
655 64 100       320 $catchblock .= $n++
656             ? "elsif (\$_tt_handler eq '$match') {\n$mblock\n}\n"
657             : "if (\$_tt_handler eq '$match') {\n$mblock\n}\n";
658             }
659 128         304 $catchblock .= "\$_tt_error = 0;";
660 128 50       352 $catchblock = pad($catchblock, 3) if $PRETTY;
661 128 100       448 if ($default) {
662 108 50       299 $default = pad($default, 1) if $PRETTY;
663 108         327 $default = "else {\n # DEFAULT\n$default\n \$_tt_error = '';\n}";
664             }
665             else {
666 20         48 $default = '# NO DEFAULT';
667             }
668 128 50       366 $default = pad($default, 2) if $PRETTY;
669              
670 128         347 $handlers = join(', ', @$handlers);
671 128         1208 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 225 my ($self, $nameargs) = @_;
703 37         80 my ($type, $args) = @$nameargs;
704 37         61 my $hash = shift(@$args);
705 37         67 my $info = shift(@$args);
706 37         63 $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     218 if (! $info) {
    100          
711 5         14 $args = "$type, undef";
712             }
713             elsif (@$hash || @$args) {
714 4         10 local $" = ', ';
715 4         6 my $i = 0;
716 8         39 $args = "$type, { args => [ "
717             . join(', ', $info, @$args)
718             . ' ], '
719             . join(', ',
720 4         24 (map { "'" . $i++ . "' => $_" } ($info, @$args)),
721             @$hash)
722             . ' }';
723             }
724             else {
725 28         86 $args = "$type, $info";
726             }
727            
728 37         161 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 18 return "\$context->throw('return', '', \\\$output);";
758             }
759              
760             #------------------------------------------------------------------------
761             # stop() [% STOP %]
762             #------------------------------------------------------------------------
763              
764             sub stop {
765 4     4 0 27 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 208     208 0 1620 my ($self, $lnameargs) = @_;
776 208         544 my ($file, $args, $alias) = @$lnameargs;
777 208         397 $file = shift @$file; # same production rule as INCLUDE
778 208   66     1115 $alias ||= $file;
779 208         795 $args = &args($self, $args);
780 208 100       779 $file .= ", $args" if $args;
781             # my $set = &assign($self, $alias, '$plugin');
782 208         1425 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 107 my ($self, $nameargs, $block, $defblocks) = @_;
794 30         70 my ($name, $args) = @$nameargs;
795 30         74 my $hash = shift @$args;
796 30         65 $name = shift @$name; # same production rule as INCLUDE
797 30 50       108 $block = pad($block, 1) if $PRETTY;
798              
799 30 100       100 if (%$defblocks) {
800 16         70 $defblocks = join(",\n", map { "'$_' => $defblocks->{ $_ }" }
  21         158  
801             keys %$defblocks);
802 16 50       59 $defblocks = pad($defblocks, 1) if $PRETTY;
803 16         75 $defblocks = "{\n$defblocks\n}";
804 16         58 push(@$hash, "'blocks'", $defblocks);
805             }
806 30 100       203 $hash = @$hash ? '{ ' . join(', ', @$hash) . ' }' : '';
807              
808 30         235 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 11     11 0 122 my ($self, $block) = @_;
833 11 50       36 $block = pad($block, 1) if $PRETTY;
834              
835 11         71 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 33 my $self = shift;
868 4         13 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 22 my ($self, $block, $line) = @_;
881 2         8 for ($block) {
882 2         4 s/^\n+//;
883 2         12 s/\n+$//;
884             }
885 2 50       7 $block = pad($block, 1) if $PRETTY;
886 2 50       9 $line = $line ? " (starting line $line)" : '';
887              
888 2         11 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 128     128 0 750 my ($self, $lnameargs, $block) = @_;
903 128         277 my ($name, $args, $alias) = @$lnameargs;
904 128         238 $name = shift @$name;
905 128         359 $args = &args($self, $args);
906 128 50       1441 $args = $args ? "$args, $alias" : ", undef, $alias"
    100          
907             if $alias;
908 128 100       347 $name .= ", $args" if $args;
909 128 50       1112 $block = pad($block, 1) if $PRETTY;
910            
911 128         661 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 10     10 0 67 my ($self, $name, $block) = @_;
933              
934 10 50       38 if (ref $name) {
935 10 50 33     68 if (scalar @$name == 2 && ! $name->[1]) {
936 10         26 $name = $name->[0];
937             }
938             else {
939 0         0 $name = '[' . join(', ', @$name) . ']';
940             }
941             }
942 10 50       31 $block = pad($block, 1) if $PRETTY;
943              
944 10         64 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 66 my ($self, $ident, $block, $args) = @_;
963 10 50       35 $block = pad($block, 2) if $PRETTY;
964              
965 10 100       21 if ($args) {
966 3         10 my $nargs = scalar @$args;
967 3         7 $args = join(', ', map { "'$_'" } @$args);
  3         16  
968 3 50       16 $args = $nargs > 1
969             ? "\@_tt_args{ $args } = splice(\@_, 0, $nargs)"
970             : "\$_tt_args{ $args } = shift";
971              
972 3         27 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         51 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 149 my ($self, $nameargs) = @_;
1017 15         25 my ($file, $args) = @$nameargs;
1018 15         19 my $hash = shift @$args;
1019 15         34 $args = join(', ', @$file, @$args);
1020 15 100       47 $args .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
1021 15         67 return "$OUTPUT \$context->debugging($args); ## DEBUG ##";
1022             }
1023              
1024              
1025             1;
1026              
1027             __END__