
Template::Parser::Greedy - reader/writer friendly chomping for TT2 templates

use Template;
use Template::Parser::Greedy;
my $parser = Template::Parser::Greedy->new();
my $config = {
PARSER => $parser,
INCLUDE_PATH => ...
};
my $template = Template->new($config);
$template->process(...) || die $template->error();

It's easy to write readable templates in Template::Toolkit, and it's easy to exercise fine-grained control over the output of Template Toolkit templates. Achieving both at the same time, however, can be tricky given the default parser's whitespace chomping rules, which consume no more than one newline character on either side of a directive.
This means that template authors optimizing for readability (and writability) may be obliged to compromise the indentation and spacing of the output and vice versa.
This module allows templates to be laid out in a readable way, while at the same time enhancing control over the spacing of the generated output. It does this by providing two new options, CHOMP_GREEDY and CHOMP_COALESCE, and their corresponding directive modifiers, ~ and ^.
In addition, a new modifier, =, for the old CHOMP_COLLAPSE option has been added.
This module is a drop-in replacement for Template::Parser, and is fully backwards compatible if the original set of chomp options or modifiers are used. The only difference is in the default values assigned for PRE_CHOMP and POST_CHOMP. Template::Parser defaults to not chomping, while Template::Parser::Greedy defaults to chomping all contiguous whitespace characters. This behaviour can be specified explicitly by passing a value of 3, or by importing the symbolic constant CHOMP_GREEDY e.g,
use Template::Parser::Greedy qw(CHOMP_GREEDY);
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => CHOMP_GREEDY,
POST_CHOMP => 0
);
In addition, Template::Parser::Greedy allows all old and new chomp options to be specified by means of the corresponding directive modifier. Thus:
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => '+',
POST_CHOMP => '='
);
Corresponds to
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => CHOMP_NONE,
POST_CHOMP => 2
);
And:
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => '~',
POST_CHOMP => '^'
);
is equivalent to:
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => CHOMP_GREEDY,
POST_CHOMP => 4
);
Greedy chomping can be relaxed or revoked on a per-directive basis in templates that are greedy by default. Likewise, greedy chomping can be selectively enabled in non-greedy templates by using the ~ and ^ modifiers.
e.g.
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => 2,
POST_CHOMP => 0
);
my $template = Template->new({ PARSER => $parser });
And, in the template:
[BLOCK foo %]
[%- IF 1 ~%]
bar
[%~ END +%]
[% END %]
In this example, the ~ modifier consumes all of the whitespace around the embedded text, and is thus equivalent to:
[%- IF 1 %]bar[% END +%]
The + modifier at the end of the IF block turns on CHOMP_NONE for the suffixed whitespace, which is therefore not chomped; and the - modifier at the beginning of the IF performs a CHOMP_COLLAPSE chomp, which collapses the indentation and one newline to a single space, but leaves the whitespace before that intact.
Template::Parser does not provide a directive modifier for CHOMP_COLLAPSE, but it can be enabled in Template::Parser::Greedy templates by using =. e.g.
[% IF 1 =%]
...
[%= END %]
The greedy version of this modifier is ^. This can also be set globally by supplying a PRE/POST_CHOMP value of 4, which is also available as the symbolic constant CHOMP_COALESCE.
use Template::Constants (:chomp);
use Template::Parser::Greedy qw(CHOMP_COALESCE);
my $parser = Template::Parser::Greedy->new(
PRE_CHOMP => CHOMP_COLLAPSE,
POST_CHOMP => CHOMP_COALESCE
);
If both CHOMP_GREEDY and CHOMP_COALESCE are needed, they can be imported by using the :all tag:
use Template::Parser::Greedy qw(:all);

As with the default parser, any whitespace inside the preceding or following text is preserved, so boilerplate only needs to concern itself with its surrounding whitespace.
This leaves indentation and newlines under the explicit control of the template author, by any of the mechanisms available in the Template technician's toolkit e.g. by using explicit newline and indentation directives:
[% nl = "\n" %]
[% BLOCK foo %] [%# params: bar, indent %]
[% outer = tab(indent) %]
[% inner = tab(add(indent, 1)) %]
[% outer %]
<foo>
[% FOR baz IN bar %]
[% nl %] [% inner %]
<bar baz="[% baz %]" />
[% END %] [% nl %] [% outer %]
</foo>
[% END %]
Or by selectively turning off left and/or right chomping:
[% IF 1 +%]
------------------------------------
| alpha | beta | gamma | vlissides |
------------------------------------
| foo | bar | baz | quux |
------------------------------------
[%+ END %]
Unlike their non-greedy counterparts, the CHOMP_GREEDY and CHOMP_COALESCE options and directives happily digest carriage returns (along with [\n\f\t ]), so they are less likely to do the wrong thing on non-Unix platforms.


1.00

chocolateboy <chocolate.boy@email.com>

Copyright (C) 2006 by chocolateboy
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.