-
Notifications
You must be signed in to change notification settings - Fork 555
/
highlight.py
190 lines (155 loc) · 5.99 KB
/
highlight.py
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
"""
Module containing filter functions that allow code to be highlighted
from within Jinja templates.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
# pygments must not be imported at the module level
# because errors should be raised at runtime if it's actually needed,
# not import time, when it may not be needed.
from html import escape
from warnings import warn
from traitlets import Dict, observe
from nbconvert.utils.base import NbConvertBase
MULTILINE_OUTPUTS = ["text", "html", "svg", "latex", "javascript", "json"]
__all__ = ["Highlight2HTML", "Highlight2Latex"]
class Highlight2HTML(NbConvertBase):
"""Convert highlighted code to html."""
extra_formatter_options = Dict(
{},
help="""
Extra set of options to control how code is highlighted.
Passed through to the pygments' HtmlFormatter class.
See available list in https://pygments.org/docs/formatters/#HtmlFormatter
""",
config=True,
)
def __init__(self, pygments_lexer=None, **kwargs):
"""Initialize the converter."""
self.pygments_lexer = pygments_lexer or "ipython3"
super().__init__(**kwargs)
@observe("default_language")
def _default_language_changed(self, change):
warn(
"Setting default_language in config is deprecated as of 5.0, "
"please use language_info metadata instead.",
stacklevel=2,
)
self.pygments_lexer = change["new"]
def __call__(self, source, language=None, metadata=None):
"""
Return a syntax-highlighted version of the input source as html output.
Parameters
----------
source : str
source of the cell to highlight
language : str
language to highlight the syntax of
metadata : NotebookNode cell metadata
metadata of the cell to highlight
"""
from pygments.formatters import HtmlFormatter
if not language:
language = self.pygments_lexer
return _pygments_highlight(
source if len(source) > 0 else " ",
# needed to help post processors:
HtmlFormatter(
cssclass=escape(f" highlight hl-{language}"), **self.extra_formatter_options
),
language,
metadata,
)
class Highlight2Latex(NbConvertBase):
"""Convert highlighted code to latex."""
extra_formatter_options = Dict(
{},
help="""
Extra set of options to control how code is highlighted.
Passed through to the pygments' LatexFormatter class.
See available list in https://pygments.org/docs/formatters/#LatexFormatter
""",
config=True,
)
def __init__(self, pygments_lexer=None, **kwargs):
"""Initialize the converter."""
self.pygments_lexer = pygments_lexer or "ipython3"
super().__init__(**kwargs)
@observe("default_language")
def _default_language_changed(self, change):
warn(
"Setting default_language in config is deprecated as of 5.0, "
"please use language_info metadata instead.",
stacklevel=2,
)
self.pygments_lexer = change["new"]
def __call__(self, source, language=None, metadata=None, strip_verbatim=False):
"""
Return a syntax-highlighted version of the input source as latex output.
Parameters
----------
source : str
source of the cell to highlight
language : str
language to highlight the syntax of
metadata : NotebookNode cell metadata
metadata of the cell to highlight
strip_verbatim : bool
remove the Verbatim environment that pygments provides by default
"""
from pygments.formatters import LatexFormatter
if not language:
language = self.pygments_lexer
latex = _pygments_highlight(
source, LatexFormatter(**self.extra_formatter_options), language, metadata
)
if strip_verbatim:
latex = latex.replace(r"\begin{Verbatim}[commandchars=\\\{\}]" + "\n", "")
return latex.replace("\n\\end{Verbatim}\n", "")
else:
return latex
def _pygments_highlight(source, output_formatter, language="ipython", metadata=None):
"""
Return a syntax-highlighted version of the input source
Parameters
----------
source : str
source of the cell to highlight
output_formatter : Pygments formatter
language : str
language to highlight the syntax of
metadata : NotebookNode cell metadata
metadata of the cell to highlight
"""
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.util import ClassNotFound
# If the cell uses a magic extension language,
# use the magic language instead.
if language.startswith("ipython") and metadata and "magics_language" in metadata:
language = metadata["magics_language"]
lexer = None
if language == "ipython2":
try:
from IPython.lib.lexers import IPythonLexer
except ImportError:
warn("IPython lexer unavailable, falling back on Python", stacklevel=2)
language = "python"
else:
lexer = IPythonLexer()
elif language == "ipython3":
try:
from IPython.lib.lexers import IPython3Lexer
except ImportError:
warn("IPython3 lexer unavailable, falling back on Python 3", stacklevel=2)
language = "python3"
else:
lexer = IPython3Lexer()
if lexer is None:
try:
lexer = get_lexer_by_name(language, stripall=True)
except ClassNotFound:
warn("No lexer found for language %r. Treating as plain text." % language, stacklevel=2)
from pygments.lexers.special import TextLexer
lexer = TextLexer()
return highlight(source, lexer, output_formatter)