Source code for leo.plugins.leo_interface

#@+leo-ver=5-thin
#@+node:ekr.20101110091234.5700: * @file leo_interface.py
#@+<< docstring >>
#@+node:ekr.20101112180523.5422: ** << docstring >>
""" Allows the user to browse XML documents in Leo.

This plugin implements an interface to XML generation,
so that the resulting file can be processed by leo.

class leo_file represents the whole leo file.
class leo_node has a headline and body text.

See the end of this file for a minimal example on
how to use these classes.

If you encounter the first of a set of clones, create a leo_node. If you
encounter the same set of clones later, create a leo_clone node and refer back
to the first element.

"""
#@-<< docstring >>
debug = False
# Define globals
vnode_count = 0
if debug:
    allvnodes = {
        # leo_file:None, # Fixed a valid pylint complaint. file is not defined.
    }
    vnode_count = 0
    vnode_stack = []
#@@language python
#@@tabwidth -4
#@+others
#@+node:ekr.20101110092416.5699: ** escape
[docs]def escape(s): s = s.replace('&', "&amp;") s = s.replace('<', "&lt;") s = s.replace('>', "&gt;") return s
#@+node:ekr.20101112045055.60165: ** init
[docs]def init(): '''Return True if the plugin has loaded successfully.''' return True
#@+node:ekr.20101110092416.5700: ** class node_with_parent
[docs]class node_with_parent(object): #@+others #@+node:ekr.20101110092416.5702: *3* set_parent
[docs] def set_parent(self, node): self.mparent = node
#@+node:ekr.20101110092416.5704: *3* parent
[docs] def parent(self): return self.mparent
#@-others #@+node:ekr.20101110092416.5705: ** class LeoNode error_count = 0
[docs]class LeoNode(object): """ Abstrace class for generating xml. """ #@+others #@+node:ekr.20101110092416.5707: *3* __init__ def __init__(self): self.children = [] #@+node:ekr.20101110092416.5709: *3* add_child
[docs] def add_child(self, child): self.children.append(child) child.set_parent(self)
#@+node:ekr.20101110092416.5711: *3* gen
[docs] def gen(self, file): pass
#@+node:ekr.20101110092416.5713: *3* gen_children
[docs] def gen_children(self, file): for child in self.children: child.gen(file)
#@+node:ekr.20101110092416.5715: *3* mark
[docs] def mark(self, file, marker, func, newline=True): file.write("<%s>" % marker) if newline: file.write("\n") func(file) file.write("</%s>\n" % marker)
#@+node:ekr.20101110092416.5717: *3* mark_with_attributes
[docs] def mark_with_attributes(self, file, marker, attribute_list, func, newline=True): write = file.write write("<") write(marker) write(" ") for name, value in attribute_list: write('%s="%s" ' % (name, value)) write(">") if newline: write("\n") func(file) write("</%s>" % marker) if newline: write("\n")
#@+node:ekr.20101110092416.5719: *3* mark_with_attributes_short
[docs] def mark_with_attributes_short(self, file, marker, attribute_list): write = file.write write("<") write(marker) write(" ") for name, value in attribute_list: write('%s="%s" ' % (name, value)) write("/>\n")
#@+node:ekr.20101110092416.5721: *3* nthChild
[docs] def nthChild (self, n): return self.children[n]
#@-others #@+node:ekr.20101110092416.5722: ** class leo_file
[docs]class leo_file(LeoNode): """Leo specific class representing a file.""" #@+others #@+node:ekr.20101110092416.5724: *3* headString
[docs] def headString(self): return "[[This is the file root]]"
#@+node:ekr.20101110092416.5726: *3* parent
[docs] def parent(self): return None
#@+node:ekr.20101110092416.5728: *3* empty
[docs] def empty(self, file): pass
#@+node:ekr.20101110092416.5730: *3* find_panel_settings
[docs] def find_panel_settings(self, file): self.mark(file, "find_string", self.empty, newline=False) self.mark(file, "change_string", self.empty, newline=False)
#@+node:ekr.20101110092416.5732: *3* gen
[docs] def gen(self, file): global error_count error_count = 0 file.write('<?xml version="1.0" encoding="UTF-8"?>\n') self.mark(file, "leo_file", self.gen1)
#@+node:ekr.20101110092416.5734: *3* gen1
[docs] def gen1(self, file): self.header(file) # This is a shortcut. file.write("""<globals body_outline_ratio="0.5"> <global_window_position top="0" left="2" height="400" width="700"/> <global_log_window_position top="0" left="0" height="0" width="0"/> </globals> """) self.mark(file, "preferences", self.preferences) self.mark(file, "find_panel_settings", self.find_panel_settings) if debug: global vnode_count vnode_count = 0 self.mark(file, "vnodes", self.gen_vnodes) self.mark(file, "tnodes", self.gen_tnodes)
#@+node:ekr.20101110092416.5736: *3* gen_tnodes
[docs] def gen_tnodes(self, file): for child in self.children: child.gen_tnodes(file)
#@+node:ekr.20101110092416.5738: *3* gen_vnodes
[docs] def gen_vnodes(self, file): if debug: global allvnodes, vnode_stack allvnodes = {file:None} vnode_stack = [] for child in self.children: child.gen_vnodes(file)
#@+node:ekr.20101110092416.5740: *3* header
[docs] def header(self, file): self.mark_with_attributes_short(file, "leo_header", (("file_format", "1"), ("tnodes", repr(self.nr_tnodes())), ("max_tnode_index", repr(self.max_tnode_index())), ("clone_windows", "0")))
#@+node:ekr.20101110092416.5742: *3* max_tnode_index
[docs] def max_tnode_index(self): return leo_node.count
#@+node:ekr.20101110092416.5744: *3* nr_tnodes
[docs] def nr_tnodes(self): return leo_node.count
#@+node:ekr.20101110092416.5746: *3* preferences
[docs] def preferences(self, file): pass
#@+node:ekr.20101110092416.5748: *3* sss
[docs] def sss(self, file): file.write("sss")
#@-others #@+node:ekr.20101110092416.5749: ** class leo_node
[docs]class leo_node(LeoNode, node_with_parent): """ Leo specific class representing a node. These nodes correspond to tnodes in LEO. They have a headline and a body. They also represent the (only) vnode in an outline without clones. """ __super_leo_node = LeoNode count = 0 #@+others #@+node:ekr.20101110092416.5751: *3* __init__ def __init__(self, headline='', body=''): self.__super_leo_node.__init__(self) leo_node.count += 1 self.nr = leo_node.count self.headline = headline self.body = body #@+node:ekr.20101110092416.5753: *3* bodyString
[docs] def bodyString(self, body): return self.body
#@+node:ekr.20101110092416.5755: *3* gen_tnodes
[docs] def gen_tnodes(self, file): self.mark_with_attributes(file, "t", ( ("tx", "T" + repr(self.nr)), ), self.gen_tnodes1, newline=False) for child in self.children: child.gen_tnodes(file)
#@+node:ekr.20101110092416.5757: *3* gen_tnodes1
[docs] def gen_tnodes1(self, file): self.write_body_escaped(file)
#@+node:ekr.20101110092416.5759: *3* gen_vnodes
[docs] def gen_vnodes(self, file): attributes = [("t", "T" + repr(self.nr))] if debug: # For debugging, make sure that we are not getting # cyclic references. # Also number all nodes for easier error hunting. vnode_stack.append(self) if self in allvnodes: print("Fix this; This is an endless recursive call in leo_interface.leo_node.gen_vnodes") x = vnode_stack[:] x.reverse() for i in x: print(i.headline) import pdb; pdb.set_trace() return global vnode_count attributes.append(('model_node_number', repr(vnode_count))) vnode_count += 1 allvnodes[self]=None self.mark_with_attributes(file, "v", attributes, self.gen_vnodes1) if debug: del allvnodes[self] vnode_stack.pop()
#@+node:ekr.20101110092416.5761: *3* gen_vnodes1
[docs] def gen_vnodes1(self, file): self.mark(file, "vh", self.write_headline_escaped, newline=False) for child in self.children: child.gen_vnodes(file)
#@+node:ekr.20101110092416.5763: *3* headString
[docs] def headString(self): return self.headline
#@+node:ekr.20101110092416.5765: *3* set_body
[docs] def set_body(self, body): self.body = body
#@+node:ekr.20101110092416.5767: *3* set_headline
[docs] def set_headline(self, headline): self.headline = headline
#@+node:ekr.20101110092416.5769: *3* write_body_escaped
[docs] def write_body_escaped(self, file): file.write(escape(self.body.encode("UTF-8")))
#@+node:ekr.20101110092416.5771: *3* write_headline
[docs] def write_headline(self, file): file.write(self.headline)
#@+node:ekr.20101110092416.5773: *3* write_headline_escaped
[docs] def write_headline_escaped(self, file): file.write(escape(self.headline.encode("UTF-8")))
#@-others #@+node:ekr.20101110092416.5774: ** class leo_clone
[docs]class leo_clone(node_with_parent): """ Class representing a clone. The (only) data of a clone is the reference to a leo_node. When you encounter the first clone of a set of clones, generate a leo_node. The second clone should then reference this leo_node, and contain no other data. Since clones are indistinguishable, there is really not much to do in this class. """ #@+others #@+node:ekr.20101110092416.5776: *3* __init__ def __init__(self, orig): self.orig = orig self.mparent = None #@+node:ekr.20101110092416.5778: *3* gen_vnodes
[docs] def gen_vnodes(self, file): self.orig.gen_vnodes(file)
# There is nothing new to do here; # just repeat what we did when we encountered # the first clone. #@+node:ekr.20101110092416.5780: *3* gen_tnodes
[docs] def gen_tnodes(self, file): pass
# the tnodes are generated by the Leo_node #@-others #@+node:ekr.20101110092416.5782: ** leotree
[docs]def leotree(): f = leo_file() return f
#@-others if __name__ == "__main__": import sys f = leotree() r = leo_node("Some headline", "some Body") f.add_child(r) f.gen(sys.stdout) #@-leo