##// END OF EJS Templates
Small latex mods: Escapes, Headings, Equations...
jakobgager -
Show More
@@ -1,348 +1,349 b''
1 1 """This module defines Exporter, a highly configurable converter
2 2 that uses Jinja2 to export notebook files into different formats.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from __future__ import print_function, absolute_import
18 18
19 19 # Stdlib imports
20 20 import io
21 21 import os
22 22 import inspect
23 23 from copy import deepcopy
24 24
25 25 # IPython imports
26 26 from IPython.config.configurable import Configurable
27 27 from IPython.config import Config
28 28 from IPython.nbformat import current as nbformat
29 29 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Bool
30 30 from IPython.utils.text import indent
31 31
32 32 # other libs/dependencies
33 33 from jinja2 import Environment, FileSystemLoader
34 34 from markdown import markdown
35 35
36 36 # local import
37 37 import nbconvert.filters.strings
38 38 import nbconvert.filters.markdown
39 39 import nbconvert.filters.latex
40 40 import nbconvert.filters.datatypefilter
41 41 import nbconvert.filters.highlight
42 42 import nbconvert.filters.ansi
43 43
44 44 import nbconvert.transformers.extractfigure
45 45 import nbconvert.transformers.coalescestreams
46 46
47 47 #-----------------------------------------------------------------------------
48 48 # Globals and constants
49 49 #-----------------------------------------------------------------------------
50 50
51 51 #Jinja2 extensions to load.
52 52 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
53 53
54 54 default_filters = {
55 55 'indent': indent,
56 56 'markdown': markdown,
57 57 'ansi2html': nbconvert.filters.ansi.ansi2html,
58 58 'filter_data_type': nbconvert.filters.datatypefilter.DataTypeFilter,
59 59 'get_lines': nbconvert.filters.strings.get_lines,
60 60 'highlight': nbconvert.filters.highlight.highlight,
61 61 'highlight2html': nbconvert.filters.highlight.highlight,
62 62 'highlight2latex': nbconvert.filters.highlight.highlight2latex,
63 63 'markdown2latex': nbconvert.filters.markdown.markdown2latex,
64 64 'markdown2rst': nbconvert.filters.markdown.markdown2rst,
65 65 'pycomment': nbconvert.filters.strings.python_comment,
66 66 'rm_ansi': nbconvert.filters.ansi.remove_ansi,
67 67 'rm_dollars': nbconvert.filters.strings.strip_dollars,
68 68 'rm_fake': nbconvert.filters.strings.rm_fake,
69 'rm_consoleesc': nbconvert.filters.strings.rm_consoleesc,
69 70 'rm_math_space': nbconvert.filters.latex.rm_math_space,
70 71 'wrap': nbconvert.filters.strings.wrap
71 72 }
72 73
73 74 #-----------------------------------------------------------------------------
74 75 # Class
75 76 #-----------------------------------------------------------------------------
76 77
77 78 class Exporter(Configurable):
78 79 """
79 80 Exports notebooks into other file formats. Uses Jinja 2 templating engine
80 81 to output new formats. Inherit from this class if you are creating a new
81 82 template type along with new filters/transformers. If the filters/
82 83 transformers provided by default suffice, there is no need to inherit from
83 84 this class. Instead, override the template_file and file_extension
84 85 traits via a config file.
85 86
86 87 {filters}
87 88 """
88 89
89 90 # finish the docstring
90 91 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
91 92
92 93
93 94 template_file = Unicode(
94 95 '', config=True,
95 96 help="Name of the template file to use")
96 97
97 98 file_extension = Unicode(
98 99 'txt', config=True,
99 100 help="Extension of the file that should be written to disk"
100 101 )
101 102
102 103 template_path = Unicode(
103 104 "/../templates/", config=True,
104 105 help="Path where the template files are located.")
105 106
106 107 template_skeleton_path = Unicode(
107 108 "/../templates/skeleton/", config=True,
108 109 help="Path where the template skeleton files are located.")
109 110
110 111 #Jinja block definitions
111 112 jinja_comment_block_start = Unicode("", config=True)
112 113 jinja_comment_block_end = Unicode("", config=True)
113 114 jinja_variable_block_start = Unicode("", config=True)
114 115 jinja_variable_block_end = Unicode("", config=True)
115 116 jinja_logic_block_start = Unicode("", config=True)
116 117 jinja_logic_block_end = Unicode("", config=True)
117 118
118 119 #Extension that the template files use.
119 120 template_extension = Unicode(".tpl", config=True)
120 121
121 122 #Processors that process the input data prior to the export, set in the
122 123 #constructor for this class.
123 124 transformers = None
124 125
125 126 _default_config = Config()
126 127
127 128
128 129 def __init__(self, transformers=None, filters=None, config=None, **kw):
129 130 """
130 131 Public constructor
131 132
132 133 Parameters
133 134 ----------
134 135 transformers : list[of transformer]
135 136 Custom transformers to apply to the notebook prior to engaging
136 137 the Jinja template engine. Any transformers specified here
137 138 will override existing transformers if a naming conflict
138 139 occurs.
139 140 filters : dict[of filter]
140 141 filters specified here will override existing filters if a naming
141 142 conflict occurs. Filters are availlable in jinja template through
142 143 the name of the corresponding key. Cf class docstring for
143 144 availlable default filters.
144 145 config : config
145 146 User configuration instance.
146 147 """
147 148
148 149 #Call the base class constructor
149 150 super(Exporter, self).__init__(config=config, **kw)
150 151
151 152 #Standard environment
152 153 self._init_environment()
153 154
154 155 #Add transformers
155 156 self._register_transformers()
156 157
157 158 #Add filters to the Jinja2 environment
158 159 self._register_filters()
159 160
160 161 #Load user transformers. Overwrite existing transformers if need be.
161 162 if transformers :
162 163 for transformer in transformers:
163 164 self.register_transformer(transformer)
164 165
165 166 #Load user filters. Overwrite existing filters if need be.
166 167 if not filters is None:
167 168 for key, user_filter in filters.iteritems():
168 169 if issubclass(user_filter, MetaHasTraits):
169 170 self.environment.filters[key] = user_filter(config=config)
170 171 else:
171 172 self.environment.filters[key] = user_filter
172 173
173 174 @property
174 175 def default_config(self):
175 176 if self._default_config:
176 177 return Config(deepcopy(self._default_config))
177 178 else :
178 179 return Config()
179 180
180 181
181 182 def from_notebook_node(self, nb, resources=None):
182 183 """
183 184 Convert a notebook from a notebook node instance.
184 185
185 186 Parameters
186 187 ----------
187 188 nb : Notebook node
188 189 resources : a dict of additional resources that
189 190 can be accessed read/write by transformers
190 191 and filters.
191 192 """
192 193 if resources is None:
193 194 resources = {}
194 195 nb, resources = self._preprocess(nb, resources)
195 196
196 197 #Load the template file.
197 198 self.template = self.environment.get_template(self.template_file+self.template_extension)
198 199
199 200 return self.template.render(nb=nb, resources=resources), resources
200 201
201 202
202 203 def from_filename(self, filename):
203 204 """
204 205 Convert a notebook from a notebook file.
205 206
206 207 Parameters
207 208 ----------
208 209 filename : str
209 210 Full filename of the notebook file to open and convert.
210 211 """
211 212
212 213 with io.open(filename) as f:
213 214 return self.from_notebook_node(nbformat.read(f, 'json'))
214 215
215 216
216 217 def from_file(self, file_stream):
217 218 """
218 219 Convert a notebook from a notebook file.
219 220
220 221 Parameters
221 222 ----------
222 223 file_stream : file-like object
223 224 Notebook file-like object to convert.
224 225 """
225 226 return self.from_notebook_node(nbformat.read(file_stream, 'json'))
226 227
227 228
228 229 def register_transformer(self, transformer):
229 230 """
230 231 Register a transformer.
231 232 Transformers are classes that act upon the notebook before it is
232 233 passed into the Jinja templating engine. Transformers are also
233 234 capable of passing additional information to the Jinja
234 235 templating engine.
235 236
236 237 Parameters
237 238 ----------
238 239 transformer : transformer
239 240 """
240 241 if self.transformers is None:
241 242 self.transformers = []
242 243
243 244 if inspect.isfunction(transformer):
244 245 self.transformers.append(transformer)
245 246 return transformer
246 247 elif isinstance(transformer, MetaHasTraits):
247 248 transformer_instance = transformer(config=self.config)
248 249 self.transformers.append(transformer_instance)
249 250 return transformer_instance
250 251 else:
251 252 transformer_instance = transformer()
252 253 self.transformers.append(transformer_instance)
253 254 return transformer_instance
254 255
255 256
256 257 def register_filter(self, name, filter):
257 258 """
258 259 Register a filter.
259 260 A filter is a function that accepts and acts on one string.
260 261 The filters are accesible within the Jinja templating engine.
261 262
262 263 Parameters
263 264 ----------
264 265 name : str
265 266 name to give the filter in the Jinja engine
266 267 filter : filter
267 268 """
268 269 if inspect.isfunction(filter):
269 270 self.environment.filters[name] = filter
270 271 elif isinstance(filter, MetaHasTraits):
271 272 self.environment.filters[name] = filter(config=self.config)
272 273 else:
273 274 self.environment.filters[name] = filter()
274 275 return self.environment.filters[name]
275 276
276 277
277 278 def _register_transformers(self):
278 279 """
279 280 Register all of the transformers needed for this exporter.
280 281 """
281 282
282 283 self.register_transformer(nbconvert.transformers.coalescestreams.coalesce_streams)
283 284
284 285 #Remember the figure extraction transformer so it can be enabled and
285 286 #disabled easily later.
286 287 self.extract_figure_transformer = self.register_transformer(nbconvert.transformers.extractfigure.ExtractFigureTransformer)
287 288
288 289
289 290 def _register_filters(self):
290 291 """
291 292 Register all of the filters required for the exporter.
292 293 """
293 294 for k, v in default_filters.iteritems():
294 295 self.register_filter(k, v)
295 296
296 297
297 298 def _init_environment(self):
298 299 """
299 300 Create the Jinja templating environment.
300 301 """
301 302
302 303 self.environment = Environment(
303 304 loader=FileSystemLoader([
304 305 os.path.dirname(os.path.realpath(__file__)) + self.template_path,
305 306 os.path.dirname(os.path.realpath(__file__)) + self.template_skeleton_path,
306 307 ]),
307 308 extensions=JINJA_EXTENSIONS
308 309 )
309 310
310 311 #Set special Jinja2 syntax that will not conflict with latex.
311 312 if self.jinja_logic_block_start:
312 313 self.environment.block_start_string = self.jinja_logic_block_start
313 314 if self.jinja_logic_block_end:
314 315 self.environment.block_end_string = self.jinja_logic_block_end
315 316 if self.jinja_variable_block_start:
316 317 self.environment.variable_start_string = self.jinja_variable_block_start
317 318 if self.jinja_variable_block_end:
318 319 self.environment.variable_end_string = self.jinja_variable_block_end
319 320 if self.jinja_comment_block_start:
320 321 self.environment.comment_start_string = self.jinja_comment_block_start
321 322 if self.jinja_comment_block_end:
322 323 self.environment.comment_end_string = self.jinja_comment_block_end
323 324
324 325
325 326 def _preprocess(self, nb, resources):
326 327 """
327 328 Preprocess the notebook before passing it into the Jinja engine.
328 329 To preprocess the notebook is to apply all of the
329 330
330 331 Parameters
331 332 ----------
332 333 nb : notebook node
333 334 notebook that is being exported.
334 335 resources : a dict of additional resources that
335 336 can be accessed read/write by transformers
336 337 and filters.
337 338 """
338 339
339 340 # Do a deepcopy first,
340 341 # we are never safe enough with what the transformers could do.
341 342 nbc = deepcopy(nb)
342 343 resc = deepcopy(resources)
343 344 #Run each transformer on the notebook. Carry the output along
344 345 #to each transformer
345 346 for transformer in self.transformers:
346 347 nb, resources = transformer(nbc, resc)
347 348 return nb, resources
348 349
@@ -1,108 +1,109 b''
1 1 """Latex filters.
2 2
3 3 Module of useful filters for processing Latex within Jinja latex templates.
4 4 """
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 import re
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Globals and constants
20 20 #-----------------------------------------------------------------------------
21 21
22 22 #Latex substitutions for escaping latex.
23 23 LATEX_SUBS = (
24 (re.compile('\033\[[0-9;]+m'),''), # handle console escapes
24 25 (re.compile(r'\\'), r'\\textbackslash'),
25 26 (re.compile(r'([{}_#%&$])'), r'\\\1'),
26 27 (re.compile(r'~'), r'\~{}'),
27 28 (re.compile(r'\^'), r'\^{}'),
28 29 (re.compile(r'"'), r"''"),
29 30 (re.compile(r'\.\.\.+'), r'\\ldots'),
30 31 )
31 32
32 33 #-----------------------------------------------------------------------------
33 34 # Functions
34 35 #-----------------------------------------------------------------------------
35 36
36 37 def escape_latex(text):
37 38 """
38 39 Escape characters that may conflict with latex.
39 40
40 41 Parameters
41 42 ----------
42 43 text : str
43 44 Text containing characters that may conflict with Latex
44 45 """
45 46 return_text = text
46 47 for pattern, replacement in LATEX_SUBS:
47 48 return_text = pattern.sub(replacement, return_text)
48 49 return return_text
49 50
50 51
51 52 def rm_math_space(text):
52 53 """
53 54 Remove the space between latex math commands and enclosing $ symbols.
54 55 This filter is important because latex isn't as flexible as the notebook
55 56 front end when it comes to flagging math using ampersand symbols.
56 57
57 58 Parameters
58 59 ----------
59 60 text : str
60 61 Text to filter.
61 62 """
62 63
63 64 # First, scan through the markdown looking for $. If
64 65 # a $ symbol is found, without a preceding \, assume
65 66 # it is the start of a math block. UNLESS that $ is
66 67 # not followed by another within two math_lines.
67 68 math_regions = []
68 69 math_lines = 0
69 70 within_math = False
70 71 math_start_index = 0
71 72 ptext = ''
72 73 last_character = ""
73 74 skip = False
74 75 for index, char in enumerate(text):
75 76
76 77 #Make sure the character isn't preceeded by a backslash
77 78 if (char == "$" and last_character != "\\"):
78 79
79 80 # Close the math region if this is an ending $
80 81 if within_math:
81 82 within_math = False
82 83 skip = True
83 84 ptext = ptext+'$'+text[math_start_index+1:index].strip()+'$'
84 85 math_regions.append([math_start_index, index+1])
85 86 else:
86 87
87 88 # Start a new math region
88 89 within_math = True
89 90 math_start_index = index
90 91 math_lines = 0
91 92
92 93 # If we are in a math region, count the number of lines parsed.
93 94 # Cancel the math region if we find two line breaks!
94 95 elif char == "\n":
95 96 if within_math:
96 97 math_lines += 1
97 98 if math_lines > 1:
98 99 within_math = False
99 100 ptext = ptext+text[math_start_index:index]
100 101
101 102 # Remember the last character so we can easily watch
102 103 # for backslashes
103 104 last_character = char
104 105 if not within_math and not skip:
105 106 ptext = ptext+char
106 107 if skip:
107 108 skip = False
108 109 return ptext
@@ -1,104 +1,117 b''
1 1 """String filters.
2 2
3 3 Contains a collection of useful string manipulation filters for use in Jinja
4 4 templates.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (c) 2013, the IPython Development Team.
8 8 #
9 9 # Distributed under the terms of the Modified BSD License.
10 10 #
11 11 # The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 import re
17 18
18 19 # Our own imports
19 20 import textwrap
20 21
21 22 #-----------------------------------------------------------------------------
22 23 # Functions
23 24 #-----------------------------------------------------------------------------
24 25
25 26 def wrap(text, width=100):
26 27 """
27 28 Intelligently wrap text.
28 29 Wrap text without breaking words if possible.
29 30
30 31 Parameters
31 32 ----------
32 33 text : str
33 34 Text to wrap.
34 35 width : int, optional
35 36 Number of characters to wrap to, default 100.
36 37 """
37 38
38 39 split_text = text.split('\n')
39 40 wrp = map(lambda x:textwrap.wrap(x,width), split_text)
40 41 wrpd = map('\n'.join, wrp)
41 42 return '\n'.join(wrpd)
42 43
43 44
44 45 def strip_dollars(text):
45 46 """
46 47 Remove all dollar symbols from text
47 48
48 49 Parameters
49 50 ----------
50 51 text : str
51 52 Text to remove dollars from
52 53 """
53 54
54 55 return text.strip('$')
55 56
56 57
58 def rm_consoleesc(text):
59 """
60 Remove console escapes from text
61
62 Parameters
63 ----------
64 text : str
65 Text to remove '/files/' from
66 """
67 r= re.compile("\033\[[0-9;]+m")
68 return r.sub('', text)
69
57 70 def rm_fake(text):
58 71 """
59 72 Remove all occurrences of '/files/' from text
60 73
61 74 Parameters
62 75 ----------
63 76 text : str
64 77 Text to remove '/files/' from
65 78 """
66 79 return text.replace('/files/', '')
67 80
68 81
69 82 def python_comment(text):
70 83 """
71 84 Build a Python comment line from input text.
72 85
73 86 Parameters
74 87 ----------
75 88 text : str
76 89 Text to comment out.
77 90 """
78 91
79 92 #Replace line breaks with line breaks and comment symbols.
80 93 #Also add a comment symbol at the beginning to comment out
81 94 #the first line.
82 95 return '# '+'\n# '.join(text.split('\n'))
83 96
84 97
85 98 def get_lines(text, start=None,end=None):
86 99 """
87 100 Split the input text into separate lines and then return the
88 101 lines that the caller is interested in.
89 102
90 103 Parameters
91 104 ----------
92 105 text : str
93 106 Text to parse lines from.
94 107 start : int, optional
95 108 First line to grab from.
96 109 end : int, optional
97 110 Last line to grab from.
98 111 """
99 112
100 113 # Split the input into lines.
101 114 lines = text.split("\n")
102 115
103 116 # Return the right lines.
104 117 return "\n".join(lines[start:end]) #re-join
@@ -1,235 +1,251 b''
1 1 ((*- extends 'display_priority.tplx' -*))
2 2
3 3 ((* block in_prompt *))((* endblock in_prompt *))
4 4
5 5 ((* block output_prompt *))((* endblock output_prompt *))
6 6
7 7 ((* block codecell *))\begin{codecell}((( super() )))
8 8 \end{codecell}
9 9 ((* endblock *))
10 10
11 11 ((* block input *))
12 12 \begin{codeinput}
13 13 \begin{lstlisting}
14 14 ((( cell.input )))
15 15 \end{lstlisting}
16 16 \end{codeinput}
17 17 ((* endblock input *))
18 18
19 19
20 20 ((= Those Two are for error displaying
21 21 even if the first one seem to do nothing,
22 22 it introduces a new line
23 23
24 24 =))
25 25 ((* block pyerr *))
26 26 \begin{traceback}
27 27 \begin{verbatim}((( super() )))
28 28 \end{verbatim}
29 29 \end{traceback}
30 30 ((* endblock pyerr *))
31 31
32 32 ((* block traceback_line *))
33 33 ((( line |indent| rm_ansi )))((* endblock traceback_line *))
34 34 ((= .... =))
35 35
36 36
37 37 ((*- block output_group -*))
38 38 \begin{codeoutput}
39 39 ((( super() )))
40 40 \end{codeoutput}((* endblock *))
41 41
42 42 ((*- block data_png -*))
43 43 \begin{center}
44 44 \includegraphics[width=0.7\textwidth, height=0.9\textheight, keepaspectratio]{(((output.key_png)))}
45 45 \par
46 46 \end{center}
47 47 ((*- endblock -*))
48 48
49 49 ((*- block data_jpg -*))
50 50 \begin{center}
51 51 \includegraphics[width=0.7\textwidth, height=0.9\textheight, keepaspectratio]{(((output.key_jpeg)))}
52 52 \par
53 53 \end{center}
54 54 ((*- endblock -*))
55 55
56 56 ((*- block data_svg -*))
57 57 \begin{center}
58 58 \includegraphics[width=0.7\textwidth]{(((output.key_svg)))}
59 59 \par
60 60 \end{center}
61 61 ((*- endblock -*))
62 62
63 63 ((* block pyout *))
64 64 ((* block data_priority scoped *))((( super() )))((* endblock *))
65 65 ((* endblock pyout *))
66 66
67 67 ((* block data_text *))
68 68 \begin{verbatim}
69 69 ((( output.text )))
70 70 \end{verbatim}
71 71 ((* endblock *))
72 72
73 73 ((* block data_latex -*))
74 \begin{equation*}
75 ((( output.latex | rm_dollars)))
76 \end{equation*}
74 ((*- if output.latex.startswith('$'): -*)) \begin{equation*}
75 ((( output.latex | rm_dollars)))
76 \end{equation*}
77 ((*- else -*)) ((( output.latex ))) ((*- endif *))
77 78 ((* endblock *))
78 79
79 80 ((* block stream *))
80 81 \begin{verbatim}
81 ((( output.text)))
82 ((( output.text | rm_consoleesc)))
82 83 \end{verbatim}
83 84 ((* endblock stream *))
84 85
85 86 ((* block markdowncell scoped *))((( cell.source | markdown2latex )))
86 87 ((* endblock markdowncell *))
87 88
88 ((* block headingcell scoped *))
89 \section{((( cell.source | markdown2latex)))}
89 ((* block headingcell scoped -*))
90 \
91 ((*- if cell.level == 1 -*))
92 ((* block h1 -*))section((* endblock h1 -*))
93 ((*- elif cell.level == 2 -*))
94 ((* block h2 -*))subsection((* endblock h2 -*))
95 ((*- elif cell.level == 3 -*))
96 ((* block h3 -*))subsubsection((* endblock h3 -*))
97 ((*- elif cell.level == 4 -*))
98 ((* block h4 -*))paragraph((* endblock h4 -*))
99 ((*- elif cell.level == 5 -*))
100 ((* block h5 -*))subparagraph((* endblock h5 -*))
101 ((*- elif cell.level == 6 -*))
102 ((* block h6 -*))subparagraph((* endblock h6 -*))
103 ((= 6th level not available in standard latex =))
104
105 ((*- endif -*)){((( cell.source | markdown2latex )))}
90 106 ((* endblock headingcell *))
91 107
92 108 ((* block rawcell scoped *))
93 109 ((( cell.source | pycomment )))
94 110 ((* endblock rawcell *))
95 111
96 112 ((* block unknowncell scoped *))
97 113 unknown type (((cell.type)))
98 114 ((* endblock unknowncell *))
99 115
100 116
101 117
102 118 ((* block body *))
103 119
104 120 ((* block bodyBegin *))
105 121 \begin{document}
106 122 ((* endblock bodyBegin *))
107 123
108 124 ((( super() )))
109 125
110 126 ((* block bodyEnd *))
111 127 \end{document}
112 128 ((* endblock bodyEnd *))
113 129 ((* endblock body *))
114 130
115 131 ((* block header *))
116 132 %% This file was auto-generated by IPython.
117 133 %% Conversion from the original notebook file:
118 134 %%
119 135 \documentclass[11pt,english]{article}
120 136
121 137 %% This is the automatic preamble used by IPython. Note that it does *not*
122 138 %% include a documentclass declaration, that is added at runtime to the overall
123 139 %% document.
124 140
125 141 \usepackage{amsmath}
126 142 \usepackage{amssymb}
127 143 \usepackage{graphicx}
128 144 \usepackage{ucs}
129 145 \usepackage[utf8x]{inputenc}
130 146
131 147 % needed for markdown enumerations to work
132 148 \usepackage{enumerate}
133 149
134 150 % Slightly bigger margins than the latex defaults
135 151 \usepackage{geometry}
136 152 \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm}
137 153
138 154 % Define a few colors for use in code, links and cell shading
139 155 \usepackage{color}
140 156 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
141 157 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
142 158 \definecolor{darkgreen}{rgb}{.12,.54,.11}
143 159 \definecolor{myteal}{rgb}{.26, .44, .56}
144 160 \definecolor{gray}{gray}{0.45}
145 161 \definecolor{lightgray}{gray}{.95}
146 162 \definecolor{mediumgray}{gray}{.8}
147 163 \definecolor{inputbackground}{rgb}{.95, .95, .85}
148 164 \definecolor{outputbackground}{rgb}{.95, .95, .95}
149 165 \definecolor{traceback}{rgb}{1, .95, .95}
150 166
151 167 % Framed environments for code cells (inputs, outputs, errors, ...). The
152 168 % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't
153 169 % randomly change them unless you're sure of the effect it will have.
154 170 \usepackage{framed}
155 171
156 172 % remove extraneous vertical space in boxes
157 173 \setlength\fboxsep{0pt}
158 174
159 175 % codecell is the whole input+output set of blocks that a Code cell can
160 176 % generate.
161 177
162 178 % TODO: unfortunately, it seems that using a framed codecell environment breaks
163 179 % the ability of the frames inside of it to be broken across pages. This
164 180 % causes at least the problem of having lots of empty space at the bottom of
165 181 % pages as new frames are moved to the next page, and if a single frame is too
166 182 % long to fit on a page, will completely stop latex from compiling the
167 183 % document. So unless we figure out a solution to this, we'll have to instead
168 184 % leave the codecell env. as empty. I'm keeping the original codecell
169 185 % definition here (a thin vertical bar) for reference, in case we find a
170 186 % solution to the page break issue.
171 187
172 188 %% \newenvironment{codecell}{%
173 189 %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}%
174 190 %% \MakeFramed{\vspace{-0.5em}}}
175 191 %% {\unskip\endMakeFramed}
176 192
177 193 % For now, make this a no-op...
178 194 \newenvironment{codecell}{}
179 195
180 196 \newenvironment{codeinput}{%
181 197 \def\FrameCommand{\colorbox{inputbackground}}%
182 198 \MakeFramed{\advance\hsize-\width \FrameRestore}}
183 199 {\unskip\endMakeFramed}
184 200
185 201 \newenvironment{codeoutput}{%
186 202 \def\FrameCommand{\colorbox{outputbackground}}%
187 203 \vspace{-1.4em}
188 204 \MakeFramed{\advance\hsize-\width \FrameRestore}}
189 205 {\unskip\medskip\endMakeFramed}
190 206
191 207 \newenvironment{traceback}{%
192 208 \def\FrameCommand{\colorbox{traceback}}%
193 209 \MakeFramed{\advance\hsize-\width \FrameRestore}}
194 210 {\endMakeFramed}
195 211
196 212 % Use and configure listings package for nicely formatted code
197 213 \usepackage{listingsutf8}
198 214 \lstset{
199 215 language=python,
200 216 inputencoding=utf8x,
201 217 extendedchars=\true,
202 218 aboveskip=\smallskipamount,
203 219 belowskip=\smallskipamount,
204 220 xleftmargin=2mm,
205 221 breaklines=true,
206 222 basicstyle=\small \ttfamily,
207 223 showstringspaces=false,
208 224 keywordstyle=\color{blue}\bfseries,
209 225 commentstyle=\color{myteal},
210 226 stringstyle=\color{darkgreen},
211 227 identifierstyle=\color{darkorange},
212 228 columns=fullflexible, % tighter character kerning, like verb
213 229 }
214 230
215 231 % The hyperref package gives us a pdf with properly built
216 232 % internal navigation ('pdf bookmarks' for the table of contents,
217 233 % internal cross-reference links, web links for URLs, etc.)
218 234 \usepackage{hyperref}
219 235 \hypersetup{
220 236 breaklinks=true, % so long urls are correctly broken across lines
221 237 colorlinks=true,
222 238 urlcolor=blue,
223 239 linkcolor=darkorange,
224 240 citecolor=darkgreen,
225 241 }
226 242
227 243 % hardcode size of all verbatim environments to be a bit smaller
228 244 \makeatletter
229 245 \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt
230 246 \makeatother
231 247
232 248 % Prevent overflowing lines due to urls and other hard-to-break entities.
233 249 \sloppy
234 250
235 251 ((* endblock *))
General Comments 0
You need to be logged in to leave comments. Login now