Version 0 of Templates and subst

Updated 2007-06-07 16:01:30 by APW

APW 2007-06-07 The contents of this page has been moved from TemplaTcl: a Tcl Template engine to here, to be able to reference that code. It is an example on how to use a simple templating language which can have Tcl code interspersed.

03jun07 jcw - But I don't see the point in embedding an escape layer using XML. Here's a visually simpler approach

  % if {$a != $b} {
      <h3> abc </h3>
      <li> [expr {$a != 1 ? $var1 : $var2}] </li>
  % } else {
      <li> [myobj getResult] </li>
      <table>
         <tr> Hello there </tr>
      </table>
  % }

What you get is the ability to use Tcl's subst where convenient and an outer-level line-by-line escape for larger amounts of code. Just like in Tcl, where we use both if's and expr's.

The example is contrived and has relatively much flow control, so it doesn't come out as clearly as real-world examples would. The above isn't an arbitrary choice btw - it's what Mason uses. As it turns out, less than a dozen lines of Tcl are needed to convert the above into a normal Tcl script which consists mostly of subst calls. In fact, I use a second level of <%...%> escapes as well for structuring the entire files into "components". This is the sort of thing Mason has worked out long ago, driven by practical use, not mere preference of a specific technology or language construct.

Before taking this discussion further, my suggestion would be to take some notation and run with it for a while to see just well it works out. You can't discuss these design choices without using them in several decently-sized real-world website applications. Well, not meaningfully anyway - IMO.

APW That approach looks very good to me and makes sense in that the final HTML layout is still visible in the template! Thanks to jcw for bringing that in.

jcw Here's the code for that approach:

  proc substify {in {var OUT}} {
    set pos 0  
    foreach pair [regexp -line -all -inline -indices {^%.*$} $in] {
      lassign $pair from to
      set s [string range $in $pos [expr {$from-2}]]
      append script "append $var \[" [list subst $s] "]\n" \
                    [string range $in [expr {$from+1}] $to] "\n"
      set pos [expr {$to+2}]
    }
    set s [string range $in $pos end]
    append script "append $var \[" [list subst $s] "]\n"
  }

You give it a template, and it returns a script you can eval to apply that template. I turn such scripts into procs, but that's just one way to use this.

APW Great work jcw, that's exactly, what I am looking for.

FF I noticed a little problem with switch:

 % switch what {
 % case1 {
 something
 % }
 % what {
 something other
 % }
 % }

seems that two adjacent % lines generate an empty append line, and a construct like switch don't like that

APW Here is a slightly modified version of substify which should handle switch correctly:

  proc substify {in {var OUT}} {
    set script ""
    set pos 0
    foreach pair [regexp -line -all -inline -indices {^%.*$} $in] {
      foreach {from to} $pair break
      set s [string range $in $pos [expr {$from-2}]]
      if {[string length $s] > 0} {
        append script "append $var \[" [list subst $s] "]\n"
      }
      append script "[string range $in [expr {$from+1}] $to]\n"
      set pos [expr {$to+2}]
    }
    set s [string range $in $pos end]
    if {[string length $s] > 0} {
      append script "append $var \[" [list subst $s] "]\n"
    }
    return $script
  }

Good catch, thanks! -jcw

FYI, fixed a missing init of $script in the above (when $in is empty).


[ Category Template ]