Browse Source

cmRST: Teach cmake-module directive to scan bracket comments

When scanning CMake module files for .rst comments, recognize
bracket comments starting in ".rst:" too.  For example:

 #[[.rst:

Include the bracket comment content terminated by the closing bracket.
Exclude the line containing the bracket if it starts in "#".

Teach the CMakeLib.testRST test to cover multiple bracket lengths
and ending brackets on lines with and without "#".

Update the cmake-developer.7 manual to document the bracket-comment
syntax for .rst documentation.
Brad King 12 years ago
parent
commit
2945814de2

+ 22 - 6
Help/manual/cmake-developer.7.rst

@@ -253,6 +253,21 @@ Add to the top of ``Modules/<module-name>.cmake`` a #-comment of the form:
  #
  # <reStructuredText documentation of module>
 
+or a bracket-comment of the form:
+
+.. code-block:: cmake
+
+ #[[.rst:
+ <module-name>
+ -------------
+
+ <reStructuredText documentation of module>
+ #]]
+
+Any number of ``=`` may be used in the opening and closing brackets
+as long as they match.  Content on the line containing the closing
+bracket is excluded if and only if the line starts in ``#``.
+
 Additional such ``.rst:`` comments may appear anywhere in the module file.
 All such comments must start with ``#`` in the first column.
 
@@ -276,12 +291,13 @@ For example, a ``Modules/Findxxx.cmake`` module may contain:
 
  <code>
 
- #.rst:
- # .. command:: xxx_do_something
- #
- #  This command does something for Xxx::
- #
- #   xxx_do_something(some arguments)
+ #[========================================[.rst:
+ .. command:: xxx_do_something
+
+  This command does something for Xxx::
+
+   xxx_do_something(some arguments)
+ #]========================================]
  macro(xxx_do_something)
    <code>
  endmacro()

+ 39 - 11
Source/cmRST.cxx

@@ -34,6 +34,7 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot):
   ReplaceDirective("^.. (\\|[^|]+\\|) replace::[ \t]*(.*)$"),
   IncludeDirective("^.. include::[ \t]+([^ \t\n]+)$"),
   TocTreeDirective("^.. toctree::[ \t]*(.*)$"),
+  ModuleRST("^#\\[(=*)\\[\\.rst:$"),
   CMakeRole("(:cmake)?:("
             "command|generator|variable|module|policy|"
             "prop_cache|prop_dir|prop_gbl|prop_sf|prop_test|prop_tgt|"
@@ -85,28 +86,55 @@ void cmRST::ProcessModule(std::istream& is)
   std::string rst;
   while(cmSystemTools::GetLineFromStream(is, line))
     {
-    if(rst == "#")
+    if(!rst.empty() && rst != "#")
       {
-      if(line == "#")
+      // Bracket mode: check for end bracket
+      std::string::size_type pos = line.find(rst);
+      if(pos == line.npos)
         {
-        this->ProcessLine("");
-        continue;
-        }
-      else if(line.substr(0, 2) == "# ")
-        {
-        this->ProcessLine(line.substr(2, line.npos));
-        continue;
+        this->ProcessLine(line);
         }
       else
         {
+        if(line[0] != '#')
+          {
+          this->ProcessLine(line.substr(0, pos));
+          }
         rst = "";
         this->Reset();
         this->OutputLinePending = true;
         }
       }
-    if(line == "#.rst:")
+    else
       {
-      rst = "#";
+      // Line mode: check for .rst start (bracket or line)
+      if(rst == "#")
+        {
+        if(line == "#")
+          {
+          this->ProcessLine("");
+          continue;
+          }
+        else if(line.substr(0, 2) == "# ")
+          {
+          this->ProcessLine(line.substr(2, line.npos));
+          continue;
+          }
+        else
+          {
+          rst = "";
+          this->Reset();
+          this->OutputLinePending = true;
+          }
+        }
+      if(line == "#.rst:")
+        {
+        rst = "#";
+        }
+      else if(this->ModuleRST.find(line))
+        {
+        rst = "]" + this->ModuleRST.match(1) + "]";
+        }
       }
     }
   if(rst == "#")

+ 1 - 0
Source/cmRST.h

@@ -84,6 +84,7 @@ private:
   cmsys::RegularExpression ReplaceDirective;
   cmsys::RegularExpression IncludeDirective;
   cmsys::RegularExpression TocTreeDirective;
+  cmsys::RegularExpression ModuleRST;
   cmsys::RegularExpression CMakeRole;
   cmsys::RegularExpression Substitution;
 

+ 6 - 0
Tests/CMakeLib/testRST.expect

@@ -27,6 +27,12 @@ CMake Module Content
 
 More CMake Module Content
 
+Bracket Comment Content
+
+[
+Bracket Comment Content
+]
+
 .. cmake:command:: some_cmd
 
    Command some_cmd description.

+ 7 - 0
Tests/CMakeLib/testRSTmod.cmake

@@ -2,3 +2,10 @@
 # CMake Module Content
 #.rst:
 # More CMake Module Content
+#[[.rst:
+Bracket Comment Content
+# not part of content]] # not part of content
+#[=[.rst:
+[
+Bracket Comment Content
+]]=] # not part of content

+ 27 - 10
Utilities/Sphinx/cmake.py

@@ -31,7 +31,6 @@ class CMakeModule(Directive):
 
     def __init__(self, *args, **keys):
         self.re_start = re.compile(r'^#\[(?P<eq>=*)\[\.rst:$')
-        self.re_end = re.compile(r'^#?\](?P<eq>=*)\]$')
         Directive.__init__(self, *args, **keys)
 
     def run(self):
@@ -61,18 +60,36 @@ class CMakeModule(Directive):
         rst = None
         lines = []
         for line in raw_lines:
-            if line == '#.rst:':
-                rst = '#'
-                line = ''
-            elif rst == '#':
-                if line == '#' or line[:2] == '# ':
-                    line = line[2:]
-                else:
+            if rst is not None and rst != '#':
+                # Bracket mode: check for end bracket
+                pos = line.find(rst)
+                if pos >= 0:
+                    if line[0] == '#':
+                        line = ''
+                    else:
+                        line = line[0:pos]
                     rst = None
-                    line = ''
             else:
-                line = ''
+                # Line mode: check for .rst start (bracket or line)
+                m = self.re_start.match(line)
+                if m:
+                    rst = ']%s]' % m.group('eq')
+                    line = ''
+                elif line == '#.rst:':
+                    rst = '#'
+                    line = ''
+                elif rst == '#':
+                    if line == '#' or line[:2] == '# ':
+                        line = line[2:]
+                    else:
+                        rst = None
+                        line = ''
+                elif rst is None:
+                    line = ''
             lines.append(line)
+        if rst is not None and rst != '#':
+            raise self.warning('"%s" found unclosed bracket "#[%s[.rst:" in %s' %
+                               (self.name, rst[1:-1], path))
         self.state_machine.insert_input(lines, path)
         return []