From a9fd81899df8a412f20784b3575b9707c530d1d1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 26 Nov 2015 08:17:28 +0200 Subject: Indent multi-line lists in plain text output --- cli/context.cxx | 21 ++++++++++++++++++--- cli/source.cxx | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/cli/context.cxx b/cli/context.cxx index 5731222..25a88a0 100644 --- a/cli/context.cxx +++ b/cli/context.cxx @@ -1375,14 +1375,29 @@ format (output_type ot, string const& s, bool para) case block::li: { v += sn; + size_t ind (0); switch (b.kind) { - case block::ul: v += "* " + pv; break; - case block::ol: v += ph + ". " + pv; break; - case block::dl: v += ph + "\n " + pv; break; + case block::ul: v += "* "; ind = 2; break; + case block::ol: v += ph + ". "; ind = ph.size () + 2; break; + case block::dl: v += ph + "\n "; ind = 8; break; default: break; } + + // Add value with indentation for subsequent paragraphs. + // + char c, p ('\0'); // Current and previous characters. + for (size_t i (0); i != pv.size (); p = c, ++i) + { + c = pv[i]; + + if (p == '\n' && c != '\n') // Don't indent blanks. + v += string (ind, ' '); + + v += c; + } + break; } case block::text: diff --git a/cli/source.cxx b/cli/source.cxx index 7bf5e8d..58637c8 100644 --- a/cli/source.cxx +++ b/cli/source.cxx @@ -246,27 +246,39 @@ namespace { assert (!d.empty ()); - string ind (indent, ' '); os << string (indent - first, ' '); + // Count the number of leading spaces at the beginning of each line. + // Then use it as an extra indentation if we are breaking this line. + // This makes multi-line definition lists look decent. Note that this + // doesn't work for ordered/unordered lists because they start on the + // same line as number/bullet. However, there is hack to make it work: + // break the first line at the 80 characters boundary explicitly with + // \n. + // + size_t wc (0), wi (0); // Count and count-based indentation. + bool cws (true); // Count flag. + size_t b (0), e (0), i (0); for (size_t n (d.size ()); i < n; ++i) { - if (d[i] == ' ' || d[i] == '\n') + char c (d[i]); + + if (c == ' ' || c == '\n') e = i; - if (d[i] == '\n' || text_size (d, b, i - b) == 79 - indent) + if (c == '\n' || text_size (d, b, i - b) == 79 - indent - wi) { if (b != 0) // Not a first line. os << endl - << " << \"" << ind; + << " << \"" << string (indent + wi, ' '); string s (d, b, (e != b ? e : i) - b); os << escape_str (s) << "\" << ::std::endl"; // Handle consecutive newlines (e.g., pre, paragraph separator). // - if (d[i] == '\n') + if (c == '\n') { for (; i + 1 < n && d[i + 1] == '\n'; e = ++i) os << endl @@ -274,6 +286,22 @@ namespace } b = e = (e != b ? e : i) + 1; + wi = wc; // Start indent beginning with the next break. + } + + if (c == '\n') + { + // Reset and start counting. + // + wc = wi = 0; + cws = true; + } + else if (cws) + { + if (c == ' ') + ++wc; + else + cws = false; } } @@ -283,7 +311,7 @@ namespace { if (b != 0) os << endl - << " << \"" << ind; + << " << \"" << string (indent + wi, ' '); string s (d, b, i - b); os << escape_str (s) << "\" << ::std::endl"; -- cgit v1.1