|
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: