comparison hgext/highlight.py @ 5532:40a06e39f010

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