1# -*- tcl -*- 2# 3# -- Engine to convert a doctools document into plain text. 4# 5# Copyright (c) 2003-2019 Andreas Kupries <andreas_kupries@sourceforge.net> 6 7# # ## ### ##### ######## ############# 8## Load shared code and modify it to our needs. 9 10dt_source _common.tcl 11dt_source _text.tcl 12 13proc c_copyrightsymbol {} {return "(c)"} 14 15# # ## ### ##### ######## 16## Special manpage contexts 17 18# example = if present, context is for an example 19# exenv = if present, reference to example variant of current context 20 21proc Example! {} { CAttrSet example . } 22proc Example? {} { CAttrHas example } 23 24proc NewExample {} { 25 return [ContextNew Example { VerbatimOn ; Example! ; Prefix! "| " }] ; # {} 26} 27 28proc Example {} { 29 if {![CAttrHas exenv]} { 30 ContextPush 31 set exenv [NewExample] 32 ContextPop 33 CAttrSet exenv $exenv 34 ContextCommit 35 } 36 return [CAttrGet exenv] 37} 38 39proc NewList {what} { 40 # List contexts 41 # Per list type several contexts are required. 42 #puts_stderr "LIST OUT [CAttrName] NewList $what" 43 44 switch -exact -- $what { 45 enumerated {NewOrderedList} 46 itemized {NewUnorderedList} 47 arguments - 48 commands - 49 options - 50 tkoptions - 51 definitions {NewDefinitionList} 52 } 53 54 #puts_stderr "LIST INN [CAttrName]" 55 return 56} 57 58proc NewUnorderedList {} { 59 # Itemized list - unordered list - bullet 60 # 1. Base context provides indentation. 61 # 2. First paragraph in a list item. 62 # 3. All other paragraphs. 63 ContextPush 64 65 set base [ContextNew Itemized { 66 LC 67 MarginIn 68 set bullet [IBullet] 69 }] ; # {} 70 71 set first [ContextNew First { 72 List! bullet $bullet [BlankMargin] 73 }] ; ContextSet $base ; # {} 74 75 set next [ContextNew Next { 76 MarginIn 77 }] ; ContextSet $base ; # {} 78 79 OUL $first $next 80 ContextCommit 81 82 ContextPop 83 ContextSet $base 84 return 85} 86 87proc NewOrderedList {} { 88 # Ordered list - enumeration - enum 89 # 1. Base context provides indentation. 90 # 2. First paragraph in a list item. 91 # 3. All other paragraphs. 92 ContextPush 93 94 set base [ContextNew Enumerated { 95 LC 96 MarginIn 97 set bullet [EBullet] 98 }] ; # {} 99 100 set first [ContextNew First { 101 List! enum $bullet [BlankMargin] 102 }] ; ContextSet $base ; # {} 103 104 set next [ContextNew Next { 105 MarginIn 106 }] ; ContextSet $base ; # {} 107 108 OUL $first $next 109 ContextCommit 110 111 ContextPop 112 ContextSet $base 113 return 114} 115 116proc NewDefinitionList {} { 117 # Definition list - terms & definitions 118 # 1. Base context provides indentation. 119 # 2. Term context 120 # 3. Definition context 121 ContextPush 122 123 set base [ContextNew Definitions { 124 LC 125 MarginIn 126 }] ; # {} 127 128 set term [ContextNew Term { 129 VerbatimOn 130 }] ; ContextSet $base ; # {} 131 132 set def [ContextNew Def { 133 MarginIn 134 }] ; ContextSet $base ; # {} 135 136 TD $term $def 137 ContextCommit 138 139 ContextPop 140 ContextSet $base 141 return 142} 143 144# # ## ### ##### ######## 145## 146 147proc LC {} { 148 # Clear inherited list type information from the current context 149 CAttrUnset _first 150 CAttrUnset _next 151 CAttrUnset _term 152 CAttrUnset _definition 153} 154 155proc OUL {f n} { 156 CAttrSet _first $f 157 CAttrSet _next $n 158} 159 160proc TD {t d} { 161 CAttrSet _term $t 162 CAttrSet _definition $d 163} 164 165proc IsPara {} { CAttrHas _next } 166proc Paras {} { global __pcount ; set __pcount } 167proc PAdvance {} { 168 global __pcount ; incr __pcount 1 169 #puts_stderr " ZZZ/ItemParas/Advance:$__pcount" 170} 171proc PReset {} { 172 #puts_stderr " ZZZ/ItemParas/Reset" 173 global __pcount ; set __pcount 0 } 174 175global __pcount ; set __pcount 0 176global __pcstack ; set __pcstack {} 177 178proc PSave {} { 179 global __pcount __pcstack 180 lappend __pcstack $__pcount 181 PReset 182} 183 184proc PRestore {} { 185 global __pcount __pcstack 186 set __pcount [lindex $__pcstack end] 187 set __pcstack [lrange $__pcstack 0 end-1] 188 #puts_stderr " ZZZ/ItemParas/Restore:$__pcount" 189 return 190} 191 192proc First {} { CAttrGet _first } 193proc Other {} { CAttrGet _next } 194proc Term {} { CAttrGet _term } 195proc Def {} { CAttrGet _definition } 196proc IsDef {} { CAttrHas _definition } 197 198# # ## ### ##### ######## 199## 200 201proc CloseCurrent {} { 202 if {[IsDef]} { 203 #puts_stderr " ZZZ/CloseCurrent/Definitions" 204 # Currently in a definition list. 205 CloseParagraph [Def] 206 } elseif {[IsPara]} { 207 #puts_stderr " ZZZ/CloseCurrent/UOL" 208 # Currently in an (un)ordered list. 209 #puts_stderr " ZZZ/ItemParas/[Paras]" 210 if {![Paras]} { 211 # No paragraphs yet, this is first in the item 212 if {[CloseParagraph [First]]} PAdvance 213 } else { 214 # More paragraphs in the item 215 if {[CloseParagraph [Other]]} PAdvance 216 } 217 } else { 218 #puts_stderr " ZZZ/CloseCurrent/Plain" 219 # Currently in a regular paragraph 220 CloseParagraph 221 } 222} 223 224proc GetCurrent {} { 225 if {[IsDef]} { 226 #puts_stderr " ZZZ/GetCurrent/Definitions" 227 # Currently in a definition list. 228 return [Def] 229 } elseif {[IsPara]} { 230 #puts_stderr " ZZZ/GetCurrent/UOL" 231 # Currently in an (un)ordered list. 232 #puts_stderr " ZZZ/ItemParas/[Paras]" 233 if {![Paras]} { 234 set res [First] 235 } else { 236 set res [Other] 237 } 238 PAdvance 239 return $res 240 } else { 241 #puts_stderr " ZZZ/GetCurrent/Plain" 242 # Currently in a regular paragraph 243 return {} 244 } 245} 246 247# # ## ### ##### ######## 248## 249 250c_holdBuffers require 251 252rename fmt_initialize BaseInitialize 253proc fmt_initialize {} {BaseInitialize ; TextInitialize ; return} 254 255proc fmt_postprocess {text} { text_postprocess $text } 256 257# # ## ### ##### ######## 258## Implementations of the formatting commands. 259 260c_pass 1 fmt_plain_text {text} NOP 261c_pass 2 fmt_plain_text {text} { text_plain_text $text } 262 263c_pass 1 fmt_manpage_begin {title section version} NOP 264c_pass 2 fmt_manpage_begin {title section version} { 265 Off 266 set module [dt_module] 267 set shortdesc [c_get_module] 268 set description [c_get_title] 269 270 set hdr [list] 271 lappend hdr "$title - $shortdesc" 272 lappend hdr [c_provenance] 273 lappend hdr "[string trimleft $title :]($section) $version $module \"$shortdesc\"" 274 set hdr [join $hdr \n] 275 276 Text $hdr 277 CloseParagraph [Verbatim] 278 Section NAME 279 Text "$title - $description" 280 CloseParagraph 281 return 282} 283 284c_pass 1 fmt_moddesc {desc} {c_set_module $desc} 285c_pass 2 fmt_moddesc {desc} NOP 286 287c_pass 1 fmt_titledesc {desc} {c_set_title $desc} 288c_pass 2 fmt_titledesc {desc} NOP 289 290c_pass 1 fmt_copyright {desc} {c_set_copyright $desc} 291c_pass 2 fmt_copyright {desc} NOP 292 293c_pass 1 fmt_manpage_end {} NOP 294c_pass 2 fmt_manpage_end {} { 295 set sa [c_xref_seealso] 296 set kw [c_xref_keywords] 297 set ca [c_xref_category] 298 set ct [c_get_copyright] 299 300 CloseParagraph 301 if {[llength $sa] > 0} {Section {SEE ALSO} ; Text [join [lsort $sa] ", "] ; CloseParagraph} 302 if {[llength $kw] > 0} {Section KEYWORDS ; Text [join [lsort $kw] ", "] ; CloseParagraph} 303 if {$ca ne ""} {Section CATEGORY ; Text $ca ; CloseParagraph} 304 if {$ct != {}} {Section COPYRIGHT ; Text $ct ; CloseParagraph [Verbatim]} 305 return 306} 307 308c_pass 1 fmt_section {name {id {}}} NOP 309c_pass 2 fmt_section {name {id {}}} {CloseParagraph ; Section $name ; return} 310 311c_pass 1 fmt_subsection {name {id {}}} NOP 312c_pass 2 fmt_subsection {name {id {}}} {CloseParagraph ; Subsection $name ; return} 313 314c_pass 1 fmt_para {} NOP 315c_pass 2 fmt_para {} { 316 CloseCurrent 317 #puts_stderr "AAA/fmt_para/START" 318 return 319} 320 321# NL is an alias of PARA 322# See also fmt_example_begin 323c_pass 1 fmt_nl {} NOP 324c_pass 2 fmt_nl {} {CloseCurrent ; return } 325 326c_pass 2 fmt_require {pkg {version {}}} NOP 327c_pass 1 fmt_require {pkg {version {}}} { 328 set result "package require $pkg" 329 if {$version != {}} {append result " $version"} 330 c_hold require $result 331 return 332} 333 334c_pass 1 fmt_usage {cmd args} {c_hold synopsis "$cmd [join $args " "]"} 335c_pass 2 fmt_usage {cmd args} NOP 336 337c_pass 1 fmt_call {cmd args} {c_hold synopsis "$cmd [join $args " "]"} 338c_pass 2 fmt_call {cmd args} {fmt_lst_item "$cmd [join $args " "]"} 339 340 341c_pass 1 fmt_description {id} NOP 342c_pass 2 fmt_description {id} { 343 On 344 set syn [c_held synopsis] 345 set req [c_held require] 346 347 if {$syn != {} || $req != {}} { 348 Section SYNOPSIS 349 if {($req != {}) && ($syn != {})} { 350 Text $req\n\n$syn 351 } else { 352 if {$req != {}} {Text $req} 353 if {$syn != {}} {Text $syn} 354 } 355 CloseParagraph [Verbatim] 356 } 357 358 Section DESCRIPTION 359 return 360} 361 362# # ## ### ##### ######## 363## 364 365c_pass 1 fmt_list_begin {what {hint {}}} NOP 366c_pass 2 fmt_list_begin {what {hint {}}} { 367 CloseCurrent 368 369 #puts_stderr "AAA/fmt_list_begin/Setup $what" 370 371 ContextPush ;# push outer 372 NewList $what ;# base/controller of current/new/inner 373 Off 374 PSave 375 376 #puts_stderr "AAA/fmt_list_begin/Enter" 377 return 378} 379 380c_pass 1 fmt_list_end {} NOP 381c_pass 2 fmt_list_end {} { 382 CloseCurrent 383 384 #puts_stderr "AAA/fmt_list_end/Exit" 385 386 ContextPop ;# return to outer 387 PRestore 388 389 #puts_stderr "AAA/fmt_list_end/Done" 390 return 391} 392 393c_pass 1 fmt_lst_item {text} NOP 394c_pass 2 fmt_lst_item {text} { 395 if {[IsOff]} { On } else { CloseParagraph [Def] } 396 397 #puts_stderr "AAA/fmt_lst_item/(($text))" 398 399 Text $text 400 CloseParagraph [Term] 401 402 #puts_stderr "AAA/fmt_lst_item/Done" 403 return 404} 405 406c_pass 1 fmt_bullet {} NOP 407c_pass 2 fmt_bullet {} { 408 if {[IsOff]} { On } else { CloseCurrent } 409 410 #puts_stderr "AAA/fmt_bullet/START" 411 PReset 412 return 413} 414 415c_pass 1 fmt_enum {} NOP 416c_pass 2 fmt_enum {} { 417 if {[IsOff]} { On } else { CloseCurrent } 418 419 #puts_stderr "AAA/fmt_enum/START" 420 PReset 421 return 422} 423 424c_pass 1 fmt_cmd_def {command} NOP 425c_pass 2 fmt_cmd_def {command} {fmt_lst_item [fmt_cmd $command]} 426 427c_pass 1 fmt_arg_def {type name {mode {}}} NOP 428c_pass 2 fmt_arg_def {type name {mode {}}} { 429 set text "$type [fmt_arg $name]" 430 if {$mode != {}} {append text " ($mode)"} 431 fmt_lst_item $text 432 return 433} 434 435c_pass 1 fmt_opt_def {name {arg {}}} NOP 436c_pass 2 fmt_opt_def {name {arg {}}} { 437 set text [fmt_option $name] 438 if {$arg != {}} {append text " $arg"} 439 fmt_lst_item $text 440 return 441} 442 443c_pass 1 fmt_tkoption_def {name dbname dbclass} NOP 444c_pass 2 fmt_tkoption_def {name dbname dbclass} { 445 set text "" 446 append text "Command-Line Switch:\t[fmt_option $name]\n" 447 append text "Database Name:\t[Strong $dbname]\n" 448 append text "Database Class:\t[Strong $dbclass]\n" 449 fmt_lst_item $text 450} 451 452# # ## ### ##### ######## 453## 454 455c_pass 1 fmt_example_begin {} NOP 456c_pass 2 fmt_example_begin {} { 457 #puts_stderr "AAA/fmt_example_begin" 458 459 CloseCurrent 460 461 #puts_stderr "AAA/fmt_example_begin/Done" 462 return 463} 464 465c_pass 1 fmt_example_end {} NOP 466c_pass 2 fmt_example_end {} { 467 #puts_stderr "AAA/fmt_example_end" 468 #puts_stderr AAA/EIN=[string map [list \1 \\1 \t \\t { } \\s] <<[join [split [Text?] \n] >>\n<<]>>] 469 470 # Flush markup from preceding commands into the text buffer. 471 TextPlain "" 472 473 TextTrimLeadingSpace 474 475 # Look for and convert continuation lines protected from Tcl 476 # substitution into a regular continuation line. 477 set t [string map [list \\\\\n \\\n] [Text?]] 478 TextClear 479 Text $t 480 481 #puts_stderr AAA/EFT=[string map [list \1\\1 \t \\t { } \\s] <<[join [split [Text?] \n] >>\n<<]>>] 482 483 set penv [GetCurrent] 484 if {$penv != {}} { 485 # In a list we save the current list context, activate the 486 # proper paragraph context and create its example 487 # variant. After closing the paragraph using the example we 488 # restore and reactivate the list context. 489 ContextPush 490 ContextSet $penv 491 #if {[CloseParagraph [Example]]} PAdvance 492 CloseParagraph [Example] 493 ContextPop 494 } else { 495 # In a regular paragraph we simple close the example 496 #if {[CloseParagraph [Example]]} PAdvance 497 CloseParagraph [Example] 498 } 499 500 #puts_stderr "AAA/fmt_example_end/Done" 501 return 502} 503 504c_pass 1 fmt_example {code} NOP 505c_pass 2 fmt_example {code} { 506 fmt_example_begin 507 fmt_plain_text $code 508 fmt_example_end 509 return 510} 511 512# # ## ### ##### ######## 513## Visual markup of words and phrases. 514 515proc fmt_arg {text} { return $text } 516proc fmt_cmd {text} { return $text } 517proc fmt_emph {text} { Em $text } 518proc fmt_opt {text} { return "?$text?" } 519proc fmt_comment {text} { return } 520proc fmt_sectref {text {label {}}} { 521 if {![string length $label]} {set label $text} 522 return "-> $text" 523} 524 525proc fmt_syscmd {text} { Strong $text } 526proc fmt_method {text} { return $text } 527proc fmt_option {text} { return $text } 528proc fmt_widget {text} { Strong $text } 529proc fmt_fun {text} { Strong $text } 530proc fmt_type {text} { Strong $text } 531proc fmt_package {text} { Strong $text } 532proc fmt_class {text} { Strong $text } 533proc fmt_var {text} { Strong $text } 534proc fmt_file {text} { return "\"$text\"" } 535proc fmt_namespace {text} { Strong $text } 536proc fmt_uri {text {label {}}} { 537 if {$label == {}} { 538 # Without label we use the link directly as part of the text. 539 return "<URL:$text>" 540 } else { 541 return "[Em $label] <URL:$text>" 542 } 543} 544proc fmt_image {text {label {}}} { 545 # text = symbolic name of the image. 546 547 set img [dt_imgdata $text {txt}] 548 if {$img != {}} { 549 if {$label == {}} { 550 return "IMAGE: $text" 551 } else { 552 return "IMAGE: $text $label" 553 } 554 } 555 556 return $img 557} 558 559proc fmt_term {text} { Em $text } 560proc fmt_const {text} { Strong $text } 561proc fmt_mdash {} { return " --- " } 562proc fmt_ndash {} { return " -- " } 563 564# # ## ### ##### ######## 565return 566