|
HikoGUI
A low latency retained GUI
|
This template language was designed for code generation for different programming languages including HTML. The language was inspired by makotemplates.org, but with a simpler data model making it more easy to do more complicated stuff.
All assignments at the top level of a file will be added to the global scope. All assignments inside an included file are also made to the global scope.
Inside functions all assignments are done in the local scope of the function.
Loops do not introduce a new scope, all assignments within a loop will therefor be in either the global or local scope depending where the loop is defined. Some special read-only names prefixed with one or more '$' characters are available inside the loop.
Functions and blocks exist in a special global scope which only contains functions. #function or #block definitions which appear later in a file will override a previous definition. By calling super() from within a #function or #block you can call its previous definition.
The tt::datum class is used for holding and operating on all the data while executing an expression of the TTauri template language. A tt::datum class can hold the following types:
Expressions can be enclosed inside parenthesis '(' ')' to force precedence on the expression inside.
| Precedence | Operator | Description |
|---|---|---|
| 2 | expr '[' expr ']' | Subscripting |
| 2 | expr '(' args ')' | Function call |
| 3 | '+' expr | Unary plus |
| 3 | '-' expr | Unary minus |
| 3 | '~' expr | Bitwise not |
| 3 | '!' expr | Boolean not |
| 3 | '++' expr | Increment |
| 3 | '–' expr | Decrement |
| 4 | expr '.' name | Member |
| 4 | expr '**' expr | Power |
| 5 | expr '*' expr | Multiply |
| 5 | expr '/' expr | Divide / path-join |
| 5 | expr '' expr | Remainder |
| 6 | expr '+' expr | Addition / append |
| 6 | expr '-' expr | Subtraction |
| 7 | expr '<<' expr | Bitwise shift left |
| 7 | expr '>>' expr | Bitwise shift right with sign extend |
| 9 | expr '<' expr | Less than |
| 9 | expr '>' expr | Greater than |
| 9 | expr '<=' expr | Less than or equal to |
| 9 | expr '>=' expr | Greater than or equal to |
| 10 | expr '==' expr | Equal to |
| 10 | expr '!=' expr | Not equal to |
| 11 | expr '&' expr | Bitwise and |
| 12 | expr '^' expr | Bitwise xor |
| 13 | expr '|' expr | Bitwise or |
| 13 | expr '|' name | String filter |
| 14 | expr '&&' expr | Logical short-circuit and |
| 15 | expr '||' expr | Logical short-circuit or |
| 16 | expr '?' expr ':' expr | Ternary short-circuit operator |
| 16 | expr '=' expr | Assign |
| 16 | expr '+=' expr | Inplace add |
| 16 | expr '-=' expr | Inplace subtractions |
| 16 | expr '*=' expr | Inplace multiply |
| 16 | expr '/=' expr | Inplace divide / path-join |
| 16 | expr '%=' expr | Inplace remainder |
| 16 | expr '<<=' expr | Inplace shift left |
| 16 | expr '>>=' expr | Inplace shift right |
| 16 | expr '&=' expr | Inplace and |
| 16 | expr '^=' expr | Inplace xor |
| 16 | expr '|=' expr | Inplace or |
| 17 | expr '!' name | String filter |
Call a function with zero or more arguments.
A function is a name in special global scope with functions. Functions are build-in, passed by the developer when evaluating an expression, or added in the template by the user.
Syntax: ‘name ’(' ( expression ( ',' expression )* ','? )? ')'`
The string filter binary operator '!' implicitly converts the left hand side expression to a string, and passes this string through the filter name, yielding a new string.
Built in filters:
html: html-encode the string.xml: xml-encode the string.url: url-encode the string.id: Convert string to match [a-zA-Z_][0-9a-zA-Z_]*.An assignment operator is different from inplace-operations. An inplace-operation will modify a value of an existing variable. An assignment operator will create or replace a variable at the current scope.
The current scope is either the local scope of the function where the expression is located. Or in the global scope if the expression is located at the top level (outside of a function) of a template. control flow will not intruduce new scopes.
An assignment done in the local-scope will hide variables in global scope with the same name.
Assignment can be done on multiple variables at the same time, by unpacking into a vector literal.
Syntax: ‘name | expr ’=' expression`
Syntax: ‘’[' name | expr ( ',' name | expr )* ']' '=' expression`
Used by the user to denote a nothing value.
Syntax: null
Used by the system to denote a nothing value. This will be used temporarily when indexing a vector or map on a non existing key which may then be replaced with a new value.
Syntax: undefined
Syntax: true or false
Explicit conversion: boolean()
Operations available that work on a boolean (all datum will be implicitly converted to a boolean):
not boolean -> booleanboolean and boolean -> booleanboolean or boolean -> booleanboolean == boolean -> booleanboolean != boolean -> booleanboolean < boolean -> booleanboolean > boolean -> booleanboolean <= boolean -> booleanboolean >= boolean -> booleanA 64 bit signed integer in 2's compliment format.
Syntax: ‘[+-]?(0[bBoOdDxX])?[0-9a-fA-F’]+`
Explicit conversion: integer()
Operations available that work on a integer:
+ integer -> integer- integer -> integer++ integer -> integer-- integer -> integerinteger + integer -> integerinteger - integer -> integerinteger * integer -> integerinteger / integer -> integerinteger % integer -> integerinteger ** integer -> integerinteger | integer -> integerinteger & integer -> integerinteger ^ integer -> integer~ integer -> integerinteger >> integer -> integerinteger << integer -> integerinteger == integer -> booleaninteger != integer -> booleaninteger < integer -> booleaninteger > integer -> booleaninteger <= integer -> booleaninteger >= integer -> booleaninteger += integer -> integerinteger -= integer -> integerinteger *= integer -> integerinteger **= integer -> floatinteger /= integer -> integerinteger %= integer -> integerinteger &= integer -> integerinteger ^= integer -> integerinteger |= integer -> integerA decimal floating point format in the form mantissa + 10**exponent.
No literal available.
Explicit conversion: decimal()
Operations available that work on a decimal float (integer are implicitly converted to decimal):
+ decimal -> decimal- decimal -> decimaldecimal + decimal -> decimaldecimal - decimal -> decimaldecimal * decimal -> decimaldecimal / decimal -> decimaldecimal % decimal -> decimaldecimal ** decimal -> decimaldecimal == decimal -> booleandecimal != decimal -> booleandecimal < decimal -> booleandecimal > decimal -> booleandecimal <= decimal -> booleandecimal >= decimal -> booleandecimal += decimal -> decimaldecimal -= decimal -> decimaldecimal *= decimal -> decimaldecimal **= decimal -> floatdecimal /= decimal -> decimaldecimal %= decimal -> decimalround(decimal)floor(decimal)ceil(decimal)A binary floating point format in the form mantissa + 2**exponent.
Syntax: [0-9]+.[0-9]*([eE][-]?[0-9]+)? or [0-9]*.[0-9]+([eE][-]?[0-9]+)?
Explicit conversion: float()
Operations available that work on a binary float (integer and decimals are implicitly converted to float):
+ float -> float- float -> floatfloat + float -> floatfloat - float -> floatfloat * float -> floatfloat / float -> floatfloat % float -> floatfloat ** float -> floatfloat == float -> booleanfloat != float -> booleanfloat < float -> booleanfloat > float -> booleanfloat <= float -> booleanfloat >= float -> booleanround(float)floor(float)ceil(float)Syntax: "([^"]|\\")*"
The literal string may include escape sequences:
\"</tt> A literal double quote
- <tt>\\n</tt> A literal line feed
- <tt>\\r</tt> A literal carriage return
- <tt>\\t</tt> A literal tab
- <tt>\\f</tt> A literal form feed
Explicit conversion can be done using the <tt>string()</tt> function.
Operations available that work on a string:
- <tt>string + string -\> string</tt>
- <tt>string == string -\> boolean</tt>
- <tt>string != string -\> boolean</tt>
- <tt>string \< string -\> boolean</tt>
- <tt>string \> string -\> boolean</tt>
- <tt>string \<= string -\> boolean</tt>
- <tt>string \>= string -\> boolean</tt>
- <tt>string[integer] -\> string</tt>
- <tt>substr(string text, integer start, integer length) -\> string</tt>
- <tt>size(string text) -\> integer</tt>
- <tt>string | name -\> string</tt> Pass the string through the named-filter.
All datums are implicitly converted to a string.
Available filters:
- <tt>url</tt> For text that needs to be encoded inside a URL.
- <tt>xml</tt> For text that needs to be encoded inside a XML or HTML document.
@subsection autotoc_md145 URL
No literal available.
Explicit conversion: <tt>url()</tt>
Operations available that work on a string:
- <tt>url / url -\> url</tt>
- <tt>url / string -\> url</tt>
- <tt>url == url -\> boolean</tt>
- <tt>url != url -\> boolean</tt>
- <tt>url \< url -\> boolean</tt>
- <tt>url \> url -\> boolean</tt>
- <tt>url \<= url -\> boolean</tt>
- <tt>url \>= url -\> boolean</tt>
@subsection autotoc_md146 Vector
A list of <tt>tt::datum</tt> objects.
Syntax: '[' ( expression ( ',' expression )* ','? )? ']'
No explicit conversion available.
Operations available that work on a vector:
- <tt>vector + vector -\> vector</tt>
- <tt>vector == vector -\> boolean</tt>
- <tt>vector != vector -\> boolean</tt>
- <tt>vector \< vector -\> boolean</tt>
- <tt>vector \> vector -\> boolean</tt>
- <tt>vector \<= vector -\> boolean</tt>
- <tt>vector \>= vector -\> boolean</tt>
- <tt>vector += datum -\> vector</tt>
- <tt>vector[integer] -\> datum</tt>
- <tt>size(vector) -\> integer</tt>
- <tt>sort(vector) -\> vector</tt>
- <tt>vector.append(datum)</tt>
- <tt>vector.pop() -\> datum</tt>
@subsection autotoc_md147 Map
A unordered map of key / value pairs; both <tt>tt::datum</tt> objects.
Syntax: '{' ( expression ':' expression ( ',' expression ':' expression )* ','? )? '}'
Operations available that work on a map:
- <tt>map + map -\> map</tt>
- <tt>map == map -\> boolean</tt>
- <tt>map != map -\> boolean</tt>
- <tt>map \< map -\> boolean</tt>
- <tt>map \> map -\> boolean</tt>
- <tt>map \<= map -\> boolean</tt>
- <tt>map \>= map -\> boolean</tt>
- <tt>map[datum] -\> datum</tt>
- <tt>size(map) -\> integer</tt>
- <tt>contains(map, datum) -\> boolean</tt>
- <tt>keys(map) -\> vector</tt>
- <tt>values(map) -\> vector</tt>
- <tt>items(map) -\> vector[key, value]</tt>
@section autotoc_md148 Escape, Statements and placeholders
Statements and placeholders are used to generate text.
To make it so generated text will not include unexpected white space the following rules apply:
* White-spaces in front of a statement are removed up to the last new-line.
* The white-spaces and the linefeed after a statement is removed.
* An escape can remove a new-line.
* Text (including trailing white-spaces) are kept in front of a statement.
@subsection autotoc_md149 Escape sequences
The backslash is used to escape:
- End of line, mostly used for formatting inside loops.
- The <tt>\$</tt> dollar character used in placeholders.
- The <tt>\#</tt> hash character used in template statements.
- The <tt>\\</tt> backslash itself.
Example:
@icode
This placeholder is suppressed: \${12 + 24}
This backslash is suppressed: \\${12 + 24}
This line\
feed is suppressed.
@endicode
Result:
@icode
This placeholder is suppressed: ${12 + 24}
This backslash is suppressed: \36
This linefeed is suppressed.
@endicode
@subsection autotoc_md150 Placeholder
The placeholder is an expression that is evaluated and explicitly converted to a string.
This string will then be inserted into the text.
Syntax: '${' expression '}'
Example:
@icode
${12 + 24}
@endicode
Result:
@icode
36
@endicode
@subsection autotoc_md151 Expression Statement
Expressions can be evaluated as statements themselves. This is mostly useful for
doing assignment, modifying data or calling functions with side effects.
Expression statement will add text to the output.
At the top-level assignments are done in global scope. Inside functions and blocks assignments
are done in the local scope, even if the name already exists in the global scope.
Loops do not introduce scopes.
Syntax: '#' expression
If the expression starts with a keyword such as <tt>if</tt>, <tt>while</tt>, <tt>return</tt>, etc. A white space should be inserted
between the '#' and the expression.
Example
@icode
#foo = 42
# [foo, bar] = [foo + 2, 2]
${foo} ${bar}
@endicode
Result:
@icode
44 2
@endicode
@subsection autotoc_md152 Including files
The <tt>\#include</tt> statement is evaluated during parsing, by parsing the included file at the current position
recursively. An <tt>\#include</tt> statement can only appear at the top-level of each file, i.e. it can not be used
inside the body of a flow-control statement.
Functions and blocks that are included by the <tt>\#include</tt> statements are available in the global scope. See
the data model chapter.
The filename is an expression, this expression is evaluated during parsing.
When the filename argument is relative, the file is located relative to the current file.
It is recommended that the included files have the <tt>.tti</tt> (TTauri Include) extension,
and top-level template files have the <tt>.ttt</tt> (TTauri Template) extension.
Warning: There is no protection against including a file multiple times or recursively.
Syntax: ‘’#include' url-expression`
Example:
@icode
#include "foo.tti"
@endicode
Result:
@icode
This is the contents of foo.tti.
@endicode
@subsection autotoc_md153 If statement
Conditional <tt>\#if</tt> statement, with optional <tt>\#elif</tt> statments and optional end <tt>\#else</tt> statement.
The expression in the <tt>\#elif</tt> statements are only evaluated if the result of the previous <tt>\#if</tt> or <tt>\#elif</tt>
expressions where <tt>false</tt>.
Syntax:
- ‘’#if' boolean-expression '\n'<tt>
-</tt>'#elif' boolean-expression '\n'<tt>
-</tt>'#else' '\n'<tt>
-</tt>'#end' '\n'`
Example:
@icode
# foo = 5
#if foo == 2
Foo is two.
#elif foo == 3
Foo is three.
#elif foo == 4
Foo is four.
#else
Foo is ${foo}.
#end
@endicode
Result:
@icode
Foo is 5.
@endicode
@subsection autotoc_md154 For loop
A for loop iterates over the result of an the expression. Each iteration-result is
assigned to the name in front of the <tt>in</tt> keyword, optionally the iteration-result is
unpacked into multiple names.
It is possible to loop over strings, vectors and maps. A string will yield a single character string
on each iterations. A vector will yield a value on each iteration. A map will yield a vector with a key
and value on each iteration, sorted by key.
When unpacking multiple names, the number of names must match the size of the vector that was yielded
on each iteration.
The <tt>\#else</tt> part of the for loop is only executed when the result of the expression
has zero items.
Inside the loop extra variables are available for convenience:
- <tt>\$i</tt> or <tt>\$count</tt> integer index of the iteration
- <tt>\$size</tt> or <tt>\$length</tt> integer index of the iteration
- <tt>\$first</tt> is true if this is the first iteration
- <tt>\$last</tt> is true if this is the last iteration
- The extra variables created by an outer loop are prefixed with an extra <tt>\$</tt>.
Syntax:
- ‘’#for' name ( ',' name )* 'in' expression '\n'<tt>
-</tt>'#else' '\n'<tt>
-</tt>'#end' '\n'`
Example:
@icode
#for x in [1, 2, "hello"]
The value of x is ${x}.
#else
The list was empty.
#end
@endicode
Result:
@icode
The value of x is 1.
The value of x is 2.
The value of x is hello.
@endicode
@subsection autotoc_md155 While loop
A while loop executes a block multiple times until the expression yields <tt>false</tt>.
Inside the loop extra variables are available for convenience:
- <tt>\$i</tt> or <tt>\$count</tt> integer index of the iteration
- <tt>\$first</tt> is true if this is the first iteration
- The extra variables created by an outer loop are prefixed with an extra <tt>\$</tt>.
Syntax:
- ‘’#while' boolean-expression '\n'<tt>
-</tt>'#end' '\n'`
Example:
@icode
# i = 0
#while i < 3
Iteration ${i}.
# i = i + 1
#end
@endicode
Result:
@icode
Iteration 0.
Iteration 1.
Iteration 2.
@endicode
@subsection autotoc_md156 Do-while loop
A do-while loop executes a block at least once until the expression yields <tt>false</tt>.
Inside the loop extra variables are available for convenience:
- <tt>\$i</tt> or <tt>\$count</tt> integer index of the iteration
- <tt>\$first</tt> is true if this is the first iteration
- The extra variables created by an outer loop are prefixed with an extra <tt>\$</tt>
Syntax:
- ‘’#do' '\n'<tt>
-</tt>'#while' boolean-expression '\n'`
@icode
# i = 0
#do
Iteration ${i}.
# i = i + 1
#while i < 0
@endicode
Result:
@icode
Iteration 0.
@endicode
@subsection autotoc_md157 Continue and Break
Stop executing of a block inside a loop, then:
- <em>continue</em> with the next iteration of the loop or
- <em>break</em> out of the loop
Syntax:
- ‘’#continue' '\n'<tt>
-</tt>'#break' '\n'`
Example:
@icode
#for x in ["foo", "bar", "baz"]
#if x == "bar"
#continue
The value of x is ${x}.
#end
#for y in ["foo", "bar", "baz"]
#if y == "bar" #break The value of y is ${y}. #end Result:
FunctionDefine a function that can be called in expressions. A function with a return statement will simply return with its value. A function without a return statement will return its textual-output.
It is not possible for a function to return both textual-output and a value.
Functions with the same name will replace the previously defined function. The previously defined function is available as super() inside the function. This functionality together with the #include statement can be used for as a simple form of object-oriented-polymorphism.
Syntax:
-'#end' 'Example:
Result:
ReturnReturn data from a function
Syntax: ‘’#return' expression '
'`
Example:
Result:
Named blockA block is like a function without arguments which is automatically evaluated where it was first defined. A block can only return textual-output.
Like a function a block can be overridden by another block definition with the same name. The previously defined block is available as super(). This functionality together with the #include statement can be used for as a simple form of object-oriented-polymorphism.
Syntax:
-'#end'`Example:
Result: