File: Synopsis/Formatters/HTML/Views/Source.py
  1#
  2# Copyright (C) 2000 Stephen Davies
  3# Copyright (C) 2000 Stefan Seefeld
  4# All rights reserved.
  5# Licensed to the public under the terms of the GNU LGPL (>= 2),
  6# see the file COPYING for details.
  7#
  8
  9from Synopsis import config
 10from Synopsis.Processor import *
 11from Synopsis.QualifiedName import *
 12from Synopsis.Formatters import join_paths
 13from Synopsis.Formatters.HTML.View import View
 14from Synopsis.Formatters.HTML.Tags import *
 15from xml.dom.minidom import parse
 16import os, urllib, time
 17
 18class SXRTranslator:
 19    """Read in an sxr file, resolve references, and write it out as
 20    part of a Source view."""
 21
 22    def __init__(self, filename, language, debug):
 23
 24        try:
 25            self.sxr = parse(filename)
 26        except:
 27            if debug:
 28                print 'Error parsing', filename
 29                raise
 30            else:
 31                raise InternalError('parsing %s'%filename)
 32        if language == 'Python':
 33            self.qname = lambda name: QualifiedPythonName(str(name).split('.'))
 34        else:
 35            self.qname = lambda name: QualifiedCxxName(str(name).split('::'))
 36
 37    def link(self, linker):
 38
 39        for a in self.sxr.getElementsByTagName('a'):
 40            ref = self.qname(a.getAttribute('href'))
 41            target = linker(ref)
 42            a.setAttribute('href', target)
 43            if a.hasAttribute('type'):
 44                a.removeAttribute('type')
 45            if a.hasAttribute('from'):
 46                a.removeAttribute('from')
 47            if a.hasAttribute('continuation'):
 48                a.removeAttribute('continuation')
 49
 50    def translate(self, writer):
 51
 52        writer.write('<pre class="sxr">')
 53        lines = self.sxr.getElementsByTagName('line')
 54        lineno_template = '%%%ds' % len(`len(lines)`)
 55        for lineno, line in enumerate(lines):
 56            writer.write('<a id="line%d"></a>'%(lineno + 1))
 57            text = lineno_template % (lineno + 1)
 58            writer.write('<span class="lineno">%s</span>'%text)
 59            text = ''.join([n.toxml() for n in line.childNodes])
 60            if text:
 61                writer.write('<span class="line">%s</span>\n'%text)
 62            else:
 63                writer.write('\n')
 64        writer.write('</pre>')
 65
 66
 67class Source(View):
 68    """A module for creating a view for each file with hyperlinked source"""
 69
 70    external_url = Parameter(None, 'base url to use for external links (if None the toc will be used')
 71
 72    def register(self, frame):
 73
 74        super(Source, self).register(frame)
 75        self.icons = {}
 76        if self.processor.sxr_prefix:
 77            share = config.datadir
 78            self.icons['C'] = 'src-c.png'
 79            self.icons['C++'] = 'src-c++.png'
 80            self.icons['Python'] = 'src-py.png'
 81            for l in self.icons:
 82                src = os.path.join(share, self.icons[l])
 83                self.directory_layout.copy_file(src, self.icons[l])
 84
 85
 86    def filename(self):
 87
 88        return self.__filename
 89
 90
 91    def title(self):
 92
 93        return self.__title
 94
 95
 96    def process(self):
 97        """Creates a view for every file"""
 98
 99        self.prefix = self.processor.sxr_prefix
100        if self.prefix is None: return
101
102        # Get the TOC
103        self.__toc = self.processor.toc
104        # create a view for each primary file
105        for file in self.processor.ir.files.values():
106            if file.annotations['primary']:
107                self.process_node(file)
108
109
110    def register_filenames(self):
111        """Registers a view for every source file"""
112
113        if self.processor.sxr_prefix is None: return
114
115        for file in self.processor.ir.files.values():
116            if file.annotations['primary']:
117                filename = file.name
118                filename = self.directory_layout.file_source(filename)
119                self.processor.register_filename(filename, self, file)
120
121
122    def process_node(self, file):
123        """Creates a view for the given file"""
124
125        # Start view
126        filename = file.name
127        self.__filename = self.directory_layout.file_source(filename)
128        self.rel_url = rel(self.filename(), '')
129
130        source = file.name
131        self.__title = source
132
133        self.start_file()
134        self.write_navigation_bar()
135        self.write('File: '+element('b', self.__title))
136
137        sxr = join_paths(self.prefix, source + '.sxr')
138        if os.path.exists(sxr):
139            translator = SXRTranslator(sxr, file.annotations['language'], self.processor.debug)
140            linker = self.external_url and self.external_ref or self.lookup_symbol
141            translator.link(linker)
142            translator.translate(self)
143        self.end_file()
144
145
146    def lookup_symbol(self, name):
147
148        e = self.__toc.lookup(name)
149        return e and self.rel_url + e.link or ''
150
151
152    def external_ref(self, name):
153
154        return self.external_url + urllib.quote(str(name))
155
156    def end_file(self):
157        """Overrides end_file to provide synopsis logo"""
158
159        self.write('\n')
160        now = time.strftime(r'%c', time.localtime(time.time()))
161        logo = img(src=rel(self.filename(), 'synopsis.png'), alt='logo')
162        logo = href('http://synopsis.fresco.org', logo + ' synopsis', target='_blank')
163        logo += ' (version %s)'%config.version
164        self.write(div('logo', 'Generated on ' + now + ' by \n<br/>\n' + logo))
165        View.end_file(self)
166