Differences between ListManager Tcl and Standard Tcl
The Tcl language used by ListManager is slightly different from normal Tcl implementations. The differences are subtle but important. There are also some important additions to the syntax that allow the user to get around some of the problems involved with using a scripting language in an email message.
Line Wrapping
The most important difference between ListManager Tcl and standard Tcl is in the way that line breaks are handled. Since most email clients automatically word-wrap outgoing mail, it is likely that Tcl scripts would be broken by these line breaks. In Tcl, the end of the line ends the current statement. Additionally a single semi-colon ( ; ) also ends the current statement. So, to avoid inadvertent line breaks, all line breaks in Tcl scripts are removed and replaced with a single space. This requires the user to end all statements with a semi-colon.
For example, the Tcl script:
for { set i 1 } { $i <= 3 } { incr i } {
set j [expr 2 * i]
set k [expr j * i]
append result "$i, $j, $k\n"
}
which is valid standard Tcl, will not be processed correctly by ListManager Tcl. This is because the line breaks after the 'set' procedure statements will be removed. Therefore, the user must always terminate statements with a semi-colon.
For example:
for { set i 1 } { $i <= 3 } { incr i } {
set j [expr 2 * i] ;
set k [expr j * i] ;
append result "$i, $j, $k\n" ;
}
Note that the semi-colon must always be preceded by a space and followed by a space or a line break.
The importance of this feature is evident in scripts where a single command line exceeds the line-wrapping width of the email client's editor. Most editors only do line-wrapping when the message is actually sent so that it is not possible to know exactly where the line will be wrapped. The process of removing line breaks is called 'line unwrapping' as opposed to 'line wrapping'.
Line unwrapping is done before the Tcl script is evaluated and it does not make any distinctions between quoted text and Tcl code. For example, the following Tcl script:
%%set result "The domain name for your email address [merge EmailAddr_]
is [getdomain [merge EmailAddr_]]"%%
has a line break in the middle of a string. In standard Tcl, this requires the use of a backslash ( \ ) at the break point as in:
set result "The domain name for your email address [merge EmailAddr_]\
is [getdomain [merge EmailAddr_]]" ;
In ListManager Tcl, the line break is turned into a single space. In standard Tcl, the use of the backslash at the point of the line break has additional functionality. All whitespace (i.e. non-printing characters such as line-breaks, tabs, and spaces) after the backslash is removed and replaced by a single space. This makes it possible to do the following:
set result "The domain name for you email address [merge EmailAddr_]\
is [getdomain [merge EmailAddr_]]"
;
In this case, the spaces at the beginning of the second line will be removed and the entire break will be replaced by a single space. If you do not end the line with a backslash, then all the spaces at the beginning of the next line will be included in the result.
The backslash is also used in Tcl to continue Tcl code on the next line as in:
for { set i 1 } { $i <= 3 } \
{ incr i } { ...
}
This is not required in ListManager Tcl because lines are always wrapped. Extra whitespace is ignored. It is only noticeable when it is in a string because this is generally what is visible to the user. For consistency, it is recommended that you use the backslash when inserting new lines in Tcl scripts.
There is another problem that cannot be solved automatically through line unwrapping. There are some strings that exceed the word-wrapping width of a mail-client that don't have any spaces. In this case, it cannot be safely broken at a space and is generally just broken at the wrap width. The most common case of this is long URL's. To get around this problem in Tcl, you can construct the string in pieces where each piece is less than the word wrapping width. For example:
%%
set mystring "" ;
append mystring
"http://www.somelongdomainname.com/cgi-bin/somescript.pl"
"?someparameter=somevalue"
"&someotherparameter=someothervalue"
"&yetanotherparameter=yetanothervalue" ;
return $mystring ;
%%
Make sure you set mystring to an empty string before you do append otherwise you will keep appending to the same string for each recipient.
It is possible to disable the line unwrapping step by including an exclamation mark ( ! ) immediately
after the first %% mail merge tag delimiter. Care must be taken to avoid any undesired line-wrapping when
the message is sent.
For example
%%!
for { set i 1 } { $i <= 3 } { incr i } {
set j [expr 2 * i]
set k [expr j * i]
append result "$i, $j, $k\n"
}
return $result
%%
Text Quoting
Another important addition to ListManager Tcl is the inclusion of block-quoting delimiters '<<' and '>>'. Any line breaks that occur within these quotes are converted to "\r\n" sequences. These are special characters that are converted by Tcl into a line break within the string. Additionally, any normal quotes ( " ) are converted to 'escaped' quotes (i.e. \" sequences that represent a quote to Tcl) which allows them to be included in a Tcl string variable. The '<<' and '>>' characters are converted to normal quotes.
This allows the following:
%%set advertisement
<<blah blah blah blah blah blah blah
blah blah blah "quoted blah" blah blah
more blah blah blah>>%%
to be converted to a legal Tcl statement:
set advertisement "blah blah blah blah blah blah blah\r\nblah blah blah \"quoted blah\"\r\nblah blah more blah blah blah"
which is interpreted and returned by Tcl as:
blah blah blah blah blah blah blah
blah blah blah "quoted blah" blah blah
more blah blah blah
Procedures and variables are still processed as normal within these quotes as in:
%%set advertisement
<<blah blah blah $variable blah blah blah
blah [someprocedure] blah "quoted blah" blah blah
more blah blah blah>>%%
Since all normal quotes are 'escaped' within block quotes, it is not possible to use them as Tcl, non-string, quotes as in:
%%set advertisement
<<blah blah blah $variable blah blah blah
blah [someprocedure "some argument"] blah "quoted blah" blah blah
more blah blah blah>>%%
The [someprocedure "some argument"] text will be converted to [someprocedure \"some argument\"] which is probably not what was wanted. If you need to quote any text for a procedure within block quotes, use the '{' and '}' style quotes.
If you wanted to process Tcl code in the quoted argument then use a variable and set the argument text before you quote your block of text. For example:
%%set argument "argument with a [tcl procedure] and $string variable" ;
set advertisement
<<blah blah blah $variable blah blah blah
blah [someprocedure $argument] blah "quoted blah" blah blah
more blah blah blah>>%%
or
%%set somestring [someprocedure "argument with a [tcl procedure] and $string variable"] ;
set advertisement
<<blah blah blah $variable blah blah blah
blah $somestring blah "quoted blah" blah blah
more blah blah blah>>%%