Skip navigation links
Expressively and easily automate your text documents with TExpressive!
Expressively and easily automate your text documents with TExpressive!

Language syntax

Scripts and text

TExpressive templates contain both plain text and scripts.  The plain text is used as-is, and the scripts are first processed after which their result is added to the output.  Scripts use the format:

<# ... #>

where the ... denotes the script's content.

When you put more than one function in a script, you need to seperate these functions from each other with a ";".

Using script start and end delimiters in normal text

When you want to include the special TExpressive script start and end delimiters (<# and #>) in your normal text, you have to double them.  So, the text fragment

before <#<#inside#>#> after

will be processed to:

before <#inside#> after


The content of comments is not processed by TExpressive.  Their content will not appear in the final output.  Comments can appear everywhere in scripts but not in literal texts.  Comments can be nested.

The format of comments is:

{ ... }

An example:

  • <# { comment containing a <#script fragment#> which will not be processed } #>

Name validity

There are several places where TExpressive expects a name.  Names are used in functions (the function name and argument names) and in parameters (the parameter name and subparameter names).  There is a single common rule determining the validity of names: they may only contain the characters "a" to "z", "A" to "Z", "0" to "9", "-" and "_".  TExpressive is not case-sensitive when handling names.  Note however that names starting with a "_" are reserved for use by TExpressive itself; it's not advisable to start your own names with a "_".  See the list of predefined parameters for more information.

The format of names is:

a-z | A-Z | 0-9 | - | _

Some examples:

  • MyName
  • 2345
  • another-name_9_all-allowed


All indexes in TExpressive start at 1.  So the first character in a text is at position 1, the first subparameter can be found at index 1 and loops (For, ForEach, While and Until) start at loop number 1.


Functions have a few things in common.  They are written in scripts (between <# and #>), they have a function name and 0 or more arguments.  Each argument has a name and optionally a value.  The value, if present, is separated from the argument name by a ":"

There are three types of argument values you can specify: literal text (text within quotes which is used as-is; e.g. "texts"), parameter names (whose value will be used for the argument) and script fragments (which are processed separately after which the result is stored in the argument).

Literal text is great for using simple textual or numerical values.  Literal text can contain all characters, including line endings; these are retained in the final result.  To insert the quotation mark itself, you have to double it.  Parameters allow you to store information in one part of your TExpressive script and use it again in another part.  Script fragments allow you to (conditionally) process sub-scripts.  Script fragments temporarily start a new subcontext with ( which is closed again by a matching ).  Once the script fragment is fully evaluated, the result (a text fragment) is stored in the argument.  This way you can, in an easy manner, compose more complex values to assign to arguments.

Between each part of a function you are allowed to place whitespace, including line breaks.  These will have no effect on the final result.

The format of functions is:

FunctionName [Arguments]
a valid name
Argument [Argument [Argument [...]]]
a valid name
"literal text" | ParameterName | (ScriptFragment)
a valid parameter name (incl. indices)
functions and comments

Some examples:

  • <#
      Set Param:"PetName" To:(
          Count What:"z" In:PetName


TExpressive allows you to set up parameters to store and later retrieve values.  This way you can transfer information from one part of your script to another.

The parameters can be nested to form a parameter tree (parameters containing subparameters); there is no limit to the depth of this nesting.  To access a subparameter you have to specify the parameter path to it.  Separate parts in the parameter path must be separated with a ".".  You can access subparameters again by using their name (mainparam.subparam) or by using their sequence number under the main parameter (e.g. mainparam.#2).  Sequence numbers may also be negative; in that case TExpressive starts counting from the last sub parameter backwards.  Sequence number -1 thus is the last sub parameter, -2 is the next to last, etc.  Note that sequence numbers may not contain whitespace between the "#" and the number.

Wherever you can specify a parameter, you can also specify a parameter path.  It is not allowed to have two same-named subparameters under the same parent parameter.

Some functions allow you to create (sub)parameters without specifying a name for them.  In that case TExpressive assigns a unique name to that parameter.  The name will be "Param<nr>" where "nr" is a sequence number so that it will not conflict with any other subparameters surrounding it.

The format of parameter path and parameter names is:

ParameterName | ParameterNr
a valid name
#<index number>

Some examples:

  • MyParam
  • MainParam.#2.SubSubParam