##// END OF EJS Templates
Use equation_env variable, PEP8 adaptation
jakobgager -
Show More
@@ -1,193 +1,197 b''
1 from converters.base import Converter
1 from converters.base import Converter
2 from converters.utils import markdown2latex, remove_ansi
2 from converters.utils import markdown2latex, remove_ansi
3 import os
3 import os
4 import subprocess
4 import subprocess
5 import sys
5 import sys
6
6
7 inkscape = 'inkscape'
7 inkscape = 'inkscape'
8 if sys.platform == 'darwin':
8 if sys.platform == 'darwin':
9 inkscape = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
9 inkscape = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
10 if not os.path.exists(inkscape):
10 if not os.path.exists(inkscape):
11 inkscape = None
11 inkscape = None
12
12
13
13
14 class ConverterLaTeX(Converter):
14 class ConverterLaTeX(Converter):
15 """Converts a notebook to a .tex file suitable for pdflatex.
15 """Converts a notebook to a .tex file suitable for pdflatex.
16
16
17 Note: this converter *needs*:
17 Note: this converter *needs*:
18
18
19 - `pandoc`: for all conversion of markdown cells. If your notebook only
19 - `pandoc`: for all conversion of markdown cells. If your notebook only
20 has Raw cells, pandoc will not be needed.
20 has Raw cells, pandoc will not be needed.
21
21
22 - `inkscape`: if your notebook has SVG figures. These need to be
22 - `inkscape`: if your notebook has SVG figures. These need to be
23 converted to PDF before inclusion in the TeX file, as LaTeX doesn't
23 converted to PDF before inclusion in the TeX file, as LaTeX doesn't
24 understand SVG natively.
24 understand SVG natively.
25
25
26 You will in general obtain much better final PDF results if you configure
26 You will in general obtain much better final PDF results if you configure
27 the matplotlib backend to create SVG output with
27 the matplotlib backend to create SVG output with
28
28
29 %config InlineBackend.figure_format = 'svg'
29 %config InlineBackend.figure_format = 'svg'
30
30
31 (or set the equivalent flag at startup or in your configuration profile).
31 (or set the equivalent flag at startup or in your configuration profile).
32 """
32 """
33 inkscape = inkscape
33 inkscape = inkscape
34 extension = 'tex'
34 extension = 'tex'
35 documentclass = 'article'
35 documentclass = 'article'
36 documentclass_options = '11pt,english'
36 documentclass_options = '11pt,english'
37 equation_env = 'equation*'
37 heading_map = {1: r'\section',
38 heading_map = {1: r'\section',
38 2: r'\subsection',
39 2: r'\subsection',
39 3: r'\subsubsection',
40 3: r'\subsubsection',
40 4: r'\paragraph',
41 4: r'\paragraph',
41 5: r'\subparagraph',
42 5: r'\subparagraph',
42 6: r'\subparagraph'}
43 6: r'\subparagraph'}
43 user_preamble = None
44 user_preamble = None
44 exclude_cells = []
45 exclude_cells = []
45 display_data_priority = ['latex', 'pdf', 'svg', 'png', 'jpg', 'text']
46 display_data_priority = ['latex', 'pdf', 'svg', 'png', 'jpg', 'text']
46
47
47 def in_env(self, environment, lines):
48 def in_env(self, environment, lines):
48 """Return list of environment lines for input lines
49 """Return list of environment lines for input lines
49
50
50 Parameters
51 Parameters
51 ----------
52 ----------
52 env : string
53 env : string
53 Name of the environment to bracket with begin/end.
54 Name of the environment to bracket with begin/end.
54
55
55 lines: """
56 lines: """
56 out = [ur'\begin{%s}' % environment]
57 out = [ur'\begin{%s}' % environment]
57 if isinstance(lines, basestring):
58 if isinstance(lines, basestring):
58 out.append(lines)
59 out.append(lines)
59 else: # list
60 else: # list
60 out.extend(lines)
61 out.extend(lines)
61 out.append(ur'\end{%s}' % environment)
62 out.append(ur'\end{%s}' % environment)
62 return out
63 return out
63
64
64 def convert(self, *args, **kwargs):
65 def convert(self, *args, **kwargs):
65 # The main body is done by the logic in the parent class, and that's
66 # The main body is done by the logic in the parent class, and that's
66 # all we need if preamble support has been turned off.
67 # all we need if preamble support has been turned off.
67 body = super(ConverterLaTeX, self).convert(*args, **kwargs)
68 body = super(ConverterLaTeX, self).convert(*args, **kwargs)
68 if not self.with_preamble:
69 if not self.with_preamble:
69 return body
70 return body
70 # But if preamble is on, then we need to construct a proper, standalone
71 # But if preamble is on, then we need to construct a proper, standalone
71 # tex file.
72 # tex file.
72
73
73 # Tag the document at the top and set latex class
74 # Tag the document at the top and set latex class
74 final = [r'%% This file was auto-generated by IPython, do NOT edit',
75 final = [r'%% This file was auto-generated by IPython.',
75 r'%% Conversion from the original notebook file:',
76 r'%% Conversion from the original notebook file:',
76 r'%% {0}'.format(self.infile),
77 r'%% {0}'.format(self.infile),
77 r'%%',
78 r'%%',
78 r'\documentclass[%s]{%s}' % (self.documentclass_options,
79 r'\documentclass[%s]{%s}' % (self.documentclass_options,
79 self.documentclass),
80 self.documentclass),
80 '',
81 '',
81 ]
82 ]
82 # Load our own preamble, which is stored next to the main file. We
83 # Load our own preamble, which is stored next to the main file. We
83 # need to be careful in case the script entry point is a symlink
84 # need to be careful in case the script entry point is a symlink
84 myfile = os.path.realpath(__file__)
85 myfile = os.path.realpath(__file__)
85 preamble = '../preamble.tex'
86 preamble = '../preamble.tex'
86 with open(os.path.join(os.path.dirname(myfile), preamble)) as f:
87 with open(os.path.join(os.path.dirname(myfile), preamble)) as f:
87 final.append(f.read())
88 final.append(f.read())
88
89
89 # Load any additional user-supplied preamble
90 # Load any additional user-supplied preamble
90 if self.user_preamble:
91 if self.user_preamble:
91 final.extend(['', '%% Adding user preamble from file:',
92 final.extend(['', '%% Adding user preamble from file:',
92 '%% {0}'.format(self.user_preamble), ''])
93 '%% {0}'.format(self.user_preamble), ''])
93 with open(self.user_preamble) as f:
94 with open(self.user_preamble) as f:
94 final.append(f.read())
95 final.append(f.read())
95
96
96 # Include document body
97 # Include document body
97 final.extend([r'\begin{document}', '',
98 final.extend([r'\begin{document}', '',
98 body,
99 body,
99 r'\end{document}', ''])
100 r'\end{document}', ''])
100 # Return value must be a string
101 # Return value must be a string
101 return '\n'.join(final)
102 return '\n'.join(final)
102
103
103 def render_heading(self, cell):
104 def render_heading(self, cell):
104 marker = self.heading_map[cell.level]
105 marker = self.heading_map[cell.level]
105 return ['%s{%s}' % (marker, cell.source)]
106 return ['%s{%s}' % (marker, cell.source)]
106
107
107 def render_code(self, cell):
108 def render_code(self, cell):
108 if not cell.input:
109 if not cell.input:
109 return []
110 return []
110
111
111 # Cell codes first carry input code, we use lstlisting for that
112 # Cell codes first carry input code, we use lstlisting for that
112 lines = [ur'\begin{codecell}']
113 lines = [ur'\begin{codecell}']
113
114
114 if 'source' not in self.exclude_cells:
115 if 'source' not in self.exclude_cells:
115 lines.extend(self.in_env('codeinput',
116 lines.extend(self.in_env('codeinput',
116 self.in_env('lstlisting', cell.input)))
117 self.in_env('lstlisting', cell.input)))
117 else:
118 else:
118 # Empty output is still needed for LaTeX formatting
119 # Empty output is still needed for LaTeX formatting
119 lines.extend(self.in_env('codeinput', ''))
120 lines.extend(self.in_env('codeinput', ''))
120
121
121 outlines = []
122 outlines = []
122 if 'output' not in self.exclude_cells:
123 if 'output' not in self.exclude_cells:
123 for output in cell.outputs:
124 for output in cell.outputs:
124 conv_fn = self.dispatch(output.output_type)
125 conv_fn = self.dispatch(output.output_type)
125 outlines.extend(conv_fn(output))
126 outlines.extend(conv_fn(output))
126
127
127 # And then output of many possible types; use a frame for all of it.
128 # And then output of many possible types; use a frame for all of it.
128 if outlines:
129 if outlines:
129 lines.extend(self.in_env('codeoutput', outlines))
130 lines.extend(self.in_env('codeoutput', outlines))
130
131
131 lines.append(ur'\end{codecell}')
132 lines.append(ur'\end{codecell}')
132
133
133 return lines
134 return lines
134
135
135 def _img_lines(self, img_file):
136 def _img_lines(self, img_file):
136 return self.in_env('center',
137 rel_img_position = os.path.relpath(img_file, self.infile_dir)
137 [r'\includegraphics[width=0.7\textwidth]{%s}' % os.path.relpath(img_file, self.infile_dir), r'\par'])
138 return self.in_env('center',
139 [r'\includegraphics[width=0.7\textwidth]{%s}' % rel_img_position,
140 r'\par'])
138
141
139 def _svg_lines(self, img_file):
142 def _svg_lines(self, img_file):
140 base_file = os.path.splitext(img_file)[0]
143 base_file = os.path.splitext(img_file)[0]
141 pdf_file = base_file + '.pdf'
144 pdf_file = base_file + '.pdf'
142 subprocess.check_call([self.inkscape, '--export-pdf=%s' % pdf_file,
145 subprocess.check_call([self.inkscape, '--export-pdf=%s' % pdf_file,
143 img_file])
146 img_file])
144 return self._img_lines(pdf_file)
147 return self._img_lines(pdf_file)
145
148
146 def render_markdown(self, cell):
149 def render_markdown(self, cell):
147 return [markdown2latex(cell.source)]
150 return [markdown2latex(cell.source)]
148
151
149 def render_pyout(self, output):
152 def render_pyout(self, output):
150 lines = []
153 lines = []
151
154
152 # output is a dictionary like object with type as a key
155 # output is a dictionary like object with type as a key
153 if 'latex' in output:
156 if 'latex' in output:
154 lines.extend(self.in_env('equation', output.latex.lstrip('$$').rstrip('$$')))
157 lines.extend(self.in_env(self.equation_env,
155
158 output.latex.lstrip('$$').rstrip('$$')))
156 #use text only if no latex representation is available
159 #use text only if no latex representation is available
157 elif 'text' in output:
160 elif 'text' in output:
158 lines.extend(self.in_env('verbatim', output.text))
161 lines.extend(self.in_env('verbatim', output.text))
159
162
160 return lines
163 return lines
161
164
162 def render_pyerr(self, output):
165 def render_pyerr(self, output):
163 # Note: a traceback is a *list* of frames.
166 # Note: a traceback is a *list* of frames.
164 return self.in_env('traceback',
167 return self.in_env('traceback',
165 self.in_env('verbatim',
168 self.in_env('verbatim',
166 remove_ansi('\n'.join(output.traceback))))
169 remove_ansi('\n'.join(output.traceback))))
167
170
168 def render_raw(self, cell):
171 def render_raw(self, cell):
169 if self.raw_as_verbatim:
172 if self.raw_as_verbatim:
170 return self.in_env('verbatim', cell.source)
173 return self.in_env('verbatim', cell.source)
171 else:
174 else:
172 return [cell.source]
175 return [cell.source]
173
176
174 def _unknown_lines(self, data):
177 def _unknown_lines(self, data):
175 return [r'{\vspace{5mm}\bf WARNING:: unknown cell:}'] + \
178 return [r'{\vspace{5mm}\bf WARNING:: unknown cell:}'] + \
176 self.in_env('verbatim', data)
179 self.in_env('verbatim', data)
177
180
178 def render_display_format_text(self, output):
181 def render_display_format_text(self, output):
179 return self.in_env('verbatim', output.text.strip())
182 return self.in_env('verbatim', output.text.strip())
180
183
181 def render_display_format_html(self, output):
184 def render_display_format_html(self, output):
182 return []
185 return []
183
186
184 def render_display_format_latex(self, output):
187 def render_display_format_latex(self, output):
185 return self.in_env('equation', output.latex.lstrip('$$').rstrip('$$'))
188 return self.in_env(self.equation_env,
189 output.latex.lstrip('$$').rstrip('$$'))
186
190
187 def render_display_format_json(self, output):
191 def render_display_format_json(self, output):
188 # latex ignores json
192 # latex ignores json
189 return []
193 return []
190
194
191 def render_display_format_javascript(self, output):
195 def render_display_format_javascript(self, output):
192 # latex ignores javascript
196 # latex ignores javascript
193 return []
197 return []
General Comments 0
You need to be logged in to leave comments. Login now