##// END OF EJS Templates
highlight: split code to improve startup times
Patrick Mezard -
r6938:ce94b323 default
parent child Browse files
Show More
@@ -0,0 +1,50 b''
1 """a mercurial extension for syntax highlighting in hgweb
2
3 It depends on the pygments syntax highlighting library:
4 http://pygments.org/
5
6 To enable the extension add this to hgrc:
7
8 [extensions]
9 hgext.highlight =
10
11 There is a single configuration option:
12
13 [web]
14 pygments_style = <style>
15
16 The default is 'colorful'.
17
18 -- Adam Hupp <adam@hupp.org>
19 """
20
21 import highlight
22 from mercurial.hgweb import webcommands, webutil, common
23
24 web_filerevision = webcommands._filerevision
25 web_annotate = webcommands.annotate
26
27 def filerevision_highlight(web, tmpl, fctx):
28 style = web.config('web', 'pygments_style', 'colorful')
29 highlight.pygmentize('fileline', fctx, style, tmpl)
30 return web_filerevision(web, tmpl, fctx)
31
32 def annotate_highlight(web, req, tmpl):
33 fctx = webutil.filectx(web.repo, req)
34 style = web.config('web', 'pygments_style', 'colorful')
35 highlight.pygmentize('annotateline', fctx, style, tmpl)
36 return web_annotate(web, req, tmpl)
37
38 def generate_css(web, req, tmpl):
39 pg_style = web.config('web', 'pygments_style', 'colorful')
40 fmter = highlight.HtmlFormatter(style = pg_style)
41 req.respond(common.HTTP_OK, 'text/css')
42 return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
43
44
45 # monkeypatch in the new version
46
47 webcommands._filerevision = filerevision_highlight
48 webcommands.annotate = annotate_highlight
49 webcommands.highlightcss = generate_css
50 webcommands.__all__.append('highlightcss')
@@ -1,98 +1,54 b''
1 """a mercurial extension for syntax highlighting in hgweb
1 # highlight extension implementation file
2
2 #
3 It depends on the pygments syntax highlighting library:
3 # The original module was split in an interface and an implementation
4 http://pygments.org/
4 # file to defer pygments loading and speedup extension setup.
5
6 To enable the extension add this to hgrc:
7
8 [extensions]
9 hgext.highlight =
10
11 There is a single configuration option:
12
13 [web]
14 pygments_style = <style>
15
16 The default is 'colorful'.
17
18 -- Adam Hupp <adam@hupp.org>
19 """
20
5
21 from mercurial import demandimport
6 from mercurial import demandimport
22 demandimport.ignore.extend(['pkgutil', 'pkg_resources', '__main__',])
7 demandimport.ignore.extend(['pkgutil', 'pkg_resources', '__main__',])
23
8
24 from mercurial.hgweb import webcommands, webutil, common
25 from mercurial import util
9 from mercurial import util
26 from mercurial.templatefilters import filters
10 from mercurial.templatefilters import filters
27
11
28 from pygments import highlight
12 from pygments import highlight
29 from pygments.util import ClassNotFound
13 from pygments.util import ClassNotFound
30 from pygments.lexers import guess_lexer, guess_lexer_for_filename, TextLexer
14 from pygments.lexers import guess_lexer, guess_lexer_for_filename, TextLexer
31 from pygments.formatters import HtmlFormatter
15 from pygments.formatters import HtmlFormatter
32
16
33 SYNTAX_CSS = ('\n<link rel="stylesheet" href="{url}highlightcss" '
17 SYNTAX_CSS = ('\n<link rel="stylesheet" href="{url}highlightcss" '
34 'type="text/css" />')
18 'type="text/css" />')
35
19
36 def pygmentize(field, fctx, style, tmpl):
20 def pygmentize(field, fctx, style, tmpl):
37
21
38 # append a <link ...> to the syntax highlighting css
22 # append a <link ...> to the syntax highlighting css
39 old_header = ''.join(tmpl('header'))
23 old_header = ''.join(tmpl('header'))
40 if SYNTAX_CSS not in old_header:
24 if SYNTAX_CSS not in old_header:
41 new_header = old_header + SYNTAX_CSS
25 new_header = old_header + SYNTAX_CSS
42 tmpl.cache['header'] = new_header
26 tmpl.cache['header'] = new_header
43
27
44 text = fctx.data()
28 text = fctx.data()
45 if util.binary(text):
29 if util.binary(text):
46 return
30 return
47
31
48 # To get multi-line strings right, we can't format line-by-line
32 # To get multi-line strings right, we can't format line-by-line
49 try:
33 try:
50 lexer = guess_lexer_for_filename(fctx.path(), text[:1024],
34 lexer = guess_lexer_for_filename(fctx.path(), text[:1024],
51 encoding=util._encoding)
35 encoding=util._encoding)
52 except (ClassNotFound, ValueError):
36 except (ClassNotFound, ValueError):
53 try:
37 try:
54 lexer = guess_lexer(text[:1024], encoding=util._encoding)
38 lexer = guess_lexer(text[:1024], encoding=util._encoding)
55 except (ClassNotFound, ValueError):
39 except (ClassNotFound, ValueError):
56 lexer = TextLexer(encoding=util._encoding)
40 lexer = TextLexer(encoding=util._encoding)
57
41
58 formatter = HtmlFormatter(style=style, encoding=util._encoding)
42 formatter = HtmlFormatter(style=style, encoding=util._encoding)
59
43
60 colorized = highlight(text, lexer, formatter)
44 colorized = highlight(text, lexer, formatter)
61 # strip wrapping div
45 # strip wrapping div
62 colorized = colorized[:colorized.find('\n</pre>')]
46 colorized = colorized[:colorized.find('\n</pre>')]
63 colorized = colorized[colorized.find('<pre>')+5:]
47 colorized = colorized[colorized.find('<pre>')+5:]
64 coloriter = iter(colorized.splitlines())
48 coloriter = iter(colorized.splitlines())
65
49
66 filters['colorize'] = lambda x: coloriter.next()
50 filters['colorize'] = lambda x: coloriter.next()
67
51
68 oldl = tmpl.cache[field]
52 oldl = tmpl.cache[field]
69 newl = oldl.replace('line|escape', 'line|colorize')
53 newl = oldl.replace('line|escape', 'line|colorize')
70 tmpl.cache[field] = newl
54 tmpl.cache[field] = newl
71
72 web_filerevision = webcommands._filerevision
73 web_annotate = webcommands.annotate
74
75 def filerevision_highlight(web, tmpl, fctx):
76 style = web.config('web', 'pygments_style', 'colorful')
77 pygmentize('fileline', fctx, style, tmpl)
78 return web_filerevision(web, tmpl, fctx)
79
80 def annotate_highlight(web, req, tmpl):
81 fctx = webutil.filectx(web.repo, req)
82 style = web.config('web', 'pygments_style', 'colorful')
83 pygmentize('annotateline', fctx, style, tmpl)
84 return web_annotate(web, req, tmpl)
85
86 def generate_css(web, req, tmpl):
87 pg_style = web.config('web', 'pygments_style', 'colorful')
88 fmter = HtmlFormatter(style = pg_style)
89 req.respond(common.HTTP_OK, 'text/css')
90 return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
91
92
93 # monkeypatch in the new version
94
95 webcommands._filerevision = filerevision_highlight
96 webcommands.annotate = annotate_highlight
97 webcommands.highlightcss = generate_css
98 webcommands.__all__.append('highlightcss')
@@ -1,137 +1,138 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # This is the mercurial setup script.
3 # This is the mercurial setup script.
4 #
4 #
5 # 'python setup.py install', or
5 # 'python setup.py install', or
6 # 'python setup.py --help' for more options
6 # 'python setup.py --help' for more options
7
7
8 import sys
8 import sys
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
10 raise SystemExit, "Mercurial requires python 2.3 or later."
10 raise SystemExit, "Mercurial requires python 2.3 or later."
11
11
12 import os
12 import os
13 import shutil
13 import shutil
14 import tempfile
14 import tempfile
15 from distutils.core import setup, Extension
15 from distutils.core import setup, Extension
16 from distutils.command.install_data import install_data
16 from distutils.command.install_data import install_data
17 from distutils.ccompiler import new_compiler
17 from distutils.ccompiler import new_compiler
18
18
19 import mercurial.version
19 import mercurial.version
20
20
21 extra = {}
21 extra = {}
22 scripts = ['hg']
22 scripts = ['hg']
23 if os.name == 'nt':
23 if os.name == 'nt':
24 scripts.append('contrib/win32/hg.bat')
24 scripts.append('contrib/win32/hg.bat')
25
25
26 # simplified version of distutils.ccompiler.CCompiler.has_function
26 # simplified version of distutils.ccompiler.CCompiler.has_function
27 # that actually removes its temporary files.
27 # that actually removes its temporary files.
28 def has_function(cc, funcname):
28 def has_function(cc, funcname):
29 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
29 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
30 devnull = oldstderr = None
30 devnull = oldstderr = None
31 try:
31 try:
32 try:
32 try:
33 fname = os.path.join(tmpdir, 'funcname.c')
33 fname = os.path.join(tmpdir, 'funcname.c')
34 f = open(fname, 'w')
34 f = open(fname, 'w')
35 f.write('int main(void) {\n')
35 f.write('int main(void) {\n')
36 f.write(' %s();\n' % funcname)
36 f.write(' %s();\n' % funcname)
37 f.write('}\n')
37 f.write('}\n')
38 f.close()
38 f.close()
39 # Redirect stderr to /dev/null to hide any error messages
39 # Redirect stderr to /dev/null to hide any error messages
40 # from the compiler.
40 # from the compiler.
41 # This will have to be changed if we ever have to check
41 # This will have to be changed if we ever have to check
42 # for a function on Windows.
42 # for a function on Windows.
43 devnull = open('/dev/null', 'w')
43 devnull = open('/dev/null', 'w')
44 oldstderr = os.dup(sys.stderr.fileno())
44 oldstderr = os.dup(sys.stderr.fileno())
45 os.dup2(devnull.fileno(), sys.stderr.fileno())
45 os.dup2(devnull.fileno(), sys.stderr.fileno())
46 objects = cc.compile([fname])
46 objects = cc.compile([fname])
47 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
47 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
48 except:
48 except:
49 return False
49 return False
50 return True
50 return True
51 finally:
51 finally:
52 if oldstderr is not None:
52 if oldstderr is not None:
53 os.dup2(oldstderr, sys.stderr.fileno())
53 os.dup2(oldstderr, sys.stderr.fileno())
54 if devnull is not None:
54 if devnull is not None:
55 devnull.close()
55 devnull.close()
56 shutil.rmtree(tmpdir)
56 shutil.rmtree(tmpdir)
57
57
58 # py2exe needs to be installed to work
58 # py2exe needs to be installed to work
59 try:
59 try:
60 import py2exe
60 import py2exe
61
61
62 # Help py2exe to find win32com.shell
62 # Help py2exe to find win32com.shell
63 try:
63 try:
64 import modulefinder
64 import modulefinder
65 import win32com
65 import win32com
66 for p in win32com.__path__[1:]: # Take the path to win32comext
66 for p in win32com.__path__[1:]: # Take the path to win32comext
67 modulefinder.AddPackagePath("win32com", p)
67 modulefinder.AddPackagePath("win32com", p)
68 pn = "win32com.shell"
68 pn = "win32com.shell"
69 __import__(pn)
69 __import__(pn)
70 m = sys.modules[pn]
70 m = sys.modules[pn]
71 for p in m.__path__[1:]:
71 for p in m.__path__[1:]:
72 modulefinder.AddPackagePath(pn, p)
72 modulefinder.AddPackagePath(pn, p)
73 except ImportError:
73 except ImportError:
74 pass
74 pass
75
75
76 extra['console'] = ['hg']
76 extra['console'] = ['hg']
77
77
78 except ImportError:
78 except ImportError:
79 pass
79 pass
80
80
81 # specify version string, otherwise 'hg identify' will be used:
81 # specify version string, otherwise 'hg identify' will be used:
82 version = ''
82 version = ''
83
83
84 class install_package_data(install_data):
84 class install_package_data(install_data):
85 def finalize_options(self):
85 def finalize_options(self):
86 self.set_undefined_options('install',
86 self.set_undefined_options('install',
87 ('install_lib', 'install_dir'))
87 ('install_lib', 'install_dir'))
88 install_data.finalize_options(self)
88 install_data.finalize_options(self)
89
89
90 mercurial.version.remember_version(version)
90 mercurial.version.remember_version(version)
91 cmdclass = {'install_data': install_package_data}
91 cmdclass = {'install_data': install_package_data}
92
92
93 ext_modules=[
93 ext_modules=[
94 Extension('mercurial.base85', ['mercurial/base85.c']),
94 Extension('mercurial.base85', ['mercurial/base85.c']),
95 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
95 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
96 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
96 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
97 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
97 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
98 Extension('mercurial.parsers', ['mercurial/parsers.c']),
98 Extension('mercurial.parsers', ['mercurial/parsers.c']),
99 ]
99 ]
100
100
101 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert']
101 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
102 'hgext.highlight']
102
103
103 try:
104 try:
104 import posix
105 import posix
105 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
106 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
106
107
107 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
108 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
108 # The inotify extension is only usable with Linux 2.6 kernels.
109 # The inotify extension is only usable with Linux 2.6 kernels.
109 # You also need a reasonably recent C library.
110 # You also need a reasonably recent C library.
110 cc = new_compiler()
111 cc = new_compiler()
111 if has_function(cc, 'inotify_add_watch'):
112 if has_function(cc, 'inotify_add_watch'):
112 ext_modules.append(Extension('hgext.inotify.linux._inotify',
113 ext_modules.append(Extension('hgext.inotify.linux._inotify',
113 ['hgext/inotify/linux/_inotify.c']))
114 ['hgext/inotify/linux/_inotify.c']))
114 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
115 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
115 except ImportError:
116 except ImportError:
116 pass
117 pass
117
118
118 setup(name='mercurial',
119 setup(name='mercurial',
119 version=mercurial.version.get_version(),
120 version=mercurial.version.get_version(),
120 author='Matt Mackall',
121 author='Matt Mackall',
121 author_email='mpm@selenic.com',
122 author_email='mpm@selenic.com',
122 url='http://selenic.com/mercurial',
123 url='http://selenic.com/mercurial',
123 description='Scalable distributed SCM',
124 description='Scalable distributed SCM',
124 license='GNU GPL',
125 license='GNU GPL',
125 scripts=scripts,
126 scripts=scripts,
126 packages=packages,
127 packages=packages,
127 ext_modules=ext_modules,
128 ext_modules=ext_modules,
128 data_files=[(os.path.join('mercurial', root),
129 data_files=[(os.path.join('mercurial', root),
129 [os.path.join(root, file_) for file_ in files])
130 [os.path.join(root, file_) for file_ in files])
130 for root, dirs, files in os.walk('templates')],
131 for root, dirs, files in os.walk('templates')],
131 cmdclass=cmdclass,
132 cmdclass=cmdclass,
132 options=dict(py2exe=dict(packages=['hgext', 'email']),
133 options=dict(py2exe=dict(packages=['hgext', 'email']),
133 bdist_mpkg=dict(zipdist=True,
134 bdist_mpkg=dict(zipdist=True,
134 license='COPYING',
135 license='COPYING',
135 readme='contrib/macosx/Readme.html',
136 readme='contrib/macosx/Readme.html',
136 welcome='contrib/macosx/Welcome.html')),
137 welcome='contrib/macosx/Welcome.html')),
137 **extra)
138 **extra)
General Comments 0
You need to be logged in to leave comments. Login now