1# -*- tcl -*-
2# sak::doc::auto - Documentation facilities, support for automatic
3# list of manpages, keyword index, and table of contents.
4
5package require sak::util
6
7namespace eval ::sak::doc::auto {
8    set here [file dirname [file normalize [info script]]]
9}
10
11getpackage fileutil         fileutil/fileutil.tcl
12getpackage doctools         doctools/doctools.tcl
13getpackage textutil::repeat textutil/repeat.tcl
14
15# ###
16# API commands
17
18proc ::sak::doc::auto::manpages {} {
19    variable here
20    return [file join $here manpages.txt]
21}
22
23proc ::sak::doc::auto::kwic {} {
24    variable here
25    return [file join $here kwic.txt]
26}
27
28proc ::sak::doc::auto::toc {} {
29    variable here
30    return [file join $here toc.txt]
31}
32
33## ### ### ### ######### ######### #########
34
35proc ::sak::doc::auto::findManpages {base} {
36    set top [file normalize $base]
37    set manpages {}
38    foreach page [concat \
39		      [glob -nocomplain -directory $top/modules */*.man] \
40		      [glob -nocomplain -directory $top/apps      *.man]] {
41	lappend manpages [fileutil::stripPath $top $page]
42    }
43    return [lsort -dict $manpages]
44}
45
46proc ::sak::doc::auto::saveManpages {manpages} {
47    fileutil::writeFile [manpages] [join [lsort -dict $manpages] \n]\n
48    return
49}
50
51proc ::sak::doc::auto::loadManpages {} {
52    return [lsort -dict [split [fileutil::cat [manpages]] \n]]
53}
54
55## ### ### ### ######### ######### #########
56
57proc ::sak::doc::auto::scanManpages {manpages} {
58    ::doctools::new dt -format list
59    set data {}
60    puts Scanning...
61    foreach page $manpages {
62	puts ...$page
63	lappend data $page [lindex [dt format [fileutil::cat $page]] 1]
64    }
65
66    dt destroy
67    return $data
68}
69
70## ### ### ### ######### ######### #########
71
72proc ::sak::doc::auto::saveKeywordIndex {kv nv} {
73    upvar 1 $kv kwic $nv name
74    # kwic: keyword -> list (files)
75    # name: file    -> label
76
77    TagsBegin
78    Tag+ index_begin [list {Keyword Index} {}]
79
80    # Handle the keywords in dictionary order for nice display.
81    foreach kw [lsort -dict [array names kwic]] {
82	set tmp [Sortable $kwic($kw) name max _]
83
84	Tag+ key [list $kw]
85	foreach item [lsort -dict -index 0 $tmp] {
86	    foreach {label file} $item break
87	    Tag+ manpage [FmtR max $file] [list $label]
88	}
89    }
90
91    Tag+ index_end
92
93    fileutil::writeFile [kwic] [join $lines \n]
94    return
95}
96
97## ### ### ### ######### ######### #########
98
99proc ::sak::doc::auto::saveTableOfContents {tv nv cv av mv} {
100    upvar 1 $tv title $nv name $cv cat $av apps $mv mods
101    # title: file     -> description
102    # name:  file     -> label
103    # cat:   category -> list (file...)
104
105    TagsBegin
106    Tag+ toc_begin [list {Table Of Contents} {}]
107
108    # The man pages are sorted in several ways for the toc.
109    # 1. First section by category. Subsections are categories.
110    #    Sorted by category name, in dictionary order.
111    #    Inside the subsections the files, sorted by label and
112    #    description.
113    # 2. Second section for types. Subsections are modules and apps.
114    #    Apps first, then modules. For apps items directly, sorted
115    #    by name and description. For modules one sub-subsection
116    #    per module, elements the packages, sorted by label and
117    #    description.
118
119    Tag+ division_start [list {By Categories}]
120    foreach c [lsort -dict [array names cat]] {
121	Tag+ division_start [list $c]
122	foreach item [lsort -dict -index 0 [Sortable $cat($c) name maxf maxl]] {
123	    foreach {label file} $item break
124	    Tag+ item \
125		[FmtR maxf $file] \
126		[FmtR maxl $label] \
127		[list $title($file)]
128	}
129	Tag+ division_end
130    }
131    Tag+ division_end
132
133    Tag+ division_start [list {By Type}]
134    # Not handled: 'no applications'
135    Tag+ division_start [list {Applications}]
136    foreach item [lsort -dict -index 0 [Sortable $apps name maxf maxl]] {
137	foreach {label file} $item break
138	Tag+ item \
139	    [FmtR maxf $file] \
140	    [FmtR maxl $label] \
141	    [list $title($file)]
142    }
143    Tag+ division_end
144    # Not handled: 'no modules'
145    Tag+ division_start [list {Modules}]
146    foreach m [lsort -dict [array names mods]] {
147	Tag+ division_start [list $m]
148	foreach item [lsort -dict -index 0 [Sortable $mods($m) name maxf maxl]] {
149	    foreach {label file} $item break
150	    Tag+ item \
151		[FmtR maxf $file] \
152		[FmtR maxl $label] \
153		[list $title($file)]
154	}
155	Tag+ division_end
156    }
157    Tag+ division_end
158    Tag+ division_end
159    Tag+ toc_end
160
161    fileutil::writeFile [toc] [join $lines \n]
162    return
163}
164
165proc ::sak::doc::auto::Sortable {files nv mfv mnv} {
166    upvar 1 $nv name $mfv maxf $mnv maxn
167    # Generate a list of files sortable by name, and also find the
168    # max length of all relevant names.
169    set maxf 0
170    set maxn 0
171    set tmp {}
172    foreach file $files {
173	lappend tmp [list $name($file) $file]
174	Max maxf $file
175	Max maxn $name($file)
176    }
177    return $tmp
178}
179
180## ### ### ### ######### ######### #########
181
182proc ::sak::doc::auto::Max {v str} {
183    upvar 1 $v max
184    set x [string length $str]
185    if {$x <= $max} return
186    set max $x
187    return
188}
189
190proc ::sak::doc::auto::FmtR {v str} {
191    upvar 1 $v max
192    return [list $str][textutil::repeat::blank \
193	    [expr {$max - [string length [list $str]]}]]
194}
195
196## ### ### ### ######### ######### #########
197
198proc ::sak::doc::auto::Tag {n args} {
199    if {[llength $args]} {
200	return "\[$n [join $args]\]"
201    } else {
202	return "\[$n\]"
203    }
204    #return \[[linsert $args 0 $n]\]
205}
206
207proc ::sak::doc::auto::Tag+ {n args} {
208    upvar 1 lines lines
209    lappend lines [eval [linsert $args 0 ::sak::doc::auto::Tag $n]]
210    return
211}
212
213proc ::sak::doc::auto::TagsBegin {} {
214    upvar 1 lines lines
215    set lines {}
216    return
217}
218
219## ### ### ### ######### ######### #########
220
221package provide sak::doc::auto 1.0
222