1.1 --- a/moinformat/__init__.py Sun Apr 30 17:59:52 2017 +0200
1.2 +++ b/moinformat/__init__.py Sun Apr 30 23:15:22 2017 +0200
1.3 @@ -19,7 +19,7 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from moinformat.tree import Block, Break, Heading, ListItem, Region, Rule, Text
1.8 +from moinformat.tree import Block, Break, DefItem, DefTerm, Heading, ListItem, Region, Rule, Text
1.9 import re
1.10
1.11 # Regular expressions.
1.12 @@ -34,17 +34,21 @@
1.13 # Line-oriented patterns:
1.14 # blank line
1.15 "break" : r"^(\s*?)\n",
1.16 + # ws... expecting text ::
1.17 + "defterm" : r"^(\s+)(?=.+?::)",
1.18 + # ws... expecting :: ws...
1.19 + "defterm_empty" : r"^(\s+)(?=::\s+)",
1.20 # [ws...] =... ws... expecting headingend
1.21 "heading" : r"^(\s*)(?P<x>=+)(\s+)(?=.*?\s+(?P=x)\s*\n)",
1.22 - # indent list-item [ws...]
1.23 + # ws... list-item [ws...]
1.24 "listitem" : r"^(\s+)(\*)(\s*)",
1.25 - # indent number-item ws...
1.26 + # ws... number-item ws...
1.27 "listitem_num" : r"^(\s+)(\d+\.)(\s+)",
1.28 - # indent alpha-item ws...
1.29 + # ws... alpha-item ws...
1.30 "listitem_alpha": r"^(\s+)([aA]\.)(\s+)",
1.31 - # indent roman-item ws...
1.32 + # ws... roman-item ws...
1.33 "listitem_roman": r"^(\s+)([iI]\.)(\s+)",
1.34 - # indent dot-item [ws...]
1.35 + # ws... dot-item [ws...]
1.36 "listitem_dot" : r"^(\s+)(\.)(\s*)",
1.37
1.38 # Region contents:
1.39 @@ -55,6 +59,8 @@
1.40 "headingend" : r"(\s+)(=+)(\s*\n)", # ws... =... [ws...] nl
1.41
1.42 # List contents:
1.43 + "deftermend" : r"::(\s*?\n)",
1.44 + "deftermsep" : r"::(\s+)",
1.45 "listitemend" : r"^", # next line
1.46 }
1.47
1.48 @@ -176,8 +182,11 @@
1.49
1.50 new_block(region)
1.51 parse_region_details(items, region, [
1.52 - "break", "heading", "listitem", "listitem_num", "listitem_alpha",
1.53 - "listitem_roman", "listitem_dot", "regionstart", "regionend", "rule"])
1.54 + "break", "heading",
1.55 + "defterm", "defterm_empty",
1.56 + "listitem", "listitem_alpha", "listitem_dot", "listitem_num",
1.57 + "listitem_roman",
1.58 + "regionstart", "regionend", "rule"])
1.59
1.60 def parse_region_opaque(items, region):
1.61
1.62 @@ -233,6 +242,38 @@
1.63 region.add(Break())
1.64 new_block(region)
1.65
1.66 +def parse_defitem(items, region, extra=""):
1.67 +
1.68 + "Handle a definition item within 'region'."
1.69 +
1.70 + pad = items.read_match(1)
1.71 + item = DefItem([], pad, extra)
1.72 + parse_region_details(items, item, ["listitemend"])
1.73 + region.append(item)
1.74 + new_block(region)
1.75 +
1.76 +def parse_defterm(items, region):
1.77 +
1.78 + "Handle a definition term within 'region'."
1.79 +
1.80 + pad = items.read_match(1)
1.81 + term = DefTerm([], pad)
1.82 + parse_region_details(items, term, ["deftermend", "deftermsep"])
1.83 + region.append(term)
1.84 + if items.matching == "deftermsep":
1.85 + parse_defitem(items, region)
1.86 +
1.87 +def parse_defterm_empty(items, region):
1.88 +
1.89 + "Handle an empty definition term within 'region'."
1.90 +
1.91 + extra = items.read_match(1)
1.92 + parse_region_details(items, region, ["deftermsep"])
1.93 + parse_defitem(items, region, extra)
1.94 +
1.95 +parse_defterm_end = end_region
1.96 +parse_defterm_sep = end_region
1.97 +
1.98 def parse_heading(items, region):
1.99
1.100 "Handle a heading."
1.101 @@ -267,11 +308,7 @@
1.102 region.append(item)
1.103 new_block(region)
1.104
1.105 -def parse_listitem_end(items, item):
1.106 -
1.107 - "Handle the end of a list."
1.108 -
1.109 - raise StopIteration
1.110 +parse_listitem_end = end_region
1.111
1.112 def parse_rule(items, region):
1.113
1.114 @@ -308,6 +345,10 @@
1.115 handlers = {
1.116 None : end_region,
1.117 "break" : parse_break,
1.118 + "defterm" : parse_defterm,
1.119 + "defterm_empty" : parse_defterm_empty,
1.120 + "deftermend" : parse_defterm_end,
1.121 + "deftermsep" : parse_defterm_sep,
1.122 "heading" : parse_heading,
1.123 "headingend" : parse_heading_end,
1.124 "listitemend" : parse_listitem_end,
2.1 --- a/moinformat/serialisers.py Sun Apr 30 17:59:52 2017 +0200
2.2 +++ b/moinformat/serialisers.py Sun Apr 30 23:15:22 2017 +0200
2.3 @@ -50,6 +50,18 @@
2.4 def end_block(self):
2.5 pass
2.6
2.7 + def start_defitem(self, pad, extra):
2.8 + self.out((extra and "\n" + extra + "::" or "") + pad)
2.9 +
2.10 + def end_defitem(self, pad, extra):
2.11 + pass
2.12 +
2.13 + def start_defterm(self, pad):
2.14 + self.out(pad)
2.15 +
2.16 + def end_defterm(self, pad):
2.17 + self.out("::")
2.18 +
2.19 def start_heading(self, level, extra, pad):
2.20 self.out(extra + "=" * level + pad)
2.21
2.22 @@ -100,6 +112,18 @@
2.23 def end_block(self):
2.24 self.out("</p>")
2.25
2.26 + def start_defitem(self, pad, extra):
2.27 + self.out("<dd>")
2.28 +
2.29 + def end_defitem(self, pad, extra):
2.30 + self.out("</dd>")
2.31 +
2.32 + def start_defterm(self, pad):
2.33 + self.out("<dt>")
2.34 +
2.35 + def end_defterm(self, pad):
2.36 + self.out("</dt>")
2.37 +
2.38 def start_heading(self, level, extra, pad):
2.39 self.out("<h%d>" % level)
2.40
3.1 --- a/moinformat/tree.py Sun Apr 30 17:59:52 2017 +0200
3.2 +++ b/moinformat/tree.py Sun Apr 30 23:15:22 2017 +0200
3.3 @@ -76,8 +76,14 @@
3.4 def __str__(self):
3.5 return self.prettyprint()
3.6
3.7 - def prettyprint(self, indent=""):
3.8 - pass
3.9 + def _prettyprint(self, l, indent=""):
3.10 + for node in self.nodes:
3.11 + l.append(node.prettyprint(indent + " "))
3.12 + return "\n".join(l)
3.13 +
3.14 + def _to_string(self, out):
3.15 + for node in self.nodes:
3.16 + node.to_string(out)
3.17
3.18 class Region(Container):
3.19
3.20 @@ -115,14 +121,11 @@
3.21
3.22 def prettyprint(self, indent=""):
3.23 l = ["%sRegion: level=%d indent=%d type=%s" % (indent, self.level, self.indent, self.type)]
3.24 - for node in self.nodes:
3.25 - l.append(node.prettyprint(indent + " "))
3.26 - return "\n".join(l)
3.27 + return self._prettyprint(l, indent)
3.28
3.29 def to_string(self, out):
3.30 out.start_region(self.level, self.indent, self.type)
3.31 - for node in self.nodes:
3.32 - node.to_string(out)
3.33 + self._to_string(out)
3.34 out.end_region(self.level, self.indent, self.type)
3.35
3.36 class Block(Container):
3.37 @@ -134,16 +137,54 @@
3.38
3.39 def prettyprint(self, indent=""):
3.40 l = ["%sBlock" % indent]
3.41 - for node in self.nodes:
3.42 - l.append(node.prettyprint(indent + " "))
3.43 - return "\n".join(l)
3.44 + return self._prettyprint(l, indent)
3.45
3.46 def to_string(self, out):
3.47 out.start_block()
3.48 - for node in self.nodes:
3.49 - node.to_string(out)
3.50 + self._to_string(out)
3.51 out.end_block()
3.52
3.53 +class DefItem(Container):
3.54 +
3.55 + "A definition item."
3.56 +
3.57 + def __init__(self, nodes, pad, extra):
3.58 + Container.__init__(self, nodes)
3.59 + self.pad = pad
3.60 + self.extra = extra
3.61 +
3.62 + def __repr__(self):
3.63 + return "DefItem(%r, %r, %r)" % (self.nodes, self.pad, self.extra)
3.64 +
3.65 + def prettyprint(self, indent=""):
3.66 + l = ["%sDefItem: pad=%r extra=%r" % (indent, self.pad, self.extra)]
3.67 + return self._prettyprint(l, indent)
3.68 +
3.69 + def to_string(self, out):
3.70 + out.start_defitem(self.pad, self.extra)
3.71 + self._to_string(out)
3.72 + out.end_defitem(self.pad, self.extra)
3.73 +
3.74 +class DefTerm(Container):
3.75 +
3.76 + "A definition term."
3.77 +
3.78 + def __init__(self, nodes, pad):
3.79 + Container.__init__(self, nodes)
3.80 + self.pad = pad
3.81 +
3.82 + def __repr__(self):
3.83 + return "DefTerm(%r, %r)" % (self.nodes, self.pad)
3.84 +
3.85 + def prettyprint(self, indent=""):
3.86 + l = ["%sDefTerm: pad=%r" % (indent, self.pad)]
3.87 + return self._prettyprint(l, indent)
3.88 +
3.89 + def to_string(self, out):
3.90 + out.start_defterm(self.pad)
3.91 + self._to_string(out)
3.92 + out.end_defterm(self.pad)
3.93 +
3.94 class Heading(Container):
3.95
3.96 "A heading."
3.97 @@ -163,14 +204,11 @@
3.98 def prettyprint(self, indent=""):
3.99 l = ["%sHeading: level=%d start_extra=%r start_pad=%r end_pad=%r end_extra=%r" % (
3.100 indent, self.level, self.start_extra, self.start_pad, self.end_pad, self.end_extra)]
3.101 - for node in self.nodes:
3.102 - l.append(node.prettyprint(indent + " "))
3.103 - return "\n".join(l)
3.104 + return self._prettyprint(l, indent)
3.105
3.106 def to_string(self, out):
3.107 out.start_heading(self.level, self.start_extra, self.start_pad)
3.108 - for node in self.nodes:
3.109 - node.to_string(out)
3.110 + self._to_string(out)
3.111 out.end_heading(self.level, self.end_pad, self.end_extra)
3.112
3.113 class ListItem(Container):
3.114 @@ -188,14 +226,11 @@
3.115
3.116 def prettyprint(self, indent=""):
3.117 l = ["%sListItem: indent=%d marker=%r space=%r" % (indent, self.indent, self.marker, self.space)]
3.118 - for node in self.nodes:
3.119 - l.append(node.prettyprint(indent + " "))
3.120 - return "\n".join(l)
3.121 + return self._prettyprint(l, indent)
3.122
3.123 def to_string(self, out):
3.124 out.start_listitem(self.indent, self.marker, self.space)
3.125 - for node in self.nodes:
3.126 - node.to_string(out)
3.127 + self._to_string(out)
3.128 out.end_listitem(self.indent, self.marker)
3.129
3.130