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="all_groups.html">Groups</a></td>
79 <td><a accesskey="u" href="all_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>"
93 for it in item.related():
94 txts.append("""<a href="key%(it)s.html">%(it)s</a>""" % vars() )
96 return txt + ",".join(txts)
98 def groups(self,item):
100 Create HTML to link to related groups
103 if len(item.groups()) == 0:
107 txt = "<p><b>See also:</b><br>"
109 for group in item.groups():
110 txts.append( """<a href="group%s.html">%s</a> """ % (group,group) )
112 return txt + ",".join(txts)
115 def createKeySite(self,item):
117 Create a site for a key. It contains the header/navigator, a heading,
118 the description, links to related keys and to the groups.
121 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
122 <html><head><title>Key %s</title></head>
123 <link rel="stylesheet" href="style.css" type="text/css">
124 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
126 <h2><span class="refentrytitle">%s</span></h2>
128 <div class="refsynopsisdiv">
130 <pre class="synopsis">
135 <div class="refsynopsisdiv">
136 <h2>Related Keys</h2>
137 <pre class="synopsis">
142 <div class="refsynopsisdiv">
144 <pre class="synopsis">
151 """ % (item.name(), self.createNavigator(), item.name(),
152 self.escape(item.description()), self.relatedKeys(item), self.groups(item))
154 def createGroupsSite(self, doc):
156 Create the Group Overview site
160 sorted_groups = doc.groups()
162 for group in sorted_groups:
163 groups += """<a href="group%s.html">%s</a><br>""" % (group, group)
165 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
166 <html><head><title>Group overview</title></head>
167 <link rel="stylesheet" href="style.css" type="text/css">
168 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
170 <h2>Available Groups</h2>
173 """ % (self.createNavigator(), groups)
175 def createIndex(self):
177 Create the index file
180 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
181 <html><head><title>Bitbake Documentation</title></head>
182 <link rel="stylesheet" href="style.css" type="text/css">
183 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
185 <h2>Documentation Entrance</h2>
186 <a href="groups.html">All available groups</a><br>
187 <a href="keys.html">All available keys</a><br>
189 """ % self.createNavigator()
191 def createKeysSite(self, doc):
193 Create Overview of all avilable keys
196 sorted_keys = doc.doc_keys()
198 for key in sorted_keys:
199 keys += """<a href="key%s.html">%s</a><br>""" % (key, key)
201 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
202 <html><head><title>Key overview</title></head>
203 <link rel="stylesheet" href="style.css" type="text/css">
204 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
206 <h2>Available Keys</h2>
209 """ % (self.createNavigator(), keys)
211 def createGroupSite(self,gr, items):
213 Create a site for a group:
214 Group the name of the group, items contain the name of the keys
219 items.sort(cmp=lambda x,y:cmp(x.name(),y.name()))
221 groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name())
223 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
224 <html><head><title>Group %s</title></head>
225 <link rel="stylesheet" href="style.css" type="text/css">
226 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
228 <div class="refsynopsisdiv">
229 <h2>Keys in Group %s</h2>
230 <pre class="synopsis">
235 """ % (gr, self.createNavigator(), gr, groups)
243 return """.synopsis, .classsynopsis
246 border: solid 1px #aaaaaa;
252 border: solid 1px #aaaaff;
260 .variablelist td:first-child
267 border: solid 1px #ffaaaa;
269 margin-bottom: 0.5em;
275 .navigation a:visited
292 div.gallery-float img
302 text-decoration: none;
306 text-decoration: underline;
313 class DocumentationItem:
315 A class to hold information about a configuration
316 item. It contains the key name, description, a list of related names,
317 and the group this item is contained in.
332 def description(self):
338 def setName(self, name):
341 def setDescription(self, desc):
344 def addGroup(self, group):
345 self._groups.append(group)
347 def addRelation(self,relation):
348 self._related.append(relation)
357 Holds the documentation... with mappings from key to items...
364 def insert_doc_item(self, item):
366 Insert the Doc Item into the internal list
370 self.__keys[item.name()] = item
372 for group in item.groups():
373 if not group in self.__groups:
374 self.__groups[group] = []
375 self.__groups[group].append(item)
376 self.__groups[group].sort()
379 def doc_item(self, key):
381 Return the DocumentationInstance describing the key
384 return self.__keys[key]
390 Return the documented KEYS (names)
392 return self.__keys.keys()
396 Return the names of available groups
398 return self.__groups.keys()
400 def group_content(self,group_name):
402 Return a list of keys/names that are in a specefic
403 group or the empty list
406 return self.__groups[group_name]
411 def parse_cmdline(args):
413 Parse the CMD line and return the result as a n-tuple
416 parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__,__version__))
417 usage = """%prog [options]
419 Create a set of html pages (documentation) for a bitbake.conf....
422 # Add the needed options
423 parser.add_option( "-c", "--config", help = "Use the specified configuration file as source",
424 action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") )
426 parser.add_option( "-o", "--output", help = "Output directory for html files",
427 action = "store", dest = "output", default = "html/" )
429 parser.add_option( "-D", "--debug", help = "Increase the debug level",
430 action = "count", dest = "debug", default = 0 )
432 parser.add_option( "-v","--verbose", help = "output more chit-char to the terminal",
433 action = "store_true", dest = "verbose", default = False )
435 options, args = parser.parse_args( sys.argv )
438 bb.debug_level = options.debug
440 return options.config, options.output
447 (config_file,output_dir) = parse_cmdline( sys.argv )
449 # right to let us load the file now
451 documentation = bb.parse.handle( config_file, bb.data.init() )
453 bb.fatal( "Unable to open %s" % config_file )
454 except bb.parse.ParseError:
455 bb.fatal( "Unable to parse %s" % config_file )
458 # Assuming we've the file loaded now, we will initialize the 'tree'
459 doc = Documentation()
466 for key in bb.data.keys(documentation):
467 data = bb.data.getVarFlag(key, "doc", documentation)
471 # The Documentation now starts
472 doc_ins = DocumentationItem()
476 tokens = data.split(' ')
480 token = token.strip(',')
482 if not state == state_see and token == "@see":
485 elif not state == state_group and token == "@group":
489 if state == state_begin:
490 string += " %s" % token
491 elif state == state_see:
492 doc_ins.addRelation(token)
493 elif state == state_group:
494 doc_ins.addGroup(token)
496 # set the description
497 doc_ins.setDescription(string)
498 doc.insert_doc_item(doc_ins)
500 # let us create the HTML now
501 bb.mkdirhier(output_dir)
504 # Let us create the sites now. We do it in the following order
505 # Start with the index.html. It will point to sites explaining all
507 html_slave = HTMLFormatter()
509 f = file('style.css', 'w')
510 print >> f, html_slave.createCSS()
512 f = file('index.html', 'w')
513 print >> f, html_slave.createIndex()
515 f = file('all_groups.html', 'w')
516 print >> f, html_slave.createGroupsSite(doc)
518 f = file('all_keys.html', 'w')
519 print >> f, html_slave.createKeysSite(doc)
521 # now for each group create the site
522 for group in doc.groups():
523 f = file('group%s.html' % group, 'w')
524 print >> f, html_slave.createGroupSite(group, doc.group_content(group))
527 for key in doc.doc_keys():
528 f = file('key%s.html' % doc.doc_item(key).name(), 'w')
529 print >> f, html_slave.createKeySite(doc.doc_item(key))
532 if __name__ == "__main__":