From f85405f5515ed5cc20ffe97c485d7dfef6ffc288 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Thu, 12 Sep 2013 10:05:46 -0400
Subject: Add reStructuredText (RST) documentation formatter

Temporarily add a RST formatter to convert builtin documentation to .rst
source files.  This will be removed shortly after we use it to convert
documentation.

Teach the RST formatter to:

* Output preformatted blocks as reStructuredText "::" literal blocks.

* Output option lists as bullet lists with option names enclosed in
  reStructuredText ``literal`` quoting.

* Output individual documentation objects (commands, variables, etc.)
  in separate .rst files organized in directories by type.

Replace references to cmVersion::GetCMakeVersion() in builtin
documentation with the literal placeholder "|release|" that will be
defined as a substitution later.
---
 Source/CMakeLists.txt                  |   1 +
 Source/cmDocumentation.cxx             |   8 +++
 Source/cmDocumentation.h               |   2 +
 Source/cmDocumentationFormatter.cxx    |  28 ++++++++-
 Source/cmDocumentationFormatter.h      |   2 +-
 Source/cmDocumentationFormatterRST.cxx | 107 +++++++++++++++++++++++++++++++++
 Source/cmDocumentationFormatterRST.h   |  34 +++++++++++
 Source/cmPolicies.cxx                  |   2 +-
 8 files changed, 180 insertions(+), 4 deletions(-)
 create mode 100644 Source/cmDocumentationFormatterRST.cxx
 create mode 100644 Source/cmDocumentationFormatterRST.h

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 9b81e8b..5178c0a 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -162,6 +162,7 @@ set(SRCS
   cmDocumentationFormatterHTML.cxx
   cmDocumentationFormatterDocbook.cxx
   cmDocumentationFormatterMan.cxx
+  cmDocumentationFormatterRST.cxx
   cmDocumentationFormatterText.cxx
   cmDocumentationFormatterUsage.cxx
   cmDocumentationSection.cxx
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index b0643b0..83be32d 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -654,6 +654,11 @@ cmDocumentation::Form cmDocumentation::GetFormFromFilename(
     return cmDocumentation::ManForm;
     }
 
+  if (ext == ".RST")
+    {
+    return cmDocumentation::RSTForm;
+    }
+
   return cmDocumentation::TextForm;
 }
 
@@ -1580,6 +1585,9 @@ void cmDocumentation::SetForm(Form f, int manSection)
       this->ManFormatter.SetManSection(manSection);
       this->CurrentFormatter = &this->ManFormatter;
       break;
+    case RSTForm:
+      this->CurrentFormatter = &this->RSTFormatter;
+      break;
     case TextForm:
       this->CurrentFormatter = &this->TextFormatter;
       break;
diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h
index 68ddbb8..151c242 100644
--- a/Source/cmDocumentation.h
+++ b/Source/cmDocumentation.h
@@ -18,6 +18,7 @@
 #include "cmDocumentationFormatterHTML.h"
 #include "cmDocumentationFormatterDocbook.h"
 #include "cmDocumentationFormatterMan.h"
+#include "cmDocumentationFormatterRST.h"
 #include "cmDocumentationFormatterText.h"
 #include "cmDocumentationFormatterUsage.h"
 #include "cmDocumentationSection.h"
@@ -222,6 +223,7 @@ private:
   cmDocumentationFormatterHTML HTMLFormatter;
   cmDocumentationFormatterDocbook DocbookFormatter;
   cmDocumentationFormatterMan ManFormatter;
+  cmDocumentationFormatterRST RSTFormatter;
   cmDocumentationFormatterText TextFormatter;
   cmDocumentationFormatterUsage UsageFormatter;
 
diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx
index 9f01949..a547176 100644
--- a/Source/cmDocumentationFormatter.cxx
+++ b/Source/cmDocumentationFormatter.cxx
@@ -81,7 +81,7 @@ cmDocumentationFormatter::ComputeSectionLinkPrefix(std::string const& name)
     {
     if(name.find("Global") != name.npos)
       {
-      return "prop_global";
+      return "prop_gbl";
       }
     else if(name.find("Direct") != name.npos)
       {
@@ -99,10 +99,34 @@ cmDocumentationFormatter::ComputeSectionLinkPrefix(std::string const& name)
       {
       return "prop_sf";
       }
+    else if(name.find("Cache") != name.npos)
+      {
+      return "prop_cache";
+      }
     return "property";
     }
   else if(name.find("Variable") != name.npos)
     {
+    if(name.find("Information") != name.npos)
+      {
+      return "var_info";
+      }
+    else if(name.find("Behavior") != name.npos)
+      {
+      return "var_cmake";
+      }
+    else if(name.find("Describe") != name.npos)
+      {
+      return "var_sys";
+      }
+    else if(name.find("Control") != name.npos)
+      {
+      return "var_build";
+      }
+    else if(name.find("Languages") != name.npos)
+      {
+      return "var_lang";
+      }
     return "variable";
     }
   else if(name.find("Polic") != name.npos)
@@ -128,7 +152,7 @@ cmDocumentationFormatter::ComputeSectionLinkPrefix(std::string const& name)
     }
   else if(name.find("Generators") != name.npos)
     {
-    return "gen";
+    return "generator";
     }
   else if(name.find("Options") != name.npos)
     {
diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h
index d8ce613..9278297 100644
--- a/Source/cmDocumentationFormatter.h
+++ b/Source/cmDocumentationFormatter.h
@@ -31,7 +31,7 @@ public:
     CompatCommands, Copyright, Version, Policies, SinglePolicy };
 
   /** Forms of documentation output.  */
