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">
135 <div class="refsynopsisdiv">
136 <h2>Related Keys</h2>
142 <div class="refsynopsisdiv">
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="all_groups.html">All available groups</a><br>
187 <a href="all_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, _description = None):
213 Create a site for a group:
214 Group the name of the group, items contain the name of the keys
220 # create a section with the group descriptions
222 description += "<h2 Description of Grozp %s</h2>" % gr
223 description += _description
225 items.sort(lambda x,y:cmp(x.name(),y.name()))
227 groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name())
229 return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
230 <html><head><title>Group %s</title></head>
231 <link rel="stylesheet" href="style.css" type="text/css">
232 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
235 <div class="refsynopsisdiv">
236 <h2>Keys in Group %s</h2>
237 <pre class="synopsis">
242 """ % (gr, self.createNavigator(), description, gr, groups)
250 return """.synopsis, .classsynopsis
253 border: solid 1px #aaaaaa;
259 border: solid 1px #aaaaff;
267 .variablelist td:first-child
274 border: solid 1px #ffaaaa;
276 margin-bottom: 0.5em;
282 .navigation a:visited
299 div.gallery-float img
309 text-decoration: none;
313 text-decoration: underline;
320 class DocumentationItem:
322 A class to hold information about a configuration
323 item. It contains the key name, description, a list of related names,
324 and the group this item is contained in.
339 def description(self):
345 def setName(self, name):
348 def setDescription(self, desc):
351 def addGroup(self, group):
352 self._groups.append(group)
354 def addRelation(self,relation):
355 self._related.append(relation)
364 Holds the documentation... with mappings from key to items...
371 def insert_doc_item(self, item):
373 Insert the Doc Item into the internal list
377 self.__keys[item.name()] = item
379 for group in item.groups():
380 if not group in self.__groups:
381 self.__groups[group] = []
382 self.__groups[group].append(item)
383 self.__groups[group].sort()
386 def doc_item(self, key):
388 Return the DocumentationInstance describing the key
391 return self.__keys[key]
397 Return the documented KEYS (names)
399 return self.__keys.keys()
403 Return the names of available groups
405 return self.__groups.keys()
407 def group_content(self,group_name):
409 Return a list of keys/names that are in a specefic
410 group or the empty list
413 return self.__groups[group_name]
418 def parse_cmdline(args):
420 Parse the CMD line and return the result as a n-tuple
423 parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__,__version__))
424 usage = """%prog [options]
426 Create a set of html pages (documentation) for a bitbake.conf....
429 # Add the needed options
430 parser.add_option( "-c", "--config", help = "Use the specified configuration file as source",
431 action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") )
433 parser.add_option( "-o", "--output", help = "Output directory for html files",
434 action = "store", dest = "output", default = "html/" )
436 parser.add_option( "-D", "--debug", help = "Increase the debug level",
437 action = "count", dest = "debug", default = 0 )
439 parser.add_option( "-v","--verbose", help = "output more chit-char to the terminal",
440 action = "store_true", dest = "verbose", default = False )
442 options, args = parser.parse_args( sys.argv )
445 bb.msg.set_debug_level(options.debug)
447 return options.config, options.output
454 (config_file,output_dir) = parse_cmdline( sys.argv )
456 # right to let us load the file now
458 documentation = bb.parse.handle( config_file, bb.data.init() )
460 bb.fatal( "Unable to open %s" % config_file )
461 except bb.parse.ParseError:
462 bb.fatal( "Unable to parse %s" % config_file )
465 # Assuming we've the file loaded now, we will initialize the 'tree'
466 doc = Documentation()
473 for key in bb.data.keys(documentation):
474 data = bb.data.getVarFlag(key, "doc", documentation)
478 # The Documentation now starts
479 doc_ins = DocumentationItem()
483 tokens = data.split(' ')
487 token = token.strip(',')
489 if not state == state_see and token == "@see":
492 elif not state == state_group and token == "@group":
496 if state == state_begin:
497 string += " %s" % token
498 elif state == state_see:
499 doc_ins.addRelation(token)
500 elif state == state_group:
501 doc_ins.addGroup(token)
503 # set the description
504 doc_ins.setDescription(string)
505 doc.insert_doc_item(doc_ins)
507 # let us create the HTML now
508 bb.mkdirhier(output_dir)
511 # Let us create the sites now. We do it in the following order
512 # Start with the index.html. It will point to sites explaining all
514 html_slave = HTMLFormatter()
516 f = file('style.css', 'w')
517 print >> f, html_slave.createCSS()
519 f = file('index.html', 'w')
520 print >> f, html_slave.createIndex()
522 f = file('all_groups.html', 'w')
523 print >> f, html_slave.createGroupsSite(doc)
525 f = file('all_keys.html', 'w')
526 print >> f, html_slave.createKeysSite(doc)
528 # now for each group create the site
529 for group in doc.groups():
530 f = file('group%s.html' % group, 'w')
531 print >> f, html_slave.createGroupSite(group, doc.group_content(group))
534 for key in doc.doc_keys():
535 f = file('key%s.html' % doc.doc_item(key).name(), 'w')
536 print >> f, html_slave.createKeySite(doc.doc_item(key))
539 if __name__ == "__main__":