MoinLight

Change of moinformat/tree.py

11:e1ed135d019f
moinformat/tree.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/moinformat/tree.py	Sat Apr 29 17:47:03 2017 +0200
     1.3 @@ -0,0 +1,184 @@
     1.4 +#!/usr/bin/env python
     1.5 +
     1.6 +"""
     1.7 +Moin wiki format document tree nodes.
     1.8 +
     1.9 +Copyright (C) 2017 Paul Boddie <paul@boddie.org.uk>
    1.10 +
    1.11 +This program is free software; you can redistribute it and/or modify it under
    1.12 +the terms of the GNU General Public License as published by the Free Software
    1.13 +Foundation; either version 3 of the License, or (at your option) any later
    1.14 +version.
    1.15 +
    1.16 +This program is distributed in the hope that it will be useful, but WITHOUT
    1.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.18 +FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    1.19 +details.
    1.20 +
    1.21 +You should have received a copy of the GNU General Public License along with
    1.22 +this program.  If not, see <http://www.gnu.org/licenses/>.
    1.23 +"""
    1.24 +
    1.25 +class Container:
    1.26 +
    1.27 +    "A container of document nodes."
    1.28 +
    1.29 +    def __init__(self, nodes):
    1.30 +        self.nodes = nodes
    1.31 +
    1.32 +    def append(self, node):
    1.33 +        self.nodes.append(node)
    1.34 +
    1.35 +    append_text = append
    1.36 +
    1.37 +    def empty(self):
    1.38 +        return not self.nodes
    1.39 +
    1.40 +    def normalise(self):
    1.41 +
    1.42 +        "Combine adjacent text nodes."
    1.43 +
    1.44 +        nodes = self.nodes
    1.45 +        self.nodes = []
    1.46 +        text = None
    1.47 +
    1.48 +        for node in nodes:
    1.49 +
    1.50 +            # Open a text node or merge text into an open node.
    1.51 +
    1.52 +            if isinstance(node, Text):
    1.53 +                if not text:
    1.54 +                    text = node
    1.55 +                else:
    1.56 +                    text.merge(node)
    1.57 +
    1.58 +            # Close any open text node and append the current node.
    1.59 +
    1.60 +            else:
    1.61 +                if text:
    1.62 +                    self.append(text)
    1.63 +                    text = None
    1.64 +                self.append(node)
    1.65 +
    1.66 +        # Add any open text node.
    1.67 +
    1.68 +        if text:
    1.69 +            self.append(text)
    1.70 +
    1.71 +    def __str__(self):
    1.72 +        return self.prettyprint()
    1.73 +
    1.74 +    def prettyprint(self, indent=""):
    1.75 +        pass
    1.76 +
    1.77 +class Region(Container):
    1.78 +
    1.79 +    "A region of the page."
    1.80 +
    1.81 +    transparent_region_types = ["wiki"]
    1.82 +
    1.83 +    def __init__(self, nodes, level=0, indent=0, type=None):
    1.84 +        Container.__init__(self, nodes)
    1.85 +        self.level = level
    1.86 +        self.indent = indent
    1.87 +        self.type = type
    1.88 +
    1.89 +    def append(self, node):
    1.90 +        last = self.nodes and self.nodes[-1]
    1.91 +        if last and last.empty():
    1.92 +            self.nodes[-1] = node
    1.93 +        else:
    1.94 +            self.nodes.append(node)
    1.95 +
    1.96 +    def append_text(self, s):
    1.97 +        if self.is_transparent():
    1.98 +            self.nodes[-1].append(s)
    1.99 +        else:
   1.100 +            self.append(s)
   1.101 +
   1.102 +    def have_end(self, s):
   1.103 +        return self.level and s.startswith("}") and self.level == len(s)
   1.104 +
   1.105 +    def is_transparent(self):
   1.106 +        return not self.level or self.type in self.transparent_region_types
   1.107 +
   1.108 +    def __repr__(self):
   1.109 +        return "Region(%r, %r, %r, %r)" % (self.nodes, self.level, self.indent, self.type)
   1.110 +
   1.111 +    def prettyprint(self, indent=""):
   1.112 +        l = ["%sRegion: level=%d indent=%d type=%s" % (indent, self.level, self.indent, self.type)]
   1.113 +        for node in self.nodes:
   1.114 +            l.append(node.prettyprint(indent + "  "))
   1.115 +        return "\n".join(l)
   1.116 +
   1.117 +    def to_string(self, out):
   1.118 +        out.start_region(self.level, self.indent, self.type)
   1.119 +        for node in self.nodes:
   1.120 +            node.to_string(out)
   1.121 +        out.end_region(self.level, self.indent, self.type)
   1.122 +
   1.123 +class Block(Container):
   1.124 +
   1.125 +    "A block in the page."
   1.126 +
   1.127 +    def __init__(self, nodes, final=True):
   1.128 +        Container.__init__(self, nodes)
   1.129 +        self.final = final
   1.130 +
   1.131 +    def __repr__(self):
   1.132 +        return "Block(%r)" % self.nodes
   1.133 +
   1.134 +    def prettyprint(self, indent=""):
   1.135 +        l = ["%sBlock: final=%s" % (indent, self.final)]
   1.136 +        for node in self.nodes:
   1.137 +            l.append(node.prettyprint(indent + "  "))
   1.138 +        return "\n".join(l)
   1.139 +
   1.140 +    def to_string(self, out):
   1.141 +        out.start_block(self.final)
   1.142 +        for node in self.nodes:
   1.143 +            node.to_string(out)
   1.144 +        out.end_block(self.final)
   1.145 +
   1.146 +class ListItem(Container):
   1.147 +
   1.148 +    "A list item."
   1.149 +
   1.150 +    def __repr__(self):
   1.151 +        return "ListItem(%r)" % self.nodes
   1.152 +
   1.153 +    def prettyprint(self, indent=""):
   1.154 +        l = ["%sListItem:" % indent]
   1.155 +        for node in self.nodes:
   1.156 +            l.append(node.prettyprint(indent + "  "))
   1.157 +        return "\n".join(l)
   1.158 +
   1.159 +    def to_string(self, out):
   1.160 +        out.start_listitem()
   1.161 +        for node in self.nodes:
   1.162 +            node.to_string(out)
   1.163 +        out.end_listitem()
   1.164 +
   1.165 +class Text:
   1.166 +
   1.167 +    "A text node."
   1.168 +
   1.169 +    def __init__(self, s):
   1.170 +        self.s = s
   1.171 +
   1.172 +    def empty(self):
   1.173 +        return not self.s
   1.174 +
   1.175 +    def merge(self, text):
   1.176 +        self.s += text.s
   1.177 +
   1.178 +    def __repr__(self):
   1.179 +        return "Text(%r)" % self.s
   1.180 +
   1.181 +    def prettyprint(self, indent=""):
   1.182 +        return "%sText: %r" % (indent, self.s)
   1.183 +
   1.184 +    def to_string(self, out):
   1.185 +        out.text(self.s)
   1.186 +
   1.187 +# vim: tabstop=4 expandtab shiftwidth=4