##// END OF EJS Templates
highlight: update according to latest hgweb_mod changes...
Christian Ebert -
r5991:31726c27 default
parent child Browse files
Show More
@@ -1,151 +1,139 b''
1 """
1 """
2 This is Mercurial extension for syntax highlighting in the file
2 This is Mercurial extension for syntax highlighting in the file
3 revision view of hgweb.
3 revision view of hgweb.
4
4
5 It depends on the pygments syntax highlighting library:
5 It depends on the pygments syntax highlighting library:
6 http://pygments.org/
6 http://pygments.org/
7
7
8 To enable the extension add this to hgrc:
8 To enable the extension add this to hgrc:
9
9
10 [extensions]
10 [extensions]
11 hgext.highlight =
11 hgext.highlight =
12
12
13 There is a single configuration option:
13 There is a single configuration option:
14
14
15 [web]
15 [web]
16 pygments_style = <style>
16 pygments_style = <style>
17
17
18 The default is 'colorful'. If this is changed the corresponding CSS
18 The default is 'colorful'. If this is changed the corresponding CSS
19 file should be re-generated by running
19 file should be re-generated by running
20
20
21 # pygmentize -f html -S <newstyle>
21 # pygmentize -f html -S <newstyle>
22
22
23
23
24 -- Adam Hupp <adam@hupp.org>
24 -- Adam Hupp <adam@hupp.org>
25
25
26
26
27 """
27 """
28
28
29 from mercurial import demandimport
29 from mercurial import demandimport
30 demandimport.ignore.extend(['pkgutil',
30 demandimport.ignore.extend(['pkgutil',
31 'pkg_resources',
31 'pkg_resources',
32 '__main__',])
32 '__main__',])
33
33
34 import mimetypes
34 import mimetypes
35
35
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
41
42 from pygments import highlight
42 from pygments import highlight
43 from pygments.util import ClassNotFound
43 from pygments.util import ClassNotFound
44 from pygments.lexers import guess_lexer_for_filename, TextLexer
44 from pygments.lexers import guess_lexer_for_filename, TextLexer
45 from pygments.formatters import HtmlFormatter
45 from pygments.formatters import HtmlFormatter
46
46
47 SYNTAX_CSS = ('\n<link rel="stylesheet" href="#staticurl#highlight.css" '
47 SYNTAX_CSS = ('\n<link rel="stylesheet" href="#staticurl#highlight.css" '
48 'type="text/css" />')
48 'type="text/css" />')
49
49
50 class StripedHtmlFormatter(HtmlFormatter):
50 class StripedHtmlFormatter(HtmlFormatter):
51 def __init__(self, stripecount, *args, **kwargs):
51 def __init__(self, stripecount, *args, **kwargs):
52 super(StripedHtmlFormatter, self).__init__(*args, **kwargs)
52 super(StripedHtmlFormatter, self).__init__(*args, **kwargs)
53 self.stripecount = stripecount
53 self.stripecount = stripecount
54
54
55 def wrap(self, source, outfile):
55 def wrap(self, source, outfile):
56 yield 0, "<div class='highlight'>"
56 yield 0, "<div class='highlight'>"
57 yield 0, "<pre>"
57 yield 0, "<pre>"
58 parity = paritygen(self.stripecount)
58 parity = paritygen(self.stripecount)
59
59
60 for n, i in source:
60 for n, i in source:
61 if n == 1:
61 if n == 1:
62 i = "<div class='parity%s'>%s</div>" % (parity.next(), i)
62 i = "<div class='parity%s'>%s</div>" % (parity.next(), i)
63 yield n, i
63 yield n, i
64
64
65 yield 0, "</pre>"
65 yield 0, "</pre>"
66 yield 0, "</div>"
66 yield 0, "</div>"
67
67
68
68
69 def pygments_format(filename, text, forcetext, stripecount, style):
69 def pygments_format(filename, text, forcetext, stripecount, style):
70 if not forcetext:
70 if not forcetext:
71 try:
71 try:
72 lexer = guess_lexer_for_filename(filename, text,
72 lexer = guess_lexer_for_filename(filename, text,
73 encoding=util._encoding)
73 encoding=util._encoding)
74 except ClassNotFound:
74 except ClassNotFound:
75 lexer = TextLexer(encoding=util._encoding)
75 lexer = TextLexer(encoding=util._encoding)
76 else:
76 else:
77 lexer = TextLexer(encoding=util._encoding)
77 lexer = TextLexer(encoding=util._encoding)
78
78
79 formatter = StripedHtmlFormatter(stripecount, style=style,
79 formatter = StripedHtmlFormatter(stripecount, style=style,
80 linenos='inline', encoding=util._encoding)
80 linenos='inline', encoding=util._encoding)
81
81
82 return highlight(text, lexer, formatter)
82 return highlight(text, lexer, formatter)
83
83
84
84
85 def filerevision_pygments(self, tmpl, fctx):
85 def filerevision_pygments(self, tmpl, fctx):
86 """Reimplement hgweb.filerevision to use syntax highlighting"""
86 """Reimplement hgweb.filerevision to use syntax highlighting"""
87 f = fctx.path()
87 f = fctx.path()
88
88 text = fctx.data()
89 rawtext = fctx.data()
90 text = rawtext
91
92 fl = fctx.filelog()
89 fl = fctx.filelog()
93 n = fctx.filenode()
90 n = fctx.filenode()
94
91
95 mt = mimetypes.guess_type(f)[0]
96
97 # we always want hgweb.encoding
98 util._encoding = self.encoding
99
100 if util.binary(text):
92 if util.binary(text):
101 mt = mt or 'application/octet-stream'
93 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
102 text = "(binary:%s)" % mt
94 text = "(binary:%s)" % mt
103
104 # don't parse (binary:...) as anything
95 # don't parse (binary:...) as anything
105 forcetext = True
96 forcetext = True
106 else:
97 else:
107 mt = mt or 'text/plain'
108
109 # encode to hgweb.encoding for lexers and formatter
98 # encode to hgweb.encoding for lexers and formatter
99 util._encoding = self.encoding
110 text = util.tolocal(text)
100 text = util.tolocal(text)
111 forcetext = False
101 forcetext = False
112
102
113 def lines(text):
103 def lines(text):
114 for line in text.splitlines(True):
104 for line in text.splitlines(True):
115 yield {"line": line}
105 yield {"line": line}
116
106
117 style = self.config("web", "pygments_style", "colorful")
107 style = self.config("web", "pygments_style", "colorful")
118
108
119 text_formatted = lines(pygments_format(f, text, forcetext,
109 text_formatted = lines(pygments_format(f, text, forcetext,
120 self.stripecount, style))
110 self.stripecount, style))
121
111
122 # override per-line template
112 # override per-line template
123 tmpl.cache['fileline'] = '#line#'
113 tmpl.cache['fileline'] = '#line#'
124
114
125 # append a <link ...> to the syntax highlighting css
115 # append a <link ...> to the syntax highlighting css
126 old_header = ''.join(tmpl('header'))
116 old_header = ''.join(tmpl('header'))
127 if SYNTAX_CSS not in old_header:
117 if SYNTAX_CSS not in old_header:
128 new_header = old_header + SYNTAX_CSS
118 new_header = old_header + SYNTAX_CSS
129 tmpl.cache['header'] = new_header
119 tmpl.cache['header'] = new_header
130
120
131 yield tmpl("filerevision",
121 return tmpl("filerevision",
132 file=f,
122 file=f,
133 path=hgweb_mod._up(f), # fixme: make public
123 path=hgweb_mod._up(f), # fixme: make public
134 text=text_formatted,
124 text=text_formatted,
135 raw=rawtext,
136 mimetype=mt,
137 rev=fctx.rev(),
125 rev=fctx.rev(),
138 node=hex(fctx.node()),
126 node=hex(fctx.node()),
139 author=fctx.user(),
127 author=fctx.user(),
140 date=fctx.date(),
128 date=fctx.date(),
141 desc=fctx.description(),
129 desc=fctx.description(),
142 parent=self.siblings(fctx.parents()),
130 parent=self.siblings(fctx.parents()),
143 child=self.siblings(fctx.children()),
131 child=self.siblings(fctx.children()),
144 rename=self.renamelink(fl, n),
132 rename=self.renamelink(fl, n),
145 permissions=fctx.manifest().flags(f))
133 permissions=fctx.manifest().flags(f))
146
134
147
135
148 # monkeypatch in the new version
136 # monkeypatch in the new version
149 # should be safer than overriding the method in a derived class
137 # should be safer than overriding the method in a derived class
150 # and then patching the class
138 # and then patching the class
151 hgweb.filerevision = filerevision_pygments
139 hgweb.filerevision = filerevision_pygments
General Comments 0
You need to be logged in to leave comments. Login now