2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5 # Copyright (C) 2005 Holger Hans Peter Freyther
8 # Permission is hereby granted, free of charge, to any person obtaining a copy
9 # of this software and associated documentation files (the "Software"), to deal
10 # in the Software without restriction, including without limitation the rights
11 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 # copies of the Software, and to permit persons to whom the Software is
13 # furnished to do so, subject to the following conditions:
15 # The above copyright notice and this permission notice shall be included in all
16 # copies or substantial portions of the Software.
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 # SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
24 # THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 import optparse, os, sys
31 sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
34 from string import split, join
40 Simple class to help to generate some sort of HTML files. It is
41 quite inferior solution compared to docbook, gtkdoc, doxygen but it
43 We've a global introduction site (index.html) and then one site for
44 the list of keys (alphabetical sorted) and one for the list of groups,
45 one site for each key with links to the relations and groups.
54 def replace(self, text, *pairs):
56 From pydoc... almost identical at least
60 text = join(split(text, a), b)
63 def escape(self, text):
65 Escape string to be conform HTML
67 return self.replace(text,
71 def createNavigator(self):
75 return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
77 <td><a accesskey="g" href="index.html">Home</a></td>
78 <td><a accesskey="n" href="groups.html">Groups</a></td>
79 <td><a accesskey="u" href="keys.html">Keys</a></td>
83 def relatedKeys(self, item):
85 Create HTML to link to foreign keys
88 if len(item.related()) == 0:
91 txt = "<p><b>See also:</b><br>"
92 for it in item.related():
93 txt += """<a href="key%s.html">%s</a>, """ % (it, it)
97 def groups(self,item):
99 Create HTML to link to related groups
102 if len(item.groups()) == 0:
106 txt = "<p><b>Seel also:</b><br>"
107 for group in item.groups():
108 txt += """<a href="group%s.html">%s</a>, """ % (group,group)
113 def createKeySite(self,item):
115 Create a site for a key. It contains the header/navigator, a heading,
116 the description, links to related keys and to the groups.
119 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
120 <html><head><title>Key %s</title></head>
121 <link rel="stylesheet" href="style.css" type="text/css">
122 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
124 <h2><span class="refentrytitle">%s</span></h2>
126 <div class="refsynopsisdiv">
128 <pre class="synopsis">
133 <div class="refsynopsisdiv">
134 <h2>Related Keys</h2>
135 <pre class="synopsis">
140 <div class="refsynopsisdiv">
142 <pre class="synopsis">
149 """ % (item.name(), self.createNavigator(), item.name(),
150 self.escape(item.description()), self.relatedKeys(item), self.groups(item))
152 def createGroupsSite(self, doc):
154 Create the Group Overview site
158 sorted_groups = doc.groups()
160 for group in sorted_groups:
161 groups += """<a href="group%s.html">%s</a><br>""" % (group, group)
163 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
164 <html><head><title>Group overview</title></head>
165 <link rel="stylesheet" href="style.css" type="text/css">
166 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
168 <h2>Available Groups</h2>
171 """ % (self.createNavigator(), groups)
173 def createIndex(self):
175 Create the index file
178 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
179 <html><head><title>Bitbake Documentation</title></head>
180 <link rel="stylesheet" href="style.css" type="text/css">
181 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
183 <h2>Documentation Entrance</h2>
184 <a href="groups.html">All available groups</a><br>
185 <a href="keys.html">All available keys</a><br>
187 """ % self.createNavigator()
189 def createKeysSite(self, doc):
191 Create Overview of all avilable keys
194 sorted_keys = doc.doc_keys()
196 for key in sorted_keys:
197 keys += """<a href="key%s.html">%s</a><br>""" % (key, key)
199 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
200 <html><head><title>Key overview</title></head>
201 <link rel="stylesheet" href="style.css" type="text/css">
202 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
204 <h2>Available Keys</h2>
207 """ % (self.createNavigator(), keys)
209 def createGroupSite(self,gr, items):
211 Create a site for a group:
212 Group the name of the group, items contain the name of the keys
217 groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name())
219 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
220 <html><head><title>Group %s</title></head>
221 <link rel="stylesheet" href="style.css" type="text/css">
222 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
224 <div class="refsynopsisdiv">
225 <h2>Keys in Group %s</h2>
226 <pre class="synopsis">
231 """ % (gr, self.createNavigator(), gr, groups)
239 return """.synopsis, .classsynopsis
242 border: solid 1px #aaaaaa;
248 border: solid 1px #aaaaff;
256 .variablelist td:first-child
263 border: solid 1px #ffaaaa;
265 margin-bottom: 0.5em;
271 .navigation a:visited
288 div.gallery-float img
298 text-decoration: none;
302 text-decoration: underline;
309 class DocumentationItem:
311 A class to hold information about a configuration
312 item. It contains the key name, description, a list of related names,
313 and the group this item is contained in.
328 def description(self):
334 def setName(self, name):
337 def setDescription(self, desc):
340 def addGroup(self, group):
341 self._groups.append(group)
343 def addRelation(self,relation):
344 self._related.append(relation)
353 Holds the documentation... with mappings from key to items...
360 def insert_doc_item(self, item):
362 Insert the Doc Item into the internal list
366 self.__keys[item.name()] = item
368 for group in item.groups():
369 if not group in self.__groups:
370 self.__groups[group] = []
371 self.__groups[group].append(item)
372 self.__groups[group].sort()
375 def doc_item(self, key):
377 Return the DocumentationInstance describing the key
380 return self.__keys[key]
386 Return the documented KEYS (names)
388 return self.__keys.keys()
392 Return the names of available groups
394 return self.__groups.keys()
396 def group_content(self,group_name):
398 Return a list of keys/names that are in a specefic
399 group or the empty list
402 return self.__groups[group_name]
407 def parse_cmdline(args):
409 Parse the CMD line and return the result as a n-tuple
412 parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__,__version__))
413 usage = """%prog [options]
415 Create a set of html pages (documentation) for a bitbake.conf....
418 # Add the needed options
419 parser.add_option( "-c", "--config", help = "Use the specified configuration file as source",
420 action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") )
422 parser.add_option( "-o", "--output", help = "Output directory for html files",
423 action = "store", dest = "output", default = "html/" )
425 parser.add_option( "-D", "--debug", help = "Increase the debug level",
426 action = "count", dest = "debug", default = 0 )
428 parser.add_option( "-v","--verbose", help = "output more chit-char to the terminal",
429 action = "store_true", dest = "verbose", default = False )
431 options, args = parser.parse_args( sys.argv )
434 bb.debug_level = options.debug
436 return options.config, options.output
443 (config_file,output_dir) = parse_cmdline( sys.argv )
445 # right to let us load the file now
447 documentation = bb.parse.handle( config_file, bb.data.init() )
449 bb.fatal( "Unable to open %s" % config_file )
450 except bb.parse.ParseError:
451 bb.fatal( "Unable to parse %s" % config_file )
454 # Assuming we've the file loaded now, we will initialize the 'tree'
455 doc = Documentation()
462 for key in bb.data.keys(documentation):
463 data = bb.data.getVarFlag(key, "doc", documentation)
467 # The Documentation now starts
468 doc_ins = DocumentationItem()
472 tokens = data.split(' ')
476 token = token.strip(',')
478 if not state == state_see and token == "@see":
481 elif not state == state_group and token == "@group":
485 if state == state_begin:
486 string += " %s" % token
487 elif state == state_see:
488 doc_ins.addRelation(token)
489 elif state == state_group:
490 doc_ins.addGroup(token)
492 # set the description
493 doc_ins.setDescription(string)
494 doc.insert_doc_item(doc_ins)
496 # let us create the HTML now
497 bb.mkdirhier(output_dir)
500 # Let us create the sites now. We do it in the following order
501 # Start with the index.html. It will point to sites explaining all
503 html_slave = HTMLFormatter()
505 f = file('style.css', 'w')
506 print >> f, html_slave.createCSS()
508 f = file('index.html', 'w')
509 print >> f, html_slave.createIndex()
511 f = file('groups.html', 'w')
512 print >> f, html_slave.createGroupsSite(doc)
514 f = file('keys.html', 'w')
515 print >> f, html_slave.createKeysSite(doc)
517 # now for each group create the site
518 for group in doc.groups():
519 f = file('group%s.html' % group, 'w')
520 print >> f, html_slave.createGroupSite(group, doc.group_content(group))
523 for key in doc.doc_keys():
524 f = file('key%s.html' % doc.doc_item(key).name(), 'w')
525 print >> f, html_slave.createKeySite(doc.doc_item(key))
528 if __name__ == "__main__":