File: tkmandesc.tcl

package info (click to toggle)
tkman 2.2-2etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 928 kB
  • ctags: 291
  • sloc: tcl: 8,264; sh: 400; makefile: 242
file content (364 lines) | stat: -rw-r--r-- 11,946 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
#--------------------------------------------------
#
# mandesc-like features
#
# mani(<single letter>) => name of full title main index
# mani(<letter>) => listing of full dir & list of names
# mani(<letter>,form) => formatted?
# mani(<letter>,cnt) => # of entries
# mani(<letter>,dirs) => paths x sections cross product, w/mandesc diddling
# --> everybody has a letter and letters aren't repeated
#
#--------------------------------------------------


# cross product of paths by sections
# if LANG environment variable is set, first try to read directories with that name

proc manDescDefaults {} {
	global man manx mani env

	# don't check manx(defaults) here
	manDescManiCheck return

	if {[info exists env(LANG)]} {set langs [split [string trim $env(LANG)] ":"]} else {set langs ""}
	foreach i $mani(manList) { set mani($i,dirs) {} }
	foreach i $manx(paths) { set mani($i,dirs) {} }
	set mani($man(glimpsestrays),dirs) {}
	set curdir [pwd]

	foreach i $manx(paths) {
		cd $i
		set alldirs [glob -nocomplain $manx(subdirs)]
		# is this how languages are handled?
		foreach l $langs {
			# match on $l* so pick up terrirory, character set, version
			set alldirs [concat [glob -nocomplain $l*/$manx(subdirs)] $alldirs]; # localized go first!
		}
#DEBUG {puts "    alldirs = $alldirs"}
#DEBUG {puts "    sorted alldirs = [lsort -command bytypenum $alldirs]"}
		foreach d [lsort -command bytypenum $alldirs] {
			if {[string match "*/*" $d]} {
				set lang "[file dirname $d]/"; set dir [file tail $d]
			} else {set lang ""; set dir $d }
			# keep both manN and manN.Z, with manN.Z preferred
#			set dir [file rootname $d]
#puts "*** building db: $dir"
			if {![regexp $manx(zdirsect) $dir all dirsig]} continue
			# purpose of following line?
			if {[string match "cat*" $dir]} {set dirsig [file rootname $dirsig]}
			set num [file rootname $dirsig]; set num1 [string index $num 0]

			# what section group does it belong to?
			if {[lsearch -exact $mani(manList) $num]!=-1} {set n $num} else {set n $num1}

			# check for conflicts with other abbreviations starting with same letter
			# i.e., if have <lang>/man1, disregard simple man1; if have man1, disregard cat1; but always keep sman
			set pat "^[stringregexpesc $i]/${lang}(man|sman|cat)[stringregexpesc $dirsig]\$"
			set dir $i/$d
#if {[string match "*sman*" $dir]} {puts "*** setting pat: $dir"}
#if {[string match "*sman*" $dir]} {puts "*** \[lsearch -regexp \$mani($i,dirs) $pat\]==[lsearch -regexp $mani($i,dirs) $pat]==-1 && [manPathCheckDir $dir] eq "" && ![regexp {@\d+$} $dir]"}
			if {(![string match "cat*" $d] || [lsearch -regexp $mani($i,dirs) $pat]==-1) && [manPathCheckDir $dir] eq "" && ![regexp {@\d+$} $dir]} {
#if {[string match "*sman*" $dir]} {puts "*** appended: $dir"}
				lappend mani($i,dirs) $dir
				lappend mani($n,dirs) $dir
			}
		}
#DEBUG {puts "mani($i,dirs) = $mani($i,dirs)"}
	}
#DEBUG {foreach i $mani(manList) { puts "mani($i,dirs) = $mani($i,dirs)" }}

	cd $curdir
	set manx(defaults) 1
}

proc bytypenum {a b} {
	if {[string match "*/*" $a]} {set al [file dirname $a]; set a [file tail $a] } else {set al ""}
	if {[string match "*.Z" $a]} {set as [file extension $a]; set a [file rootname $a] } else {set as ""}
	set at [string range $a 0 2]
	if {[string match "*/*" $b]} {set bl [file dirname $b]; set b [file tail $b] } else {set bl ""}
	if {[string match "*.Z" $b]} {set bs [file extension $b]; set b [file rootname $b] } else {set bs ""}
	set bt [string range $b 0 2]

	# priority: language, type (man or cat), number, .Z suffix
	if {$al ne $bl} {
		if {$al eq ""} {return 1} elseif {$bl eq ""} {return -1} elseif {$al<$bl} {return -1} else {return 1}
	} elseif {$at ne $bt} {
		if {$at eq "sma" || ($at eq "man" && $bt eq "cat")} {return -1} else {return 1}
	} elseif {$as ne $bs} {
		# prefer .Z
		if {$as eq ""} {return 1} else {return -1}
	} else {
		if {$a<$b} {return -1} else {return 1}
	}

	return 0
}


