diff options
Diffstat (limited to 'bitbake-dev/bin/bitdoc')
-rwxr-xr-x | bitbake-dev/bin/bitdoc | 534 |
1 files changed, 0 insertions, 534 deletions
diff --git a/bitbake-dev/bin/bitdoc b/bitbake-dev/bin/bitdoc deleted file mode 100755 index 4940f660a6..0000000000 --- a/bitbake-dev/bin/bitdoc +++ /dev/null | |||
@@ -1,534 +0,0 @@ | |||
1 | #!/usr/bin/env python | ||
2 | # ex:ts=4:sw=4:sts=4:et | ||
3 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | ||
4 | # | ||
5 | # Copyright (C) 2005 Holger Hans Peter Freyther | ||
6 | # | ||
7 | # This program is free software; you can redistribute it and/or modify | ||
8 | # it under the terms of the GNU General Public License version 2 as | ||
9 | # published by the Free Software Foundation. | ||
10 | # | ||
11 | # This program is distributed in the hope that it will be useful, | ||
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | # GNU General Public License for more details. | ||
15 | # | ||
16 | # You should have received a copy of the GNU General Public License along | ||
17 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | |||
20 | import optparse, os, sys | ||
21 | |||
22 | # bitbake | ||
23 | sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) | ||
24 | import bb | ||
25 | import bb.parse | ||
26 | from string import split, join | ||
27 | |||
28 | __version__ = "0.0.2" | ||
29 | |||
30 | class HTMLFormatter: | ||
31 | """ | ||
32 | Simple class to help to generate some sort of HTML files. It is | ||
33 | quite inferior solution compared to docbook, gtkdoc, doxygen but it | ||
34 | should work for now. | ||
35 | We've a global introduction site (index.html) and then one site for | ||
36 | the list of keys (alphabetical sorted) and one for the list of groups, | ||
37 | one site for each key with links to the relations and groups. | ||
38 | |||
39 | index.html | ||
40 | all_keys.html | ||
41 | all_groups.html | ||
42 | groupNAME.html | ||
43 | keyNAME.html | ||
44 | """ | ||
45 | |||
46 | def replace(self, text, *pairs): | ||
47 | """ | ||
48 | From pydoc... almost identical at least | ||
49 | """ | ||
50 | while pairs: | ||
51 | (a,b) = pairs[0] | ||
52 | text = join(split(text, a), b) | ||
53 | pairs = pairs[1:] | ||
54 | return text | ||
55 | def escape(self, text): | ||
56 | """ | ||
57 | Escape string to be conform HTML | ||
58 | """ | ||
59 | return self.replace(text, | ||
60 | ('&', '&'), | ||
61 | ('<', '<' ), | ||
62 | ('>', '>' ) ) | ||
63 | def createNavigator(self): | ||
64 | """ | ||
65 | Create the navgiator | ||
66 | """ | ||
67 | return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"> | ||
68 | <tr valign="middle"> | ||
69 | <td><a accesskey="g" href="index.html">Home</a></td> | ||
70 | <td><a accesskey="n" href="all_groups.html">Groups</a></td> | ||
71 | <td><a accesskey="u" href="all_keys.html">Keys</a></td> | ||
72 | </tr></table> | ||
73 | """ | ||
74 | |||
75 | def relatedKeys(self, item): | ||
76 | """ | ||
77 | Create HTML to link to foreign keys | ||
78 | """ | ||
79 | |||
80 | if len(item.related()) == 0: | ||
81 | return "" | ||
82 | |||
83 | txt = "<p><b>See also:</b><br>" | ||
84 | txts = [] | ||
85 | for it in item.related(): | ||
86 | txts.append("""<a href="key%(it)s.html">%(it)s</a>""" % vars() ) | ||
87 | |||
88 | return txt + ",".join(txts) | ||
89 | |||
90 | def groups(self,item): | ||
91 | """ | ||
92 | Create HTML to link to related groups | ||
93 | """ | ||
94 | |||
95 | if len(item.groups()) == 0: | ||
96 | return "" | ||
97 | |||
98 | |||
99 | txt = "<p><b>See also:</b><br>" | ||
100 | txts = [] | ||
101 | for group in item.groups(): | ||
102 | txts.append( """<a href="group%s.html">%s</a> """ % (group,group) ) | ||
103 | |||
104 | return txt + ",".join(txts) | ||
105 | |||
106 | |||
107 | def createKeySite(self,item): | ||
108 | """ | ||
109 | Create a site for a key. It contains the header/navigator, a heading, | ||
110 | the description, links to related keys and to the groups. | ||
111 | """ | ||
112 | |||
113 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
114 | <html><head><title>Key %s</title></head> | ||
115 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
116 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
117 | %s | ||
118 | <h2><span class="refentrytitle">%s</span></h2> | ||
119 | |||
120 | <div class="refsynopsisdiv"> | ||
121 | <h2>Synopsis</h2> | ||
122 | <p> | ||
123 | %s | ||
124 | </p> | ||
125 | </div> | ||
126 | |||
127 | <div class="refsynopsisdiv"> | ||
128 | <h2>Related Keys</h2> | ||
129 | <p> | ||
130 | %s | ||
131 | </p> | ||
132 | </div> | ||
133 | |||
134 | <div class="refsynopsisdiv"> | ||
135 | <h2>Groups</h2> | ||
136 | <p> | ||
137 | %s | ||
138 | </p> | ||
139 | </div> | ||
140 | |||
141 | |||
142 | </body> | ||
143 | """ % (item.name(), self.createNavigator(), item.name(), | ||
144 | self.escape(item.description()), self.relatedKeys(item), self.groups(item)) | ||
145 | |||
146 | def createGroupsSite(self, doc): | ||
147 | """ | ||
148 | Create the Group Overview site | ||
149 | """ | ||
150 | |||
151 | groups = "" | ||
152 | sorted_groups = doc.groups() | ||
153 | sorted_groups.sort() | ||
154 | for group in sorted_groups: | ||
155 | groups += """<a href="group%s.html">%s</a><br>""" % (group, group) | ||
156 | |||
157 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
158 | <html><head><title>Group overview</title></head> | ||
159 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
160 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
161 | %s | ||
162 | <h2>Available Groups</h2> | ||
163 | %s | ||
164 | </body> | ||
165 | """ % (self.createNavigator(), groups) | ||
166 | |||
167 | def createIndex(self): | ||
168 | """ | ||
169 | Create the index file | ||
170 | """ | ||
171 | |||
172 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
173 | <html><head><title>Bitbake Documentation</title></head> | ||
174 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
175 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
176 | %s | ||
177 | <h2>Documentation Entrance</h2> | ||
178 | <a href="all_groups.html">All available groups</a><br> | ||
179 | <a href="all_keys.html">All available keys</a><br> | ||
180 | </body> | ||
181 | """ % self.createNavigator() | ||
182 | |||
183 | def createKeysSite(self, doc): | ||
184 | """ | ||
185 | Create Overview of all avilable keys | ||
186 | """ | ||
187 | keys = "" | ||
188 | sorted_keys = doc.doc_keys() | ||
189 | sorted_keys.sort() | ||
190 | for key in sorted_keys: | ||
191 | keys += """<a href="key%s.html">%s</a><br>""" % (key, key) | ||
192 | |||
193 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
194 | <html><head><title>Key overview</title></head> | ||
195 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
196 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
197 | %s | ||
198 | <h2>Available Keys</h2> | ||
199 | %s | ||
200 | </body> | ||
201 | """ % (self.createNavigator(), keys) | ||
202 | |||
203 | def createGroupSite(self, gr, items, _description = None): | ||
204 | """ | ||
205 | Create a site for a group: | ||
206 | Group the name of the group, items contain the name of the keys | ||
207 | inside this group | ||
208 | """ | ||
209 | groups = "" | ||
210 | description = "" | ||
211 | |||
212 | # create a section with the group descriptions | ||
213 | if _description: | ||
214 | description += "<h2 Description of Grozp %s</h2>" % gr | ||
215 | description += _description | ||
216 | |||
217 | items.sort(lambda x,y:cmp(x.name(),y.name())) | ||
218 | for group in items: | ||
219 | groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name()) | ||
220 | |||
221 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
222 | <html><head><title>Group %s</title></head> | ||
223 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
224 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
225 | %s | ||
226 | %s | ||
227 | <div class="refsynopsisdiv"> | ||
228 | <h2>Keys in Group %s</h2> | ||
229 | <pre class="synopsis"> | ||
230 | %s | ||
231 | </pre> | ||
232 | </div> | ||
233 | </body> | ||
234 | """ % (gr, self.createNavigator(), description, gr, groups) | ||
235 | |||
236 | |||
237 | |||
238 | def createCSS(self): | ||
239 | """ | ||
240 | Create the CSS file | ||
241 | """ | ||
242 | return """.synopsis, .classsynopsis | ||
243 | { | ||
244 | background: #eeeeee; | ||
245 | border: solid 1px #aaaaaa; | ||
246 | padding: 0.5em; | ||
247 | } | ||
248 | .programlisting | ||
249 | { | ||
250 | background: #eeeeff; | ||
251 | border: solid 1px #aaaaff; | ||
252 | padding: 0.5em; | ||
253 | } | ||
254 | .variablelist | ||
255 | { | ||
256 | padding: 4px; | ||
257 | margin-left: 3em; | ||
258 | } | ||
259 | .variablelist td:first-child | ||
260 | { | ||
261 | vertical-align: top; | ||
262 | } | ||
263 | table.navigation | ||
264 | { | ||
265 | background: #ffeeee; | ||
266 | border: solid 1px #ffaaaa; | ||
267 | margin-top: 0.5em; | ||
268 | margin-bottom: 0.5em; | ||
269 | } | ||
270 | .navigation a | ||
271 | { | ||
272 | color: #770000; | ||
273 | } | ||
274 | .navigation a:visited | ||
275 | { | ||
276 | color: #550000; | ||
277 | } | ||
278 | .navigation .title | ||
279 | { | ||
280 | font-size: 200%; | ||
281 | } | ||
282 | div.refnamediv | ||
283 | { | ||
284 | margin-top: 2em; | ||
285 | } | ||
286 | div.gallery-float | ||
287 | { | ||
288 | float: left; | ||
289 | padding: 10px; | ||
290 | } | ||
291 | div.gallery-float img | ||
292 | { | ||
293 | border-style: none; | ||
294 | } | ||
295 | div.gallery-spacer | ||
296 | { | ||
297 | clear: both; | ||
298 | } | ||
299 | a | ||
300 | { | ||
301 | text-decoration: none; | ||
302 | } | ||
303 | a:hover | ||
304 | { | ||
305 | text-decoration: underline; | ||
306 | color: #FF0000; | ||
307 | } | ||
308 | """ | ||
309 | |||
310 | |||
311 | |||
312 | class DocumentationItem: | ||
313 | """ | ||
314 | A class to hold information about a configuration | ||
315 | item. It contains the key name, description, a list of related names, | ||
316 | and the group this item is contained in. | ||
317 | """ | ||
318 | |||
319 | def __init__(self): | ||
320 | self._groups = [] | ||
321 | self._related = [] | ||
322 | self._name = "" | ||
323 | self._desc = "" | ||
324 | |||
325 | def groups(self): | ||
326 | return self._groups | ||
327 | |||
328 | def name(self): | ||
329 | return self._name | ||
330 | |||
331 | def description(self): | ||
332 | return self._desc | ||
333 | |||
334 | def related(self): | ||
335 | return self._related | ||
336 | |||
337 | def setName(self, name): | ||
338 | self._name = name | ||
339 | |||
340 | def setDescription(self, desc): | ||
341 | self._desc = desc | ||
342 | |||
343 | def addGroup(self, group): | ||
344 | self._groups.append(group) | ||
345 | |||
346 | def addRelation(self,relation): | ||
347 | self._related.append(relation) | ||
348 | |||
349 | def sort(self): | ||
350 | self._related.sort() | ||
351 | self._groups.sort() | ||
352 | |||
353 | |||
354 | class Documentation: | ||
355 | """ | ||
356 | Holds the documentation... with mappings from key to items... | ||
357 | """ | ||
358 | |||
359 | def __init__(self): | ||
360 | self.__keys = {} | ||
361 | self.__groups = {} | ||
362 | |||
363 | def insert_doc_item(self, item): | ||
364 | """ | ||
365 | Insert the Doc Item into the internal list | ||
366 | of representation | ||
367 | """ | ||
368 | item.sort() | ||
369 | self.__keys[item.name()] = item | ||
370 | |||
371 | for group in item.groups(): | ||
372 | if not group in self.__groups: | ||
373 | self.__groups[group] = [] | ||
374 | self.__groups[group].append(item) | ||
375 | self.__groups[group].sort() | ||
376 | |||
377 | |||
378 | def doc_item(self, key): | ||
379 | """ | ||
380 | Return the DocumentationInstance describing the key | ||
381 | """ | ||
382 | try: | ||
383 | return self.__keys[key] | ||
384 | except KeyError: | ||
385 | return None | ||
386 | |||
387 | def doc_keys(self): | ||
388 | """ | ||
389 | Return the documented KEYS (names) | ||
390 | """ | ||
391 | return self.__keys.keys() | ||
392 | |||
393 | def groups(self): | ||
394 | """ | ||
395 | Return the names of available groups | ||
396 | """ | ||
397 | return self.__groups.keys() | ||
398 | |||
399 | def group_content(self,group_name): | ||
400 | """ | ||
401 | Return a list of keys/names that are in a specefic | ||
402 | group or the empty list | ||
403 | """ | ||
404 | try: | ||
405 | return self.__groups[group_name] | ||
406 | except KeyError: | ||
407 | return [] | ||
408 | |||
409 | |||
410 | def parse_cmdline(args): | ||
411 | """ | ||
412 | Parse the CMD line and return the result as a n-tuple | ||
413 | """ | ||
414 | |||
415 | parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__,__version__)) | ||
416 | usage = """%prog [options] | ||
417 | |||
418 | Create a set of html pages (documentation) for a bitbake.conf.... | ||
419 | """ | ||
420 | |||
421 | # Add the needed options | ||
422 | parser.add_option( "-c", "--config", help = "Use the specified configuration file as source", | ||
423 | action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") ) | ||
424 | |||
425 | parser.add_option( "-o", "--output", help = "Output directory for html files", | ||
426 | action = "store", dest = "output", default = "html/" ) | ||
427 | |||
428 | parser.add_option( "-D", "--debug", help = "Increase the debug level", | ||
429 | action = "count", dest = "debug", default = 0 ) | ||
430 | |||
431 | parser.add_option( "-v","--verbose", help = "output more chit-char to the terminal", | ||
432 | action = "store_true", dest = "verbose", default = False ) | ||
433 | |||
434 | options, args = parser.parse_args( sys.argv ) | ||
435 | |||
436 | if options.debug: | ||
437 | bb.msg.set_debug_level(options.debug) | ||
438 | |||
439 | return options.config, options.output | ||
440 | |||
441 | def main(): | ||
442 | """ | ||
443 | The main Method | ||
444 | """ | ||
445 | |||
446 | (config_file,output_dir) = parse_cmdline( sys.argv ) | ||
447 | |||
448 | # right to let us load the file now | ||
449 | try: | ||
450 | documentation = bb.parse.handle( config_file, bb.data.init() ) | ||
451 | except IOError: | ||
452 | bb.fatal( "Unable to open %s" % config_file ) | ||
453 | except bb.parse.ParseError: | ||
454 | bb.fatal( "Unable to parse %s" % config_file ) | ||
455 | |||
456 | if isinstance(documentation, dict): | ||
457 | documentation = documentation[""] | ||
458 | |||
459 | # Assuming we've the file loaded now, we will initialize the 'tree' | ||
460 | doc = Documentation() | ||
461 | |||
462 | # defined states | ||
463 | state_begin = 0 | ||
464 | state_see = 1 | ||
465 | state_group = 2 | ||
466 | |||
467 | for key in bb.data.keys(documentation): | ||
468 | data = bb.data.getVarFlag(key, "doc", documentation) | ||
469 | if not data: | ||
470 | continue | ||
471 | |||
472 | # The Documentation now starts | ||
473 | doc_ins = DocumentationItem() | ||
474 | doc_ins.setName(key) | ||
475 | |||
476 | |||
477 | tokens = data.split(' ') | ||
478 | state = state_begin | ||
479 | string= "" | ||
480 | for token in tokens: | ||
481 | token = token.strip(',') | ||
482 | |||
483 | if not state == state_see and token == "@see": | ||
484 | state = state_see | ||
485 | continue | ||
486 | elif not state == state_group and token == "@group": | ||
487 | state = state_group | ||
488 | continue | ||
489 | |||
490 | if state == state_begin: | ||
491 | string += " %s" % token | ||
492 | elif state == state_see: | ||
493 | doc_ins.addRelation(token) | ||
494 | elif state == state_group: | ||
495 | doc_ins.addGroup(token) | ||
496 | |||
497 | # set the description | ||
498 | doc_ins.setDescription(string) | ||
499 | doc.insert_doc_item(doc_ins) | ||
500 | |||
501 | # let us create the HTML now | ||
502 | bb.mkdirhier(output_dir) | ||
503 | os.chdir(output_dir) | ||
504 | |||
505 | # Let us create the sites now. We do it in the following order | ||
506 | # Start with the index.html. It will point to sites explaining all | ||
507 | # keys and groups | ||
508 | html_slave = HTMLFormatter() | ||
509 | |||
510 | f = file('style.css', 'w') | ||
511 | print >> f, html_slave.createCSS() | ||
512 | |||
513 | f = file('index.html', 'w') | ||
514 | print >> f, html_slave.createIndex() | ||
515 | |||
516 | f = file('all_groups.html', 'w') | ||
517 | print >> f, html_slave.createGroupsSite(doc) | ||
518 | |||
519 | f = file('all_keys.html', 'w') | ||
520 | print >> f, html_slave.createKeysSite(doc) | ||
521 | |||
522 | # now for each group create the site | ||
523 | for group in doc.groups(): | ||
524 | f = file('group%s.html' % group, 'w') | ||
525 | print >> f, html_slave.createGroupSite(group, doc.group_content(group)) | ||
526 | |||
527 | # now for the keys | ||
528 | for key in doc.doc_keys(): | ||
529 | f = file('key%s.html' % doc.doc_item(key).name(), 'w') | ||
530 | print >> f, html_slave.createKeySite(doc.doc_item(key)) | ||
531 | |||
532 | |||
533 | if __name__ == "__main__": | ||
534 | main() | ||