##// END OF EJS Templates
highlight: mandatory arguments where possible
Christian Ebert -
r5654:831e34e1 default
parent child Browse files
Show More
@@ -1,147 +1,144 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, rawtext, forcetext=False, stripecount=1,
69 def pygments_format(filename, rawtext, forcetext, stripecount, style):
70 style='colorful'):
71 if not forcetext:
70 if not forcetext:
72 try:
71 try:
73 lexer = guess_lexer_for_filename(filename, rawtext)
72 lexer = guess_lexer_for_filename(filename, rawtext)
74 except ClassNotFound:
73 except ClassNotFound:
75 lexer = TextLexer()
74 lexer = TextLexer()
76 else:
75 else:
77 lexer = TextLexer()
76 lexer = TextLexer()
78
77
79 formatter = StripedHtmlFormatter(stripecount, style=style,
78 formatter = StripedHtmlFormatter(stripecount, style=style,
80 linenos='inline')
79 linenos='inline')
81
80
82 return highlight(rawtext, lexer, formatter)
81 return highlight(rawtext, lexer, formatter)
83
82
84
83
85 def filerevision_pygments(self, tmpl, fctx):
84 def filerevision_pygments(self, tmpl, fctx):
86 """Reimplement hgweb.filerevision to use syntax highlighting"""
85 """Reimplement hgweb.filerevision to use syntax highlighting"""
87 f = fctx.path()
86 f = fctx.path()
88
87
89 rawtext = fctx.data()
88 rawtext = fctx.data()
90 text = rawtext
89 text = rawtext
91
90
92 fl = fctx.filelog()
91 fl = fctx.filelog()
93 n = fctx.filenode()
92 n = fctx.filenode()
94
93
95 mt = mimetypes.guess_type(f)[0]
94 mt = mimetypes.guess_type(f)[0]
96
95
97 if util.binary(text):
96 if util.binary(text):
98 mt = mt or 'application/octet-stream'
97 mt = mt or 'application/octet-stream'
99 text = "(binary:%s)" % mt
98 text = "(binary:%s)" % mt
100
99
101 # don't parse (binary:...) as anything
100 # don't parse (binary:...) as anything
102 forcetext = True
101 forcetext = True
103 else:
102 else:
104 mt = mt or 'text/plain'
103 mt = mt or 'text/plain'
105 forcetext = False
104 forcetext = False
106
105
107 def lines(text):
106 def lines(text):
108 for line in text.splitlines(True):
107 for line in text.splitlines(True):
109 yield {"line": line}
108 yield {"line": line}
110
109
111 style = self.config("web", "pygments_style", "colorful")
110 style = self.config("web", "pygments_style", "colorful")
112
111
113 text_formatted = lines(pygments_format(f, text,
112 text_formatted = lines(pygments_format(f, text, forcetext,
114 forcetext=forcetext,
113 self.stripecount, style))
115 stripecount=self.stripecount,
116 style=style))
117
114
118 # override per-line template
115 # override per-line template
119 tmpl.cache['fileline'] = '#line#'
116 tmpl.cache['fileline'] = '#line#'
120
117
121 # append a <link ...> to the syntax highlighting css
118 # append a <link ...> to the syntax highlighting css
122 old_header = ''.join(tmpl('header'))
119 old_header = ''.join(tmpl('header'))
123 if SYNTAX_CSS not in old_header:
120 if SYNTAX_CSS not in old_header:
124 new_header = old_header + SYNTAX_CSS
121 new_header = old_header + SYNTAX_CSS
125 tmpl.cache['header'] = new_header
122 tmpl.cache['header'] = new_header
126
123
127 yield tmpl("filerevision",
124 yield tmpl("filerevision",
128 file=f,
125 file=f,
129 path=hgweb_mod._up(f), # fixme: make public
126 path=hgweb_mod._up(f), # fixme: make public
130 text=text_formatted,
127 text=text_formatted,
131 raw=rawtext,
128 raw=rawtext,
132 mimetype=mt,
129 mimetype=mt,
133 rev=fctx.rev(),
130 rev=fctx.rev(),
134 node=hex(fctx.node()),
131 node=hex(fctx.node()),
135 author=fctx.user(),
132 author=fctx.user(),
136 date=fctx.date(),
133 date=fctx.date(),
137 desc=fctx.description(),
134 desc=fctx.description(),
138 parent=self.siblings(fctx.parents()),
135 parent=self.siblings(fctx.parents()),
139 child=self.siblings(fctx.children()),
136 child=self.siblings(fctx.children()),
140 rename=self.renamelink(fl, n),
137 rename=self.renamelink(fl, n),
141 permissions=fctx.manifest().flags(f))
138 permissions=fctx.manifest().flags(f))
142
139
143
140
144 # monkeypatch in the new version
141 # monkeypatch in the new version
145 # should be safer than overriding the method in a derived class
142 # should be safer than overriding the method in a derived class
146 # and then patching the class
143 # and then patching the class
147 hgweb.filerevision = filerevision_pygments
144 hgweb.filerevision = filerevision_pygments
General Comments 0
You need to be logged in to leave comments. Login now