[FF] 2007-30-05 - The discussion evolved in [ToW Tcl on WebFreeWay] has generate some interest, and here is an effort for making a '''minimal''' template engine. I would like to use this page for collecting ideas from people. Fell free to change everything, fix bugs and revolutionize the concept - it is the purpose of the page. Here's how it is (initially) supposed to work: first, let's create a template file (templtest.tmpl): <% for {set i 0} {$i < 4} {incr i} { %> <% } %>
<%= $i %>
now run it: source TemplaTcl TemplaTcl::parse templtest.tmpl TemplaTcl::dump and here's the output that gets produced:
0
1
2
3
---- #!/usr/bin/env tclsh package require Tcl 8.2 package require struct namespace eval TemplaTcl { variable data variable mode variable modeprev proc parse {file} { variable data variable mode variable modeprev set mode raw mode raw # read the template into $rawl - list of chars set fh [open $file r] set raw [read $fh] if {[catch {close $fh} err]} {puts "TemplaTcl: $err"} set rawl [split $raw {}] ::struct::queue cc foreach ch $rawl { # we work char-by-char :| cc put $ch set sz [cc size] # max block to compare (<%=) is 3 chars long: if {$sz >= 3} { set s3 [join [cc peek 3] {}] set s2 [join [cc peek 2] {}] if {$mode == "raw"} { if {$s3 == "<%="} { # <%= is a shorthand for puts ... cc get 3 mode code buf "puts -nonewline " continue } elseif {$s2 == "<%"} { # <% indicates begin of a code block cc get 2 mode code continue } } elseif {$mode == "code"} { if {$s2 == "%>"} { # and %> is the end of code block cc get 2 mode raw continue } } buf [cc get] } } # finish working on the queue: while {[cc size] > 0} { buf [cc get] } mode flush } proc mode {m} { # used internally by parse - switches mode and stuff... variable data variable mode variable modeprev set newm {} switch $m {code - raw {set newm $m}} if {$newm != {}} { set modeprev $mode set mode $newm set data(buf:$mode) {} } if {$m == "flush"} {set modeprev $mode ; set mode _} if {$mode != $modeprev} { lappend data(out) [list $modeprev $data(buf:$modeprev)] set data(buf:$modeprev) {} } } proc buf {ch} { # used internally by parse - put $ch in the right buffer variable data variable mode append data(buf:$mode) $ch } proc dump {} { # run the template script variable data set tclBuf "" foreach l $data(out) { set t [lindex $l 0] set d [lindex $l 1] switch $t { raw {append tclBuf [list puts -nonewline $d]\n} code {append tclBuf $d\n} } } eval $tclBuf } } ---- ''[APW] 2007-05-30'' Great idea to start with implementing something to play with!! What about naming the page "Tcl Template Engines"? I will add a reference to your page in ToW. [FF] Yes, I thought so ([TemplaTcl: a Tcl template engine]) but I forgot that when creating the page. :) ---- [[ [Category Application] ]]