"WhipIt" - Wikit run in a Slave Interpreter on TclHttpd
Since I read the comments below this became an itch I just had to scratch! Jeff Smith
Extracted from the How to grow your own Wiki page.
MDD: What would be really nice would be if someone would create a Starkit that combines tclhttpd and the wikit into one turnkey wiki server. Performance should be better, since you wouldn't have to use CGI.
11apr03 jcw - Yes, that would be cool, but it may need some work (either to make it properly keep state with repeated requests, or to make it work in a slave interp which gets re-inited on each access).
To try "WhipIt" place the following whipit.tcl code into the custom directory of your TclHttpd Starkit or get a ready made starkit, whipit.kit, from [L1 ]. This starkit has a copy of wikit.kit inside and copies it to the outside directory at startup if the wikit.kit file does not exist.
To launch on unix
# ./tclkit whipit.kit
On Windows
from a dos window
C:\tclkitsh whipit.kit
from windows explorer
drag and release whipit.kit on tclkit
Point your browser to
http://yourhost:8015/wikit/
This provides a nice wrapper around Wikit to allow you to dynamically control it. For example the WIKIT_BASE environment variable is dynamically set per request in the code below. Some ideas for the future
BAJ uses whipit and finds it very useful, but just discovered that the history feature of wikit (enabled with "WIKIT_HIST" is broken by whipit (the puts that should write to a disk file ends up being remapped to the WktCGI_Puts command in script below).
Jeff Smith 22 November 2004 - Thanks for the report! I have never used the history feature. If you have a fix can you post it here?
#Mount the wikit startkit vfs::mk4::Mount [file dir $starkit::topdir]/wikit.kit [file dir $starkit::topdir]/wikit.kit set WktDir [file dir $starkit::topdir]/wikit.kit # Append wikit library from the mounted wikit starkit to the auto_path lappend auto_path [file dir $starkit::topdir]/wikit.kit/lib Url_PrefixInstall /wikit [list wikitProc /wikit] proc wikitProc {prefix sock suffix} { upvar #0 Httpd$sock data global env auto_path # Set the CGI environment variables Cgi_SetEnv $sock $prefix set env(PATH_INFO) $suffix set env(SCRIPT_NAME) $prefix # This sets the WIKIT_BASE environment vaiable dynamically based on # the host portion of the url typed in the browser. set env(WIKIT_BASE) http://$env(HTTP_HOST)$prefix/ append data(query) "" # Use the Session Module in TclHttpd to create a slave interpreter. # A session state array is also created but we don't use it. This # maybe of some use if you have a need for a session based wiki. # # To emulate a CGI environment for Wikit, a slave interpreter is created # and then destroyed per request. # Destroy any old sessions that are laying around. Interpreters that have # been created but for some reason not destroyed. In this instance # 2 minutes is the setting. Session_Reap 120 Wkt # Create a new session. set session [Session_Create Wkt 0] set html [WktProcess $session $data(query)] Httpd_ReturnData $sock text/html $html Session_Destroy $session } proc WktProcess {session query} { upvar #0 Session:$session state set interp $state(interp) global auto_path WktDir set WktCGI_LineNumber 0 set html "" # Redirect the read and puts in the slave interpreter # that runs Wikit. interp eval $interp {rename puts real_puts} interp alias $interp puts {} WktCGI_Puts interp hidden $interp interp eval $interp {rename read real_read} interp alias $interp read {} WktCGI_Read $interp $query # Fool wikit to think it is running in it own Starkit so we can copy # the first ten pages from wikidoc.tkd interp eval $interp [list namespace eval starkit set topdir $WktDir] # Following taken from httpd.tcl for getting these variables into # a slave interpreter. # # Transfer the scalar global variables foreach var {::v ::auto_path} { $interp eval [list set $var [set $var]] } # Procedure that is run when the slave interpreter does a read. proc WktCGI_Read {interp query args} { if { [llength $args] == 2 && [lindex $args 0] == "stdin" } { return [$interp eval subst $query] } else { return [$interp eval real_read $args] } } # Precedure that is run when the slave interpreter does a puts. proc WktCGI_Puts {args} { upvar 1 WktCGI_LineNumber WktCGI_LineNumber upvar 1 html html incr WktCGI_LineNumber if {$WktCGI_LineNumber <= 4} { return "" } else { append html [lindex $args end] } } # Setup and run Wikit. $interp eval { set argv0 tclkit set argv {} set argc 0 package require cgi #cgi_debug -on # Work around for getting lassign into the slave interpreter. # From "Practical Programming in Tcl and Tk" Third Edition # by Brent B. Welch page 131. proc lassign {valueList args} { if {[llength $args] == 0 } { error "wrong # args: lassign list varname ?varname ..?" } if {[llength $valueList] == 0} { #Ensure one trip through the foreach loop set valueList [list {}] } uplevel 1 [list foreach $args $valueList {break}] return [lrange $valueList [llength $args] end] } # Source the starkit package require app-wikit } return $html }