# HG changeset patch # User Paul Boddie # Date 1493586922 -7200 # Node ID 3e5b1b8cb456025305e0af6839cb25e7a821b5a8 # Parent 81089c4cb6ebbf21bce4387d61523751b048be95 Added initial definition list element support. Consolidated common serialisation routines. diff -r 81089c4cb6eb -r 3e5b1b8cb456 moinformat/__init__.py --- a/moinformat/__init__.py Sun Apr 30 17:59:52 2017 +0200 +++ b/moinformat/__init__.py Sun Apr 30 23:15:22 2017 +0200 @@ -19,7 +19,7 @@ this program. If not, see . """ -from moinformat.tree import Block, Break, Heading, ListItem, Region, Rule, Text +from moinformat.tree import Block, Break, DefItem, DefTerm, Heading, ListItem, Region, Rule, Text import re # Regular expressions. @@ -34,17 +34,21 @@ # Line-oriented patterns: # blank line "break" : r"^(\s*?)\n", + # ws... expecting text :: + "defterm" : r"^(\s+)(?=.+?::)", + # ws... expecting :: ws... + "defterm_empty" : r"^(\s+)(?=::\s+)", # [ws...] =... ws... expecting headingend "heading" : r"^(\s*)(?P=+)(\s+)(?=.*?\s+(?P=x)\s*\n)", - # indent list-item [ws...] + # ws... list-item [ws...] "listitem" : r"^(\s+)(\*)(\s*)", - # indent number-item ws... + # ws... number-item ws... "listitem_num" : r"^(\s+)(\d+\.)(\s+)", - # indent alpha-item ws... + # ws... alpha-item ws... "listitem_alpha": r"^(\s+)([aA]\.)(\s+)", - # indent roman-item ws... + # ws... roman-item ws... "listitem_roman": r"^(\s+)([iI]\.)(\s+)", - # indent dot-item [ws...] + # ws... dot-item [ws...] "listitem_dot" : r"^(\s+)(\.)(\s*)", # Region contents: @@ -55,6 +59,8 @@ "headingend" : r"(\s+)(=+)(\s*\n)", # ws... =... [ws...] nl # List contents: + "deftermend" : r"::(\s*?\n)", + "deftermsep" : r"::(\s+)", "listitemend" : r"^", # next line } @@ -176,8 +182,11 @@ new_block(region) parse_region_details(items, region, [ - "break", "heading", "listitem", "listitem_num", "listitem_alpha", - "listitem_roman", "listitem_dot", "regionstart", "regionend", "rule"]) + "break", "heading", + "defterm", "defterm_empty", + "listitem", "listitem_alpha", "listitem_dot", "listitem_num", + "listitem_roman", + "regionstart", "regionend", "rule"]) def parse_region_opaque(items, region): @@ -233,6 +242,38 @@ region.add(Break()) new_block(region) +def parse_defitem(items, region, extra=""): + + "Handle a definition item within 'region'." + + pad = items.read_match(1) + item = DefItem([], pad, extra) + parse_region_details(items, item, ["listitemend"]) + region.append(item) + new_block(region) + +def parse_defterm(items, region): + + "Handle a definition term within 'region'." + + pad = items.read_match(1) + term = DefTerm([], pad) + parse_region_details(items, term, ["deftermend", "deftermsep"]) + region.append(term) + if items.matching == "deftermsep": + parse_defitem(items, region) + +def parse_defterm_empty(items, region): + + "Handle an empty definition term within 'region'." + + extra = items.read_match(1) + parse_region_details(items, region, ["deftermsep"]) + parse_defitem(items, region, extra) + +parse_defterm_end = end_region +parse_defterm_sep = end_region + def parse_heading(items, region): "Handle a heading." @@ -267,11 +308,7 @@ region.append(item) new_block(region) -def parse_listitem_end(items, item): - - "Handle the end of a list." - - raise StopIteration +parse_listitem_end = end_region def parse_rule(items, region): @@ -308,6 +345,10 @@ handlers = { None : end_region, "break" : parse_break, + "defterm" : parse_defterm, + "defterm_empty" : parse_defterm_empty, + "deftermend" : parse_defterm_end, + "deftermsep" : parse_defterm_sep, "heading" : parse_heading, "headingend" : parse_heading_end, "listitemend" : parse_listitem_end, diff -r 81089c4cb6eb -r 3e5b1b8cb456 moinformat/serialisers.py --- a/moinformat/serialisers.py Sun Apr 30 17:59:52 2017 +0200 +++ b/moinformat/serialisers.py Sun Apr 30 23:15:22 2017 +0200 @@ -50,6 +50,18 @@ def end_block(self): pass + def start_defitem(self, pad, extra): + self.out((extra and "\n" + extra + "::" or "") + pad) + + def end_defitem(self, pad, extra): + pass + + def start_defterm(self, pad): + self.out(pad) + + def end_defterm(self, pad): + self.out("::") + def start_heading(self, level, extra, pad): self.out(extra + "=" * level + pad) @@ -100,6 +112,18 @@ def end_block(self): self.out("

