Added some ideas.
[docutils/kirr.git] / sandbox / rst2beamer / latexbeamer / __init__.py
blob11e5b5f337317d6d561a7f8ccb1f0aa52e0d07af
1 """
2 LaTeX Beamer document tree Writer.
3 """
5 __docformat__ = 'reStructuredText'
7 from docutils import frontend, nodes
8 from docutils.writers import latex2e
9 from docutils.readers import standalone
10 from docutils.transforms import references, Transform, TransformError
12 class Writer(latex2e.Writer):
14 supported = ('latexbeamer')
15 """Formats this writer supports."""
17 settings_spec = (
18 'LaTeX Beamer Specific Options',
19 'The LaTeX "--output-encoding" default is "latin-1:strict".',
20 (('Specify document options. Multiple options can be given, '
21 'separated by commas. Default is no options.',
22 ['--documentoptions'],
23 {'default': '', }),
24 ('Use LaTeX footnotes. LaTeX supports only numbered footnotes (does it?). '
25 'Default: no, uses figures.',
26 ['--use-latex-footnotes'],
27 {'default': 0, 'action': 'store_true',
28 'validator': frontend.validate_boolean}),
29 ('Format for footnote references: one of "superscript" or '
30 '"brackets". Default is "superscript".',
31 ['--footnote-references'],
32 {'choices': ['superscript', 'brackets'], 'default': 'superscript',
33 'metavar': '<format>',
34 'overrides': 'trim_footnote_reference_space'}),
35 ('Use LaTeX citations. '
36 'Default: no, uses figures which might get mixed with images.',
37 ['--use-latex-citations'],
38 {'default': 0, 'action': 'store_true',
39 'validator': frontend.validate_boolean}),
40 ('Format for block quote attributions: one of "dash" (em-dash '
41 'prefix), "parentheses"/"parens", or "none". Default is "dash".',
42 ['--attribution'],
43 {'choices': ['dash', 'parentheses', 'parens', 'none'],
44 'default': 'dash', 'metavar': '<format>'}),
45 ('Specify a stylesheet file. The file will be "input" by latex in '
46 'the document header. Default is no stylesheet (""). '
47 'Overrides --stylesheet-path.',
48 ['--stylesheet'],
49 {'default': '', 'metavar': '<file>',
50 'overrides': 'stylesheet_path'}),
51 ('Specify a stylesheet file, relative to the current working '
52 'directory. Overrides --stylesheet.',
53 ['--stylesheet-path'],
54 {'metavar': '<file>', 'overrides': 'stylesheet'}),
55 ('Table of contents by docutils (default) or latex. Latex (writer) '
56 'supports only one ToC per document, but docutils does not write '
57 'pagenumbers.',
58 ['--use-latex-toc'],
59 {'default': 0, 'action': 'store_true',
60 'validator': frontend.validate_boolean}),
61 ('Color of any hyperlinks embedded in text '
62 '(default: "0" (disabled)).',
63 ['--hyperlink-color'], {'default': '0'}),
64 ('Enable compound enumerators for nested enumerated lists '
65 '(e.g. "1.2.a.ii"). Default: disabled.',
66 ['--compound-enumerators'],
67 {'default': None, 'action': 'store_true',
68 'validator': frontend.validate_boolean}),
69 ('Disable compound enumerators for nested enumerated lists. This is '
70 'the default.',
71 ['--no-compound-enumerators'],
72 {'action': 'store_false', 'dest': 'compound_enumerators'}),
73 ('Enable section ("." subsection ...) prefixes for compound '
74 'enumerators. This has no effect without --compound-enumerators. '
75 'Default: disabled.',
76 ['--section-prefix-for-enumerators'],
77 {'default': None, 'action': 'store_true',
78 'validator': frontend.validate_boolean}),
79 ('Disable section prefixes for compound enumerators. '
80 'This is the default.',
81 ['--no-section-prefix-for-enumerators'],
82 {'action': 'store_false', 'dest': 'section_prefix_for_enumerators'}),
83 ('Set the separator between section number and enumerator '
84 'for compound enumerated lists. Default is "-".',
85 ['--section-enumerator-separator'],
86 {'default': '-', 'metavar': '<char>'}),
87 ('When possibile, use verbatim for literal-blocks. '
88 'Default is to always use the mbox environment.',
89 ['--use-verbatim-when-possible'],
90 {'default': 0, 'action': 'store_true',
91 'validator': frontend.validate_boolean}),
92 ('Table style. "standard" with horizontal and vertical lines, '
93 '"booktabs" (LaTeX booktabs style) only horizontal lines '
94 'above and below the table and below the header or "nolines". '
95 'Default: "standard"',
96 ['--table-style'],
97 {'choices': ['standard', 'booktabs','nolines'], 'default': 'standard',
98 'metavar': '<format>'}),
99 ('LaTeX graphicx package option. '
100 'Possible values are "dvips", "pdftex". "auto" includes LaTeX code '
101 'to use "pdftex" if processing with pdf(la)tex and dvips otherwise. '
102 'Default is no option.',
103 ['--graphicx-option'],
104 {'default': ''}),
105 ('LaTeX font encoding. '
106 'Possible values are "T1", "OT1", "" or some other fontenc option. '
107 'The font encoding influences available symbols, e.g. "<<" as one '
108 'character. Default is "" which leads to package "ae" (a T1 '
109 'emulation using CM fonts).',
110 ['--font-encoding'],
111 {'default': ''}),
112 # TODO Themes must be changeable by ``usecolortheme``,
113 # ``usefonttheme``, ``useinnertheme``, and ``useoutertheme``
114 # separately
115 ('LaTeX Beamer theme to use. '
116 'Default is JuanLesPins.',
117 ['--beamer-theme'],
118 {'default': 'JuanLesPins'}),
119 ('Insert intermediate outline slides at a certain level. '
120 'Possible values are "section" and "subsection". '
121 'Default is no intermediate outline slides.',
122 ['--intermediate-outlines'],
123 {'choices': ['section', 'subsection',],
124 'default': ''}),
125 # TODO Some themes accept options which must be supported here as
126 # plain strings for those who know what they do
129 def __init__(self):
130 latex2e.Writer.__init__(self)
131 self.translator_class = BeamerTranslator
133 class DocumentClass(latex2e.DocumentClass):
134 """Details of a LaTeX document class."""
136 def __init__(self):
137 pass
139 def section(self, level):
140 """ Return the section name at the given level for the specific
141 document class.
143 Level is 1,2,3..., as level 0 is the title."""
145 # TODO Level where sections become frames must be an option - might be
146 # determined by a preprocessor, then it is also not fixed - might be
147 # driven by the first content under a section
148 sections = [ 'section', "begin{frame}\n\\frametitle", ]
149 if level <= len(sections):
150 return sections[level-1]
151 else:
152 return sections[-1]
154 def section_end(self, level):
155 """ Return the section name at the given level for the specific
156 document class.
158 Level is 1,2,3..., as level 0 is the title."""
160 # TODO See above
161 sections = [ '', "\n\\end{frame}\n", ]
162 if level <= len(sections):
163 return sections[level-1]
164 else:
165 return sections[-1]
167 class BeamerTranslator(latex2e.LaTeXTranslator):
169 def __init__(self, document):
170 document.settings.documentclass = 'beamer'
171 document.settings.use_latex_docinfo = 1
172 latex2e.LaTeXTranslator.__init__(self, document)
173 # TODO Should be done via explicit head_prefix
174 self.head_prefix = [ line
175 for line in self.head_prefix
176 if 'typearea' not in line and 'hyperref' not in line ]
177 # Montpellier, Warsaw, JuanLesPins, Darmstadt, Antibes
178 self.head_prefix.extend(('\n',
179 '\\mode<presentation>\n',
180 '{\n',
181 ' \\usetheme{%s}\n'
182 % ( document.settings.beamer_theme, ),
183 # TODO Argument to `setbeamercovered` must be
184 # an option
185 ' \\setbeamercovered{transparent}\n',
186 '}\n',
187 '\n',
189 # TODO Name of outline slides should be the name given for the contents
190 # (is a `title` element) - might be determined by a preprocessor
191 document.settings.toc_title = 'Outline'
192 # TODO Must be present only if there is a toc
193 if document.settings.intermediate_outlines:
194 if document.settings.intermediate_outlines == 'section':
195 at_begin = 'AtBeginSection'
196 toc_option = 'currentsection'
197 else:
198 at_begin = 'AtBeginSubsection'
199 toc_option = 'currentsection,currentsubsection'
200 self.head_prefix.extend(('\n',
201 '\\%s[]\n' % ( at_begin, ),
202 '{\n',
203 ' \\begin{frame}<beamer>\n',
204 ' \\frametitle{%s}\n' % ( document.settings.toc_title, ),
205 ' \\tableofcontents[%s]\n' % ( toc_option, ),
206 ' \\end{frame}\n',
207 '}\n',
209 self.d_class = DocumentClass()
210 self.subtitle = ''
212 def visit_docinfo(self, node):
213 self.docinfo = []
214 # TODO :Organization: should be handled as institute
216 def depart_docinfo(self, node):
217 self.docinfo = None
218 # Do not output this because relevant data has been gathered
220 def visit_topic(self, node):
221 self.topic_classes = node['classes']
222 if 'contents' in node['classes']:
223 self.body.append( '\n\\begin{frame}\n \\frametitle{%s}\n \\tableofcontents\n\\end{frame}'
224 % ( self.document.settings.toc_title, ))
225 self.topic_classes = []
226 raise nodes.SkipNode
228 def depart_topic(self, node):
229 self.topic_classes = []
230 self.body.append('\n')
232 def visit_title(self, node):
233 """Section and other titles."""
235 if (isinstance(node.parent, nodes.topic)
236 or isinstance(node.parent, nodes.sidebar)
237 or isinstance(node.parent, nodes.admonition)
238 or isinstance(node.parent, nodes.table)
239 or self.section_level == 0):
240 latex2e.LaTeXTranslator.visit_title(self, node)
241 else:
242 self.body.append('\n\n')
243 self.body.append('%' + '_' * 75)
244 self.body.append('\n\n')
245 self.bookmark(node)
247 section_name = self.d_class.section(self.section_level)
248 self.body.append('\\%s{' % (section_name, ))
249 self.context.append('}\n')
251 def visit_subtitle(self, node):
252 if isinstance(node.parent, nodes.document):
253 self.subtitle = self.encode(node.astext())
254 raise nodes.SkipNode
255 else:
256 latex2e.LaTeXTranslator.visit_subtitle(self, node)
258 def depart_section(self, node):
259 self.body.append(self.d_class.section_end(self.section_level))
260 latex2e.LaTeXTranslator.depart_section(self, node)
262 def astext(self):
263 if self.pdfinfo is not None:
264 if self.pdfauthor:
265 self.pdfinfo.append('pdfauthor={%s}' % self.pdfauthor)
266 if self.pdfinfo:
267 pdfinfo = '\\hypersetup{\n' + ',\n'.join(self.pdfinfo) + '\n}\n'
268 else:
269 pdfinfo = ''
270 head = '\\title{%s}\n\\subtitle{%s}\n\\author{%s}\n\\date{%s}\n' % \
271 (self.title, self.subtitle,
272 ' \\and\n'.join(['~\\\\\n'.join(author_lines)
273 for author_lines in self.author_stack]),
274 self.date)
275 return ''.join(self.head_prefix + [head] + self.head + [pdfinfo]
276 + self.body_prefix + self.body + self.body_suffix)
278 # Use an own reader to modify transformations done.
279 class Reader(standalone.Reader):
281 def get_transforms(self):
282 default = standalone.Reader.get_transforms(self)
283 return ([ i
284 for i in default
285 if i is not references.DanglingReferences ]
286 + [ RemoveClassHandout, ])
288 # TODO Must be supported by the right beamer mode (see section 20.2)
289 class RemoveClassHandout(Transform):
292 Remove all elements with a given class attribute.
295 # TODO This should be more generic
296 classToRemove = 'handout'
298 # Must be less than
299 # docutils.transforms.misc.ClassAttribute.default_priority
300 default_priority = 120
302 def apply(self):
303 for node in self.document.traverse(nodes.Element):
304 if node.has_key('classes'):
305 if self.classToRemove in node['classes']:
306 if node.parent:
307 node.parent.remove(node)
309 # TODO \pause needs to be supported as an inline element; the following works
310 # but is ugly::
312 # .. |p| raw:: latex
314 # \pause
316 # It also is problematic because it ends up in an error if ``raw`` is disabled
317 # - even when rendering HTML
319 # S5 solves this problem purely by classes and ::
321 # .. role:: incremental
322 # .. default-role:: incremental
324 # in s5defs.txt. Semantics seems to be a \pause before the marked up text.
325 # Unfortunately then the role is used and things like `*emphasis*` don't work.
327 # If there would be a class ``pause`` implemented by `latexbeamer` then
328 # something like this could work::
330 # .. |p| class:: pause
332 # Pause |p| as much |p| as you like |p|
334 # and where |p| you like |p|
336 # and use *any* |p| other role flexibly.
338 # However, any element needs to be checked for the respective class then. A
339 # construct like ::
341 # .. class:: pause
343 # * First point
345 # * Second point
347 # Unfortunately this doesn't work :-( .
349 # TODO *emphasis* must translate to bold text and **strong emphasis** to \alert
351 # TODO \logo picture must be supported as an option
353 # TODO \appendix must be supported as a directive