Text::...TTerse(3pm)

πŸ’– Text::...TTerse(3pm) πŸ’–

okay so this is the manual page for Text::...TTerse(3pm) from User Contributed Perl Documentation and bestie, we're gonna get through it together, no cap πŸ’…


✨ NAME ✨

Text::Xslate::Syntax::TTerse β€” an alternative syntax that's compatible with Template Toolkit 2 πŸŽ€


✨ SYNOPSIS ✨

use Text::Xslate;
my $tx = Text::Xslate->new(
    syntax => 'TTerse',
);

print $tx->render_string(
    'Hello, [% dialect %] world!',
    { dialect => 'TTerse' }
);

# PRE_PROCESS/POST_PROCESS
$tx = Text::Xslate->new(
    syntax => 'TTerse',
    header => ['header.tt'],
    footer => ['footer.tt'],
);

✨ DESCRIPTION ✨

So TTerse is a subset of the Template-Toolkit 2 syntax (and partially the 3 one too, slay), and it uses [% ... %] tags plus %% ... for line code πŸ¦‹

Real talk though: TTerse itself is out here with only a few methods and filters, while Template-Toolkit 2 has like, a whole lot. So if you want all those extra methods and filters, go look at the Text::Xslate::Bridge::* modules on CPAN, mwah πŸ’‹

(TODO: I should concentrate on the difference between Template-Toolkit 2 and TTerse) β€” not me leaving a TODO in the docs, iconic honestly 😭

✨ SYNTAX ✨

It supports a Template-Toolkit compatible syntax, lowkey β€” although the details might be different πŸ‘€

Also: lower-cased keywords are allowed too, since they were inspired by Template-Toolkit 3. cute πŸ’œ

🌸 Variable access

Scalar access:

