Mercurial > hg
view hgext/highlight.py @ 6174:434139080ed4
Permit XML entities to be escaped in template output.
Useful for creating XML documents directly from Hg logging. Can also be used for
HTML. For use in content, will escape '&', '<', and for completeness '>'
(although it is not strictly necessary). For use in attributes, will also escape
' and ". Will also replace nonprinting (ASCII) control characters with spaces,
since these are illegal in XML.
author | Jesse Glick <jesse.glick@sun.com> |
---|---|
date | Mon, 28 Jan 2008 22:19:12 -0500 |
parents | 31726c27e40e |
children | 2344da8eb9b4 |
line wrap: on
line source
""" This is Mercurial extension for syntax highlighting in the file revision view of hgweb. It depends on the pygments syntax highlighting library: http://pygments.org/ To enable the extension add this to hgrc: [extensions] hgext.highlight = There is a single configuration option: [web] pygments_style = <style> The default is 'colorful'. If this is changed the corresponding CSS file should be re-generated by running # pygmentize -f html -S <newstyle> -- Adam Hupp <adam@hupp.org> """ from mercurial import demandimport demandimport.ignore.extend(['pkgutil', 'pkg_resources', '__main__',]) import mimetypes from mercurial.hgweb import hgweb_mod from mercurial.hgweb.hgweb_mod import hgweb from mercurial import util from mercurial.hgweb.common import paritygen from mercurial.node import hex from pygments import highlight from pygments.util import ClassNotFound from pygments.lexers import guess_lexer_for_filename, TextLexer from pygments.formatters import HtmlFormatter 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#' # 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)) # 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