From c37f07f5134104dae6d5bbc18a3d133b023ff792 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 31 Oct 2015 12:01:41 +0200 Subject: Add support for \h paragraph --- cli/context.cxx | 101 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 17 deletions(-) (limited to 'cli') diff --git a/cli/context.cxx b/cli/context.cxx index 8de23ab..c462a5e 100644 --- a/cli/context.cxx +++ b/cli/context.cxx @@ -4,6 +4,7 @@ // license : MIT; see accompanying LICENSE file #include +#include // strncmp() #include #include "context.hxx" @@ -489,6 +490,11 @@ format_line (output_type ot, string& r, const char* s, size_t n) r += '}'; break; } + case '|': + { + r += '|'; + break; + } default: { cerr << "error: unknown escape sequence '\\" << c << "' in " @@ -606,6 +612,13 @@ format_line (output_type ot, string& r, const char* s, size_t n) } } + if (escape) + { + cerr << "error: unterminated escape sequence in documentation " + << "paragraph '" << string (s, 0, n) << "'" << endl; + throw generation_failed (); + } + if (!blocks.empty ()) { unsigned char b (blocks.top ()); @@ -621,6 +634,29 @@ format_line (output_type ot, string& r, const char* s, size_t n) } } +// Return true if this line ends the paragraph, that is, ends with an +// unescaped '|'. +// +static bool +end_para (const char* l, size_t n) +{ + if (l[n - 1] != '|') + return false; + + if (n == 1 || l[n - 2] != '\\') + return true; + + // To determine whether this is an escape sequence we have to find + // first non-backslash character and then figure out who escapes who. + // + size_t i (n - 2); + for (; i != 0 && l[i - 1] == '\\'; --i) ; + + // If we have an even number of backslashes, the it is unescaped. + // + return (n - i - 1) % 2 == 0; +} + string context:: format (output_type ot, string const& s, bool para) { @@ -632,33 +668,64 @@ format (output_type ot, string const& s, bool para) { bool first (b == 0), last (e == string::npos); - if (first) // Before first line. - { - if (ot == ot_html && para) - r += "

"; - } - else // Between lines. + const char* l (s.c_str () + b); + size_t n ((last ? s.size () : e) - b); + + // Some paragraph blocks are only valid if we are required to start + // a new paragraph (para is true). + // + if (n >= 3 && strncmp (l, "\\h|", 3) == 0) { - if (ot == ot_html && para) - r += "

"; + if (!para) + { + cerr << "error: invalid context '" << s << "' for paragraph '" + << string (l, 0, n) << "'" << endl; + throw generation_failed (); + } - r += '\n'; + if (!end_para (l, n)) + { + cerr << "error: '|' expected at the end of paragraph '" + << string (l, 0, n) << "'" << endl; + throw generation_failed (); + } - if (ot == ot_html) + if (n == 4) { - r += "

"; - para = true; + cerr << "error: empty paragraph '" << string (l, 0, n) << "'" << endl; + throw generation_failed (); } - } - format_line (ot, r, s.c_str () + b, (last ? s.size () : e) - b); + if (ot == ot_html) + r += "

"; + + format_line (ot, r, l + 3, n - 4); - if (last) // After last line. + if (ot == ot_html) + r += "

"; + } + else // Normal text. { - if (ot == ot_html && para) - r += "

"; + if (para || !first) // Start a paragraph? + { + if (ot == ot_html) + r += "

"; + } + + format_line (ot, r, l, n); + + if (para || !first) // End a paragraph? + { + if (ot == ot_html) + r += "

"; + } } + // Separate paragraphs with newline. + // + if (!last) + r += '\n'; + // Get next line. // b = e; -- cgit v1.1