# HG changeset patch
# User Paul Boddie
# Date 1493334586 -7200
# Node ID c3831bd8835fe151360f71f78d245692968f9aa0
# Parent 0cbb97f958954a7835d01b33203abd78baa86031
Added initial support for list item parsing.
diff -r 0cbb97f95895 -r c3831bd8835f moinformat.py
--- a/moinformat.py Thu Apr 27 23:42:43 2017 +0200
+++ b/moinformat.py Fri Apr 28 01:09:46 2017 +0200
@@ -32,6 +32,10 @@
# Region contents:
"break" : (r"^(\s*?)\n", re.MULTILINE), # blank line
+ "listitem" : (r"^((\s+)([*]|\d+[.]))", re.MULTILINE), # indent (list-item or number-item)
+
+ # List contents:
+ "listitemend" : (r"^", re.MULTILINE), # next line
}
# Define patterns for the regular expressions.
@@ -56,6 +60,9 @@
append_text = append
+ def empty(self):
+ return not self.nodes
+
def normalise(self):
"Combine adjacent text nodes."
@@ -104,6 +111,13 @@
self.level = level
self.type = type
+ def append(self, node):
+ last = self.nodes and self.nodes[-1]
+ if last and last.empty():
+ self.nodes[-1] = node
+ else:
+ self.nodes.append(node)
+
def append_text(self, s):
if self.is_transparent():
self.nodes[-1].append(s)
@@ -154,6 +168,26 @@
node.to_string(out)
out.end_block(self.final)
+class ListItem(Container):
+
+ "A list item."
+
+ def __repr__(self):
+ return "ListItem(%r)" % self.nodes
+
+ def prettyprint(self, indent=""):
+ l = ["%sListItem:" % indent]
+ for node in self.nodes:
+ l.append(node.prettyprint(indent + " "))
+ return "\n".join(l)
+
+ def to_string(self, out):
+ out.start_listitem()
+ for node in self.nodes:
+ node.to_string(out)
+ out.end_listitem()
+
+
class Text:
"A text node."
@@ -161,6 +195,9 @@
def __init__(self, s):
self.s = s
+ def empty(self):
+ return not self.s
+
def merge(self, text):
self.s += text.s
@@ -207,6 +244,12 @@
if not final:
self.out("\n")
+ def start_listitem(self):
+ self.out(" *")
+
+ def end_listitem(self):
+ pass
+
def text(self, s):
self.out(s)
@@ -236,6 +279,12 @@
def end_block(self, final):
self.out("
")
+ def start_listitem(self):
+ self.out("")
+
+ def end_listitem(self):
+ self.out("")
+
def text(self, s):
self.out(escape(s))
@@ -289,8 +338,10 @@
if self.match:
_start, self.pos = self.match.span()
- s = self.match.group(1)
- return s
+ try:
+ return self.match.group(1)
+ except IndexError:
+ return ""
else:
self.pos = len(self.s)
return None
@@ -343,7 +394,7 @@
"Parse the data provided by 'items' to populate a wiki 'region'."
new_block(region)
- parse_region_details(items, region, ["break", "regionstart", "regionend"])
+ parse_region_details(items, region, ["break", "listitem", "regionstart", "regionend"])
def parse_region_opaque(items, region):
@@ -402,6 +453,21 @@
block.final = False
new_block(region)
+def parse_listitem_end(items, region):
+
+ "Handle the end of a list."
+
+ raise StopIteration
+
+def parse_listitem(items, region):
+
+ "Handle a list item marker within 'region'."
+
+ item = ListItem([])
+ parse_region_details(items, item, ["listitemend"])
+ region.append(item)
+ new_block(region)
+
def parse_section(items, region):
"Handle the start of a new section within 'region'."
@@ -427,6 +493,8 @@
handlers = {
None : end_region,
"break" : parse_break,
+ "listitemend" : parse_listitem_end,
+ "listitem" : parse_listitem,
"regionstart" : parse_section,
"regionend" : parse_section_end,
}
diff -r 0cbb97f95895 -r c3831bd8835f tests/test_parser.py
--- a/tests/test_parser.py Thu Apr 27 23:42:43 2017 +0200
+++ b/tests/test_parser.py Fri Apr 28 01:09:46 2017 +0200
@@ -12,6 +12,10 @@
End
}}}}
XXX
+
+ * Item 1
+ * Item 2
+XXX
"""
s1 = """\