Templates

Anathema has a template language to describe user interfaces. This makes it possible to ship the template(s) together with the compiled binary so the application can be customised without having to be recompiled.

The widget syntax looks as follows: <widget> <attributes> <value>

  Widget name                                         
  |    Start of (optional) attributes
  |    |    Attribute name                            
  |    |    |          Attribute value
  |    |    |          |     Attribute separator      End of attributes
  |    |    |          |     |                        | Values / Text
  |    |    |          |     |                        | |
  |    |    |          |     |                        | |------+-+-+
  |    |    |          |     |                        | |      | | |
widget [optional: "attribute", separated: "by a comma"] "text" 1 2 ident

Widgets don't receive events (only views does) and should be thought of as something that is drawn to the screen.

There is for instance no "input" widget. To represent an input widget the view would handle the key press, capture the char and write it to a state value, and in the template an input field could be written as text input_value.

Attributes

Widget attributes are optional.

Attributes consists of a collection of ident, :, and value (more about values in the next section).

An ident has to start with a letter (a-zA-Z) and can contain one or more _.

Example:

widget [attribute_a: "some string", attribute_b: false]

An attribute name is always an ident, however the value can be anything.

Values

A value can be one of the following:

  • string: "Empty vessel, under the sun"
  • integer: 123
  • float: 1.23
  • colour: #fab or #ffaabb
  • boolean: true or false
  • list: [1, 2, 3]
  • map: {"key": "value"}
  • ident: state_value

Idents are used to access state values.

Widgets and children

Some widgets can have one or more children.

Example: a border widget with a text widget inside

border
    text "look, a border"

Loops

Given a collection it's possible to loop over the elements of the collection. The syntax for loops are for <element> in <collection>.

Example: looping over static values

for value in [1, 2, "hello", 3]
    text value

Widgets generated by the loop can be thought of as belonging to the parent widget as the loop it self is not a widget.

Example: mixing loops and widgets

vstack
    text "start"
    for val in [1, 2, 3]
        text "some value: " val "."
    text "end"

The above example would render widgets as:

vstack
    text "start"
    text "some value: " 1 "."
    text "some value: " 2 "."
    text "some value: " 3 "."
    text "end"

Note: For-loops does not work inside attributes, and can only produce widgets.

If / Else

It's possible to use if and else to determine what to layout.

Example:

if true
    text "It's true!"
    
if value > 10
    text "Larger than ten"
else if value > 5
    text "Larger than five but less than ten"
else
    text "It's a small value..."

Operators

  • Equality ==
  • Greater than >
  • Greater than or equals >=
  • Less than <
  • Less than or equals <=
  • And &&
  • Or ||

Note: just like for-loops it's not possible to use if/else with attributes.