# HG changeset patch # User Paul Boddie # Date 1531604250 -7200 # Node ID 24e8cc2a2a1ecdcd864d1558e52e6a8ca15789cb # Parent 21bc17cf10003d91dec54da2b4cffb5ea0c07098 Attempt to add support for inline regions, relaxing the region patterns. diff -r 21bc17cf1000 -r 24e8cc2a2a1e moinformat/parsers/common.py --- a/moinformat/parsers/common.py Sat Jul 14 16:17:36 2018 +0200 +++ b/moinformat/parsers/common.py Sat Jul 14 23:37:30 2018 +0200 @@ -256,14 +256,14 @@ # Top-level parser handler methods. - def parse_region(self, level=0, indent=0): + def parse_region(self, level=0, indent=0, type=None): """ Parse the data to populate a region with the given 'level' at the given - 'indent'. + 'indent' having the given initial 'type'. """ - region = Region([], level, indent) + region = Region([], level, indent, type) # Parse section headers, then parse according to region type. @@ -278,6 +278,12 @@ Use configured parsers to parse 'region' based on its type. """ + # Handle potentially inline regions. + + if region.type == "inline": + self.parse_region_inline(region) + return + # Find an appropriate parser given the type. parser = self.get_parser(region.type) @@ -306,6 +312,20 @@ region.transparent = False self.parse_region_details(region, ["regionend"]) + def parse_region_inline(self, region): + + "Parse the data to populate an inline 'region'." + + region.transparent = False + self.parse_region_details(region, ["regionend"]) + + # Reset the type if the region was not inline. + + if region.type == "inline": + first = region.nodes and region.nodes[0] + if first and isinstance(first, Text) and first.multiline(): + region.type = None + # Parsing utilities. def parse_region_details(self, region, pattern_names, strict=False): diff -r 21bc17cf1000 -r 24e8cc2a2a1e moinformat/parsers/moin.py --- a/moinformat/parsers/moin.py Sat Jul 14 16:17:36 2018 +0200 +++ b/moinformat/parsers/moin.py Sat Jul 14 23:37:30 2018 +0200 @@ -55,7 +55,7 @@ """ self.items = self.get_items(s) - self.region = Region([]) + self.region = Region([], type="moin") # Parse page header. @@ -278,7 +278,7 @@ indent = len(self.read_match(2)) level = len(self.read_match(3)) - self.add_node(region, self.parse_region(level, indent)) + self.add_node(region, self.parse_region(level, indent, "inline")) self.new_block(region) def parse_section_end(self, region): @@ -459,8 +459,8 @@ syntax = { # Page regions: - "regionstart" : r"((^\N*)([{]{3,}))", # {{{... - "regionend" : r"^\N*([}]{3,})", # }}}... + "regionstart" : r"((\N*)([{]{3,}))", # [line-start ws] {{{... + "regionend" : r"(?:\N*)([}]{3,})", # [line-start ws] }}}... "header" : r"#!(.*?)\n", # #! char-excl-nl # Region contents: @@ -547,8 +547,8 @@ ] inline_pattern_names = [ - "fontstyle", "larger", "link", "monospace", "smaller", "strike", "sub", - "super", "underline", + "fontstyle", "larger", "link", "monospace", "regionstart", "smaller", + "strike", "sub", "super", "underline", ] list_pattern_names = [ diff -r 21bc17cf1000 -r 24e8cc2a2a1e moinformat/serialisers/html.py --- a/moinformat/serialisers/html.py Sat Jul 14 16:17:36 2018 +0200 +++ b/moinformat/serialisers/html.py Sat Jul 14 23:37:30 2018 +0200 @@ -25,6 +25,19 @@ "Serialisation of the page." + def _region_tag(self, type): + + # NOTE: Need to support types in general. + + type = type.split()[0] + + if type == "inline": + return "tt" + elif type in (None, "python"): + return "pre" + else: + return "span" + def start_region(self, level, indent, type): l = [] out = l.append @@ -36,13 +49,14 @@ # NOTE: Encode type details for CSS. - if type: - out("type-%s" % escape_attr(type)) + out("type-%s" % escape_attr(type or "opaque")) - self.out("" % " ".join(l)) + tag = self._region_tag(type) + self.out("<%s class='%s'>" % (tag, " ".join(l))) def end_region(self, level, indent, type): - self.out("") + tag = self._region_tag(type) + self.out("" % tag) def start_block(self): self.out("

") diff -r 21bc17cf1000 -r 24e8cc2a2a1e moinformat/serialisers/moin.py --- a/moinformat/serialisers/moin.py Sat Jul 14 16:17:36 2018 +0200 +++ b/moinformat/serialisers/moin.py Sat Jul 14 23:37:30 2018 +0200 @@ -29,7 +29,10 @@ out = self.out if level: out(" " * indent + "{" * level) - if type and level: + + # Produce a header for regions within a top-level region. + + if type and type != "inline" and level: out("#!%s\n" % type) def end_region(self, level, indent, type): diff -r 21bc17cf1000 -r 24e8cc2a2a1e moinformat/tree.py --- a/moinformat/tree.py Sat Jul 14 16:17:36 2018 +0200 +++ b/moinformat/tree.py Sat Jul 14 23:37:30 2018 +0200 @@ -552,6 +552,9 @@ def empty(self): return not self.s + def multiline(self): + return "\n" in self.s + def merge(self, text): self.s += text.s diff -r 21bc17cf1000 -r 24e8cc2a2a1e tests/test3.txt --- a/tests/test3.txt Sat Jul 14 16:17:36 2018 +0200 +++ b/tests/test3.txt Sat Jul 14 23:37:30 2018 +0200 @@ -3,8 +3,12 @@ i. Romanus eunt domus! I. What did they do for us? + I. {{{Did for us}}} 1. {{{ -Doing for us}}} +Doing ''for'' us}}} + 1. {{{#!python +motto = "Romanus eunt domus!" +}}} a.#18 The Romans. 1. Starting from one