1.1 --- a/moinformat/metadata.py Fri Jun 30 00:37:36 2023 +0200
1.2 +++ b/moinformat/metadata.py Fri Jun 30 00:40:39 2023 +0200
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Metadata for document conversion.
1.6
1.7 -Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2018, 2019, 2021, 2023 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -43,13 +43,13 @@
1.13 }
1.14
1.15 effects = {
1.16 - "input_context" : "input",
1.17 - "input_format" : "parser",
1.18 - "input_separator" : "input",
1.19 - "link_format" : "linker",
1.20 - "output_context" : "output",
1.21 - "output_format" : "serialiser",
1.22 - "theme_name" : "theme",
1.23 + "input_context" : ["input"],
1.24 + "input_format" : ["parser", "serialiser"],
1.25 + "input_separator" : ["input"],
1.26 + "link_format" : ["linker"],
1.27 + "output_context" : ["output"],
1.28 + "output_format" : ["serialiser"],
1.29 + "theme_name" : ["theme"],
1.30 }
1.31
1.32 def __init__(self, parameters=None):
1.33 @@ -92,12 +92,14 @@
1.34
1.35 self.parameters[name] = value
1.36
1.37 - # Invalidate any affected setting.
1.38 + # Invalidate any affected settings.
1.39
1.40 affected = self.effects.get(name)
1.41
1.42 - if affected and self.has_key(affected):
1.43 - del self.parameters[affected]
1.44 + if affected:
1.45 + for affected_name in affected:
1.46 + if self.has_key(affected_name):
1.47 + del self.parameters[affected_name]
1.48
1.49 # Set any default values.
1.50
1.51 @@ -106,36 +108,43 @@
1.52 if affected and not self.get(affected):
1.53 self.set(affected, value)
1.54
1.55 - def make_object(self, name, fn, typename, typevalue=None):
1.56 + def get_update(self, name, value=None):
1.57
1.58 """
1.59 - Make an object to be stored in the setting 'name', using 'fn' to
1.60 - acquire the object class, with the object type being retrieved from the
1.61 - 'typename' setting, this being overwritten by 'typevalue' if specified.
1.62 - Return None if no class is obtained.
1.63 + Obtain the 'name' setting, this being overwritten by 'value' if
1.64 + specified. Return the updated setting.
1.65 """
1.66
1.67 - # Return any existing object if not reset.
1.68 + # Overwrite any existing setting.
1.69
1.70 - if not typevalue:
1.71 - obj = self.get(name)
1.72 - if obj:
1.73 - return obj
1.74 + if value:
1.75 + self.set(name, value)
1.76 + return value
1.77 + else:
1.78 + return self.get(name)
1.79 +
1.80 + def make_object(self, name, cls):
1.81
1.82 - # Overwrite any existing typename setting.
1.83 + """
1.84 + Make an object to be stored in the setting 'name', using 'cls' as the
1.85 + object class.
1.86 + """
1.87
1.88 - else:
1.89 - self.set(typename, typevalue)
1.90 + # Return any existing, preserved object. Since updates to various
1.91 + # properties will discard objects, any preserved object should still be
1.92 + # applicable.
1.93
1.94 - # Obtain the class.
1.95 + obj = self.get(name)
1.96 + if obj:
1.97 + return obj
1.98
1.99 - cls = fn(self.get(typename))
1.100 + # Without any object class, return None.
1.101
1.102 if not cls:
1.103 self.set(name, None)
1.104 return None
1.105
1.106 - # Instantiate the class.
1.107 + # Instantiate the class and record the object.
1.108
1.109 obj = cls(self)
1.110 self.set(name, obj)
1.111 @@ -148,7 +157,9 @@
1.112 "input_context" setting which will be replaced by any given 'name'.
1.113 """
1.114
1.115 - return self.make_object("input", get_input, "input_context", name)
1.116 + cls = get_input(self.get_update("input_context", name))
1.117 +
1.118 + return self.make_object("input", cls)
1.119
1.120 def get_linker(self, name=None):
1.121
1.122 @@ -157,7 +168,9 @@
1.123 "link_format" setting which will be replaced by any given 'name'.
1.124 """
1.125
1.126 - return self.make_object("linker", get_linker, "link_format", name)
1.127 + cls = get_linker(self.get_update("link_format", name))
1.128 +
1.129 + return self.make_object("linker", cls)
1.130
1.131 def get_output(self, name=None):
1.132
1.133 @@ -166,7 +179,9 @@
1.134 "output_context" setting which will be replaced by any given 'name'.
1.135 """
1.136
1.137 - return self.make_object("output", get_output, "output_context", name)
1.138 + cls = get_output(self.get_update("output_context", name))
1.139 +
1.140 + return self.make_object("output", cls)
1.141
1.142 def get_parser(self, name=None):
1.143
1.144 @@ -175,7 +190,9 @@
1.145 "input_format" setting which will be replaced by any given 'name'.
1.146 """
1.147
1.148 - parser = self.make_object("parser", get_parser, "input_format", name)
1.149 + cls = get_parser(self.get_update("input_format", name))
1.150 +
1.151 + parser = self.make_object("parser", cls)
1.152 parser.parsers = parsers
1.153 return parser
1.154
1.155 @@ -186,8 +203,10 @@
1.156 "output_format" setting which will be replaced by any given 'name'.
1.157 """
1.158
1.159 - serialiser = self.make_object("serialiser", get_serialiser,
1.160 - "output_format", name)
1.161 + cls = get_serialiser(self.get_update("output_format", name),
1.162 + self.get("input_format"))
1.163 +
1.164 + serialiser = self.make_object("serialiser", cls)
1.165 serialiser.serialisers = serialisers
1.166 return serialiser
1.167
1.168 @@ -198,6 +217,8 @@
1.169 setting which will be replaced by any given 'name'.
1.170 """
1.171
1.172 - return self.make_object("theme", get_theme, "theme_name", name)
1.173 + cls = get_theme(self.get_update("theme_name", name))
1.174 +
1.175 + return self.make_object("theme", cls)
1.176
1.177 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/moinformat/output/common.py Fri Jun 30 00:37:36 2023 +0200
2.2 +++ b/moinformat/output/common.py Fri Jun 30 00:40:39 2023 +0200
2.3 @@ -3,7 +3,7 @@
2.4 """
2.5 Output context common functionality.
2.6
2.7 -Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
2.8 +Copyright (C) 2018, 2023 Paul Boddie <paul@boddie.org.uk>
2.9
2.10 This program is free software; you can redistribute it and/or modify it under
2.11 the terms of the GNU General Public License as published by the Free Software
2.12 @@ -40,9 +40,10 @@
2.13
2.14 def reset(self):
2.15
2.16 - "Set up an output collector."
2.17 + "Set up an output collector and output state."
2.18
2.19 self.output = []
2.20 + self.indent = ""
2.21
2.22 def encode(self, text):
2.23
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/moinformat/parsers/pretty.py Fri Jun 30 00:40:39 2023 +0200
3.3 @@ -0,0 +1,78 @@
3.4 +#!/usr/bin/env python
3.5 +
3.6 +"""
3.7 +Prettyprinted document tree parser.
3.8 +
3.9 +Copyright (C) 2017, 2018, 2019, 2023 Paul Boddie <paul@boddie.org.uk>
3.10 +
3.11 +This program is free software; you can redistribute it and/or modify it under
3.12 +the terms of the GNU General Public License as published by the Free Software
3.13 +Foundation; either version 3 of the License, or (at your option) any later
3.14 +version.
3.15 +
3.16 +This program is distributed in the hope that it will be useful, but WITHOUT
3.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3.19 +details.
3.20 +
3.21 +You should have received a copy of the GNU General Public License along with
3.22 +this program. If not, see <http://www.gnu.org/licenses/>.
3.23 +"""
3.24 +
3.25 +from moinformat.tree.pretty import Node
3.26 +
3.27 +class PrettyParser:
3.28 +
3.29 + "A prettyprinted document tree parser."
3.30 +
3.31 + formats = ["pretty"]
3.32 +
3.33 + def __init__(self, metadata):
3.34 + self.metadata = metadata
3.35 +
3.36 + def parse(self, s):
3.37 +
3.38 + "Parse the tree structure representation in 's'."
3.39 +
3.40 + indent = 0
3.41 + branches = []
3.42 +
3.43 + for line in s.split("\n"):
3.44 + line = line.rstrip()
3.45 + if not line:
3.46 + continue
3.47 +
3.48 + new_indent = line.rfind(" ") + 1
3.49 + node = Node(line[new_indent:])
3.50 +
3.51 + # Establish a branch to add nodes to.
3.52 +
3.53 + if not branches:
3.54 + branches.append(node)
3.55 + else:
3.56 + # Note the current node as outermost branch.
3.57 +
3.58 + if new_indent > indent:
3.59 + branches.append(node)
3.60 + else:
3.61 + # Reduced indent involves obtaining an inner branch again.
3.62 +
3.63 + while indent > new_indent:
3.64 + del branches[-1]
3.65 + indent -= 2
3.66 +
3.67 + # Note the current node as outermost branch.
3.68 +
3.69 + branches[-1] = node
3.70 +
3.71 + # Append the current node to the parent branch.
3.72 +
3.73 + branches[-2].append(node)
3.74 +
3.75 + indent = new_indent
3.76 +
3.77 + return branches[0]
3.78 +
3.79 +parser = PrettyParser
3.80 +
3.81 +# vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/moinformat/serialisers/__init__.py Fri Jun 30 00:37:36 2023 +0200
4.2 +++ b/moinformat/serialisers/__init__.py Fri Jun 30 00:40:39 2023 +0200
4.3 @@ -23,11 +23,15 @@
4.4
4.5 # Top-level functions.
4.6
4.7 -def get_serialiser(name):
4.8 +def get_serialiser(name, doctype=None):
4.9
4.10 - "Return the main serialiser class for the format having the given 'name'."
4.11 + """
4.12 + Return the main serialiser class for the format having the given 'name'.
4.13 + If 'doctype' is indicated, obtain a serialiser class specific to that
4.14 + document type. Otherwise, a general Moin serialiser class is obtained.
4.15 + """
4.16
4.17 - return serialisers["%s.moin" % name]
4.18 + return serialisers["%s.%s" % (name, doctype or "moin")]
4.19
4.20 def make_serialiser(metadata, format=None):
4.21
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/moinformat/serialisers/pretty/__init__.py Fri Jun 30 00:40:39 2023 +0200
5.3 @@ -0,0 +1,22 @@
5.4 +#!/usr/bin/env python
5.5 +
5.6 +"""
5.7 +A package of modules containing prettyprinting serialisers.
5.8 +
5.9 +Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
5.10 +
5.11 +This program is free software; you can redistribute it and/or modify it under
5.12 +the terms of the GNU General Public License as published by the Free Software
5.13 +Foundation; either version 3 of the License, or (at your option) any later
5.14 +version.
5.15 +
5.16 +This program is distributed in the hope that it will be useful, but WITHOUT
5.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
5.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
5.19 +details.
5.20 +
5.21 +You should have received a copy of the GNU General Public License along with
5.22 +this program. If not, see <http://www.gnu.org/licenses/>.
5.23 +"""
5.24 +
5.25 +# vim: tabstop=4 expandtab shiftwidth=4
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/moinformat/serialisers/pretty/common.py Fri Jun 30 00:40:39 2023 +0200
6.3 @@ -0,0 +1,38 @@
6.4 +#!/usr/bin/env python
6.5 +
6.6 +"""
6.7 +Generic prettyprinted text serialiser.
6.8 +
6.9 +Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
6.10 +
6.11 +This program is free software; you can redistribute it and/or modify it under
6.12 +the terms of the GNU General Public License as published by the Free Software
6.13 +Foundation; either version 3 of the License, or (at your option) any later
6.14 +version.
6.15 +
6.16 +This program is distributed in the hope that it will be useful, but WITHOUT
6.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
6.19 +details.
6.20 +
6.21 +You should have received a copy of the GNU General Public License along with
6.22 +this program. If not, see <http://www.gnu.org/licenses/>.
6.23 +"""
6.24 +
6.25 +from moinformat.serialisers.common import Serialiser as CommonSerialiser
6.26 +
6.27 +class Serialiser(CommonSerialiser):
6.28 +
6.29 + "Serialisation of nodes for inspection."
6.30 +
6.31 + def container(self, container):
6.32 +
6.33 + "Visit all nodes in 'container'."
6.34 +
6.35 + if container.nodes:
6.36 + self.output.indent += " "
6.37 + for node in container.nodes:
6.38 + self.visit(node)
6.39 + self.output.indent = self.output.indent[:-2]
6.40 +
6.41 +# vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/moinformat/serialisers/pretty/graphviz.py Fri Jun 30 00:40:39 2023 +0200
7.3 @@ -0,0 +1,40 @@
7.4 +#!/usr/bin/env python
7.5 +
7.6 +"""
7.7 +Prettyprinted text serialiser for Graphviz nodes.
7.8 +
7.9 +Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
7.10 +
7.11 +This program is free software; you can redistribute it and/or modify it under
7.12 +the terms of the GNU General Public License as published by the Free Software
7.13 +Foundation; either version 3 of the License, or (at your option) any later
7.14 +version.
7.15 +
7.16 +This program is distributed in the hope that it will be useful, but WITHOUT
7.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
7.19 +details.
7.20 +
7.21 +You should have received a copy of the GNU General Public License along with
7.22 +this program. If not, see <http://www.gnu.org/licenses/>.
7.23 +"""
7.24 +
7.25 +from moinformat.serialisers.pretty.common import Serialiser
7.26 +
7.27 +class GraphvizSerialiser(Serialiser):
7.28 +
7.29 + "Serialisation of Graphviz nodes for inspection."
7.30 +
7.31 + input_formats = ["dot", "graphviz"]
7.32 + formats = ["pretty"]
7.33 +
7.34 + # Node handler methods.
7.35 +
7.36 + def directive(self, directive):
7.37 + self.out("%sDirective: key=%r value=%r directive=%r\n" % (
7.38 + self.output.indent, directive.key, directive.value,
7.39 + directive.directive))
7.40 +
7.41 +serialiser = GraphvizSerialiser
7.42 +
7.43 +# vim: tabstop=4 expandtab shiftwidth=4
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/moinformat/serialisers/pretty/moin.py Fri Jun 30 00:40:39 2023 +0200
8.3 @@ -0,0 +1,168 @@
8.4 +#!/usr/bin/env python
8.5 +
8.6 +"""
8.7 +Prettyprinted text serialiser for Moin nodes.
8.8 +
8.9 +Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
8.10 +
8.11 +This program is free software; you can redistribute it and/or modify it under
8.12 +the terms of the GNU General Public License as published by the Free Software
8.13 +Foundation; either version 3 of the License, or (at your option) any later
8.14 +version.
8.15 +
8.16 +This program is distributed in the hope that it will be useful, but WITHOUT
8.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
8.19 +details.
8.20 +
8.21 +You should have received a copy of the GNU General Public License along with
8.22 +this program. If not, see <http://www.gnu.org/licenses/>.
8.23 +"""
8.24 +
8.25 +from moinformat.serialisers.pretty.common import Serialiser
8.26 +
8.27 +class MoinSerialiser(Serialiser):
8.28 +
8.29 + "Serialisation of Moin nodes for inspection."
8.30 +
8.31 + input_formats = ["moin", "wiki"]
8.32 + formats = ["pretty"]
8.33 +
8.34 + # Node handler methods.
8.35 +
8.36 + def region(self, region):
8.37 + self.out("%sRegion: level=%d indent=%d type=%s args=%r extra=%r\n" % (
8.38 + self.output.indent, region.level, region.indent, region.type, region.args,
8.39 + region.extra))
8.40 + self.visit_region(region)
8.41 +
8.42 + # Block node methods.
8.43 +
8.44 + def block(self, block):
8.45 + self.out("%sBlock\n" % self.output.indent)
8.46 + self.container(block)
8.47 +
8.48 + def defitem(self, defitem):
8.49 + self.out("%sDefItem: pad=%r extra=%r\n" % (self.output.indent,
8.50 + defitem.pad, defitem.extra))
8.51 + self.container(defitem)
8.52 +
8.53 + def defterm(self, defterm):
8.54 + self.out("%sDefTerm: pad=%r extra=%r\n" % (self.output.indent,
8.55 + defterm.pad, defterm.extra))
8.56 + self.container(defterm)
8.57 +
8.58 + def fontstyle(self, fontstyle):
8.59 + self.out("%sFontStyle: emphasis=%r strong=%r\n" % (self.output.indent,
8.60 + fontstyle.emphasis, fontstyle.strong))
8.61 + self.container(fontstyle)
8.62 +
8.63 + def heading(self, heading):
8.64 + self.out("%sHeading: level=%d start_extra=%r start_pad=%r end_pad=%r"
8.65 + " end_extra=%r identifier=%r\n" % (
8.66 + self.output.indent, heading.level, heading.start_extra,
8.67 + heading.start_pad, heading.end_pad, heading.end_extra,
8.68 + heading.identifier))
8.69 + self.container(heading)
8.70 +
8.71 + def link_label(self, link_label):
8.72 + self.out("%sLinkLabel\n" % self.output.indent)
8.73 + self.container(link_label)
8.74 +
8.75 + def link_parameter(self, link_parameter):
8.76 + self.out("%sLinkParameter\n" % self.output.indent)
8.77 + self.container(link_parameter)
8.78 +
8.79 + def list(self, list):
8.80 + self.out("%sList: indent=%r marker=%r num=%r\n" % (
8.81 + self.output.indent, list.indent, list.marker, list.num))
8.82 + self.container(list)
8.83 +
8.84 + def listitem(self, listitem):
8.85 + self.out("%sListItem: indent=%d marker=%r space=%r num=%r\n" % (
8.86 + self.output.indent, listitem.indent, listitem.marker, listitem.space, listitem.num))
8.87 + self.container(listitem)
8.88 +
8.89 + def table(self, table):
8.90 + self.out("%sTable:\n" % self.output.indent)
8.91 + self.container(table)
8.92 +
8.93 + def table_attrs(self, table_attrs):
8.94 + self.out("%sTableAttrs:\n" % self.output.indent)
8.95 + self.container(table_attrs)
8.96 +
8.97 + def table_cell(self, table_cell):
8.98 + self.out("%sTableCell: leading=%r padding=%r\n" % (
8.99 + self.output.indent, table_cell.leading, table_cell.padding))
8.100 + self.container(table_cell)
8.101 +
8.102 + def table_row(self, table_row):
8.103 + self.out("%sTableRow: trailing=%r leading=%r padding=%r\n" % (
8.104 + self.output.indent, table_row.trailing, table_row.leading,
8.105 + table_row.padding))
8.106 + self.container(table_row)
8.107 +
8.108 + def inline(self, inline):
8.109 + self.out("%s%s\n" % (self.output.indent, inline.__class__.__name__))
8.110 +
8.111 + # Inline nodes with children.
8.112 +
8.113 + def inline_container(self, inline):
8.114 + self.inline(inline)
8.115 + self.container(inline)
8.116 +
8.117 + larger = inline_container
8.118 +
8.119 + def link(self, link):
8.120 + self.out("%sLink: target=%r\n" % (self.output.indent, link.target))
8.121 + self.container(link)
8.122 +
8.123 + def macro(self, macro):
8.124 + self.out("%sMacro: name=%r args=%r\n" % (self.output.indent, macro.name, macro.args))
8.125 + self.container(macro)
8.126 +
8.127 + monospace = inline_container
8.128 + smaller = inline_container
8.129 + strikethrough = inline_container
8.130 + subscript = inline_container
8.131 + superscript = inline_container
8.132 +
8.133 + def transclusion(self, transclusion):
8.134 + self.out("%sTransclusion: target=%r\n" % (self.output.indent, transclusion.target))
8.135 + self.container(transclusion)
8.136 +
8.137 + underline = inline_container
8.138 +
8.139 + # Inline nodes without children.
8.140 +
8.141 + def anchor(self, anchor):
8.142 + self.out("%sAnchor: target=%r\n" % (self.output.indent, anchor.target))
8.143 +
8.144 + break_ = inline
8.145 +
8.146 + def comment(self, comment):
8.147 + self.out("%sComment: comment=%r extra=%r\n" % (self.output.indent, comment.comment, comment.extra))
8.148 +
8.149 + def directive(self, directive):
8.150 + self.out("%sDirective: directive=%r extra=%r\n" % (self.output.indent, directive.directive, directive.extra))
8.151 +
8.152 + linebreak = inline
8.153 + nbsp = inline
8.154 +
8.155 + def rule(self, rule):
8.156 + self.out("%sRule: height=%d\n" % (self.output.indent, rule.height))
8.157 +
8.158 + def table_attr(self, table_attr):
8.159 + self.out("%sTableAttr: name=%r value=%r concise=%r quote=%r\n" % (
8.160 + self.output.indent, table_attr.name, table_attr.value,
8.161 + table_attr.concise, table_attr.quote))
8.162 +
8.163 + def text(self, text):
8.164 + self.out("%sText: %r\n" % (self.output.indent, text.s))
8.165 +
8.166 + def verbatim(self, verbatim):
8.167 + self.out("%sVerbatim: text=%r\n" % (self.output.indent, verbatim.text))
8.168 +
8.169 +serialiser = MoinSerialiser
8.170 +
8.171 +# vim: tabstop=4 expandtab shiftwidth=4
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/moinformat/serialisers/pretty/pretty.py Fri Jun 30 00:40:39 2023 +0200
9.3 @@ -0,0 +1,38 @@
9.4 +#!/usr/bin/env python
9.5 +
9.6 +"""
9.7 +Prettyprinted document node prettyprinter.
9.8 +
9.9 +Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
9.10 +
9.11 +This program is free software; you can redistribute it and/or modify it under
9.12 +the terms of the GNU General Public License as published by the Free Software
9.13 +Foundation; either version 3 of the License, or (at your option) any later
9.14 +version.
9.15 +
9.16 +This program is distributed in the hope that it will be useful, but WITHOUT
9.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
9.19 +details.
9.20 +
9.21 +You should have received a copy of the GNU General Public License along with
9.22 +this program. If not, see <http://www.gnu.org/licenses/>.
9.23 +"""
9.24 +
9.25 +from moinformat.serialisers.pretty.common import Serialiser
9.26 +
9.27 +class PrettySerialiser(Serialiser):
9.28 +
9.29 + "Serialisation of prettyprinted document nodes for inspection."
9.30 +
9.31 + input_formats = ["pretty"]
9.32 + formats = ["pretty"]
9.33 +
9.34 + def node(self, node):
9.35 + self.out("%s%s%s\n" % (self.output.indent, node.name,
9.36 + len(node.nodes) and " nodes=%d" % len(node.nodes) or ""))
9.37 + self.container(node)
9.38 +
9.39 +serialiser = PrettySerialiser
9.40 +
9.41 +# vim: tabstop=4 expandtab shiftwidth=4
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/moinformat/serialisers/pretty/table.py Fri Jun 30 00:40:39 2023 +0200
10.3 @@ -0,0 +1,35 @@
10.4 +#!/usr/bin/env python
10.5 +
10.6 +"""
10.7 +Moin wiki table prettyprinter.
10.8 +
10.9 +Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
10.10 +
10.11 +This program is free software; you can redistribute it and/or modify it under
10.12 +the terms of the GNU General Public License as published by the Free Software
10.13 +Foundation; either version 3 of the License, or (at your option) any later
10.14 +version.
10.15 +
10.16 +This program is distributed in the hope that it will be useful, but WITHOUT
10.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10.19 +details.
10.20 +
10.21 +You should have received a copy of the GNU General Public License along with
10.22 +this program. If not, see <http://www.gnu.org/licenses/>.
10.23 +"""
10.24 +
10.25 +from moinformat.serialisers.pretty.moin import MoinSerialiser
10.26 +
10.27 +class MoinTableSerialiser(MoinSerialiser):
10.28 +
10.29 + "Serialisation of table nodes for inspection."
10.30 +
10.31 + input_formats = ["table"]
10.32 +
10.33 + def continuation(self, continuation):
10.34 + self.out("%sContinuation: %r\n" % (self.output.indent, continuation.text))
10.35 +
10.36 +serialiser = MoinTableSerialiser
10.37 +
10.38 +# vim: tabstop=4 expandtab shiftwidth=4
11.1 --- a/moinformat/tree/graphviz.py Fri Jun 30 00:37:36 2023 +0200
11.2 +++ b/moinformat/tree/graphviz.py Fri Jun 30 00:40:39 2023 +0200
11.3 @@ -39,9 +39,6 @@
11.4 def __repr__(self):
11.5 return "Directive(%r, %r, %r)" % (self.key, self.value, self.directive)
11.6
11.7 - def prettyprint(self, indent=""):
11.8 - return "%sDirective: key=%r value=%r directive=%r" % (indent, self.key, self.value, self.directive)
11.9 -
11.10 def visit(self, visitor):
11.11 visitor.directive(self)
11.12
12.1 --- a/moinformat/tree/moin.py Fri Jun 30 00:37:36 2023 +0200
12.2 +++ b/moinformat/tree/moin.py Fri Jun 30 00:40:39 2023 +0200
12.3 @@ -175,14 +175,6 @@
12.4
12.5 return not self.text_content().strip()
12.6
12.7 - def __str__(self):
12.8 - return self.prettyprint()
12.9 -
12.10 - def _prettyprint(self, l, indent=""):
12.11 - for node in self.nodes:
12.12 - l.append(node.prettyprint(indent + " "))
12.13 - return "\n".join(l)
12.14 -
12.15 class Region(Container):
12.16
12.17 "A region of the page."
12.18 @@ -213,11 +205,6 @@
12.19 return "Region(%r, %r, %r, %r, %r, %r, %r)" % (self.nodes, self.level,
12.20 self.indent, self.type, self.args, self.transparent, self.extra)
12.21
12.22 - def prettyprint(self, indent=""):
12.23 - l = ["%sRegion: level=%d indent=%d type=%s args=%r extra=%r" % (indent,
12.24 - self.level, self.indent, self.type, self.args, self.extra)]
12.25 - return self._prettyprint(l, indent)
12.26 -
12.27 def visit(self, visitor):
12.28 visitor.region(self)
12.29
12.30 @@ -232,10 +219,6 @@
12.31 def __repr__(self):
12.32 return "Block(%r)" % self.nodes
12.33
12.34 - def prettyprint(self, indent=""):
12.35 - l = ["%sBlock" % indent]
12.36 - return self._prettyprint(l, indent)
12.37 -
12.38 def visit(self, visitor):
12.39 visitor.block(self)
12.40
12.41 @@ -251,10 +234,6 @@
12.42 def __repr__(self):
12.43 return "DefItem(%r, %r, %r)" % (self.nodes, self.pad, self.extra)
12.44
12.45 - def prettyprint(self, indent=""):
12.46 - l = ["%sDefItem: pad=%r extra=%r" % (indent, self.pad, self.extra)]
12.47 - return self._prettyprint(l, indent)
12.48 -
12.49 def visit(self, visitor):
12.50 visitor.defitem(self)
12.51
12.52 @@ -270,10 +249,6 @@
12.53 def __repr__(self):
12.54 return "DefTerm(%r, %r, %r)" % (self.nodes, self.pad, self.extra)
12.55
12.56 - def prettyprint(self, indent=""):
12.57 - l = ["%sDefTerm: pad=%r extra=%r" % (indent, self.pad, self.extra)]
12.58 - return self._prettyprint(l, indent)
12.59 -
12.60 def visit(self, visitor):
12.61 visitor.defterm(self)
12.62
12.63 @@ -303,10 +278,6 @@
12.64 def __repr__(self):
12.65 return "FontStyle(%r, %r, %r)" % (self.nodes, self.emphasis, self.strong)
12.66
12.67 - def prettyprint(self, indent=""):
12.68 - l = ["%sFontStyle: emphasis=%r strong=%r" % (indent, self.emphasis, self.strong)]
12.69 - return self._prettyprint(l, indent)
12.70 -
12.71 def visit(self, visitor):
12.72 visitor.fontstyle(self)
12.73
12.74 @@ -329,13 +300,6 @@
12.75 self.nodes, self.level, self.start_extra, self.start_pad,
12.76 self.end_pad, self.end_extra, self.identifier)
12.77
12.78 - def prettyprint(self, indent=""):
12.79 - l = ["%sHeading: level=%d start_extra=%r start_pad=%r end_pad=%r"
12.80 - " end_extra=%r identifier=%r" % (
12.81 - indent, self.level, self.start_extra, self.start_pad, self.end_pad,
12.82 - self.end_extra, self.identifier)]
12.83 - return self._prettyprint(l, indent)
12.84 -
12.85 def visit(self, visitor):
12.86 visitor.heading(self)
12.87
12.88 @@ -346,10 +310,6 @@
12.89 def __repr__(self):
12.90 return "LinkLabel(%r)" % self.nodes
12.91
12.92 - def prettyprint(self, indent=""):
12.93 - l = ["%sLinkLabel" % indent]
12.94 - return self._prettyprint(l, indent)
12.95 -
12.96 def visit(self, visitor):
12.97 visitor.link_label(self)
12.98
12.99 @@ -360,10 +320,6 @@
12.100 def __repr__(self):
12.101 return "LinkParameter(%r)" % self.nodes
12.102
12.103 - def prettyprint(self, indent=""):
12.104 - l = ["%sLinkParameter" % indent]
12.105 - return self._prettyprint(l, indent)
12.106 -
12.107 def visit(self, visitor):
12.108 visitor.link_parameter(self)
12.109
12.110 @@ -384,12 +340,6 @@
12.111 def __repr__(self):
12.112 return "List(%r)" % self.nodes
12.113
12.114 - def prettyprint(self, indent=""):
12.115 - if not self.first:
12.116 - self.init()
12.117 - l = ["%sList: indent=%r marker=%r num=%r" % (indent, self.indent, self.marker, self.num)]
12.118 - return self._prettyprint(l, indent)
12.119 -
12.120 def visit(self, visitor):
12.121 if not self.first:
12.122 self.init()
12.123 @@ -413,12 +363,18 @@
12.124 def __repr__(self):
12.125 return "ListItem(%r, %r, %r, %r, %r)" % (self.nodes, self.indent, self.marker, self.space, self.num)
12.126
12.127 - def prettyprint(self, indent=""):
12.128 - l = ["%sListItem: indent=%d marker=%r space=%r num=%r" % (indent, self.indent, self.marker, self.space, self.num)]
12.129 - return self._prettyprint(l, indent)
12.130 + def visit(self, visitor):
12.131 + visitor.listitem(self)
12.132 +
12.133 +class Table(Container):
12.134 +
12.135 + "A table."
12.136 +
12.137 + def __repr__(self):
12.138 + return "Table(%r)" % self.nodes
12.139
12.140 def visit(self, visitor):
12.141 - visitor.listitem(self)
12.142 + visitor.table(self)
12.143
12.144 class TableAttrs(Container):
12.145
12.146 @@ -436,27 +392,9 @@
12.147 def __repr__(self):
12.148 return "TableAttrs(%r)" % self.nodes
12.149
12.150 - def prettyprint(self, indent=""):
12.151 - l = ["%sTableAttrs:" % indent]
12.152 - return self._prettyprint(l, indent)
12.153 -
12.154 def visit(self, visitor):
12.155 visitor.table_attrs(self)
12.156
12.157 -class Table(Container):
12.158 -
12.159 - "A table."
12.160 -
12.161 - def __repr__(self):
12.162 - return "Table(%r)" % self.nodes
12.163 -
12.164 - def prettyprint(self, indent=""):
12.165 - l = ["%sTable:" % indent]
12.166 - return self._prettyprint(l, indent)
12.167 -
12.168 - def visit(self, visitor):
12.169 - visitor.table(self)
12.170 -
12.171 class TableCell(Container):
12.172
12.173 "A table cell."
12.174 @@ -471,11 +409,6 @@
12.175 return "TableCell(%r, %r, %r, %r)" % (self.nodes, self.attrs,
12.176 self.leading, self.padding)
12.177
12.178 - def prettyprint(self, indent=""):
12.179 - l = ["%sTableCell: leading=%r padding=%r" % (indent, self.leading,
12.180 - self.padding)]
12.181 - return self._prettyprint(l, indent)
12.182 -
12.183 def visit(self, visitor):
12.184 visitor.table_cell(self)
12.185
12.186 @@ -493,11 +426,6 @@
12.187 return "TableRow(%r, %r, %r, %r)" % (self.nodes, self.trailing,
12.188 self.leading, self.padding)
12.189
12.190 - def prettyprint(self, indent=""):
12.191 - l = ["%sTableRow: trailing=%r leading=%r padding=%r" % (
12.192 - indent, self.trailing, self.leading, self.padding)]
12.193 - return self._prettyprint(l, indent)
12.194 -
12.195 def visit(self, visitor):
12.196 visitor.table_row(self)
12.197
12.198 @@ -512,10 +440,6 @@
12.199 def __repr__(self):
12.200 return "%s(%r)" % (self.__class__.__name__, self.nodes)
12.201
12.202 - def prettyprint(self, indent=""):
12.203 - l = ["%s%s" % (indent, self.__class__.__name__)]
12.204 - return self._prettyprint(l, indent)
12.205 -
12.206 class Larger(Inline):
12.207
12.208 "Larger text."
12.209 @@ -534,10 +458,6 @@
12.210 def __repr__(self):
12.211 return "Link(%r, %r)" % (self.nodes, self.target)
12.212
12.213 - def prettyprint(self, indent=""):
12.214 - l = ["%sLink: target=%r" % (indent, self.target)]
12.215 - return self._prettyprint(l, indent)
12.216 -
12.217 def visit(self, visitor):
12.218 visitor.link(self)
12.219
12.220 @@ -558,10 +478,6 @@
12.221 self.parent, self.region,
12.222 self.nodes, self.inline)
12.223
12.224 - def prettyprint(self, indent=""):
12.225 - l = ["%sMacro: name=%r args=%r" % (indent, self.name, self.args)]
12.226 - return self._prettyprint(l, indent)
12.227 -
12.228 def visit(self, visitor):
12.229 visitor.macro(self)
12.230
12.231 @@ -611,10 +527,6 @@
12.232 def __repr__(self):
12.233 return "Transclusion(%r, %r)" % (self.nodes, self.target)
12.234
12.235 - def prettyprint(self, indent=""):
12.236 - l = ["%sTransclusion: target=%r" % (indent, self.target)]
12.237 - return self._prettyprint(l, indent)
12.238 -
12.239 def visit(self, visitor):
12.240 visitor.transclusion(self)
12.241
12.242 @@ -646,9 +558,6 @@
12.243 def __repr__(self):
12.244 return "Anchor(%r)" % self.target
12.245
12.246 - def prettyprint(self, indent=""):
12.247 - return "%sAnchor: target=%r" % (indent, self.target)
12.248 -
12.249 def visit(self, visitor):
12.250 visitor.anchor(self)
12.251
12.252 @@ -659,9 +568,6 @@
12.253 def __repr__(self):
12.254 return "Break()"
12.255
12.256 - def prettyprint(self, indent=""):
12.257 - return "%sBreak" % indent
12.258 -
12.259 def visit(self, visitor):
12.260 visitor.break_(self)
12.261
12.262 @@ -676,9 +582,6 @@
12.263 def __repr__(self):
12.264 return "Comment(%r, %r)" % (self.comment, self.extra)
12.265
12.266 - def prettyprint(self, indent=""):
12.267 - return "%sComment: comment=%r extra=%r" % (indent, self.comment, self.extra)
12.268 -
12.269 def visit(self, visitor):
12.270 visitor.comment(self)
12.271
12.272 @@ -693,9 +596,6 @@
12.273 def __repr__(self):
12.274 return "Directive(%r, %r)" % (self.directive, self.extra)
12.275
12.276 - def prettyprint(self, indent=""):
12.277 - return "%sDirective: directive=%r extra=%r" % (indent, self.directive, self.extra)
12.278 -
12.279 def visit(self, visitor):
12.280 visitor.directive(self)
12.281
12.282 @@ -706,9 +606,6 @@
12.283 def __repr__(self):
12.284 return "LineBreak()"
12.285
12.286 - def prettyprint(self, indent=""):
12.287 - return "%sLineBreak" % indent
12.288 -
12.289 def visit(self, visitor):
12.290 visitor.linebreak(self)
12.291
12.292 @@ -719,9 +616,6 @@
12.293 def __repr__(self):
12.294 return "NonBreakingSpace()"
12.295
12.296 - def prettyprint(self, indent=""):
12.297 - return "%sNonBreakingSpace" % indent
12.298 -
12.299 def visit(self, visitor):
12.300 visitor.nbsp(self)
12.301
12.302 @@ -735,9 +629,6 @@
12.303 def __repr__(self):
12.304 return "Rule(%d)" % self.height
12.305
12.306 - def prettyprint(self, indent=""):
12.307 - return "%sRule: height=%d" % (indent, self.height)
12.308 -
12.309 def visit(self, visitor):
12.310 visitor.rule(self)
12.311
12.312 @@ -754,9 +645,6 @@
12.313 def __repr__(self):
12.314 return "TableAttr(%r, %r, %r, %r)" % (self.name, self.value, self.concise, self.quote)
12.315
12.316 - def prettyprint(self, indent=""):
12.317 - return "%sTableAttr: name=%r value=%r concise=%r quote=%r" % (indent, self.name, self.value, self.concise, self.quote)
12.318 -
12.319 def visit(self, visitor):
12.320 visitor.table_attr(self)
12.321
12.322 @@ -779,9 +667,6 @@
12.323 def __repr__(self):
12.324 return "Text(%r)" % self.s
12.325
12.326 - def prettyprint(self, indent=""):
12.327 - return "%sText: %r" % (indent, self.s)
12.328 -
12.329 def visit(self, visitor):
12.330 visitor.text(self)
12.331
12.332 @@ -795,9 +680,6 @@
12.333 def __repr__(self):
12.334 return "Verbatim(%r)" % self.text
12.335
12.336 - def prettyprint(self, indent=""):
12.337 - return "%sVerbatim: text=%r" % (indent, self.text)
12.338 -
12.339 def visit(self, visitor):
12.340 visitor.verbatim(self)
12.341
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/moinformat/tree/pretty.py Fri Jun 30 00:40:39 2023 +0200
13.3 @@ -0,0 +1,65 @@
13.4 +#!/usr/bin/env python
13.5 +
13.6 +"""
13.7 +Prettyprinted document tree nodes.
13.8 +
13.9 +Copyright (C) 2017, 2018, 2019, 2023 Paul Boddie <paul@boddie.org.uk>
13.10 +
13.11 +This program is free software; you can redistribute it and/or modify it under
13.12 +the terms of the GNU General Public License as published by the Free Software
13.13 +Foundation; either version 3 of the License, or (at your option) any later
13.14 +version.
13.15 +
13.16 +This program is distributed in the hope that it will be useful, but WITHOUT
13.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13.19 +details.
13.20 +
13.21 +You should have received a copy of the GNU General Public License along with
13.22 +this program. If not, see <http://www.gnu.org/licenses/>.
13.23 +"""
13.24 +
13.25 +from moinformat.tree.moin import Container
13.26 +
13.27 +class Node:
13.28 +
13.29 + "A simplified tree node representation."
13.30 +
13.31 + def __init__(self, name):
13.32 + self.name = name
13.33 + self.nodes = []
13.34 +
13.35 + def __repr__(self):
13.36 + return "Node(%r, %r)" % (self.name, self.nodes)
13.37 +
13.38 + def visit(self, visitor):
13.39 + visitor.node(self)
13.40 +
13.41 + def append(self, node):
13.42 + self.nodes.append(node)
13.43 +
13.44 + def test(self, other):
13.45 +
13.46 + """
13.47 + Test whether this node is considered equivalent to 'other', where
13.48 + 'other' is a moinparser.tree node.
13.49 +
13.50 + Return any failing tree nodes or None.
13.51 + """
13.52 +
13.53 + if other.__class__.__name__ != self.name:
13.54 + return self, other, "name"
13.55 +
13.56 + if isinstance(other, Container):
13.57 + for node, other_node in map(None, self.nodes, other.nodes):
13.58 + if node is None or other_node is None:
13.59 + return self, other, node is None and "simple" or "document"
13.60 + t = node.test(other_node)
13.61 + if t:
13.62 + return t
13.63 + elif self.nodes:
13.64 + return self, other, "empty"
13.65 +
13.66 + return None
13.67 +
13.68 +# vim: tabstop=4 expandtab shiftwidth=4
14.1 --- a/moinformat/tree/table.py Fri Jun 30 00:37:36 2023 +0200
14.2 +++ b/moinformat/tree/table.py Fri Jun 30 00:40:39 2023 +0200
14.3 @@ -31,9 +31,6 @@
14.4 def __repr__(self):
14.5 return "Continuation(%r)" % self.text
14.6
14.7 - def prettyprint(self, indent=""):
14.8 - return "%sContinuation: %r" % (indent, self.text)
14.9 -
14.10 def visit(self, visitor):
14.11 visitor.continuation(self)
14.12
15.1 --- a/tests/test_parser.py Fri Jun 30 00:37:36 2023 +0200
15.2 +++ b/tests/test_parser.py Fri Jun 30 00:40:39 2023 +0200
15.3 @@ -1,5 +1,24 @@
15.4 #!/usr/bin/env python
15.5
15.6 +"""
15.7 +Test document parsing and serialisation.
15.8 +
15.9 +Copyright (C) 2017, 2018, 2019, 2023 Paul Boddie <paul@boddie.org.uk>
15.10 +
15.11 +This program is free software; you can redistribute it and/or modify it under
15.12 +the terms of the GNU General Public License as published by the Free Software
15.13 +Foundation; either version 3 of the License, or (at your option) any later
15.14 +version.
15.15 +
15.16 +This program is distributed in the hope that it will be useful, but WITHOUT
15.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15.19 +details.
15.20 +
15.21 +You should have received a copy of the GNU General Public License along with
15.22 +this program. If not, see <http://www.gnu.org/licenses/>.
15.23 +"""
15.24 +
15.25 from os import listdir
15.26 from os.path import abspath, split
15.27 import sys
15.28 @@ -17,10 +36,12 @@
15.29
15.30 # Import specific objects.
15.31
15.32 -from moinformat import Metadata, make_input, make_output, make_parser, \
15.33 - make_serialiser, parse, serialise
15.34 +from moinformat import get_parser, Metadata, make_input, make_output, \
15.35 + make_parser, make_serialiser, parse, serialise
15.36 from moinformat.tree.moin import Container
15.37
15.38 +
15.39 +
15.40 def test_input(d, s):
15.41
15.42 "Compare serialised output from 'd' with its original form 's'."
15.43 @@ -61,7 +82,8 @@
15.44 metadata.set("output_format", "html")
15.45 metadata.set("mapping", {"MoinMoin" : "https://moinmo.in/"})
15.46
15.47 - print serialise(d, make_serialiser(metadata))
15.48 + result = serialise(d, make_serialiser(metadata))
15.49 + print output.encode(result)
15.50 print "-" * 60
15.51 print
15.52
15.53 @@ -69,7 +91,9 @@
15.54
15.55 def test_tree(d, t, ts):
15.56
15.57 - "Compare tree structure 'd' with simplified, expected form 't' from 'ts'."
15.58 + """
15.59 + Compare tree structure 'd' with simplified, expected form 't' from 'ts'.
15.60 + """
15.61
15.62 failing = t.test(d)
15.63
15.64 @@ -78,9 +102,12 @@
15.65
15.66 # Show tree versus expected forms.
15.67
15.68 + moin_prettyprinter = make_serialiser(Metadata({"input_format" : "moin"}), "pretty")
15.69 + tree_prettyprinter = make_serialiser(Metadata({"input_format" : "pretty"}), "pretty")
15.70 +
15.71 print not failing
15.72 print "-" * 60
15.73 - print d.prettyprint()
15.74 + print serialise(d, moin_prettyprinter)
15.75 if failing:
15.76 print "-" * 60
15.77 print ts
15.78 @@ -90,102 +117,14 @@
15.79 print repr(simple)
15.80 print repr(tree)
15.81 print "-" * 60
15.82 - print tree.prettyprint()
15.83 + print serialise(tree, tree_prettyprinter)
15.84 print "-" * 60
15.85 - print simple.prettyprint()
15.86 + print serialise(simple, tree_prettyprinter)
15.87 print "-" * 60
15.88 print
15.89
15.90 return not failing
15.91
15.92 -class Node:
15.93 -
15.94 - "A simplified tree node representation."
15.95 -
15.96 - def __init__(self, name):
15.97 - self.name = name
15.98 - self.nodes = []
15.99 -
15.100 - def __repr__(self):
15.101 - return "Node(%r, %r)" % (self.name, self.nodes)
15.102 -
15.103 - def prettyprint(self, indent=""):
15.104 - l = []
15.105 - l.append("%s%s%s" % (indent, self.name, len(self.nodes) and " nodes=%d" % len(self.nodes) or ""))
15.106 - for node in self.nodes:
15.107 - l.append(node.prettyprint(indent + " "))
15.108 - return "\n".join(l)
15.109 -
15.110 - def append(self, node):
15.111 - self.nodes.append(node)
15.112 -
15.113 - def test(self, other):
15.114 -
15.115 - """
15.116 - Test whether this node is considered equivalent to 'other', where
15.117 - 'other' is a moinparser.tree node.
15.118 -
15.119 - Return any failing tree nodes or None.
15.120 - """
15.121 -
15.122 - if other.__class__.__name__ != self.name:
15.123 - return self, other, "name"
15.124 -
15.125 - if isinstance(other, Container):
15.126 - for node, other_node in map(None, self.nodes, other.nodes):
15.127 - if node is None or other_node is None:
15.128 - return self, other, node is None and "simple" or "document"
15.129 - t = node.test(other_node)
15.130 - if t:
15.131 - return t
15.132 - elif self.nodes:
15.133 - return self, other, "empty"
15.134 -
15.135 - return None
15.136 -
15.137 -def parse_tree(s):
15.138 -
15.139 - "Parse the tree structure representation in 's'."
15.140 -
15.141 - indent = 0
15.142 - branches = []
15.143 -
15.144 - for line in s.split("\n"):
15.145 - line = line.rstrip()
15.146 - if not line:
15.147 - continue
15.148 -
15.149 - new_indent = line.rfind(" ") + 1
15.150 - node = Node(line[new_indent:])
15.151 -
15.152 - # Establish a branch to add nodes to.
15.153 -
15.154 - if not branches:
15.155 - branches.append(node)
15.156 - else:
15.157 - # Note the current node as outermost branch.
15.158 -
15.159 - if new_indent > indent:
15.160 - branches.append(node)
15.161 - else:
15.162 - # Reduced indent involves obtaining an inner branch again.
15.163 -
15.164 - while indent > new_indent:
15.165 - del branches[-1]
15.166 - indent -= 2
15.167 -
15.168 - # Note the current node as outermost branch.
15.169 -
15.170 - branches[-1] = node
15.171 -
15.172 - # Append the current node to the parent branch.
15.173 -
15.174 - branches[-2].append(node)
15.175 -
15.176 - indent = new_indent
15.177 -
15.178 - return branches[0]
15.179 -
15.180 def get_filename(filename):
15.181
15.182 "Using 'filename', return the core text filename and any encoding."
15.183 @@ -206,10 +145,14 @@
15.184
15.185 if input.dir.exists(tree_filename):
15.186 ts = input.readfile(tree_filename)
15.187 - return ts, parse_tree(ts)
15.188 + return ts, parse(ts, make_parser(Metadata(), "pretty"))
15.189 else:
15.190 return None, None
15.191
15.192 +
15.193 +
15.194 +# Main program.
15.195 +
15.196 if __name__ == "__main__":
15.197 args = sys.argv[1:]
15.198