# commands: move, copy, delete
# from, to *list* of source, target dirs
# list is list of directory *patterns*

proc manDescMove {from to dirs} {manDesc move $from $to $dirs}
proc manDescDelete {from dirs} {manDesc delete $from "" $dirs}
proc manDescCopy {from to dirs} {manDesc copy $from $to $dirs}
set manx(mandesc-warnings) ""
proc manDescAdd {to dirs} {
	global mani manx man

	set manx(mandesc-warnings) ""
	set warnings ""

	manDescManiCheck
	foreach d $dirs {
		if {[set warnmsg [manPathCheckDir $d]] ne ""} {
			append warnings $warnmsg
		} else {
			foreach t $to {lappend mani($t,dirs) $d}

			# try to attach these oddball directories to some MANPATH
			# in order to make them available for Glimpse indexing
DEBUG {puts "MANPATH for $d?"}
			set mp $d
			while {[string match "/*" $mp] && $mp ne "/"} {
				if {[lsearch -exact $manx(paths) $mp]>=0} {
DEBUG {puts "\tyes, in $mp"}
					lappend mani($mp,dirs) $d; break
				} else {set mp [file dirname $mp]}
			}
			if {$mp eq "/"} { lappend mani($man(glimpsestrays),dirs) $d
DEBUG {puts "\tno, added to strays\n\t\tnow mani($man(glimpsestrays),dirs) =  $mani($man(glimpsestrays),dirs)"}
			}
		}
	}


	if {$warnings ne ""} {
		if {![string match *manDescAdd* $manx(mandesc-warnings)]} {
			append manx(mandesc-warnings) "Problems with manDescAdd's...\n"
		}
		append manx(mandesc-warnings) $warnings
	}
}


proc manDesc {cmd from to dirs} {
	global man manx mani

	manDescManiCheck
	if {$from eq "*"} {set from $mani(manList)}
	if {$to eq "*"} {set to $mani(manList)}
	foreach n [concat $from $to] {
		if {[lsearch $mani(manList) $n]==-1} {
			puts stderr "$cmd: Section letter `$n' doesn't exist."
			exit 1
		}
	}

DEBUG {puts stdout "$cmd {$from} {$to} {$dirs}"}
	foreach d $dirs {
		foreach f $from {
			set newdir {}
			foreach fi $mani($f,dirs) {
				if {[string match $d $fi]} {
					if {$cmd eq "copy"} {lappend newdir $fi}
					if {[regexp "copy|move" $cmd]} {
						foreach t $to {if {$f ne $t} {lappend mani($t,dirs) $fi} else {lappend newdir $fi}}
					}
				} else {lappend newdir $fi}
			}
			set mani($f,dirs) $newdir
DEBUG {puts stdout $f:$mani($f,dirs)}
		}
	}
}

proc manDescAddSects {l {posn "end"} {what "n"}} {
	global man mani

	manDescManiCheck
	if {[regexp "before|after" $posn]} {set l [lreverse $l]}
	foreach i $l {
		foreach {n tit} $i break
		if {[lsearch $mani(manList) $n]!=-1} {
			puts stderr "Section letter `$n' already in use; request ignored."
			continue
		}

		if {$posn eq "end"} {
			lappend mani(manList) $n
			lappend mani(manTitleList) $tit

		} elseif {$posn eq "before" || $posn eq "after"} {
			if {[set ndx [lsearch $mani(manList) $what]]==-1} {
				puts stderr "Requested $posn $what, but $what doesn't exist; request ignored"
				continue
			}
			if {$posn eq "after"} {incr ndx}
			set mani(manList) [linsert $mani(manList) $ndx $n]
			set mani(manTitleList) [linsert $mani(manTitleList) $ndx $tit]

		} elseif {$posn eq "sort"} {
			lappend mani(manList) $n
			set mani(manList) [lsort $mani(manList)]
			set ndx [lsearch $mani(manList) $n]
			set mani(manTitleList) [linsert $mani(manTitleList) $ndx $tit]
		}

		set mani($n,dirs) {}
	}
}


# if mani array, matrix not already created, do it now

proc manDescManiCheck {{action "exit"}} {
	global man mani manx env

	# check for missing call to manDot
	if {!$manx(manDot)} manDot

	if {![info exists mani(manList)]} {
		set mani(manList) $man(manList)
		set mani(manTitleList) $man(manTitleList)

		if {![info exists env(MANPATH)] || [string trim $env(MANPATH)] eq ""} {
			puts stderr "You must set a MANPATH environment variable,\nwhich is a colon-separated list of directories in which\nto find man pages, for example /usr/man:/usr/share/man.\n(See the help page for an explanation of why\nalternatives to the MANPATH are a bad thing.)"
			exit 1
		}
		set manx(MANPATH0) $env(MANPATH)

		manManpathCheck

		if {$action eq "return"} return
		manDescDefaults
	}
}


