diff -r be27ed110b50 -r d8ac696cc51f buildframework/helium/external/python/lib/2.5/Sphinx-0.5.1-py2.5.egg/sphinx/latexwriter.py --- a/buildframework/helium/external/python/lib/2.5/Sphinx-0.5.1-py2.5.egg/sphinx/latexwriter.py Wed Oct 28 14:39:48 2009 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1192 +0,0 @@ -# -*- coding: utf-8 -*- -""" - sphinx.latexwriter - ~~~~~~~~~~~~~~~~~~ - - Custom docutils writer for LaTeX. - - Much of this code is adapted from Dave Kuhlman's "docpy" writer from his - docutils sandbox. - - :copyright: 2007-2008 by Georg Brandl, Dave Kuhlman. - :license: BSD. -""" - -import re -import sys -from os import path - -from docutils import nodes, writers -from docutils.writers.latex2e import Babel - -from sphinx import addnodes -from sphinx import highlighting -from sphinx.locale import admonitionlabels, versionlabels -from sphinx.util import ustrftime -from sphinx.util.texescape import tex_escape_map -from sphinx.util.smartypants import educateQuotesLatex - -HEADER = r'''%% Generated by Sphinx. -\documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(docclass)s} -%(inputenc)s -%(fontenc)s -%(babel)s -%(fontpkg)s -%(fncychap)s -\usepackage{sphinx} -%(preamble)s - -\title{%(title)s} -\date{%(date)s} -\release{%(release)s} -\author{%(author)s} -\newcommand{\sphinxlogo}{%(logo)s} -\renewcommand{\releasename}{%(releasename)s} -%(makeindex)s -%(makemodindex)s -''' - -BEGIN_DOC = r''' -\begin{document} -%(shorthandoff)s -%(maketitle)s -%(tableofcontents)s -''' - -FOOTER = r''' -%(footer)s -\renewcommand{\indexname}{%(modindexname)s} -%(printmodindex)s -\renewcommand{\indexname}{%(indexname)s} -%(printindex)s -\end{document} -''' - - -class LaTeXWriter(writers.Writer): - - supported = ('sphinxlatex',) - - settings_spec = ('LaTeX writer options', '', ( - ('Document name', ['--docname'], {'default': ''}), - ('Document class', ['--docclass'], {'default': 'manual'}), - ('Author', ['--author'], {'default': ''}), - )) - settings_defaults = {} - - output = None - - def __init__(self, builder): - writers.Writer.__init__(self) - self.builder = builder - - def translate(self): - visitor = LaTeXTranslator(self.document, self.builder) - self.document.walkabout(visitor) - self.output = visitor.astext() - - -# Helper classes - -class ExtBabel(Babel): - def get_shorthandoff(self): - shortlang = self.language.split('_')[0] - if shortlang in ('de', 'sl', 'pt', 'es', 'nl', 'pl'): - return '\\shorthandoff{"}' - return '' - - _ISO639_TO_BABEL = Babel._ISO639_TO_BABEL.copy() - _ISO639_TO_BABEL['sl'] = 'slovene' - - -class Table(object): - def __init__(self): - self.col = 0 - self.colcount = 0 - self.colspec = None - self.had_head = False - self.has_verbatim = False - self.caption = None - - -class Desc(object): - def __init__(self, node): - self.env = LaTeXTranslator.desc_map.get(node['desctype'], 'describe') - self.type = self.cls = self.name = self.params = self.annotation = '' - self.count = 0 - - -class LaTeXTranslator(nodes.NodeVisitor): - sectionnames = ["part", "chapter", "section", "subsection", - "subsubsection", "paragraph", "subparagraph"] - - ignore_missing_images = False - - default_elements = { - 'docclass': 'manual', - 'papersize': 'letterpaper', - 'pointsize': '10pt', - 'classoptions': '', - 'inputenc': '\\usepackage[utf8]{inputenc}', - 'fontenc': '\\usepackage[T1]{fontenc}', - 'babel': '\\usepackage{babel}', - 'fontpkg': '\\usepackage{times}', - 'fncychap': '\\usepackage[Bjarne]{fncychap}', - 'preamble': '', - 'title': '', - 'date': '', - 'release': '', - 'author': '', - 'logo': '', - 'releasename': 'Release', - 'makeindex': '\\makeindex', - 'makemodindex': '\\makemodindex', - 'shorthandoff': '', - 'maketitle': '\\maketitle', - 'tableofcontents': '\\tableofcontents', - 'footer': '', - 'printmodindex': '\\printmodindex', - 'printindex': '\\printindex', - } - - def __init__(self, document, builder): - nodes.NodeVisitor.__init__(self, document) - self.builder = builder - self.body = [] - - # sort out some elements - papersize = builder.config.latex_paper_size + 'paper' - if papersize == 'paper': # e.g. command line "-D latex_paper_size=" - papersize = 'letterpaper' - - self.elements = self.default_elements.copy() - self.elements.update({ - 'docclass': document.settings.docclass, - 'papersize': papersize, - 'pointsize': builder.config.latex_font_size, - # if empty, the title is set to the first section title - 'title': document.settings.title, - 'date': ustrftime(builder.config.today_fmt or _('%B %d, %Y')), - 'release': builder.config.release, - 'author': document.settings.author, - 'releasename': _('Release'), - 'preamble': builder.config.latex_preamble, - 'modindexname': _('Module Index'), - 'indexname': _('Index'), - }) - if builder.config.latex_logo: - self.elements['logo'] = '\\includegraphics{%s}\\par' % \ - path.basename(builder.config.latex_logo) - if builder.config.language: - babel = ExtBabel(builder.config.language) - lang = babel.get_language() - if lang: - self.elements['classoptions'] += ',' + babel.get_language() - else: - self.builder.warn('no Babel option known for language %r' % - builder.config.language) - self.elements['shorthandoff'] = babel.get_shorthandoff() - self.elements['fncychap'] = '\\usepackage[Sonny]{fncychap}' - else: - self.elements['classoptions'] += ',english' - if not builder.config.latex_use_modindex: - self.elements['makemodindex'] = '' - self.elements['printmodindex'] = '' - # allow the user to override them all - self.elements.update(builder.config.latex_elements) - - self.highlighter = highlighting.PygmentsBridge( - 'latex', builder.config.pygments_style) - self.context = [] - self.descstack = [] - self.bibitems = [] - self.table = None - self.next_table_colspec = None - self.highlightlang = builder.config.highlight_language - self.highlightlinenothreshold = sys.maxint - self.written_ids = set() - self.footnotestack = [] - if self.elements['docclass'] == 'manual': - if builder.config.latex_use_parts: - self.top_sectionlevel = 0 - else: - self.top_sectionlevel = 1 - else: - self.top_sectionlevel = 2 - self.next_section_target = None - # flags - self.verbatim = None - self.in_title = 0 - self.in_production_list = 0 - self.first_document = 1 - self.this_is_the_title = 1 - self.literal_whitespace = 0 - self.no_contractions = 0 - - def astext(self): - return (HEADER % self.elements + self.highlighter.get_stylesheet() + - u''.join(self.body) + FOOTER % self.elements) - - def visit_document(self, node): - self.footnotestack.append(self.collect_footnotes(node)) - if self.first_document == 1: - # the first document is all the regular content ... - self.body.append(BEGIN_DOC % self.elements) - self.first_document = 0 - elif self.first_document == 0: - # ... and all others are the appendices - self.body.append('\n\\appendix\n') - self.first_document = -1 - # "- 1" because the level is increased before the title is visited - self.sectionlevel = self.top_sectionlevel - 1 - def depart_document(self, node): - if self.bibitems: - widest_label = "" - for bi in self.bibitems: - if len(widest_label) < len(bi[0]): - widest_label = bi[0] - self.body.append('\n\\begin{thebibliography}{%s}\n' % widest_label) - for bi in self.bibitems: - # cite_key: underscores must not be escaped - cite_key = bi[0].replace(r"\_", "_") - self.body.append('\\bibitem[%s]{%s}{%s}\n' % (bi[0], cite_key, bi[1])) - self.body.append('\\end{thebibliography}\n') - self.bibitems = [] - - def visit_start_of_file(self, node): - # This marks the begin of a new file; therefore the current module and - # class must be reset - self.body.append('\n\\resetcurrentobjects\n') - # and also, new footnotes - self.footnotestack.append(self.collect_footnotes(node)) - - def collect_footnotes(self, node): - fnotes = {} - def footnotes_under(n): - if isinstance(n, nodes.footnote): - yield n - else: - for c in n.children: - if isinstance(c, addnodes.start_of_file): - continue - for k in footnotes_under(c): - yield k - for fn in footnotes_under(node): - num = fn.children[0].astext().strip() - fnotes[num] = fn - fn.parent.remove(fn) - return fnotes - - def depart_start_of_file(self, node): - self.footnotestack.pop() - - def visit_highlightlang(self, node): - self.highlightlang = node['lang'] - self.highlightlinenothreshold = node['linenothreshold'] - raise nodes.SkipNode - - def visit_section(self, node): - if not self.this_is_the_title: - self.sectionlevel += 1 - self.body.append('\n\n') - if self.next_section_target: - self.body.append(r'\hypertarget{%s}{}' % self.next_section_target) - self.next_section_target = None - #if node.get('ids'): - # for id in node['ids']: - # if id not in self.written_ids: - # self.body.append(r'\hypertarget{%s}{}' % id) - # self.written_ids.add(id) - def depart_section(self, node): - self.sectionlevel = max(self.sectionlevel - 1, self.top_sectionlevel - 1) - - def visit_problematic(self, node): - self.body.append(r'{\color{red}\bfseries{}') - def depart_problematic(self, node): - self.body.append('}') - - def visit_topic(self, node): - self.body.append('\\setbox0\\vbox{\n' - '\\begin{minipage}{0.95\\textwidth}\n') - def depart_topic(self, node): - self.body.append('\\end{minipage}}\n' - '\\begin{center}\\setlength{\\fboxsep}{5pt}' - '\\shadowbox{\\box0}\\end{center}\n') - visit_sidebar = visit_topic - depart_sidebar = depart_topic - - def visit_glossary(self, node): - pass - def depart_glossary(self, node): - pass - - def visit_productionlist(self, node): - self.body.append('\n\n\\begin{productionlist}\n') - self.in_production_list = 1 - def depart_productionlist(self, node): - self.body.append('\\end{productionlist}\n\n') - self.in_production_list = 0 - - def visit_production(self, node): - if node['tokenname']: - self.body.append('\\production{%s}{' % self.encode(node['tokenname'])) - else: - self.body.append('\\productioncont{') - def depart_production(self, node): - self.body.append('}\n') - - def visit_transition(self, node): - self.body.append('\n\n\\bigskip\\hrule{}\\bigskip\n\n') - def depart_transition(self, node): - pass - - def visit_title(self, node): - parent = node.parent - if isinstance(parent, addnodes.seealso): - # the environment already handles this - raise nodes.SkipNode - elif self.this_is_the_title: - if len(node.children) != 1 and not isinstance(node.children[0], nodes.Text): - self.builder.warn('document title is not a single Text node') - if not self.elements['title']: - # text needs to be escaped since it is inserted into - # the output literally - self.elements['title'] = node.astext().translate(tex_escape_map) - self.this_is_the_title = 0 - raise nodes.SkipNode - elif isinstance(parent, nodes.section): - try: - self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel]) - except IndexError: - from sphinx.application import SphinxError - raise SphinxError('too many nesting section levels for LaTeX, ' - 'at heading: %s' % node.astext()) - self.context.append('}\n') - elif isinstance(parent, (nodes.topic, nodes.sidebar)): - self.body.append(r'\textbf{') - self.context.append('}\n\n\medskip\n\n') - elif isinstance(parent, nodes.Admonition): - self.body.append('{') - self.context.append('}\n') - elif isinstance(parent, nodes.table): - self.table.caption = self.encode(node.astext()) - raise nodes.SkipNode - else: - self.builder.warn('encountered title node not in section, topic, ' - 'table, admonition or sidebar') - self.body.append('\\textbf{') - self.context.append('}\n') - self.in_title = 1 - def depart_title(self, node): - self.in_title = 0 - self.body.append(self.context.pop()) - - def visit_subtitle(self, node): - if isinstance(node.parent, nodes.sidebar): - self.body.append('~\\\\\n\\textbf{') - self.context.append('}\n\\smallskip\n') - else: - self.context.append('') - def depart_subtitle(self, node): - self.body.append(self.context.pop()) - - desc_map = { - 'function' : 'funcdesc', - 'class': 'classdesc', - 'method': 'methoddesc', - 'staticmethod': 'staticmethoddesc', - 'exception': 'excdesc', - 'data': 'datadesc', - 'attribute': 'memberdesc', - 'opcode': 'opcodedesc', - - 'cfunction': 'cfuncdesc', - 'cmember': 'cmemberdesc', - 'cmacro': 'csimplemacrodesc', - 'ctype': 'ctypedesc', - 'cvar': 'cvardesc', - - 'describe': 'describe', - # and all others are 'describe' too - } - - def visit_desc(self, node): - self.descstack.append(Desc(node)) - def depart_desc(self, node): - d = self.descstack.pop() - self.body.append("\\end{%s}\n" % d.env) - - def visit_desc_signature(self, node): - d = self.descstack[-1] - # reset these for every signature - d.type = d.cls = d.name = d.params = '' - def depart_desc_signature(self, node): - d = self.descstack[-1] - d.cls = d.cls.rstrip('.') - if node.parent['desctype'] != 'describe' and node['ids']: - hyper = '\\hypertarget{%s}{}' % node['ids'][0] - else: - hyper = '' - if d.count == 0: - t1 = "\n\n%s\\begin{%s}" % (hyper, d.env) - else: - t1 = "\n%s\\%sline" % (hyper, d.env[:-4]) - d.count += 1 - if d.env in ('funcdesc', 'classdesc', 'excclassdesc'): - t2 = "{%s}{%s}" % (d.name, d.params) - elif d.env in ('datadesc', 'excdesc', 'csimplemacrodesc'): - t2 = "{%s}" % (d.name) - elif d.env in ('methoddesc', 'staticmethoddesc'): - if d.cls: - t2 = "[%s]{%s}{%s}" % (d.cls, d.name, d.params) - else: - t2 = "{%s}{%s}" % (d.name, d.params) - elif d.env == 'memberdesc': - if d.cls: - t2 = "[%s]{%s}" % (d.cls, d.name) - else: - t2 = "{%s}" % d.name - elif d.env == 'cfuncdesc': - if d.cls: - # C++ class names - d.name = '%s::%s' % (d.cls, d.name) - t2 = "{%s}{%s}{%s}" % (d.type, d.name, d.params) - elif d.env == 'cmemberdesc': - try: - type, container = d.type.rsplit(' ', 1) - container = container.rstrip('.') - except ValueError: - container = '' - type = d.type - t2 = "{%s}{%s}{%s}" % (container, type, d.name) - elif d.env == 'cvardesc': - t2 = "{%s}{%s}" % (d.type, d.name) - elif d.env == 'ctypedesc': - t2 = "{%s}" % (d.name) - elif d.env == 'opcodedesc': - t2 = "{%s}{%s}" % (d.name, d.params) - elif d.env == 'describe': - t2 = "{%s}" % d.name - self.body.append(t1 + t2) - - def visit_desc_type(self, node): - d = self.descstack[-1] - if d.env == 'describe': - d.name += self.encode(node.astext()) - else: - self.descstack[-1].type = self.encode(node.astext().strip()) - raise nodes.SkipNode - - def visit_desc_name(self, node): - d = self.descstack[-1] - if d.env == 'describe': - d.name += self.encode(node.astext()) - else: - self.descstack[-1].name = self.encode(node.astext().strip()) - raise nodes.SkipNode - - def visit_desc_addname(self, node): - d = self.descstack[-1] - if d.env == 'describe': - d.name += self.encode(node.astext()) - else: - self.descstack[-1].cls = self.encode(node.astext().strip()) - raise nodes.SkipNode - - def visit_desc_parameterlist(self, node): - d = self.descstack[-1] - if d.env == 'describe': - d.name += self.encode(node.astext()) - else: - self.descstack[-1].params = self.encode(node.astext().strip()) - raise nodes.SkipNode - - def visit_desc_annotation(self, node): - d = self.descstack[-1] - if d.env == 'describe': - d.name += self.encode(node.astext()) - else: - self.descstack[-1].annotation = self.encode(node.astext().strip()) - raise nodes.SkipNode - - def visit_refcount(self, node): - self.body.append("\\emph{") - def depart_refcount(self, node): - self.body.append("}\\\\") - - def visit_desc_content(self, node): - if node.children and not isinstance(node.children[0], nodes.paragraph): - # avoid empty desc environment which causes a formatting bug - self.body.append('~') - def depart_desc_content(self, node): - pass - - def visit_seealso(self, node): - self.body.append("\n\n\\strong{%s:}\n\n" % admonitionlabels['seealso']) - def depart_seealso(self, node): - self.body.append("\n\n") - - def visit_rubric(self, node): - if len(node.children) == 1 and node.children[0].astext() == 'Footnotes': - raise nodes.SkipNode - self.body.append('\\paragraph{') - self.context.append('}\n') - def depart_rubric(self, node): - self.body.append(self.context.pop()) - - def visit_footnote(self, node): - pass - def depart_footnote(self, node): - pass - - def visit_label(self, node): - if isinstance(node.parent, nodes.citation): - self.bibitems[-1][0] = node.astext() - raise nodes.SkipNode - - def visit_tabular_col_spec(self, node): - self.next_table_colspec = node['spec'] - raise nodes.SkipNode - - def visit_table(self, node): - if self.table: - raise NotImplementedError('Nested tables are not supported.') - self.table = Table() - self.tablebody = [] - # Redirect body output until table is finished. - self._body = self.body - self.body = self.tablebody - def depart_table(self, node): - self.body = self._body - if self.table.caption is not None: - self.body.append('\n\\begin{threeparttable}\n' - '\\caption{%s}\n' % self.table.caption) - if self.table.has_verbatim: - self.body.append('\n\\begin{tabular}') - else: - self.body.append('\n\\begin{tabulary}{\\textwidth}') - if self.table.colspec: - self.body.append(self.table.colspec) - else: - if self.table.has_verbatim: - colwidth = 0.95 / self.table.colcount - colspec = ('p{%.3f\\textwidth}|' % colwidth) * self.table.colcount - self.body.append('{|' + colspec + '}\n') - else: - self.body.append('{|' + ('L|' * self.table.colcount) + '}\n') - self.body.extend(self.tablebody) - if self.table.has_verbatim: - self.body.append('\\end{tabular}\n\n') - else: - self.body.append('\\end{tabulary}\n\n') - if self.table.caption is not None: - self.body.append('\\end{threeparttable}\n\n') - self.table = None - self.tablebody = None - - def visit_colspec(self, node): - self.table.colcount += 1 - def depart_colspec(self, node): - pass - - def visit_tgroup(self, node): - pass - def depart_tgroup(self, node): - pass - - def visit_thead(self, node): - if self.next_table_colspec: - self.table.colspec = '{%s}\n' % self.next_table_colspec - self.next_table_colspec = None - self.body.append('\\hline\n') - self.table.had_head = True - def depart_thead(self, node): - self.body.append('\\hline\n') - - def visit_tbody(self, node): - if not self.table.had_head: - self.visit_thead(node) - def depart_tbody(self, node): - self.body.append('\\hline\n') - - def visit_row(self, node): - self.table.col = 0 - def depart_row(self, node): - self.body.append('\\\\\n') - - def visit_entry(self, node): - if node.has_key('morerows') or node.has_key('morecols'): - raise NotImplementedError('Column or row spanning cells are ' - 'not implemented.') - if self.table.col > 0: - self.body.append(' & ') - self.table.col += 1 - if isinstance(node.parent.parent, nodes.thead): - self.body.append('\\textbf{') - self.context.append('}') - else: - self.context.append('') - def depart_entry(self, node): - self.body.append(self.context.pop()) # header - - def visit_acks(self, node): - # this is a list in the source, but should be rendered as a - # comma-separated list here - self.body.append('\n\n') - self.body.append(', '.join(n.astext() for n in node.children[0].children) + '.') - self.body.append('\n\n') - raise nodes.SkipNode - - def visit_bullet_list(self, node): - self.body.append('\\begin{itemize}\n' ) - def depart_bullet_list(self, node): - self.body.append('\\end{itemize}\n' ) - - def visit_enumerated_list(self, node): - self.body.append('\\begin{enumerate}\n' ) - def depart_enumerated_list(self, node): - self.body.append('\\end{enumerate}\n' ) - - def visit_list_item(self, node): - # Append "{}" in case the next character is "[", which would break - # LaTeX's list environment (no numbering and the "[" is not printed). - self.body.append(r'\item {} ') - def depart_list_item(self, node): - self.body.append('\n') - - def visit_definition_list(self, node): - self.body.append('\\begin{description}\n') - def depart_definition_list(self, node): - self.body.append('\\end{description}\n') - - def visit_definition_list_item(self, node): - pass - def depart_definition_list_item(self, node): - pass - - def visit_term(self, node): - ctx = ']' - if node.has_key('ids') and node['ids']: - ctx += '\\hypertarget{%s}{}' % node['ids'][0] - self.body.append('\\item[') - self.context.append(ctx) - def depart_term(self, node): - self.body.append(self.context.pop()) - - def visit_classifier(self, node): - self.body.append('{[}') - def depart_classifier(self, node): - self.body.append('{]}') - - def visit_definition(self, node): - pass - def depart_definition(self, node): - self.body.append('\n') - - def visit_field_list(self, node): - self.body.append('\\begin{quote}\\begin{description}\n') - def depart_field_list(self, node): - self.body.append('\\end{description}\\end{quote}\n') - - def visit_field(self, node): - pass - def depart_field(self, node): - pass - - visit_field_name = visit_term - depart_field_name = depart_term - - visit_field_body = visit_definition - depart_field_body = depart_definition - - def visit_paragraph(self, node): - self.body.append('\n') - def depart_paragraph(self, node): - self.body.append('\n') - - def visit_centered(self, node): - self.body.append('\n\\begin{centering}') - def depart_centered(self, node): - self.body.append('\n\\end{centering}') - - def visit_module(self, node): - modname = node['modname'] - self.body.append('\n\\declaremodule[%s]{}{%s}' % (modname.replace('_', ''), - self.encode(modname))) - self.body.append('\n\\modulesynopsis{%s}' % self.encode(node['synopsis'])) - if node.has_key('platform'): - self.body.append('\\platform{%s}' % self.encode(node['platform'])) - def depart_module(self, node): - pass - - def latex_image_length(self, width_str): - match = re.match('(\d*\.?\d*)\s*(\S*)', width_str) - if not match: - # fallback - return width_str - res = width_str - amount, unit = match.groups()[:2] - if not unit or unit == "px": - # pixels: let LaTeX alone - return None - elif unit == "%": - res = "%.3f\\linewidth" % (float(amount) / 100.0) - return res - - def visit_image(self, node): - attrs = node.attributes - pre = [] # in reverse order - post = [] - include_graphics_options = [] - inline = isinstance(node.parent, nodes.TextElement) - if attrs.has_key('scale'): - # Could also be done with ``scale`` option to - # ``\includegraphics``; doing it this way for consistency. - pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,)) - post.append('}') - if attrs.has_key('width'): - w = self.latex_image_length(attrs['width']) - if w: - include_graphics_options.append('width=%s' % w) - if attrs.has_key('height'): - h = self.latex_image_length(attrs['height']) - if h: - include_graphics_options.append('height=%s' % h) - if attrs.has_key('align'): - align_prepost = { - # By default latex aligns the top of an image. - (1, 'top'): ('', ''), - (1, 'middle'): ('\\raisebox{-0.5\\height}{', '}'), - (1, 'bottom'): ('\\raisebox{-\\height}{', '}'), - (0, 'center'): ('{\\hfill', '\\hfill}'), - # These 2 don't exactly do the right thing. The image should - # be floated alongside the paragraph. See - # http://www.w3.org/TR/html4/struct/objects.html#adef-align-IMG - (0, 'left'): ('{', '\\hfill}'), - (0, 'right'): ('{\\hfill', '}'),} - try: - pre.append(align_prepost[inline, attrs['align']][0]) - post.append(align_prepost[inline, attrs['align']][1]) - except KeyError: - pass # XXX complain here? - if not inline: - pre.append('\n') - post.append('\n') - pre.reverse() - if node['uri'] in self.builder.images: - uri = self.builder.images[node['uri']] - else: - # missing image! - if self.ignore_missing_images: - return - uri = node['uri'] - if uri.find('://') != -1: - # ignore remote images - return - self.body.extend(pre) - options = '' - if include_graphics_options: - options = '[%s]' % ','.join(include_graphics_options) - self.body.append('\\includegraphics%s{%s}' % (options, uri)) - self.body.extend(post) - def depart_image(self, node): - pass - - def visit_figure(self, node): - if (not node.attributes.has_key('align') or - node.attributes['align'] == 'center'): - # centering does not add vertical space like center. - align = '\n\\centering' - align_end = '' - else: - # TODO non vertical space for other alignments. - align = '\\begin{flush%s}' % node.attributes['align'] - align_end = '\\end{flush%s}' % node.attributes['align'] - self.body.append('\\begin{figure}[htbp]%s\n' % align) - self.context.append('%s\\end{figure}\n' % align_end) - def depart_figure(self, node): - self.body.append(self.context.pop()) - - def visit_caption(self, node): - self.body.append('\\caption{') - def depart_caption(self, node): - self.body.append('}') - - def visit_legend(self, node): - self.body.append('{\\small ') - def depart_legend(self, node): - self.body.append('}') - - def visit_admonition(self, node): - self.body.append('\n\\begin{notice}{note}') - def depart_admonition(self, node): - self.body.append('\\end{notice}\n') - - def _make_visit_admonition(name): - def visit_admonition(self, node): - self.body.append('\n\\begin{notice}{%s}{%s:}' % - (name, admonitionlabels[name])) - return visit_admonition - def _depart_named_admonition(self, node): - self.body.append('\\end{notice}\n') - - visit_attention = _make_visit_admonition('attention') - depart_attention = _depart_named_admonition - visit_caution = _make_visit_admonition('caution') - depart_caution = _depart_named_admonition - visit_danger = _make_visit_admonition('danger') - depart_danger = _depart_named_admonition - visit_error = _make_visit_admonition('error') - depart_error = _depart_named_admonition - visit_hint = _make_visit_admonition('hint') - depart_hint = _depart_named_admonition - visit_important = _make_visit_admonition('important') - depart_important = _depart_named_admonition - visit_note = _make_visit_admonition('note') - depart_note = _depart_named_admonition - visit_tip = _make_visit_admonition('tip') - depart_tip = _depart_named_admonition - visit_warning = _make_visit_admonition('warning') - depart_warning = _depart_named_admonition - - def visit_versionmodified(self, node): - intro = versionlabels[node['type']] % node['version'] - if node.children: - intro += ': ' - else: - intro += '.' - self.body.append(intro) - def depart_versionmodified(self, node): - pass - - def visit_target(self, node): - def add_target(id): - # indexing uses standard LaTeX index markup, so the targets - # will be generated differently - if not id.startswith('index-'): - self.body.append(r'\hypertarget{%s}{}' % id) - - if node.has_key('refid') and node['refid'] not in self.written_ids: - parindex = node.parent.index(node) - try: - next = node.parent[parindex+1] - if isinstance(next, nodes.section): - self.next_section_target = node['refid'] - return - except IndexError: - pass - add_target(node['refid']) - self.written_ids.add(node['refid']) - def depart_target(self, node): - pass - - def visit_attribution(self, node): - self.body.append('\n\\begin{flushright}\n') - self.body.append('---') - def depart_attribution(self, node): - self.body.append('\n\\end{flushright}\n') - - def visit_index(self, node, scre=re.compile(r';\s*')): - entries = node['entries'] - for type, string, tid, _ in entries: - if type == 'single': - self.body.append(r'\index{%s}' % scre.sub('!', self.encode(string))) - elif type == 'pair': - parts = tuple(self.encode(x.strip()) for x in string.split(';', 1)) - try: - self.body.append(r'\indexii{%s}{%s}' % parts) - except TypeError: - self.builder.warn('invalid pair index entry %r' % string) - elif type == 'triple': - parts = tuple(self.encode(x.strip()) for x in string.split(';', 2)) - try: - self.body.append(r'\indexiii{%s}{%s}{%s}' % parts) - except TypeError: - self.builder.warn('invalid triple index entry %r' % string) - else: - self.builder.warn('unknown index entry type %s found' % type) - raise nodes.SkipNode - - def visit_raw(self, node): - if 'latex' in node.get('format', '').split(): - self.body.append(node.astext()) - raise nodes.SkipNode - - def visit_reference(self, node): - uri = node.get('refuri', '') - if self.in_title or not uri: - self.context.append('') - elif uri.startswith('mailto:') or uri.startswith('http:') or \ - uri.startswith('https:') or uri.startswith('ftp:'): - self.body.append('\\href{%s}{' % self.encode(uri)) - self.context.append('}') - elif uri.startswith('#'): - self.body.append('\\hyperlink{%s}{' % uri[1:]) - self.context.append('}') - elif uri.startswith('@token'): - if self.in_production_list: - self.body.append('\\token{') - else: - self.body.append('\\grammartoken{') - self.context.append('}') - else: - self.builder.warn('unusable reference target found: %s' % uri) - self.context.append('') - def depart_reference(self, node): - self.body.append(self.context.pop()) - - def visit_pending_xref(self, node): - pass - def depart_pending_xref(self, node): - pass - - def visit_emphasis(self, node): - self.body.append(r'\emph{') - def depart_emphasis(self, node): - self.body.append('}') - - def visit_literal_emphasis(self, node): - self.body.append(r'\emph{\texttt{') - self.no_contractions += 1 - def depart_literal_emphasis(self, node): - self.body.append('}}') - self.no_contractions -= 1 - - def visit_strong(self, node): - self.body.append(r'\textbf{') - def depart_strong(self, node): - self.body.append('}') - - def visit_title_reference(self, node): - self.body.append(r'\emph{') - def depart_title_reference(self, node): - self.body.append('}') - - def visit_citation(self, node): - # TODO maybe use cite bibitems - self.bibitems.append(['', '']) - self.context.append(len(self.body)) - def depart_citation(self, node): - size = self.context.pop() - text = ''.join(self.body[size:]) - del self.body[size:] - self.bibitems[-1][1] = text - - def visit_citation_reference(self, node): - citeid = node.astext() - self.body.append('\\cite{%s}' % citeid) - raise nodes.SkipNode - - def visit_literal(self, node): - content = self.encode(node.astext().strip()) - if self.in_title: - self.body.append(r'\texttt{%s}' % content) - elif node.has_key('role') and node['role'] == 'samp': - self.body.append(r'\samp{%s}' % content) - else: - self.body.append(r'\code{%s}' % content) - raise nodes.SkipNode - - def visit_footnote_reference(self, node): - num = node.astext().strip() - try: - fn = self.footnotestack[-1][num] - except (KeyError, IndexError): - raise nodes.SkipNode - self.body.append('\\footnote{') - fn.walkabout(self) - raise nodes.SkipChildren - def depart_footnote_reference(self, node): - self.body.append('}') - - def visit_literal_block(self, node): - self.verbatim = '' - def depart_literal_block(self, node): - code = self.verbatim.rstrip('\n') - lang = self.highlightlang - linenos = code.count('\n') >= self.highlightlinenothreshold - 1 - if node.has_key('language'): - # code-block directives - lang = node['language'] - if node.has_key('linenos'): - linenos = node['linenos'] - hlcode = self.highlighter.highlight_block(code, lang, linenos) - # workaround for Unicode issue - hlcode = hlcode.replace(u'€', u'@texteuro[]') - # must use original Verbatim environment and "tabular" environment - if self.table: - hlcode = hlcode.replace('\\begin{Verbatim}', - '\\begin{OriginalVerbatim}') - self.table.has_verbatim = True - # get consistent trailer - hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim} - hlcode = hlcode.rstrip() + '\n' - self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' % - (self.table and 'Original' or '')) - self.verbatim = None - visit_doctest_block = visit_literal_block - depart_doctest_block = depart_literal_block - - def visit_line_block(self, node): - """line-block: - * whitespace (including linebreaks) is significant - * inline markup is supported. - * serif typeface - """ - self.body.append('{\\raggedright{}') - self.literal_whitespace = 1 - def depart_line_block(self, node): - self.literal_whitespace = 0 - # remove the last \\ - del self.body[-1] - self.body.append('}\n') - - def visit_line(self, node): - self._line_start = len(self.body) - def depart_line(self, node): - if self._line_start == len(self.body): - # no output in this line -- add a nonbreaking space, else the - # \\ command will give an error - self.body.append('~') - if self.table is not None: - self.body.append('\\newline\n') - else: - self.body.append('\\\\\n') - - def visit_block_quote(self, node): - # If the block quote contains a single object and that object - # is a list, then generate a list not a block quote. - # This lets us indent lists. - done = 0 - if len(node.children) == 1: - child = node.children[0] - if isinstance(child, nodes.bullet_list) or \ - isinstance(child, nodes.enumerated_list): - done = 1 - if not done: - self.body.append('\\begin{quote}\n') - def depart_block_quote(self, node): - done = 0 - if len(node.children) == 1: - child = node.children[0] - if isinstance(child, nodes.bullet_list) or \ - isinstance(child, nodes.enumerated_list): - done = 1 - if not done: - self.body.append('\\end{quote}\n') - - # option node handling copied from docutils' latex writer - - def visit_option(self, node): - if self.context[-1]: - # this is not the first option - self.body.append(', ') - def depart_option(self, node): - # flag that the first option is done. - self.context[-1] += 1 - - def visit_option_argument(self, node): - """The delimiter betweeen an option and its argument.""" - self.body.append(node.get('delimiter', ' ')) - def depart_option_argument(self, node): - pass - - def visit_option_group(self, node): - self.body.append('\\item [') - # flag for first option - self.context.append(0) - def depart_option_group(self, node): - self.context.pop() # the flag - self.body.append('] ') - - def visit_option_list(self, node): - self.body.append('\\begin{optionlist}{3cm}\n') - def depart_option_list(self, node): - self.body.append('\\end{optionlist}\n') - - def visit_option_list_item(self, node): - pass - def depart_option_list_item(self, node): - pass - - def visit_option_string(self, node): - ostring = node.astext() - self.body.append(self.encode(ostring.replace('--', u'-{-}'))) - raise nodes.SkipNode - - def visit_description(self, node): - self.body.append( ' ' ) - def depart_description(self, node): - pass - - def visit_superscript(self, node): - self.body.append('$^{\\text{') - def depart_superscript(self, node): - self.body.append('}}$') - - def visit_subscript(self, node): - self.body.append('$_{\\text{') - def depart_subscript(self, node): - self.body.append('}}$') - - def visit_substitution_definition(self, node): - raise nodes.SkipNode - - def visit_substitution_reference(self, node): - raise nodes.SkipNode - - def visit_generated(self, node): - pass - def depart_generated(self, node): - pass - - def visit_compound(self, node): - pass - def depart_compound(self, node): - pass - - def visit_container(self, node): - pass - def depart_container(self, node): - pass - - def visit_decoration(self, node): - pass - def depart_decoration(self, node): - pass - - # text handling - - def encode(self, text): - text = unicode(text).translate(tex_escape_map) - if self.literal_whitespace: - # Insert a blank before the newline, to avoid - # ! LaTeX Error: There's no line here to end. - text = text.replace(u'\n', u'~\\\\\n').replace(u' ', u'~') - if self.no_contractions: - text = text.replace('--', u'-{-}') - return text - - def visit_Text(self, node): - if self.verbatim is not None: - self.verbatim += node.astext() - else: - text = self.encode(node.astext()) - self.body.append(educateQuotesLatex(text)) - def depart_Text(self, node): - pass - - def visit_comment(self, node): - raise nodes.SkipNode - - def visit_meta(self, node): - # only valid for HTML - raise nodes.SkipNode - - def visit_system_message(self, node): - pass - def depart_system_message(self, node): - self.body.append('\n') - - def unknown_visit(self, node): - raise NotImplementedError('Unknown node: ' + node.__class__.__name__)