1.1 --- a/moinformat/parsers/moin.py Wed Dec 13 00:50:09 2017 +0100
1.2 +++ b/moinformat/parsers/moin.py Fri Jun 01 15:18:32 2018 +0200
1.3 @@ -19,11 +19,11 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from moinformat.parsers.common import ParserBase, get_patterns, get_subset, new_block
1.8 +from moinformat.parsers.common import ParserBase, get_patterns, get_subset
1.9 from moinformat.serialisers import serialise
1.10 from moinformat.tree import Break, DefItem, DefTerm, FontStyle, Heading, \
1.11 - Larger, ListItem, Monospace, Region, Rule, Smaller, \
1.12 - Subscript, Superscript, Table, TableAttr, \
1.13 + Larger, List, ListItem, Monospace, Region, Rule, \
1.14 + Smaller, Subscript, Superscript, Table, TableAttr, \
1.15 TableAttrs, TableCell, TableRow, Text, Underline
1.16
1.17 class MoinParser(ParserBase):
1.18 @@ -95,8 +95,8 @@
1.19
1.20 "Handle a paragraph break within 'region'."
1.21
1.22 - region.add(Break())
1.23 - new_block(region)
1.24 + self.add_node(region, Break())
1.25 + self.new_block(region)
1.26
1.27 def parse_defitem(self, region, extra=""):
1.28
1.29 @@ -105,8 +105,8 @@
1.30 pad = self.read_match(1)
1.31 item = DefItem([], pad, extra)
1.32 self.parse_region_details(item, ["listitemend"])
1.33 - region.add(item)
1.34 - new_block(region)
1.35 + self.add_node(region, item)
1.36 + self.new_block(region)
1.37
1.38 def parse_defterm(self, region):
1.39
1.40 @@ -115,7 +115,7 @@
1.41 pad = self.read_match(1)
1.42 term = DefTerm([], pad)
1.43 self.parse_region_details(term, ["deftermend", "deftermsep"])
1.44 - region.add(term)
1.45 + self.add_node(region, term)
1.46 if self.read_matching() == "deftermsep":
1.47 self.parse_defitem(region)
1.48
1.49 @@ -183,8 +183,8 @@
1.50 start_pad = self.read_match(3)
1.51 heading = Heading([], level, start_extra, start_pad)
1.52 self.parse_region_details(heading, ["headingend"] + self.inline_pattern_names)
1.53 - region.add(heading)
1.54 - new_block(region)
1.55 + self.add_node(region, heading)
1.56 + self.new_block(region)
1.57
1.58 def parse_heading_end(self, heading):
1.59
1.60 @@ -196,6 +196,14 @@
1.61 heading.end_extra = self.read_match(3)
1.62 raise StopIteration
1.63
1.64 + def parse_list(self, item):
1.65 +
1.66 + "Create a list, starting with 'item'."
1.67 +
1.68 + list = List([item], item.indent, item.marker)
1.69 + self.parse_region_details(list, self.list_pattern_names, True)
1.70 + return list
1.71 +
1.72 def parse_listitem(self, region):
1.73
1.74 "Handle a list item marker within 'region'."
1.75 @@ -203,10 +211,32 @@
1.76 indent = len(self.read_match(1))
1.77 marker = self.read_match(2)
1.78 space = self.read_match(3)
1.79 +
1.80 item = ListItem([], indent, marker, space)
1.81 self.parse_region_details(item, self.listitem_pattern_names)
1.82 - region.add(item)
1.83 - new_block(region)
1.84 +
1.85 + last = region.node(-1)
1.86 +
1.87 + # Start a new list if not preceded by a list item.
1.88 +
1.89 + if not isinstance(last, ListItem):
1.90 + item = self.parse_list(item)
1.91 +
1.92 + # End the current list if the indent or marker is different from the
1.93 + # last list item.
1.94 +
1.95 + elif last.indent != indent or last.marker != marker:
1.96 +
1.97 + # Queue the new list, end this list, causing the new list to be
1.98 + # added after this one.
1.99 +
1.100 + self.queue_region(self.parse_list(item), region)
1.101 + self.end_region(region)
1.102 +
1.103 + # Add a new item in a list or a completed nested list.
1.104 +
1.105 + self.add_node(region, item)
1.106 + self.new_block(region)
1.107
1.108 def parse_rule(self, region):
1.109
1.110 @@ -214,8 +244,8 @@
1.111
1.112 length = len(self.read_match(1))
1.113 rule = Rule(length)
1.114 - region.add(rule)
1.115 - new_block(region)
1.116 + self.add_node(region, rule)
1.117 + self.new_block(region)
1.118
1.119 def parse_section(self, region):
1.120
1.121 @@ -225,8 +255,8 @@
1.122
1.123 indent = len(self.read_match(2))
1.124 level = len(self.read_match(3))
1.125 - region.add(self.parse_region(level, indent))
1.126 - new_block(region)
1.127 + self.add_node(region, self.parse_region(level, indent))
1.128 + self.new_block(region)
1.129
1.130 def parse_section_end(self, region):
1.131
1.132 @@ -307,7 +337,7 @@
1.133 region.append_inline(Text(serialise(cell)))
1.134 region.append_inline(Text(trailing))
1.135
1.136 - new_block(region)
1.137 + self.new_block(region)
1.138 return
1.139
1.140 # Append the final cell, if not empty.
1.141 @@ -327,9 +357,9 @@
1.142
1.143 table.add(row)
1.144 if new_table:
1.145 - region.add(new_table)
1.146 + self.add_node(region, new_table)
1.147
1.148 - new_block(region)
1.149 + self.new_block(region)
1.150
1.151 def parse_valign(self, attrs):
1.152
1.153 @@ -483,11 +513,15 @@
1.154 "fontstyle", "larger", "monospace", "smaller", "sub", "super", "underline",
1.155 ]
1.156
1.157 + list_pattern_names = [
1.158 + "listitem", "listitem_alpha", "listitem_dot", "listitem_num",
1.159 + "listitem_roman",
1.160 + ]
1.161 +
1.162 listitem_pattern_names = inline_pattern_names + ["listitemend"]
1.163
1.164 - region_pattern_names = inline_pattern_names + [
1.165 - "break", "heading", "defterm", "defterm_empty", "listitem",
1.166 - "listitem_alpha", "listitem_dot", "listitem_num", "listitem_roman",
1.167 + region_pattern_names = inline_pattern_names + list_pattern_names + [
1.168 + "break", "heading", "defterm", "defterm_empty",
1.169 "regionstart", "regionend", "rule", "tablerow",
1.170 ]
1.171