# HG changeset patch # User Paul Boddie # Date 1533654386 -7200 # Node ID f54f64f11d3a59559e3f39981c155d6f12488c97 # Parent f360a1d0929a5def7e6c7a2688b1073a1f2a3f59 Added support for comments and region directives. diff -r f360a1d0929a -r f54f64f11d3a moinformat/parsers/common.py --- a/moinformat/parsers/common.py Tue Aug 07 17:05:58 2018 +0200 +++ b/moinformat/parsers/common.py Tue Aug 07 17:06:26 2018 +0200 @@ -348,9 +348,11 @@ region = Region([], level, indent, type) - # Parse section headers, then parse according to region type. + # Parse section headers and directives, then parse according to region + # type. self.parse_region_header(region) + self.parse_region_directives(region) self.parse_region_type(region) return region @@ -379,6 +381,30 @@ region.args = self.match_group("args") region.type = region.args.split(" ", 1)[0] + def parse_region_directives(self, region): + + """ + Parse any directives immediately after the region header, adding them to + the 'region' object. + """ + + while True: + preceding = self.read_until(["directive"], False) + + # With an immediately-appearing directive, handle its details. + + if preceding == "": + handler = self.handlers.get(self.matching_pattern()) + if handler: + handler(self, region) + else: + break + + # Otherwise, with no immediate directive (or none at all), stop. + + else: + break + # Parsing utilities. def parse_region_details(self, region, pattern_names, strict=False): diff -r f360a1d0929a -r f54f64f11d3a moinformat/parsers/moin.py --- a/moinformat/parsers/moin.py Tue Aug 07 17:05:58 2018 +0200 +++ b/moinformat/parsers/moin.py Tue Aug 07 17:06:26 2018 +0200 @@ -35,12 +35,13 @@ # Document tree nodes. -from moinformat.tree.moin import Anchor, Break, DefItem, DefTerm, FontStyle, \ - Heading, Larger, LineBreak, Link, List, \ - ListItem, Macro, Monospace, Region, Rule, \ - Smaller, Strikethrough, Subscript, \ - Superscript, Table, TableAttr, TableAttrs, \ - TableCell, TableRow, Text, Underline +from moinformat.tree.moin import Anchor, Break, Comment, DefItem, DefTerm, \ + Directive, FontStyle, Heading, Larger, \ + LineBreak, Link, List, ListItem, Macro, \ + Monospace, Region, Rule, Smaller, \ + Strikethrough, Subscript, Superscript, Table, \ + TableAttr, TableAttrs, TableCell, TableRow, \ + Text, Underline join = "".join @@ -85,9 +86,10 @@ self.items = self.get_items(s) self.region = Region([], type="moin") - # Parse page header. + # Parse page header and directives. self.parse_region_header(self.region) + self.parse_region_directives(self.region) # Handle pages directly with this parser. Pages do not need to use an # explicit format indicator. @@ -170,6 +172,15 @@ self.add_node(region, Break()) self.new_block(region) + def parse_comment(self, region): + + "Handle a comment within 'region'." + + comment = self.match_group("comment") + extra = self.match_group("extra") + self.add_node(region, Comment(comment, extra)) + self.new_block(region) + def parse_defitem(self, region, extra=""): "Handle a definition item within 'region'." @@ -205,6 +216,15 @@ self.parse_region_details(region, ["deftermsep"]) self.parse_defitem(region, extra) + def parse_directive(self, region): + + "Handle a processing directive within 'region'." + + directive = self.match_group("directive") + extra = self.match_group("extra") + self.add_node(region, Directive(directive, extra)) + self.new_block(region) + def parse_fontstyle(self, region): "Handle emphasis and strong styles." @@ -581,12 +601,17 @@ "regionend" : join((r"\N*", # ws... (optional) group("feature", join(( group("level", repeat("[}]", 3)), # }}}... - group("extra", r"\n"), - "?"))))), # nl (optional) + optional(group("extra", r"\n"))))))), # nl (optional) + + # Region header and directives: "header" : join(("#!", # #! group("args", ".*?"), "\n")), # text-excl-nl + "directive" : join((r"^#", # # + group("directive", r".*?$"), # rest of line + optional(group("extra", r"\n")))), # nl (optional) + # Region contents: # Line-oriented patterns support features which require their own @@ -594,6 +619,10 @@ "break" : r"^(\s*?)\n", # blank line + "comment" : join((r"^##", # ## + group("comment", r".*?$"), # rest of line + optional(group("extra", r"\n")))), # nl (optional) + "defterm" : join(("^", group("pad", r"\N+"), # ws... expect(".+?::"))), # text :: @@ -772,7 +801,7 @@ listitem_pattern_names = inline_pattern_names + ["listitemend"] region_without_table_pattern_names = inline_pattern_names + list_pattern_names + [ - "break", "heading", "defterm", "defterm_empty", + "break", "comment", "heading", "defterm", "defterm_empty", "regionend", "rule", ] @@ -799,10 +828,12 @@ "break" : parse_break, "colour" : parse_colour, "colspan" : parse_colspan, + "comment" : parse_comment, "defterm" : parse_defterm, "defterm_empty" : parse_defterm_empty, "deftermend" : end_region, "deftermsep" : end_region, + "directive" : parse_directive, "fontstyle" : parse_fontstyle, "halign" : parse_halign, "heading" : parse_heading, diff -r f360a1d0929a -r f54f64f11d3a moinformat/serialisers/html/moin.py --- a/moinformat/serialisers/html/moin.py Tue Aug 07 17:05:58 2018 +0200 +++ b/moinformat/serialisers/html/moin.py Tue Aug 07 17:06:26 2018 +0200 @@ -253,6 +253,12 @@ def break_(self): pass + def comment(self, comment, extra): + pass + + def directive(self, directive, extra): + pass + def linebreak(self): self.out("
") diff -r f360a1d0929a -r f54f64f11d3a moinformat/serialisers/moin/moin.py --- a/moinformat/serialisers/moin/moin.py Tue Aug 07 17:05:58 2018 +0200 +++ b/moinformat/serialisers/moin/moin.py Tue Aug 07 17:06:26 2018 +0200 @@ -185,6 +185,12 @@ def break_(self): self.out("\n") + def comment(self, comment, extra): + self.out("##%s%s" % (comment, extra)) + + def directive(self, directive, extra): + self.out("#%s%s" % (directive, extra)) + def linebreak(self): self.out(r"\\") diff -r f360a1d0929a -r f54f64f11d3a moinformat/tree/moin.py --- a/moinformat/tree/moin.py Tue Aug 07 17:05:58 2018 +0200 +++ b/moinformat/tree/moin.py Tue Aug 07 17:06:26 2018 +0200 @@ -621,6 +621,40 @@ def to_string(self, out): out.break_() +class Comment(Node): + + "A comment." + + def __init__(self, comment, extra): + self.comment = comment + self.extra = extra + + def __repr__(self): + return "Comment(%r, %r)" % (self.comment, self.extra) + + def prettyprint(self, indent=""): + return "%sComment: comment=%r extra=%r" % (indent, self.comment, self.extra) + + def to_string(self, out): + out.comment(self.comment, self.extra) + +class Directive(Node): + + "A processing directive." + + def __init__(self, directive, extra): + self.directive = directive + self.extra = extra + + def __repr__(self): + return "Directive(%r, %r)" % (self.directive, self.extra) + + def prettyprint(self, indent=""): + return "%sDirective: directive=%r extra=%r" % (indent, self.directive, self.extra) + + def to_string(self, out): + out.directive(self.directive, self.extra) + class LineBreak(Node): "A line break within a block." diff -r f360a1d0929a -r f54f64f11d3a tests/test_directives.tree --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_directives.tree Tue Aug 07 17:06:26 2018 +0200 @@ -0,0 +1,20 @@ +Region + Directive + Directive + Block + Text + Break + Region + Directive + Break + Block + Text + Comment + Block + Break + Region + Directive + Directive + Block + Text + Block diff -r f360a1d0929a -r f54f64f11d3a tests/test_directives.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_directives.txt Tue Aug 07 17:06:26 2018 +0200 @@ -0,0 +1,17 @@ +#language en_GB +# A directive +Hello +# Visible non-comment + +{{{{#!wiki +## A comment + +# Visible non-comment +### Another comment +}}}} + +{{{#!wiki +# A directive +## A comment +Goodbye +}}}