-  enum Form { TextForm, HTMLForm, ManForm, UsageForm, DocbookForm };
+  enum Form { TextForm, HTMLForm, RSTForm, ManForm, UsageForm, DocbookForm };
 };
 
 class cmDocumentationSection;
diff --git a/Source/cmDocumentationFormatterRST.cxx b/Source/cmDocumentationFormatterRST.cxx
new file mode 100644
index 0000000..86d1fd0
--- /dev/null
+++ b/Source/cmDocumentationFormatterRST.cxx
@@ -0,0 +1,107 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmDocumentationFormatterRST.h"
+#include "cmDocumentationSection.h"
+#include "cmVersion.h"
+
+#include "cmSystemTools.h"
+
+cmDocumentationFormatterRST::cmDocumentationFormatterRST()
+:cmDocumentationFormatterText()
+{
+}
+
+static std::string rstFileName(std::string fn)
+{
+  cmSystemTools::ReplaceString(fn, "<", "");
+  cmSystemTools::ReplaceString(fn, ">", "");
+  return fn;
+}
+
+void cmDocumentationFormatterRST
+::PrintSection(std::ostream& os,
+               const cmDocumentationSection &section,
+               const char* name)
+{
+  std::string prefix = this->ComputeSectionLinkPrefix(name);
+  std::vector<cmDocumentationEntry> const& entries = section.GetEntries();
+  this->TextWidth = 70;
+
+  for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
+      op != entries.end();)
+    {
+    if(op->Name.size())
+      {
+      for(;op != entries.end() && op->Name.size(); ++op)
+        {
+        if(prefix == "opt" || prefix == "see")
+          {
+          os << "\n";
+          os << "* ``" << op->Name << "``: " << op->Brief << "\n";
+          this->TextIndent = "  ";
+          if(op->Full.size())
+            {
+            os << "\n";
+            this->PrintFormatted(os, op->Full.c_str());
+            }
+          this->TextIndent = "";
+          }
+        else
+          {
+          cmSystemTools::MakeDirectory(prefix.c_str());
+          std::string fname = prefix + "/" + rstFileName(op->Name) + ".rst";
+          if(cmSystemTools::FileExists(fname.c_str()))
+            {
+            cmSystemTools::Error("Duplicate file name: ", fname.c_str());
+            continue;
+            }
+          std::ofstream of(fname.c_str());
+          of << op->Name << "\n";
+          for(size_t i = 0; i < op->Name.size(); ++i)
+            {
+            of << "-";
+            }
+          of << "\n\n" << op->Brief << "\n";
+          if(op->Full.size())
+            {
+            of << "\n";
+            this->PrintFormatted(of, op->Full.c_str());
+            }
+          }
+        }
+      }
+    else
+      {
+      this->PrintFormatted(os, op->Brief.c_str());
+      os << "\n";
+      ++op;
+      }
+    }
+}
+
+void cmDocumentationFormatterRST::PrintPreformatted(std::ostream& os,
+                                                    const char* text)
+{
+  os << this->TextIndent << "::\n\n";
+  bool newline = true;
+  for(const char* c = text; *c; ++c)
+    {
+    if (newline)
+      {
+      os << this->TextIndent;
+      newline = false;
+      }
+    os << *c;
+    newline = (*c == '\n');
+    }
+  os << "\n";
+}
diff --git a/Source/cmDocumentationFormatterRST.h b/Source/cmDocumentationFormatterRST.h
new file mode 100644
index 0000000..c0d2e91
--- /dev/null
+++ b/Source/cmDocumentationFormatterRST.h
@@ -0,0 +1,34 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef _cmDocumentationFormatterRST_h
+#define _cmDocumentationFormatterRST_h
+
+#include "cmStandardIncludes.h"
+
+#include "cmDocumentationFormatterText.h"
+
+/** Class to print the documentation as reStructuredText.  */
+class cmDocumentationFormatterRST : public cmDocumentationFormatterText
+{
+public:
+  cmDocumentationFormatterRST();
+
+  virtual cmDocumentationEnums::Form GetForm() const
+                                      { return cmDocumentationEnums::RSTForm;}
+
+  virtual void PrintSection(std::ostream& os,
+                    const cmDocumentationSection& section,
+                    const char* name);
+  virtual void PrintPreformatted(std::ostream& os, const char* text);
+};
+
+#endif
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index d07645c..0731fc2 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -949,7 +949,7 @@ void cmPolicies::GetDocumentation(std::vector<cmDocumentationEntry>& v)
     if(i->first != cmPolicies::CMP0000)
       {
       full << "  "
-           << "CMake version " << cmVersion::GetCMakeVersion() << " ";
+           << "CMake version |release| ";
       // add in some more text here based on status
       switch (i->second->Status)
         {
-- 
cgit v0.12