hpage (title) (text) ;# register a hypertext page's title and text body htext (widget) ?title? ;# bring up a toplevel showing the specified page(or an alphabetic index of titles, if not specified). Thus you can use it for context-sensitive help. Hypertext pages are in a subset of Wiki format:
- indented lines come in fixed font without evaluation;
- blank lines break paragraphs
- all lines without leading blanks are displayed without explicit linebreak (but possibly word-wrapped)
- a link is the title of another page in brackets (see examples at end).
set range [$w tag prevrange link "[$w index @$x,$y] + 1 char"]}
namespace eval htext {
namespace export hpage htext
variable pages
variable history {} seen {}
proc hpage {title body} {
variable pages
set pages($title) $body
}
proc htext {w args} {
if ![winfo exists $w] {
wm title [toplevel $w] Help
text $w.t -border 5 -relief flat -wrap word -state disabled
pack $w.t -fill both -expand 1
$w.t tag config link -foreground blue -underline 1
$w.t tag config seen -foreground purple4 -underline 1
$w.t tag bind link <Enter> "$w.t config -cursor hand2"
$w.t tag bind link <Leave> "$w.t config -cursor {}"
$w.t tag bind link <1> "[namespace current]::click $w.t %x %y"
$w.t tag config hdr -font {Times 16}
$w.t tag config fix -font {Courier 9}
}
raise $w
variable pages
if ![llength [array names pages $args]] {set args Index}
show $w.t $args
}
proc click {w x y} {
set range [$w tag prevrange link [$w index @$x,$y]]
if [llength $range] {show $w [eval $w get $range]}
}
proc back w {
variable history
set l [llength $history]
set last [lindex $history [expr $l-2]]
set history [lrange $history 0 [expr $l-3]]
show $w $last
}
proc listpage {w list} {
foreach i $list {$w insert end \n; showlink $w $i}
}
proc search w {
$w insert end "\nSearch phrase: "
entry $w.e -textvar [namespace current]::search
$w window create end -window $w.e
focus $w.e
$w.e select range 0 end
bind $w.e <Return> "htext::dosearch $w"
button $w.b -text Search! -command "htext::dosearch $w" -pady 0
$w window create end -window $w.b
}
proc dosearch w {
variable search
variable pages
$w config -state normal
$w insert end "\n\nSearch results for '$search':\n"
foreach i [lsort [array names pages]] {
if [regexp -nocase $search $i] {
$w insert end \n; showlink $w $i ;# found in title
} elseif [regexp -nocase -indices -- $search $pages($i) pos] {
regsub -all \n [string range $pages($i) \
[expr [lindex $pos 0]-20] [expr [lindex $pos 1]+20]] \
" " context
$w insert end \n
showlink $w $i
$w insert end " - ...$context..."
}
}
$w config -state disabled
}
proc showlink {w link} {
variable seen
set tag link
if {[lsearch -exact $seen $link]>-1} {
lappend tag seen
}
$w insert end $link $tag
}
proc show {w title} {
variable pages
variable history
variable seen
if {[lsearch -exact $seen $title]==-1} {lappend seen $title}
$w config -state normal
$w delete 1.0 end
$w insert end $title hdr \n
switch -- $title {
Back {back $w; return}
History {listpage $w $history}
Index {listpage $w [lsort [array names pages]]}
Search {search $w}
default {
set var 1
foreach i [split $pages($title) \n] {
if [regexp {^[ \t]+} $i] {
if $var {$w insert end \n\n; set var 0}
$w insert end $i\n fix
continue
}
set i [string trim $i]
if ![string length $i] {$w insert end \n\n; continue}
if !$var {$w insert end \n}
set var 1
while {[regexp {([^[]*)[[]([^]]+)[]](.*)} $i \
-> before link after]} {
$w insert end "$before " {}
showlink $w $link
set i $after
}
$w insert end "$i "
}
}
}
$w insert end \n------\n {} Index link " - " {} Search link
if [llength $history] {
$w insert end " - " {} History link " - " {} Back link
}
$w insert end \n
lappend history $title
$w config -state disabled
}
}# Example test code (please ignore the links below): namespace import htext::*
hpage Test {This is a help page with a Reference. Before this sentence came a hard linebreak.This is after an empty line. } hpage Reference {This is another page which points back to [Test] and to [Index]. It also shows acode example [which should come in Courier] and has two lines that should stay close togetherand back in normal text. }
hpage Foo {Frequent but undefined word. See also [Bar]}
hpage Bar {Place to drink, for example. Have you checked [Foo]?}
hpage "Two words" {Just checking - [Foo] and [Bar].}
htext .hSince my help texts are fairly long sometimes, I added a scrollbar.Just change two lines of proc htext:
...
text $w.t -border 5 -relief flat -wrap word -state disabled
pack $w.t -fill both -expand 1
...to
...
text $w.t -border 5 -relief flat -wrap word -state disabled \
-yscrollcommand "$w.s set"
scrollbar $w.s -orient vert -command "$w.t yview"
pack $w.t -fill both -expand 1 -side left
pack $w.s -fill y -side left
...US
