[gobject-introspection/mallard-templates] g-ir-doctool: Move to Mako templates for generating Mallard



commit 1cb2568b4d56905e3d255a042a15b0094dce156e
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date:   Wed Aug 17 10:23:58 2011 +0200

    g-ir-doctool: Move to Mako templates for generating Mallard
    
    Also removes the docbook writer

 giscanner/docmain.py                    |   53 +---
 giscanner/mallard-C-class.tmpl          |   34 ++
 giscanner/mallard-C-default.tmpl        |   10 +
 giscanner/mallard-C-function.tmpl       |   11 +
 giscanner/mallard-C-method.tmpl         |   11 +
 giscanner/mallard-C-namespace.tmpl      |   19 ++
 giscanner/mallard-C-record.tmpl         |   11 +
 giscanner/mallard-Python-class.tmpl     |   34 ++
 giscanner/mallard-Python-default.tmpl   |   10 +
 giscanner/mallard-Python-function.tmpl  |   11 +
 giscanner/mallard-Python-method.tmpl    |   11 +
 giscanner/mallard-Python-namespace.tmpl |   19 ++
 giscanner/mallard-Python-record.tmpl    |   12 +
 giscanner/mallardwriter.py              |  520 +++++--------------------------
 tests/doctool/Makefile.am               |    4 +-
 15 files changed, 289 insertions(+), 481 deletions(-)
---
diff --git a/giscanner/docmain.py b/giscanner/docmain.py
index e6ae8b6..e3ef4ae 100644
--- a/giscanner/docmain.py
+++ b/giscanner/docmain.py
@@ -21,39 +21,15 @@
 import os
 import optparse
 
-from .docbookwriter import DocBookWriter
-from .docbookwriter import DocBookFormatterC
-from .docbookwriter import DocBookFormatterPython
 from .mallardwriter import MallardWriter
-from .mallardwriter import MallardFormatterC
-from .mallardwriter import MallardFormatterPython
 from .transformer import Transformer
 
-class GIDocGenerator(object):
-
-    def parse(self, filename):
-        if 'UNINSTALLED_INTROSPECTION_SRCDIR' in os.environ:
-            top_srcdir = os.environ['UNINSTALLED_INTROSPECTION_SRCDIR']
-            top_builddir = os.environ['UNINSTALLED_INTROSPECTION_BUILDDIR']
-            extra_include_dirs = [os.path.join(top_srcdir, 'gir'), top_builddir]
-        else:
-            extra_include_dirs = []
-        self.transformer = Transformer.parse_from_gir(filename, extra_include_dirs)
-
-    def generate(self, writer, output):
-        writer.add_transformer(self.transformer)
-        writer.write(output)
-
 def doc_main(args):
     parser = optparse.OptionParser('%prog [options] GIR-file')
 
     parser.add_option("-o", "--output",
                       action="store", dest="output",
                       help="Filename to write output")
