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