123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- #!/usr/bin/env python3
- # 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
- #
- # SPDX-License-Identifier: GPL-2.0-only
- #
- import optparse, os, sys
- # bitbake
- sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__), '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 = sorted(doc.groups())
- 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 = sorted(doc.doc_keys())
- 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 )
-
- bb.msg.init_msgconfig(options.verbose, 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 )
- if isinstance(documentation, dict):
- documentation = documentation[""]
- # 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 = documentation.getVarFlag(key, "doc", False)
- 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.utils.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()
|