Introducing Ornament a Tcl Template Module

Ornament is a Tcl template module that allows you to define, parse and compile a template to produce a script which can then be run using a safe interpreter. The idea came from the Templates and subst page of the Tclers Wiki.

Ornament on GitHub

Ornament is licensed under an MIT licence and there is a repo on GitHub, from which you can download Ornament and where you can contribute to it. There is also an issues tracker where you can report bugs.

Module Commands

Ornament has two commands:

Takes a template and outputs a script to be evaluated with run
Takes a script created with compile and evaluates it using a safe interpreter to create its final output.


You control ornament using a commandChar in the first column of a line, this defaults to !. If you want to change the commandChar you can do so using the commandChar followed by *.

!# This is a command
!* commandChar %
%# commandChar is now %, so we have to use %# as a comment
%* commandChar !
!# Now we are back to where we started

The following Tcl script demonstrates how to use ornament.

package require ornament
namespace import ornament::*

# This is the template
set tpl {
!# You can configure ornament the defaults are:
!#    commandChar     !
!#    commandSubst    false
!#    variableSubst   false
!#    backslashSubst  false
!* commandSubst true variableSubst true backslashSubst true
This is some normal text
!# This is a comment and is ignored by `compile`
!# The following line will be executed as it begins with a `!` followed by a space
! for {set i 0} {$i < 5} {incr i} {
    Number: $i
! }

!# You can also use `!!` followed by a space instead of a `!`
!! set flow 152
flow: $flow

!# You can use `\` at the end of a line beginning with `!` or `!!` to
!# continue it
! set nums [list 1 2 \
                 3 4]
nums: $nums

!# Alternatively you can continue a line using `!\` at the start
!\ set letters [list a b
!                    c d]
letters: $letters

 ! Because the ! wasn't in the first column of the line, this line isn't executed
!# Below some variables are used that have been passed to the template:
Name: $name
Age: $age
!# Below a command is called that has been passed to the template:
I want to say: [greet $name]

!# You can change the command character to anyone of {! % @ ~}
!* commandChar %
% set nextAge [expr {$age + 2}]
nextAge: $nextAge
%* commandChar !

!# You can change whether variable substitution happens
!* variableSubst false
look at this: $nextAge
!* variableSubst true
and now: $nextAge

!# You can change whether command substitution happens
!* commandSubst false
look at this: [expr {5 + 6}]
!* commandSubst true
and now: [expr {5 + 6}]

!# You can change whether backslash substitution happens
!* backslashSubst false
look at this:\n
!* backslashSubst true
and now:\n

# int is the safe interpreter that is running the script
proc CmdGreet {greeting int name} {
  return "$greeting $name"

# You can pass commands to the template
set cmds [dict create greet [list CmdGreet "hello"]]

# You can pass variables to the template
set vars [dict create name Brodie age 37]

set script [compile $tpl]
puts [run $script $cmds $vars]

The script above gives the following output.

This is some normal text
    Number: 0
    Number: 1
    Number: 2
    Number: 3
    Number: 4

flow: 152

nums: 1 2 3 4

letters: a b c d

 ! Because the ! wasn't in the first column of the line, this line isn't executed
Name: Brodie
Age: 37
I want to say: hello Brodie

nextAge: 39

look at this: $nextAge
and now: 39

look at this: [expr {5 + 6}]
and now: 11

look at this:\n
and now:
Creative Commons License
Introducing Ornament a Tcl Template Module by Lawrence Woodman is licensed under a Creative Commons Attribution 4.0 International License.

Share This Post


Related Articles

xdgbasedir: A Tcl Module to Access the XDG Base Directory Specification

Unix has traditionally lacked a consistent way of storing user specific and system wide configuration and support files. This has lead to a mess of dot files in a user's home directory and other assoc...   Read More

Compiling a Tcl Script into an Executable

Locating Tcl scripts to load from an executable can be awkward if you want to make your program cross-platform. An easier way is to compile a Tcl script directly into the executable and let that scrip...   Read More

Embedding an SDL Surface in a Tk Window

Tk is great, but sometimes it just isn't fast enough. SDL is fast, but has no support for input dialogs and other GUI conventions. By embedding an SDL surface in a Tk window you get the best of both ...   Read More

Modula-2 Compilers on CP/M

Modula-2 is a great language in general and is a good choice for programming on CP/M. There are three good compilers available for CP/M which all require a Z80 processor and we'll compare each in turn...   Read More

Is SUBLEQ the Right Choice for a VM?

SUBLEQ is an interesting architecture because of its simplicity, adaptability and power. It is therefore an attractive choice for a simple virtual machine. However, this comes at a cost which we will...   Read More