From 2d0287dd5e12f57085d01badc9c0696924b61d94 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Mon, 21 Oct 2013 15:31:44 -0400
Subject: cmRST: Process literal blocks after paragraphs ending in '::'

Teach cmRST to recognize non-markup lines ending in '::' followed by a
blank line as starting a literal block.  Record the whole block as if it
were a literal block directive and print it just like a code block.
Extend the CMakeLib.testRST test to cover such cases.
---
 Source/cmRST.cxx              | 22 ++++++++++++++++++++++
 Source/cmRST.h                |  3 +++
 Tests/CMakeLib/testRST.expect | 17 +++++++++++++++++
 Tests/CMakeLib/testRST.rst    | 17 +++++++++++++++++
 4 files changed, 59 insertions(+)

diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index b64887d..d2eeb0c 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -22,6 +22,7 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot):
   DocRoot(docroot),
   IncludeDepth(0),
   OutputLinePending(false),
+  LastLineEndedInColonColon(false),
   Markup(MarkupNone),
   Directive(DirectiveNone),
   CMakeDirective("^.. (cmake:)?("
@@ -125,6 +126,7 @@ void cmRST::Reset()
     {
     case DirectiveNone: break;
     case DirectiveParsedLiteral: this->ProcessDirectiveParsedLiteral(); break;
+    case DirectiveLiteralBlock: this->ProcessDirectiveLiteralBlock(); break;
     case DirectiveCodeBlock: this->ProcessDirectiveCodeBlock(); break;
     case DirectiveReplace: this->ProcessDirectiveReplace(); break;
     case DirectiveTocTree: this->ProcessDirectiveTocTree(); break;
@@ -137,6 +139,9 @@ void cmRST::Reset()
 //----------------------------------------------------------------------------
 void cmRST::ProcessLine(std::string const& line)
 {
+  bool lastLineEndedInColonColon = this->LastLineEndedInColonColon;
+  this->LastLineEndedInColonColon = false;
+
   // A line starting in .. is an explicit markup start.
   if(line == ".." || (line.size() >= 3 && line[0] == '.' &&
                       line[1] == '.' && isspace(line[2])))
@@ -211,10 +216,21 @@ void cmRST::ProcessLine(std::string const& line)
       this->MarkupLines.push_back(line);
       }
     }
+  // A blank line following a paragraph ending in "::" starts a literal block.
+  else if(lastLineEndedInColonColon && line.empty())
+    {
+    // Record the literal lines to output after whole block.
+    this->Markup = MarkupNormal;
+    this->Directive = DirectiveLiteralBlock;
+    this->MarkupLines.push_back("");
+    this->OutputLine("", false);
+    }
   // Print non-markup lines.
   else
     {
     this->NormalLine(line);
+    this->LastLineEndedInColonColon = (line.size() >= 2
+      && line[line.size()-2] == ':' && line[line.size()-1] == ':');
     }
 }
 
@@ -344,6 +360,12 @@ void cmRST::ProcessDirectiveParsedLiteral()
 }
 
 //----------------------------------------------------------------------------
+void cmRST::ProcessDirectiveLiteralBlock()
+{
+  this->OutputMarkupLines(false);
+}
+
+//----------------------------------------------------------------------------
 void cmRST::ProcessDirectiveCodeBlock()
 {
   this->OutputMarkupLines(false);
diff --git a/Source/cmRST.h b/Source/cmRST.h
index a3b9c32..faae25f 100644
--- a/Source/cmRST.h
+++ b/Source/cmRST.h
@@ -38,6 +38,7 @@ private:
   {
     DirectiveNone,
     DirectiveParsedLiteral,
+    DirectiveLiteralBlock,
     DirectiveCodeBlock,
     DirectiveReplace,
     DirectiveTocTree
@@ -53,6 +54,7 @@ private:
   void OutputMarkupLines(bool inlineMarkup);
   bool ProcessInclude(std::string file, IncludeType type);
   void ProcessDirectiveParsedLiteral();
+  void ProcessDirectiveLiteralBlock();
   void ProcessDirectiveCodeBlock();
   void ProcessDirectiveReplace();
   void ProcessDirectiveTocTree();
@@ -62,6 +64,7 @@ private:
   std::string DocRoot;
   int IncludeDepth;
   bool OutputLinePending;
+  bool LastLineEndedInColonColon;
   MarkupType Markup;
   DirectiveType Directive;
   cmsys::RegularExpression CMakeDirective;
diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect
index 28981bf..9bd0ca4 100644
--- a/Tests/CMakeLib/testRST.expect
+++ b/Tests/CMakeLib/testRST.expect
@@ -53,6 +53,23 @@ More CMake Module Content
  endif()
  # |not replaced in literal|
 
+A literal block starts after a line consisting of two colons
+
+::
+
+  Literal block.
+ Common Indentation Removed
+ # |not replaced in literal|
+
+or after a paragraph ending in two colons::
+
+  Literal block.
+ Common Indentation Removed
+ # |not replaced in literal|
+
+but not after a line ending in two colons::
+in the middle of a paragraph.
+
 substituted text with multiple lines becomes one line
 
 End of first include.
diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst
index 46ec771..5cb6d91 100644
--- a/Tests/CMakeLib/testRST.rst
+++ b/Tests/CMakeLib/testRST.rst
@@ -66,6 +66,23 @@ Generator :generator:`Some Generator` with space.
    endif()
    # |not replaced in literal|
 
+A literal block starts after a line consisting of two colons
+
+::
+
+    Literal block.
+   Common Indentation Removed
+   # |not replaced in literal|
+
+or after a paragraph ending in two colons::
+
+    Literal block.
+   Common Indentation Removed
+   # |not replaced in literal|
+
+but not after a line ending in two colons::
+in the middle of a paragraph.
+
 .. |substitution| replace::
    |nested substitution|
    with multiple lines becomes one line
-- 
cgit v0.12