") + def start_defitem(self, pad, extra): + self.out("
") + + def end_defitem(self, pad, extra): + self.out("
") + + def start_defterm(self, pad): + self.out("
") + + def end_defterm(self, pad): + self.out("
") + def start_heading(self, level, extra, pad): self.out("" % level) diff -r 81089c4cb6eb -r 3e5b1b8cb456 moinformat/tree.py --- a/moinformat/tree.py Sun Apr 30 17:59:52 2017 +0200 +++ b/moinformat/tree.py Sun Apr 30 23:15:22 2017 +0200 @@ -76,8 +76,14 @@ def __str__(self): return self.prettyprint() - def prettyprint(self, indent=""): - pass + def _prettyprint(self, l, indent=""): + for node in self.nodes: + l.append(node.prettyprint(indent + " ")) + return "\n".join(l) + + def _to_string(self, out): + for node in self.nodes: + node.to_string(out) class Region(Container): @@ -115,14 +121,11 @@ def prettyprint(self, indent=""): l = ["%sRegion: level=%d indent=%d type=%s" % (indent, self.level, self.indent, self.type)] - for node in self.nodes: - l.append(node.prettyprint(indent + " ")) - return "\n".join(l) + return self._prettyprint(l, indent) def to_string(self, out): out.start_region(self.level, self.indent, self.type) - for node in self.nodes: - node.to_string(out) + self._to_string(out) out.end_region(self.level, self.indent, self.type) class Block(Container): @@ -134,16 +137,54 @@ def prettyprint(self, indent=""): l = ["%sBlock" % indent] - for node in self.nodes: - l.append(node.prettyprint(indent + " ")) - return "\n".join(l) + return self._prettyprint(l, indent) def to_string(self, out): out.start_block() - for node in self.nodes: - node.to_string(out) + self._to_string(out) out.end_block() +class DefItem(Container): + + "A definition item." + + def __init__(self, nodes, pad, extra): + Container.__init__(self, nodes) + self.pad = pad + self.extra = extra + + def __repr__(self): + return "DefItem(%r, %r, %r)" % (self.nodes, self.pad, self.extra) + + def prettyprint(self, indent=""): + l = ["%sDefItem: pad=%r extra=%r" % (indent, self.pad, self.extra)] + return self._prettyprint(l, indent) + + def to_string(self, out): + out.start_defitem(self.pad, self.extra) + self._to_string(out) + out.end_defitem(self.pad, self.extra) + +class DefTerm(Container): + + "A definition term." + + def __init__(self, nodes, pad): + Container.__init__(self, nodes) + self.pad = pad + + def __repr__(self): + return "DefTerm(%r, %r)" % (self.nodes, self.pad) + + def prettyprint(self, indent=""): + l = ["%sDefTerm: pad=%r" % (indent, self.pad)] + return self._prettyprint(l, indent) + + def to_string(self, out): + out.start_defterm(self.pad) + self._to_string(out) + out.end_defterm(self.pad) + class Heading(Container): "A heading." @@ -163,14 +204,11 @@ def prettyprint(self, indent=""): l = ["%sHeading: level=%d start_extra=%r start_pad=%r end_pad=%r end_extra=%r" % ( indent, self.level, self.start_extra, self.start_pad, self.end_pad, self.end_extra)] - for node in self.nodes: - l.append(node.prettyprint(indent + " ")) - return "\n".join(l) + return self._prettyprint(l, indent) def to_string(self, out): out.start_heading(self.level, self.start_extra, self.start_pad) - for node in self.nodes: - node.to_string(out) + self._to_string(out) out.end_heading(self.level, self.end_pad, self.end_extra) class ListItem(Container): @@ -188,14 +226,11 @@ def prettyprint(self, indent=""): l = ["%sListItem: indent=%d marker=%r space=%r" % (indent, self.indent, self.marker, self.space)] - for node in self.nodes: - l.append(node.prettyprint(indent + " ")) - return "\n".join(l) + return self._prettyprint(l, indent) def to_string(self, out): out.start_listitem(self.indent, self.marker, self.space) - for node in self.nodes: - node.to_string(out) + self._to_string(out) out.end_listitem(self.indent, self.marker) diff -r 81089c4cb6eb -r 3e5b1b8cb456 tests/test_parser.py --- a/tests/test_parser.py Sun Apr 30 17:59:52 2017 +0200 +++ b/tests/test_parser.py Sun Apr 30 23:15:22 2017 +0200 @@ -25,6 +25,10 @@ . Item 3 . Item 3.1 XXX +""") + +sl.append("""\ +XXX a. Appendix i. Romanus eunt domus! @@ -32,6 +36,14 @@ """) sl.append("""\ + term:: item +not a term:: nor an item + term:: + :: item + ::non-item +""") + +sl.append("""\ Hello {{{{#!xxx A region