[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:
----
#!/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]
]]