summaryrefslogtreecommitdiffstats
path: root/tcllib/modules/doctools/mpformats/_nroff.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'tcllib/modules/doctools/mpformats/_nroff.tcl')
-rw-r--r--tcllib/modules/doctools/mpformats/_nroff.tcl183
1 files changed, 183 insertions, 0 deletions
diff --git a/tcllib/modules/doctools/mpformats/_nroff.tcl b/tcllib/modules/doctools/mpformats/_nroff.tcl
new file mode 100644
index 0000000..c630875
--- /dev/null
+++ b/tcllib/modules/doctools/mpformats/_nroff.tcl
@@ -0,0 +1,183 @@
+# -*- tcl -*-
+#
+# -- nroff commands
+#
+# Copyright (c) 2003-2005 Andreas Kupries <andreas_kupries@sourceforge.net>
+
+
+################################################################
+# nroff specific commands
+#
+# All dot-commands (f.e. .PP) are returned with a leading \n\1,
+# enforcing that they are on a new line and will be protected as markup.
+# Any empty line created because of this is filtered out in the
+# post-processing step.
+
+
+proc nr_lp {} {return \n\1.LP}
+proc nr_ta {{text {}}} {return "\1.ta$text"}
+proc nr_bld {} {return \1\\fB}
+proc nr_bldt {t} {return "\n\1.B $t\n"}
+proc nr_ul {} {return \1\\fI}
+proc nr_rst {} {return \1\\fR}
+proc nr_p {} {return \n\1.PP\n}
+proc nr_comment {text} {return "\1'\1\\\" [join [split $text \n] "\n\1'\1\\\" "]"} ; # "
+proc nr_enum {num} {nr_item " \[$num\]"}
+proc nr_item {{text {}}} {return "\n\1.IP$text"}
+proc nr_vspace {} {return \n\1.sp\n}
+proc nr_blt {text} {return "\n\1.TP\n$text"}
+proc nr_bltn {n text} {return "\n\1.TP $n\n$text"}
+proc nr_in {} {return \n\1.RS}
+proc nr_out {} {return \n\1.RE}
+proc nr_nofill {} {return \n\1.nf}
+proc nr_fill {} {return \n\1.fi}
+proc nr_title {text} {return "\n\1.TH $text"}
+proc nr_include {file} {return "\n\1.so $file"}
+proc nr_bolds {} {return \n\1.BS}
+proc nr_bolde {} {return \n\1.BE}
+proc nr_read {fn} {return [nroffMarkup [dt_read $fn]]}
+proc nr_cs {} {return \n\1.CS\n}
+proc nr_ce {} {return \n\1.CE\n}
+
+proc nr_section {name} {
+ if {![regexp {[ ]} $name]} {
+ return "\n\1.SH [string toupper $name]"
+ }
+ return "\n\1.SH \"[string toupper $name]\""
+}
+proc nr_subsection {name} {
+ if {![regexp {[ ]} $name]} {
+ return "\n\1.SS [string toupper $name]"
+ }
+ return "\n\1.SS \"[string toupper $name]\""
+}
+
+
+################################################################
+
+# Handling of nroff special characters in content:
+#
+# Plain text is initially passed through unescaped;
+# internally-generated markup is protected by preceding it with \1.
+# The final PostProcess step strips the escape character from
+# real markup and replaces unadorned special characters in content
+# with proper escapes.
+#
+
+global markupMap
+set markupMap [list \
+ "\\" "\1\\" \
+ "'" "\1'" \
+ "." "\1." \
+ "\\\\" "\\"]
+global finalMap
+set finalMap [list \
+ "\1\\" "\\" \
+ "\1'" "'" \
+ "\1." "." \
+ "." "\\&." \
+ "\\" "\\\\"]
+global textMap
+set textMap [list "\\" "\\\\"]
+
+
+proc nroffEscape {text} {
+ global textMap
+ return [string map $textMap $text]
+}
+
+# markup text --
+# Protect markup characters in $text.
+# These will be stripped out in PostProcess.
+#
+proc nroffMarkup {text} {
+ global markupMap
+ return [string map $markupMap $text]
+}
+
+proc nroff_postprocess {nroff} {
+ global finalMap
+
+ # Postprocessing final nroff text.
+ # - Strip empty lines out of the text
+ # - Remove leading and trailing whitespace from lines.
+ # - Exceptions to the above: Keep empty lines and leading
+ # whitespace when in verbatim sections (no-fill-mode)
+
+ set nfMode [list \1.nf \1.CS] ; # commands which start no-fill mode
+ set fiMode [list \1.fi \1.CE] ; # commands which terminate no-fill mode
+ set lines [list] ; # Result buffer
+ set verbatim 0 ; # Automaton mode/state
+
+ foreach line [split $nroff "\n"] {
+ #puts_stderr |[expr {$verbatim ? "VERB" : " "}]|$line|
+
+ if {!$verbatim} {
+ # Normal lines, not in no-fill mode.
+
+ if {[lsearch -exact $nfMode [split $line]] >= 0} {
+ # no-fill mode starts after this line.
+ set verbatim 1
+ }
+
+ # Ensure that empty lines are not added.
+ # This also removes leading and trailing whitespace.
+
+ if {![string length $line]} {continue}
+ set line [string trim $line]
+ if {![string length $line]} {continue}
+
+ if {[regexp {^\x1\\f[BI]\.} $line]} {
+ # We found confusing formatting at the beginning of
+ # the current line. We lift this line up and attach it
+ # at the end of the last line to remove this
+ # irregularity. Note that the regexp has to look for
+ # the special 0x01 character as well to be sure that
+ # the sequence in question truly is formatting.
+ # [bug-3601370] Only lift & attach if last line is not
+ # a directive
+
+ set last [lindex $lines end]
+ if { ! [string match "\1.*" $last] } {
+ #puts_stderr \tLIFT
+ set lines [lreplace $lines end end]
+ set line "$last $line"
+ }
+ } elseif {[string match {[']*} $line]} {
+ # Apostrophes at the beginning of a line have to be
+ # quoted to prevent misinterpretation as comments.
+ # The true comments and are quoted with \1 already and
+ # will therefore not detected by the code here.
+ # puts_stderr \tQUOTE
+ set line \1\\$line
+ } ; # We are not handling dots at the beginning of a line here.
+ # # We are handling them in the finalMap which will quote _all_
+ # # dots in a text with a zero-width escape (\&).
+ } else {
+ # No-fill mode. We remove trailing whitespace, but keep
+ # leading whitespace and empty lines.
+
+ if {[lsearch -exact $fiMode [split $line]] >= 0} {
+ # Normal mode resumes after this line.
+ set verbatim 0
+ }
+ set line [string trimright $line]
+ }
+ lappend lines $line
+ }
+
+ set lines [join $lines "\n"]
+
+ # Now remove all superfluous .IP commands (empty paragraphs). The
+ # first identity mapping is present to avoid smashing a man macro
+ # definition.
+
+ lappend map \n\1.IP\n\1.\1.\n \n\1.IP\n\1.\1.\n
+ lappend map \n\1.IP\n\1. \n\1.
+
+ set lines [string map $map $lines]
+
+ # Return the modified result buffer
+ return [string map $finalMap $lines]
+}
+