hash => {a => 'b'},
};
+ # print to STDOUT
$t->process('my/template.tt', $swap)
|| die $t->error;
- ### Anything in the Template::Toolkit SYNOPSIS would fit here also
+ # process into a variable
+ my $out = '';
+ $t->process('my/template.tt', $swap, \$out);
+
+ ### CET uses the same syntax and configuration as Template::Toolkit
=head1 DESCRIPTION
there will continue to be code sharing between the two projects. (Acutally
I will try and keep applicable fixes in sync with TT).
+CGI::Ex::Template uses a recursive regex based grammar (early versions
+before the 2.10 release did not). This allows for the embedding of opening
+and closing tags inside other tags (as in [% a = "[% 1 + 2 %]" ; a|eval %]).
+The individual methods such as parse_expr and play_expr may be used by external
+applications to add TT style variable parsing to other applications.
+
Most of the standard Template::Toolkit documentation covering directives,
variables, configuration, plugins, filters, syntax, and vmethods should
apply to CET just fine (This pod tries to explain everything - but there is
In general the following statements are true:
If you load a new Template object each time and pass a filename, CET
- is around 4 times faster.
+ is around 3.5 times faster.
If you load a new Template object and pass a string ref, CET
- is around 3.5 times faster.
+ is around 3 times faster.
If you load a new Template object and use CACHE_EXT, CET
is around 1.5 times faster.
then CET is 50% faster.
If you use Template::Stash::XS with a cached in memory template,
- then CET is about as fast.
-
- Using TT with a compiled-in-memory template is only 33%
- faster than CET with a new object compiling each time.
+ then CET is about as fast. But if you use CGI::Ex::Template::XS,
+ the CETX is faster still (about twice as fast as CET).
It is pretty hard to beat the speed of XS stash with compiled in
memory templates. Many systems don't have access to those so
CET may make more sense. Hopefully as TT is revised, many of the CET
speed advantages can be incorporated so that the core TT is just as
-fast or faster.
+fast or faster. This was last updated at version 2.10 of CET and
+2.18 of TT.
So should you use CGI::Ex::Template ? Well, try it out. It may
give you no visible improvement. Or it could.
=head1 TODO
- Add WRAPPER configuration item (the WRAPPER directive is supported).
-
- Add ERROR config item
+ Add HTML::Template support
=head1 HOW IS CGI::Ex::Template DIFFERENT
[% (a ~ b).length %]
- [% "hi".repeat(3) %]
+ [% "hi".repeat(3) %] # = hihihi
- [% {a => b}.size %]
+ [% {a => b}.size %] # = 1
=item The "${" and "}" variable interpolators can contain expressions,
not just variables.
[% color = qw/Red Blue/; FOR [1..4] ; color.${ loop.index % color.size } ; END %]
# = RedBlueRedBlue
+=item You can use regular expression quoting.
+
+ [% "foo".match( /(F\w+)/i ).0 %] # = foo
+
+=item Tags can be nested.
+
+ [% f = "[% (1 + 2) %]" %][% f|eval %] # = 3
+
=item Arrays can be accessed with non-integer numbers.
[% [0..10].${ 2.3 } %] # = 3
[% "aa" | repeat(2) . length %] # = 4
+=item 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
+
=item Added Virtual Object Namespaces. (TT3)
The Text, List, and Hash types give direct access
| Hash.keys
| List.join(", ") %] # = a, b
-=item Added "as" scalar, list, and hash virtual methods.
+=item Added "fmt" scalar, list, and hash virtual methods.
- [% list.as("%s", ", ") %]
+ [% list.fmt("%s", ", ") %]
- [% hash.as("%s => %s", "\n") %]
+ [% hash.fmt("%s => %s", "\n") %]
=item Whitespace is less meaningful. (TT3)
[% qw/a b c/.2 %] # = c
+=item Added regex contructor. (TT3)
+
+ [% "FOO".match(/(foo)/i).0 %] # = FOO
+
+ [% a = /(foo)/i; "FOO".match(a).0 %] # = FOO
+
=item Allow for scientific notation. (TT3)
[% a = 1.2e-20 %]
- [% 123.as('%.3e') %] # = 1.230e+02
+ [% 123.fmt('%.3e') %] # = 1.230e+02
=item Allow for hexidecimal input. (TT3)
[% a = 0xff0000 %][% a %] # = 16711680
- [% a = 0xff2 / 0xd; a.as('%x') %] # = 13a
+ [% a = 0xff2 / 0xd; a.fmt('%x') %] # = 13a
=item FOREACH variables can be nested.
[% DUMP a.a %]
+=item Added CONFIG directive.
+
+ [% CONFIG
+ ANYCASE => 1
+ PRE_CHOMP => '-'
+ %]
+
+=item Configuration options can use lowercase names instead
+of the all uppercase names that TT2 uses.
+
+ my $t = CGI::Ex::Template->new({
+ anycase => 1,
+ interpolate => 1,
+ });
+
=item CET does not generate Perl code.
-It generates an "opcode" tree.
+It generates an "opcode" tree. The opcode tree is an arrayref
+of scalars and array refs nested as deeply as possible. This "simple"
+structure could be shared TT implementations in other languages
+via JSON or YAML.
=item CET uses storable for its compiled templates.
If EVAL_PERL is off, CET will not eval_string on ANY piece of information.
+=item There is eval_filter and MACRO recursion protection
+
+You can control the nested nature of eval_filter and MACRO
+recursion using the MAX_EVAL_RECURSE and MAX_MACRO_RECURSE
+configuration items.
+
=item There is no context.
CET provides a context object that mimics the Template::Context
-interface for use by some TT filters, eval perl blocks, and plugins.
+interface for use by some TT filters, eval perl blocks, views,
+and plugins.
=item There is no stash.
CET uses the load_parsed_tree method to get and cache templates.
-=item There is no grammar.
-
-CET has its own built in recursive grammar system.
-
-=item There is no VIEW directive.
-
-
-=item There are no references.
-
-There was in initial beta tests, but it was decided to remove the little used feature.
-
-It makes it the same as
+=item There is no parser/grammar.
- [% obj.method("foo") %]
+CET has its own built-in recursive regex based parser and grammar system.
-This is removed in CET.
+CET can actually be substituted in place of the native Template::Parser and
+Template::Grammar in TT by using the Template::Parser::CET module. This
+module uses the output of parse_tree to generate a TT style compiled perl
+document.
=item The DEBUG directive is more limited.
It only understands DEBUG_DIRS (8) and DEBUG_UNDEF (2).
-=item When debug dirs is on, directives on different lines separated by colons show the line they
-are on rather than a general line range.
+=item CET has better line information
-=item There is no ANYCASE configuration item.
+When debug dirs is on, directives on different lines separated
+by colons show the line they are on rather than a general line range.
-There was in initial beta tests, but it was dropped in favor of consistent parsing syntax.
-
-=item There is no V1DOLLAR configuration item.
-
-This is a TT version 1 compatibility item and is not available in CET.
+Parse errors actually know what line and character they occured at.
=back
=head1 VARIABLES
-This section discusses how to use variables and expressions in the TT mini-language.
+This section discusses how to use variables and expressions in the TT
+mini-language.
-A variable is the most simple construct to insert into the TT mini language. A variable
-name will look for the matching value inside CGI::Ex::Templates internal stash of variables
-which is essentially a hash reference. This stash is initially populated by either passing
-a hashref as the second argument to the process method, or by setting the "VARIABLES" or
-"PRE_DEFINE" configuration variables.
+A variable is the most simple construct to insert into the TT mini
+language. A variable name will look for the matching value inside
+CGI::Ex::Templates internal stash of variables which is essentially a
+hash reference. This stash is initially populated by either passing a
+hashref as the second argument to the process method, or by setting
+the "VARIABLES" or "PRE_DEFINE" configuration variables.
### some sample variables
my %vars = (
=head2 GETTING VARIABLES
-Once you have variables defined, they can be used directly in the template by using their name
-in the stash. Or by using the GET directive.
+Once you have variables defined, they can be used directly in the
+template by using their name in the stash. Or by using the GET
+directive.
[% foo %]
[% one %]
1.0
bar
-To access members of a hashref or an arrayref, you can chain together the names using a ".".
+To access members of a hashref or an arrayref, you can chain together
+the names using a ".".
[% some_data.a %]
[% my_list.0] [% my_list.1 %] [% my_list.-1 %]
20 21 50
4
-If the value of a variable is a code reference, it will be called. You can add a set of parenthesis
-and arguments to pass arguments. Arguments are variables and can be as complex as necessary.
+If the value of a variable is a code reference, it will be called.
+You can add a set of parenthesis and arguments to pass arguments.
+Arguments are variables and can be as complex as necessary.
[% some_code %]
[% some_code() %]
You passed me (bar).
You passed me (1.0, 2, 3).
-If the value of a variable is an object, methods can be called using the "." operator.
+If the value of a variable is an object, methods can be called using
+the "." operator.
[% cet %]
- [% cet.dump_parse('1 + 2').replace('\s+', ' ') %]
+ [% cet.dump_parse_expr('1 + 2').replace('\s+', ' ') %]
Would print something like:
CGI::Ex::Template=HASH(0x814dc28)
- $VAR1 = [ \[ '+', '1', '2' ], 0 ];
+ $VAR1 = [ [ undef, '+', '1', '2' ], 0 ];
Each type of data (string, array and hash) have virtual methods
associated with them. Virtual methods allow for access to functions
31
3 | 1 | 4 | 5 | 9
-It is also possible to "interpolate" variable names using a "$". This allows for storing
-the name of a variable inside another variable. If a variable name is a little
-more complex it can be embedded inside of "${" and "}".
+It is also possible to "interpolate" variable names using a "$". This
+allows for storing the name of a variable inside another variable. If
+a variable name is a little more complex it can be embedded inside of
+"${" and "}".
[% $vname %]
[% ${vname} %]
3234
3234
-In CET it is also possible to embed any expression (non-directive) in "${" and "}"
-and it is possible to use non-integers for array access. (This is not available in TT2)
+In CET it is also possible to embed any expression (non-directive) in
+"${" and "}" and it is possible to use non-integers for array access.
+(This is not available in TT2)
[% ['a'..'z'].${ 2.3 } %]
[% {ab => 'AB'}.${ 'a' ~ 'b' } %]
=head2 SETTING VARIABLES.
-To define variables during processing, you can use the = operator. In most cases
-this is the same as using the SET directive.
+To define variables during processing, you can use the = operator. In
+most cases this is the same as using the SET directive.
[% a = 234 %][% a %]
[% SET b = "Hello" %][% b %]
[% 314159e-5 + 0 %] Prints 3.14159.
- [% .0000001.as('%.1e') %] Prints 1.0e-07
+ [% .0000001.fmt('%.1e') %] Prints 1.0e-07
Hexidecimal input is also supported.
[% 0xff + 0 %] Prints 255
- [% 48875.as('%x') %] Prints beeb
+ [% 48875.fmt('%x') %] Prints beeb
=item Single quoted strings.
Note: virtual methods can only be used on literal strings in CET, not in TT.
+You may also embed the current tags in strings (CET only).
+
+ [% '[% 1 + 2 %]' | eval %] Prints "3"
+
=item Double quoted strings.
Returns the string. Variable interpolation happens.
Note: virtual methods can only be used on literal strings in CET, not in TT.
+You may also embed the current tags in strings (CET only).
+
+ [% "[% 1 + 2 %]" | eval %] Prints "3"
+
=item Array Constructs.
[% [1, 2, 3] %] Prints something like ARRAY(0x8309e90).
Note: virtual methods can only be used on hash contructs in CET, not in TT.
+=item Regex Constructs.
+
+ [% /foo/ %] Prints (?-xism:foo)
+ [% a = /(foo)/i %][% "FOO".match(a).0 %] Prints FOO
+
+Note: this works in CET and is planned for TT3.
+
=head1 EXPRESSIONS
Expressions are one or more variables or literals joined together with
with the exception of the variable name in the SET directive, and the
filename of PROCESS, INCLUDE, WRAPPER, and INSERT.
-The following section shows some samples of expressions. For a full list
-of available operators, please see the section titled OPERATORS.
+The following section shows some samples of expressions. For a full
+list of available operators, please see the section titled OPERATORS.
[% 1 + 2 %] Prints 3
[% 1 + 2 * 3 %] Prints 7
=head2 SCALAR VIRTUAL METHODS AND FILTERS
-The following is the list of builtin virtual methods and filters
-that can be called on scalar data types. In CET and TT3, filters and
-virtual methods are more closely related than in TT2. In general anywhere a
-virtual method can be used a filter can be used also - and likewise all scalar
-virtual methods can be used as filters.
+The following is the list of builtin virtual methods and filters that
+can be called on scalar data types. In CET and TT3, filters and
+virtual methods are more closely related than in TT2. In general
+anywhere a virtual method can be used a filter can be used also - and
+likewise all scalar virtual methods can be used as filters.
In addition to the filters listed below, CET will automatically load
Template::Filters and use them if Template::Toolkit is installed.
=item '0'
- [% item = 'foo' %][% item.0 %] Returns self. Allows for scalars to mask as arrays.
+ [% item = 'foo' %][% item.0 %] Returns foo.
-=item as
-
- [% item.as('%d') %]
-
-Similar to format. Returns a string formatted with the passed pattern. Default pattern is %s.
+Allows for scalars to mask as arrays (scalars already will, but this
+allows for more direct access).
=item chunk
Same as the redirect filter.
+=item fmt
+
+ [% item.fmt('%d') %]
+ [% item.fmt('%6s') %]
+ [% item.fmt('%*s', 6) %]
+
+Similar to format. Returns a string formatted with the passed pattern. Default pattern is %s.
+
=item format
- [% item.format('%d') %] Print the string out in the specified format. Each line is
- processed separately.
+ [% item.format('%d') %]
+ [% item.format('%6s') %]
+ [% item.format('%*s', 6) %]
+
+Print the string out in the specified format. It is similar to
+the "fmt" virtual method, except that the item is split on newline and each line is
+processed separately.
=item hash
[% item.match("(\w+) (\w+)", 1) %] Same as before - but match globally.
+In CGI::Ex::Template and TT3 you can use regular expressions notation as well.
+
+ [% item.match( /(\w+) (\w+)/ ) %] Same as before.
+
+ [% item.match( m{(\w+) (\w+)} ) %] Same as before.
+
=item null
[% item.null %] Do nothing.
=item remove
- [% item.remove("\s+") %] Same as remove - but is global and replaces with nothing.
+ [% item.remove("\s+") %] Same as replace - but is global and replaces with nothing.
=item redirect
[% item.replace("\s+", " ") %] Globally replace all space with
- [% item.replace("foo", "bar", 0) Replace only the first instance of foo with bar.
+ [% item.replace("foo", "bar", 0) %] Replace only the first instance of foo with bar.
[% item.replace("(\w+)", "($1)") %] Surround all words with parenthesis.
+In CGI::Ex::Template and TT3 you may also use normal regular expression notation.
+
+ [% item.replace(/(\w+)/, "($1)") %] Same as before.
+
=item search
- [% item.search("(\w+)" %] Tests if the given pattern is in the string.
+ [% item.search("(\w+)") %] Tests if the given pattern is in the string.
+
+In CGI::Ex::Template and TT3 you may also use normal regular expression notation.
+
+ [% item.search(/(\w+)/, "($1)") %] Same as before.
=item size
[% item.split("\s+", 3) %] Returns an arrayref from the item split on /\s+/ splitting until 3 elements are found.
+In CGI::Ex::Template and TT3 you may also use normal regular expression notation.
+
+ [% item.split( /\s+/, 3 ) %] Same as before.
+
=item stderr
[% item.stderr %] Print the item to the current STDERR handle.
[% item.uri %] Perform a very basic URI encoding.
+=item url
+
+ [% item.url %] Perform a URI encoding - but some characters such
+ as : and / are left intact.
+
=back
=head2 LIST VIRTUAL METHODS
=over 4
-=item as
+=item fmt
- [% mylist.as('%s', ', ') %]
+ [% mylist.fmt('%s', ', ') %]
+ [% mylist.fmt('%6s', ', ') %]
+ [% mylist.fmt('%*s', ', ', 6) %]
Passed a pattern and an string to join on. Returns a string of the values of the list
formatted with the passed pattern and joined with the passed string.
[% mylist.push(23) %] Adds an element to the end of the arrayref (the stash is modified).
-=item random
+=item pick
- [% mylist.random %] Returns a random item from the list.
- [% ['a' .. 'z'].random %]
+ [% mylist.pick %] Returns a random item from the list.
+ [% ['a' .. 'z'].pick %]
+
+An additional numeric argument is how many items to return.
+
+ [% ['a' .. 'z'].pick(8).join('') %]
Note: This filter is not available as of TT2.15.
=over 4
-=item as
+=item fmt
- [% myhash.as('%s => %s', "\n") %]
+ [% myhash.fmt('%s => %s', "\n") %]
+ [% myhash.fmt('%4s => %5s', "\n") %]
+ [% myhash.fmt('%*s => %*s', "\n", 4, 5) %]
Passed a pattern and an string to join on. Returns a string of the key/value pairs
of the hash formatted with the passed pattern and joined with the passed string.
[% myhash.delete('a') %] Deletes the item from the hash.
+Unlink Perl the value is not returned. Multiple values may be passed
+and represent the keys to be deleted.
+
=item each
[% myhash.each.join(", ") %] Turns the contents of the hash into a list - subject
or template. This can be useful when used in conjunction with the TRY
statement to clear generated content if an error occurs later.
+=item C<CONFIG>
+
+Allow for changing the value of some compile time and runtime configuration
+options.
+
+ [% CONFIG
+ ANYCASE => 1
+ PRE_CHOMP => '-'
+ %]
+
+The following compile time configuration options may be set:
+
+ ANYCASE
+ INTERPOLATE
+ PRE_CHOMP
+ POST_CHOMP
+ V1DOLLAR
+ V2PIPE
+
+The following runtime configuration options may be set:
+
+ DUMP
+
+If non-named parameters as passed, they will show the current configuration:
+
+ [% CONFIG ANYCASE, PRE_CHOMP %]
+
+ CONFIG ANYCASE = undef
+ CONFIG PRE_CHOMP = undef
+
=item C<DEBUG>
Used to reset the DEBUG_FORMAT configuration variable, or to turn
=item C<DUMP>
-This is not provided in TT. DUMP inserts a Data::Dumper printout
-of the variable or expression. If no argument is passed it will
-dump the entire contents of the current variable stash (with
-private keys removed.
+DUMP inserts a Data::Dumper printout of the variable or expression.
+If no argument is passed it will dump the entire contents of the
+current variable stash (with private keys removed).
+
+The output also includes the current file and line number that the
+DUMP directive was called from.
-If the template is being processed in a web request, DUMP will html
-encode the DUMP automatically.
+See the DUMP configuration item for ways to customize and control
+the output available to the DUMP directive.
[% DUMP %] # dumps everything
Alias for the FILTER directive. Note that | is similar to the
'.' in CGI::Ex::Template. Therefore a pipe cannot be used directly after a
variable name in some situations (the pipe will act only on that variable).
-This is the behavior employed by TT3.
+This is the behavior employed by TT3. To get the TT2 behavior for a PIPE, use
+the V2PIPE configuration item.
=item C<FINAL>
Filenames must be relative to INCLUDE_PATH unless the ABSOLUTE
or RELATIVE configuration items are set.
+Multiple filenames can be passed by separating them with a plus, a space,
+or commas (TT2 doesn't support the comma). Any supplied arguments will
+be used on all templates.
+
+ [% INCLUDE "path/to/template.html",
+ "path/to/template2.html" a = "An arg" b = "Another arg" %]
+
=item C<INSERT>
Insert the contents of a file without template parsing.
Filenames must be relative to INCLUDE_PATH unless the ABSOLUTE
or RELATIVE configuration items are set.
+Multiple filenames can be passed by separating them with a plus, a space,
+or commas (TT2 doesn't support the comma).
+
+ [% INSERT "path/to/template.html",
+ "path/to/template2.html" %]
+
=item C<LAST>
Used to exit out of a WHILE or FOREACH loop.
Filenames must be relative to INCLUDE_PATH unless the ABSOLUTE
or RELATIVE configuration items are set.
+Multiple filenames can be passed by separating them with a plus, a space,
+or commas (TT2 doesn't support the comma). Any supplied arguments will
+be used on all templates.
+
+ [% PROCESS "path/to/template.html",
+ "path/to/template2.html" a = "An arg" b = "Another arg" %]
+
=item C<RAWPERL>
Only available if the EVAL_PERL configuration item is true (default is false).
The named tags are (duplicated from TT):
- template => ['[%', '%]'], # default
- metatext => ['%%', '%%'], # Text::MetaText
- star => ['[*', '*]'], # TT alternate
- php => ['<?', '?>'], # PHP
- asp => ['<%', '%>'], # ASP
- mason => ['<%', '>' ], # HTML::Mason
- html => ['<!--', '-->'], # HTML comments
+ asp => ['<%', '%>' ], # ASP
+ default => ['\[%', '%\]' ], # default
+ html => ['<!--', '-->' ], # HTML comments
+ mason => ['<%', '>' ], # HTML::Mason
+ metatext => ['%%', '%%' ], # Text::MetaText
+ php => ['<\?', '\?>' ], # PHP
+ star => ['\[\*', '\*\]' ], # TT alternate
+ template => ['\[%', '%\]' ], # Normal Template Toolkit
+ template1 => ['[\[%]%', '%[%\]]'], # allow TT1 style
+ tt2 => ['\[%', '%\]' ], # TT2
+
+If custom tags are supplied, by default they are escaped using
+quotemeta. You may also pass explicitly quoted strings,
+or regular expressions as arguments as well (if your
+regex begins with a ', ", or / you must quote it.
+
+ [% TAGS [<] [>] %] matches "[<] tag [>]"
+
+ [% TAGS '[<]' '[>]' %] matches "[<] tag [>]"
+
+ [% TAGS "[<]" "[>]" %] matches "[<] tag [>]"
+
+ [% TAGS /[<]/ /[>]/ %] matches "< tag >"
+
+ [% TAGS ** ** %] matches "** tag **"
+
+ [% TAGS /**/ /**/ %] Throws an exception.
=item C<THROW>
# The LOAD_PERL directive should be set to 1
[% USE cet = CGI::Ex::Template %]
- [%~ cet.dump_parse('2 * 3').replace('\s+', ' ') %]
+ [%~ cet.dump_parse_expr('2 * 3').replace('\s+', ' ') %]
Would print:
- $VAR1 = [ \[ '*', '2', '3' ], 0 ];
+ $VAR1 = [ [ undef, '*', '2', '3' ], 0 ];
See the PLUGIN_BASE, and PLUGINS configuration items.
See the documentation for Template::Manual::Plugins.
+=item C<VIEW>
+
+Implement a TT style view. For more information, please
+see the Template::View documentation. This DIRECTIVE
+will correctly parse the arguments and then pass them
+along to a newly created Template::View object. It
+will fail if Template::View can not be found.
+
=item C<WHILE>
Will process a block of code while a condition is true.
in the [% content %] variable to the block or filename listed in the
WRAPPER tag.
- [% WRAPPER foo %]
- My content to be processed.[% a = 2 %]
+ [% WRAPPER foo b = 23 %]
+ My content to be processed ([% b %]).[% a = 2 %]
[% END %]
[% BLOCK foo %]
This would print.
A header (2).
- My content to be processed.
+ My content to be processed (23).
A footer (2).
-The WRAPPER directive may also be used as a post directive.
+The WRAPPER directive may also be used as a post operative directive.
[% BLOCK baz %]([% content %])[% END -%]
[% "foobar" WRAPPER baz %]
(foobar)');
+Multiple filenames can be passed by separating them with a plus, a space,
+or commas (TT2 doesn't support the comma). Any supplied arguments will
+be used on all templates. Wrappers are processed in reverse order, so
+that the first wrapper listed will surround each subsequent wrapper listed.
+Variables from inner wrappers are available to the next wrapper that
+surrounds it.
+
+ [% WRAPPER "path/to/outer.html",
+ "path/to/inner.html" a = "An arg" b = "Another arg" %]
+
+
=back
This shouldn't be too much hardship and offers the great return of disambiguating
virtual method access.
+=item C<\>
+
+Unary. The reference operator. Not well publicized in TT. Stores a reference
+to a variable for use later. Can also be used to "alias" long names.
+
+ [% f = 7 ; foo = \f ; f = 8 ; foo %] => 8
+
+ [% foo = \f.g.h.i.j.k; f.g.h.i.j.k = 7; foo %] => 7
+
+ [% f = "abcd"; foo = \f.replace("ab", "-AB-") ; foo %] => -AB-cd
+
+ [% f = "abcd"; foo = \f.replace("bc") ; foo("-BC-") %] => a-BC-d
+
+ [% f = "abcd"; foo = \f.replace ; foo("cd", "-CD-") %] => ab-CD-
+
=item C<++ -->
Pre and post increment and decrement. My be used as either a prefix
In order to not conflict with SET, FOREACH and other operations, this
operator is only available in parenthesis.
- [% a = 2 %][% a += 3 %] --- [% a %] => --- 5 # is was handled by SET
+ [% a = 2 %][% a += 3 %] --- [% a %] => --- 5 # is handled by SET
[% a = 2 %][% (a += 3) %] --- [% a %] => 5 --- 5
=item C<=>
to not conflict with SET, FOREACH and other operations, this operator is only
available in parenthesis. Returns the value of the righthand side.
- [% a = 1 %] --- [% a %] => --- 1 # is was handled by SET
+ [% a = 1 %] --- [% a %] => --- 1 # is handled by SET
[% (a = 1) %] --- [% a %] => 1 --- 1
=item C<not NOT>
Right associative. Lower precedence version of the '||' operator.
-=item C<hash>
+=item C<{}>
This operator is not used in TT. It is used internally
by CGI::Ex::Template to delay the creation of a hash until the
execution of the compiled template.
-=item C<array>
+=item C<[]>
This operator is not used in TT. It is used internally
by CGI::Ex::Template to delay the creation of an array until the
execution of the compiled template.
+=item C<qr>
+
+This operator is not used in TT. It is used internally
+by CGI::Ex::Template to store a regular expression and its options.
+It will return a compiled Regexp object when compiled.
+
=back
Hello.
- [%- "Hi." -%]
+ [%= "Hi." =%]
Howdy.
Hello.
- [%- "Hi." -%]
+ [%~ "Hi." ~%]
Howdy.
These variables should be passed to the "new" constructor.
- my $obj = CGI::Ex::Template->new(
- VARIABLES => \%hash_of_variables,
- AUTO_RESET => 0,
- TRIM => 1,
- POST_CHOMP => "=",
- PRE_CHOMP => "-",
- );
+ my $obj = CGI::Ex::Template->new(
+ VARIABLES => \%hash_of_variables,
+ AUTO_RESET => 0,
+ TRIM => 1,
+ POST_CHOMP => "=",
+ PRE_CHOMP => "-",
+ );
=over 4
Boolean. Default false. Are absolute paths allowed for included files.
+=item ANYCASE
+
+Allow directive matching to be case insensitive.
+
+ [% get 23 %] prints 23 with ANYCASE => 1
+
=item AUTO_RESET
Boolean. Default 1. Clear blocks that were set during the process method.
A hashref of blocks that can be used by the process method.
- BLOCKS => {
- block_1 => sub { ... }, # coderef that returns a block
- block_2 => 'A String', # simple string
- },
+ BLOCKS => {
+ block_1 => sub { ... }, # coderef that returns a block
+ block_2 => 'A String', # simple string
+ },
Note that a Template::Document cannot be supplied as a value (TT
supports this). However, it is possible to supply a value that is
String to use to split INCLUDE_PATH with. Default is :. It is more
straight forward to just send INCLUDE_PATH an arrayref of paths.
+=item DUMP
+
+Configures the behavior of the DUMP tag. May be set to 0, a hashref,
+or another true value. Default is true.
+
+If set to 0, all DUMP directives will do nothing. This is useful if
+you would like to turn off the DUMP directives under some environments.
+
+IF set to a true value (or undefined) then DUMP directives will operate.
+
+If set to a hashref, the values of the hash can be used to configure
+the operation of the DUMP directives. The following are the values
+that can be set in this hash.
+
+=over 4
+
+=item EntireStash
+
+Default 1. If set to 0, then the DUMP directive will not print the
+entire contents of the stash when a DUMP directive is called without
+arguments.
+
+=item handler
+
+Defaults to an internal coderef. If set to a coderef, the DUMP directive will pass the
+arguments to be dumped and expects a string with the dumped data. This
+gives complete control over the dump process.
+
+Note 1: The default handler makes sure that values matching the
+private variable regex are not included. If you install your own handler,
+you will need to take care of these variables if you intend for them
+to not be shown.
+
+Note 2: If you would like the name of the variable to be dumped, include
+the string '$VAR1' and the DUMP directive will interpolate the value. For
+example, to dump all output as YAML - you could do the following:
+
+ DUMP => {
+ handler => sub {
+ require YAML;
+ return "\$VAR1 =\n".YAML::Dump(shift);
+ },
+ }
+
+=item header
+
+Default 1. Controls whether a header is printed for each DUMP directive.
+The header contains the file and line number the DUMP directive was
+called from. If set to 0 the headers are disabled.
+
+=item html
+
+Defaults to 1 if $ENV{'REQUEST_METHOD'} is set - 0 otherwise. If set to
+1, then the output of the DUMP directive is passed to the html filter
+and encased in "pre" tags. If set to 0 no html encoding takes place.
+
+=item Sortkeys, Useqq, Ident, Pad, etc
+
+Any of the Data::Dumper configuration items may be passed.
+
+=back
+
=item END_TAG
Set a string to use as the closing delimiter for TT. Default is "%]".
+=item ERROR
+
+Used as a fall back when the processing of a template fails. May either
+be a single filename that will be used in all cases, or may be a hashref
+of options where the keynames represent error types that will be handled
+by the filename in their value. A key named default will be used if no
+other matching keyname can be found. The selection process is similar
+to that of the TRY/CATCH/THROW directives (see those directives for more
+information).
+
+ my $t = CGI::Ex::Template->new({
+ ERROR => 'general/catch_all_errors.html',
+ });
+
+ my $t = CGI::Ex::Template->new({
+ ERROR => {
+ default => 'general/catch_all_errors.html',
+ foo => 'catch_all_general_foo_errors.html',
+ 'foo.bar' => 'catch_foo_bar_errors.html',
+ },
+ });
+
+Note that the ERROR handler will only be used for errors during the
+processing of the main document. It will not catch errors that
+occur in templates found in the PRE_PROCESS, POST_PROCESS, and WRAPPER
+configuration items.
+
+=item ERRORS
+
+Same as the ERROR configuration item. Both may be used interchangably.
+
=item EVAL_PERL
Boolean. Default false. If set to a true value, PERL and RAWPERL blocks
my $str = q{
[% a = "Hello" %]
- 1([% a | filter1 %])
- 2([% a | filter2 %])
- 3([% a | filter3 %])
+ 1 ([% a | filter1 %])
+ 2 ([% a | filter2 %])
+ 3 ([% a | filter3 %])
};
my $obj = CGI::Ex::Template->new(FILTERS => $filters);
Would print:
- (11111)
- (22222)
- (33333)
+ 1 (11111)
+ 2 (22222)
+ 3 (33333)
Filters passed in as an arrayref should contain a coderef and a value
indicating if they are dynamic or static (true meaning dynamic). The
[% IF 1 %]The variable $variable had a value ${var.value}[% END %]
-
=item LOAD_PERL
Indicates if the USE directive can fall back and try and load a perl module
if the indicated module was not found in the PLUGIN_BASE path. See the
USE directive.
+=item MAX_EVAL_RECURSE (CET only)
+
+Will use $CGI::Ex::Template::MAX_EVAL_RECURSE if not present. Default is 50.
+Prevents runaway on the following:
+
+ [% f = "[% f|eval %]" %][% f|eval %]
+
+=item MAX_MACRO_RECURSE (CET only)
+
+Will use $CGI::Ex::Template::MAX_MACRO_RECURSE if not present. Default is 50.
+Prevents runaway on the following:
+
+ [% MACRO f BLOCK %][% f %][% END %][% f %]
+
=item NAMESPACE
No Template::Namespace::Constants support. Hashref of hashrefs representing
Any number of hashes can be added to the NAMESPACE hash.
+=item NEGATIVE_STAT_TTL (Not in TT)
+
+Defaults to STAT_TTL which defaults to $STAT_TTL which defaults to 1.
+
+Similar to STAT_TTL - but represents the time-to-live
+seconds until a document that was not found is checked again against
+the system for modifications. Setting this number higher will allow for
+fewer file system accesses. Setting it to a negative number will allow
+for the file system to be checked every hit.
+
=item OUTPUT
Alternate way of passing in the output location for processed templates.
Default value is Template::Plugin. The base module namespace
that template plugins will be looked for. See the USE directive
-for more information.
+for more information. May be either a single namespace, or an arrayref
+of namespaces.
=item POST_CHOMP
Set a string to use as the opening delimiter for TT. Default is "[%".
+=item STAT_TTL
+
+Defaults to $STAT_TTL which defaults to 1. Represents time-to-live
+seconds until a cached in memory document is compared to the file
+system for modifications. Setting this number higher will allow for
+fewer file system accesses. Setting it to a negative number will allow
+for the file system to be checked every hit.
+
=item TAG_STYLE
Allow for setting the type of tag delimiters to use for parsing the TT.
You can also sub class the module and override the undefined_get method.
-=item VARIABLES
+=item V1DOLLAR
-A hashref of variables to initialize the template stash with. These
-variables are available for use in any of the executed templates.
-See the section on VARIABLES for the types of information that can be passed in.
+This allows for some compatibility with TT1 templates. The only real
+behavior change is that [% $foo %] becomes the same as [% foo %]. The
+following is a basic table of changes invoked by using V1DOLLAR.
-=back
+ With V1DOLLAR Equivalent Without V1DOLLAR (Normal default)
+ "[% foo %]" "[% foo %]"
+ "[% $foo %]" "[% foo %]"
+ "[% ${foo} %]" "[% ${foo} %]"
+ "[% foo.$bar %]" "[% foo.bar %]"
+ "[% ${foo.bar} %]" "[% ${foo.bar} %]"
+ "[% ${foo.$bar} %]" "[% ${foo.bar} %]"
+ "Text: $foo" "Text: $foo"
+ "Text: ${foo}" "Text: ${foo}"
+ "Text: ${$foo}" "Text: ${foo}"
+=item V2PIPE
+Restores the behavior of the pipe operator to be compatible with TT2.
-=head1 UNSUPPORTED TT CONFIGURATION
+With V2PIPE = 1
-=over 4
+ [%- BLOCK a %]b is [% b %]
+ [% END %]
+ [%- PROCESS a b => 237 | repeat(2) %]
-=item ANYCASE
+ # output of block "a" with b set to 237 is passed to the repeat(2) filter
+
+ b is 237
+ b is 237
-This will not be supported. You will have to use the full case directive names.
-(It was in the beta code but was removed prior to release).
+With V2PIPE = 0 (default)
+
+ [%- BLOCK a %]b is [% b %]
+ [% END %]
+ [% PROCESS a b => 237 | repeat(2) %]
+
+ # b set to 237 repeated twice, and b passed to block "a"
+
+ b is 237237
+
+=item VARIABLES
+
+A hashref of variables to initialize the template stash with. These
+variables are available for use in any of the executed templates.
+See the section on VARIABLES for the types of information that can be passed in.
=item WRAPPER
-This will be supported - just not done yet.
+Operates similar to the WRAPPER directive. The option can be given a
+single filename, or an arrayref of filenames that will be used to wrap
+the processed content. If an arrayref is passed the filenames are
+processed in reverse order, so that the first filename specified will
+end up being on the outside (surrounding all other wrappers).
-=item ERROR
+ my $t = CGI::Ex::Template->new(
+ WRAPPER => ['my/wrappers/outer.html', 'my/wrappers/inner.html'],
+ );
-This will be supported - just not done yet.
+Content generated by the PRE_PROCESS and POST_PROCESS will come before
+and after (respectively) the content generated by the WRAPPER
+configuration item.
-=item V1DOLLAR
+See the WRAPPER direcive for more examples of how wrappers are construted.
-This will not be supported.
+=back
+
+
+=head1 UNSUPPORTED TT CONFIGURATION
+
+=over 4
=item LOAD_TEMPLATES
CGI::Ex::Template has its own built in parser. The closest similarity is
the parse_tree method. The output of parse_tree is an optree that is
-later run by execute_tree.
+later run by execute_tree. CET provides a backend to the Template::Parser::CET
+module which can be used to replace the default parser when using
+the standard Template::Toolkit library.
=item GRAMMAR
=head1 VARIABLE PARSE TREE
-CGI::Ex::Template parses templates into an tree of operations. Even
-variable access is parsed into a tree. This is done in a manner
-somewhat similar to the way that TT operates except that nested
-variables such as foo.bar|baz contain the '.' or '|' in between each
-name level. Operators are parsed and stored as part of the variable (it
-may be more appropriate to say we are parsing a term or an expression).
+CGI::Ex::Template parses templates into an tree of operations (an AST
+or abstract syntax tree). Even variable access is parsed into a tree.
+This is done in a manner somewhat similar to the way that TT operates
+except that nested variables such as foo.bar|baz contain the '.' or
+'|' in between each name level. Operators are parsed and stored as
+part of the variable (it may be more appropriate to say we are parsing
+a term or an expression).
The following table shows a variable or expression and the corresponding parsed tree
(this is what the parse_expr method would return).
one.${two().three} [ 'one', 0, '.', ['two', [], '.', 'three', 0], 0]
2.34 2.34
"one" "one"
- "one"|length [ \"one", 0, '|', 'length', 0 ]
- "one $a two" [ \ [ '~', 'one ', ['a', 0], ' two' ], 0 ]
- [0, 1, 2] [ \ [ 'array', 0, 1, 2 ], 0 ]
- [0, 1, 2].size [ \ [ 'array', 0, 1, 2 ], 0, '.', 'size', 0 ]
- ['a', a, $a ] [ \ [ 'array', 'a', ['a', 0], [['a', 0], 0] ], 0]
- {a => 'b'} [ \ [ 'hash', 'a', 'b' ], 0 ]
- {a => 'b'}.size [ \ [ 'hash', 'a', 'b' ], 0, '.', 'size', 0 ]
- {$a => b} [ \ [ 'hash', ['a', 0], ['b', 0] ], 0 ]
- 1 + 2 [ \ [ '+', 1, 2 ], 0]
- a + b [ \ [ '+', ['a', 0], ['b', 0] ], 0 ]
- a * (b + c) [ \ [ '*', ['a', 0], [ \ ['+', ['b', 0], ['c', 0]], 0 ]], 0 ]
- (a + b) [ \ [ '+', ['a', 0], ['b', 0] ]], 0 ]
- (a + b) * c [ \ [ '*', [ \ [ '+', ['a', 0], ['b', 0] ], 0 ], ['c', 0] ], 0 ]
- a ? b : c [ \ [ '?', ['a', 0], ['b', 0], ['c', 0] ], 0 ]
- a || b || c [ \ [ '||', ['a', 0], [ \ [ '||', ['b', 0], ['c', 0] ], 0 ] ], 0 ]
- ! a [ \ [ '!', ['a', 0] ], 0 ]
+ 1 + 2 [ [ undef, '+', 1, 2 ], 0]
+ a + b [ [ undef, '+', ['a', 0], ['b', 0] ], 0 ]
+ "one"|length [ [ undef, '~', "one" ], 0, '|', 'length', 0 ]
+ "one $a two" [ [ undef, '~', 'one ', ['a', 0], ' two' ], 0 ]
+ [0, 1, 2] [ [ undef, '[]', 0, 1, 2 ], 0 ]
+ [0, 1, 2].size [ [ undef, '[]', 0, 1, 2 ], 0, '.', 'size', 0 ]
+ ['a', a, $a ] [ [ undef, '[]', 'a', ['a', 0], [['a', 0], 0] ], 0]
+ {a => 'b'} [ [ undef, '{}', 'a', 'b' ], 0 ]
+ {a => 'b'}.size [ [ undef, '{}', 'a', 'b' ], 0, '.', 'size', 0 ]
+ {$a => b} [ [ undef, '{}', ['a', 0], ['b', 0] ], 0 ]
+ a * (b + c) [ [ undef, '*', ['a', 0], [ [undef, '+', ['b', 0], ['c', 0]], 0 ]], 0 ]
+ (a + b) [ [ undef, '+', ['a', 0], ['b', 0] ]], 0 ]
+ (a + b) * c [ [ undef, '*', [ [undef, '+', ['a', 0], ['b', 0] ], 0 ], ['c', 0] ], 0 ]
+ a ? b : c [ [ undef, '?', ['a', 0], ['b', 0], ['c', 0] ], 0 ]
+ a || b || c [ [ undef, '||', ['a', 0], [ [undef, '||', ['b', 0], ['c', 0] ], 0 ] ], 0 ]
+ ! a [ [ undef, '!', ['a', 0] ], 0 ]
Some notes on the parsing.
Operators are parsed as part of the variable and become part of the variable tree.
- Operators are stored in the variable tree using a reference to the arrayref - which
+ Operators are stored in the variable tree using an operator identity array which
+ contains undef as the first value, the operator, and the operator arguments. This
allows for quickly descending the parsed variable tree and determining that the next
node is an operator.
The following perl can be typed at the command line to view the parsed variable tree:
- perl -e 'use CGI::Ex::Template; print CGI::Ex::Template::dump_parse("foo.bar + 2")."\n"'
+ perl -e 'use CGI::Ex::Template; print CGI::Ex::Template::dump_parse_expr("foo.bar + 2")."\n"'
Also the following can be included in a template to view the output in a template:
[% USE cet = CGI::Ex::Template %]
- [%~ cet.dump_parse('foo.bar + 2').replace('\s+', ' ') %]
+ [%~ cet.dump_parse_expr('foo.bar + 2').replace('\s+', ' ') %]
=head1 SEMI PUBLIC METHODS
=item C<dump_parse>
-This method allows for returning a Data::Dumper dump of a parsed variable. It is mainly used for testing.
+This method allows for returning a Data::Dumper dump of a parsed
+template. It is mainly used for testing.
+
+=item C<dump_parse_expr>
+
+This method allows for returning a Data::Dumper dump of a parsed
+variable. It is mainly used for testing.
=item C<exception>
=item C<play_expr>
-Turns a variable identity array into the parsed variable. This
-method is also responsible for playing operators and running virtual methods
-and filters. The method could more accurately be called play_expression.
+Play the parsed expression. Turns a variable identity array into the
+parsed variable. This method is also responsible for playing
+operators and running virtual methods and filters. The variable
+identity array may also contain literal values, or operator identity
+arrays.
=item C<include_filename>
=item C<filter_*>
-Methods by these names implement filters that are more than one line.
+Methods by these names implement filters that are more complex than one liners.
=item C<get_line_number_by_index>
=item C<play_operator>
-Used to execute any found operators
+Used to execute any found operators. The single argument is
+an operator identy returned by the parse_expr method (if the expression
+contained an operator). Normally you would just call play_expr
+instead and it will call play_operator if the structure
+contains an operator.
=item C<_process>
=item C<vmethod_*>
-Methods by these names implement virtual methods that are more than one line.
-
-=item C<weak_copy>
-
-Used to create a weak reference to self to avoid circular references. (this
-is needed by macros)
+Methods by these names implement virtual methods that are more complex than oneliners.
=back
Paul Seamons <paul at seamons dot com>
+=head1 LICENSE
+
+This module may be distributed under the same terms as Perl itself.
+
=cut