Mercurial > hg
comparison hgext/highlight.py @ 6193:2344da8eb9b4
highlight: support annotate, and reduce layering violations.
author | Brendan Cully <brendan@kublai.com> |
---|---|
date | Thu, 28 Feb 2008 21:35:27 -0800 |
parents | 31726c27e40e |
children | fe54e7501de1 |
comparison
equal
deleted
inserted
replaced
6192:cd65a67aff31 | 6193:2344da8eb9b4 |
---|---|
36 from mercurial.hgweb import hgweb_mod | 36 from mercurial.hgweb import hgweb_mod |
37 from mercurial.hgweb.hgweb_mod import hgweb | 37 from mercurial.hgweb.hgweb_mod import hgweb |
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 |
44 from pygments.lexers import guess_lexer_for_filename, TextLexer | 45 from pygments.lexers import guess_lexer_for_filename, TextLexer |
45 from pygments.formatters import HtmlFormatter | 46 from pygments.formatters import HtmlFormatter |
46 | 47 |
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(), | |
130 parent=self.siblings(fctx.parents()), | |
131 child=self.siblings(fctx.children()), | |
132 rename=self.renamelink(fl, n), | |
133 permissions=fctx.manifest().flags(f)) | |
134 | 66 |
67 formatter = HtmlFormatter(style=style, encoding=util._encoding) | |
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 |