There is a new module that has just been released to CPAN.
I don't know if it is of interest to very many, but essentially it allows for
using the CGI::Ex::Template recursive grammar engine to parse documents, but
after that, to run them on the existing Template system. It takes
CGI::Ex::Template's AST and translates it into a Template::Document document.
At the very least it will allow for people to play around with TT3 syntax
running on the TT2 engine.
Hopefully it will be more useful than that and will provide useful working
code for getting the real TT3 out sooner. It also allows for introducing the
DUMP and CONFIG directives without having to modify the Template::Grammar and
worry about all of the ramifications that that carries.
Note that this isn't a "toy status" module. It is a first release and should
obviously be tested in your installations before rolling out. But it handles
the full Template test suite as well as the full CGI::Ex::Template test suite
(there are a few exceptions dealing with cases where TT2 can't handle some
parsing and expects that the parsing fails or expects particular error
messages - these are listed in the perldoc under the section called "TT2
TESTS THAT FAIL"). You will also want to pay attention to the section
called "TT2 SYNTAX THAT WILL BREAK" for the few rare cases of TT2 syntax that
will not work directly on TT3.
The code was uploaded to cpan an hour ago. Until it shows up on mirrors you
can read the included Perldoc below.
Paul
Perldoc from Template::Parser::CET
NAME
Template::Parser::CET - CGI::Ex::Template based parser for the TT2
engine
SYNOPSIS
use Template;
use Template::Parser::CET;
my $t = Template->new(
PARSER => Template::Parser->new
);
# you can override all instances of TT
# by any of the following methods
use Template::Parser::CET activate => 1;
# OR
use Template::Parser::CET;
Template::Parser::CET->activate;
# OR
use Template::Config;
$Template::Config::PARSER = 'Template::Parser::CET';
my $t = Template->new;
DESCRIPTION
Template::Parser::CET provides much or most of the TT3 syntax and runs
on the current TT2 engine.
CGI::Ex::Template (CET) provides a fast implementation of TT2 and TT3.
There are some cases where Template::Toolkit is faster. There are also
some cases where shops have custom providers, or custom stashes that
require the use of the current TT2 engine. In these cases,
Template::Parser::CET provides the best of both worlds - offering TT2
AND TT3 syntax and running on the existing platform making use of all of
your current work (In many cases CET should be able to do this anyway).
This module may eventually be made obsolete when the final real
Template::Toolkit 3 engine by Andy Wardley is released. But that would
only be a good thing. If the TT3 engine doesn't provide full backward
compatibility this module will.
CET has provided TT3 features since Spring of 2006 but there has been
little reported uptake. The TT3 features/extended syntax are very
compelling. For various reasons people chose not to use CET. Now people
can use TT2 and get the features of TT3 (through CET) today.
Hopefully Template::Parser::CET and CGI::Ex::Template can be used in the
same spirit as Pugs is used for Perl 6. All of the code from CET and
Template::Parser::CET are free for use in TT3.
SPEED
All speed is relative and varies tremendously depending upon the size
and content of your template.
Template::Parser::CET generally compiles documents at the same speed as
Template::Parser and Template::Grammar. CGI::Ex::Template compiles
documents to its AST (abastract syntax tree) very quickly, but
Template::Paser::CET then has to emit a TT2 style compiled
Template::Document perl document. So even though CGI::Ex::Template has a
speed advantage, the advantage is lost in Template::Parser::CET.
If you use compiled in memory templates - they will execute as quickly
as the normal TT2 documents. In all other cases Template::Parser::CET
will prepare the documents at about the same speed.
FEATURES
So what exactly are the features and syntax that Template::Parser::CET
provides? The following is a list of most of the features that will be
in TT3 and are in Template::Parser::CET. All of the listed features are
in addition to those provided natively by Template::Toolkit.
Grammar
CGI::Ex::Template provides Template::Parser::CET with a recursive
grammar. This provides a range of benefits including speed, better
error reporting, more consistent syntax, more possibilities for
extending the grammar.
Numerical hash keys work
[% a = {1 => 2} %]
All hash key parsing is a little more sane. Not entirely more since
CET needs to be backwards compatible.
Quoted hash key interpolation is fine
[% a = {"$foo" => 1} %]
Multiple ranges in same array constructor
[% a = [1..10, 21..30] %]
Constructor types can call virtual methods. (TT3)
[% a = [1..10].reverse %]
[% "$foo".length %]
[% 123.length %] # = 3
[% 123.4.length %] # = 5
[% -123.4.length %] # = -5 ("." binds more tightly than "-")
[% (a ~ b).length %]
[% "hi".repeat(3) %] # = hihihi
[% {a => b}.size %] # = 1
The "${" and "}" variable interpolators can contain expressions, not
just variables.
[% [0..10].${ 1 + 2 } %] # = 4
[% {ab => 'AB'}.${ 'a' ~ 'b' } %] # = AB
[% color = qw/Red Blue/; FOR [1..4] ; color.${ loop.index %
color.size } ; END %]
# = RedBlueRedBlue
You can use regular expression quoting.
[% "foo".match( /(F\w+)/i ).0 %] # = foo
[% a = /a b c . e/xs %]
Tags can be nested.
[% f = "[% (1 + 2) %]" %][% f | eval %] # = 3
Reserved names are less reserved.
[% GET GET %] # gets the variable named "GET"
[% GET $GET %] # gets the variable who's name is stored in "GET"
Pipe "|" can be used anywhere dot "." can be and means to call the
virtual method.
[% a = {size => "foo"} %][% a.size %] # = foo
[% a = {size => "foo"} %][% a|size %] # = 1 (size of hash)
Added V2PIPE configuration item
Restores the behavior of the pipe operator to be compatible with
TT2.
With V2PIPE = 1
[% PROCESS a | repeat(2) %] # = value of block or file a repeated
twice
With V2PIPE = 0 (default)
[% PROCESS a | repeat(2) %] # = process block or file named a ~ a
Added "fmt" scalar, list, and hash virtual methods which work similar to
the Perl 6 methods.
[% text.fmt("%s") %]
[% list.fmt("%s", ", ") %]
[% hash.fmt("%s => %s", "\n") %]
Added "pick" list virtual method which picks a random value.
[% ["a".."z"].pick(8).join %]
Added "rand" text virtual method which gives a random number between 0
and the item.
[% 20.rand %]
Added "0" text virtual method which returns the item itself. This blurs
the line between list and text items.
[% a = "20" %][% a.0 IF a.size %]
Added "int" text virtual method which returns the integer portion of a
value.
[% "2.3343".int %]
Whitespace is less meaningful.
[% 2-1 %] # = 1 (fails in TT2)
Added pow operator.
[% 2 ** 3 %] [% 2 pow 3 %] # = 8 8
Added self modifiers (+=, -=, *=, /=, %=, **=, ~=).
[% a = 2; a *= 3 ; a %] # = 6
[% a = 2; (a *= 3) ; a %] # = 66
Added pre and post increment and decrement (++ --).
[% ++a ; ++a %] # = 12
[% a-- ; a-- %] # = 0-1
Added qw// contructor.
[% a = qw(a b c); a.1 %] # = b
[% qw/a b c/.2 %] # = c
Added regex contructor.
[% "FOO".match(/(foo)/i).0 %] # = FOO
[% a = /(foo)/i; "FOO".match(a).0 %] # = FOO
Allow for scientific notation. (TT3)
[% a = 1.2e-20 %]
[% 123.fmt('%.3e') %] # = 1.230e+02
Allow for hexidecimal input.
[% a = 0xff0000 %][% a %] # = 16711680
[% a = 0xff2 / 0xd; a.fmt('%x') %] # = 13a
Post operative directives can be nested.
Andy Wardley calls this side-by-side effect notation.
[% one IF two IF three %]
same as
[% IF three %][% IF two %][% one %][% END %][% END %]
[% a = [[1..3], [5..7]] %][% i FOREACH i = j FOREACH j = a %] # =
123567
Semi-colons on directives in the same tag are optional.
[% SET a = 1
GET a
%]
[% FOREACH i = [1 .. 10]
i
END %]
Note: a semi-colon is still required in front of any block directive
that can be used as a post-operative directive.
[% 1 IF 0
2 %] # prints 2
[% 1; IF 0
2
END %] # prints 1
Added a DUMP directive.
Used for Data::Dumpering the passed variable or expression.
[% DUMP a.a %] # dumps contents of a.a
[% DUMP %] # dumps entire stash
The Dumping is configurable via a DUMP configuration item.
Added CONFIG directive.
[% CONFIG
ANYCASE => 1
PRE_CHOMP => '-'
%]
There is better line information
When debug dirs is on, directives on different lines separated by
colons show the line they are on rather than a general line range.
Parse errors actually know what line and character they occured at
and tell you about it.
USING Template::Parser::CET
There are several ways to get TT to use Template::Parser::CET.
Pass in object during configuration.
use Template;
use Template::Parser::CET;
my $t = Template->new(
PARSER => Template::Parser::CET->new(\%config),
);
Override the current program (option 1).
use Template::Parser::CET activate => 1;
Override the current program (option 2).
use Template::Parser::CET;
Template::Parser::CET->activate;
You can then deactivate if youy want to use the normal parser by
using:
Template::Parser::CET->deactivate;
Override the current program (option 3).
use Template::Parser::CET;
use Template::Config;
local $Template::Config::PARSER = 'Template:Parser::CET';
Override all default instances.
Modify the $PARSER value in Template/Config.pm
to be 'Template::Parser::CET' rather than 'Template::Parser'.
DOCUMENTATION
Template::Toolkit and CGI::Ex::Template already cover everything that
would be covered here. If you are running Template::Parser::CET then you
already have both Template::Toolkit and CGI::Ex::Template installed.
Please refer to their documentation for complete configuration and
syntax examples.
For any of the items in the FEATURES section you will need to refer to
the CGI::Ex::Template documentation.
BUGS / TODO
* Template::Parser::CET is as non-invasive as it can be. It does no
modification to the existing TT2 install. In order to provide
features such as inline filters, self modifying operators, pre and
post decrement and increment, and CONFIG and DUMP directive support,
the abstraction to Template::Directive was broken. This means that
projects such as Jemplate can't use these extended features directly
(but projects such as Jemplate could write faster smaller templates
if they used CGI::Ex::Template's compiled AST directly).
* Cleanup compiled document output.
* Add more line numbers to the compiled output.
* Actually add the VObjects to the compile phase to get the compile
time speed benefit.
* Override filter generation code to allow for fall back to the
SCALAR_OPS methods if a filter can't be found by the passed name.
TT2 SYNTAX THAT WILL BREAK
Pipe (FILTER alias) operators in ambiguous places.
Under TT2 the following line:
[% BLOCK a %]b is [% b %][% END %][% PROCESS a b => 234 |
repeat(2) %]
Would print:
b is 234b is 234
Under CET and TT3 that line will print
b is 234234
This is because the "|" has been used to allow for filter operations
to be used inline on variables and also to call vmethods.
The configuration option V2PIPE can be used to restore the old
behavior. When V2PIPE is set to true (default is false), then CET
will parse the block the same as TT2. When false it will parse the
same as CET or TT3.
You can use the CONFIG directive to set the option around some
chunks of code that use the old syntax.
[% CONFIG V2PIPE 1 -%]
[% BLOCK a %]b is [% b %][% END %][% PROCESS a b => 234 |
repeat(2) %]
[%- CONFIG V2PIPE 0 %]
Would print
b is 234b is 234
Inline comments that end with the tag and not a newline.
Because of the way the TT2 engine matches tags, the following works
in TT2:
[% a # GET THE value of a %]
Because CET is recursive in nature, the closing tag has not been
matched by the time the comment is removed. You will get a parse
error saying not sure how to handle the tag.
Simply change the previous example to the following:
[% a # GET THE value of a
%]
All other commenting constructs parse just fine.
The qw variable parse error
If your template had a variable named qw - there will most likely be
a parse error.
In TT2 there was no qw() construct but there is in CET and TT3.
[% a = qw %] Works fine in TT2 but is a parse error in
TT3
[% a = qw(Foo Bar) %] Works fine in TT3 but is a parse error in
TT2
TT2 TESTS THAT FAIL
The following is a list of tests that will fail as of the TT2.19 test
suite. All of the failed tests are caused by behavior that will be
obsoleted by TT3.
t/compile3.t - Fails 1 test
Both CET and TT2 return the same error - but the error isn't
formatted the same.
t/debug.t - Fails 1 test
CET debugs INTERPOLATED GETS - TT2 doesn't. There is an INTERPOLATED
value that TT2 doesn't debug.
t/fileline.t - Fails 4 tests
CET is warn clean - even when performing numeric operations on
non-numeric data - TT2 isn't and is testing for warnings.
t/filter.t - Fails 1 test
CET parses { 1 2 3 } as a hashref just fine - TT2 doesn't and
expects an error.
t/vars.t - Fails 8 tests (4 really, but parsing is failing)
TT2 is allowing inline comments with closing tag on the same line.
CET is recursive, the closing tag isn't matched before the closing
tag - changing the closing tag to be on a separate line fixes the
issue.
AUTHOR
Paul Seamons <paul at seamons dot com>
LICENSE
This module may be distributed under the same terms as Perl itself.
_______________________________________________
templates mailing list
[email protected]
http://lists.template-toolkit.org/mailman/listinfo/templates