# place SGI's magically-appearing catman subdirectories into volumes

proc manDescSGI {patterns} {
	global man manx mani

	# start up checks for patterns
	# (=> maybe go with (vol name pats) tuples)

	set paterrs 0
	foreach pat $patterns {
		foreach {mapto patlist} $pat {}

		# make sure each mapping exists as a volume that's been added
		if {[lsearch -regexp $mani(manList) ".?$mapto"]==-1} {
			puts stderr "no volume corresponding to $mapto mapping (patterns: $patlist)"
			incr paterrs
		}

		# make sure patterns don't overlap
		#    can't have identical patterns (ftn =>! 2f and 3ftn.)
		#    either: 2/ftn=>2f and 3/ftn=>3ftn)  *or*  merge with ftn => 2ftn and 3ftn
		foreach p $patlist {
			foreach pat2 $patterns {
				if {$pat eq $pat2} break
				set mapto2 [lfirst $pat2]; set patlist2 [lsecond $pat2]
				foreach p2 $patlist2 {
					if {[string match $p2 $p]} {
						puts stderr "pattern $p never reached -- $mapto2's $p2 precludes it"
						incr paterrs
					}
				}
			}
		}
	}

	# add a guaranteed match, that's placed in single-letter volume
	lappend patterns {"" {""}}
	DEBUG {puts "mani(manList) => $mani(manList)"}

	# collect .../catman directories (know they're readable by this point)
	set catmen {}
	foreach d $manx(paths) {
#[split $manx(MANPATH0) ":"] {
		if {[string match "*/catman" $d]} {lappend catmen $d}
	}
	if {![llength $catmen]} {
		puts stderr "No sneaky catman directories found in MANPATH:\n\t$manx(MANPATH0)"
		return
		#exit 1
	}


	# make sure end of list test is deferred because possibly adding to list each time
	set rcats $catmen; set catmandirs {}
	for {set i 0} {$i<[llength $rcats]} {incr i} {
###	foreach dir $rcats ???
		foreach f [glob -nocomplain [file join [lindex $rcats $i] "*"]] {
			# relying on shortcircuiting behavior of &&
			# Tcl's file isdirectory dereferences symbolic links
			# SGI's xman relies upon directories not ending in .z,
			# don't use ![regexp $manx(zregexp) $f] as manx(zregexp) not set when this is called
		    	# can't rely on pack .z compression: seen .gz, seen uncompressed -- checking for "." in filename tail (.z/.gz/.3X/...)
# was:			if {![string match "*.z" $f]...
			if {![regexp {/[^/]+\.[^/]+$} $f] && [file tail $f] ne "RCS" && [file tail $f] ne "RCSdiff" && [lsearch -exact $rcats $f]==-1 && [file isdirectory $f]} {
				lappend rcats $f; lappend catmandirs $f
			}
		}
	}

	foreach dir $catmandirs {
		if {[regexp {(catman|_man)$} $dir]} continue
		set tail [file tail $dir]
		set vol [file tail [file dirname $dir]]
		if {![regexp "^(man|cat)" $vol]} {set vol $tail; set tail ""}

		set volnum [string index $vol 3]

		DEBUG {puts -nonewline "$dir ($vol:$tail ($volnum)) => "}
		set matched 0
		foreach pat $patterns {
			foreach {mapto patlist} $pat break
			foreach dp $patlist {
				if {[string match "*$dp" $dir]} {
					DEBUG {puts -nonewline "match on $dp => "}
					set matched 1
					# first try to place in mapto name in current volume
					if {[lsearch -exact $mani(manList) "$volnum$mapto"]!=-1} {
						DEBUG {puts $volnum$mapto}
						manDescAdd "$volnum$mapto" $dir

					# then try mapto name in any volume
					} elseif {[lsearch -exact $mani(manList) $mapto]!=-1} {
						DEBUG {puts $mapto}
						manDescAdd $mapto $dir

			 		# else place in a parent volume
					} elseif {[lsearch -exact $mani(manList) $volnum]!=-1} {
						DEBUG {puts $volnum}
						manDescAdd $volnum $dir

					} else {
						DEBUG {puts "can't place"}
					}

					break
				}
			}
			if {$matched} break
		}
		DEBUG {if {!$matched} {puts "CAN'T MATCH\a\a"}}
	}
}



# for debugging
proc manDescShow {} {
	global man manx mani

	manDescManiCheck
	puts stdout "*** manDescShow"
	foreach i $mani(manList) {
		puts stdout $i:$mani($i,dirs)
	}
}