Synopsis - Synopsis/SXRServer.py

File: Synopsis/SXRServer.py

      1#
      2# Copyright (C) 2006 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 IR
      9import os, fnmatch
     10
     11def escape(text):
     12    """escape special characters ('&', '\"', '<', '>')"""
     13
     14    text = text.replace('&', '&amp;')
     15    text = text.replace('"', '&quot;')
     16    text = text.replace('<', '&lt;')
     17    text = text.replace('>', '&gt;')
     18    return text
     19
     20default_template = """
     21<html>
     22  <head><title>Synopsis Cross-Reference</title></head>
     23  <body>
     24    <h1>Synopsis Cross-Reference</h1>
     25    @CONTENT@
     26  </body>
     27</html>
     28"""
     29
     30file_search_form = """
     31<table class=\"form\">
     32  <tr>
     33    <td>Enter a file name to search:</td>
     34    <td>
     35      <form method=\"get\" action=\"%(script)s/file\">
     36        <input type="text" name="string" value="" size="15"/>
     37        <input type="submit" value="Find"/>
     38      </form>
     39    </td>
     40  </tr>
     41</table>
     42"""
     43
     44ident_search_form = """
     45<table class=\"form\">
     46  <tr>
     47    <td>Enter a variable, type, or function name to search:</td>
     48    <td>
     49      <form method=\"get\" action=\"%(script)s/ident\">
     50        <input type="text" name="string" value="" size="15"/>
     51        <input type="submit" value="Find"/>
     52      </form>
     53    </td>
     54  </tr>
     55</table>
     56"""
     57
     58class SXRServer:
     59
     60    def __init__(self, root, cgi_url, src_url,
     61                 template_file = None,
     62                 sxr_prefix='/sxr'):
     63
     64        self.cgi_url = cgi_url
     65        self.src_url = src_url
     66        self.src_dir = os.path.join(root, 'Source')
     67        ir = IR.load(os.path.join(root, 'sxr.syn'))
     68        self.data = ir.sxr
     69        self.index = ir.sxr.index()
     70
     71        if template_file:
     72            template = open(template_file).read()
     73        else:
     74            template = default_template
     75        self.template = template.split("@CONTENT@")
     76
     77
     78    def ident_ref(self, file, line, scope):
     79
     80        if len(scope):
     81           text = '::'.join(scope)
     82        else:
     83           text = '<global scope>'
     84        return '<a href=\"%s/Source/%s.html#%s\">%s:%s: %s</a>'%(self.src_url, file, line, file, line, escape(text))
     85
     86
     87    def file_ref(self, file, name = None):
     88
     89        if not name: name = file
     90        name = name[:-5] # strip of trailing '.html'
     91        return "<a href=\"%s/Source/%s\">%s</a>"%(self.src_url, file, name)
     92
     93
     94    def list_refs(self, data, name):
     95
     96        html = ''
     97        if not data.has_key(name): return '\n'
     98        html += '<h3>%s</h3>\n'%escape('::'.join(name))
     99        entry = data[name]
    100        if entry.definitions:
    101            html += '<li>Defined at:<br/>\n'
    102            html += '<ul>\n'
    103            for file, line, scope in entry.definitions:
    104                html +=  '<li>%s</li>\n'%(self.ident_ref(file, line, scope))
    105            html += '</ul></li>\n'
    106        if entry.calls:
    107            html += '<li>Called from:<br/>\n'
    108            html += '<ul>\n'
    109            for file, line, scope in entry.calls:
    110                html += '<li>%s</li>\n'%(self.ident_ref(file, line, scope))
    111            html += '</ul></li>\n'
    112        if entry.references:
    113            html += '<li>Referenced from:<br/>\n'
    114            html += '<ul>\n'
    115            for file, line, scope in entry.references:
    116                html += '<li>%s</li>\n'%(self.ident_ref(file, line, scope))
    117            html += '</ul></li>\n'
    118        return html
    119
    120
    121    def search_file(self, pattern):
    122        """Generate a file search listing."""
    123
    124        html = self.template[0]
    125        html += file_search_form%{'script': self.cgi_url}
    126
    127        base_path_len = len(self.src_dir)
    128        def find(result, base, files):
    129
    130           result.extend([os.path.join(base[base_path_len + 1:], file)
    131                          for file in files
    132                          if os.path.isfile(os.path.join(base, file)) and
    133                          fnmatch.fnmatch(os.path.splitext(file)[0], pattern)])
    134
    135        result = []
    136        os.path.walk(self.src_dir, find, result)
    137        if result:
    138            html += '<ul>\n'
    139            for f in result:
    140                html += '<li>%s</li>\n'%(self.file_ref(f.strip()))
    141            html += '</ul>\n'
    142        html += self.template[1]
    143
    144        return html
    145
    146
    147    def search_ident(self, name, qualified = False):
    148        """Generate an identifier listing."""
    149
    150        html = self.template[0]
    151        html += ident_search_form%{'script' : self.cgi_url}
    152
    153        if qualified:
    154            if '::' in name:
    155                name = tuple(name.split('::'))
    156            else:
    157                name = tuple(name.split('.'))
    158            found = False
    159            # Check for exact match
    160            if self.data.has_key(name):
    161                html += 'Found exact match:<br/>\n'
    162                html += self.list_refs(self.data, name)
    163                found = True
    164            # Search for last part of name in index
    165            if self.index.has_key(name[-1]):
    166                matches = self.index[name[-1]]
    167                html += 'Found (%d) possible matches:<br/>\n'%(len(matches))
    168                html += '<ul>\n'
    169                for name in matches:
    170                    html += self.list_refs(self.data, name)
    171                html += '</ul>\n'
    172                found = True
    173            if not found:
    174                html += "No matches found<br/>\n"
    175
    176        elif self.index.has_key(name):
    177            matches = self.index[name]
    178            html += 'Found (%d) possible matches:<br/>\n'%(len(matches))
    179            html += '<ul>\n'
    180            for name in matches:
    181                html += self.list_refs(self.data, name)
    182            html += '</ul>\n'
    183        else:
    184            html += 'No matches found<br/>\n'
    185        html += self.template[1]
    186
    187        return html
    188

Generated on Thu Apr 16 16:27:12 2009 by
synopsis (version devel)