Rosetta Code Helper

Rosetta Code Helper

The following script eases composing examples for RosettaCode in a vaguely literate programming style.

# a channel transformer that captures all output to a variable while it is pushed
namespace eval capture {
    proc initialize args {info procs}
    proc finalize args {}
    proc clear args {}
    proc write {varName h data} {
        regsub -all {\r} $data {} data  ;# "clean" newlines
        append $varName $data
        return ""
    }
    namespace export *
    namespace ensemble create -parameters varName
}

package require textutil::adjust

namespace eval rosetta {

    namespace eval sandbox {   ;# where the rosetta script body is run

        namespace path [list [namespace parent]]

        proc eval {script} {
            ::if {[lindex [info level -2] 0] eq "rosetta"} {
                tailcall code $script
            } else {
                tailcall ::eval $script
            }
        }

        proc if {args} {
            ::if {[lindex $args 0] eq "0" && [llength $args] == 2} {
                tailcall comment [lindex $args 1]
            } else {
                tailcall ::if {*}$args
            }
        }

    }

    namespace import ::textutil::adjust::undent
    proc tidy {script} {
        set script [undent $script]
        set script [string trim $script]
    }

    proc comment {text} {
        upvar 2 r r
        append r [tidy $text]\n\n
    }
    proc code {script} {
        upvar 2 r r
        variable log
        set log ""
        chan push stdout [list capture [namespace which -variable log]]
        uplevel 1 $script
        chan pop stdout
        append r "<lang Tcl>[tidy $script]</lang>\n\n"
        ::if {$log ne ""} {
            append r "{{out}}\n<pre>$log</pre>\n\n"
        }
    }

    proc rosetta {script} {
        set r "=={{header|Tcl}}==\n\n"
        apply [list {} $script [namespace current]::sandbox]
        append r \n
        puts $r
    }

    namespace export rosetta
}

namespace import ::rosetta::rosetta

Here's an example of how to use it. The below script produces wiki markup for [http://rosettacode.org/wiki/Array_search#Tcl] .

source rosetta.tcl

rosetta {
    if 0 {
        Tcl's <tt>[[https://wiki.tcl-lang.org/1486 lsearch]]</tt> command takes many useful options. This task illustrates the <tt>-index</tt> and <tt>-bisect</tt> options.
    }
    eval {
        set cities {
            {"Lagos"        21}
            {"Cairo"        15.2}
            {"Kinshasa Brazzaville"        11.3}
            {"Greater Johannesburg"        7.55}
            {"Mogadishu"        5.85}
            {"Khartoum Omdurman"        4.98}
            {"Dar Es Salaam"        4.7}
            {"Alexandria"        4.58}
            {"Abidjan"        4.4}
            {"Casablanca"        3.98}
        }
        puts "Dar Es Salaam is at position: [
            lsearch -index 0 $cities "Dar Es Salaam"
        ]."

        set cities_by_size [
            lsort -index 1 -real $cities
        ]

        puts "The largest city of < 5m is: [
            lsearch -inline -index 1 -bisect -real $cities_by_size 5.0
        ]"
    }
}