summaryrefslogtreecommitdiffstats
path: root/cli/context.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'cli/context.cxx')
-rw-r--r--cli/context.cxx334
1 files changed, 330 insertions, 4 deletions
diff --git a/cli/context.cxx b/cli/context.cxx
index 3715efa..4d858a6 100644
--- a/cli/context.cxx
+++ b/cli/context.cxx
@@ -94,6 +94,42 @@ namespace
"xor",
"xor_eq"
};
+
+ static string
+ latex_section (map<char, string> const& sm, char t)
+ {
+ string s;
+ typedef map<char, string> map;
+ map::const_iterator mi (sm.find (t));
+
+ if (mi == sm.end ())
+ {
+ switch (t)
+ {
+ case '0': s = "chapter*"; break;
+ case '1': s = "chapter"; break;
+ case 'H': s = "part"; break;
+ case 'h': s = "section"; break;
+ case '2': s = "subsection"; break;
+ }
+ }
+ else
+ s = mi->second;
+ return s;
+ }
+
+ static string&
+ replace_all (string& s, string const& search, string const& replace,
+ size_t pos = 0)
+ {
+ for (; (pos = s.find (search, pos)) != string::npos;
+ pos += replace.size ())
+ {
+ s.replace (pos, search.size (), replace);
+ }
+ return s;
+ }
+
}
context::
@@ -454,6 +490,11 @@ format_line (output_type ot, string& r, const char* l, size_t n)
r += "&#160;";
break;
}
+ case ot_latex:
+ {
+ r += '~';
+ break;
+ }
case ot_man:
{
r += "\\ ";
@@ -471,6 +512,7 @@ format_line (output_type ot, string& r, const char* l, size_t n)
switch (ot)
{
case ot_plain:
+ case ot_latex:
{
r += "--";
break;
@@ -506,6 +548,14 @@ format_line (output_type ot, string& r, const char* l, size_t n)
r += "<br/>";
break;
}
+ case ot_latex:
+ {
+ if (!r.empty () && r[r.size () - 1] != '\n')
+ r += '\n';
+
+ r += "\\\\";
+ break;
+ }
case ot_man:
{
if (!r.empty () && r[r.size () - 1] != '\n')
@@ -528,6 +578,7 @@ format_line (output_type ot, string& r, const char* l, size_t n)
{
case ot_plain: break;
case ot_html:
+ case ot_latex:
case ot_man:
{
if (i + 1 < n) // More text in this paragraph?
@@ -771,6 +822,11 @@ format_line (output_type ot, string& r, const char* l, size_t n)
{
switch (ot)
{
+ case ot_latex:
+ {
+ r += "\\textbackslash{}";
+ break;
+ }
case ot_man:
{
r += "\\e";
@@ -796,7 +852,19 @@ format_line (output_type ot, string& r, const char* l, size_t n)
}
case '}':
{
- r += '}';
+ switch (ot)
+ {
+ case ot_latex:
+ {
+ r += "\\}";
+ break;
+ }
+ default:
+ {
+ r += '}';
+ break;
+ }
+ }
break;
}
case '|':
@@ -889,6 +957,67 @@ format_line (output_type ot, string& r, const char* l, size_t n)
break;
}
+ case ot_latex:
+ {
+ if (s & note)
+ {
+ r += "\\footnote{";
+ }
+ else if (s & link)
+ {
+ r += '\\';
+
+ // It might be useful to include the man section into the regex
+ // somehow.
+ //
+ string t (link_section.empty ()
+ ? link_target
+ : link_target + options.latex_output_suffix ());
+
+ bool is_internal (true);
+
+ if ( link_target[0] == '#' )
+ {
+ r += "hyperref[";
+ }
+ else
+ {
+ is_internal = false;
+ r += "href{";
+ if ( link_target.compare(0, 7, "http://") != 0 &&
+ link_target.compare(0, 8, "https://") != 0)
+ {
+ r += "run:";
+ }
+ }
+
+ string pt (process_link_target (t));
+
+ if (pt.empty ())
+ {
+ cerr << "error: link '" << t << "' became empty" << endl;
+ throw generation_failed ();
+ }
+
+ if ( is_internal )
+ r += string (pt, 1, string::npos) + "]{";
+ else
+ r += pt + "}{";
+ }
+ else
+ {
+ if (s & code)
+ r += "\\texttt{";
+
+ if (s & itlc)
+ r += "\\emph{";
+
+ if (s & bold)
+ r += "\\textbf{";
+ }
+
+ break;
+ }
case ot_man:
{
if ((s & note) != 0)
@@ -931,6 +1060,43 @@ format_line (output_type ot, string& r, const char* l, size_t n)
r += '.';
break;
}
+ case '-':
+ {
+ if (ot == ot_latex && i + 1 < n && l[i + 1] == '-')
+ r += "-{}";
+ else
+ r += c;
+ break;
+ }
+ case '^':
+ {
+ if (ot == ot_latex)
+ r += "\\textasciicircum{}";
+ else
+ r += c;
+ break;
+ }
+ case '~':
+ {
+ if (ot == ot_latex)
+ r += "\\textasciitilde{}";
+ else
+ r += c;
+ break;
+ }
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ case '_':
+ case '{':
+ {
+ if (ot == ot_latex)
+ r += string (1, '\\') + c;
+ else
+ r += c;
+ break;
+ }
case '}':
{
if (!spans.empty ())
@@ -1047,6 +1213,46 @@ format_line (output_type ot, string& r, const char* l, size_t n)
break;
}
+ case ot_latex:
+ {
+ if ((s & note) != 0)
+ {
+ r += "}";
+ }
+ else if ((s & link) != 0)
+ {
+ if (link_empty)
+ {
+ if (link_section.empty ())
+ r += link_target;
+ else
+ {
+ r += "\\texttt{\\textbf{";
+ r += link_target + "(" + link_section + ")";
+ r += "}}";
+ }
+ }
+
+ r += "}";
+ }
+ else
+ {
+ if (s & bold)
+ r += "}";
+
+ if (s & itlc)
+ r += "}";
+
+ if (s & code)
+ {
+ size_t cb (r.rfind("\\texttt{", string::npos, 8));
+ replace_all(r, string (1, '\''), string ("\\textquotesingle{}", 18), cb);
+ r += "}";
+ }
+ }
+
+ break;
+ }
case ot_man:
{
assert ((s & note) == 0);
@@ -1107,6 +1313,11 @@ format_line (output_type ot, string& r, const char* l, size_t n)
break;
}
+ else if (ot == ot_latex)
+ {
+ r += "\\}";
+ break;
+ }
}
// Fall through.
default:
@@ -1226,6 +1437,40 @@ html_margin (string& v)
return os.str ();
}
+// The same idea except there are no margins. So we just strip "\\\\"
+//
+static void
+latex_margin (string& v)
+{
+ size_t top (0), bot (0);
+
+ const char* b (v.c_str ());
+ const char* e (v.c_str () + v.size ());
+
+ for (; e - b >= 2 && strncmp (b, "\\\\", 2) == 0; ++top)
+ {
+ b += 2;
+
+ if (b != e && *b == '\n') // Remove following newline, if any.
+ ++b;
+ }
+
+ for (; e - b >= 2 && strncmp (e - 2, "\\\\", 2) == 0; ++bot)
+ {
+ e -= 2;
+
+ if (e != b && *(e - 1) == '\n') // Remove preceding newline, if any.
+ --e;
+ }
+
+ if (top != 0 || bot != 0)
+ {
+ string t;
+ t.swap (v);
+ v.assign (b, e - b);
+ }
+}
+
// The same idea except there are no margins. So we just strip .br.
//
static void
@@ -1337,6 +1582,7 @@ format (semantics::scope& scope, string const& s, bool para)
{
case ot_plain: break;
case ot_html:
+ case ot_latex:
{
// Different "newline protocol" inside TOC.
//
@@ -1531,9 +1777,10 @@ format (semantics::scope& scope, string const& s, bool para)
k == block::pre ); break;
case block::note: good = (k == block::text ||
k == block::pre ||
- (ot == ot_html && (k == block::ul ||
- k == block::ol ||
- k == block::dl))); break;
+ ((ot == ot_html || ot == ot_latex)
+ && (k == block::ul ||
+ k == block::ol ||
+ k == block::dl))); break;
case block::text: good = (k != block::li); break;
case block::pre: assert (false);
}
@@ -1812,6 +2059,26 @@ format (semantics::scope& scope, string const& s, bool para)
break;
}
+ case ot_latex:
+ {
+ // Separate paragraphs with a blank line.
+ //
+ if (!first)
+ v += "\n\n";
+
+ if (k == block::pre)
+ {
+ v += "\\begin{verbatim}\n";
+ v.append (l, n);
+ v += "\n\\end{verbatim}";
+ }
+ else
+ {
+ format_line (ot, v, l, n);
+ }
+
+ break;
+ }
case ot_man:
{
if (b.para)
@@ -2019,6 +2286,7 @@ format (semantics::scope& scope, string const& s, bool para)
break;
}
+ case ot_latex: break;
case ot_man: break;
}
}
@@ -2213,6 +2481,59 @@ format (semantics::scope& scope, string const& s, bool para)
break;
}
+ case ot_latex:
+ {
+ if (!v.empty ())
+ v += "\n\n";
+
+ switch (pb.kind)
+ {
+ case block::h:
+ {
+ char t (ph[0]);
+
+ string label;
+ string s (latex_section( options.latex_section_map (), t));
+
+ if (!pi.empty ())
+ label = "\\label{" + pi + '}';
+
+ v += '\\' + s + '{' + label + pv + '}';
+
+ break;
+ }
+ case block::ul: v += "\\begin{itemize}\n" + pv + "\n\\end{itemize}"; break;
+ case block::ol: v += "\\begin{enumerate}\n" + pv + "\n\\end{enumerate}"; break;
+ case block::dl: v += "\\begin{description}\n" + pv + "\n\\end{description}"; break;
+ case block::li:
+ {
+ latex_margin (pv); // Strip leading/trailing newline
+
+ if (b.kind == block::dl)
+ {
+ latex_margin (ph); // Strip leading/trailing newline
+
+ v += "\\item[{" + ph + "}] " + pv;
+ }
+ else
+ v += "\\item " + pv;
+
+ break;
+ }
+ case block::note:
+ {
+ v += "\\begin{tcolorbox}\n";
+ v += pv;
+ v += "\n\\end{tcolorbox}\n";
+
+ break;
+ }
+ case block::text:
+ case block::pre: assert (false);
+ }
+
+ break;
+ }
case ot_man:
{
// Seeing that we always write a macro, one newline is enough.
@@ -2305,6 +2626,10 @@ start_toc ()
tocs.push_back (toc_entry ('\0'));
return " <table class=\"toc\">";
}
+ case ot_latex:
+ {
+ return "\\tableofcontents{}\n";
+ }
case ot_man: break;
}
@@ -2346,6 +2671,7 @@ end_toc ()
v += " </table>";
return v;
}
+ case ot_latex: break;
case ot_man: break;
}