mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 00:14:35 +03:00
7241bd8d3a
This is needed in case util._encoding and hgweb.encoding conflict. Extreme example: HGENCODING=UTF-8 [web] encoding = ascii Note: display of files whose encoding differs from HGENCODING or hgweb.encoding behaves not exactly the same way as with highlight turned off as replacement chars are either converted or replaced.
152 lines
4.2 KiB
Python
152 lines
4.2 KiB
Python
"""
|
|
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()
|
|
|
|
rawtext = fctx.data()
|
|
text = rawtext
|
|
|
|
fl = fctx.filelog()
|
|
n = fctx.filenode()
|
|
|
|
mt = mimetypes.guess_type(f)[0]
|
|
|
|
# we always want hgweb.encoding
|
|
util._encoding = self.encoding
|
|
|
|
if util.binary(text):
|
|
mt = mt or 'application/octet-stream'
|
|
text = "(binary:%s)" % mt
|
|
|
|
# don't parse (binary:...) as anything
|
|
forcetext = True
|
|
else:
|
|
mt = mt or 'text/plain'
|
|
|
|
# encode to hgweb.encoding for lexers and formatter
|
|
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
|
|
|
|
yield tmpl("filerevision",
|
|
file=f,
|
|
path=hgweb_mod._up(f), # fixme: make public
|
|
text=text_formatted,
|
|
raw=rawtext,
|
|
mimetype=mt,
|
|
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
|