TTP - the Tcl Template Parser
Program documentation
Georg Lehner, 09/2007
1. Table of Contents
2. TTP - the Tcl Template Parser
TTP is yet another template engine, with, guess it, a Tcl touch.
Each template line is processed with the Tcl subst command.
TTP is a small and simple yet powerful utility. I use it in places,
where lots of configuration file with lots of little variations have
to be created.
On the other hand, TTP is a general purpose application launcher with
commandline and configfile parser. I use it to wrap my tcl
applications without need to reinvent the wheel over and over again.
TTP is written in Tcl, comprises only two small files and does not require
any additional libraries.
You can get the latest TTP at http://www.magma.com.ni/sw/ttp/ttp.tgz
3. Notation conventions
- variable
-
name of a variable
- expr
-
either
- text without whitespaces (a token), Note that this can also be a number
- "text within double quotes"
- {text within braces}
- tcl script within
- $variable
-
a variable which is expanded by prepending a $ sign to the
variable name.
- [variable]
-
a variable which is expanded by enclosing the variable name with
brackets.
- tcl script
-
a whitespace separated list of expresions of which the first
expands (hopefully) to a valid tcl command.
4. Quickref
4.1. Usage
Usage: ttp [options] [arguments]
-l file .. source in a library
-o path .. output to file instead of stdout
-d value .. set debuging level, default: INFO
-D varName value .. define a variable
-e value .. break after count parsing errors, default: 200
-h .. usage information
-I path .. set include path
loglevels: DEVEL INFO WARN FATAL ERROR DEBUG
4.2. Expansion
- some text
-
is passed through to the output unchanged
- $variable
-
is substituted with the value of the $variable named variable.
If not defined a parsing error occurs.
- [variable]
-
is substituted with the value of the [variable] name variable.
If not defined a parsing error occurs.
- [tcl script]
-
is substituted with the result of the tcl script. If an error
occurs, e.g. the first token is not a valid tcl command, a parsing
error occurs.
If a parsing error occurs, the line is passed through unchanged, but
prefixed with
`>>>`
.
The error is logged to stderr
.
4.3. Commands
- --
-
comment
- literal
-
insert text literally
- tcl
-
interpret text as tcl script
- cmd expr
-
parse each line with a command
- set: variable expr
-
set the value of $variable named variable to the result of the
expresion
- default: variable expr
-
if variable is not defined, define and set it to the result of
the expresion
- let: variable expr
-
set the [variable] named variable to the result of the
expresion
- existsElseValue variable expr
-
returns the value of the variable, if the variable does not
exist, it returns the value of the expr instead.
- stamp
-
generates three line of output:
`` # ttp: timestamp
`` # user@host:pwd
`` # commandline
- skipline
-
skip the current line
- out
-
outputs text
- parse file [mode] [tcl script]
-
inserts other files in the output. Start parsing with mode.
5. Variables
The following variables are available in a template
- rc
-
"return code", if positive, number of parse errors until now, if negative, internal error
- libs
-
list of "library" name given with the -l commandline switch
- loglevel
-
textual string, loglevel, invoke ttp -h -d DEBUG to see them all
- loglevels
-
array holding loglevels and their priority
- root
-
include directory, from where libs are imported
- defs
-
(possibly empty) list of definition files
- template
-
template file name
6. Log levels
The following are recommendations for use of the ''log loglevel msg''
command in scripts and templates. These recomendations are
(hopefully) followed in the TTP core.
- DEVEL
-
for messages used during development of templates and scripts.
Used by developers.
- DEBUG
-
for debugging of your application or template, i.e. messages which
show the progress of TTP while processing its input.
Used by developers.
- VERBOSE
-
for detailed information about the content of the definition and
template files.
Used by advanced users of the finished application/template system.
- INFO
-
for important information gathered during processing of the
definition and template files. Thinks that you want the user know.
Used by standard users of the finished application/template system.
- WARN
-
non critical warnings: information that affect the quality of the
output, put does not stop the template/application processing.
- ERROR
-
critical warnings: information that invalidates the output of the
templates or make the application do the wrong thing.
- FATAL
-
aborts TTP, and tells the user why.
7. Utility functions
7.1. For definition files
This functions are primarily used in the definition files,
e.g. default.tcl.
- include path onerror msg
-
- path filename to include
-
- onerror can have the following values:
-
- continueWhenMissing
-
if file does not exist, silently go on
- abortOnError
-
exit TTP if an error is generated while sourcing the file
- continueOnError (default)
-
continue with TTP if an error is generated while sourcing the file
- msg
-
additional message to log, default "Exiting..."
- library patch onerror msg
-
is the same is include with two differences:
- instead of a path, a filename is to be given, the file is
then sourced in from the include directory
- by default onerror is set to `abortOnError`
- follow path
-
if path is a symlink, follow it until we get to a real file.
This is a very blueyed version of follow. It will break on dangling
and circular symlinks.
- log level msg
-
log msg if level is equal or higher then loglevel.
logging goes to stderr
- fatal msg exitcode
-
log msg with level FATAL
increment the errorcount and exit
exitcode is optional.
if it is not zero don't leave (yet) and set the the variable rc to
the value of exitcode. this is an obscure feature used with negative
exitcodes on startup. Don't use exitcode at all.
8. How TTP works
You can view TTP (at least) from two different points.
- TTP reads in some (tcl) definitions from several files, then
applies them to one template file and spits out the result
- TTP reads in some libraries, eventually is instructed to parse
configfiles, and launches some tcl command or application
8.1. Template Parser
- TTP is launched as:
ttp [options] template [definitions ..]
- The input to TTP is:
- a template file
- an optional `default.tcl` include file
- optional library files specified with -l name on the commandline
- an optional list of 'definition' files specified on the commandline
The output of the parsed template is either written to stdout or to
the file specified with -o file
A 'library' is a file in the include directory.
'importing' means sourcing a tcl file into the tclsh interpreter.
After launching TTP the following happens:
- the
ttp.tcl
library which contains the parser is imported
- commandline is parsed
- the include directory is determined either as the directory
where ttp resides, or specified with -I on the commandline
- the -D definitions are processed
- if the library
default.tcl
exists it is imported
- if libraries have been specified with -l they are loaded in order
- if definition files are specified they are sourced
- the template file is parsed
- if the routines
preambel
and/or postambel
are defined
they are executed before and after parsing any template file
template files may include other templates with the parse
command.
8.2. Application Launcher
TTP inspects the name as which it is called. This means you can
either rename the file ttp
or symlink to it, and TTP will change
its "identity" to the new name. The main idea is to install TTP in
some place, say /usr/share/ttp, and then create a symlink for each
TTP-ified application you want to launch, e.g.:
```ln -s /usr/share/ttp/ttp /usr/local/bin/myapp
Then when:
- TTP is launched as ``myapp [options] [config|""] include files
- The input to TTP is
- an (almost not) optional myapp.tcl library
- optional library files specifeid with ``-l ``name on the
commandline
- an optional list of 'include' files specified on the commandline
- an optional config file to parse, or let it be the input file to
your application
- myapp.tcl is your responsibility: define tcl proc's and variables
needed by myapp, and parse configuration files with the builtin
parser.
- at the end of myapp.tcl, launch your application.
9. Examples
9.1. Just a template file
example.tpl
:
[-- This is an example template]
You, $name, will be fired.
Invocation:
ttp -D name Fred example.tpl
Will give:
You, Fred, will be fired.
9.2. Template file and default library
example.tpl
:
[-- This is an example template]
You, $name, will [fired reason] be fired.
`default.tcl`
:
proc fired_p {num} {
switch $num {
0 {return surely}
1 {return certainly}
2 {return "of course not"}
default {return never}
}
}
Invocation:
ttp -D name Fred -d reason 2 example.tpl
ttp -D name Bill -D reason 4 example.tpl
Will give:
You, Fred, will of course not be fired.
You, Bill, will never be fired.
9.3. Using a definition file
`names.def`
:
set t [clock scan now]
set reason [expr {int(srand($t)*4)}]
set names {Mike Bill Frank George}
set i [expr {int(rand()*4)}]
set name [lindex $names $i]
Invocation:
ttp example.tpl names.def
will output a random combination of name and reason to be fired each
time ttp is invoked
10. Command Reference
10.1. Preliminaries
The commands:
- -- (comment)
- literal
- tcl
can be used on a line by themselfes to start/end a region with the
respective function, or they can be used with arguments, in which case
they are "embedded" in the current line.
The
literal
command just takes (zero or) one single argument,
while ---
and tcl
can take an arbitrary long list of
arguments.
The commands:
- set:
- default:
- let:
by default take two arguments: name and value. However if you want to
use them on a line by themselfes whithout showing any output you can
add an arbitrary text (comment) after the value. Good style is
e.g. using a single dash:
[default: count 12 -]
10.2. ''--'' comment
Allows to insert comments, i.e. text that is not displayed in the
ouput. The following variations are possible:
- [--] on a line by itself: start comment region
-
Starting from this line, up to the next line where [--] occurs no
output is produced
- [-- some text] sourrounded by text: insert comment
-
the sorrounding text is output, everything between [-- and ]
disappears from the output
- [-- some text] on a single line: skip line
-
if the comment is not surrounded by text, the whole commentline is
skipped. Parsing continues normally on the next line
10.3. literal
Allows to insert text literally, i.e. without substitutions. The
following variations are possible:
- [literal] on a line itself: start literal text region
-
Starting from this line, up to the next line where [literal] occurs
each line is output literally.
Note however, that all [commands] occuring on a line are still
evaluated. While any errors are ignored silently, some commands
might confuse ttp, [exit] is such an example
- [literal {some text}] insert: text literally
-
The text inside the brace is reproduced literally in the output.
Note that this syntax is slightly different. Consider omitting the
braces, like in the following example, suppose that variable is
set to 'VAR':
[literal $variable some text]
The resulting output will be: VAR some text, since whitespace is
substituted by single blanks, and each token is evaluated with
command and variable expansion ([], $).
By putting the text inside {braces}, the parameter expansion just
eliminates the {} braces themselves and leaves the text intact.
10.4. parse
The complete syntax of parse is:
parse path [type] [tcl script]
- path
-
the file to be parsed
- type
-
the parsing type to use initially, can be:
- parse
- --
- literal
- tcl
- cmd
the default is
parse
.
- tcl script
-
this is only used when the parse type is
cmd
. It is the script
to parse each line.
10.5. cmd
This allows to parse each line of a file with some user defined
command. TTP first checks
- if the line is empty
- if the line only consists of whitespace
- if the first non-white character on the line is a #
in all this cases the line is skipped. Otherwise the given
commandline is prepended to the rest of the line and the result is
evaluated.
To start cmd parsing put:
[cmd tcl script]
on a line. cmd parsing stops either at the end of the file or when the
tcl script executes cmd
by itself again.
Any text on the same line as the cmd command is skipped.
If the tcl script is empty the rest of the file is silently skipped
without output.
If the tcl script throws an error at some line, the error is logged
and the line is output as is with ">>>" prepended.
11. Commands YetToBeExplained
11.1. tcl
11.2. set:
11.3. default:
11.4. let:
11.5. exitsElseValue
11.6. stamp
11.7. skipline
11.8. out
12. Bugs and Todo
- run parser in its own interpreter
- make the sh parser/example work
- add an example for TTP as application launcher.
- improve error messages and diagnostics on template parsing
- complete documentation of commands
- document additional files and "installation"
- -h should list log levels in order
- Copyright +
This file is part of TTP the Tcl Template Parser. TTP is (c) 2007
Georg Lehner <jorge@magma.com.ni>. Share and use it as you like, but
don't blame me
This is my version of the OOL, the One Line License. Essentially it is
a Free Software compatible license, which i use for small tools i do
not care much about, because anybody could write them from scratch in
a reasonable time.
It does not require you (explicitely) to credit me, however it states
clearly, that i AM the original author.
Also i fillow DJB, who likes to put it this way:
Like any other piece of software (and information generally), [this
software] comes with NO WARRANTY.