| 1 | # -*- tcl -*- |
|---|
| 2 | # |
|---|
| 3 | # -- nroff commands |
|---|
| 4 | # |
|---|
| 5 | # Copyright (c) 2003-2005 Andreas Kupries <andreas_kupries@sourceforge.net> |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | ################################################################ |
|---|
| 9 | # nroff specific commands |
|---|
| 10 | # |
|---|
| 11 | # All dot-commands (f.e. .PP) are returned with a leading \n, |
|---|
| 12 | # enforcing that they are on a new line. Any empty line created |
|---|
| 13 | # because of this is filtered out in the post-processing step. |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | proc nr_lp {} {return \n.LP} |
|---|
| 17 | proc nr_ta {{text {}}} {return ".ta$text"} |
|---|
| 18 | proc nr_bld {} {return \1\\fB} |
|---|
| 19 | proc nr_ul {} {return \1\\fI} |
|---|
| 20 | proc nr_rst {} {return \1\\fR} |
|---|
| 21 | proc nr_p {} {return \n.PP\n} |
|---|
| 22 | proc nr_comment {text} {return "\1'\1\\\" [join [split $text \n] "\n\1'\1\\\" "]"} ; # " |
|---|
| 23 | proc nr_enum {num} {nr_item " \[$num\]"} |
|---|
| 24 | proc nr_item {{text {}}} {return "\n.IP$text"} |
|---|
| 25 | proc nr_vspace {} {return \n.sp} |
|---|
| 26 | proc nr_blt {text} {return "\n.TP\n$text"} |
|---|
| 27 | proc nr_bltn {n text} {return "\n.TP $n\n$text"} |
|---|
| 28 | proc nr_in {} {return \n.RS} |
|---|
| 29 | proc nr_out {} {return \n.RE} |
|---|
| 30 | proc nr_nofill {} {return \n.nf} |
|---|
| 31 | proc nr_fill {} {return \n.fi} |
|---|
| 32 | proc nr_title {text} {return "\n.TH $text"} |
|---|
| 33 | proc nr_include {file} {return "\n.so $file"} |
|---|
| 34 | proc nr_bolds {} {return \n.BS} |
|---|
| 35 | proc nr_bolde {} {return \n.BE} |
|---|
| 36 | |
|---|
| 37 | proc nr_section {name} { |
|---|
| 38 | if {![regexp {[ ]} $name]} { |
|---|
| 39 | return "\n.SH $name" |
|---|
| 40 | } |
|---|
| 41 | return "\n.SH \"$name\"" |
|---|
| 42 | } |
|---|
| 43 | proc nr_subsection {name} { |
|---|
| 44 | if {![regexp {[ ]} $name]} { |
|---|
| 45 | return "\n.SS $name" |
|---|
| 46 | } |
|---|
| 47 | return "\n.SS \"$name\"" |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | |
|---|
| 51 | ################################################################ |
|---|
| 52 | |
|---|
| 53 | # Handling of nroff special characters in content: |
|---|
| 54 | # |
|---|
| 55 | # Plain text is initially passed through unescaped; |
|---|
| 56 | # internally-generated markup is protected by preceding it with \1. |
|---|
| 57 | # The final PostProcess step strips the escape character from |
|---|
| 58 | # real markup and replaces unadorned special characters in content |
|---|
| 59 | # with proper escapes. |
|---|
| 60 | # |
|---|
| 61 | |
|---|
| 62 | global markupMap |
|---|
| 63 | set markupMap [list "\\" "\1\\"] |
|---|
| 64 | global finalMap |
|---|
| 65 | set finalMap [list \ |
|---|
| 66 | "\1\\" "\\" \ |
|---|
| 67 | "\1'" "'" \ |
|---|
| 68 | "\\" "\\\\"] |
|---|
| 69 | global textMap |
|---|
| 70 | set textMap [list "\\" "\\\\"] |
|---|
| 71 | |
|---|
| 72 | |
|---|
| 73 | proc nroffEscape {text} { |
|---|
| 74 | global textMap |
|---|
| 75 | return [string map $textMap $text] |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | # markup text -- |
|---|
| 79 | # Protect markup characters in $text. |
|---|
| 80 | # These will be stripped out in PostProcess. |
|---|
| 81 | # |
|---|
| 82 | proc nroffMarkup {text} { |
|---|
| 83 | global markupMap |
|---|
| 84 | return [string map $markupMap $text] |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | proc nroff_postprocess {nroff} { |
|---|
| 88 | global finalMap |
|---|
| 89 | |
|---|
| 90 | # Postprocessing final nroff text. |
|---|
| 91 | # - Strip empty lines out of the text |
|---|
| 92 | # - Remove leading and trailing whitespace from lines. |
|---|
| 93 | # - Exceptions to the above: Keep empty lines and leading |
|---|
| 94 | # whitespace when in verbatim sections (no-fill-mode) |
|---|
| 95 | |
|---|
| 96 | set nfMode [list .nf .CS] ; # commands which start no-fill mode |
|---|
| 97 | set fiMode [list .fi .CE] ; # commands which terminate no-fill mode |
|---|
| 98 | set lines [list] ; # Result buffer |
|---|
| 99 | set verbatim 0 ; # Automaton mode/state |
|---|
| 100 | |
|---|
| 101 | foreach line [split $nroff "\n"] { |
|---|
| 102 | if {!$verbatim} { |
|---|
| 103 | # Normal lines, not in no-fill mode. |
|---|
| 104 | |
|---|
| 105 | if {[lsearch -exact $nfMode [split $line]] >= 0} { |
|---|
| 106 | # no-fill mode starts after this line. |
|---|
| 107 | set verbatim 1 |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | # Ensure that empty lines are not added. |
|---|
| 111 | # This also removes leading and trailing whitespace. |
|---|
| 112 | |
|---|
| 113 | if {![string length $line]} {continue} |
|---|
| 114 | set line [string trim $line] |
|---|
| 115 | if {![string length $line]} {continue} |
|---|
| 116 | |
|---|
| 117 | if {[regexp {^\x1\\f[BI]\.} $line]} { |
|---|
| 118 | # We found confusing formatting at the beginning of |
|---|
| 119 | # the current line. We lift this line up and attach it |
|---|
| 120 | # at the end of the last line to remove this |
|---|
| 121 | # irregularity. Note that the regexp has to look for |
|---|
| 122 | # the special 0x01 character as well to be sure that |
|---|
| 123 | # the sequence in question truly is formatting. |
|---|
| 124 | |
|---|
| 125 | set last [lindex $lines end] |
|---|
| 126 | set lines [lreplace $lines end end] |
|---|
| 127 | set line "$last $line" |
|---|
| 128 | } elseif {[string match '* $line]} { |
|---|
| 129 | # Apostrophes at the beginning of a line have to |
|---|
| 130 | # quoted to prevent misinterpretation as comments. |
|---|
| 131 | # The apostrophes for true comments are quoted with \1 |
|---|
| 132 | # already and will therefore not detected by the code |
|---|
| 133 | # here. |
|---|
| 134 | |
|---|
| 135 | set line \1\\$line |
|---|
| 136 | } |
|---|
| 137 | } else { |
|---|
| 138 | # No-fill mode. We remove trailing whitespace, but keep |
|---|
| 139 | # leading whitespace and empty lines. |
|---|
| 140 | |
|---|
| 141 | if {[lsearch -exact $fiMode [split $line]] >= 0} { |
|---|
| 142 | # Normal mode resumes after this line. |
|---|
| 143 | set verbatim 0 |
|---|
| 144 | } |
|---|
| 145 | set line [string trimright $line] |
|---|
| 146 | } |
|---|
| 147 | lappend lines $line |
|---|
| 148 | } |
|---|
| 149 | # Return the modified result buffer |
|---|
| 150 | return [string map $finalMap [join $lines "\n"]] |
|---|
| 151 | } |
|---|
| 152 | |
|---|