diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2015-12-12 23:30:45 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2015-12-12 23:30:45 +0100 |
commit | aeb5ea59340f91ae445330c95429f903a8f20e8a (patch) | |
tree | 09e0e73b3faedfbbaed8823137a0935c56a61930 /doc/tools | |
parent | fb00cee33bd29969805572238815c0fb3d29ee45 (diff) |
Move documentation python tools to doc/tools folder
Diffstat (limited to 'doc/tools')
-rw-r--r-- | doc/tools/doc_merge.py | 208 | ||||
-rw-r--r-- | doc/tools/locales/es/LC_MESSAGES/makedocs.mo | bin | 0 -> 2321 bytes | |||
-rw-r--r-- | doc/tools/locales/es/LC_MESSAGES/makedocs.po | 142 | ||||
-rw-r--r-- | doc/tools/main.css | 146 | ||||
-rw-r--r-- | doc/tools/makedocs.pot | 108 | ||||
-rw-r--r-- | doc/tools/makedocs.py | 382 | ||||
-rw-r--r-- | doc/tools/makedoku.py | 511 | ||||
-rw-r--r-- | doc/tools/makehtml.py | 717 | ||||
-rw-r--r-- | doc/tools/makemd.py | 345 |
9 files changed, 2559 insertions, 0 deletions
diff --git a/doc/tools/doc_merge.py b/doc/tools/doc_merge.py new file mode 100644 index 0000000000..872f38ed87 --- /dev/null +++ b/doc/tools/doc_merge.py @@ -0,0 +1,208 @@ +import sys +import xml.etree.ElementTree as ET + + +tree = ET.parse(sys.argv[1]) +old_doc=tree.getroot() + +tree = ET.parse(sys.argv[2]) +new_doc=tree.getroot() + +f = file(sys.argv[3],"wb") +tab=0 + +old_classes={} + +def write_string(_f, text,newline=True): + for t in range(tab): + _f.write("\t") + _f.write(text) + if (newline): + _f.write("\n") + +def escape(ret): + ret=ret.replace("&","&"); + ret=ret.replace("<",">"); + ret=ret.replace(">","<"); + ret=ret.replace("'","'"); + ret=ret.replace("\"","""); + return ret + + +def inc_tab(): + global tab + tab+=1 + +def dec_tab(): + global tab + tab-=1 + +write_string(f,'<?xml version="1.0" encoding="UTF-8" ?>') +write_string(f,'<doc version="'+new_doc.attrib["version"]+'">') + +def get_tag(node,name): + tag="" + if (name in node.attrib): + tag=' '+name+'="'+escape(node.attrib[name])+'" ' + return tag + +def find_method_descr(old_class,name): + + methods = old_class.find("methods") + if(methods!=None and len(list(methods))>0): + for m in list(methods): + if (m.attrib["name"]==name): + description=m.find("description") + if (description!=None and description.text.strip()!=""): + return description.text + + return None + +def find_signal_descr(old_class,name): + + signals = old_class.find("signals") + if(signals!=None and len(list(signals))>0): + for m in list(signals): + if (m.attrib["name"]==name): + description=m.find("description") + if (description!=None and description.text.strip()!=""): + return description.text + + return None + +def find_constant_descr(old_class,name): + + if (old_class==None): + return None + constants = old_class.find("constants") + if(constants!=None and len(list(constants))>0): + for m in list(constants): + if (m.attrib["name"]==name): + if (m.text.strip()!=""): + return m.text + return None + +def write_class(c): + class_name = c.attrib["name"] + print("Parsing Class: "+class_name) + if (class_name in old_classes): + old_class=old_classes[class_name] + else: + old_class=None + + + category=get_tag(c,"category") + inherits=get_tag(c,"inherits") + write_string(f,'<class name="'+class_name+'" '+category+inherits+'>') + inc_tab() + + write_string(f,"<brief_description>") + + if (old_class!=None): + old_brief_descr=old_class.find("brief_description") + if (old_brief_descr!=None): + write_string(f,escape(old_brief_descr.text.strip())) + + + write_string(f,"</brief_description>") + + write_string(f,"<description>") + if (old_class!=None): + old_descr=old_class.find("description") + if (old_descr!=None): + write_string(f,escape(old_descr.text.strip())) + + write_string(f,"</description>") + + methods = c.find("methods") + if(methods!=None and len(list(methods))>0): + + write_string(f,"<methods>") + inc_tab() + + for m in list(methods): + qualifiers=get_tag(m,"qualifiers") + + write_string(f,'<method name="'+escape(m.attrib["name"])+'" ' +qualifiers+'>') + inc_tab() + + for a in list(m): + if (a.tag=="return"): + typ=get_tag(a,"type") + write_string(f,'<return'+typ+'>'); + write_string(f,'</return>'); + elif (a.tag=="argument"): + + default=get_tag(a,"default") + + write_string(f,'<argument index="'+a.attrib["index"]+'" name="'+escape(a.attrib["name"])+'" type="'+a.attrib["type"]+'"' +default+'>'); + write_string(f,'</argument>'); + + write_string(f,'<description>'); + if (old_class!=None): + old_method_descr=find_method_descr(old_class,m.attrib["name"]) + if (old_method_descr): + write_string(f,escape(escape(old_method_descr.strip()))) + + write_string(f,'</description>'); + dec_tab() + write_string(f,"</method>") + dec_tab() + write_string(f,"</methods>") + + signals = c.find("signals") + if(signals!=None and len(list(signals))>0): + + write_string(f,"<signals>") + inc_tab() + + for m in list(signals): + + write_string(f,'<signal name="'+escape(m.attrib["name"])+'">') + inc_tab() + + for a in list(m): + if (a.tag=="argument"): + + write_string(f,'<argument index="'+a.attrib["index"]+'" name="'+escape(a.attrib["name"])+'" type="'+a.attrib["type"]+'">'); + write_string(f,'</argument>'); + + write_string(f,'<description>'); + if (old_class!=None): + old_signal_descr=find_signal_descr(old_class,m.attrib["name"]) + if (old_signal_descr): + write_string(f,escape(old_signal_descr.strip())) + write_string(f,'</description>'); + dec_tab() + write_string(f,"</signal>") + dec_tab() + write_string(f,"</signals>") + + constants = c.find("constants") + if(constants!=None and len(list(constants))>0): + + write_string(f,"<constants>") + inc_tab() + + for m in list(constants): + + write_string(f,'<constant name="'+escape(m.attrib["name"])+'" value="'+m.attrib["value"]+'">') + old_constant_descr=find_constant_descr(old_class,m.attrib["name"]) + if (old_constant_descr): + write_string(f,escape(old_constant_descr.strip())) + write_string(f,"</constant>") + + dec_tab() + write_string(f,"</constants>") + + dec_tab() + write_string(f,"</class>") + +for c in list(old_doc): + old_classes[c.attrib["name"]]=c + +for c in list(new_doc): + write_class(c) +write_string(f,'</doc>\n') + + diff --git a/doc/tools/locales/es/LC_MESSAGES/makedocs.mo b/doc/tools/locales/es/LC_MESSAGES/makedocs.mo Binary files differnew file mode 100644 index 0000000000..8d7ea2689e --- /dev/null +++ b/doc/tools/locales/es/LC_MESSAGES/makedocs.mo diff --git a/doc/tools/locales/es/LC_MESSAGES/makedocs.po b/doc/tools/locales/es/LC_MESSAGES/makedocs.po new file mode 100644 index 0000000000..82115dd897 --- /dev/null +++ b/doc/tools/locales/es/LC_MESSAGES/makedocs.po @@ -0,0 +1,142 @@ +# Translations template for PROJECT. +# Copyright (C) 2015 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: makedocs\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2015-10-07 11:47-0600\n" +"PO-Revision-Date: 2015-10-07 13:10-0600\n" +"Last-Translator: Jorge Araya Navarro <elcorreo@deshackra.com>\n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.0\n" +"X-Generator: Poedit 1.8.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: makedocs.py:74 +msgid "" +"\"<code>{gclass}</code>(Go to page of class {gclass})\":/class_{lkclass}" +msgstr "" +"\"<code>{gclass}</code>(Ir a la pagina de la clase {gclass})\":/" +"class_{lkclass}" + +#: makedocs.py:76 +msgid "" +"\"<code>{gclass}.{method}</code>(Go to page {gclass}, section {method})\":/" +"class_{lkclass}#{lkmethod}" +msgstr "" +"\"<code>{gclass}.{method}</code>(Ir a la pagina {gclass}, sección " +"{method})\":/class_{lkclass}#{lkmethod}" + +#: makedocs.py:79 +msgid "\"<code>{method}</code>(Jump to method {method})\":#{lkmethod}" +msgstr "\"<code>{method}</code>(Saltar al método {method})\":#{lkmethod}" + +#: makedocs.py:81 +msgid " \"{rtype}(Go to page of class {rtype})\":/class_{link} " +msgstr " \"{rtype}(Ir a la pagina de la clase {rtype})\":/class_{link} " + +#: makedocs.py:82 +msgid "" +"\"*{funcname}*(Jump to description for node {funcname})\":#{link} <b>(</b> " +msgstr "" +"\"*{funcname}*(Saltar a la descripción para el nodo {funcname})\":#{link} " +"<b>(</b> " + +#: makedocs.py:87 +msgid "h4. Inherits: " +msgstr "h4. Hereda de: " + +#: makedocs.py:232 +msgid "<doc>'s version attribute missing" +msgstr "El atributo version de <doc> no existe" + +#: makedocs.py:246 +msgid "|_. Index symbol |_. Class name |_. Index symbol |_. Class name |\n" +msgstr "" +"|_. Índice de símbolo |_. Nombre de la clase |_. Índice de símbolo |_. " +"Nombre de la clase |\n" + +#: makedocs.py:305 +msgid "" +"h4. Category: {}\n" +"\n" +msgstr "" +"h4. Categoría: {}\n" +"\n" + +#: makedocs.py:310 +msgid "" +"h2. Brief Description\n" +"\n" +msgstr "" +"h2. Descripción breve\n" +"\n" + +#: makedocs.py:312 +msgid "" +"\"read more\":#more\n" +"\n" +msgstr "" +"\"Leer más\":#more\n" +"\n" + +#: makedocs.py:317 +msgid "" +"\n" +"h3. Member Functions\n" +"\n" +msgstr "" +"\n" +"h3. Funciones miembro\n" +"\n" + +#: makedocs.py:323 +msgid "" +"\n" +"h3. Signals\n" +"\n" +msgstr "" +"\n" +"h3. Señales\n" +"\n" + +#: makedocs.py:331 +msgid "" +"\n" +"h3. Numeric Constants\n" +"\n" +msgstr "" +"\n" +"h3. Constantes numéricas\n" +"\n" + +#: makedocs.py:347 +msgid "" +"\n" +"h3(#more). Description\n" +"\n" +msgstr "" +"\n" +"h3(#more). Descripción\n" +"\n" + +#: makedocs.py:351 +msgid "_Nothing here, yet..._\n" +msgstr "_Aún nada por aquí..._\n" + +#: makedocs.py:355 +msgid "" +"\n" +"h3. Member Function Description\n" +"\n" +msgstr "" +"\n" +"h3. Descripción de las funciones miembro\n" +"\n" diff --git a/doc/tools/main.css b/doc/tools/main.css new file mode 100644 index 0000000000..a76e6bbed8 --- /dev/null +++ b/doc/tools/main.css @@ -0,0 +1,146 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV, SPAN { + font-family: Arial, Geneva, Helvetica, sans-serif; +} + +a { + + text-decoration: none; + +} + +a:hover { + + text-decoration: underline; +} + +td.top_table { + + padding: 5px; +} + +div.method_doc { + + padding-bottom: 30px; +} + +div.method_description { + margin-left: 30px; +} + +list.inh_class_list { + margin-left: 30px; + +} + +div.inh_class_list { + margin-left: 30px; + +} + +div.method_doc div.method { + + font-size: 12pt; + font-weight: bold; +} + +span.funcdecl { + + color: #202060; +} + +span.funcdef { + + color: #202060; +} + + +span.qualifier { + + font-weight: bold; +} + + +span.symbol { + + /*font-weight: bold;*/ + color: #471870; +} + + +span.datatype { + + color: #6a1533; +} + +tr.category_title { + + background-color: #333333; +} +a.category_title { + font-weight: bold; + color: #FFFFFF; +} + +div.method_list { + + margin-left: 30px; +} + +div.constant_list { + + margin-left: 30px; +} + +div.member_list { + + margin-left: 30px; +} + +div.description { + + margin-left: 30px; +} + +div.class_description { + + margin-left: 30px; +} + +div.method_list li div { + + display: inline; +} + +div.member_list li div.member { + + display: inline; +} + +div.constant_list li div.constant { + + display: inline; +} + +span.member_description { + + font-style: italic; + color: grey; +} + +span.constant_description { + + font-style: italic; + color: grey; +} + +span.identifier { + + font-weight: bold; +} + + +table.class_table td { + + vertical-align: top; +} + diff --git a/doc/tools/makedocs.pot b/doc/tools/makedocs.pot new file mode 100644 index 0000000000..be3220f686 --- /dev/null +++ b/doc/tools/makedocs.pot @@ -0,0 +1,108 @@ +# Translations template for PROJECT. +# Copyright (C) 2015 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2015. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: makedocs 0.1\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2015-10-07 11:47-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.0\n" +"X-Generator: Poedit 1.8.4\n" + +#: makedocs.py:74 +msgid "\"<code>{gclass}</code>(Go to page of class {gclass})\":/class_{lkclass}" +msgstr "" + +#: makedocs.py:76 +msgid "\"<code>{gclass}.{method}</code>(Go to page {gclass}, section {method})\":/class_{lkclass}#{lkmethod}" +msgstr "" + +#: makedocs.py:79 +msgid "\"<code>{method}</code>(Jump to method {method})\":#{lkmethod}" +msgstr "" + +#: makedocs.py:81 +msgid " \"{rtype}(Go to page of class {rtype})\":/class_{link} " +msgstr "" + +#: makedocs.py:82 +msgid "\"*{funcname}*(Jump to description for node {funcname})\":#{link} <b>(</b> " +msgstr "" + +#: makedocs.py:87 +msgid "h4. Inherits: " +msgstr "" + +#: makedocs.py:232 +msgid "<doc>'s version attribute missing" +msgstr "" + +#: makedocs.py:246 +msgid "|_. Index symbol |_. Class name |_. Index symbol |_. Class name |\n" +msgstr "" + +#: makedocs.py:305 +msgid "" +"h4. Category: {}\n" +"\n" +msgstr "" + +#: makedocs.py:310 +msgid "" +"h2. Brief Description\n" +"\n" +msgstr "" + +#: makedocs.py:312 +msgid "" +"\"read more\":#more\n" +"\n" +msgstr "" + +#: makedocs.py:317 +msgid "" +"\n" +"h3. Member Functions\n" +"\n" +msgstr "" + +#: makedocs.py:323 +msgid "" +"\n" +"h3. Signals\n" +"\n" +msgstr "" + +#: makedocs.py:331 +msgid "" +"\n" +"h3. Numeric Constants\n" +"\n" +msgstr "" + +#: makedocs.py:347 +msgid "" +"\n" +"h3(#more). Description\n" +"\n" +msgstr "" + +#: makedocs.py:351 +msgid "_Nothing here, yet..._\n" +msgstr "" + +#: makedocs.py:355 +msgid "" +"\n" +"h3. Member Function Description\n" +"\n" +msgstr "" diff --git a/doc/tools/makedocs.py b/doc/tools/makedocs.py new file mode 100644 index 0000000000..be57891abc --- /dev/null +++ b/doc/tools/makedocs.py @@ -0,0 +1,382 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +# +# makedocs.py: Generate documentation for Open Project Wiki +# Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. +# Contributor: Jorge Araya Navarro <elcorreo@deshackra.com> +# + +# IMPORTANT NOTICE: +# If you are going to modify anything from this file, please be sure to follow +# the Style Guide for Python Code or often called "PEP8". To do this +# automagically just install autopep8: +# +# $ sudo pip3 install autopep8 +# +# and run: +# +# $ autopep8 makedocs.py +# +# Before committing your changes. Also be sure to delete any trailing +# whitespace you may left. +# +# TODO: +# * Refactor code. +# * Adapt this script for generating content in other markup formats like +# DokuWiki, Markdown, etc. +# +# Also check other TODO entries in this script for more information on what is +# left to do. +import argparse +import gettext +import logging +import re +from itertools import zip_longest +from os import path, listdir +from xml.etree import ElementTree + + +# add an option to change the verbosity +logging.basicConfig(level=logging.INFO) + + +def getxmlfloc(): + """ Returns the supposed location of the XML file + """ + filepath = path.dirname(path.abspath(__file__)) + return path.join(filepath, "class_list.xml") + + +def langavailable(): + """ Return a list of languages available for translation + """ + filepath = path.join( + path.dirname(path.abspath(__file__)), "locales") + files = listdir(filepath) + choices = [x for x in files] + choices.insert(0, "none") + return choices + + +desc = "Generates documentation from a XML file to different markup languages" + +parser = argparse.ArgumentParser(description=desc) +parser.add_argument("--input", dest="xmlfp", default=getxmlfloc(), + help="Input XML file, default: {}".format(getxmlfloc())) +parser.add_argument("--output-dir", dest="outputdir", required=True, + help="Output directory for generated files") +parser.add_argument("--language", choices=langavailable(), default="none", + help=("Choose the language of translation" + " for the output files. Default is English (none). " + "Note: This is NOT for the documentation itself!")) +# TODO: add an option for outputting different markup formats + +args = parser.parse_args() +# Let's check if the file and output directory exists +if not path.isfile(args.xmlfp): + logging.critical("File not found: {}".format(args.xmlfp)) + exit(1) +elif not path.isdir(args.outputdir): + logging.critical("Path does not exist: {}".format(args.outputdir)) + exit(1) + +_ = gettext.gettext +if args.language != "none": + lang = gettext.translation(domain="makedocs", + localedir="locales", + languages=[args.language]) + lang.install() + + _ = lang.gettext + +# Strings +C_LINK = _("\"<code>{gclass}</code>(Go to page of class" + " {gclass})\":/class_{lkclass}") +MC_LINK = _("\"<code>{gclass}.{method}</code>(Go " + "to page {gclass}, section {method})\"" + ":/class_{lkclass}#{lkmethod}") +TM_JUMP = _("\"<code>{method}</code>(Jump to method" + " {method})\":#{lkmethod}") +GTC_LINK = _(" \"{rtype}(Go to page of class {rtype})\":/class_{link} ") +DFN_JUMP = _("\"*{funcname}*(Jump to description for" + " node {funcname})\":#{link} <b>(</b> ") +M_ARG_DEFAULT = C_LINK + " {name}={default}" +M_ARG = C_LINK + " {name}" + +OPENPROJ_INH = _("h4. Inherits: ") + C_LINK + "\n\n" + + +def tb(string): + """ Return a byte representation of a string + """ + return bytes(string, "UTF-8") + + +def sortkey(c): + """ Symbols are first, letters second + """ + if "_" == c.attrib["name"][0]: + return "A" + else: + return c.attrib["name"] + + +def toOP(text): + """ Convert commands in text to Open Project commands + """ + # TODO: Make this capture content between [command] ... [/command] + groups = re.finditer((r'\[html (?P<command>/?\w+/?)(\]| |=)?(\]| |=)?(?P<a' + 'rg>\w+)?(\]| |=)?(?P<value>"[^"]+")?/?\]'), text) + alignstr = "" + for group in groups: + gd = group.groupdict() + if gd["command"] == "br/": + text = text.replace(group.group(0), "\n\n", 1) + elif gd["command"] == "div": + if gd["value"] == '"center"': + alignstr = ("{display:block; margin-left:auto;" + " margin-right:auto;}") + elif gd["value"] == '"left"': + alignstr = "<" + elif gd["value"] == '"right"': + alignstr = ">" + text = text.replace(group.group(0), "\n\n", 1) + elif gd["command"] == "/div": + alignstr = "" + text = text.replace(group.group(0), "\n\n", 1) + elif gd["command"] == "img": + text = text.replace(group.group(0), "!{align}{src}!".format( + align=alignstr, src=gd["value"].strip('"')), 1) + elif gd["command"] == "b" or gd["command"] == "/b": + text = text.replace(group.group(0), "*", 1) + elif gd["command"] == "i" or gd["command"] == "/i": + text = text.replace(group.group(0), "_", 1) + elif gd["command"] == "u" or gd["command"] == "/u": + text = text.replace(group.group(0), "+", 1) + # Process other non-html commands + groups = re.finditer((r'\[method ((?P<class>[aA0-zZ9_]+)(?:\.))' + r'?(?P<method>[aA0-zZ9_]+)\]'), text) + for group in groups: + gd = group.groupdict() + if gd["class"]: + replacewith = (MC_LINK.format(gclass=gd["class"], + method=gd["method"], + lkclass=gd["class"].lower(), + lkmethod=gd["method"].lower())) + else: + # The method is located in the same wiki page + replacewith = (TM_JUMP.format(method=gd["method"], + lkmethod=gd["method"].lower())) + + text = text.replace(group.group(0), replacewith, 1) + # Finally, [Classes] are around brackets, make them direct links + groups = re.finditer(r'\[(?P<class>[az0-AZ0_]+)\]', text) + for group in groups: + gd = group.groupdict() + replacewith = (C_LINK. + format(gclass=gd["class"], + lkclass=gd["class"].lower())) + text = text.replace(group.group(0), replacewith, 1) + + return text + "\n\n" + + +def mkfn(node, is_signal=False): + """ Return a string containing a unsorted item for a function + """ + finalstr = "" + name = node.attrib["name"] + rtype = node.find("return") + if rtype: + rtype = rtype.attrib["type"] + else: + rtype = "void" + # write the return type and the function name first + finalstr += "* " + # return type + if not is_signal: + if rtype != "void": + finalstr += GTC_LINK.format( + rtype=rtype, + link=rtype.lower()) + else: + finalstr += " void " + + # function name + if not is_signal: + finalstr += DFN_JUMP.format( + funcname=name, + link=name.lower()) + else: + # Signals have no description + finalstr += "*{funcname}* <b>(</b>".format(funcname=name) + # loop for the arguments of the function, if any + args = [] + for arg in sorted( + node.iter(tag="argument"), + key=lambda a: int(a.attrib["index"])): + + ntype = arg.attrib["type"] + nname = arg.attrib["name"] + + if "default" in arg.attrib: + args.insert(-1, M_ARG_DEFAULT.format( + gclass=ntype, + lkclass=ntype.lower(), + name=nname, + default=arg.attrib["default"])) + else: + # No default value present + args.insert(-1, M_ARG.format(gclass=ntype, + lkclass=ntype.lower(), name=nname)) + # join the arguments together + finalstr += ", ".join(args) + # and, close the function with a ) + finalstr += " <b>)</b>" + # write the qualifier, if any + if "qualifiers" in node.attrib: + qualifier = node.attrib["qualifiers"] + finalstr += " " + qualifier + + finalstr += "\n" + + return finalstr + +# Let's begin +tree = ElementTree.parse(args.xmlfp) +root = tree.getroot() + +# Check version attribute exists in <doc> +if "version" not in root.attrib: + logging.critical(_("<doc>'s version attribute missing")) + exit(1) + +version = root.attrib["version"] +classes = sorted(root, key=sortkey) +# first column is always longer, second column of classes should be shorter +zclasses = zip_longest(classes[:int(len(classes) / 2 + 1)], + classes[int(len(classes) / 2 + 1):], + fillvalue="") + +# We write the class_list file and also each class file at once +with open(path.join(args.outputdir, "class_list.txt"), "wb") as fcl: + # Write header of table + fcl.write(tb("|^.\n")) + fcl.write(tb(_("|_. Index symbol |_. Class name " + "|_. Index symbol |_. Class name |\n"))) + fcl.write(tb("|-.\n")) + + indexletterl = "" + indexletterr = "" + for gdclassl, gdclassr in zclasses: + # write a row # + # write the index symbol column, left + if indexletterl != gdclassl.attrib["name"][0]: + indexletterl = gdclassl.attrib["name"][0] + fcl.write(tb("| *{}* |".format(indexletterl.upper()))) + else: + # empty cell + fcl.write(tb("| |")) + # write the class name column, left + fcl.write(tb(C_LINK.format( + gclass=gdclassl.attrib["name"], + lkclass=gdclassl.attrib["name"].lower()))) + + # write the index symbol column, right + if isinstance(gdclassr, ElementTree.Element): + if indexletterr != gdclassr.attrib["name"][0]: + indexletterr = gdclassr.attrib["name"][0] + fcl.write(tb("| *{}* |".format(indexletterr.upper()))) + else: + # empty cell + fcl.write(tb("| |")) + # We are dealing with an empty string + else: + # two empty cell + fcl.write(tb("| | |\n")) + # We won't get the name of the class since there is no ElementTree + # object for the right side of the tuple, so we iterate the next + # tuple instead + continue + + # write the class name column (if any), right + fcl.write(tb(C_LINK.format( + gclass=gdclassl.attrib["name"], + lkclass=gdclassl.attrib["name"].lower()) + "|\n")) + + # row written # + # now, let's write each class page for each class + for gdclass in [gdclassl, gdclassr]: + if not isinstance(gdclass, ElementTree.Element): + continue + + classname = gdclass.attrib["name"] + with open(path.join(args.outputdir, "{}.txt".format( + classname.lower())), "wb") as clsf: + # First level header with the name of the class + clsf.write(tb("h1. {}\n\n".format(classname))) + # lay the attributes + if "inherits" in gdclass.attrib: + inh = gdclass.attrib["inherits"].strip() + clsf.write(tb(OPENPROJ_INH.format(gclass=inh, + lkclass=inh.lower()))) + if "category" in gdclass.attrib: + clsf.write(tb(_("h4. Category: {}\n\n"). + format(gdclass.attrib["category"].strip()))) + # lay child nodes + briefd = gdclass.find("brief_description") + if briefd.text.strip(): + clsf.write(tb(_("h2. Brief Description\n\n"))) + clsf.write(tb(toOP(briefd.text.strip()) + + _("\"read more\":#more\n\n"))) + + # Write the list of member functions of this class + methods = gdclass.find("methods") + if methods and len(methods) > 0: + clsf.write(tb(_("\nh3. Member Functions\n\n"))) + for method in methods.iter(tag='method'): + clsf.write(tb(mkfn(method))) + + signals = gdclass.find("signals") + if signals and len(signals) > 0: + clsf.write(tb(_("\nh3. Signals\n\n"))) + for signal in signals.iter(tag='signal'): + clsf.write(tb(mkfn(signal, True))) + # TODO: <members> tag is necessary to process? it does not + # exists in class_list.xml file. + + consts = gdclass.find("constants") + if consts and len(consts) > 0: + clsf.write(tb(_("\nh3. Numeric Constants\n\n"))) + for const in sorted(consts, key=lambda k: + k.attrib["name"]): + if const.text.strip(): + clsf.write(tb("* *{name}* = *{value}* - {desc}\n". + format( + name=const.attrib["name"], + value=const.attrib["value"], + desc=const.text.strip()))) + else: + # Constant have no description + clsf.write(tb("* *{name}* = *{value}*\n". + format( + name=const.attrib["name"], + value=const.attrib["value"]))) + descrip = gdclass.find("description") + clsf.write(tb(_("\nh3(#more). Description\n\n"))) + if descrip.text: + clsf.write(tb(descrip.text.strip() + "\n")) + else: + clsf.write(tb(_("_Nothing here, yet..._\n"))) + + # and finally, the description for each method + if methods and len(methods) > 0: + clsf.write(tb(_("\nh3. Member Function Description\n\n"))) + for method in methods.iter(tag='method'): + clsf.write(tb("h4(#{n}). {name}\n\n".format( + n=method.attrib["name"].lower(), + name=method.attrib["name"]))) + clsf.write(tb(mkfn(method) + "\n")) + clsf.write(tb(toOP(method.find( + "description").text.strip()))) diff --git a/doc/tools/makedoku.py b/doc/tools/makedoku.py new file mode 100644 index 0000000000..e8207715fe --- /dev/null +++ b/doc/tools/makedoku.py @@ -0,0 +1,511 @@ +import sys +import xml.etree.ElementTree as ET + +input_list = [] + + +for arg in sys.argv[1:]: + input_list.append(arg) + +if len(input_list) < 1: + print("usage: makedoku.py <class_list.xml>") + sys.exit(0) + + +def validate_tag(elem,tag): + if (elem.tag != tag): + print("Tag mismatch, expected '"+tag+"', got "+elem.tag); + sys.exit(255) + + +class_names=[] +classes={} + + +def make_class_list(class_list,columns): + + f=open("class_list.txt","wb") + prev=0 + col_max = len(class_list) / columns + 1 + print("col max is ", col_max) + col_count = 0 + row_count = 0 + last_initial = "" + fit_columns=[] + + for n in range(0,columns): + fit_columns+=[[]] + + indexers=[] + last_initial="" + + idx=0 + for n in class_list: + col = idx/col_max + if (col>=columns): + col=columns-1 + fit_columns[col]+=[n] + idx+=1 + if (n[:1]!=last_initial): + indexers+=[n] + last_initial=n[:1] + + + row_max=0 + + for n in range(0,columns): + if (len(fit_columns[n])>row_max): + row_max=len(fit_columns[n]) + + + for r in range(0,row_max): + s="|" + for c in range(0,columns): + if (r>=len(fit_columns[c])): + continue + + classname = fit_columns[c][r] + initial=classname[0] + if (classname in indexers): + s+="**"+initial+"**|" + else: + s+=" |" + + s+="[["+classname.lower()+"|"+classname+"]]|" + + s+="\n" + f.write(s) + + +def dokuize_text(txt): + + return txt + + +def dokuize_text(text): + pos=0 + while(True): + pos = text.find("[",pos) + if (pos==-1): + break + + endq_pos=text.find("]",pos+1) + if (endq_pos==-1): + break + + pre_text=text[:pos] + post_text=text[endq_pos+1:] + tag_text=text[pos+1:endq_pos] + + if (tag_text in class_names): + tag_text="[["+tag_text.lower()+"|"+tag_text+"]]" + else: #command + cmd=tag_text + space_pos=tag_text.find(" ") + if (cmd.find("html")==0): + cmd=tag_text[:space_pos] + param=tag_text[space_pos+1:] + tag_text="<"+param+">" + elif(cmd.find("method")==0): + cmd=tag_text[:space_pos] + param=tag_text[space_pos+1:] + + if (param.find(".")!=-1): + class_param,method_param=param.split(".") + tag_text="[["+class_param.lower()+"#"+method_param+"|"+class_param+'.'+method_param+"]]" + else: + tag_text="[[#"+param+"|"+param+"]]" + elif (cmd.find("image=")==0): + tag_text="{{"+cmd[6:]+"}}" + elif (cmd.find("url=")==0): + tag_text="[["+cmd[4:]+"|" + elif (cmd=="/url"): + tag_text="]]>" + elif (cmd=="center"): + tag_text="" + elif (cmd=="/center"): + tag_text="" + elif (cmd=="br"): + tag_text="\\\\\n" + elif (cmd=="i" or cmd=="/i"): + tag_text="//" + elif (cmd=="b" or cmd=="/b"): + tag_text="**" + elif (cmd=="u" or cmd=="/u"): + tag_text="__" + else: + tag_text="["+tag_text+"]" + + + text=pre_text+tag_text+post_text + pos=len(pre_text)+len(tag_text) + + #tnode = ET.SubElement(parent,"div") + #tnode.text=text + return text + + +def make_type(t): + global class_names + if (t in class_names): + return "[["+t.lower()+"|"+t+"]]" + return t + + +def make_method(f,name,m,declare,event=False): + + s=" * " + ret_type="void" + args=list(m) + mdata={} + mdata["argidx"]=[] + for a in args: + if (a.tag=="return"): + idx=-1 + elif (a.tag=="argument"): + idx=int(a.attrib["index"]) + else: + continue + + mdata["argidx"].append(idx) + mdata[idx]=a + + + + if (not event): + if (-1 in mdata["argidx"]): + s+=make_type(mdata[-1].attrib["type"]) + else: + s+="void" + s+=" " + + if (declare): + + #span.attrib["class"]="funcdecl" + #a=ET.SubElement(span,"a") + #a.attrib["name"]=name+"_"+m.attrib["name"] + #a.text=name+"::"+m.attrib["name"] + s+="**"+m.attrib["name"]+"**" + else: + s+="[[#"+m.attrib["name"]+"|"+m.attrib["name"]+"]]" + + s+="**(**" + argfound=False + for a in mdata["argidx"]: + arg=mdata[a] + if (a<0): + continue + if (a>0): + s+=", " + else: + s+=" " + + s+=make_type(arg.attrib["type"]) + if ("name" in arg.attrib): + s+=" "+arg.attrib["name"] + else: + s+=" arg"+str(a) + + if ("default" in arg.attrib): + s+="="+arg.attrib["default"] + + + argfound=True + + if (argfound): + s+=" " + s+="**)**" + + if ("qualifiers" in m.attrib): + s+=" "+m.attrib["qualifiers"] + + f.write(s+"\n") + + +def make_doku_class(node): + + name = node.attrib["name"] + + f=open(name.lower()+".txt","wb") + + f.write("====== "+name+" ======\n") + + if ("inherits" in node.attrib): + inh=node.attrib["inherits"].strip() + f.write("**Inherits:** [["+inh.lower()+"|"+inh+"]]\\\\\n") + if ("category" in node.attrib): + f.write("**Category:** "+node.attrib["category"].strip()+"\\\\\n") + + briefd = node.find("brief_description") + if (briefd!=None): + f.write("===== Brief Description ======\n") + f.write( dokuize_text(briefd.text.strip())+"\n" ) + + methods = node.find("methods") + + if(methods!=None and len(list(methods))>0): + f.write("===== Member Functions ======\n") + for m in list(methods): + make_method(f,node.attrib["name"],m,False) + + events = node.find("signals") + if(events!=None and len(list(events))>0): + f.write("===== Signals ======\n") + for m in list(events): + make_method(f,node.attrib["name"],m,True,True) + + members = node.find("members") + + if(members!=None and len(list(members))>0): + f.write("===== Member Variables ======\n") + + for c in list(members): + s = " * " + s+=make_type(c.attrib["type"])+" " + s+="**"+c.attrib["name"]+"**" + if (c.text.strip()!=""): + s+=" - "+c.text.strip() + f.write(s+"\n") + + + + constants = node.find("constants") + if(constants!=None and len(list(constants))>0): + f.write("===== Numeric Constants ======\n") + for c in list(constants): + s = " * " + s+="**"+c.attrib["name"]+"**" + if ("value" in c.attrib): + s+=" = **"+c.attrib["value"]+"**" + if (c.text.strip()!=""): + s+=" - "+c.text.strip() + f.write(s+"\n") + + + descr=node.find("description") + if (descr!=None and descr.text.strip()!=""): + f.write("===== Description ======\n") + f.write(dokuize_text(descr.text.strip())+"\n") + + methods = node.find("methods") + + if(methods!=None and len(list(methods))>0): + f.write("===== Member Function Description ======\n") + for m in list(methods): + + d=m.find("description") + if (d==None or d.text.strip()==""): + continue + f.write("== "+m.attrib["name"]+" ==\n") + make_method(f,node.attrib["name"],m,False) + f.write("\\\\\n") + f.write(dokuize_text(d.text.strip())) + f.write("\n") + + + + + + """ + div=ET.Element("div") + div.attrib["class"]="class"; + + a=ET.SubElement(div,"a") + a.attrib["name"]=node.attrib["name"] + + h3=ET.SubElement(a,"h3") + h3.attrib["class"]="title class_title" + h3.text=node.attrib["name"] + + briefd = node.find("brief_description") + if (briefd!=None): + div2=ET.SubElement(div,"div") + div2.attrib["class"]="description class_description" + div2.text=briefd.text + + if ("inherits" in node.attrib): + ET.SubElement(div,"br") + + div2=ET.SubElement(div,"div") + div2.attrib["class"]="inheritance"; + + span=ET.SubElement(div2,"span") + span.text="Inherits: " + + make_type(node.attrib["inherits"],div2) + + if ("category" in node.attrib): + ET.SubElement(div,"br") + + div3=ET.SubElement(div,"div") + div3.attrib["class"]="category"; + + span=ET.SubElement(div3,"span") + span.attrib["class"]="category" + span.text="Category: " + + a = ET.SubElement(div3,"a") + a.attrib["class"]="category_ref" + a.text=node.attrib["category"] + catname=a.text + if (catname.rfind("/")!=-1): + catname=catname[catname.rfind("/"):] + catname="CATEGORY_"+catname + + if (single_page): + a.attrib["href"]="#"+catname + else: + a.attrib["href"]="category.html#"+catname + + + methods = node.find("methods") + + if(methods!=None and len(list(methods))>0): + + h4=ET.SubElement(div,"h4") + h4.text="Public Methods:" + + method_table=ET.SubElement(div,"table") + method_table.attrib["class"]="method_list"; + + for m in list(methods): +# li = ET.SubElement(div2, "li") + method_table.append( make_method_def(node.attrib["name"],m,False) ) + + events = node.find("signals") + + if(events!=None and len(list(events))>0): + h4=ET.SubElement(div,"h4") + h4.text="Events:" + + event_table=ET.SubElement(div,"table") + event_table.attrib["class"]="method_list"; + + for m in list(events): +# li = ET.SubElement(div2, "li") + event_table.append( make_method_def(node.attrib["name"],m,False,True) ) + + + members = node.find("members") + if(members!=None and len(list(members))>0): + + h4=ET.SubElement(div,"h4") + h4.text="Public Variables:" + div2=ET.SubElement(div,"div") + div2.attrib["class"]="member_list"; + + for c in list(members): + + li = ET.SubElement(div2, "li") + div3=ET.SubElement(li,"div") + div3.attrib["class"]="member"; + make_type(c.attrib["type"],div3) + span=ET.SubElement(div3,"span") + span.attrib["class"]="identifier member_name" + span.text=" "+c.attrib["name"]+" " + span=ET.SubElement(div3,"span") + span.attrib["class"]="member_description" + span.text=c.text + + + constants = node.find("constants") + if(constants!=None and len(list(constants))>0): + + h4=ET.SubElement(div,"h4") + h4.text="Constants:" + div2=ET.SubElement(div,"div") + div2.attrib["class"]="constant_list"; + + for c in list(constants): + li = ET.SubElement(div2, "li") + div3=ET.SubElement(li,"div") + div3.attrib["class"]="constant"; + + span=ET.SubElement(div3,"span") + span.attrib["class"]="identifier constant_name" + span.text=c.attrib["name"]+" " + if ("value" in c.attrib): + span=ET.SubElement(div3,"span") + span.attrib["class"]="symbol" + span.text="= " + span=ET.SubElement(div3,"span") + span.attrib["class"]="constant_value" + span.text=c.attrib["value"]+" " + span=ET.SubElement(div3,"span") + span.attrib["class"]="constant_description" + span.text=c.text + +# ET.SubElement(div,"br") + + + descr=node.find("description") + if (descr!=None and descr.text.strip()!=""): + + h4=ET.SubElement(div,"h4") + h4.text="Description:" + + make_text_def(node.attrib["name"],div,descr.text) +# div2=ET.SubElement(div,"div") +# div2.attrib["class"]="description"; +# div2.text=descr.text + + + + if(methods!=None or events!=None): + + h4=ET.SubElement(div,"h4") + h4.text="Method Documentation:" + iter_list = [] + if (methods!=None): + iter_list+=list(methods) + if (events!=None): + iter_list+=list(events) + + for m in iter_list: + + descr=m.find("description") + + if (descr==None or descr.text.strip()==""): + continue; + + div2=ET.SubElement(div,"div") + div2.attrib["class"]="method_doc"; + + + div2.append( make_method_def(node.attrib["name"],m,True) ) + #anchor = ET.SubElement(div2, "a") + #anchor.attrib["name"] = + make_text_def(node.attrib["name"],div2,descr.text) + #div3=ET.SubElement(div2,"div") + #div3.attrib["class"]="description"; + #div3.text=descr.text + + + return div +""" +for file in input_list: + tree = ET.parse(file) + doc=tree.getroot() + + if ("version" not in doc.attrib): + print("Version missing from 'doc'") + sys.exit(255) + + version=doc.attrib["version"] + + for c in list(doc): + if (c.attrib["name"] in class_names): + continue + class_names.append(c.attrib["name"]) + classes[c.attrib["name"]]=c + + +class_names.sort() + +make_class_list(class_names,4) + +for cn in class_names: + c=classes[cn] + make_doku_class(c) + + diff --git a/doc/tools/makehtml.py b/doc/tools/makehtml.py new file mode 100644 index 0000000000..9b9c62f33b --- /dev/null +++ b/doc/tools/makehtml.py @@ -0,0 +1,717 @@ +import sys +import xml.etree.ElementTree as ET +from xml.sax.saxutils import escape, unescape + +html_escape_table = { + '"': """, + "'": "'" +} + +html_unescape_table = {v:k for k, v in html_escape_table.items()} + +def html_escape(text): + return escape(text, html_escape_table) + +def html_unescape(text): + return unescape(text, html_unescape_table) + +input_list = [] + +single_page=True + +for arg in sys.argv[1:]: + if arg[:1] == "-": + if arg[1:] == "multipage": + single_page = False + if arg[1:] == "singlepage": + single_page = True + else: + input_list.append(arg) + +if len(input_list) < 1: + print("usage: makehtml.py <class_list.xml>") + sys.exit(0) + + +def validate_tag(elem,tag): + if (elem.tag != tag): + print("Tag mismatch, expected '"+tag+"', got "+elem.tag); + sys.exit(255) + +def make_html_bottom(body): + #make_html_top(body,True) + ET.SubElement(body,"hr") + copyright = ET.SubElement(body,"span") + copyright.text = "Copyright 2008-2010 Codenix SRL" + +def make_html_top(body,bottom=False): + + if (bottom): + ET.SubElement(body,"hr") + + table = ET.SubElement(body,"table") + table.attrib["class"]="top_table" + tr = ET.SubElement(table,"tr") + td = ET.SubElement(tr,"td") + td.attrib["class"]="top_table" + + img = ET.SubElement(td,"image") + img.attrib["src"]="images/logo.png" + td = ET.SubElement(tr,"td") + td.attrib["class"]="top_table" + a = ET.SubElement(td,"a") + a.attrib["href"]="index.html" + a.text="Index" + td = ET.SubElement(tr,"td") + td.attrib["class"]="top_table" + a = ET.SubElement(td,"a") + a.attrib["href"]="alphabetical.html" + a.text="Classes" + td = ET.SubElement(tr,"td") + td.attrib["class"]="top_table" + a = ET.SubElement(td,"a") + a.attrib["href"]="category.html" + a.text="Categories" + td = ET.SubElement(tr,"td") + a = ET.SubElement(td,"a") + a.attrib["href"]="inheritance.html" + a.text="Inheritance" + if (not bottom): + ET.SubElement(body,"hr") + + + + +def make_html_class_list(class_list,columns): + + div=ET.Element("div") + div.attrib["class"]="ClassList"; + + h1=ET.SubElement(div,"h2") + h1.text="Alphabetical Class List" + + table=ET.SubElement(div,"table") + table.attrib["class"]="class_table" + table.attrib["width"]="100%" + prev=0 + + col_max = len(class_list) / columns + 1 + print("col max is ", col_max) + col_count = 0 + row_count = 0 + last_initial = "" + fit_columns=[] + + for n in range(0,columns): + fit_columns+=[[]] + + indexers=[] + last_initial="" + + idx=0 + for n in class_list: + col = int(idx/col_max) + if (col>=columns): + col=columns-1 + fit_columns[col]+=[n] + idx+=1 + if (n[:1]!=last_initial): + indexers+=[n] + last_initial=n[:1] + + row_max=0 + + for n in range(0,columns): + if (len(fit_columns[n])>row_max): + row_max=len(fit_columns[n]) + + + for r in range(0,row_max): + tr = ET.SubElement(table,"tr") + for c in range(0,columns): + tdi = ET.SubElement(tr,"td") + tdi.attrib["align"]="right" + td = ET.SubElement(tr,"td") + if (r>=len(fit_columns[c])): + continue + + classname = fit_columns[c][r] + print(classname) + if (classname in indexers): + + span = ET.SubElement(tdi, "span") + span.attrib["class"] = "class_index_letter" + span.text = classname[:1].upper() + + if (single_page): + link="#"+classname + else: + link=classname+".html" + + a=ET.SubElement(td,"a") + a.attrib["href"]=link + a.text=classname + + + if (not single_page): + cat_class_list=ET.Element("html") + csscc = ET.SubElement(cat_class_list, "link") + csscc.attrib["href"] = "main.css" + csscc.attrib["rel"] = "stylesheet" + csscc.attrib["type"] = "text/css" + bodycc = ET.SubElement(cat_class_list, "body") + make_html_top(bodycc) + + cat_class_parent=bodycc + else: + cat_class_parent=div + + + + + h1=ET.SubElement(cat_class_parent,"h2") + h1.text="Class List By Category" + + class_cat_table={} + class_cat_list=[] + + for c in class_list: + clss = classes[c] + if ("category" in clss.attrib): + class_cat=clss.attrib["category"] + else: + class_cat="Core" + if (class_cat.find("/")!=-1): + class_cat=class_cat[class_cat.rfind("/")+1:] + if (not class_cat in class_cat_list): + class_cat_list.append(class_cat) + class_cat_table[class_cat]=[] + class_cat_table[class_cat].append(c) + + class_cat_list.sort() + + ct = ET.SubElement(cat_class_parent,"table") + for cl in class_cat_list: + l = class_cat_table[cl] + l.sort() + tr = ET.SubElement(ct,"tr") + tr.attrib["class"]="category_title" + td = ET.SubElement(ct,"td") + td.attrib["class"]="category_title" + + a = ET.SubElement(td,"a") + a.attrib["class"]="category_title" + a.text=cl + a.attrib["name"]="CATEGORY_"+cl + + td = ET.SubElement(ct,"td") + td.attrib["class"]="category_title" + + for clt in l: + tr = ET.SubElement(ct,"tr") + td = ET.SubElement(ct,"td") + make_type(clt,td) + clss=classes[clt] + bd = clss.find("brief_description") + bdtext="" + if (bd!=None): + bdtext=bd.text + td = ET.SubElement(ct,"td") + td.text=bdtext + + if (not single_page): + make_html_bottom(bodycc) + catet_out = ET.ElementTree(cat_class_list) + catet_out.write("category.html") + + + if (not single_page): + inh_class_list=ET.Element("html") + cssic = ET.SubElement(inh_class_list, "link") + cssic.attrib["href"] = "main.css" + cssic.attrib["rel"] = "stylesheet" + cssic.attrib["type"] = "text/css" + bodyic = ET.SubElement(inh_class_list, "body") + make_html_top(bodyic) + inh_class_parent=bodyic + else: + inh_class_parent=div + + + + + h1=ET.SubElement(inh_class_parent,"h2") + h1.text="Class List By Inheritance" + + itemlist = ET.SubElement(inh_class_parent,"list") + + class_inh_table={} + + def add_class(clss): + if (clss.attrib["name"] in class_inh_table): + return #already added + parent_list=None + + if ("inherits" in clss.attrib): + inhc = clss.attrib["inherits"] + if (not (inhc in class_inh_table)): + add_class(classes[inhc]) + + parent_list = class_inh_table[inhc].find("div") + if (parent_list == None): + parent_div = ET.SubElement(class_inh_table[inhc],"div") + parent_list = ET.SubElement(parent_div,"list") + parent_div.attrib["class"]="inh_class_list" + else: + parent_list = parent_list.find("list") + + + else: + parent_list=itemlist + + item = ET.SubElement(parent_list,"li") +# item.attrib["class"]="inh_class_list" + class_inh_table[clss.attrib["name"]]=item + make_type(clss.attrib["name"],item) + + + for c in class_list: + add_class(classes[c]) + + if (not single_page): + make_html_bottom(bodyic) + catet_out = ET.ElementTree(inh_class_list) + catet_out.write("inheritance.html") + + + + + + #h1=ET.SubElement(div,"h2") + #h1.text="Class List By Inheritance" + + return div + + +def make_type(p_type,p_parent): + if (p_type=="RefPtr"): + p_type="Resource" + + if (p_type in class_names): + a=ET.SubElement(p_parent,"a") + a.attrib["class"]="datatype_existing" + a.text=p_type+" " + if (single_page): + a.attrib["href"]="#"+p_type + else: + a.attrib["href"]=p_type+".html" + else: + span=ET.SubElement(p_parent,"span") + span.attrib["class"]="datatype" + span.text=p_type+" " + + + +def make_text_def(class_name,parent,text): + text = html_escape(text) + pos=0 + while(True): + pos = text.find("[",pos) + if (pos==-1): + break + + endq_pos=text.find("]",pos+1) + if (endq_pos==-1): + break + + pre_text=text[:pos] + post_text=text[endq_pos+1:] + tag_text=text[pos+1:endq_pos] + + if (tag_text in class_names): + if (single_page): + tag_text='<a href="#'+tag_text+'">'+tag_text+'</a>' + else: + tag_text='<a href="'+tag_text+'.html">'+tag_text+'</a>' + else: #command + cmd=tag_text + space_pos=tag_text.find(" ") + if (cmd.find("html")==0): + cmd=tag_text[:space_pos] + param=tag_text[space_pos+1:] + tag_text="<"+param+">" + elif(cmd.find("method")==0): + cmd=tag_text[:space_pos] + param=tag_text[space_pos+1:] + + if (not single_page and param.find(".")!=-1): + class_param,method_param=param.split(".") + tag_text=tag_text='<a href="'+class_param+'.html#'+class_param+"_"+method_param+'">'+class_param+'.'+method_param+'()</a>' + else: + tag_text=tag_text='<a href="#'+class_name+"_"+param+'">'+class_name+'.'+param+'()</a>' + elif (cmd.find("image=")==0): + print("found image: "+cmd) + tag_text="<img src="+cmd[6:]+"/>" + elif (cmd.find("url=")==0): + tag_text="<a href="+cmd[4:]+">" + elif (cmd=="/url"): + tag_text="</a>" + elif (cmd=="center"): + tag_text="<div align=\"center\">" + elif (cmd=="/center"): + tag_text="</div>" + elif (cmd=="br"): + tag_text="<br/>" + elif (cmd=="i" or cmd=="/i" or cmd=="b" or cmd=="/b" or cmd=="u" or cmd=="/u"): + tag_text="<"+tag_text+">" #html direct mapping + else: + tag_text="["+tag_text+"]" + + + text=pre_text+tag_text+post_text + pos=len(pre_text)+len(tag_text) + + #tnode = ET.SubElement(parent,"div") + #tnode.text=text + text="<div class=\"description\">"+text+"</div>" + try: + tnode=ET.XML(text) + parent.append(tnode) + except: + print("Error parsing description text: '"+text+"'") + sys.exit(255) + + + return tnode + + + + +def make_method_def(name,m,declare,event=False): + + mdata={} + + + if (not declare): + div=ET.Element("tr") + div.attrib["class"]="method" + ret_parent=ET.SubElement(div,"td") + ret_parent.attrib["align"]="right" + func_parent=ET.SubElement(div,"td") + else: + div=ET.Element("div") + div.attrib["class"]="method" + ret_parent=div + func_parent=div + + mdata["argidx"]=[] + mdata["name"]=m.attrib["name"] + qualifiers="" + if ("qualifiers" in m.attrib): + qualifiers=m.attrib["qualifiers"] + + args=list(m) + for a in args: + if (a.tag=="return"): + idx=-1 + elif (a.tag=="argument"): + idx=int(a.attrib["index"]) + else: + continue + + mdata["argidx"].append(idx) + mdata[idx]=a + + if (not event): + if (-1 in mdata["argidx"]): + make_type(mdata[-1].attrib["type"],ret_parent) + mdata["argidx"].remove(-1) + else: + make_type("void",ret_parent) + + span=ET.SubElement(func_parent,"span") + if (declare): + span.attrib["class"]="funcdecl" + a=ET.SubElement(span,"a") + a.attrib["name"]=name+"_"+m.attrib["name"] + a.text=name+"::"+m.attrib["name"] + else: + span.attrib["class"]="identifier funcdef" + a=ET.SubElement(span,"a") + a.attrib["href"]="#"+name+"_"+m.attrib["name"] + a.text=m.attrib["name"] + + span=ET.SubElement(func_parent,"span") + span.attrib["class"]="symbol" + span.text=" (" + + for a in mdata["argidx"]: + arg=mdata[a] + if (a>0): + span=ET.SubElement(func_parent,"span") + span.text=", " + else: + span=ET.SubElement(func_parent,"span") + span.text=" " + + + make_type(arg.attrib["type"],func_parent) + + span=ET.SubElement(func_parent,"span") + span.text=arg.attrib["name"] + if ("default" in arg.attrib): + span.text=span.text+"="+arg.attrib["default"] + + + span=ET.SubElement(func_parent,"span") + span.attrib["class"]="symbol" + if (len(mdata["argidx"])): + span.text=" )" + else: + span.text=")" + + if (qualifiers): + span=ET.SubElement(func_parent,"span") + span.attrib["class"]="qualifier" + span.text=" "+qualifiers + + return div + + +def make_html_class(node): + + div=ET.Element("div") + div.attrib["class"]="class"; + + a=ET.SubElement(div,"a") + a.attrib["name"]=node.attrib["name"] + + h3=ET.SubElement(a,"h3") + h3.attrib["class"]="title class_title" + h3.text=node.attrib["name"] + + briefd = node.find("brief_description") + if (briefd!=None): + div2=ET.SubElement(div,"div") + div2.attrib["class"]="description class_description" + div2.text=briefd.text + + if ("inherits" in node.attrib): + ET.SubElement(div,"br") + + div2=ET.SubElement(div,"div") + div2.attrib["class"]="inheritance"; + + span=ET.SubElement(div2,"span") + span.text="Inherits: " + + make_type(node.attrib["inherits"],div2) + + if ("category" in node.attrib): + ET.SubElement(div,"br") + + div3=ET.SubElement(div,"div") + div3.attrib["class"]="category"; + + span=ET.SubElement(div3,"span") + span.attrib["class"]="category" + span.text="Category: " + + a = ET.SubElement(div3,"a") + a.attrib["class"]="category_ref" + a.text=node.attrib["category"] + catname=a.text + if (catname.rfind("/")!=-1): + catname=catname[catname.rfind("/"):] + catname="CATEGORY_"+catname + + if (single_page): + a.attrib["href"]="#"+catname + else: + a.attrib["href"]="category.html#"+catname + + + methods = node.find("methods") + + if(methods!=None and len(list(methods))>0): + + h4=ET.SubElement(div,"h4") + h4.text="Public Methods:" + + method_table=ET.SubElement(div,"table") + method_table.attrib["class"]="method_list"; + + for m in list(methods): +# li = ET.SubElement(div2, "li") + method_table.append( make_method_def(node.attrib["name"],m,False) ) + + events = node.find("signals") + + if(events!=None and len(list(events))>0): + h4=ET.SubElement(div,"h4") + h4.text="Events:" + + event_table=ET.SubElement(div,"table") + event_table.attrib["class"]="method_list"; + + for m in list(events): +# li = ET.SubElement(div2, "li") + event_table.append( make_method_def(node.attrib["name"],m,False,True) ) + + + members = node.find("members") + if(members!=None and len(list(members))>0): + + h4=ET.SubElement(div,"h4") + h4.text="Public Variables:" + div2=ET.SubElement(div,"div") + div2.attrib["class"]="member_list"; + + for c in list(members): + + li = ET.SubElement(div2, "li") + div3=ET.SubElement(li,"div") + div3.attrib["class"]="member"; + make_type(c.attrib["type"],div3) + span=ET.SubElement(div3,"span") + span.attrib["class"]="identifier member_name" + span.text=" "+c.attrib["name"]+" " + span=ET.SubElement(div3,"span") + span.attrib["class"]="member_description" + span.text=c.text + + + constants = node.find("constants") + if(constants!=None and len(list(constants))>0): + + h4=ET.SubElement(div,"h4") + h4.text="Constants:" + div2=ET.SubElement(div,"div") + div2.attrib["class"]="constant_list"; + + for c in list(constants): + li = ET.SubElement(div2, "li") + div3=ET.SubElement(li,"div") + div3.attrib["class"]="constant"; + + span=ET.SubElement(div3,"span") + span.attrib["class"]="identifier constant_name" + span.text=c.attrib["name"]+" " + if ("value" in c.attrib): + span=ET.SubElement(div3,"span") + span.attrib["class"]="symbol" + span.text="= " + span=ET.SubElement(div3,"span") + span.attrib["class"]="constant_value" + span.text=c.attrib["value"]+" " + span=ET.SubElement(div3,"span") + span.attrib["class"]="constant_description" + span.text=c.text + +# ET.SubElement(div,"br") + + + descr=node.find("description") + if (descr!=None and descr.text.strip()!=""): + h4=ET.SubElement(div,"h4") + h4.text="Description:" + + make_text_def(node.attrib["name"],div,descr.text) +# div2=ET.SubElement(div,"div") +# div2.attrib["class"]="description"; +# div2.text=descr.text + + + + if(methods!=None or events!=None): + + h4=ET.SubElement(div,"h4") + h4.text="Method Documentation:" + iter_list = [] + if (methods!=None): + iter_list+=list(methods) + if (events!=None): + iter_list+=list(events) + + for m in iter_list: + + descr=m.find("description") + + if (descr==None or descr.text.strip()==""): + continue; + + div2=ET.SubElement(div,"div") + div2.attrib["class"]="method_doc"; + + + div2.append( make_method_def(node.attrib["name"],m,True) ) + #anchor = ET.SubElement(div2, "a") + #anchor.attrib["name"] = + make_text_def(node.attrib["name"],div2,descr.text) + #div3=ET.SubElement(div2,"div") + #div3.attrib["class"]="description"; + #div3.text=descr.text + + + return div + +class_names=[] +classes={} + +for file in input_list: + tree = ET.parse(file) + doc=tree.getroot() + + if ("version" not in doc.attrib): + print("Version missing from 'doc'") + sys.exit(255) + + version=doc.attrib["version"] + + for c in list(doc): + if (c.attrib["name"] in class_names): + continue + class_names.append(c.attrib["name"]) + classes[c.attrib["name"]]=c + +html = ET.Element("html") +css = ET.SubElement(html, "link") +css.attrib["href"] = "main.css" +css.attrib["rel"] = "stylesheet" +css.attrib["type"] = "text/css" + +body = ET.SubElement(html, "body") +if (not single_page): + make_html_top(body) + + + +class_names.sort() + +body.append( make_html_class_list(class_names,5) ) + +for cn in class_names: + c=classes[cn] + if (single_page): + body.append( make_html_class(c)) + else: + html2 = ET.Element("html") + css = ET.SubElement(html2, "link") + css.attrib["href"] = "main.css" + css.attrib["rel"] = "stylesheet" + css.attrib["type"] = "text/css" + body2 = ET.SubElement(html2, "body" ) + make_html_top(body2) + body2.append( make_html_class(c) ); + make_html_bottom(body2) + et_out = ET.ElementTree(html2) + et_out.write(c.attrib["name"]+".html") + + +et_out = ET.ElementTree(html) +if (single_page): + et_out.write("singlepage.html") +else: + make_html_bottom(body) + et_out.write("alphabetical.html") + diff --git a/doc/tools/makemd.py b/doc/tools/makemd.py new file mode 100644 index 0000000000..f85d145d5e --- /dev/null +++ b/doc/tools/makemd.py @@ -0,0 +1,345 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import sys +import xml.etree.ElementTree as ET + +input_list = [] + +for arg in sys.argv[1:]: + input_list.append(arg) + +if len(input_list) < 1: + print 'usage: makedoku.py <class_list.xml>' + sys.exit(0) + + +def validate_tag(elem, tag): + if elem.tag != tag: + print "Tag mismatch, expected '" + tag + "', got " + elem.tag + sys.exit(255) + + +class_names = [] +classes = {} + + +def make_class_list(class_list, columns): + + f = open('class_list.md', 'wb') + prev = 0 + col_max = len(class_list) / columns + 1 + print ('col max is ', col_max) + col_count = 0 + row_count = 0 + last_initial = '' + fit_columns = [] + + for n in range(0, columns): + fit_columns += [[]] + + indexers = [] + last_initial = '' + + idx = 0 + for n in class_list: + col = idx / col_max + if col >= columns: + col = columns - 1 + fit_columns[col] += [n] + idx += 1 + if n[:1] != last_initial: + indexers += [n] + last_initial = n[:1] + + row_max = 0 + f.write("\n") + + for n in range(0, columns): + if len(fit_columns[n]) > row_max: + row_max = len(fit_columns[n]) + + f.write("| ") + for n in range(0, columns): + f.write(" | |") + + f.write("\n") + f.write("| ") + for n in range(0, columns): + f.write(" --- | ------- |") + f.write("\n") + + for r in range(0, row_max): + s = '| ' + for c in range(0, columns): + if r >= len(fit_columns[c]): + continue + + classname = fit_columns[c][r] + initial = classname[0] + if classname in indexers: + s += '**' + initial + '** | ' + else: + s += ' | ' + + s += '[' + classname + '](class_'+ classname.lower()+') | ' + + s += '\n' + f.write(s) + + +def dokuize_text(txt): + + return txt + + +def dokuize_text(text): + pos = 0 + while True: + pos = text.find('[', pos) + if pos == -1: + break + + endq_pos = text.find(']', pos + 1) + if endq_pos == -1: + break + + pre_text = text[:pos] + post_text = text[endq_pos + 1:] + tag_text = text[pos + 1:endq_pos] + + if tag_text in class_names: + tag_text = make_type(tag_text) + else: + + # command + + cmd = tag_text + space_pos = tag_text.find(' ') + if cmd.find('html') == 0: + cmd = tag_text[:space_pos] + param = tag_text[space_pos + 1:] + tag_text = '<' + param + '>' + elif cmd.find('method') == 0: + cmd = tag_text[:space_pos] + param = tag_text[space_pos + 1:] + + if param.find('.') != -1: + (class_param, method_param) = param.split('.') + tag_text = '['+class_param+'.'+method_param.replace("_","_")+'](' + class_param.lower() + '#' \ + + method_param + ')' + else: + tag_text = '[' + param.replace("_","_") + '](#' + param + ')' + elif cmd.find('image=') == 0: + tag_text = '![](' + cmd[6:] + ')' + elif cmd.find('url=') == 0: + tag_text = '[' + cmd[4:] + ']('+cmd[4:] + elif cmd == '/url': + tag_text = ')' + elif cmd == 'center': + tag_text = '' + elif cmd == '/center': + tag_text = '' + elif cmd == 'br': + tag_text = '\n' + elif cmd == 'i' or cmd == '/i': + tag_text = '_' + elif cmd == 'b' or cmd == '/b': + tag_text = '**' + elif cmd == 'u' or cmd == '/u': + tag_text = '__' + else: + tag_text = '[' + tag_text + ']' + + text = pre_text + tag_text + post_text + pos = len(pre_text) + len(tag_text) + + # tnode = ET.SubElement(parent,"div") + # tnode.text=text + + return text + + +def make_type(t): + global class_names + if t in class_names: + return '[' + t + '](class_' + t.lower() + ')' + return t + + +def make_method( + f, + name, + m, + declare, + event=False, + ): + + s = ' * ' + ret_type = 'void' + args = list(m) + mdata = {} + mdata['argidx'] = [] + for a in args: + if a.tag == 'return': + idx = -1 + elif a.tag == 'argument': + idx = int(a.attrib['index']) + else: + continue + + mdata['argidx'].append(idx) + mdata[idx] = a + + if not event: + if -1 in mdata['argidx']: + s += make_type(mdata[-1].attrib['type']) + else: + s += 'void' + s += ' ' + + if declare: + + # span.attrib["class"]="funcdecl" + # a=ET.SubElement(span,"a") + # a.attrib["name"]=name+"_"+m.attrib["name"] + # a.text=name+"::"+m.attrib["name"] + + s += ' **'+m.attrib['name'].replace("_","_")+'** ' + else: + s += ' **['+ m.attrib['name'].replace("_","_")+'](#' + m.attrib['name'] + ')** ' + + s += ' **(**' + argfound = False + for a in mdata['argidx']: + arg = mdata[a] + if a < 0: + continue + if a > 0: + s += ', ' + else: + s += ' ' + + s += make_type(arg.attrib['type']) + if 'name' in arg.attrib: + s += ' ' + arg.attrib['name'] + else: + s += ' arg' + str(a) + + if 'default' in arg.attrib: + s += '=' + arg.attrib['default'] + + argfound = True + + if argfound: + s += ' ' + s += ' **)**' + + if 'qualifiers' in m.attrib: + s += ' ' + m.attrib['qualifiers'] + + f.write(s + '\n') + + +def make_doku_class(node): + + name = node.attrib['name'] + + f = open("class_"+name.lower() + '.md', 'wb') + + f.write('# ' + name + ' \n') + + if 'inherits' in node.attrib: + inh = node.attrib['inherits'].strip() + f.write('####**Inherits:** '+make_type(inh)+'\n') + if 'category' in node.attrib: + f.write('####**Category:** ' + node.attrib['category'].strip() + + '\n') + + briefd = node.find('brief_description') + if briefd != None: + f.write('\n### Brief Description \n') + f.write(dokuize_text(briefd.text.strip()) + '\n') + + methods = node.find('methods') + + if methods != None and len(list(methods)) > 0: + f.write('\n### Member Functions \n') + for m in list(methods): + make_method(f, node.attrib['name'], m, False) + + events = node.find('signals') + if events != None and len(list(events)) > 0: + f.write('\n### Signals \n') + for m in list(events): + make_method(f, node.attrib['name'], m, True, True) + + members = node.find('members') + + if members != None and len(list(members)) > 0: + f.write('\n### Member Variables \n') + + for c in list(members): + s = ' * ' + s += make_type(c.attrib['type']) + ' ' + s += '**' + c.attrib['name'] + '**' + if c.text.strip() != '': + s += ' - ' + c.text.strip() + f.write(s + '\n') + + constants = node.find('constants') + if constants != None and len(list(constants)) > 0: + f.write('\n### Numeric Constants \n') + for c in list(constants): + s = ' * ' + s += '**' + c.attrib['name'] + '**' + if 'value' in c.attrib: + s += ' = **' + c.attrib['value'] + '**' + if c.text.strip() != '': + s += ' - ' + c.text.strip() + f.write(s + '\n') + + descr = node.find('description') + if descr != None and descr.text.strip() != '': + f.write('\n### Description \n') + f.write(dokuize_text(descr.text.strip()) + '\n') + + methods = node.find('methods') + + if methods != None and len(list(methods)) > 0: + f.write('\n### Member Function Description \n') + for m in list(methods): + + d = m.find('description') + if d == None or d.text.strip() == '': + continue + f.write('\n#### <a name="'+m.attrib['name']+'">' + m.attrib['name'] + '</a>\n') + make_method(f, node.attrib['name'], m, True) + f.write('\n') + f.write(dokuize_text(d.text.strip())) + f.write('\n') + + +for file in input_list: + tree = ET.parse(file) + doc = tree.getroot() + + if 'version' not in doc.attrib: + print "Version missing from 'doc'" + sys.exit(255) + + version = doc.attrib['version'] + + for c in list(doc): + if c.attrib['name'] in class_names: + continue + class_names.append(c.attrib['name']) + classes[c.attrib['name']] = c + +class_names.sort() + +make_class_list(class_names, 2) + +for cn in class_names: + c = classes[cn] + make_doku_class(c) + |