##// END OF EJS Templates
highlight: support annotate, and reduce layering violations.
Brendan Cully -
r6193:2344da8e default
parent child Browse files
Show More
@@ -38,6 +38,7 b' from mercurial.hgweb.hgweb_mod import hg'
38 from mercurial import util
38 from mercurial import util
39 from mercurial.hgweb.common import paritygen
39 from mercurial.hgweb.common import paritygen
40 from mercurial.node import hex
40 from mercurial.node import hex
41 from mercurial.templatefilters import filters
41
42
42 from pygments import highlight
43 from pygments import highlight
43 from pygments.util import ClassNotFound
44 from pygments.util import ClassNotFound
@@ -47,93 +48,50 b' from pygments.formatters import HtmlForm'
47 SYNTAX_CSS = ('\n<link rel="stylesheet" href="#staticurl#highlight.css" '
48 SYNTAX_CSS = ('\n<link rel="stylesheet" href="#staticurl#highlight.css" '
48 'type="text/css" />')
49 'type="text/css" />')
49
50
50 class StripedHtmlFormatter(HtmlFormatter):
51 def pygmentize(self, tmpl, fctx, field):
51 def __init__(self, stripecount, *args, **kwargs):
52 super(StripedHtmlFormatter, self).__init__(*args, **kwargs)
53 self.stripecount = stripecount
54
55 def wrap(self, source, outfile):
56 yield 0, "<div class='highlight'>"
57 yield 0, "<pre>"
58 parity = paritygen(self.stripecount)
59
60 for n, i in source:
61 if n == 1:
62 i = "<div class='parity%s'>%s</div>" % (parity.next(), i)
63 yield n, i
64
65 yield 0, "</pre>"
66 yield 0, "</div>"
67
68
69 def pygments_format(filename, text, forcetext, stripecount, style):
70 if not forcetext:
71 try:
72 lexer = guess_lexer_for_filename(filename, text,
73 encoding=util._encoding)
74 except ClassNotFound:
75 lexer = TextLexer(encoding=util._encoding)
76 else:
77 lexer = TextLexer(encoding=util._encoding)
78
79 formatter = StripedHtmlFormatter(stripecount, style=style,
80 linenos='inline', encoding=util._encoding)
81
82 return highlight(text, lexer, formatter)
83
84
85 def filerevision_pygments(self, tmpl, fctx):
86 """Reimplement hgweb.filerevision to use syntax highlighting"""
87 f = fctx.path()
88 text = fctx.data()
89 fl = fctx.filelog()
90 n = fctx.filenode()
91
92 if util.binary(text):
93 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
94 text = "(binary:%s)" % mt
95 # don't parse (binary:...) as anything
96 forcetext = True
97 else:
98 # encode to hgweb.encoding for lexers and formatter
99 util._encoding = self.encoding
100 text = util.tolocal(text)
101 forcetext = False
102
103 def lines(text):
104 for line in text.splitlines(True):
105 yield {"line": line}
106
107 style = self.config("web", "pygments_style", "colorful")
108
109 text_formatted = lines(pygments_format(f, text, forcetext,
110 self.stripecount, style))
111
112 # override per-line template
113 tmpl.cache['fileline'] = '#line#'
114
115 # append a <link ...> to the syntax highlighting css
52 # append a <link ...> to the syntax highlighting css
116 old_header = ''.join(tmpl('header'))
53 old_header = ''.join(tmpl('header'))
117 if SYNTAX_CSS not in old_header:
54 if SYNTAX_CSS not in old_header:
118 new_header = old_header + SYNTAX_CSS
55 new_header = old_header + SYNTAX_CSS
119 tmpl.cache['header'] = new_header
56 tmpl.cache['header'] = new_header
120
57
121 return tmpl("filerevision",
58 style = self.config("web", "pygments_style", "colorful")
122 file=f,
59 # To get multi-line strings right, we can't format line-by-line
123 path=hgweb_mod._up(f), # fixme: make public
60 text = fctx.data()
124 text=text_formatted,
61 try:
125 rev=fctx.rev(),
62 lexer = guess_lexer_for_filename(fctx.path(), text,
126 node=hex(fctx.node()),
63 encoding=util._encoding)
127 author=fctx.user(),
64 except ClassNotFound:
128 date=fctx.date(),
65 lexer = TextLexer(encoding=util._encoding)
129 desc=fctx.description(),
66
130 parent=self.siblings(fctx.parents()),
67 formatter = HtmlFormatter(style=style, encoding=util._encoding)
131 child=self.siblings(fctx.children()),
132 rename=self.renamelink(fl, n),
133 permissions=fctx.manifest().flags(f))
134
68
69 colorized = highlight(text, lexer, formatter)
70 # strip wrapping div
71 colorized = colorized[:colorized.find('\n</pre>')]
72 colorized = colorized[colorized.find('<span'):]
73 coloriter = (l for l in colorized.splitlines())
74
75 filters['colorize'] = lambda x: coloriter.next()
76
77 oldl = tmpl.cache[field]
78 newl = oldl.replace('line|escape', 'line|colorize')
79 tmpl.cache[field] = newl
80
81 def filerevision_highlight(self, tmpl, fctx):
82 pygmentize(self, tmpl, fctx, 'fileline')
83
84 return realrevision(self, tmpl, fctx)
85
86 def fileannotate_highlight(self, tmpl, fctx):
87 pygmentize(self, tmpl, fctx, 'annotateline')
88
89 return realannotate(self, tmpl, fctx)
135
90
136 # monkeypatch in the new version
91 # monkeypatch in the new version
137 # should be safer than overriding the method in a derived class
92 # should be safer than overriding the method in a derived class
138 # and then patching the class
93 # and then patching the class
139 hgweb.filerevision = filerevision_pygments
94 realrevision = hgweb.filerevision
95 hgweb.filerevision = filerevision_highlight
96 realannotate = hgweb.fileannotate
97 hgweb.fileannotate = fileannotate_highlight
General Comments 0
You need to be logged in to leave comments. Login now