Version 39 of HTML generator

Updated 2007-06-03 11:22:57 by colin

== Extending tcl to generate html ==

CMcC Following from jenglish's comment: why learn to use a monster HTML-template library when you can, with a few lines of code, extend the base language so you can write things like [<A> href "/home.html" { ! "Home" }] ... I wrote the following to do just that using the techniques in let unknown know.

 package require know
 know {[string match <*> [lindex $args 0]]} {
    set tag [string trim [lindex $args 0] "<>"]
    ::proc ::<$tag> {args} [string map [list @T $tag] {
        set result {}
        foreach {n v} [lrange $args 0 end-1] {
            lappend result "$n='[armour $v]'"
        }
        return "<@T [join ${result}]>[lindex $args end]</@T>"
    }]
    return [eval $args]
 }

This will generate a proc for any command like [<li>] which will do pretty much what you'd expect it to.


== Armouring HTML ==

Prevent output from containing html-significant characters

 interp alias {} armour {} string map {& & < < > > \" " ' '} ... fairly clearly ''that'' needs some work :)

== Functional HTML generation ==

Often what you want isn't to iterate, but to convert a list into something else. One generic technique I've found helpful is the use of join, as follows:

  <ul><li>[[join $list </li></li>]</li></ul>

Which will convert a tcl list into an HTML unordered list. Similar techniques are possible with <table>s

The technique can be readily made generic:

== Subst-if ==

Here's a variant of if which evaluates its conditional using subst and not eval

 proc If {args} {
    while {[llength $args] && ![uplevel expr [lindex $args 0]]} {
        set args [lrange $args 2 end]        ;# lose the cond and positive-cond

        if {[lindex $args 0] eq "elseif"} {
            set args [lrange $args 1 end]
            continue        ;# continue to evaluate conditionals
        } elseif {[lindex $args 0] eq "else"} {
            break
        }
    }
    return [uplevel subst [list [lindex $args 1]]] ;# return with neg-consequence
 }

 set a 1; set b 2
 puts [If {$a} {a is true} else {a is false}]
 puts [If {$a == $b} {a == b} elseif {$b == 1} {b is 1} else {b is not 1 it is $b}]