minirst: parse field lists
authorMartin Geisler <mg@lazybytes.net>
Sun, 02 Aug 2009 23:38:07 +0200
changeset 9293 e48a48b754d3
parent 9292 01e580143423
child 9294 5f4862a00697
minirst: parse field lists
mercurial/minirst.py
tests/test-minirst.py
tests/test-minirst.py.out
--- a/mercurial/minirst.py	Sun Aug 02 21:29:15 2009 +0200
+++ b/mercurial/minirst.py	Sun Aug 02 23:38:07 2009 +0200
@@ -22,6 +22,8 @@
 
 - lists (items must start with '-')
 
+- field lists (colons cannot be escaped)
+
 - literal blocks
 
 - option lists (supports only long options without arguments)
@@ -188,6 +190,43 @@
     return blocks
 
 
+_fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):( +)(.*)')
+def findfieldlists(blocks):
+    """Finds fields lists.
+
+    The blocks must have a 'type' field, i.e., they should have been
+    run through findliteralblocks first.
+    """
+    i = 0
+    while i < len(blocks):
+        # Searching for a paragraph that looks like this:
+        #
+        #
+        # +--------------------+----------------------+
+        # | ":" field name ":" | field body           |
+        # +-------+------------+                      |
+        #         | (body elements)+                  |
+        #         +-----------------------------------+
+        if (blocks[i]['type'] == 'paragraph' and
+            _fieldre.match(blocks[i]['lines'][0])):
+            indent = blocks[i]['indent']
+            fields = []
+            for line in blocks[i]['lines']:
+                m = _fieldre.match(line)
+                if m:
+                    key, spaces, rest = m.groups()
+                    width = 2 + len(key) + len(spaces)
+                    fields.append(dict(type='field', lines=[],
+                                       indent=indent, width=width))
+                    # Turn ":foo: bar" into "foo   bar".
+                    line = '%s  %s%s' % (key, spaces, rest)
+                fields[-1]['lines'].append(line)
+            blocks[i:i+1] = fields
+            i += len(fields) - 1
+        i += 1
+    return blocks
+
+
 def finddefinitionlists(blocks):
     """Finds definition lists.
 
@@ -230,7 +269,7 @@
     i = 1
     while i < len(blocks):
         if (blocks[i]['type'] == blocks[i-1]['type'] and
-            blocks[i]['type'] in ('bullet', 'option', 'definition')):
+            blocks[i]['type'] in ('bullet', 'option', 'field', 'definition')):
             i += 1
         else:
             blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
@@ -261,7 +300,7 @@
         if block['type'] == 'bullet':
             initindent = indent + '- '
             subindent = indent + '  '
-        elif block['type'] == 'option':
+        elif block['type'] in ('option', 'field'):
             subindent = indent + block['width'] * ' '
 
         return textwrap.fill(text, width=width,
@@ -276,6 +315,7 @@
     blocks = findsections(blocks)
     blocks = findbulletlists(blocks)
     blocks = findoptionlists(blocks)
+    blocks = findfieldlists(blocks)
     blocks = finddefinitionlists(blocks)
     blocks = addmargins(blocks)
     return '\n'.join(formatblock(b, width) for b in blocks)
@@ -297,6 +337,7 @@
     blocks = debug(findsections, blocks)
     blocks = debug(findbulletlists, blocks)
     blocks = debug(findoptionlists, blocks)
+    blocks = debug(findfieldlists, blocks)
     blocks = debug(finddefinitionlists, blocks)
     blocks = debug(addmargins, blocks)
     print '\n'.join(formatblock(b, 30) for b in blocks)
--- a/tests/test-minirst.py	Sun Aug 02 21:29:15 2009 +0200
+++ b/tests/test-minirst.py	Sun Aug 02 23:38:07 2009 +0200
@@ -137,3 +137,17 @@
 
 debugformat('options', options, 60)
 debugformat('options', options, 30)
+
+
+fields = """
+Field lists give a simple two-column layout:
+
+:key:         The whitespace following the key is
+  significant for the wrapping of this text.
+:another key: More text.
+    The indentation on the following
+    lines is not significant.
+"""
+
+debugformat('fields', fields, 60)
+debugformat('fields', fields, 30)
--- a/tests/test-minirst.py.out	Sun Aug 02 21:29:15 2009 +0200
+++ b/tests/test-minirst.py.out	Sun Aug 02 23:38:07 2009 +0200
@@ -209,3 +209,31 @@
 --foo bar baz
 ----------------------------------------------------------------------
 
+fields formatted to fit within 60 characters:
+----------------------------------------------------------------------
+Field lists give a simple two-column layout:
+
+key           The whitespace following the key is
+              significant for the wrapping of this text.
+another key   More text. The indentation on the following
+              lines is not significant.
+----------------------------------------------------------------------
+
+fields formatted to fit within 30 characters:
+----------------------------------------------------------------------
+Field lists give a simple two-
+column layout:
+
+key           The whitespace
+              following the
+              key is
+              significant for
+              the wrapping of
+              this text.
+another key   More text. The
+              indentation on
+              the following
+              lines is not
+              significant.
+----------------------------------------------------------------------
+