1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# -*- coding: utf-8 -*-
"""
sphinx.highlighting
~~~~~~~~~~~~~~~~~~~
Highlight code blocks using Pygments.
:copyright: 2007-2008 by Georg Brandl.
:license: BSD.
"""
import sys
import cgi
import re
import parser
try:
import pygments
from pygments import highlight
from pygments.lexers import PythonLexer, PythonConsoleLexer, CLexer, \
TextLexer, RstLexer
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter, LatexFormatter
from pygments.filters import ErrorToken
from pygments.style import Style
from pygments.styles import get_style_by_name
from pygments.styles.friendly import FriendlyStyle
from pygments.token import Generic, Comment, Number
except ImportError:
pygments = None
else:
class SphinxStyle(Style):
"""
Like friendly, but a bit darker to enhance contrast on the green
background.
"""
background_color = '#eeffcc'
default_style = ''
styles = FriendlyStyle.styles
styles.update({
Generic.Output: '#333',
Comment: 'italic #408090',
Number: '#208050',
})
lexers = dict(
none = TextLexer(),
python = PythonLexer(),
pycon = PythonConsoleLexer(),
rest = RstLexer(),
c = CLexer(),
)
for _lexer in lexers.values():
_lexer.add_filter('raiseonerror')
def escape_tex(text):
return text.replace('@', '\x00'). \
replace('[', '\x01'). \
replace(']', '\x02'). \
replace('\x00', '@at[]').\
replace('\x01', '@lb[]').\
replace('\x02', '@rb[]')
parsing_exceptions = (SyntaxError, UnicodeEncodeError)
if sys.version_info < (2, 5):
# Python <= 2.4 raises MemoryError when parsing an
# invalid encoding cookie
parsing_exceptions += MemoryError,
class PygmentsBridge(object):
def __init__(self, dest='html', stylename='sphinx'):
self.dest = dest
if not pygments:
return
if stylename == 'sphinx':
style = SphinxStyle
else:
style = get_style_by_name(stylename)
self.hfmter = {False: HtmlFormatter(style=style),
True: HtmlFormatter(style=style, linenos=True)}
self.lfmter = {False: LatexFormatter(style=style),
True: LatexFormatter(style=style, linenos=True)}
def highlight_block(self, source, lang, linenos=False):
def unhighlighted():
if self.dest == 'html':
return '<pre>' + cgi.escape(source) + '</pre>\n'
else:
return '\\begin{Verbatim}[commandchars=@\\[\\]]\n' + \
escape_tex(source) + '\\end{Verbatim}\n'
if not pygments:
return unhighlighted()
if lang == 'python':
if source.startswith('>>>'):
# interactive session
lexer = lexers['pycon']
else:
# maybe Python -- try parsing it
src = source + '\n'
# Replace "..." by a special mark, which is also a valid python expression
# (Note, the highlighter gets the original source, this is only done
# to allow "..." in code and still highlight it as Python code.)
mark = "__highlighting__ellipsis__"
src = src.replace("...", mark)
# lines beginning with "..." are probably placeholders for suite
src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src)
# if we're using 2.5, use the with statement
if sys.version_info >= (2, 5):
src = 'from __future__ import with_statement\n' + src
try:
parser.suite(src)
except parsing_exceptions:
return unhighlighted()
else:
lexer = lexers['python']
else:
if lang in lexers:
lexer = lexers[lang]
else:
lexer = lexers[lang] = get_lexer_by_name(lang)
lexer.add_filter('raiseonerror')
try:
fmter = (self.dest == 'html' and self.hfmter or self.lfmter)[bool(linenos)]
return highlight(source, lexer, fmter)
except ErrorToken:
# this is most probably not the selected language, so let it pass unhighlighted
return unhighlighted()
def get_stylesheet(self):
if not pygments:
return ''
return (self.dest == 'html' and self.hfmter or self.lfmter)[0].get_style_defs()
|