Version 7 of A Minimal Hypertext Help System

Updated 2005-11-15 09:12:02

D. McC: For those who want super-simple hypertext help with extremely little overhead, here's something that will do the job. It requires:

  • Tk 8.5, to use the "-all" flag in the text searches. (At the expense of making it a bit less simple, I'll try to come up with a loop to substitute for the "-all" flag in Tk 8.4--soon, very soon. At least Tk 8.4 will be needed in any event, to use the "-elide" flag for hiding the link markup tags.)
  • A plain-text help file with uniquely named section titles (or other section identifiers), plus minimal markup for links with names that exactly replicate the section titles, like this:
 <link "Run Programs:">Run Programs</link>

 package require Tk

 # Here's a proc to create the text box:

 proc userhelp {} {
        toplevel .uhelp
        grid [text .uhelp.tx -width 65 -height 25 -bg white \
                -yscrollcommand ".uhelp.roll set" \
                -font "times 14" -wrap word -cursor top_left_arrow] \
                -row 0 -column 0 -sticky news
        grid [scrollbar .uhelp.roll -width 12 \
                -command ".uhelp.tx yview"] -row 0 -column 1 -sticky news
        grid [button .uhelp.close -text "Close" -borderwidth 6 \
                -command {destroy .uhelp}] -row 1 -column 0 \
                -columnspan 2 -sticky news
        grid rowconfigure    .uhelp 0 -weight 1
        grid columnconfigure .uhelp 0 -weight 1
 }

 # Here's one to get the text widget to display links and let the user see 
 # the uniquely named sections when the links are clicked 
 # (anybody who can make this one even simpler than it is, please let me know):

 proc getlinks {} {

        # Find beginnings and ends of all links:
        set linkstars [.uhelp.tx search -regexp -all \
                -count cti "<link .+?>" 1.0 end]
        set linkends [.uhelp.tx search -regexp -all "</link>" 1.0 end]   ;# !!

        # Fix the links up to work:
        for {set i 0} {$i < [llength $linkstars]} {incr i} {
                set star [lindex $linkstars $i] ; # Begin link-start tag
                set starleng [lindex $cti $i] ; # Length of link-start tag
                set starsplit [split $star "."]
                set starline [lindex $starsplit 0] ; # Line number in text
                set starchar [lindex $starsplit end] ; # Position in line

                # End of link-start tag:
                set starend $starline.[expr {$starchar + $starleng}]
                # Content of link-start tag:
                set linkstar [.uhelp.tx get $star $starend]
                set linkname [string trim $linkstar "<>"] ; # Link name

                # Tag to hide link tags:
                .uhelp.tx tag configure hide -elide 1
                .uhelp.tx tag add hide $star $starend

                # Add tag for clickable link between link-start and link-end tags:
                set finis [lindex $linkends $i]
                .uhelp.tx tag add $linkname $starend $finis
                # And one to hide the link-end tag:
                .uhelp.tx tag add hide $finis "$finis +7c"

                # Get clickable tag to look right and do things:
                .uhelp.tx tag configure $linkname -foreground blue -underline 1
                .uhelp.tx tag bind $linkname <ButtonRelease-1> {
                        # See where clicked link is:
                        set clickpos [.uhelp.tx index insert]
                        # Verify that it's really a link:
                        set tagnames [.uhelp.tx tag names $clickpos]
                        set tagplace [lsearch $tagnames "link *"]
                        if {$tagplace > -1} {
                                # If so, strip off everything but its name:
                                set tagname [lindex $tagnames $tagplace]
                                set tagend [lindex [.uhelp.tx tag range "$tagname"] end]
                                set searchname [string map "{link } {} {\"} {}" $tagname]
                                # And find where the name appears in the help-file text:
                                set target [.uhelp.tx search "$searchname" $tagend \
                                         end]
                                if {$target ne ""} {
                                        .uhelp.tx see $target
                                }
                        }
                }
        }
 }

 # And here's an example of a proc for getting an application to invoke the help system:

 proc comhelp {} {
        userhelp
        wm title .uhelp "WISH Command Center - User Help"
        set helpfile [open /home/david/9.com/wish/suite/comhelp_link.txt r]
        set helpcontents [read $helpfile]
        close $helpfile
        .uhelp.tx insert 1.0 $helpcontents
        getlinks
 }

 # Test:
 comhelp

HJG I get an error: 'bad switch "-all": must be -, -backward, -count, -elide, -exact, -forward, -nocase, or -regexp' in getlinks (the line marked with "!!"). Maybe requiring Tcl 8.4 is not specific enough ?

D. McC: Ugh! You're right. I just noticed that the "-all" flag for text-widget searches only came in with Tk 8.5. I've changed the statement of requirements at the top of this page. I do have some code for a loop that can substitute for the "-all" flag; I'll see about modifying it for use with this help system.


Category Deployment | Category Documentation