Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
#!/usr/bin/tclsh8.0 # (find-angg "TH/Generate") # «.functional» (to "functional") # «.proc1_procj» (to "proc1_procj") # «.basic_html» (to "basic_html") # «.encode_entities» (to "encode_entities") # «.local_remote_modes» (to "local_remote_modes") # «.boolean_env_vars» (to "boolean_env_vars") # «.local_remote_urls» (to "local_remote_urls") # «.LR_modifiers» (to "LR_modifiers") # «.file_IO» (to "file_IO") # «.relative_links» (to "relative_links") # «.extra_utils» (to "extra_utils") # «.templates» (to "templates") #%%%% # # Routines with a functional taste # #%%%% # «functional» (to ".functional") proc id1 {x} {return $x} proc id {args} {return $args} proc myconcat {args} {join $args} proc nonvoid {str} { string length [string trim $str] } proc nonvoids {list} { Filter1 nonvoid $list } proc Filter {f args} { return [Filter1 $f $args] } proc Filter1 {f list} { set list2 {} foreach item $list { if [uplevel #0 $f [list $item]] { lappend list2 $item } } return $list2 } # [Filter nonvoid foo " \t\n " " aa"] -> {foo { aa}} proc Map {f args} { return [Map1 $f $args] } proc Map1 {f list} { set list2 {} foreach item $list { lappend list2 [uplevel #0 $f [list $item]] } return $list2 } #%%%% # # proc1 and procj # #%%%% # «proc1_procj» (to ".proc1_procj") proc adddollar {str} { return "\$$str" } proc proc1_ {lastarg proc1name args1list code1} { proc $proc1name $args1list $code1 set procname \ [string range $proc1name 0 [expr [string length $proc1name]-2]] set nargs [llength $args1list] set firstargs [lrange $args1list 0 [expr $nargs-2]] set code "$proc1name [join [Map1 adddollar $firstargs]] $lastarg" proc $procname "$firstargs args" $code } proc proc1 {proc1name args1list code1} { proc1_ {$args} $proc1name $args1list $code1 } proc procj {proc1name args1list code1} { proc1_ {[join $args]} $proc1name $args1list $code1 } # So that: # proc1 foo1 {aaa bbb ccc} {puts hello} # becomes: # proc foo1 {aaa bbb ccc} {puts hello} # proc foo {aaa bbb args} {foo1 $aaa $bbb $args} # and: # procj wee1 {ddd eee fff} {puts bye} # becomes: # proc wee1 {ddd eee fff} {puts bye} # proc wee {ddd eee args} {wee1 $ddd $eee [join $args]} # # The convention is that the chopped char is always "1". # (find-fline "~/TCL/PAGE2/linux.th") proc void {str} { expr ![nonvoid $str] } procj E1 {code} { uplevel #0 subst [list $code] } procj EV1 {code} { uplevel #0 $code } proc1 J1 {list} { join $list } #%%%% # # basic html functions # #%%%% # «basic_html» (to ".basic_html") proc <> {tag {body {}}} { return "<$tag>$body" } proc <>n {tag {body {}}} { return "<$tag>$body\n" } proc <></> {tag body} { return "<$tag>$body</$tag>" } proc <></>n {tag body} { return "<$tag>$body</$tag>\n" } proc <>n</> {tag body} { return "<$tag>$body\n</$tag>" } proc <>n</>n {tag body} { return "<$tag>$body\n</$tag>\n" } proc <>N</>n {tag body} { return "<$tag>\n$body</$tag>\n" } proc <>nn</>n {tag body} { return "<$tag>\n$body\n</$tag>\n" } proc <+></> {tag extra body} { return "<$tag $extra>$body</$tag>" } procj HREF1 {url str} { <+></> a href=\"$url\" $str } procj H11 {str} { <></>n h1 $str } procj H21 {str} { <></>n h2 $str } procj H31 {str} { <></>n h3 $str } procj H41 {str} { <></>n h4 $str } procj H51 {str} { <></>n h5 $str } procj H61 {str} { <></>n h6 $str } procj UL1 {str} { <>N</>n ul $str } procj LI1 {str} { <>n li $str } proc1 LIST11 {list} { UL1 [join [Map1 LI1 [nonvoids $list]] ""] } proc1 LIST21 {list} { UL1 [join [Map1 LI1 [nonvoids $list]] ""] } proc1 LIST31 {list} { UL1 [join [Map1 LI1 [nonvoids $list]] ""] } proc1 HLIST11 {head list} { return [H21 $head][LIST11 $list] } proc1 HLIST21 {head list} { return $head\n[LIST21 $list] } proc1 HLIST31 {head list} { return $head\n[LIST31 $list] } procj BF1 {str} { <></> strong $str } procj IT1 {str} { <></> i $str } procj RM1 {str} { return "</i>$str<i>" } procj TT1 {str} { <></> code $str } procj EM1 {str} { <></> em $str } procj NAME1 {tag str} { <+></> a name=\"$tag\" $str } procj COLOR1 {color str} { <+></> font color=\"$color\" $str } procj PRE1 {str} { <></> pre $str } procj P1 {str} { return \n\n<p>$str } # (find-fline "$S/http/www.gnu.org/software/hurd/easy.html") set metastr "" proc AddMeta {tag args} { global metastr append metastr "<meta name=\"$tag\" content=\"[join $args ", "]\">\n" } proc AddKeywords {args} { eval AddMeta keywords $args } procj TITLE1 {str} { <>n</>n title $str } procj HEAD1 {str} { <>N</>n head $str } procj BODY1 {str} { <>nn</>n body \n$str } procj HTML1 {str} { <>N</>n html $str } # <html>\n <head>\n <title> foo bar \n</title>\n </head>\n # <body>\n ... \n</body>\n </html>\n procj TITLEDHTML1 {title body} { global metastr return [HTML1 [HEAD1 [TITLE1 $title]$metastr]\n[BODY1 $body]] } #%%%% # # encode_entities # #%%%% # «encode_entities» (to ".encode_entities") # splitter - split in pattern/nonpattern chunks. # This is used by encode_entities. # proc splitter0 {str p1p2} { foreach {p1 p2} $p1p2 {} return [list [string range $str 0 [expr $p1-1]] \ [string range $str $p1 $p2] \ [string range $str [expr $p2+1] end]] } proc splitter {pat str} { set rest $str while {[regexp -indices $pat $rest {} range]} { foreach {prematch match rest} [splitter0 $rest $range] {} lappend pieces $prematch $match } lappend pieces $rest return $pieces } # encode_entities: "&" -> "&", etc # for {set x 128} {$x<256} {incr x} { set Entname([format "%c" $x]) [format "%c" $x] } # puts $Entname(ˆ) -> ˆ foreach {char entname} { Æ AElig Á Aacute  Acirc À Agrave Å Aring à Atilde Ä Auml Ç Ccedil É Eacute Ê Ecirc È Egrave Ë Euml Í Iacute Ï Iuml Ó Oacute Ô Ocirc Ò Ograve Õ Otilde Ö Ouml Ú Uacute Û Ucirc Ù Ugrave Ü Uuml á aacute â acirc æ aelig à agrave å aring ã atilde ä auml ç ccedil é eacute ê ecirc è egrave ë euml í iacute î icirc ì igrave ï iuml ó oacute ô ocirc ò ograve õ otilde ö ouml ß szlig ú uacute û ucirc ù ugrave ü uuml ª ordf « laquo ° deg º ordm » raquo & amp > gt < lt \" quot } { set Entname($char) "&$entname;" } proc encode_entities {str} { global Entname # set spl [splitter "(\[\"<>&\200-\377\]+)" $str] set spl [splitter "(\[<>&\200-\377\]+)" $str] foreach {straight queer} $spl { append encoded $straight set equeer "" foreach c [split $queer {}] { append equeer $Entname($c) } append encoded $equeer } return $encoded } procj Q1 {str} { encode_entities $str } #proc Q {args} { Q1 [J $args] } #%%%% # # local/remote modes # #%%%% # «local_remote_modes» (to ".local_remote_modes") # Local/remote modes # The default is local. # set islocalv 0 proc islocal {args} { global islocalv; eval set islocalv $args } proc IFLR {yescode {nocode {}}} { if [islocal] { EV1 $yescode } else { EV1 $nocode } } proc1 IFL1 {code} { IFLR $code } proc1 IFR1 {code} { IFLR {} $code } #%%%% # # Boolean environment variables # #%%%% # «boolean_env_vars» (to ".boolean_env_vars") # (find-es "tcl" "environment") # proc env {vname {default {}}} { global env if {[info exists env($vname)]} { return $env($vname) } else { return $default # TO DO: make it scream if called without default and vname not found } } proc getboolenv {vname} { env $vname 0 } # If DOLOCAL is 1, # we enter local mode. # if [getboolenv DOLOCAL] { islocal 1 } #%%%% # # Local/remote urls # #%%%% # «local_remote_urls» (to ".local_remote_urls") # set snarfprefix [env S /snarf] proc tosnarf {url} { global snarfprefix if [regexp "^((http|ftp|file)://)(.*)$" $url {} {} proto rest] { set url $snarfprefix/$proto/$rest } return $url } proc addindexhtml {url} { if [regexp "^/snarf/http/.*/$" $url] { if [file exists ${url}index.html] { set url ${url}index.html } } return $url } proc ungz {url} { if [regexp {^(/.*\.(ps|dvi))\.(z|gz|Z)} $url -> ungzurl] { if [file exists $ungzurl] { return $ungzurl } } return $url } proc tosnarfindex {url} { ungz [addindexhtml [tosnarf $url]] } proc isrmturl {url} { regexp "^((http|ftp|file)://)(.*)$" $url } proc islocalurl {url} { expr ![isrmturl $url] } proc lurl {url} { if {[islocal] && [isrmturl $url]} { tosnarfindex $url } else { return $url } } procj LRHREF1 {url text} { if {$text==""} {set text [Q1 $url]} if {[islocal] && [isrmturl $url]} { set url2 [tosnarfindex $url] return "[HREF1 $url2 $text] ([HREF $url rmt])" } else { HREF1 $url $text } } procj LHREF1 {url text} { if {$text==""} {set text [Q1 $url]} if {[islocal] && [isrmturl $url]} { set url2 [tosnarfindex $url] HREF1 $url2 $text } else { HREF1 $url $text } } # L/L1 are the most usual ways to write links. # They are sentitive to "islocal" and to Lr-mode; # see below. # set metaL1 LHREF1 procj L1 {url text} { global metaL1 $metaL1 $url $text } procj LR1 {url text} { LRHREF1 $url $text } #%%%% # # Modifiers: Rmt, Lr. # #%%%% # «LR_modifiers» (to ".LR_modifiers") # Rmt evals its code as if we were in remote mode. # Lr evals its code in LR mode, i.e., each snarfable link gets a local # version and a remote version. # The code they get is evaluated at top level, not E'ed; it must start # with the name of a command. For example: # # Rmt L http://foo Foo Bar # Rmt1 {L http://foo Foo Bar} # Rmt1 {concat [L http://foo Foo Bar], a f.b. page.} procj Rmt1 {code} { set oldislocal [islocal] islocal 0 set retstr [uplevel #0 $code] islocal $oldislocal return $retstr } procj Lr1 {code} { global metaL1 set oldmetaL1 $metaL1 set metaL1 LRHREF1 set retstr [uplevel #0 $code] set metaL1 $oldmetaL1 return $retstr } #%%%% # # File I/O # #%%%% # «file_IO» (to ".file_IO") proc readfile {fname} { set channel [open $fname r]; set bigstr [read $channel]; close $channel return $bigstr } proc writefile {fname bigstr} { set channel [open $fname w]; puts -nonewline $channel $bigstr; close $channel } set outfile "-" proc outputs {bigstr} { global outfile if {$outfile=="-"} { puts -nonewline $bigstr } else { writefile $outfile $bigstr } } #%%%% # # Relative links # #%%%% # «relative_links» (to ".relative_links") proc relativepathto {to} { global outfile set from $outfile while {[regexp {([^/]+)/(.*)} $from {} p1from restfrom] && [regexp {([^/]+)/(.*)} $to {} p1to restto] && $p1from==$p1to} { set from $restfrom set to $restto } while {[regexp {([^/]+)/(.*)} $from {} p1from restfrom]} { set from $restfrom set to "../$to" } return $to } #%%%% # # Some extra utilities, in no particular order. # #%%%% # «extra_utils» (to ".extra_utils") proc1 exclude1 {all no} { set rest {} foreach item $all { if {[lsearch $no $item]==-1} { lappend rest $item } } return $rest } # Almost the same: proc1 without1 {no all} { exclude1 $all $no } #%%%% # # Functions for processing templates (for the Hurd pages) # #%%%% # «templates» (to ".templates") # (find-es "hurd" "fsmunoz-template") # split_by_guills replaces the slow regexp below: # regexp {^(.*)«([^«»]*)»(.*)$} $bigstr -> before between after proc split_by_guills {str vbefore vbetween vafter} { set p2 [string first » $str] if {$p2<0} { return 0 } set p1 [string last « [string range $str 0 $p2]] if {$p1<0} { error "too many closing guillemots" } upvar $vbefore before upvar $vbetween between upvar $vafter after set before [string range $str 0 [expr $p1-1]] set between [string range $str [expr $p1+1] [expr $p2-1]] set after [string range $str [expr $p2+1] end] return 1 } proc process_template {bigstr} { while {[split_by_guills $bigstr before between after]} { puts !!! if {![regexp {^([^*]*)*(.*)$} $between -> tclcode pairs]} { error "No Tcl code" } parse_pairs $pairs puts $tclcode uplevel #0 $tclcode set bigstr "$before œœœ $after" } return $bigstr } proc parse_pairs {str} { global lcapts rcapts set lcapts {} set rcapts {} foreach pair [split $str "*"] { if {[regexp {^(([^]*))?([^]*)$} $pair -> _ lcapt rcapt]} { lappend lcapts $lcapt lappend rcapts $rcapt } else { error "Too many triangles" } } } proc captdef {procf func arglist body} { global lcapts rcapts set precode {} foreach lcapt $lcapts rcapt $rcapts { if {$lcapt!="" && [lsearch $arglist $lcapt]==-1} { append precode "[list set $lcapt $rcapt]\n" } } # puts "$procf [list $func] [list $arglist] [list $precode$body]" uplevel #0 "$procf [list $func] [list $arglist] [list $precode$body]" } # Note that this file (Htmllib.tcl) is just a library. # The top-level stuff is at: # (find-fline "~/TH/Generate") # Older notes: # (find-fline "~/TCL/localth") # (find-fline "~/TCL/remoteth") # (find-fline "~/TCL/e2html") # (find-fline "~/TCL/generate") # Some of them may be symlinks. Check: # (find-fline "~/TCL/") # Local Variables: # coding: no-conversion # ee-anchor-format: "«%s»" # ee-charset-indicator: "Ñ" # End: