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   4322 use strict;
  80         172  
  80         2915  
30 80     80   416 use warnings;
  80         159  
  80         2213  
31 80     80   1643 use base 'Template::Base';
  80         391  
  80         6062  
32 80     80   457 use Template::Constants;
  80         309  
  80         3661  
33 80     80   522 use Template::Exception;
  80         163  
  80         467310  
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   528 my ($self, $config) = @_;
44 133         779 $self->{ NAMESPACE } = $config->{ NAMESPACE };
45 133         1521 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 1441     1441 0 7555 my ($self, $block) = @_;
74 1441 50       4424 $block = pad($block, 2) if $PRETTY;
75              
76 1441 100       7857 return "sub { return '' }" unless $block =~ /\S/;
77              
78 1431         9561 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 2132     2132 0 10167 my ($self, $block) = @_;
134 2132 100       3342 return join("\n", @{ $block || [] });
  2132         14450  
135             }
136              
137              
138             #------------------------------------------------------------------------
139             # textblock($text)
140             #------------------------------------------------------------------------
141              
142             sub textblock {
143 3119     3119 0 15040 my ($self, $text) = @_;
144 3119         8436 return "$OUTPUT " . &text($self, $text) . ';';
145             }
146              
147              
148             #------------------------------------------------------------------------
149             # text($text)
150             #------------------------------------------------------------------------
151              
152             sub text {
153 3375     3375 0 11017 my ($self, $text) = @_;
154 3375         7620 for ($text) {
155 3375         8751 s/(["\$\@\\])/\\$1/g;
156 3375         13376 s/\n/\\n/g;
157             }
158 3375         16900 return '"' . $text . '"';
159             }
160              
161              
162             #------------------------------------------------------------------------
163             # quoted(\@items) "foo$bar"
164             #------------------------------------------------------------------------
165              
166             sub quoted {
167 171     171 0 974 my ($self, $items) = @_;
168 171 50       584 return '' unless @$items;
169 171 100       682 return ("('' . " . $items->[0] . ')') if scalar @$items == 1;
170 120         684 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 3032     3032 0 15137 my ($self, $ident) = @_;
183 3032 50       7131 return "''" unless @$ident;
184 3032         3460 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 3032 100       13682 if (ref $self) {
195             # trace variable usage
196 3030 50       7595 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 3030 100 100     12447 if (@$ident > 2 && ($ns = $self->{ NAMESPACE })) {
211 44         82 my $key = $ident->[0];
212 44         264 $key =~ s/^'(.+)'$/$1/s;
213 44 100       155 if ($ns = $ns->{ $key }) {
214 31         135 return $ns->ident($ident);
215             }
216             }
217             }
218            
219 3001 100 100     13308 if (scalar @$ident <= 2 && ! $ident->[1]) {
220 1638         3026 $ident = $ident->[0];
221             }
222             else {
223 1363         6370 $ident = '[' . join(', ', @$ident) . ']';
224             }
225 3001         11949 return "\$stash->get($ident)";
226             }
227              
228             #------------------------------------------------------------------------
229             # identref(\@ident) \foo.bar(baz)
230             #------------------------------------------------------------------------
231              
232             sub identref {
233 6     6 0 38 my ($self, $ident) = @_;
234 6 50       21 return "''" unless @$ident;
235 6 100 100     34 if (scalar @$ident <= 2 && ! $ident->[1]) {
236 3         9 $ident = $ident->[0];
237             }
238             else {
239 3         17 $ident = '[' . join(', ', @$ident) . ']';
240             }
241 6         29 return "\$stash->getref($ident)";
242             }
243              
244              
245             #------------------------------------------------------------------------
246             # assign(\@ident, $value, $default) foo = bar
247             #------------------------------------------------------------------------
248              
249             sub assign {
250 501     501 0 1175 my ($self, $var, $val, $default) = @_;
251              
252 501 100       1461 if (ref $var) {
253 497 100 66     2749 if (scalar @$var == 2 && ! $var->[1]) {
254 432         920 $var = $var->[0];
255             }
256             else {
257 65         366 $var = '[' . join(', ', @$var) . ']';
258             }
259             }
260 501 100       1157 $val .= ', 1' if $default;
261 501         3814 return "\$stash->set($var, $val)";
262             }
263              
264              
265             #------------------------------------------------------------------------
266             # args(\@args) foo, bar, baz = qux
267             #------------------------------------------------------------------------
268              
269             sub args {
270 869     869 0 3412 my ($self, $args) = @_;
271 869         1445 my $hash = shift @$args;
272 869 100       2941 push(@$args, '{ ' . join(', ', @$hash) . ' }')
273             if @$hash;
274              
275 869 100       2211 return '0' unless @$args;
276 722         3928 return '[ ' . join(', ', @$args) . ' ]';
277             }
278              
279             #------------------------------------------------------------------------
280             # filenames(\@names)
281             #------------------------------------------------------------------------
282              
283             sub filenames {
284 201     201 0 358 my ($self, $names) = @_;
285 201 100       514 if (@$names > 1) {
286 4         26 $names = '[ ' . join(', ', @$names) . ' ]';
287             }
288             else {
289 197         357 $names = shift @$names;
290             }
291 201         472 return $names;
292             }
293              
294              
295             #------------------------------------------------------------------------
296             # get($expr) [% foo %]
297             #------------------------------------------------------------------------
298              
299             sub get {
300 2079     2079 0 10525 my ($self, $expr) = @_;
301 2079         8638 return "$OUTPUT $expr;";
302             }
303              
304              
305             #------------------------------------------------------------------------
306             # call($expr) [% CALL bar %]
307             #------------------------------------------------------------------------
308              
309             sub call {
310 24     24 0 122 my ($self, $expr) = @_;
311 24         48 $expr .= ';';
312 24         68 return $expr;
313             }
314              
315              
316             #------------------------------------------------------------------------
317             # set(\@setlist) [% foo = bar, baz = qux %]
318             #------------------------------------------------------------------------
319              
320             sub set {
321 402     402 0 2551 my ($self, $setlist) = @_;
322 402         630 my $output;
323 402         1893 while (my ($var, $val) = splice(@$setlist, 0, 2)) {
324 464         1628 $output .= &assign($self, $var, $val) . ";\n";
325             }
326 402         993 chomp $output;
327 402         1554 return $output;
328             }
329              
330              
331             #------------------------------------------------------------------------
332             # default(\@setlist) [% DEFAULT foo = bar, baz = qux %]
333             #------------------------------------------------------------------------
334              
335             sub default {
336 24     24 0 192 my ($self, $setlist) = @_;
337 24         44 my $output;
338 24         128 while (my ($var, $val) = splice(@$setlist, 0, 2)) {
339 31         106 $output .= &assign($self, $var, $val, 1) . ";\n";
340             }
341 24         67 chomp $output;
342 24         81 return $output;
343             }
344              
345              
346             #------------------------------------------------------------------------
347             # insert(\@nameargs) [% INSERT file %]
348             # # => [ [ $file, ... ], \@args ]
349             #------------------------------------------------------------------------
350              
351             sub insert {
352 15     15 0 101 my ($self, $nameargs) = @_;
353 15         32 my ($file, $args) = @$nameargs;
354 15         53 $file = $self->filenames($file);
355 15         64 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 976 my ($self, $nameargs) = @_;
366 153         334 my ($file, $args) = @$nameargs;
367 153         372 my $hash = shift @$args;
368 153         562 $file = $self->filenames($file);
369 153 100       559 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
370 153         758 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 231 my ($self, $nameargs) = @_;
381 33         91 my ($file, $args) = @$nameargs;
382 33         73 my $hash = shift @$args;
383 33         141 $file = $self->filenames($file);
384 33 100       134 $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 78     78 0 548 my ($self, $expr, $block, $else) = @_;
399 78 100       297 my @else = $else ? @$else : ();
400 78         156 $else = pop @else;
401 78 50       278 $block = pad($block, 1) if $PRETTY;
402              
403 78         370 my $output = "if ($expr) {\n$block\n}\n";
404              
405 78         223 foreach my $elsif (@else) {
406 8         21 ($expr, $block) = @$elsif;
407 8 50       59 $block = pad($block, 1) if $PRETTY;
408 8         38 $output .= "elsif ($expr) {\n$block\n}\n";
409             }
410 78 100       278 if (defined $else) {
411 33 50       95 $else = pad($else, 1) if $PRETTY;
412 33         123 $output .= "else {\n$else\n}\n";
413             }
414              
415 78         302 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 655 my ($self, $target, $list, $args, $block, $label) = @_;
427 151         319 $args = shift @$args;
428 151 50       700 $args = @$args ? ', { ' . join(', ', @$args) . ' }' : '';
429 151   100     531 $label ||= 'LOOP';
430              
431 151         251 my ($loop_save, $loop_set, $loop_restore, $setiter);
432 151 100       463 if ($target) {
433 139         554 $loop_save = 'eval { $_tt_oldloop = ' . &ident($self, ["'loop'"]) . ' }';
434 139         520 $loop_set = "\$stash->{'$target'} = \$_tt_value";
435 139         259 $loop_restore = "\$stash->set('loop', \$_tt_oldloop)";
436             }
437             else {
438 12         27 $loop_save = '$stash = $context->localise()';
439             # $loop_set = "\$stash->set('import', \$_tt_value) "
440             # . "if ref \$value eq 'HASH'";
441 12         28 $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       479 $block = pad($block, 3) if $PRETTY;
446              
447 151         1453 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 27 my ($self, $label) = @_;
485 10   50     31 $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 73 my ($self, $nameargs, $block) = @_;
500 11         138 my ($file, $args) = @$nameargs;
501 11         18 my $hash = shift @$args;
502              
503 11         27 local $" = ', ';
504             # print STDERR "wrapper([@$file], { @$hash })\n";
505              
506 11 100       41 return $self->multi_wrapper($file, $hash, $block)
507             if @$file > 1;
508 9         20 $file = shift @$file;
509              
510 9 50       24 $block = pad($block, 1) if $PRETTY;
511 9         21 push(@$hash, "'content'", '$output');
512 9 50       45 $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
513              
514 9         57 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 7 my ($self, $file, $hash, $block) = @_;
528 2 50       11 $block = pad($block, 1) if $PRETTY;
529              
530 2         9 push(@$hash, "'content'", '$output');
531 2 50       14 $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
532              
533 2         9 $file = join(', ', reverse @$file);
534             # print STDERR "multi wrapper: $file\n";
535              
536 2         19 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 55 my ($self, $expr, $block, $label) = @_;
559 16 50       50 $block = pad($block, 2) if $PRETTY;
560 16   100     58 $label ||= 'LOOP';
561              
562 16         133 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 133 my ($self, $expr, $case) = @_;
587 20         50 my @case = @$case;
588 20         33 my ($match, $block, $default);
589 20         36 my $caseblock = '';
590              
591 20         43 $default = pop @case;
592              
593 20         44 foreach $case (@case) {
594 31         55 $match = $case->[0];
595 31         49 $block = $case->[1];
596 31 50       106 $block = pad($block, 1) if $PRETTY;
597 31         117 $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       61 $caseblock .= $default
608             if defined $default;
609 20 50       54 $caseblock = pad($caseblock, 2) if $PRETTY;
610              
611 20         119 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 889 my ($self, $block, $catch) = @_;
635 128         356 my @catch = @$catch;
636 128         233 my ($match, $mblock, $default, $final, $n);
637 128         238 my $catchblock = '';
638 128         273 my $handlers = [];
639              
640 128 50       583 $block = pad($block, 2) if $PRETTY;
641 128         222 $final = pop @catch;
642 128 100       612 $final = "# FINAL\n" . ($final ? "$final\n" : '')
643             . 'die $_tt_error if $_tt_error;' . "\n" . '$output;';
644 128 50       541 $final = pad($final, 1) if $PRETTY;
645              
646 128         198 $n = 0;
647 128         310 foreach $catch (@catch) {
648 172   66     603 $match = $catch->[0] || do {
649             $default ||= $catch->[1];
650             next;
651             };
652 64         141 $mblock = $catch->[1];
653 64 50       153 $mblock = pad($mblock, 1) if $PRETTY;
654 64         155 push(@$handlers, "'$match'");
655 64 100       278 $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         276 $catchblock .= "\$_tt_error = 0;";
660 128 50       358 $catchblock = pad($catchblock, 3) if $PRETTY;
661 128 100       292 if ($default) {
662 108 50       262 $default = pad($default, 1) if $PRETTY;
663 108         353 $default = "else {\n # DEFAULT\n$default\n \$_tt_error = '';\n}";
664             }
665             else {
666 20         39 $default = '# NO DEFAULT';
667             }
668 128 50       341 $default = pad($default, 2) if $PRETTY;
669              
670 128         311 $handlers = join(', ', @$handlers);
671 128         1510 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 242 my ($self, $nameargs) = @_;
703 37         84 my ($type, $args) = @$nameargs;
704 37         70 my $hash = shift(@$args);
705 37         67 my $info = shift(@$args);
706 37         60 $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     223 if (! $info) {
    100          
711 5         11 $args = "$type, undef";
712             }
713             elsif (@$hash || @$args) {
714 4         9 local $" = ', ';
715 4         6 my $i = 0;
716 8         41 $args = "$type, { args => [ "
717             . join(', ', $info, @$args)
718             . ' ], '
719             . join(', ',
720 4         23 (map { "'" . $i++ . "' => $_" } ($info, @$args)),
721             @$hash)
722             . ' }';
723             }
724             else {
725 28         83 $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 19 return "\$context->throw('return', '', \\\$output);";
758             }
759              
760             #------------------------------------------------------------------------
761             # stop() [% STOP %]
762             #------------------------------------------------------------------------
763              
764             sub stop {
765 4     4 0 24 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 2341 my ($self, $lnameargs) = @_;
776 209         582 my ($file, $args, $alias) = @$lnameargs;
777 209         424 $file = shift @$file; # same production rule as INCLUDE
778 209   66     1056 $alias ||= $file;
779 209         753 $args = &args($self, $args);
780 209 100       833 $file .= ", $args" if $args;
781             # my $set = &assign($self, $alias, '$plugin');
782 209         1210 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 74 my ($self, $nameargs, $block, $defblocks) = @_;
794 30         87 my ($name, $args) = @$nameargs;
795 30         77 my $hash = shift @$args;
796 30         75 $name = shift @$name; # same production rule as INCLUDE
797 30 50       88 $block = pad($block, 1) if $PRETTY;
798              
799 30 100       97 if (%$defblocks) {
800 16         56 $defblocks = join(",\n", map { "'$_' => $defblocks->{ $_ }" }
  21         128  
801             keys %$defblocks);
802 16 50       62 $defblocks = pad($defblocks, 1) if $PRETTY;
803 16         61 $defblocks = "{\n$defblocks\n}";
804 16         51 push(@$hash, "'blocks'", $defblocks);
805             }
806 30 100       162 $hash = @$hash ? '{ ' . join(', ', @$hash) . ' }' : '';
807              
808 30         195 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 116 my ($self, $block) = @_;
833 11 50       36 $block = pad($block, 1) if $PRETTY;
834              
835 11         69 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 32 my $self = shift;
868 4         11 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         6 for ($block) {
882 2         5 s/^\n+//;
883 2         11 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 134     134 0 1046 my ($self, $lnameargs, $block) = @_;
903 134         316 my ($name, $args, $alias) = @$lnameargs;
904 134         259 $name = shift @$name;
905 134         402 $args = &args($self, $args);
906 134 50       343 $args = $args ? "$args, $alias" : ", undef, $alias"
    100          
907             if $alias;
908 134 100       370 $name .= ", $args" if $args;
909 134 50       310 $block = pad($block, 1) if $PRETTY;
910            
911 134         700 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 66 my ($self, $name, $block) = @_;
933              
934 10 50       36 if (ref $name) {
935 10 50 33     59 if (scalar @$name == 2 && ! $name->[1]) {
936 10         25 $name = $name->[0];
937             }
938             else {
939 0         0 $name = '[' . join(', ', @$name) . ']';
940             }
941             }
942 10 50       29 $block = pad($block, 1) if $PRETTY;
943              
944 10         60 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       27 $block = pad($block, 2) if $PRETTY;
964              
965 10 100       19 if ($args) {
966 3         5 my $nargs = scalar @$args;
967 3         7 $args = join(', ', map { "'$_'" } @$args);
  3         10  
968 3 50       11 $args = $nargs > 1
969             ? "\@_tt_args{ $args } = splice(\@_, 0, $nargs)"
970             : "\$_tt_args{ $args } = shift";
971              
972 3         18 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         46 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 150 my ($self, $nameargs) = @_;
1017 15         24 my ($file, $args) = @$nameargs;
1018 15         16 my $hash = shift @$args;
1019 15         32 $args = join(', ', @$file, @$args);
1020 15 100       50 $args .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
1021 15         64 return "$OUTPUT \$context->debugging($args); ## DEBUG ##";
1022             }
1023              
1024              
1025             1;
1026              
1027             __END__