diff options
author | Richard Purdie <richard@openedhand.com> | 2008-09-30 15:08:33 +0000 |
---|---|---|
committer | Richard Purdie <richard@openedhand.com> | 2008-09-30 15:08:33 +0000 |
commit | c30eddb243e7e65f67f656e62848a033cf6f2e5c (patch) | |
tree | 110dd95788b76f55d31cb8d30aac2de8400b6f4a /bitbake-dev/bin/bitdoc | |
parent | 5ef0510474004eeb2ae8a99b64e2febb1920e077 (diff) | |
download | openembedded-core-c30eddb243e7e65f67f656e62848a033cf6f2e5c.tar.gz openembedded-core-c30eddb243e7e65f67f656e62848a033cf6f2e5c.tar.bz2 openembedded-core-c30eddb243e7e65f67f656e62848a033cf6f2e5c.zip |
Add bitbake-dev to allow ease of testing and development of bitbake trunk
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5337 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'bitbake-dev/bin/bitdoc')
-rwxr-xr-x | bitbake-dev/bin/bitdoc | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/bitbake-dev/bin/bitdoc b/bitbake-dev/bin/bitdoc new file mode 100755 index 0000000000..3bcc9b344b --- /dev/null +++ b/bitbake-dev/bin/bitdoc @@ -0,0 +1,532 @@ +#!/usr/bin/env python +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (C) 2005 Holger Hans Peter Freyther +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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, os, sys + +# bitbake +sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) +import bb +import bb.parse +from string import split, join + +__version__ = "0.0.2" + +class HTMLFormatter: + """ + Simple class to help to generate some sort of HTML files. It is + quite inferior solution compared to docbook, gtkdoc, doxygen but it + should work for now. + We've a global introduction site (index.html) and then one site for + the list of keys (alphabetical sorted) and one for the list of groups, + one site for each key with links to the relations and groups. + + index.html + all_keys.html + all_groups.html + groupNAME.html + keyNAME.html + """ + + def replace(self, text, *pairs): + """ + From pydoc... almost identical at least + """ + while pairs: + (a,b) = pairs[0] + text = join(split(text, a), b) + pairs = pairs[1:] + return text + def escape(self, text): + """ + Escape string to be conform HTML + """ + return self.replace(text, + ('&', '&'), + ('<', '<' ), + ('>', '>' ) ) + def createNavigator(self): + """ + Create the navgiator + """ + return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"> +<tr valign="middle"> +<td><a accesskey="g" href="index.html">Home</a></td> +<td><a accesskey="n" href="all_groups.html">Groups</a></td> +<td><a accesskey="u" href="all_keys.html">Keys</a></td> +</tr></table> +""" + + def relatedKeys(self, item): + """ + Create HTML to link to foreign keys + """ + + if len(item.related()) == 0: + return "" + + txt = "<p><b>See also:</b><br>" + txts = [] + for it in item.related(): + txts.append("""<a href="key%(it)s.html">%(it)s</a>""" % vars() ) + + return txt + ",".join(txts) + + def groups(self,item): + """ + Create HTML to link to related groups + """ + + if len(item.groups()) == 0: + return "" + + + txt = "<p><b>See also:</b><br>" + txts = [] + for group in item.groups(): + txts.append( """<a href="group%s.html">%s</a> """ % (group,group) ) + + return txt + ",".join(txts) + + + def createKeySite(self,item): + """ + Create a site for a key. It contains the header/navigator, a heading, + the description, links to related keys and to the groups. + """ + + return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html><head><title>Key %s</title></head> +<link rel="stylesheet" href="style.css" type="text/css"> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +%s +<h2><span class="refentrytitle">%s</span></h2> + +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<p> +%s +</p> +</div> + +<div class="refsynopsisdiv"> +<h2>Related Keys</h2> +<p> +%s +</p> +</div> + +<div class="refsynopsisdiv"> +<h2>Groups</h2> +<p> +%s +</p> +</div> + + +</body> +""" % (item.name(), self.createNavigator(), item.name(), + self.escape(item.description()), self.relatedKeys(item), self.groups(item)) + + def createGroupsSite(self, doc): + """ + Create the Group Overview site + """ + + groups = "" + sorted_groups = doc.groups() + sorted_groups.sort() + for group in sorted_groups: + groups += """<a href="group%s.html">%s</a><br>""" % (group, group) + + return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html><head><title>Group overview</title></head> +<link rel="stylesheet" href="style.css" type="text/css"> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +%s +<h2>Available Groups</h2> +%s +</body> +""" % (self.createNavigator(), groups) + + def createIndex(self): + """ + Create the index file + """ + + return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html><head><title>Bitbake Documentation</title></head> +<link rel="stylesheet" href="style.css" type="text/css"> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +%s +<h2>Documentation Entrance</h2> +<a href="all_groups.html">All available groups</a><br> +<a href="all_keys.html">All available keys</a><br> +</body> +""" % self.createNavigator() + + def createKeysSite(self, doc): + """ + Create Overview of all avilable keys + """ + keys = "" + sorted_keys = doc.doc_keys() + sorted_keys.sort() + for key in sorted_keys: + keys += """<a href="key%s.html">%s</a><br>""" % (key, key) + + return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html><head><title>Key overview</title></head> +<link rel="stylesheet" href="style.css" type="text/css"> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +%s +<h2>Available Keys</h2> +%s +</body> +""" % (self.createNavigator(), keys) + + def createGroupSite(self, gr, items, _description = None): + """ + Create a site for a group: + Group the name of the group, items contain the name of the keys + inside this group + """ + groups = "" + description = "" + + # create a section with the group descriptions + if _description: + description += "<h2 Description of Grozp %s</h2>" % gr + description += _description + + items.sort(lambda x,y:cmp(x.name(),y.name())) + for group in items: + groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name()) + + return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html><head><title>Group %s</title></head> +<link rel="stylesheet" href="style.css" type="text/css"> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +%s +%s +<div class="refsynopsisdiv"> +<h2>Keys in Group %s</h2> +<pre class="synopsis"> +%s +</pre> +</div> +</body> +""" % (gr, self.createNavigator(), description, gr, groups) + + + + def createCSS(self): + """ + Create the CSS file + """ + return """.synopsis, .classsynopsis +{ + background: #eeeeee; + border: solid 1px #aaaaaa; + padding: 0.5em; +} +.programlisting +{ + background: #eeeeff; + border: solid 1px #aaaaff; + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} +table.navigation +{ + background: #ffeeee; + border: solid 1px #ffaaaa; + margin-top: 0.5em; + margin-bottom: 0.5em; +} +.navigation a +{ + color: #770000; +} +.navigation a:visited +{ + color: #550000; +} +.navigation .title +{ + font-size: 200%; +} +div.refnamediv +{ + margin-top: 2em; +} +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} +a +{ + text-decoration: none; +} +a:hover +{ + text-decoration: underline; + color: #FF0000; +} +""" + + + +class DocumentationItem: + """ + A class to hold information about a configuration + item. It contains the key name, description, a list of related names, + and the group this item is contained in. + """ + + def __init__(self): + self._groups = [] + self._related = [] + self._name = "" + self._desc = "" + + def groups(self): + return self._groups + + def name(self): + return self._name + + def description(self): + return self._desc + + def related(self): + return self._related + + def setName(self, name): + self._name = name + + def setDescription(self, desc): + self._desc = desc + + def addGroup(self, group): + self._groups.append(group) + + def addRelation(self,relation): + self._related.append(relation) + + def sort(self): + self._related.sort() + self._groups.sort() + + +class Documentation: + """ + Holds the documentation... with mappings from key to items... + """ + + def __init__(self): + self.__keys = {} + self.__groups = {} + + def insert_doc_item(self, item): + """ + Insert the Doc Item into the internal list + of representation + """ + item.sort() + self.__keys[item.name()] = item + + for group in item.groups(): + if not group in self.__groups: + self.__groups[group] = [] + self.__groups[group].append(item) + self.__groups[group].sort() + + + def doc_item(self, key): + """ + Return the DocumentationInstance describing the key + """ + try: + return self.__keys[key] + except KeyError: + return None + + def doc_keys(self): + """ + Return the documented KEYS (names) + """ + return self.__keys.keys() + + def groups(self): + """ + Return the names of available groups + """ + return self.__groups.keys() + + def group_content(self,group_name): + """ + Return a list of keys/names that are in a specefic + group or the empty list + """ + try: + return self.__groups[group_name] + except KeyError: + return [] + + +def parse_cmdline(args): + """ + Parse the CMD line and return the result as a n-tuple + """ + + parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__,__version__)) + usage = """%prog [options] + +Create a set of html pages (documentation) for a bitbake.conf.... +""" + + # Add the needed options + parser.add_option( "-c", "--config", help = "Use the specified configuration file as source", + action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") ) + + parser.add_option( "-o", "--output", help = "Output directory for html files", + action = "store", dest = "output", default = "html/" ) + + parser.add_option( "-D", "--debug", help = "Increase the debug level", + action = "count", dest = "debug", default = 0 ) + + parser.add_option( "-v","--verbose", help = "output more chit-char to the terminal", + action = "store_true", dest = "verbose", default = False ) + + options, args = parser.parse_args( sys.argv ) + + if options.debug: + bb.msg.set_debug_level(options.debug) + + return options.config, options.output + +def main(): + """ + The main Method + """ + + (config_file,output_dir) = parse_cmdline( sys.argv ) + + # right to let us load the file now + try: + documentation = bb.parse.handle( config_file, bb.data.init() ) + except IOError: + bb.fatal( "Unable to open %s" % config_file ) + except bb.parse.ParseError: + bb.fatal( "Unable to parse %s" % config_file ) + + + # Assuming we've the file loaded now, we will initialize the 'tree' + doc = Documentation() + + # defined states + state_begin = 0 + state_see = 1 + state_group = 2 + + for key in bb.data.keys(documentation): + data = bb.data.getVarFlag(key, "doc", documentation) + if not data: + continue + + # The Documentation now starts + doc_ins = DocumentationItem() + doc_ins.setName(key) + + + tokens = data.split(' ') + state = state_begin + string= "" + for token in tokens: + token = token.strip(',') + + if not state == state_see and token == "@see": + state = state_see + continue + elif not state == state_group and token == "@group": + state = state_group + continue + + if state == state_begin: + string += " %s" % token + elif state == state_see: + doc_ins.addRelation(token) + elif state == state_group: + doc_ins.addGroup(token) + + # set the description + doc_ins.setDescription(string) + doc.insert_doc_item(doc_ins) + + # let us create the HTML now + bb.mkdirhier(output_dir) + os.chdir(output_dir) + + # Let us create the sites now. We do it in the following order + # Start with the index.html. It will point to sites explaining all + # keys and groups + html_slave = HTMLFormatter() + + f = file('style.css', 'w') + print >> f, html_slave.createCSS() + + f = file('index.html', 'w') + print >> f, html_slave.createIndex() + + f = file('all_groups.html', 'w') + print >> f, html_slave.createGroupsSite(doc) + + f = file('all_keys.html', 'w') + print >> f, html_slave.createKeysSite(doc) + + # now for each group create the site + for group in doc.groups(): + f = file('group%s.html' % group, 'w') + print >> f, html_slave.createGroupSite(group, doc.group_content(group)) + + # now for the keys + for key in doc.doc_keys(): + f = file('key%s.html' % doc.doc_item(key).name(), 'w') + print >> f, html_slave.createKeySite(doc.doc_item(key)) + + +if __name__ == "__main__": + main() |