-    parser.add_option("-f", "--format",
-                      action="store", dest="format",
-                      default="docbook",
-                      help="Output format")
     parser.add_option("-l", "--language",
                       action="store", dest="language",
                       default="Python",
@@ -66,28 +42,15 @@ def doc_main(args):
     if len(args) < 2:
         raise SystemExit("Need an input GIR filename")
 
-    if options.format == "docbook":
-        if options.language == "Python":
-            formatter = DocBookFormatterPython()
-        elif options.language == "C":
-            formatter = DocBookFormatterC()
-        else:
-            raise SystemExit("Unsupported language: %s" % (options.language, ))
-        writer = DocBookWriter(formatter)
-    elif options.format == "mallard":
-        if options.language == "Python":
-            formatter = MallardFormatterPython()
-        elif options.language == "C":
-            formatter = MallardFormatterC()
-        else:
-            raise SystemExit("Unsupported language: %s" % (options.language, ))
-        writer = MallardWriter(formatter)
+    if 'UNINSTALLED_INTROSPECTION_SRCDIR' in os.environ:
+        top_srcdir = os.environ['UNINSTALLED_INTROSPECTION_SRCDIR']
+        top_builddir = os.environ['UNINSTALLED_INTROSPECTION_BUILDDIR']
+        extra_include_dirs = [os.path.join(top_srcdir, 'gir'), top_builddir]
     else:
-        raise SystemExit("Unsupported output format: %s" % (options.format, ))
-
-    generator = GIDocGenerator()
-    generator.parse(args[1])
+        extra_include_dirs = []
+    transformer = Transformer.parse_from_gir(args[1], extra_include_dirs)
 
-    generator.generate(writer, options.output)
+    writer = MallardWriter(transformer, options.language)
+    writer.write(options.output)
 
     return 0
diff --git a/giscanner/mallard-C-class.tmpl b/giscanner/mallard-C-class.tmpl
new file mode 100644
index 0000000..c08aea0
--- /dev/null
+++ b/giscanner/mallard-C-class.tmpl
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<page id="${node.namespace.name}.${node.name}"
+      type="guide"
+      style="class"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="index" group="class"/>
+  </info>
+  <title>${node.namespace.name}${node.name}</title>
+  <synopsis ui:expanded="no">
+    <title>Hierarchy</title>
+    <tree>
+      <item>
+        <code>GObjectObject</code>
+      </item>
+    </tree>
+  </synopsis>
+  <links type="topic" ui:expanded="yes" groups="constructor">
+    <title>Constructors</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="method">
+    <title>Methods</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="property">
+    <title>Properties</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="signal">
+    <title>Signals</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="#first #default #last">
+    <title>Other</title>
+  </links>
+</page>
diff --git a/giscanner/mallard-C-default.tmpl b/giscanner/mallard-C-default.tmpl
new file mode 100644
index 0000000..3b6cb26
--- /dev/null
+++ b/giscanner/mallard-C-default.tmpl
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<page id="${node.namespace.name}.${node.name}"
+      type="topic"
+      style=""
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+  </info>
+  <title>${node.namespace.name}${node.name}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-C-function.tmpl b/giscanner/mallard-C-function.tmpl
new file mode 100644
index 0000000..fabbe31
--- /dev/null
+++ b/giscanner/mallard-C-function.tmpl
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<page id="${namespace.name}.${node.name}"
+      type="topic"
+      style="function"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="index" group="function"/>
+  </info>
+  <title>${node.symbol}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-C-method.tmpl b/giscanner/mallard-C-method.tmpl
new file mode 100644
index 0000000..bf998ab
--- /dev/null
+++ b/giscanner/mallard-C-method.tmpl
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<page id="${namespace.name}.${parent.name}.${node.name}"
+      type="topic"
+      style="method"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="${namespace.name}.${parent.name}" group="method"/>
+  </info>
+  <title>${node.symbol}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-C-namespace.tmpl b/giscanner/mallard-C-namespace.tmpl
new file mode 100644
index 0000000..935cd44
--- /dev/null
+++ b/giscanner/mallard-C-namespace.tmpl
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<page id="index"
+      type="guide"
+      style="namespace"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+  </info>
+  <title>${node.name} Documentation</title>
+  <links type="topic" ui:expanded="yes" groups="class">
+    <title>Classes</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="function">
+    <title>Functions</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="#first #default #last">
+    <title>Other</title>
+  </links>
+</page>
diff --git a/giscanner/mallard-C-record.tmpl b/giscanner/mallard-C-record.tmpl
new file mode 100644
index 0000000..e6424fd
--- /dev/null
+++ b/giscanner/mallard-C-record.tmpl
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<page id="${node.namespace.name}.${node.name}"
+      type="guide"
+      style="record"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="index"/>
+  </info>
+  <title>${node.namespace.name}${node.name}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-Python-class.tmpl b/giscanner/mallard-Python-class.tmpl
new file mode 100644
index 0000000..020c672
--- /dev/null
+++ b/giscanner/mallard-Python-class.tmpl
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<page id="${node.namespace.name}.${node.name}"
+      type="guide"
+      style="class"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="index" group="class"/>
+  </info>
+  <title>${node.namespace.name}.${node.name}</title>
+  <synopsis ui:expanded="no">
+    <title>Hierarchy</title>
+    <tree>
+      <item>
+        <code>GObject.Object</code>
+      </item>
+    </tree>
+  </synopsis>
+  <links type="topic" ui:expanded="yes" groups="constructor">
+    <title>Constructors</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="method">
+    <title>Methods</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="property">
+    <title>Properties</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="signal">
+    <title>Signals</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="#first #default #last">
+    <title>Other</title>
+  </links>
+</page>
diff --git a/giscanner/mallard-Python-default.tmpl b/giscanner/mallard-Python-default.tmpl
new file mode 100644
index 0000000..9340940
--- /dev/null
+++ b/giscanner/mallard-Python-default.tmpl
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<page id="${node.namespace.name}.${node.name}"
+      type="topic"
+      style=""
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+  </info>
+  <title>${node.namespace.name}.${node.name}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-Python-function.tmpl b/giscanner/mallard-Python-function.tmpl
new file mode 100644
index 0000000..fabbe31
--- /dev/null
+++ b/giscanner/mallard-Python-function.tmpl
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<page id="${namespace.name}.${node.name}"
+      type="topic"
+      style="function"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="index" group="function"/>
+  </info>
+  <title>${node.symbol}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-Python-method.tmpl b/giscanner/mallard-Python-method.tmpl
new file mode 100644
index 0000000..bf998ab
--- /dev/null
+++ b/giscanner/mallard-Python-method.tmpl
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<page id="${namespace.name}.${parent.name}.${node.name}"
+      type="topic"
+      style="method"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="${namespace.name}.${parent.name}" group="method"/>
+  </info>
+  <title>${node.symbol}</title>
+${format(node.doc)}</page>
diff --git a/giscanner/mallard-Python-namespace.tmpl b/giscanner/mallard-Python-namespace.tmpl
new file mode 100644
index 0000000..935cd44
--- /dev/null
+++ b/giscanner/mallard-Python-namespace.tmpl
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<page id="index"
+      type="guide"
+      style="namespace"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+  </info>
+  <title>${node.name} Documentation</title>
+  <links type="topic" ui:expanded="yes" groups="class">
+    <title>Classes</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="function">
+    <title>Functions</title>
+  </links>
+  <links type="topic" ui:expanded="yes" groups="#first #default #last">
+    <title>Other</title>
+  </links>
+</page>
diff --git a/giscanner/mallard-Python-record.tmpl b/giscanner/mallard-Python-record.tmpl
new file mode 100644
index 0000000..1b00e3b
--- /dev/null
+++ b/giscanner/mallard-Python-record.tmpl
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<page id="${node.namespace.name}.${node.name}"
+      type="guide"
+      style="record"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:ui="http://projectmallard.org/experimental/ui/";>
+  <info>
+    <link type="guide" xref="index"/>
+  </info>
+  <title>${node.namespace.name}${node.name}</title>
+  <p>${node.doc}</p>
+</page>
diff --git a/giscanner/mallardwriter.py b/giscanner/mallardwriter.py
index a71528e..5c2e295 100644
--- a/giscanner/mallardwriter.py
+++ b/giscanner/mallardwriter.py
@@ -21,454 +21,106 @@
 # 02110-1301, USA.
 #
 
-import os.path
+import os
 import re
-import sys
 
-from . import ast
-from .girparser import GIRParser
-from .xmlwriter import XMLWriter
-
-XMLNS = "http://projectmallard.org/1.0/";
-XMLNS_UI = "http://projectmallard.org/experimental/ui/";
-
-def _space(num):
-    return " " * num
-
-class MallardFormatter(object):
-    def __init__(self):
-        pass
-
-    def get_title(self, node, parent):
-        raise NotImplementedError('get_title not implemented')
-
-    # FIXME
-    def render_parameter(self, param_type, param_name):
-        return "%s %s" % (param_type, param_name)
-
-    def _render_parameter(self, param, extra_content=''):
-        with self._writer.tagcontext("parameter"):
-            if param.type.ctype is not None:
-                link_dest = param.type.ctype.replace("*", "")
-            else:
-                link_dest = param.type.ctype
-            with self._writer.tagcontext("link", [("linkend", "%s" % link_dest)]):
-                self._writer.write_tag("type", [], link_dest)
-            self._writer.write_line(extra_content)
-
-    def _render_parameters(self, parent, parameters):
-        self._writer.write_line(
-            "%s(" % _space(40 - len(parent.symbol)))
-
-        parent_class = parent.parent_class
-        ctype = ast.Type(parent.parent_class.ctype + '*')
-        params = []
-        params.append(ast.Parameter(parent_class.name.lower(), ctype))
-        params.extend(parameters)
-
-        first_param = True
-        for param in params:
-            if not first_param:
-                self._writer.write_line("\n%s" % _space(61))
-            else:
-                first_param = False
-
-            if not param == params[-1]:
-                comma = ", "
-            else:
-                comma = ""
-            if param.type.target_fundamental == '<varargs>':
-                extra_content = "..."
-                continue
-            extra_content = " "
-            if param.type.ctype is not None and '*' in param.type.ctype:
-                extra_content += '*'
-            if param.argname is None:
-                import pdb
-                pdb.set_trace()
-            extra_content += param.argname
-            extra_content += comma
-            self._render_parameter(param, extra_content)
-
-        self._writer.write_line(");\n")
-
-    def get_method_as_title(self, entity):
-        method = entity.get_ast()
-        return "%s ()" % method.symbol
-
-    def get_page_name(self, node):
-        if node.gtype_name is None:
-            return node.ctype
-        return node.gtype_name
-
-    def get_class_name(self, node):
-        if node.gtype_name is None:
-            return node.ctype
-        return node.gtype_name
-
-    def get_type_name(self, node):
-        if isinstance(node, ast.Array):
-            if node.array_type == ast.Array.C:
-                return str(node.element_type) + "[]"
-            else:
-                return "%s&lt;%s&gt;" % (node.array_type, str(node.element_type))
-        elif isinstance(node, ast.Map):
-            return "GHashTable&lt;%s, %s&gt;" % (str(node.key_type), str(node.value_type))
-        elif isinstance(node, ast.List):
-            return "GList&lt;%s&gt;" % str(node.element_type)
-        else:
-            return str(node)
-
-    def render_method(self, entity, link=False):
-        method = entity.get_ast()
-        self._writer.disable_whitespace()
-
-        retval_type = method.retval.type
-        if retval_type.ctype:
-            link_dest = retval_type.ctype.replace("*", "")
-        else:
-            link_dest = str(retval_type)
-
-        if retval_type.target_giname:
-            ns = retval_type.target_giname.split('.')
-            if ns[0] == self._namespace.name:
-                link_dest = "%s" % (
-                    retval_type.ctype.replace("*", ""))
-
-        with self._writer.tagcontext("link", [("linkend", link_dest)]):
-            self._writer.write_tag("returnvalue", [], link_dest)
-
-        if retval_type.ctype is not None and '*' in retval_type.ctype:
-            self._writer.write_line(' *')
-
-        self._writer.write_line(
-            _space(20 - len(self.get_type_string(method.retval.type))))
-
-        if link:
-            self._writer.write_tag("link", [("linkend",
-                                            method.symbol.replace("_", "-"))],
-                                  method.symbol)
-        else:
-            self._writer.write_line(method.symbol)
-
-        self._render_parameters(method, method.parameters)
-        self._writer.enable_whitespace()
-
-    def _get_annotations(self, argument):
-        annotations = {}
-
-        if hasattr(argument.type, 'element_type') and \
-           argument.type.element_type is not None:
-            annotations['element-type'] = argument.type.element_type
-
-        if argument.transfer is not None and argument.transfer != 'none':
-            annotations['transfer'] = argument.transfer
-
-        if hasattr(argument, 'allow_none') and argument.allow_none:
-            annotations['allow-none'] = None
-
-        return annotations
-
-    def render_param_list(self, entity):
-        method = entity.get_ast()
-
-        self._render_param(method.parent_class.name.lower(), 'instance', [])
-
-        for param in method.parameters:
-            self._render_param(param.argname, param.doc,
-                               self._get_annotations(param))
-
-        self._render_param('Returns', method.retval.doc,
-                           self._get_annotations(method.retval))
-
-    def _render_param(self, argname, doc, annotations):
-        if argname is None:
-            return
-        with self._writer.tagcontext('varlistentry'):
-            with self._writer.tagcontext('term'):
-                self._writer.disable_whitespace()
-                try:
-                    with self._writer.tagcontext('parameter'):
-                        self._writer.write_line(argname)
-                    if doc is not None:
-                        self._writer.write_line('&#xA0;:')
-                finally:
-                    self._writer.enable_whitespace()
-            if doc is not None:
-                with self._writer.tagcontext('listitem'):
-                    with self._writer.tagcontext('simpara'):
-                        self._writer.write_line(doc)
-                        if annotations:
-                            with self._writer.tagcontext('emphasis', [('role', 'annotation')]):
-                                for key, value in annotations.iteritems():
-                                    self._writer.disable_whitespace()
-                                    try:
-                                        self._writer.write_line('[%s' % key)
-                                        if value is not None:
-                                            self._writer.write_line(' %s' % value)
-                                        self._writer.write_line(']')
-                                    finally:
-                                        self._writer.enable_whitespace()
-
-    def render_property(self, entity, link=False):
-        prop = entity.get_ast()
-
-        prop_name = '"%s"' % prop.name
-        prop_type = self.get_type_name(prop.type)
-
-        flags = []
-        if prop.readable:
-            flags.append("Read")
-        if prop.writable:
-            flags.append("Write")
-        if prop.construct:
-            flags.append("Construct")
-        if prop.construct_only:
-            flags.append("Construct Only")
-
-        self._render_prop_or_signal(prop_name, prop_type, flags)
-
-    def _render_prop_or_signal(self, name, type_, flags):
-        self._writer.disable_whitespace()
-
-        line = _space(2) + name + _space(27 - len(name))
-        line += str(type_) + _space(22 - len(str(type_)))
-        line += ": " + " / ".join(flags)
-
-        self._writer.write_line(line + "\n")
-
-        self._writer.enable_whitespace()
+from xml.sax import saxutils
+from mako.template import Template
+from mako.runtime import supports_caller
 
+from . import ast
 
-    def render_signal(self, entity, link=False):
-        signal = entity.get_ast()
+def format(doc):
+    if doc is None:
+        return ''
+
+    result = ''
+    for para in doc.split('\n\n'):
+        result += '<p>'
+        result += format_inline(para)
+        result += '</p>'
+    return result
+
+def escape(text):
+    return saxutils.escape(text.encode('utf-8')).decode('utf-8')
+
+def format_inline(para):
+    result = ''
+
+    poss = []
+    poss.append((para.find('#'), '#'))
+    poss = [pos for pos in poss if pos[0] >= 0]
+    poss.sort(cmp=lambda x, y: cmp(x[0], y[0]))
+    if len(poss) == 0:
+        result += escape(para)
+    elif poss[0][1] == '#':
+        pos = poss[0][0]
+        result += escape(para[:pos])
+        rest = para[pos + 1:]
+        link = re.split('[^a-zA-Z_:-]', rest, maxsplit=1)[0]
+        xref = link #self.writer._xrefs.get(link, link)
+        result += '<link xref="%s">%s</link>' % (xref, link)
+        if len(link) < len(rest):
+            result += format_inline(rest[len(link):])
+
+    return result
 
-        sig_name = '"%s"' % signal.name
-        flags = ["TODO: signal flags not in GIR currently"]
-        self._render_prop_or_signal(sig_name, "", flags)
+class MallardWriter(object):
+    def __init__(self, transformer, language):
+        if language not in ["Python", "C"]:
+            raise SystemExit("Unsupported language: %s" % language)
 
-class MallardFormatterC(MallardFormatter):
-    def get_title(self, node, parent):
-        if isinstance(node, ast.Namespace):
-            return "%s Documentation" % node.name
-        elif isinstance(node, ast.Function):
-            return node.symbol
-        elif isinstance(node, ast.Property):
-            return parent.c_name + ':' + node.name
-        elif isinstance(node, ast.Signal):
-            return parent.c_name + '::' + node.name
-        else:
-            return node.c_name
+        self._transformer = transformer
+        self._language = language
 
-class MallardFormatterPython(MallardFormatter):
-    def get_title(self, node, parent):
+    def write(self, output):
+        self._render_node(self._transformer.namespace, output)
+        for node in self._transformer.namespace.itervalues():
+            self._render_node(node, output)
+            if isinstance(node, (ast.Class, ast.Record)):
+                for method in node.methods:
+                    self._render_node(method, output, node)
+
+    def _render_node(self, node, output, parent=None):
+        namespace = self._transformer.namespace
         if isinstance(node, ast.Namespace):
-            return "%s Documentation" % node.name
+            template_name = 'mallard-%s-namespace.tmpl' % self._language
+            page_id = 'index'
+        elif isinstance(node, (ast.Class, ast.Interface)):
+            template_name = 'mallard-%s-class.tmpl' % self._language
+            page_id = '%s.%s' % (namespace.name, node.name)
+        elif isinstance(node, ast.Record):
+            template_name = 'mallard-%s-record.tmpl' % self._language
+            page_id = '%s.%s' % (namespace.name, node.name)
+        elif isinstance(node, ast.Function) and parent is not None:
+            template_name = 'mallard-%s-method.tmpl' % self._language
+            page_id = '%s.%s.%s' % (namespace.name, parent.name, node.name)
         elif isinstance(node, ast.Function):
-            if node.is_method or node.is_constructor:
-                return "%s.%s.%s" % (node.namespace.name, parent.name, node.name)
-            else:
-                return "%s.%s" % (node.namespace.name, node.name)
-        elif isinstance(node, ast.Property):
-            return "%s" % node.name
-        elif isinstance(node, ast.Signal):
-            return "%s" % node.name
+            template_name = 'mallard-%s-function.tmpl' % self._language
+            page_id = '%s.%s' % (namespace.name, node.name)
         else:
-            return "%s.%s" % (node.namespace.name, node.name)
-
-class MallardPage(object):
-    def __init__(self, writer, node, parent):
-        self.writer = writer
-        self.node = node
-        self.parent = parent
-        self.page_id = None
-        self.page_type = 'topic'
-        self.page_style = ''
+            template_name = 'mallard-%s-default.tmpl' % self._language
+            page_id = '%s.%s' % (namespace.name, node.name)
 
-        node.page = self
-        if not isinstance(node, ast.Namespace):
-            if node.namespace is None:
-                if parent is not None and parent.namespace is not None:
-                    node.namespace = parent.namespace
-
-        self.title = writer._formatter.get_title(node, parent)
-        self.links = []
-        self.linksels = []
-
-        if isinstance(node, ast.Namespace):
-            self.page_id = 'index'
-        elif isinstance(node, ast.Property) and parent is not None:
-            self.page_id = node.namespace.name + '.' + parent.name + '-' + node.name
-        elif isinstance(node, ast.Signal) and parent is not None:
-            self.page_id = node.namespace.name + '.' + parent.name + '--' + node.name
-        elif parent is not None and not isinstance(parent, ast.Namespace):
-            self.page_id = node.namespace.name + '.' + parent.name + '.' + node.name
+        if 'UNINSTALLED_INTROSPECTION_SRCDIR' in os.environ:
+            top_srcdir = os.environ['UNINSTALLED_INTROSPECTION_SRCDIR']
+            template_dir = os.path.join(top_srcdir, 'giscanner')
         else:
-            self.page_id = node.namespace.name + '.' + node.name
-
-        if getattr(node, 'symbol', None) is not None:
-            self.writer._xrefs[node.symbol] = self.page_id
-        elif isinstance(node, ast.Class):
-            self.writer._xrefs[node.c_name] = self.page_id
-
-        self.create_content()
-        self.add_child_nodes()
-
-    def add_link(self, linktype, xref, group=None):
-        self.links.append((linktype, xref, group))
-
-    def add_child_nodes(self):
-        children = []
-        if isinstance(self.node, ast.Namespace):
-            children = [node for node in self.node.itervalues()]
-        elif isinstance(self.node, (ast.Class, ast.Record)):
-            children = self.node.methods + self.node.constructors
-        elif isinstance(self.node, ast.Interface):
-            children = self.node.methods
-
-        if isinstance(self.node, (ast.Class, ast.Interface)):
-            children += self.node.properties + self.node.signals
-        for child in children:
-            self.writer._pages.append(MallardPage(self.writer, child, self.node))
-
-    def create_content(self):
-        if isinstance(self.node, ast.Namespace):
-            self.page_type = 'guide'
-            self.page_style = 'namespace'
-            self.linksels = (('class', 'Classes'),
-                             ('function', 'Functions'),
-                             ('#first #default #last', 'Other'))
-        elif isinstance(self.node, ast.Class):
-            self.page_type = 'guide'
-            self.page_style = 'class'
-            self.linksels = (('constructor', 'Constructors'),
-                             ('method', 'Methods'),
-                             ('property', 'Properties'),
-                             ('signal', 'Signals'),
-                             ('#first #default #last', 'Other'))
-            self.add_link('guide', self.parent.page.page_id, 'class')
-        elif isinstance(self.node, ast.Record):
-            self.page_type = 'guide'
-            self.page_style = 'record'
-            self.add_link('guide', self.parent.page.page_id)
-        elif isinstance(self.node, ast.Interface):
-            self.page_type = 'guide'
-            self.page_style = 'interface'
-            self.add_link('guide', self.parent.page.page_id)
-        elif isinstance(self.node, ast.Function):
-            if self.node.is_constructor:
-                self.page_style = 'constructor'
-                self.add_link('guide', self.parent.page.page_id, 'constructor')
-            elif self.node.is_method:
-                self.page_style = 'method'
-                self.add_link('guide', self.parent.page.page_id, 'method')
-            else:
-                self.page_style = 'function'
-                self.add_link('guide', self.parent.page.page_id, 'function')
-        elif isinstance(self.node, ast.Property):
-            self.page_style = 'property'
-            self.add_link('guide', self.parent.page.page_id, 'property')
-        elif isinstance(self.node, ast.Signal):
-            self.page_style = 'signal'
-            self.add_link('guide', self.parent.page.page_id, 'signal')
-
-    def render(self, writer):
-        with writer.tagcontext('page', [
-            ('id', self.page_id),
-            ('type', self.page_type),
-            ('style', self.page_style),
-            ('xmlns', XMLNS), ('xmlns:ui', XMLNS_UI)]):
-            with writer.tagcontext('info'):
-                for linktype, xref, group in self.links:
-                    if group is not None:
-                        writer.write_tag('link', [
-                                ('type', linktype), ('xref', xref), ('group', group)])
-                    else:
-                        writer.write_tag('link', [
-                                ('type', linktype), ('xref', xref)])
-            writer.write_tag('title', [], self.title)
-            if isinstance(self.node, ast.Annotated):
-                self.render_doc(writer, self.node.doc)
-            if isinstance(self.node, ast.Class):
-                parent_chain = []
-                node = self.node
-                while node.parent:
-                    node = self.writer._transformer.lookup_giname(str(node.parent))
-                    parent_chain.append(node)
-                    if node.namespace.name == 'GObject' and node.name == 'Object':
-                        break
-                parent_chain.reverse()
-                def print_chain(chain):
-                    with writer.tagcontext('item', []):
-                        attrs = []
-                        title = self.writer._formatter.get_title(chain[0], None)
-                        if hasattr(chain[0], 'page'):
-                            attrs.append(('xref', chain[0].page.page_id))
-                        writer.write_tag('code', attrs, title)
-                        if len(chain) > 1:
-                            print_chain(chain[1:])
-                with writer.tagcontext('synopsis', [('ui:expanded', 'no')]):
-                    writer.write_tag('title', [], 'Hierarchy')
-                    with writer.tagcontext('tree', []):
-                        print_chain(parent_chain)
-            for linkstype, title in self.linksels:
-                with writer.tagcontext('links', [
-                        ('type', 'topic'), ('ui:expanded', 'yes'),
-                        ('groups', linkstype)]):
-                    writer.write_tag('title', [], title)
-
-    def render_doc(self, writer, doc):
-        if doc is not None:
-            for para in doc.split('\n\n'):
-                writer.disable_whitespace()
-                with writer.tagcontext('p', []):
-                    self.render_doc_inline(writer, para)
-                writer.enable_whitespace()
-
-    def render_doc_inline(self, writer, text):
-        poss = []
-        poss.append((text.find('#'), '#'))
-        poss = [pos for pos in poss if pos[0] >= 0]
-        poss.sort(cmp=lambda x, y: cmp(x[0], y[0]))
-        if len(poss) == 0:
-            writer.write_line(text, do_escape=True)
-        elif poss[0][1] == '#':
-            pos = poss[0][0]
-            writer.write_line(text[:pos], do_escape=True)
-            rest = text[pos + 1:]
-            link = re.split('[^a-zA-Z_:-]', rest, maxsplit=1)[0]
-            xref = self.writer._xrefs.get(link, link)
-            writer.write_tag('link', [('xref', xref)], link)
-            if len(link) < len(rest):
-                self.render_doc_inline(writer, rest[len(link):])
-
-class MallardWriter(object):
-    def __init__(self, formatter):
-        self._namespace = None
-        self._index = None
-        self._pages = []
-        self._formatter = formatter
-        self._xrefs = {}
-
-    def add_transformer(self, transformer):
-        self._transformer = transformer
-        self._namespace = self._transformer._namespace
-        self._index = MallardPage(self, self._namespace, None)
-
-    def write(self, output):
-        xmlwriter = XMLWriter()
-        self._index.render(xmlwriter)
-        fp = open(output, 'w')
-        fp.write(xmlwriter.get_xml())
+            template_dir = 'unimplemented'
+
+        file_name = os.path.join(template_dir, template_name)
+        template = Template(filename=file_name)
+        result = template.render(namespace=namespace,
+                                 node=node,
+                                 format=format,
+                                 parent=parent)
+
+        output_file_name = os.path.join(os.path.dirname(output),
+                                        page_id + '.page')
+        fp = open(output_file_name, 'w')
+        fp.write(result)
         fp.close()
 
-        for page in self._pages:
-            xmlwriter = XMLWriter()
-            page.render(xmlwriter)
-            fp = open(os.path.join(os.path.dirname(output), page.page_id + '.page'), 'w')
-            fp.write(xmlwriter.get_xml())
-            fp.close()
-
     def _render_page_object_hierarchy(self, page_node):
         parent_chain = self._get_parent_chain(page_node)
         parent_chain.append(page_node)
diff --git a/tests/doctool/Makefile.am b/tests/doctool/Makefile.am
index b9d5206..5bb84a6 100644
--- a/tests/doctool/Makefile.am
+++ b/tests/doctool/Makefile.am
@@ -12,10 +12,10 @@ EXTRA_DIST = $(EXPECTED_MALLARD_DIRS)
 	cp ../../$*.gir .
 
 %-C: %.gir
-	mkdir $*-C ; rm $*-C/*.page ; $(INTROSPECTION_DOCTOOL) --language C --format mallard $*.gir -o $*-C/index.page && echo "  GEN  $*-C/index.page"
+	mkdir $*-C ; rm $*-C/*.page ; $(INTROSPECTION_DOCTOOL) --language C $*.gir -o $*-C/index.page && echo "  GEN  $*-C/index.page"
 
 %-Python: %.gir
-	mkdir $*-Python ; rm $*-Python/*.page ; $(INTROSPECTION_DOCTOOL) --language Python --format mallard $*.gir -o $*-Python/index.page && echo "  GEN  $*-Python/index.page"
+	mkdir $*-Python ; rm $*-Python/*.page ; $(INTROSPECTION_DOCTOOL) --language Python $*.gir -o $*-Python/index.page && echo "  GEN  $*-Python/index.page"
 
 %-C.page.check: %-C
 	@diff -u -U 10 $(srcdir)/$*-C-expected $*-C && echo "  TEST  $*-C" && rm -rf $*-C



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]