highlight: support annotate, and reduce layering violations.
authorBrendan Cully <brendan@kublai.com>
Thu, 28 Feb 2008 21:35:27 -0800
changeset 6193 2344da8eb9b4
parent 6192 cd65a67aff31
child 6194 fe54e7501de1
highlight: support annotate, and reduce layering violations.
hgext/highlight.py
--- a/hgext/highlight.py	Fri Feb 29 02:45:12 2008 +0100
+++ b/hgext/highlight.py	Thu Feb 28 21:35:27 2008 -0800
@@ -38,6 +38,7 @@
 from mercurial import util
 from mercurial.hgweb.common import paritygen
 from mercurial.node import hex
+from mercurial.templatefilters import filters
 
 from pygments import highlight
 from pygments.util import ClassNotFound
@@ -47,93 +48,50 @@
 SYNTAX_CSS = ('\n<link rel="stylesheet" href="#staticurl#highlight.css" '
               'type="text/css" />')
 
-class StripedHtmlFormatter(HtmlFormatter):
-    def __init__(self, stripecount, *args, **kwargs):
-        super(StripedHtmlFormatter, self).__init__(*args, **kwargs)
-        self.stripecount = stripecount
-
-    def wrap(self, source, outfile):
-        yield 0, "<div class='highlight'>"
-        yield 0, "<pre>"
-        parity = paritygen(self.stripecount)
-
-        for n, i in source:
-            if n == 1:
-                i = "<div class='parity%s'>%s</div>" % (parity.next(), i)
-            yield n, i
-
-        yield 0, "</pre>"
-        yield 0, "</div>"
-
-
-def pygments_format(filename, text, forcetext, stripecount, style):
-    if not forcetext:
-        try:
-            lexer = guess_lexer_for_filename(filename, text,
-                                             encoding=util._encoding)
-        except ClassNotFound:
-            lexer = TextLexer(encoding=util._encoding)
-    else:
-        lexer = TextLexer(encoding=util._encoding)
-
-    formatter = StripedHtmlFormatter(stripecount, style=style,
-                                     linenos='inline', encoding=util._encoding)
-
-    return highlight(text, lexer, formatter)
-
-
-def filerevision_pygments(self, tmpl, fctx):
-    """Reimplement hgweb.filerevision to use syntax highlighting"""
-    f = fctx.path()
-    text = fctx.data()
-    fl = fctx.filelog()
-    n = fctx.filenode()
-
-    if util.binary(text):
-        mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
-        text = "(binary:%s)" % mt
-        # don't parse (binary:...) as anything
-        forcetext = True
-    else:
-        # encode to hgweb.encoding for lexers and formatter
-        util._encoding = self.encoding
-        text = util.tolocal(text)
-        forcetext = False
-
-    def lines(text):
-        for line in text.splitlines(True):
-            yield {"line": line}
-
-    style = self.config("web", "pygments_style", "colorful")
-
-    text_formatted = lines(pygments_format(f, text, forcetext,
-                                           self.stripecount, style))
-
-    # override per-line template
-    tmpl.cache['fileline'] = '#line#'
-
+def pygmentize(self, tmpl, fctx, field):
     # append a <link ...> to the syntax highlighting css
     old_header = ''.join(tmpl('header'))
     if SYNTAX_CSS not in old_header:
         new_header =  old_header + SYNTAX_CSS
         tmpl.cache['header'] = new_header
 
-    return tmpl("filerevision",
-               file=f,
-               path=hgweb_mod._up(f), # fixme: make public
-               text=text_formatted,
-               rev=fctx.rev(),
-               node=hex(fctx.node()),
-               author=fctx.user(),
-               date=fctx.date(),
-               desc=fctx.description(),
-               parent=self.siblings(fctx.parents()),
-               child=self.siblings(fctx.children()),
-               rename=self.renamelink(fl, n),
-               permissions=fctx.manifest().flags(f))
+    style = self.config("web", "pygments_style", "colorful")
+    # To get multi-line strings right, we can't format line-by-line
+    text = fctx.data()
+    try:
+        lexer = guess_lexer_for_filename(fctx.path(), text,
+                                         encoding=util._encoding)
+    except ClassNotFound:
+        lexer = TextLexer(encoding=util._encoding)
+
+    formatter = HtmlFormatter(style=style, encoding=util._encoding)
 
+    colorized = highlight(text, lexer, formatter)
+    # strip wrapping div
+    colorized = colorized[:colorized.find('\n</pre>')]
+    colorized = colorized[colorized.find('<span'):]
+    coloriter = (l for l in colorized.splitlines())
+
+    filters['colorize'] = lambda x: coloriter.next()
+
+    oldl = tmpl.cache[field]
+    newl = oldl.replace('line|escape', 'line|colorize')
+    tmpl.cache[field] = newl
+
+def filerevision_highlight(self, tmpl, fctx):
+    pygmentize(self, tmpl, fctx, 'fileline')
+
+    return realrevision(self, tmpl, fctx)
+
+def fileannotate_highlight(self, tmpl, fctx):
+    pygmentize(self, tmpl, fctx, 'annotateline')
+
+    return realannotate(self, tmpl, fctx)
 
 # monkeypatch in the new version
 # should be safer than overriding the method in a derived class
 # and then patching the class
-hgweb.filerevision = filerevision_pygments
+realrevision = hgweb.filerevision
+hgweb.filerevision = filerevision_highlight
+realannotate = hgweb.fileannotate
+hgweb.fileannotate = fileannotate_highlight