---
name: "Text::Xslate::Syntax::TTerse"
section: "3pm"
platform: "linux"
package: "libtext-xslate-perl"
version: "3.5.9-2+b1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Text::Xslate::Syntax::TTerse"
---

# Text::Xslate::Syntax::TTerse(3pm)

An alternative syntax compatible with Template Toolkit 2

## NAME

Text::Xslate::Syntax::TTerse - An alternative syntax 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

TTerse is a subset of the Template-Toolkit 2 (and partially  3) syntax, using `"[% ... %]"` tags and `"%% ..."` line code.

Note that TTerse itself has few methods and filters while Template-Toolkit 2 has a lot. See `"Text::Xslate::Bridge::*"` modules on CPAN which provide extra methods and filters if you want to use those features.

(TODO: I should concentrate on the difference between Template-Toolkit 2 and TTerse)

## SYNTAX

This supports a Template-Toolkit compatible syntax, although the details might be different.

Note that lower-cased keywords, which are inspired in Template-Toolkit 3, are also allowed.

### 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.

If *$var* is an object instance, you can call its methods.

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

### Expressions

Almost the same as Text::Xslate::Syntax::Kolon, but `"infix:<_>"` for concatenation is supported for compatibility.

### Loops

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

Loop iterators are partially supported.

```
    [% 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"` doesn't accept a HASH reference, so you must convert HASH references to ARRAY references by `keys()`, `values()`, or `kv()` methods.

Template-Toolkit compatible names are also supported, but the use of them is discouraged because they are 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, namely `"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 %]
```

`"WITH variables"` syntax is also supported, although the `"WITH"` keyword is optional 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. The argument of `"WRAPPER"`, however, must be string literals, because templates will be statically linked while compiling.

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

The content will be 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 a syntactic sugar to template cascading. Here is a counterpart of the example in Kolon.

```
    : macro my_content -> {
        Hello, world!
    : }
    : cascade "file.tx" { content => my_content() }
```

Note that 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 `"header"` and `"footer"` options as follows:

```
    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 (`"()"`).

### 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();
```

However, there is a bridge mechanism that allows you to use external methods. For example, Text::Xslate::Bridge::TT2 provides the TT2 virtual methods for Xslate, which bridges 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 does not print it.

```
    [% CALL expr %]
```

SET and assignments, although the use of them are strongly discouraged.

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

DEFAULT statements as a syntactic sugar to `"SET var = var // expr"`:

```
    [% DEFAULT lang = "TTerse" %]
```

FILTER blocks to apply filters to text sections:

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

## COMPATIBILITY

There are some differences between TTerse and Template-Toolkit.

- •

  `"INCLUDE"` of TTerse requires an expression for the file name, while that of Template-Toolkit 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. `"USE"` directive), but understands the `"USE"` keyword as an alias to `"CALL"`, so you could use some simple plugins which do not 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.

## SEE ALSO

Text::Xslate

Template (Template::Toolkit)

Template::Tiny

Text::Xslate::Bridge::TT2

Text::Xslate::Bridge::TT2Like

Text::Xslate::Bridge::Alloy
