## 3 Template Syntax Reference

### 3.1 Whitespace

It often makes templates more readable to include extra whitespace around statements. In particular, the CamlTemplate syntax encourages a style in which each statement is on a line by itself, possibly indented. This means that there is extra whitespace around the statement: the indentation preceding it, and the newline after it. However, it is often not desirable to include that extra whitespace in the output. To support this, CamlTemplate ignores whitespace in certain contexts. The basic rules are as follows:

- When a line begins with whitepace followed by `#`, that whitespace is ignored.
- When a newline follows the closing parenthesis of a statement, or a keyword such as `#else`, the newline is ignored.

Thus a statement or keyword on a line by itself 'disappears' from the output (except for any output produced by the statement itself). Consider the following template:

    #macro sayHello()
    Hello.
    #end
    #if (true)
      #sayHello()
    #end

This will print a single line of text, consisting of `Hello.` followed by a newline.
Another example:

    #macro sayHello()
    Hello.
    #end
    #if (true)
    The greeting is: #sayHello()
    #end

This will print:

    The greeting is: Hello.

Note that since the call to `#sayHello()` does not fall at the beginning of a line, the space after the colon is preserved.
It is often convenient to put a comment at the end of a line, like this:

    #if (showGreeting)
    ${greeting} #* Display the greeting *#
    #end

The rule for comments is therefore slightly different in one respect: whitespace preceding a comment is always ignored (even if it doesn't start at the beginning of a line), and a newline following a comment is ignored. The above example will print the value of `greeting`, with no additional whitespace or newlines.
In other contexts where a newline makes the template more readable, but you don't want to include it in the output, you can precede it with a backslash; both the backslash and the newline will be ignored, e.g.:

    #if (true)
    yes\
    #end

This will print `yes` with no newline.

### 3.2 Comments

> `#*` comment `*#`

Comments can be nested.

### 3.3 Escaping Characters

When used literally (rather than to indicate an expansion or a statement), `${` and `#` must be escaped with a backslash:

    \${
    \#

Additional backslashes preceding an escape sequence are simply included in the output, as are backslashes not followed by `${` or `#`.

### 3.4 Expansions

> `${`expression`}`

Adds the value of expression (which must evaluate to a scalar) to the output.

### 3.5 Statements

A statement begins with a `#` character followed by a keyword. When a statement has a body, it is terminated by `#end`. If you need `#end` to be followed by a letter, you can write `#end#`; similarly, you can write `#else#` instead of `#else`. This makes it possible to write a template without newlines, e.g.:

    There #if (n == 1)is 1 file#else#are ${n} files#end#.

#### 3.5.1 foreach

> `#foreach` (name in expression)

> > template text

> `#end`

Evaluates expression as a list; iterates over the list, assigning each element in turn to name. Any previous value of name is temporarily hidden.

#### 3.5.2 if

> `#if` (expression)

> > template text

> `#elseif` (expression)

> > template text

> `#else`

> > template text

> `#end`

The `#elseif` and `#else` blocks are optional; any number of `#elseif` blocks may be used. You can write `#else#` instead of `#else`.

#### 3.5.3 set

> `#set` (name `=` expression)

Assigns the value of expression to the variable name in one of the following places, in order of preference:

1. In macro scope, if invoked in macro scope and the variable already has a value there.
2. In template scope.

#### 3.5.4 var

> `#var` (name)
> `#var` (name `=` expression)

Assigns the value of expression (or a null value if expression is not supplied), to the variable name in one of the following places, in order of preference:

1. In macro scope, if invoked in macro scope.
2. In template scope.

#### 3.5.5 include

> `#include` (expression)

Interprets the string value of expression as the name of a template, and includes the contents of that template in the one currently being processed.

#### 3.5.6 Macro Definition

> `#macro` macroname (paramname1, paramname2, ... paramnamen)

> > template text

> `#end`

Defines a macro called macroname that takes n parameters.

#### 3.5.7 Macro Invocation

> `#`macroname (param1, param2, ... paramn)

Invokes the macro called macroname. If a macro is called with fewer parameters than were defined in the macro, the remaining parameters are set to null.

#### 3.5.8 open

> `#open` (expression)

Interprets the string value of expression as the name of a template, and adds it to the list of templates in which macros will be searched for when invoked in the currently running template.

### 3.6 Expressions

#### 3.6.1 Data Types

- Scalar:
  String
    A string literal is enclosed in double quotes: `"`string`"`). A double quote in a string literal must be escaped by preceding it with a backslash. The escapes `\t` (tab), `\r` (carriage return) and `\n` (newline) can also be used; `\\` produces a backslash.
  Integer
    An integer literal is a sequence of one or more digits, optionally preceded by a minus sign. For convenience and readability, underscore characters (_) are accepted (and ignored) within integer literals.
  Float
    A floating-point literal consists of an integer part, a decimal part and an exponent part. The integer part is a sequence of one or more digits, optionally preceded by a minus sign. The decimal part is a decimal point followed by zero, one or more digits. The exponent part is the character e or E followed by an optional + or - sign, followed by one or more digits. The decimal part or the exponent part can be omitted, but not both (to avoid ambiguity with integer literals). For convenience and readability, underscore characters (_) are accepted (and ignored) within floating-point literals.
  Boolean
    The boolean literals are `true` and `false`.
- Hash. Keys are identifiers, values are any template data type.
- List. Values are any template data type.
- Null. A nonexistent value of any type is represented as null. The null literal is `null`.

#### 3.6.2 Conversions

Scalar types are converted to other scalar types automatically. When an operator has one integer operand and one float operand, the integer is promoted to a float. Otherwise, the interpreter attempts to convert the right-hand side of an expression to the type of the left-hand side, and raises `Template_error` if this not possible.
Any value can be compared with a boolean or null value. All scalar values are equal to `true` except integer 0 and the empty string; a null value is equal to `false`. All list and hash values are equal to `true` except the empty list. The string and integer values of `true` are `"true"` and 1, respectively; the string and integer values of `false` are `""` (the empty string) and 0.

#### 3.6.3 Identifiers

The characters allowed in identifiers are upper-case and lower-case ASCII letters, digits, the underscore and the apostrophe. The first character of an identifier must be an ASCII letter.

#### 3.6.4 Operators

Table 1 lists the operators supported in expressions. Standard operator precedence applies, and can be overridden using parentheses.

> Operator | Meaning | Compatible Types
> ! | unary not | boolean values
> - | subtraction, unary negation | integers, floats
> + | addition, string concatenation | integers, floats, strings
> * | multiplication | integers, floats
> / | division | integers, floats
> % | modulo | integers, floats
> == | equality | scalars
> != | inequality | scalars
> < | less than | integers, floats, strings
> > | greater than | integers, floats, strings
> <= | less than or equal to | integers, floats, strings
> >= | greater than or equal to | integers, floats, strings
> && | and | boolean values
> || | or | boolean values
> . | hash lookup with identifier as key | hash on left, identifier on right
> [] | hash lookup with string as key | hash on left, string on right
> () | function call | function on left, comma-separated expressions in parentheses
> = | assignment | identifier on left, expression on right

> Table 1: Operators