Status & Roadmap
Authors & License
Funding Ultimate++
Search on this site

SourceForge.net Logo




The first phase in compilation of witz templates is preprocessing. Preprocessing itself can be broken to include phase, when other template or template snippets are combined to form single body and subblock replacement phase, when all references to subblocks are replaced with defined subblocks.


#include path


This attempts to retrieve and include another witz template into current body. Witz preprocessor attempts to retrieve language specific version of template first, then defaults to common version.


#define id


This starts a new template subblock which ends with another subblock. First subblock (the one before first #define is encountered) has id "MAIN". The value of "MAIN" subblock represents the template at the end of preprocessing process.




Occurence of # followed by id that is neither "include" or "define" inserts a subblock defined by #define id. This process is recursive - subblock keep replacing until there are no more #id in the block, however any id can be replaced only once (to avoid infinite recursion). If id is encountered for which there is no corresponding #define, original text is left unchanged. If there are more definition for single id, the last one is used. ## is always replaced with single #.











#define TITLE Generic title




#include base

#define TITLE The page title

#define BODY

<b><i>Hello world!</i></b>


Witz code


Witz code is marked by '$' character (the end of code within template is determined by syntax rules, in rare situations you might have to enclose expressions in parenthesis). Character '$' can be escaped to be inserted into text as '$$'.




The type of values processed by Witz is basically equal to U++ Value. Skylark understands some of Value types and perform operations on them (like arithmetics for numbers, concatenating Strings), but generally any Value can be yielded by expression evaluation (either come from handler variables, or be created by function). Skylark always uses .ToString method of Value to convert final expression value before inserting it to the document.


Witz primary values come from shared variable space of Skylark handler; the only other way to define a new variable is by using for statements. Variable names follow C/C++ rules, '.' before variable designates session variable, '@' designates cookie.


There are also value literals, generally following JavaScript syntax:


numbers: 1, -100, 1.23

strings: "string"

arrays: [1, "hello", 123]

maps: { "key1":"value1", "key2":123 }




When expressions are used as logical values, then:


if expression yields a number (int, int64, double, bool), it is false if it is Null or zero, true otherwise

if expression yields a ValueArray, it is false if ValueArray is empty, true otherwise

in other cases, it is false if expression is Null, true otherwise (note that this means that empty String is false, non-empty true).


In following table, thick lines divide operators with the same priority, with topmost items having the highest priority:





Map value at key. If there is no such


Same as map["field"]. Note that there are 4 special pseudo-fields with different meaning.


Variable must be control variable of for cycle. Returns true if current iteration is first.


Variable must be control variable of for cycle. Returns true if current iteration is last.


Variable must be control variable of for cycle. Returns zero-based index of iteration.


Variable must be control variable of for cycle. Returns the key when iterating the map.


Array element at position index.

function(value1, value2, ...)

Call to function (functions are defined in C++).

handler(value1, value2, ...)

If the id before '(' represents Skylark handler, then what looks like function call gets actually translated to into the URL link to Skylark handler function, replacing value parameters at their corresponding positions in the URL, so they act as handler parameters.


Unary minus.


Bit-wise complement.


Logical not. 1 when value represents false, 0 otherwise.

number * number


number / number


number % number


String + String

Concatenates Strings.

number + number


number - number


number << number

Shift left.

number >> number

Shift right.

number < number

number > number

number <= number

number >= number

Comparison of numbers.

String < String

String > String

String <= String

String >= String

Comparison of Strings.

value == value


value != value


number & number

Binary and.

number ^ number

Binary xor.

number | number

Binary or.

value && value

Logical and. If first value is false, second value is not evaluated, just skipped.

value || value

Logical or. If first value is true, second value is not evaluated, just skipped.

value ? value : value

Conditional expression. Only necessary expressions are evaluated.





Note that for structured statements, '$/' is an alternative to '$endfor' and '$endif'.





Expression. It gets evaluated and the result is put into the document.



$endif or $/

Conditional statement.





$endif or $/

Conditional statement with else clause.

$for(variable in array_or_map)


$endfor or $/



Loop iterating through ValueMap or ValueArray. Variable is assigned all values of container while special pseudo-fields are provided for this value:


._first true if element is first in the container

._last true if element is last in the container

._index index of element

._key if container is a map, returns the key of current element


$for(variable in array_or_map)




$endfor or $/


The optional else clause is invoked if no iteration is performed (map or array is empty).


Standard library




cycle(i, p1, ..., pn)

Returns p[i mod n].


Returns argument as "raw" text that is not supposed to be html escaped.


Returns the number of elements in ValueArray or ValueMap; 0 if parameter is neither.


Returns a complete definition of FORM hiddent field needed for CSRF attack prevention.


Returns a script required that provides CSRF protection for AJAX POSTs.


Returns html formatted list of current shared variables. Useful for debugging.

render(witz_template, p1, ...)

Inserts another template into output. Current variables are copied to new template, parameters p1... are copied as $_1, $_2 etc. This is similar to using #include, but with it is easier to pass arguments to included template this way.


Last edit by cxl on 12/02/2017. Do you want to contribute?. T++