"""A Trac syntax highlighting module for Lisp. """ from __future__ import generators import sys import re from trac.core import * from trac.mimeview.api import IHTMLPreviewRenderer from trac.web.chrome import add_stylesheet from xmlrpclib import * __all__ = ['LispRenderer'] types = [ 'text/x-lisp' ] COLORIZER_URL = "http://localhost:8080/RPC2" CACHE_SIZE = 50 class LRUCache: """ Implementation of a length-limited O(1) LRU queue. Built for and used by PyPE: http://pype.sourceforge.net Copyright 2003 Josiah Carlson. From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252524 """ class Node: def __init__(self, prev, me): self.prev = prev self.me = me self.next = None def __init__(self, count, pairs=[]): self.count = max(count, 1) self.d = {} self.first = None self.last = None for key, value in pairs: self[key] = value def __contains__(self, obj): return obj in self.d def __getitem__(self, obj): a = self.d[obj].me self[a[0]] = a[1] return a[1] def __setitem__(self, obj, val): if obj in self.d: del self[obj] nobj = self.Node(self.last, (obj, val)) if self.first is None: self.first = nobj if self.last: self.last.next = nobj self.last = nobj self.d[obj] = nobj if len(self.d) > self.count: if self.first == self.last: self.first = None self.last = None return a = self.first a.next.prev = None self.first = a.next a.next = None del self.d[a.me[0]] del a def __delitem__(self, obj): nobj = self.d[obj] if nobj.prev: nobj.prev.next = nobj.next else: self.first = nobj.next if nobj.next: nobj.next.prev = nobj.prev else: self.last = nobj.prev del self.d[obj] def __iter__(self): cur = self.first while cur != None: cur2 = cur.next yield cur.me[1] cur = cur2 def iteritems(self): cur = self.first while cur != None: cur2 = cur.next yield cur.me cur = cur2 def iterkeys(self): return iter(self.d) def itervalues(self): for i,j in self.iteritems(): yield j def keys(self): return self.d.keys() def testCache(): cache = LRUCache(3) cache[0] = True cache[1] = True cache[2] = True print 0 in cache print 1 in cache print 2 in cache print not (3 in cache) print cache[0] print cache[1] print cache[2] cache[3] = True print not (0 in cache) class LispRenderer(Component): """Syntax highlighting for Lisp.""" implements(IHTMLPreviewRenderer) cache = LRUCache(CACHE_SIZE) cache_hits = 0 cache_misses = 0 def get_quality_ratio(self, mimetype): #sys.stderr.write("Considering %s\n" % (mimetype,)) if mimetype in types: #sys.stderr.write("It's lisp!\n") return 4 return 0 def render(self, req, mimetype, content, filename=None, rev=None): #sys.stderr.write("Rendering lisp\n") cache_key = content try: add_stylesheet(req, 'common/css/lisp.css') if not (cache_key in self.cache): colorizer = ServerProxy(COLORIZER_URL) html = colorizer.colorize("lisp", content, 0) html = html.replace("\n", "") html = html.replace("
", "\n") html = html.splitlines() self.cache[cache_key] = html self.cache_misses = self.cache_misses + 1 sys.stderr.write("Lisp rendering cache hits: %s misses: %s\n" % (self.cache_hits, self.cache_misses)) return html else: self.cache_hits = self.cache_hits + 1 html = self.cache[cache_key] sys.stderr.write("Lisp rendering cache hits: %s misses: %s\n" % (self.cache_hits, self.cache_misses)) return html except Exception, e: sys.stderr.write("Got exception: %s" % (e,)) raise e