Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Formatter/HTML/core.py
1| # $Id: core.py,v 1.47 2003/01/20 06:43:02 chalky Exp $
2| #
3| # This file is a part of Synopsis.
4| # Copyright (C) 2000, 2001 Stephen Davies
5| #
6| # Synopsis is free software; you can redistribute it and/or modify it
7| # under the terms of the GNU General Public License as published by
8| # the Free Software Foundation; either version 2 of the License, or
9| # (at your option) any later version.
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 GNU
14| # General Public License for more details.
15| #
16| # You should have received a copy of the GNU General Public License
17| # along with this program; if not, write to the Free Software
18| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19| # 02111-1307, USA.
20| #
21| # $Log: core.py,v $
22| # Revision 1.47 2003/01/20 06:43:02 chalky
23| # Refactored comment processing. Added AST.CommentTag. Linker now determines
24| # comment summary and extracts tags. Increased AST version number.
25| #
26| # Revision 1.46 2003/01/16 16:48:23 chalky
27| # Using FileTree now forces FileListing, FileIndexer and FileDetails to be used.
28| #
29| # Revision 1.45 2003/01/16 12:46:46 chalky
30| # Renamed FilePages to FileSource, FileTree to FileListing. Added FileIndexer
31| # (used to be part of FileTree) and FileDetails.
32| #
33| # Revision 1.44 2003/01/02 07:00:58 chalky
34| # Only use Core.FileTree, refactored FileTree to be quicker and better.
35| #
36| # Revision 1.43 2002/12/12 17:25:33 chalky
37| # Implemented Include support for C++ parser. A few other minor fixes.
38| #
39| # Revision 1.42 2002/12/09 04:00:59 chalky
40| # Added multiple file support to parsers, changed AST datastructure to handle
41| # new information, added a demo to demo/C++. AST Declarations now have a
42| # reference to a SourceFile (which includes a filename) instead of a filename.
43| #
44| # Revision 1.41 2002/11/16 04:12:33 chalky
45| # Added strategies for page formatting, and added one to allow template HTML
46| # files to be used.
47| #
48| # Revision 1.40 2002/11/13 02:29:24 chalky
49| # Support exclude_glob option to exclude files from listings. Remove debug info.
50| #
51| # Revision 1.39 2002/11/11 15:19:35 chalky
52| # More fixes to get demo/C++ sxr working without frames
53| #
54| # Revision 1.38 2002/11/02 06:37:37 chalky
55| # Allow non-frames output, some refactoring of page layout, new modules.
56| #
57| # Revision 1.37 2002/10/29 12:43:56 chalky
58| # Added flexible TOC support to link to things other than ScopePages
59| #
60| # Revision 1.36 2002/10/28 17:39:37 chalky
61| # Cross referencing support
62| #
63| # Revision 1.35 2002/10/28 06:12:30 chalky
64| # Add structs_as_classes option
65| #
66| # Revision 1.34 2002/10/27 12:05:44 chalky
67| # Add 2 verbose levels, make default (1) less verbose
68| #
69| # Revision 1.33 2002/10/11 06:02:33 chalky
70| # Allow GUi to pass config object
71| #
72| # Revision 1.32 2002/08/23 04:37:26 chalky
73| # Huge refactoring of Linker to make it modular, and use a config system similar
74| # to the HTML package
75| #
76| # Revision 1.31 2002/07/04 06:43:18 chalky
77| # Improved support for absolute references - pages known their full path.
78| #
79| # Revision 1.30 2002/07/04 05:16:19 chalky
80| # Impl output_dir option for config to replace -o argument to HTML formatter.
81| #
82| # Revision 1.29 2002/03/14 00:19:47 chalky
83| # Added demo of template specializations, and fixed HTML formatter to deal with
84| # angle brackets in class names :)
85| #
86| # Revision 1.28 2002/01/13 09:44:51 chalky
87| # Allow formatted source in GUI
88| #
89| # Revision 1.27 2002/01/09 11:43:41 chalky
90| # Inheritance pics
91| #
92| # Revision 1.26 2002/01/09 10:16:35 chalky
93| # Centralized navigation, clicking links in (html) docs works.
94| #
95| # Revision 1.25 2001/11/09 15:35:04 chalky
96| # GUI shows HTML pages. just. Source window also scrolls to correct line.
97| #
98| # Revision 1.24 2001/07/19 05:10:39 chalky
99| # Use filenames stored in AST object
100| #
101| # Revision 1.23 2001/07/19 04:03:05 chalky
102| # New .syn file format.
103| #
104| # Revision 1.22 2001/07/10 14:41:22 chalky
105| # Make treeformatter config nicer
106| #
107| # Revision 1.21 2001/07/10 02:55:51 chalky
108| # Better comments in some files, and more links work with the nested layout
109| #
110| # Revision 1.20 2001/07/05 02:08:35 uid20151
111| # Changed the registration of pages to be part of a two-phase construction
112| #
113| # Revision 1.19 2001/07/04 08:17:48 uid20151
114| # Comments
115| #
116| # Revision 1.18 2001/06/28 07:22:18 stefan
117| # more refactoring/cleanup in the HTML formatter
118| #
119| # Revision 1.17 2001/06/26 04:32:16 stefan
120| # A whole slew of changes mostly to fix the HTML formatter's output generation,
121| # i.e. to make the output more robust towards changes in the layout of files.
122| #
123| # the rpm script now works, i.e. it generates source and binary packages.
124| #
125| # Revision 1.16 2001/06/16 01:29:42 stefan
126| # change the HTML formatter to not use chdir, as this triggers a but in python's import implementation
127| #
128| # Revision 1.15 2001/06/05 05:28:34 chalky
129| # Some old tree abstraction
130| #
131| # Revision 1.14 2001/05/25 13:45:49 stefan
132| # fix problem with getopt error reporting
133| #
134| # Revision 1.13 2001/04/06 02:39:26 chalky
135| # Get toc in/out from config
136| #
137| # Revision 1.12 2001/04/06 01:41:09 chalky
138| # More verbose verbosity
139| #
140| # Revision 1.11 2001/03/29 14:05:33 chalky
141| # Can give namespace to manager._calculateStart. Timing of pages if verbose
142| #
143| # Revision 1.10 2001/02/13 02:54:15 chalky
144| # Added Name Index page
145| #
146| # Revision 1.9 2001/02/12 04:08:09 chalky
147| # Added config options to HTML and Linker. Config demo has doxy and synopsis styles.
148| #
149| # Revision 1.8 2001/02/07 14:13:51 chalky
150| # Small fixes.
151| #
152| # Revision 1.7 2001/02/06 05:13:05 chalky
153| # Fixes
154| #
155| # Revision 1.6 2001/02/05 07:58:39 chalky
156| # Cleaned up image copying for *JS. Added synopsis logo to ScopePages.
157| #
158| # Revision 1.5 2001/02/05 05:26:24 chalky
159| # Graphs are separated. Misc changes
160| #
161| # Revision 1.4 2001/02/01 20:08:35 chalky
162| # Added types to config
163| #
164| # Revision 1.3 2001/02/01 18:36:55 chalky
165| # Moved TOC out to Formatter/TOC.py
166| #
167| # Revision 1.2 2001/02/01 15:23:24 chalky
168| # Copywritten brown paper bag edition.
169| #
170| # Revision 1.1 2001/02/01 14:58:48 chalky
171| # Modularized HTML formatter a bit :)
172| #
173| # These are from the old HTML.py:
174| # Revision 1.55 2001/01/24 18:05:16 stefan
175| # extended the HTML submodule loading to allow for external formatters
176| #
177| # Revision 1.54 2001/01/24 13:06:48 chalky
178| # Fixed bug related to /**/ causing following //. to be on same line
179| #
180| # Revision 1.53 2001/01/24 12:50:23 chalky
181| # Fixes to get summary/detail linking again since AST.Visitor changed ...
182| #
183| # Revision 1.52 2001/01/24 01:38:36 chalky
184| # Added docstrings to all modules
185| #
186| # Revision 1.51 2001/01/23 00:20:27 chalky
187| # Added employee.cc demo. Fixed small bug wrt linking to details of variables.
188| #
189| # Revision 1.50 2001/01/22 20:14:36 stefan
190| # forgot two flags in the usage() function
191| #
192| # Revision 1.49 2001/01/22 19:54:41 stefan
193| # better support for help message
194| #
195| # Revision 1.48 2001/01/22 17:06:15 stefan
196| # added copyright notice, and switched on logging
197| #
198|
199| # HTML2 Formatter by Stephen Davies
200| # Based on HTML Formatter by Stefan Seefeld
201| #
202| # Generates a page for each Module/Class and an inheritance tree
203| # Also 3-frame format inspired by Javadoc
204|
205| """
206| Core module for the HTML Formatter.
207|
208| This module is the first to be loaded, and it creates the global 'core.config'
209| object before creating any pages. It also handles the command line parsing for
210| this module, and coordinates the actual output generation.
211| """
212|
213| # System modules
214| import sys, getopt, os, os.path, string, types, errno, stat, re, time
215|
216| # Synopsis modules
217| from Synopsis.Config import Base
218| from Synopsis.Core import AST, Type, Util
219| from Synopsis.Core.FileTree import FileTree
220| from Synopsis.Formatter import TOC, ClassTree, xref
221| from Synopsis.Formatter.HTML import TreeFormatter
222|
223| from Synopsis.Core.Util import import_object
224|
225| verbose=0
226|
227| # Create the Config class before importing any HTML modules
228| class Config:
229| """Central configuration repository for HTML formatter.
230| This class holds references to the current formatters, tocs, etc."""
231| def __init__(self):
232| """Constructor - initialise objects to None."""
233| self.ast = None
234| self.commentFormatter = None
235| self.commentFormatterList = []
236| self.types = None # Filled in first thing in format()
237| self.toc = None
238| self.toc_out = ""
239| self.toc_in = []
240| self.default_toc = 'ScopePages'
241| self.basename = None
242| self.datadir = None
243| self.stylesheet = ""
244| self.stylesheet_file = None
245| self.sorter = None
246| self.namespace = ""
247| self.files = None
248| self.files_class = None
249| self.pageset = None
250| self.sorter = None
251| self.classTree = None
252| self.structs_as_classes = 0
253| self.using_frames = 1
254| self.using_module_index = 0
255| self.base_dir = ''
256| self.start_dir = ''
257| self.exclude_globs = []
258| self.page_format = ""
259| self.treeFormatterClass = TreeFormatter.TreeFormatter
260| self.page_contents = "" # page contents frame (top-left)
261| self.page_index = "" # page for index frame (left)
262| self.page_main = "" # page for main index.html page
263| self.pages = [
264| 'ScopePages', 'ModuleListing', 'ModuleIndexer',
265| 'FileListing', 'FileIndexer', 'FileDetails',
266| 'InheritanceTree', 'InheritanceGraph', 'NameIndex', 'FramesIndex'
267| ]
268| self.verbose = 0
269| self.xref = xref.CrossReferencer()
270|
271|
272| def fillDefaults(self):
273| """Fill in empty options with defaults"""
274| if not self.sorter:
275| import ScopeSorter
276| self.sorter = ScopeSorter.ScopeSorter()
277|
278| def use_config(self, obj):
279| """Extracts useful attributes from 'obj' and stores them. The object
280| itself is also stored as config.obj"""
281| # obj.pages is a list of module names
282| self.obj = obj
283| if hasattr(obj, 'verbose'): self.verbose = obj.verbose
284| options = ('pages', 'sorter', 'datadir', 'stylesheet', 'stylesheet_file',
285| 'comment_formatters', 'toc_out', 'toc_in', 'tree_formatter',
286| 'file_layout', 'output_dir', 'structs_as_classes', 'default_toc',
287| 'base_dir', 'start_dir', 'exclude_globs', 'page_format')
288| for option in options:
289| if hasattr(obj, option):
290| getattr(self, '_config_'+option)(getattr(obj, option))
291| elif self.verbose > 1: print "Option",option,"not found in config."
292|
293| def _config_pages(self, pages):
294| "Configures from the given list of pages"
295| if type(pages) != types.ListType:
296| raise TypeError, "HTML.pages must be a list."
297| if self.verbose > 1: print "Using pages:",pages
298| self.pages = pages
299| if 'FramesIndex' in pages: self.using_frames = 1
300| else: self.using_frames = 0
301|
302| def _config_sorter(self, sorter):
303| if self.verbose > 1: print "Using sorter:",sorter
304| self.sorter = import_object(sorter)()
305|
306| def _config_datadir(self, datadir):
307| if self.verbose > 1: print "Using datadir:", datadir
308| self.datadir = datadir
309|
310| def _config_output_dir(self, output_dir):
311| if self.verbose > 1: print "Using output_dir:", output_dir
312| self.basename = output_dir
313|
314| def _config_stylesheet(self, stylesheet):
315| if self.verbose > 1: print "Using stylesheet:", stylesheet
316| self.stylesheet = stylesheet
317|
318| def _config_stylesheet_file(self, stylesheet_file):
319| if self.verbose > 1: print "Using stylesheet file:", stylesheet_file
320| self.stylesheet_file = stylesheet_file
321|
322| def _config_comment_formatters(self, comment_formatters):
323| if self.verbose > 1: print "Using comment formatters:", comment_formatters
324| basePackage = 'Synopsis.Formatter.HTML.CommentFormatter.'
325| for formatter in comment_formatters:
326| if type(formatter) == types.StringType:
327| if CommentFormatter.commentFormatters.has_key(formatter):
328| self.commentFormatterList.append(
329| CommentFormatter.commentFormatters[formatter]()
330| )
331| else:
332| raise ImportError, "No builtin comment formatter '%s'"%formatter
333| else:
334| clas = import_object(formatter, basePackage)
335| self.commentFormatterList.append(clas())
336|
337| def _config_toc_in(self, toc_in):
338| if self.verbose > 1: print "Will read toc(s) from",toc_in
339| self.toc_in = toc_in
340|
341| def _config_default_toc(self, page):
342| if self.verbose > 1: print "Will use page %s for generating default TOC"%page
343| self.default_toc = page
344|
345| def _config_toc_out(self, toc_out):
346| if self.verbose > 1: print "Will save toc to",toc_out
347| self.toc_out = toc_out
348|
349| def _config_tree_formatter(self, tree_class):
350| if self.verbose > 1: print "Using tree class",tree_class
351| clas = import_object(tree_class, basePackage='Synopsis.Formatter.HTML.')
352| self.treeFormatterClass = clas
353|
354| def _config_file_layout(self, layout):
355| if self.verbose > 1: print "Using file layout",layout
356| self.files_class = import_object(layout)
357|
358| def _config_base_dir(self, dir):
359| if self.verbose > 1: print "Using base dir",dir
360| self.base_dir = str(dir)
361|
362| def _config_start_dir(self, dir):
363| if self.verbose > 1: print "Using start dir",dir
364| self.start_dir = str(dir)
365|
366| def _config_structs_as_classes(self, yesno):
367| if self.verbose > 1: print "Using structs as classes:",yesno
368| self.structs_as_classes = yesno
369|
370| def _config_exclude_globs(self, globs):
371| if self.verbose > 1: print "Using exclude globs:",globs
372| self.exclude_globs = map(compile_glob, globs)
373|
374| def _config_page_format(self, page_format):
375| if self.verbose > 1: print "Using page format class:",page_format
376| self.page_format = page_format
377|
378| def set_contents_page(self, page):
379| """Call this method to set the contents page. First come first served
380| -- whatever module the user puts first in the list that sets this is
381| it. This is the frame in the top-left if you use the default frameset."""
382| if not self.page_contents: self.page_contents = page
383|
384| def set_index_page(self, page):
385| """Call this method to set the index page. First come first served
386| -- whatever module the user puts first in the list that sets this is
387| it. This is the frame on the left if you use the default frameset."""
388| if not self.page_index: self.page_index = page
389|
390| def set_main_page(self, page):
391| """Call this method to set the main index.html page. First come first served
392| -- whatever module the user puts first in the list that sets this is
393| it."""
394| if not self.page_main: self.page_main = page
395|
396| def set_using_module_index(self):
397| """Sets the using_module_index flag. This will cause the an
398| intermediate level of links intended to go in the left frame."""
399| self.using_module_index = 1
400|
401| # Create a globally accessible Config. After this point the HTML modules may
402| # import it into their namespace for ease of use
403| config = Config()
404|
405| # HTML modules
406| import CommentFormatter, FileLayout, ScopeSorter, Page
407| from Tags import *
408|
409| def sort(list):
410| "Utility func to sort and return the given list"
411| list.sort()
412| return list
413|
414| def old_reference(name, scope, label=None, **keys):
415| """Utility method to insert a reference to a name.
416| @see ASTFormatter.BaseFormatter.reference()
417| """
418| if not label: label = anglebrackets(Util.ccolonName(name, scope))
419| entry = config.toc[name]
420| if entry: return apply(href, (entry.link, label), keys)
421| return label or ''
422|
423| def compile_glob(globstr):
424| """Returns a compiled regular expression for the given glob string. A
425| glob string is something like "*.?pp" which gets translated into
426| "^.*\..pp$"."""
427| glob = string.replace(globstr, '.', '\.')
428| glob = string.replace(glob, '?', '.')
429| glob = string.replace(glob, '*', '.*')
430| glob = re.compile('^%s$'%glob)
431| return glob
432|
433|
434| class Struct:
435| "Dummy class. Initialise with keyword args."
436| def __init__(self, **keys):
437| for name, value in keys.items(): setattr(self, name, value)
438|
439| class DeclStyle:
440| """This class just maintains a mapping from declaration to display style.
441| The style is an enumeration, possible values being: SUMMARY (only display
442| a summary for this declaration), DETAIL (summary and detailed info),
443| INLINE (summary and detailed info, where detailed info is an inline
444| version of the declaration even if it's a class, etc.)
445|
446| Upon initiation, an instance of this class installs itself in the config
447| object as "decl_style".
448| """
449| SUMMARY = 0
450| DETAIL = 1
451| INLINE = 2
452|
453| def __init__(self):
454| self.__dict = {}
455| def style_of(self, decl):
456| """Returns the style of the given decl"""
457| SUMMARY = self.SUMMARY
458| DETAIL = self.DETAIL
459| key = id(decl)
460| if self.__dict.has_key(key): return self.__dict[key]
461| if len(decl.comments()) == 0:
462| # Set to summary, as this will mean no detailed section
463| style = SUMMARY
464| else:
465| comment = decl.comments()[0]
466| # Calculate the style. The default is detail
467| if not comment.text():
468| # No comment, don't show detail
469| style = SUMMARY
470| elif comment.summary() != comment.text():
471| # There is more to the comment than the summary, show detail
472| style = DETAIL
473| else:
474| # Summary == Comment, don't show detail
475| style = SUMMARY
476| # Always show tags
477| if comment.tags():
478| style = DETAIL
479| # Always show enums
480| if isinstance(decl, AST.Enum):
481| style = DETAIL
482| # Show functions if they have exceptions
483| if isinstance(decl, AST.Function) and len(decl.exceptions()):
484| style = DETAIL
485| # Don't show detail for scopes (they have their own pages)
486| if isinstance(decl, AST.Scope):
487| style = SUMMARY
488| self.__dict[key] = style
489| return style
490| __getitem__ = style_of
491|
492| class PageManager:
493| """This class manages and coordinates the various pages. The user adds
494| pages by passing their class object to the addPage method. Pages should be
495| derived from Page.Page, and their constructors may want to call the
496| addRootPage method of the PageManager object to register a name and link
497| that is listed along with other root or top-level pages.
498| @see Page.Page
499| """
500| def __init__(self):
501| self.__pages = [] #all pages
502| self.__roots = [] #pages with roots, list of Structs
503| self.__global = None # The global scope
504| self.__files = {} # map from filename to (page,scope)
505| self.__page_objects = {} # map of pages by name
506| self._loadPages()
507|
508| def getPage(self, name):
509| """Returns the Page with the given name"""
510| return self.__page_objects[name]
511|
512| def globalScope(self):
513| "Return the global scope"
514| return self.__global
515|
516| def calculateStart(self, root, namespace=None):
517| "Calculates the start scope using the 'namespace' config var"
518| scope_names = string.split(namespace or config.namespace, "::")
519| start = root # The running result
520| config.sorter.set_scope(root)
521| scope = [] # The running name of the start
522| for scope_name in scope_names:
523| if not scope_name: break
524| scope.append(scope_name)
525| try:
526| child = config.sorter.child(tuple(scope))
527| if isinstance(child, AST.Scope):
528| start = child
529| config.sorter.set_scope(start)
530| else:
531| raise TypeError, 'calculateStart: Not a Scope'
532| except:
533| # Don't continue if scope traversal failed!
534| import traceback
535| traceback.print_exc()
536| print "Fatal: Couldn't find child scope",scope
537| print "Children:",map(lambda x:x.name(), config.sorter.children())
538| sys.exit(3)
539| return start
540|
541| def addPage(self, pageClass):
542| """Add a page of the given class. An instance is created and stored,
543| and its root() method is called and the name,link tuple stored if None
544| isn't returned."""
545| page = pageClass(self)
546| self.__pages.append(page)
547| page.register()
548| return page
549|
550| def addRootPage(self, file, label, target, visibility):
551| """Adds a named link to the list of root pages. Called from the
552| constructors of Page objects. The root pages are displayed at the top
553| of every page, depending on their visibility (higher = more visible).
554| @param file the filename, to be used when generating the
555| @param label the label of the p
556| @param target target frame
557| @param visibility should be a number such as 1 or 2. Visibility 2 is
558| shown on all pages, 1 only on pages with lots of
559| room. For example, pages for the top-left frame
560| only show visibility 2 pages."""
561| self.__roots.append(Struct(file=file, label=label, target=target, visibility=visibility))
562|
563| def formatHeader(self, origin, visibility=1):
564| """Formats the list of root pages to HTML. The origin specifies the
565| generated page itself (which shouldn't be linked), such that the relative
566| links can be generated. Only root pages of 'visibility' or
567| above are included."""
568| # If not using frames, show all headings on all pages!
569| if not config.using_frames: visibility=1
570| #filter out roots that are visible
571| roots = filter(lambda x,v=visibility: x.visibility >= v, self.__roots)
572| #a function generating a link
573| other = lambda x, o=origin, span=span: span('root-other', href(rel(o, x.file), x.label, target=x.target))
574| #a function simply printing label
575| current = lambda x, span=span: span('root-current', x.label)
576| # generate the header
577| roots = map(lambda x, o=origin, other=other, current=current: x.file==o and current(x) or other(x), roots)
578| return string.join(roots, ' | \n')+'\n<hr>\n'
579|
580| def process(self, root):
581| """Create all pages from the start Scope, derived from the root Scope"""
582| self.__global = root
583| start = self.calculateStart(root)
584| if config.verbose: print "Registering filenames...",
585| for page in self.__pages:
586| page.register_filenames(start)
587| if config.verbose: print "Done."
588| for page in self.__pages:
589| if config.verbose:
590| print "Time for %s:"%page.__class__.__name__,
591| sys.stdout.flush()
592| start_time = time.time()
593| page.process(start)
594| if config.verbose:
595| print "%f"%(time.time() - start_time)
596|
597| def _loadPages(self):
598| """Loads the page objects from the config.pages list. Each element is
599| either a string or a tuple of two strings. One string means load the named
600| module and look for a 'htmlPageClass' attribute in it. A tuple of two
601| strings means load the module from the first string, and look for an
602| attribute using the second string."""
603| defaultAttr = 'htmlPageClass'
604| basePackage = 'Synopsis.Formatter.HTML.'
605| for page in list(config.pages):
606| obj = self.addPage(import_object(page, defaultAttr, basePackage))
607| self.__page_objects[page] = obj
608|
609| def register_filename(self, filename, page, scope):
610| """Registers a file for later production. The first page to register
611| the filename gets to keep it."""
612| filename = str(filename)
613| if not self.__files.has_key(filename):
614| self.__files[filename] = (page, scope)
615|
616| def filename_info(self, filename):
617| """Returns information about a registered file, as a (page,scope)
618| pair. Will return None if the filename isn't registered."""
619| filename = str(filename)
620| if not self.__files.has_key(filename): return None
621| return self.__files[filename]
622|
623| def usage():
624| """Print usage to stdout"""
625| print \
626| """
627| -o <dir> Output directory, created if it doesn't exist.
628| -s <filename> Filename of stylesheet in output directory
629| -S <filename> Filename of stylesheet to copy
630| If this is newer than the one in the output directory then it
631| is copied over it.
632| -n <namespace> Namespace to output
633| -c <formatter> add external Comment formatter
634| -C <formatter> add std Comment formatter (part of the HTML module) to use
635| - default Nothing
636| - ssd Filters for and strips //. comments
637| - javadoc @tag style comments
638| - section test section breaks.
639| You may use multiple -c options
640| -t <filename> Generate a table of content and write it to <filename>
641| -r <filename> ['|'<url>|<directory>] merge in table of content from <filename>, possibly prefixing entries with the
642| given url or directory, to resolve external symbols"""
643|
644| def __parseArgs(args, config_obj):
645| global verbose, commentParser, toc_out, toc_in
646| commentFormatters = CommentFormatter.commentFormatters
647| # Defaults
648|
649| # Convert the arguments to a list with custom getopt
650| try:
651| opts,remainder = Util.getopt_spec(args, "hvo:s:n:c:C:S:t:r:d:")
652| except Util.getopt.error, e:
653| sys.stderr.write("Error in arguments: " + str(e) + "\n")
654| sys.exit(1)
655|
656| # Check for verbose first so config loading can use it
657| for o, a in opts:
658| if o == '-v':
659| config.verbose = verbose = 1
660|
661| # Use config object if present
662| if config_obj: config.use_config(config_obj)
663| elif config.verbose: print "No config object given"
664|
665| # Parse the list of arguments
666| for opt in opts:
667| o,a = opt
668| if o == "-o":
669| config.basename = a #open(a, "w")
670| elif o == "-d":
671| config.datadir = a
672| elif o == "-s":
673| config.stylesheet = a
674| elif o == "-S":
675| config.stylesheet_file = a
676| elif o == "-n":
677| config.namespace = a
678| elif o == "-c": config.commentFormatterList.append(Util._import(a))
679| elif o == "-C":
680| if commentFormatters.has_key(a):
681| config.commentFormatterList.append(commentFormatters[a]())
682| else:
683| print "Error: Unknown formatter. Available comment formatters are:",string.join(commentFormatters.keys(), ', ')
684| sys.exit(1)
685| elif o == "-t":
686| config.toc_out = a
687| elif o == "-r":
688| config.toc_in.append(a)
689| elif o == "-h":
690| usage()
691| sys.exit(1)
692| elif o == "-v":
693| verbose=1
694| config.verbose = 1
695|
696| # Fill in any unspecified defaults
697| config.fillDefaults()
698|
699| def format(args, ast, config_obj):
700| global toc_out, toc_in, manager
701| __parseArgs(args, config_obj)
702| config.ast = ast
703| config.types = ast.types()
704| declarations = ast.declarations()
705|
706| # Instantiate the files object
707| config.files = config.files_class()
708|
709| # Create the declaration styler and the comment formatter
710| config.decl_style = DeclStyle()
711| config.comments = CommentFormatter.CommentFormatter()
712|
713| # Create the Class Tree (TODO: only if needed...)
714| config.classTree = ClassTree.ClassTree()
715|
716| # Create the File Tree (TODO: only if needed...)
717| config.fileTree = FileTree()
718| config.fileTree.set_ast(ast)
719|
720| # Build class tree
721| for d in declarations:
722| d.accept(config.classTree)
723|
724| # Create the page manager, which loads the pages
725| manager = PageManager()
726| root = AST.Module(None,-1,"C++","Global",())
727| root.declarations()[:] = declarations
728|
729| # Create table of contents index
730| start = manager.calculateStart(root)
731| config.toc = manager.getPage(config.default_toc).get_toc(start)
732| if verbose: print "HTML Formatter: Initialising TOC"
733|
734| # Add all declarations to the namespace tree
735| #for d in declarations:
736| # d.accept(config.t
737|
738| if verbose: print "TOC size:",config.toc.size()
739| if len(config.toc_out): config.toc.store(config.toc_out)
740|
741| # load external references from toc files, if any
742| for t in config.toc_in: config.toc.load(t)
743|
744| if verbose: print "HTML Formatter: Writing Pages..."
745| # Create the pages
746| manager.process(root)
747|
748| def configure_for_gui(ast, config_obj):
749| global manager
750|
751| if config.ast is ast: return
752|
753| __parseArgs(["-o","/tmp"], config_obj)
754| config.ast = ast
755| config.types = ast.types()
756| declarations = ast.declarations()
757| config.files = config.files_class()
758| config.decl_style = DeclStyle()
759| config.comments = CommentFormatter.CommentFormatter()
760| config.classTree = ClassTree.ClassTree()
761| FileTree()
762|
763| # Build class and file trees
764| for d in declarations:
765| d.accept(config.classTree)
766|
767| config.fileTree.buildTree()
768|
769| # Create table of contents index
770| config.toc = TOC.TableOfContents(config.files)
771|
772| # Add all declarations to the namespace tree
773| for d in declarations:
774| d.accept(config.toc)
775| #if len(config.toc_out): config.toc.store(config.toc_out)
776|
777| # load external references from toc files, if any
778| for t in config.toc_in: config.toc.load(t)
779|
780| # Create the pages
781| # Create a dummy Module for the global namespace to simplify things
782| #root = AST.Module('',-1,"C++","Global",())
783| #root.declarations()[:] = declarations
784| manager = PageManager()
785| #manager.process(root)
786|
787|