[%  var %]
[% $var %]
[% GET var # 'GET' is optional %]

Field access:

[% var.0 %]
[% var.field %]
[% var.accessor %]
[% var.$field ]%
[% var[$field] # TTerse specific %]

Variables may be HASH references, ARRAY references, or objects.

And if $var is an object instance? bestie you can just call its methods πŸ’…

[% $var.method() %]
[% $var.method(1, 2, 3) %]
[% $var.method(foo => [1, 2, 3]) %]
[% $var.method({ foo => 'bar' }) %]

🌸 Expressions

Basically almost the same as Text::Xslate::Syntax::Kolon, except infix:<_> for concatenation is also supported for compatibility. periodt ✨

🌸 Loops

[% FOREACH item IN arrayref %]
    * [% item %]
[% END %]

Loop iterators are partially supported, so here's the whole menu:

[% FOREACH item IN arrayref %]
    [%- IF loop.is_first -%]
    <first>
    [%- END -%]
    * [% loop.index %]  # 0 origin
    * [% loop.count     # loop.index + 1 %]
    * [% loop.body      # alias to arrayref %]
    * [% loop.size      # loop.body.size %]
    * [% loop.max_index # loop.size - 1 %]
    * [% loop.peek_next # loop.body[ loop.index + 1 %]
    * [% loop.peek_prev # loop.body[ loop.index - 1 %]
    [%- IF loop.is_last -%]
    <last>
    [%- END -%]
[% END %]
⚠️ Unlike Template-Toolkit, FOREACH does not accept a HASH reference. So you must convert HASH references to ARRAY references using the keys(), values(), or kv() methods. no shortcuts bestie 🫢

Template-Toolkit compatible names are also supported, BUT using them is discouraged because they're genuinely not easy to understand πŸ™ˆ:

loop.max   # for loop.max_index
loop.next  # for loop.peek_next
loop.prev  # for loop.peek_prev
loop.first # for loop.is_first
loop.last  # for loop.is_last

Loop control statements, aka NEXT and LAST, are also supported in both FOR and WHILE loops:

[% FOR item IN data -%]
    [% LAST IF item == 42 -%]
    ...
[% END -%]

🌸 Conditional statements

[% IF logical_expression %]
    Case 1
[% ELSIF logical_expression %]
    Case 2
[% ELSE %]
    Case 3
[% END %]

[% UNLESS logical_expression %]
    Case 1
[% ELSE %]
    Case 2
[% END %]

[% SWITCH expression %]
[% CASE case1 %]
    Case 1
[% CASE case2 %]
    Case 2
[% CASE DEFAULT %]
    Case 3
[% END %]

🌸 Functions and filters

[% var | f %]
[% f(var)  %]

🌸 Template inclusion

The INCLUDE statement is supported πŸ’–

[% INCLUDE "file.tt" %]
[% INCLUDE $var %]

The WITH variables syntax is supported too, even though the WITH keyword is optional over in Template-Toolkit:

[% INCLUDE "file.tt" WITH foo = 42, bar = 3.14 %]
[% INCLUDE "file.tt" WITH
    foo = 42
    bar = 3.14
%]

The WRAPPER statement is also supported. BUT β€” the argument of WRAPPER must be string literals, because templates get statically linked while compiling. no cap ✨

[% WRAPPER "file.tt" %]
Hello, world!
[% END %]

%%# with variable
[% WRAPPER "file.tt" WITH title = "Foo!" %]
Hello, world!
[% END %]

The content gets set into content, but you can specify its name with the INTO keyword:

[% WRAPPER "foo.tt" INTO wrapped_content WITH title = "Foo!" %]
...
[% END %]

This is basically syntactic sugar for template cascading πŸ“ Here's the counterpart of the example in Kolon:

: macro my_content -> {
    Hello, world!
: }
: cascade "file.tx" { content => my_content() }
⚠️ Heads up: the WRAPPER option (http://template-toolkit.org/docs/manual/Config.html#section_WRAPPER) in Template-Toolkit is not supported directly. Instead, you can emulate it with the header and footer options, like this:
my %vpath = (
    wrap_begin => '[% WRAPPER "base" %]',
    wrap_end => '[% END %]',

    base => 'Hello, [% content %] world!' . "\n",
    content => 'Xslate',
);

my $tx = Text::Xslate->new(
    syntax => 'TTerse',
    path => \%vpath,

    header => ['wrap_begin'],
    footer => ['wrap_end'],
);

print $tx->render('content'); # => Hello, Xslate world!;

🌸 Macro blocks

Definition:

[% MACRO foo BLOCK -%]
    This is a macro.
[% END -%]

[% MACRO add(a, b) BLOCK -%]
[%  a + b -%]
[% END -%]

Call:

[% foo()     %]
[% add(1, 2) %]
⚠️ Unlike Template-Toolkit, calling macros requires parens (()). yes you have to, bestie 😀

🌸 Virtual methods

A few methods are supported in the Xslate core:

%% a.size();
%% a.join(", ");
%% a.reverse();

%% h.size();
%% h.keys();
%% h.values();
%% h.kv();

BUT there's a whole bridge mechanism that lets you use external methods πŸ‘‘ For example, Text::Xslate::Bridge::TT2 provides the TT2 virtual methods for Xslate, which bridges the Template::VMethods implementation:

use Text::Xslate::Bridge::TT2;

my $tx = Text::Xslate->new(
    syntax => 'TTerse',
    module => [qw(Text::Xslate::Bridge::TT2)],
);

print $tx->render_string('[% "foo".length() %]'); # => 3

See Text::Xslate::Bridge, or search for Text::Xslate::Bridge::* on CPAN πŸ¦‹

🌸 Misc.

CALL evaluates expressions, but it does not print them:

[% CALL expr %]

SET and assignments exist, although using them is strongly discouraged 😭:

[% SET var1 = expr1, var2 = expr2 %]
[% var = expr %]

DEFAULT statements, as a syntactic sugar for SET var = var // expr:

[% DEFAULT lang = "TTerse" %]

And FILTER blocks, to apply filters to text sections:

[% FILTER html -%]
Hello, <Xslate> world!
[% END -%]

✨ COMPATIBILITY ✨

There are some differences between TTerse and Template-Toolkit, and honestly they matter, so let's go πŸ’€

  • INCLUDE of TTerse requires an expression for the file name, while Template-Toolkit's allows a bare token:
[% INCLUDE  foo.tt  # doesn't work! %]
[% INCLUDE "foo.tt" # OK %]
  • FOREACH item = list is forbidden in TTerse. It must be FOREACH item IN list.
  • TTerse does not support plugins (i.e. the USE directive), BUT it understands the USE keyword as an alias to CALL. So you could use some simple plugins that don't depend on the context object of Template-Toolkit 🌈
use Template::Plugin::Math;
use Template::Plugin::String;

my $tt = Text::Xslate->new(...);

mt %vars = (
    Math   => Template::Plugin::Math->new(),   # as a namespace
    String => Template::Plugin::String->new(), # as a prototype
);
print $tt->render_string(<<'T', \%vars);
[% USE Math # does nothing actually, only for compatibility %]
[% USE String %]
[% Math.abs(-100)          # => 100 %]
[% String.new("foo").upper # => FOO %]
  • The following directives are not supported: INSERT, PROCESS, BLOCK as a named blocks, USE (but see above πŸ‘†), PERL, RAWPERL, TRY, THROW, RETURN, STOP, CLEAR, META, TAGS, DEBUG, and VIEW.

Some might be supported in a future πŸ‘€ (manifesting it fr fr πŸ™)


✨ SEE ALSO ✨

  • Text::Xslate
  • Template (Template::Toolkit)
  • Template::Tiny
  • Text::Xslate::Bridge::TT2
  • Text::Xslate::Bridge::TT2Like
  • Text::Xslate::Bridge::Alloy

okay that's the whole thing bestie, you ate that reading session πŸ’…βœ¨ this page ships with perl v5.42.3 and it's dated 2026-08-22 β€” go forth and render, mwah πŸŽ€πŸ¦‹πŸ’–

πŸ“¦ where this page comes from