Expressions
Literals
Literals are the most straightforward form of expressions. Literals are representations for types such as strings, numbers, and arrays. Here are the existing literals:
String:
"Hello World"
- Any content between two double or single quotes is considered a string. Strings are essential when a template requires a text value, whether as function arguments, filters, or for template extension or inclusion. A delimiter inside a string can exist if preceded by a backslash, as in'It\'s good'
. To escape a string containing a backslash (like 'c:\Program Files'), double the backslash, e.g.,'c:\\Program Files'
.Numbers:
42 / 42.23
- Writing down a number creates integers and floating-point numbers. If a dot appears, the number is a float; otherwise, it's an integer.Arrays:
["foo", "bar"]
- Arrays consist of a series of expressions separated by commas and enclosed in square brackets.Hashes:
{"foo": "bar"}
- Hashes are formed by a list of keys and values separated by commas and wrapped in curly braces:{# keys as string #} { 'foo': 'foo', 'bar': 'bar' } {# keys as names (equivalent to the previous hash) #} { foo: 'foo', bar: 'bar' } {# keys as integer #} { 2: 'foo', 4: 'bar' } {# omitting keys when it matches the variable name #} { foo } {# this is the same as: #} { 'foo': foo } {# keys as expressions (enclose the expression in parentheses) #} { (foo): 'foo', (1 + 1): 'bar', (foo ~ 'b'): 'baz' }
Boolean:
true / false
- The valuetrue
signifies true, whilefalse
denotes false.Null:
null
- This symbolizes no specific value and is the outcome when a variable is absent.none
is synonymous withnull
.
Arrays and hashes can also be nested:
{% set foo = [1, {"foo": "bar"}] %}
Math
The template engine empowers you to carry out mathematical operations within templates. Below are the supported mathematical operators:
Addition (+): Adds two numbers together. Both operands are converted to numbers.
{{ 1 + 1 }} {# returns 2 #}
Subtraction (-): Deducts the second number from the first.
{{ 3 - 2 }} {# returns 1 #}
Division (/): Divides two numbers, producing a floating-point result.
{{ 1 / 2 }} {# returns 0.5 #}
Modulus (%): Provides the remainder from an integer division.
{{ 11 % 7 }} {# returns 4 #}
Floor Division (//): Divides two numbers and furnishes the floored integer outcome.
{{ 20 // 7 }} {# returns 2 #} {{ -20 // 7 }} {# returns -3 #}
This is essentially a shorthand for the round filter.
Multiplication (*): Multiplies the operands.
{{ 2 * 2 }} {# returns 4 #}
Power (**): Elevates the left operand by the right operand's power.
{{ 2 ** 3 }} {# returns 8 #}
Logic
You have the flexibility to combine multiple expressions utilizing the following operators:
and: Validates as true only if both the left and right operands are true.
{% if var1 and var2 %} ... {% endif %}
or: Affirms as true if either the left or right operand is true.
{% if var1 or var2 %} ... {% endif %}
not: Functions to negate a statement.
{% if not var1 %} ... {% endif %}
(expr): Facilitates in grouping an expression.
{% if (var1 and var2) or var3 %} ... {% endif %
Comparisons
The template engine supports a range of comparison operators in any given expression, including: ==
, !=
, <
, >
, >=
, and <=
.
You can evaluate if a string commences or concludes with a certain string:
{% if 'Hello' starts with 'H' %}
...
{% endif %}
{% if 'Hello' ends with 'o' %}
...
{% endif %}
For asserting that one string encompasses another, you can utilize the containment operator (explained in the following section).
Containment Operator
The in
operator assesses containment. It renders as true if the left operand is found within the right:
{# This returns true #}
{{ 1 in [1, 2, 3] }}
{{ 'cd' in 'abcde' }}
For negated containment tests, utilize the not in
operator:
{% if 1 not in [1, 2, 3] %}
...
{% endif %}
{# This is synonymous to #}
{% if not (1 in [1, 2, 3]) %}
...
{% endif %}
Test Operator
The is
operator facilitates tests. These tests allow a variable to be compared against standard expressions. The test's name serves as the right operand:
{# Testing if a variable is odd #}
{{ name is odd }}
Tests can also accept arguments:
{% if variable is divisible by(3) %}
...
{% endif %}
To negate tests, employ the is not
operator:
{% if variable is not divisible by(3) %}
...
{% endif %}
{# This is synonymous to #}
{% if not (variable is divisible by(3)) %}
...
{% endif %}
Go to the tests page to delve deeper into the inherent tests.
Other Operators
There are several operators that don't fit neatly into other categories:
|
: Used to apply a filter...
: Generates a sequence based on the preceding and following operand. Essentially, it's a shortcut for therange
function. If you wish to combine this with the filter operator, ensure to use parentheses due to operator precedence:(1..5)|join(', ')
{{ 1..5 }} {# equivalent to #} {{ range(1, 5) }}
~
: Transforms all operands to strings and joins them. So,{{ "Hello " ~ name ~ "!" }}
, assumingname
is 'John', will yieldHello John!
..
,[]
: Fetches an attribute of a variable.?::
The ternary operator:{{ foo ? 'yes' : 'no' }} {{ foo ?: 'no' }} {# This is the same as {{ foo ? foo : 'no' }} #} {{ foo ? 'yes' }} {# This equates to {{ foo ? 'yes' : '' }} #}
??
: The null-coalescing operator:{# Yields the value of foo if it's defined and not null, otherwise 'no' #} {{ foo ?? 'no' }}
String Interpolation
String interpolation (#{expression}
) lets you embed any valid expression within a double-quoted string. The outcome of the evaluated expression is then inserted into the string:
{{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}
When rendered, if bar
is, for instance, 3
, the first line will yield foo 3 baz
. The second line will produce foo 3 baz
since the arithmetic operation is evaluated as 3
.
Last updated