Statements
Capek supports a number of standard statements:
if
andswitch
statements to generate text based on conditions,for
loops,choices
to support alternative wordings,for_choices
to support a sequence of alternatives,set
andcapture
to set variables to a certain value,macro
to define reusable templates.
Common properties
Statements are of two types:
- a simple statement:
{% ... %}
; for example,{% set a = expression %}
- a block:
{% block %}
and{% end_block %}
; for example,{% for i in list %} ... {% end_for %}
For all statements, it is possible to control the surrounding whitespace:
- trim leading whitespace:
{%- tag %}
- trim trailing whitespace:
{% tag -%}
- trim leading and trailing whitespace:
{%- tag -%}
Conditions
For cases where the message content depends on data we use classic conditions directly in text:
{% if <condition> %} text {% endif %}
{% if <condition> %} text {% else %} text2 {% endif %}
{% if <condition> %} text {% elif <condition2> %} text2 {% else %} text3 {% endif %}
{% switch expression %}
{% case 10 %}text1
{% case 20 %}text2
{% default %}text3
{% endswitch %}
Loops
To iterate over items in a sequence or a dictionary, we use a for loop.
A loop can iterate either over a list or a map.
For example, this template
{% for i in [1,2,3] %}
i={{i}}: i²={{i*i}}
{% endfor %}
produces:
i=1: i²=1
i=2: i²=4
i=3: i²=9
while this template
{% for k,v in {1: "a", 2: "b", 3: "c"} %}
{{k}} -> {{v}}
{% endfor %}
produces:
1 -> a
2 -> b
3 -> c
When combined with the unitNum
filter:
{% for q,u in {5: "box", 1: "bottle", 30: "cup"} %}
{{q|unitNum(u)}}
{% endfor %}
we can get the following for English:
five boxes
one bottle
30 cups
Inside loops, there is a special variable loop
with information about the iteration.
loop.length
- size of the iterated collectionloop.index
- the current iteration of the loop. (1-indexed)loop.index0
- the current iteration of the loop. (0-indexed)loop.revindex
- the number of iterations from the end of the loop (1-indexed)loop.revindex0
- the number of iterations from the end of the loop (0-indexed)loop.first
- true if the first iterationloop.last
- true if the last iteration
Alternatives
A random choice between multiple alternatives is supported with the choices
tag.
For example, this template
{% choices %}
{% case %}text1
{% case %}text2
{% case %}text3
{% endchoices %}
randomly outputs either text1, text2, or text3.
All choices are equally probable.
To influence the relative probability, we can use the weight
parameter:
{% choices %}
{% case weight=40 %}text1
{% case weight=20 %}text2
{% case %}text3
{% endchoices %}
In this case, text1 will be twice as likely to be selected as text2,
which in turn will be twice as likely as text3 (weight=10
is the default).
We can also add conditions blocking individual choices.
So, for example, the following template
{% choices %}
{% case condition=(i>20) %}text1
{% case %}text2
{% endchoices %}
outputs text1 only if the variable i
is greater than 20.
Looped alternatives
The for_choices
tag combines the functionality of a for
loop with a random choice of alternatives,
similar to the choices
tag:
{% for_choices i in [1,2,3,4,5] %}
{% case %} The {{i | ord_numeral_in_words }} option is great.
{% case %} Option {{i}} is a good option .
{% case %} Let's not forget the option {{i|numeral}}.
{% endfor_choices %}
can generate for example::
Option 1 is a good option.
The second option is great.
Option 3 is a good option.
Let's not forget the option 4.
The fifth option is great.
Inside for_choices
, it is possible to use the loop
variable
with information about the iteration in the same way as within a for
loop.
The probability of generating a particular case can be influenced by the weight
parameter:
{% for_choices i in [1,2,3,4,5] %}
{% case weight=40 %}text1
{% case weight=20 %}text2
{% case %}text3
{% endfor_choices %}
In this case, text1 will be twice as probable as text2,
which in turn will be twice as probable as text3 (weight=10
is the default).
We can also add conditions blocking individual choices. So, for example, the following template
{% for_choices i in [1,2,3] %}
{% case condition=(loop.first) %}text1
{% case %}text2
{% case %}text3
{% case condition=(loop.last) %}text4
{% endfor_choices %}
can produce text1 only in the first iteration, and text4 only in the last iteration, while text2 and text3 can be output in any iterations. Therefore, the result can be for example::
text1
text2
text4
or:
text2
text2
text2
or:
text1
text3
text2
Variables
A variable can be assigned a value by the set
or capture
statements.
The set
statement is used to assign the result of an expression.
For example, the following template
{% set v = "abc" | upper %}
{{ v }}{{ v }}
produces:
ABCABC
The capture
statement is used to capture the contents of the enclosed block into a variable.
Therefore, the following template
{% capture v %}some content{% endcapture %}
{{ v }} and {{ v }}
produces:
some content and some content
Macros
In cases when a certain template is used repeatedly, we can pre-define it as macro:
{% macro cmpAdverb(diff) %}
{% if diff > 0 %} less {% else %} more {% endif %}
{% endmacro %}
and then call the macro when necessary (it does not have to be in the beginning of the document, but it needs to be defined before it is used):
Year-to-year, gas costs {{region.price.diesel.y1Diff\|abs}} cents {{cmpAdverb(region.price.diesel.y1Diff)}}.
produces results such as these, depending on the value of region.price.diesel.y1Diff
:
- Year-to-year, gas costs 30 cents less.
- Year-to-year, gas costs 30 cents more.