summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2011-02-01 16:12:30 -0200
committerLaszlo Pandy <lpandy@src.gnome.org>2011-08-11 10:29:23 +0200
commit6a0a3f54db9a20cad02e954355cfb93ded1eb4dd (patch)
treeee2f588601bcc3a0b8b4cead722594107b71a31f
parentd19fcd098ed69d9216efbf68fc8ae4ba57d09638 (diff)
downloadgobject-introspection-6a0a3f54db9a20cad02e954355cfb93ded1eb4dd.tar.gz
WIP doctool
https://bugzilla.gnome.org/show_bug.cgi?id=625494
-rw-r--r--Makefile-giscanner.am2
-rw-r--r--Makefile-tools.am14
-rw-r--r--giscanner/docbookwriter.py251
-rw-r--r--giscanner/docmain.py66
-rw-r--r--tools/g-ir-doc-tool.in43
5 files changed, 373 insertions, 3 deletions
diff --git a/Makefile-giscanner.am b/Makefile-giscanner.am
index 0ca98f6c..4b98ecd3 100644
--- a/Makefile-giscanner.am
+++ b/Makefile-giscanner.am
@@ -33,6 +33,8 @@ pkgpyexec_PYTHON = \
giscanner/ast.py \
giscanner/cachestore.py \
giscanner/codegen.py \
+ giscanner/docbookwriter.py \
+ giscanner/docmain.py \
giscanner/dumper.py \
giscanner/introspectablepass.py \
giscanner/girparser.py \
diff --git a/Makefile-tools.am b/Makefile-tools.am
index 7bc2f3f6..84858c84 100644
--- a/Makefile-tools.am
+++ b/Makefile-tools.am
@@ -1,6 +1,10 @@
bin_PROGRAMS += g-ir-compiler g-ir-generate
-bin_SCRIPTS += g-ir-scanner g-ir-annotation-tool
-EXTRA_DIST += tools/g-ir-scanner.in tools/g-ir-annotation-tool.in
+bin_SCRIPTS += g-ir-scanner g-ir-annotation-tool g-ir-doc-tool
+
+EXTRA_DIST += \
+ tools/g-ir-scanner.in \
+ tools/g-ir-annotation-tool.in \
+ tools/g-ir-doc-tool.in
TOOL_SUBSTITUTIONS = sed -e s,@libdir\@,$(libdir), -e s,@datarootdir\@,$(datarootdir), -e s,@PYTHON\@,$(PYTHON),
@@ -12,6 +16,10 @@ g-ir-annotation-tool: tools/g-ir-annotation-tool.in _giscanner.la Makefile
$(AM_V_GEN) $(TOOL_SUBSTITUTIONS) $< > $@.tmp && mv $@.tmp $@
@chmod a+x $@
+g-ir-doc-tool: tools/g-ir-doc-tool.in _giscanner.la Makefile
+ $(AM_V_GEN) sed -e s,@libdir\@,$(libdir), -e s,@PYTHON\@,$(PYTHON), $< > $@.tmp && mv $@.tmp $@
+ @chmod a+x $@
+
g_ir_compiler_SOURCES = tools/compiler.c
g_ir_compiler_CPPFLAGS = -DGIREPO_DEFAULT_SEARCH_PATH="\"$(libdir)\"" \
-I$(top_srcdir)/girepository
@@ -34,4 +42,4 @@ GCOVSOURCES = \
$(g_ir_compiler_SOURCES) \
$(g_ir_generate_SOURCES)
-CLEANFILES += g-ir-scanner g-ir-annotation-tool
+CLEANFILES += g-ir-scanner g-ir-annotation-tool g-ir-doc-tool
diff --git a/giscanner/docbookwriter.py b/giscanner/docbookwriter.py
new file mode 100644
index 00000000..2ff8cdf2
--- /dev/null
+++ b/giscanner/docbookwriter.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2010 Zach Goldberg
+# Copyright (C) 2011 Johan Dahlin
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+import sys
+
+from . import ast
+from .girparser import GIRParser
+from .xmlwriter import XMLWriter
+
+XMLNS = "http://docbook.org/ns/docbook"
+XMLVERSION = "5.0"
+
+def _space(num):
+ return " " * num
+
+class DocBookFormatter(object):
+ def __init__(self, writer):
+ self._namespace = None
+ self._writer = writer
+
+ def set_namespace(self, namespace):
+ self._namespace = namespace
+
+ def get_type_string(self, type):
+ return str(type.ctype)
+
+ def render_parameter(self, param_type, param_name):
+ return "%s %s" % (param_type, param_name)
+
+ def _render_parameter(self, param):
+ self._writer.push_tag("parameter", [])
+ self._writer.push_tag("link", [("linkend", "%s" % (
+ param.type.ctype))])
+ self._writer.write_tag("type", [], self.get_type_string(param.type))
+ self._writer.pop_tag()
+
+ 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
+
+ self._render_parameter(param)
+ if not param == params[-1]:
+ comma = ", "
+ else:
+ comma = ""
+
+ self._writer.write_line(" %s%s" % (param.argname, comma))
+ self._writer.pop_tag()
+
+ self._writer.write_line(");\n")
+
+ def render_method(self, entity, link=False):
+ method = entity.get_ast()
+ self._writer.disable_whitespace()
+
+ retval_type = method.retval.type
+ link_dest = retval_type.ctype.replace("*", "")
+ 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", [],
+ self.get_type_string(method.retval.type))
+
+ self._writer.write_line(
+ _space(20 - len(self.get_type_string(method.retval.type))))
+
+ if link:
+ self._writer.write_tag("link", [("linkend",
+ "%s-details" % (method.name))],
+ method.symbol)
+ else:
+ self._writer.write_line(method.symbol)
+
+ self._render_parameters(method, method.parameters)
+ self._writer.enable_whitespace()
+
+
+class DocBookPage(object):
+ def __init__(self, name, description=""):
+ self.entities = []
+ self.name = name
+ self.description = description
+
+ def add_entity(self, entity):
+ self.entities.append(entity)
+
+ def get_entities(self):
+ return self.entities
+
+
+class DocBookEntity(object):
+ def __init__(self, entity_name, entity_type, entity_ast):
+ self.entity_name = entity_name
+ self.entity_type = entity_type
+ self.entity_ast = entity_ast
+
+ def get_ast(self):
+ return self.entity_ast
+
+ def get_type(self):
+ return self.entity_type
+
+ def get_name(self):
+ return self.entity_name
+
+
+class DocBookWriter(object):
+ def __init__(self):
+ self._namespace = None
+ self._pages = []
+
+ self._writer = XMLWriter()
+ self._formatter = DocBookFormatter(self._writer)
+
+ def _add_page(self, page):
+ self._pages.append(page)
+
+ def add_namespace(self, namespace):
+ self._namespace = namespace
+ self._formatter.set_namespace(namespace)
+
+ page = DocBookPage(namespace.name,
+ ("Details about namespace should go here which are "
+ "not currently scanned by the gir"))
+ self._add_page(page)
+
+ for name, node in namespace.iteritems():
+ self._add_node(node, name)
+
+ def _add_node(self, node, name):
+ page = DocBookPage(name, node.doc)
+ self._add_page(page)
+
+ if isinstance(node, (ast.Class, ast.Record, ast.Interface)):
+ for method in node.methods:
+ method.parent_class = node
+ page.add_entity(DocBookEntity(method.name, "method", method))
+
+ def write(self, output):
+ with self._writer.tagcontext("book", [
+ ("xml:id", "page_%s" % self._namespace.name),
+ ("xmlns", XMLNS),
+ ("version", XMLVERSION)]):
+ self._writer.write_tag("title", [], "%s Documentation" % (
+ self._namespace.name))
+
+ for page in self._pages:
+ self._render_page(page)
+
+ fp = open(output, 'w')
+ fp.write(self._writer.get_xml())
+ fp.close()
+
+ def _render_page(self, page):
+ with self._writer.tagcontext("chapter", [("xml:id", "ch_%s" % (
+ page.name))]):
+ self._writer.write_tag(
+ "anchor", [("id", "ch_%s" % (page.name))])
+ self._writer.write_tag(
+ "anchor", [("id", "%s%s" % (self._namespace.name, page.name))])
+ self._writer.write_tag(
+ "title", [], "%s %s" % (self._namespace.name, page.name))
+
+ with self._writer.tagcontext("refsynopsisdiv", [
+ ('id', '%s.synopsis' % page.name),
+ ('role', 'synopsis')
+ ]):
+ self._writer.write_tag(
+ "title", [("role", "synopsis.title")], "Synopsis")
+ with self._writer.tagcontext('synopsis'):
+ for entity in page.get_entities():
+ self._formatter.render_method(entity, link=True)
+
+ # if page.description:
+ # with self._writer.tagcontext(
+ # 'refsect1',
+ # [('id', '%s.description' % (page.name, )),
+ # ]):
+ # self._writer.write_tag(
+ # "title", [("role", "desc.title")], "Description")
+ # import cgi
+ # desc = page.description
+ # while True:
+ # start = desc.find('|[')
+ # if start == -1:
+ # break
+ # end = desc.find(']|')
+ # desc = desc[:start] + cgi.escape(desc[start+2:end]) + desc[end+2:]
+ # desc = desc.replace("&", "&amp;")
+ # self._writer.write_line(desc)
+
+ for entity in page.get_entities():
+ self._render_entity(entity)
+
+ def _render_entity(self, entity):
+ with self._writer.tagcontext('refsect1',
+ [('id', "%s-details" % (entity.get_name())),
+ ("role", "details")]):
+ self._writer.write_tag("title", [("role", "details.title")],
+ "Details")
+
+ self._writer.push_tag('refsect2',
+ [('id', "%s-function" % entity.get_name()),
+ ('role', 'struct')])
+ self._writer.write_tag("title", [], entity.get_name())
+
+ with self._writer.tagcontext("indexterm",
+ [("zone", "%s" % entity.get_name())]):
+ self._writer.write_tag("primary", [], entity.get_name())
+
+ with self._writer.tagcontext("programlisting"):
+ self._formatter.render_method(entity)
+
+ self._writer.write_tag("para", [], entity.get_ast().doc)
+ self._writer.pop_tag()
diff --git a/giscanner/docmain.py b/giscanner/docmain.py
new file mode 100644
index 00000000..8e54d7ad
--- /dev/null
+++ b/giscanner/docmain.py
@@ -0,0 +1,66 @@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2008-2011 Johan Dahlin
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+import optparse
+
+from .docbookwriter import DocBookWriter
+from .girparser import GIRParser
+
+class GIDocGenerator(object):
+
+ def parse(self, filename):
+ self.parser = GIRParser()
+ self.parser.parse(filename)
+
+ def generate(self, writer, output):
+ ns = self.parser.get_namespace()
+ writer.add_namespace(ns)
+ writer.write(output)
+
+
+def doc_main(args):
+ parser = optparse.OptionParser('%prog [options] sources')
+
+ 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")
+
+ options, args = parser.parse_args(args)
+ if not options.output:
+ raise SystemExit("missing output parameter")
+
+ if len(args) < 2:
+ raise SystemExit("Need an input gir filename")
+
+ if options.format == "docbook":
+ writer = DocBookWriter()
+ else:
+ raise SystemExit("Unsupported output format: %s" % (options.format, ))
+
+ generator = GIDocGenerator()
+ generator.parse(args[1])
+
+ generator.generate(writer, options.output)
+
+ return 0
diff --git a/tools/g-ir-doc-tool.in b/tools/g-ir-doc-tool.in
new file mode 100644
index 00000000..dcf01128
--- /dev/null
+++ b/tools/g-ir-doc-tool.in
@@ -0,0 +1,43 @@
+#!@PYTHON@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2008 Johan Dahlin
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+import os
+import sys
+
+if 'GI_SCANNER_DEBUG' in os.environ:
+ def on_exception(exctype, value, tb):
+ print "Caught exception: %r %r" % (exctype, value)
+ import pdb
+ pdb.pm()
+ sys.excepthook = on_exception
+
+srcdir = os.getenv('UNINSTALLED_INTROSPECTION_SRCDIR', None)
+if srcdir is not None:
+ path = srcdir
+else:
+ # This is a private directory, we don't want to pollute the global
+ # namespace.
+ path = os.path.join('@libdir@', 'gobject-introspection')
+sys.path.insert(0, path)
+
+from giscanner.docmain import doc_main
+
+sys.exit(doc_main(sys.argv))