|
|
1.1 root 1: #
2: # help.tcl --
3: #
4: # Tcl help command. (see TclX manual)
5: #
6: #------------------------------------------------------------------------------
7: # Copyright 1992 Karl Lehenbauer and Mark Diekhans.
8: #
9: # Permission to use, copy, modify, and distribute this software and its
10: # documentation for any purpose and without fee is hereby granted, provided
11: # that the above copyright notice appear in all copies. Karl Lehenbauer and
12: # Mark Diekhans make no representations about the suitability of this
13: # software for any purpose. It is provided "as is" without express or
14: # implied warranty.
15: #------------------------------------------------------------------------------
16: # $Id: help.tcl,v 2.0 1992/10/16 04:52:01 markd Rel $
17: #------------------------------------------------------------------------------
18: #
19:
20: #@package: TclX-help help helpcd helppwd apropos
21:
22: #------------------------------------------------------------------------------
23: # Take a path name which might have . and .. elements and flatten them out.
24:
25: proc help:flattenPath {pathName} {
26: set newPath {}
27: foreach element [split $pathName /] {
28: if {"$element" == "."} {
29: continue
30: }
31: if {"$element" == ".."} {
32: if {[llength [join $newPath /]] == 0} {
33: error "Help: name goes above subject directory root"}
34: lvarpop newPath [expr [llength $newPath]-1]
35: continue
36: }
37: lappend newPath $element
38: }
39: set newPath [join $newPath /]
40:
41: # Take care of the case where we started with something line "/" or "/."
42:
43: if {("$newPath" == "") && [string match "/*" $pathName]} {
44: set newPath "/"}
45:
46: return $newPath
47: }
48:
49: #------------------------------------------------------------------------------
50: # Take the help current directory and a path and evaluate it into a help root-
51: # based path name.
52:
53: proc help:EvalPath {pathName} {
54: global TCLENV
55:
56: if {![string match "/*" $pathName]} {
57: if {"$pathName" == ""} {
58: return $TCLENV(help:curDir)}
59: if {"$TCLENV(help:curDir)" == "/"} {
60: set pathName "/$pathName"
61: } else {
62: set pathName "$TCLENV(help:curDir)/$pathName"
63: }
64: }
65: set pathName [help:flattenPath $pathName]
66: if {[string match "*/" $pathName] && ($pathName != "/")} {
67: set pathName [csubstr $pathName 0 [expr [length $pathName]-1]]}
68:
69: return $pathName
70: }
71:
72: #------------------------------------------------------------------------------
73: # Display a line of output, pausing waiting for input before displaying if the
74: # screen size has been reached. Return 1 if output is to continue, return
75: # 0 if no more should be outputed, indicated by input other than return.
76: #
77:
78: proc help:Display {line} {
79: global TCLENV
80: if {$TCLENV(help:lineCnt) >= 23} {
81: set TCLENV(help:lineCnt) 0
82: puts stdout ":" nonewline
83: flush stdout
84: gets stdin response
85: if {![lempty $response]} {
86: return 0}
87: }
88: puts stdout $line
89: incr TCLENV(help:lineCnt)
90: }
91:
92: #------------------------------------------------------------------------------
93: # Display a file.
94:
95: proc help:DisplayFile {filepath} {
96:
97: set inFH [open $filepath r]
98: while {[gets $inFH fileBuf] >= 0} {
99: if {![help:Display $fileBuf]} {
100: break}
101: }
102: close $inFH
103:
104: }
105:
106: #------------------------------------------------------------------------------
107: # Procedure to return contents of a directory. A list is returned, consisting
108: # of two lists. The first list are all the directories (subjects) in the
109: # specified directory. The second is all of the help files. Eash sub-list
110: # is sorted in alphabetical order.
111: #
112:
113: proc help:ListDir {dirPath} {
114: set dirList {}
115: set fileList {}
116: if {[catch {set dirFiles [glob $dirPath/*]}] != 0} {
117: error "No files in subject directory: $dirPath"}
118: foreach fileName $dirFiles {
119: if [file isdirectory $fileName] {
120: lappend dirList "[file tail $fileName]/"
121: } else {
122: lappend fileList [file tail $fileName]
123: }
124: }
125: return [list [lsort $dirList] [lsort $fileList]]
126: }
127:
128: #------------------------------------------------------------------------------
129: # Display a list of file names in a column format. This use columns of 14
130: # characters 3 blanks.
131:
132: proc help:DisplayColumns {nameList} {
133: set count 0
134: set outLine ""
135: foreach name $nameList {
136: if {$count == 0} {
137: append outLine " "}
138: append outLine $name
139: if {[incr count] < 4} {
140: set padLen [expr 17-[clength $name]]
141: if {$padLen < 3} {
142: set padLen 3}
143: append outLine [replicate " " $padLen]
144: } else {
145: if {![help:Display $outLine]} {
146: return}
147: set outLine ""
148: set count 0
149: }
150: }
151: if {$count != 0} {
152: help:Display $outLine}
153: return
154: }
155:
156:
157: #------------------------------------------------------------------------------
158: # Help command main.
159:
160: proc help {{subject {}}} {
161: global TCLENV
162:
163: set TCLENV(help:lineCnt) 0
164:
165: # Special case "help help", so we can get it at any level.
166:
167: if {($subject == "help") || ($subject == "?")} {
168: help:DisplayFile "$TCLENV(help:root)/help"
169: return
170: }
171:
172: set request [help:EvalPath $subject]
173: set requestPath "$TCLENV(help:root)$request"
174:
175: if {![file exists $requestPath]} {
176: error "Help:\"$request\" does not exist"}
177:
178: if [file isdirectory $requestPath] {
179: set dirList [help:ListDir $requestPath]
180: set subList [lindex $dirList 0]
181: set fileList [lindex $dirList 1]
182: if {[llength $subList] != 0} {
183: help:Display "\nSubjects available in $request:"
184: help:DisplayColumns $subList
185: }
186: if {[llength $fileList] != 0} {
187: help:Display "\nHelp files available in $request:"
188: help:DisplayColumns $fileList
189: }
190: } else {
191: help:DisplayFile $requestPath
192: }
193: return
194: }
195:
196:
197: #------------------------------------------------------------------------------
198: # Helpcd main.
199: #
200: # The name of the new current directory is assembled from the current
201: # directory and the argument. The name will be flatten and any trailing
202: # "/" will be removed, unless the name is just "/".
203:
204: proc helpcd {{dir /}} {
205: global TCLENV
206:
207: set request [help:EvalPath $dir]
208: set requestPath "$TCLENV(help:root)$request"
209:
210: if {![file exists $requestPath]} {
211: error "Helpcd: \"$request\" does not exist"}
212:
213: if {![file isdirectory $requestPath]} {
214: error "Helpcd: \"$request\" is not a directory"}
215:
216: set TCLENV(help:curDir) $request
217: return
218: }
219:
220: #------------------------------------------------------------------------------
221: # Helpcd main.
222:
223: proc helppwd {} {
224: global TCLENV
225: echo "Current help subject directory: $TCLENV(help:curDir)"
226: }
227:
228: #==============================================================================
229: # Tcl apropos command. (see Tcl shell manual)
230: #------------------------------------------------------------------------------
231:
232: proc apropos {name} {
233: global TCLENV
234:
235: set TCLENV(help:lineCnt) 0
236:
237: set aproposCT [scancontext create]
238: scanmatch -nocase $aproposCT $name {
239: set path [lindex $matchInfo(line) 0]
240: set desc [lrange $matchInfo(line) 1 end]
241: if {![help:Display [format "%s - %s" $path $desc]]} {
242: return}
243: }
244: foreach brief [glob -nocomplain $TCLENV(help:root)/*.brf] {
245: set briefFH [open $brief]
246: scanfile $aproposCT $briefFH
247: close $briefFH
248: }
249: scancontext delete $aproposCT
250: }
251:
252: #------------------------------------------------------------------------------
253: # One time initialization done when the file is sourced.
254: #
255: global TCLENV TCLPATH
256:
257: set TCLENV(help:root) [searchpath $TCLPATH help]
258: set TCLENV(help:curDir) "/"
259: set TCLENV(help:outBuf) {}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.