Synopsis - Cross-Reference
File: Synopsis/Formatters/HTML/__init__.py1# 2# Copyright (C) 2003 Stefan Seefeld 3# All rights reserved. 4# Licensed to the public under the terms of the GNU LGPL (>= 2), 5# see the file COPYING for details. 6# 7 8from Synopsis import config 9from Synopsis.Processor import * 10from Synopsis import IR, ASG 11from Synopsis.QualifiedName import * 12from Synopsis.DocString import DocString 13from Synopsis.FileTree import make_file_tree 14from Synopsis.Formatters.TOC import TOC 15from Synopsis.Formatters.ClassTree import ClassTree 16from DirectoryLayout import * 17from XRefPager import XRefPager 18from Views import * 19from Frame import Frame 20from FrameSet import FrameSet 21from Synopsis.Formatters.HTML.Markup.Javadoc import Javadoc 22try: 23 from Synopsis.Formatters.HTML.Markup.RST import RST 24except ImportError: 25 from Synopsis.Formatters.HTML.Markup import Formatter as RST 26import Markup 27import Tags 28 29import time 30 31class DocCache: 32 """""" 33 34 def __init__(self, processor, markup_formatters): 35 36 self._processor = processor 37 self._markup_formatters = markup_formatters 38 # Make sure we have a default markup formatter. 39 if '' not in self._markup_formatters: 40 self._markup_formatters[''] = Markup.Formatter() 41 for f in self._markup_formatters.values(): 42 f.init(self._processor) 43 self._doc_cache = {} 44 45 46 def _process(self, decl, view): 47 """Return the documentation for the given declaration.""" 48 49 key = id(decl) 50 if key not in self._doc_cache: 51 doc = decl.annotations.get('doc') 52 if doc: 53 formatter = self._markup_formatters.get(doc.markup, 54 self._markup_formatters['']) 55 doc = formatter.format(decl, view) 56 else: 57 doc = Markup.Struct() 58 59 # FIXME: Unfortunately we can't easily cache these, as they may 60 # contain relative URLs that aren't valid across views. 61 # self._doc_cache[key] = doc 62 return doc 63 else: 64 return self._doc_cache[key] 65 66 67 def summary(self, decl, view): 68 """""" 69 70 doc = self._process(decl, view) 71 return doc.summary 72 73 74 def details(self, decl, view): 75 """""" 76 77 doc = self._process(decl, view) 78 return doc.details 79 80 81class Formatter(Processor): 82 83 title = Parameter('Synopsis - Generated Documentation', 'title to put into html header') 84 stylesheet = Parameter(os.path.join(config.datadir, 'html.css'), 'stylesheet to be used') 85 directory_layout = Parameter(NestedDirectoryLayout(), 'how to lay out the output files') 86 toc_in = Parameter([], 'list of table of content files to use for symbol lookup') 87 toc_out = Parameter('', 'name of file into which to store the TOC') 88 sxr_prefix = Parameter(None, 'path prefix (directory) under which to find sxr info') 89 90 index = Parameter([ModuleTree(), FileTree()], '') 91 detail = Parameter([ModuleIndex(), FileIndex()], '') 92 content = Parameter([Scope(), 93 Source(), 94 XRef(), 95 FileDetails(), 96 InheritanceTree(), 97 InheritanceGraph(), 98 NameIndex()], 99 '') 100 101 markup_formatters = Parameter({'javadoc':Javadoc(), 102 'rst':RST(), 103 'reStructuredText':RST()}, 104 'Markup-specific formatters.') 105 graph_color = Parameter('#ffcc99', 'base color for inheritance graphs') 106 107 def process(self, ir, **kwds): 108 109 self.set_parameters(kwds) 110 if not self.output: raise MissingArgument('output') 111 112 self.ir = self.merge_input(ir) 113 # Make sure we operate on a single top-level node. 114 # (Python package, C++ global namespace, etc.) 115 if (len(self.ir.asg.declarations) != 1 or 116 not isinstance(self.ir.asg.declarations[0], ASG.Module)): 117 # Assume this is C++ in this case. 118 self.root = ASG.Module(None, -1, 'namespace', QualifiedName()) 119 self.root.declarations = ir.asg.declarations 120 else: 121 self.root = self.ir.asg.declarations[0] 122 123 self.directory_layout.init(self) 124 self.documentation = DocCache(self, self.markup_formatters) 125 126 # Create the class tree (shared by inheritance graph / tree views). 127 self.class_tree = ClassTree() 128 for d in self.root.declarations: 129 d.accept(self.class_tree) 130 131 # Create the file tree (shared by file listing / tree views). 132 self.file_tree = make_file_tree(self.ir.files.values()) 133 134 # Create the cross reference table (shared by XRef / Scope views) 135 self.xref = XRefPager(self.ir) 136 137 from Synopsis.DeclarationSorter import DeclarationSorter 138 self.sorter = DeclarationSorter() 139 140 # Make all views queryable through Formatter.has_view() 141 self.views = self.content + self.index + self.detail 142 143 frames = [] 144 # If only content contains views don't use frames. 145 if self.index or self.detail: 146 Tags.using_frames = True 147 148 frames.append(Frame(self, self.index)) 149 frames.append(Frame(self, self.detail)) 150 frames.append(Frame(self, self.content)) 151 else: 152 Tags.using_frames = False 153 154 frames.append(Frame(self, self.content, noframes = True)) 155 156 self.__files = {} # map from filename to (view,scope) 157 158 # The table of content is by definition the TOC of the first 159 # view on the content frame. 160 self.toc = self.content[0].toc() 161 if self.verbose: print "TOC size:", self.toc.size() 162 if self.toc_out: self.toc.store(self.toc_out) 163 # load external references from toc files, if any 164 for t in self.toc_in: self.toc.load(t) 165 166 if self.verbose: print "HTML Formatter: Generating views..." 167 168 # Process the views. 169 if len(frames) > 1: 170 frameset = FrameSet() 171 frameset.process(self.output, self.directory_layout.index(), 172 self.title, 173 self.index[0].root()[0] or self.index[0].filename(), 174 self.detail[0].root()[0] or self.detail[0].filename(), 175 self.content[0].root()[0] or self.content[0].filename()) 176 for frame in frames: frame.process() 177 return self.ir 178 179 def has_view(self, name): 180 """test whether the given view is part of the views list.""" 181 182 return name in [x.__class__.__name__ for x in self.views] 183 184 def register_filename(self, filename, view, scope): 185 """Registers a file for later production. The first view to register 186 the filename gets to keep it.""" 187 188 filename = str(filename) 189 if not self.__files.has_key(filename): 190 self.__files[filename] = (view, scope) 191 192 def filename_info(self, filename): 193 """Returns information about a registered file, as a (view,scope) 194 pair. Will return None if the filename isn't registered.""" 195 196 return self.__files.get(filename) 197 198
Generated on Tue May 13 02:39:12 2008 by
synopsis (version 0.10)
synopsis (version 0.10)