Commit c283ff8e authored by Andreas Jung's avatar Andreas Jung

update to docutils 0.3.9

parent ac405197
# Author: Ivan Vilata i Balaguer
# Contact: ivan@selidor.net
# Revision: $Revision: 3276 $
# Date: $Date: 2005-04-30 13:34:52 +0200 (Sat, 30 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
# translated for each language: one in docutils/languages, the other in
# docutils/parsers/rst/languages.
"""
Catalan-language mappings for language-dependent features of Docutils.
"""
__docformat__ = 'reStructuredText'
labels = {
# fixed: language-dependent
'author': u'Autor',
'authors': u'Autors',
'organization': u'Organitzaci\u00F3',
'address': u'Adre\u00E7a',
'contact': u'Contacte',
'version': u'Versi\u00F3',
'revision': u'Revisi\u00F3',
'status': u'Estat',
'date': u'Data',
'copyright': u'Copyright',
'dedication': u'Dedicat\u00F2ria',
'abstract': u'Resum',
'attention': u'Atenci\u00F3!',
'caution': u'Compte!',
'danger': u'PERILL!',
'error': u'Error',
'hint': u'Suggeriment',
'important': u'Important',
'note': u'Nota',
'tip': u'Consell',
'warning': u'Av\u00EDs',
'contents': u'Contingut'}
"""Mapping of node class name to label text."""
bibliographic_fields = {
# language-dependent: fixed
u'autor': 'author',
u'autors': 'authors',
u'organitzaci\u00F3': 'organization',
u'adre\u00E7a': 'address',
u'contacte': 'contact',
u'versi\u00F3': 'version',
u'revisi\u00F3': 'revision',
u'estat': 'status',
u'data': 'date',
u'copyright': 'copyright',
u'dedicat\u00F2ria': 'dedication',
u'resum': 'abstract'}
"""Catalan (lowcased) to canonical name mapping for bibliographic fields."""
author_separators = [';', ',']
"""List of separator strings for the 'Authors' bibliographic field. Tried in
order."""
# Author: Martijn Pieters
# Contact: mjpieters@users.sourceforge.net
# Revision: $Revision: 3058 $
# Date: $Date: 2005-03-18 21:09:22 +0100 (Fri, 18 Mar 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
# translated for each language: one in docutils/languages, the other in
# docutils/parsers/rst/languages.
"""
Dutch-language mappings for language-dependent features of Docutils.
"""
__docformat__ = 'reStructuredText'
labels = {
# fixed: language-dependent
'author': 'Auteur',
'authors': 'Auteurs',
'organization': 'Organisatie',
'address': 'Adres',
'contact': 'Contact',
'version': 'Versie',
'revision': 'Revisie',
'status': 'Status',
'date': 'Datum',
'copyright': 'Copyright',
'dedication': 'Toewijding',
'abstract': 'Samenvatting',
'attention': 'Attentie!',
'caution': 'Let op!',
'danger': '!GEVAAR!',
'error': 'Fout',
'hint': 'Hint',
'important': 'Belangrijk',
'note': 'Opmerking',
'tip': 'Tip',
'warning': 'Waarschuwing',
'contents': 'Inhoud'}
"""Mapping of node class name to label text."""
bibliographic_fields = {
# language-dependent: fixed
'auteur': 'author',
'auteurs': 'authors',
'organisatie': 'organization',
'adres': 'address',
'contact': 'contact',
'versie': 'version',
'revisie': 'revision',
'status': 'status',
'datum': 'date',
'copyright': 'copyright',
'toewijding': 'dedication',
'samenvatting': 'abstract'}
"""Dutch (lowcased) to canonical name mapping for bibliographic fields."""
author_separators = [';', ',']
"""List of separator strings for the 'Authors' bibliographic field. Tried in
order."""
# Author: Ivan Vilata i Balaguer
# Contact: ivan@selidor.net
# Revision: $Revision: 3276 $
# Date: $Date: 2005-04-30 13:34:52 +0200 (Sat, 30 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
# translated for each language: one in docutils/languages, the other in
# docutils/parsers/rst/languages.
"""
Catalan-language mappings for language-dependent features of
reStructuredText.
"""
__docformat__ = 'reStructuredText'
directives = {
# language-dependent: fixed
u'atenci\u00F3': 'attention',
u'compte': 'caution',
u'perill': 'danger',
u'error': 'error',
u'suggeriment': 'hint',
u'important': 'important',
u'nota': 'note',
u'consell': 'tip',
u'av\u00EDs': 'warning',
u'advertiment': 'admonition',
u'nota-al-marge': 'sidebar',
u'nota-marge': 'sidebar',
u'tema': 'topic',
u'bloc-de-l\u00EDnies': 'line-block',
u'bloc-l\u00EDnies': 'line-block',
u'literal-analitzat': 'parsed-literal',
u'r\u00FAbrica': 'rubric',
u'ep\u00EDgraf': 'epigraph',
u'sumari': 'highlights',
u'cita-destacada': 'pull-quote',
u'compost': 'compound',
#'questions': 'questions',
u'taula': 'table',
u'taula-csv': 'csv-table',
u'taula-llista': 'list-table',
#'qa': 'questions',
#'faq': 'questions',
u'meta': 'meta',
#'imagemap': 'imagemap',
u'imatge': 'image',
u'figura': 'figure',
u'inclou': 'include',
u'incloure': 'include',
u'cru': 'raw',
u'reempla\u00E7a': 'replace',
u'reempla\u00E7ar': 'replace',
u'unicode': 'unicode',
u'classe': 'class',
u'rol': 'role',
u'contingut': 'contents',
u'numsec': 'sectnum',
u'numeraci\u00F3-de-seccions': 'sectnum',
u'numeraci\u00F3-seccions': 'sectnum',
u'cap\u00E7alera': 'header',
u'peu-de-p\u00E0gina': 'footer',
u'peu-p\u00E0gina': 'footer',
#'footnotes': 'footnotes',
#'citations': 'citations',
u'notes-amb-destinacions': 'target-notes',
u'notes-destinacions': 'target-notes',
u'directiva-de-prova-de-restructuredtext': 'restructuredtext-test-directive'}
"""Catalan name to registered (in directives/__init__.py) directive name
mapping."""
roles = {
# language-dependent: fixed
u'abreviatura': 'abbreviation',
u'abreviaci\u00F3': 'abbreviation',
u'abrev': 'abbreviation',
u'ab': 'abbreviation',
u'acr\u00F2nim': 'acronym',
u'ac': 'acronym',
u'\u00EDndex': 'index',
u'i': 'index',
u'sub\u00EDndex': 'subscript',
u'sub': 'subscript',
u'super\u00EDndex': 'superscript',
u'sup': 'superscript',
u'refer\u00E8ncia-a-t\u00EDtol': 'title-reference',
u'refer\u00E8ncia-t\u00EDtol': 'title-reference',
u't\u00EDtol': 'title-reference',
u't': 'title-reference',
u'refer\u00E8ncia-a-pep': 'pep-reference',
u'refer\u00E8ncia-pep': 'pep-reference',
u'pep': 'pep-reference',
u'refer\u00E8ncia-a-rfc': 'rfc-reference',
u'refer\u00E8ncia-rfc': 'rfc-reference',
u'rfc': 'rfc-reference',
u'\u00E8mfasi': 'emphasis',
u'destacat': 'strong',
u'literal': 'literal',
u'refer\u00E8ncia-amb-nom': 'named-reference',
u'refer\u00E8ncia-nom': 'named-reference',
u'refer\u00E8ncia-an\u00F2nima': 'anonymous-reference',
u'refer\u00E8ncia-a-nota-al-peu': 'footnote-reference',
u'refer\u00E8ncia-nota-al-peu': 'footnote-reference',
u'refer\u00E8ncia-a-cita': 'citation-reference',
u'refer\u00E8ncia-cita': 'citation-reference',
u'refer\u00E8ncia-a-substituci\u00F3': 'substitution-reference',
u'refer\u00E8ncia-substituci\u00F3': 'substitution-reference',
u'destinaci\u00F3': 'target',
u'refer\u00E8ncia-a-uri': 'uri-reference',
u'refer\u00E8ncia-uri': 'uri-reference',
u'uri': 'uri-reference',
u'url': 'uri-reference',
u'cru': 'raw',}
"""Mapping of Catalan role names to canonical role names for interpreted text.
"""
# Author: Martijn Pieters
# Contact: mjpieters@users.sourceforge.net
# Revision: $Revision: 3184 $
# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
# translated for each language: one in docutils/languages, the other in
# docutils/parsers/rst/languages.
"""
Dutch-language mappings for language-dependent features of
reStructuredText.
"""
__docformat__ = 'reStructuredText'
directives = {
# language-dependent: fixed
'attentie': 'attention',
'let-op': 'caution',
'gevaar': 'danger',
'fout': 'error',
'hint': 'hint',
'belangrijk': 'important',
'opmerking': 'note',
'tip': 'tip',
'waarschuwing': 'warning',
'aanmaning': 'admonition',
'katern': 'sidebar',
'onderwerp': 'topic',
'lijn-blok': 'line-block',
'letterlijk-ontleed': 'parsed-literal',
'rubriek': 'rubric',
'opschrift': 'epigraph',
'hoogtepunten': 'highlights',
'pull-quote': 'pull-quote', # Dutch printers use the english term
'samenstelling': 'compound',
'verbinding': 'compound',
#'vragen': 'questions',
'tabel': 'table',
'csv-tabel': 'csv-table',
'lijst-tabel': 'list-table',
#'veelgestelde-vragen': 'questions',
'meta': 'meta',
#'imagemap': 'imagemap',
'beeld': 'image',
'figuur': 'figure',
'opnemen': 'include',
'onbewerkt': 'raw',
'vervang': 'replace',
'vervanging': 'replace',
'unicode': 'unicode',
'klasse': 'class',
'rol': 'role',
'inhoud': 'contents',
'sectnum': 'sectnum',
'sectie-nummering': 'sectnum',
'hoofdstuk-nummering': 'sectnum',
u'header (translation required)': 'header',
u'footer (translation required)': 'footer',
#'voetnoten': 'footnotes',
#'citaten': 'citations',
'verwijzing-voetnoten': 'target-notes',
'restructuredtext-test-instructie': 'restructuredtext-test-directive'}
"""Dutch name to registered (in directives/__init__.py) directive name
mapping."""
roles = {
# language-dependent: fixed
'afkorting': 'abbreviation',
# 'ab': 'abbreviation',
'acroniem': 'acronym',
'ac': 'acronym',
'index': 'index',
'i': 'index',
'inferieur': 'subscript',
'inf': 'subscript',
'superieur': 'superscript',
'sup': 'superscript',
'titel-referentie': 'title-reference',
'titel': 'title-reference',
't': 'title-reference',
'pep-referentie': 'pep-reference',
'pep': 'pep-reference',
'rfc-referentie': 'rfc-reference',
'rfc': 'rfc-reference',
'nadruk': 'emphasis',
'extra': 'strong',
'extra-nadruk': 'strong',
'vet': 'strong',
'letterlijk': 'literal',
'benoemde-referentie': 'named-reference',
'anonieme-referentie': 'anonymous-reference',
'voetnoot-referentie': 'footnote-reference',
'citaat-referentie': 'citation-reference',
'substitie-reference': 'substitution-reference',
'verwijzing': 'target',
'uri-referentie': 'uri-reference',
'uri': 'uri-reference',
'url': 'uri-reference',
'onbewerkt': 'raw',}
"""Mapping of Dutch role names to canonical role names for interpreted text.
"""
"""
:Author: Felix Wiemann
:Contact: Felix_Wiemann@ososo.de
:Revision: $Revision: 3376 $
:Date: $Date: 2005-05-26 23:33:24 +0200 (Thu, 26 May 2005) $
:Copyright: This module has been placed in the public domain.
LaTeX2e document tree Writer.
"""
# Thanks to Engelbert Gruber and various contributors for the original
# LaTeX writer, some code and many ideas of which have been used for
# this writer.
__docformat__ = 'reStructuredText'
from __future__ import nested_scopes
import re
import os.path
from types import ListType
import docutils
from docutils import nodes, writers, utils
class Writer(writers.Writer):
supported = ('newlatex', 'newlatex2e')
"""Formats this writer supports."""
settings_spec = (
'LaTeX-Specific Options',
'The LaTeX "--output-encoding" default is "latin-1:strict". '
'Note that this LaTeX writer is still EXPERIMENTAL.',
(('Specify a stylesheet file. The path is used verbatim to include '
'the file. Overrides --stylesheet-path.',
['--stylesheet'],
{'default': '', 'metavar': '<file>',
'overrides': 'stylesheet_path'}),
('Specify a stylesheet file, relative to the current working '
'directory. Overrides --stylesheet.',
['--stylesheet-path'],
{'metavar': '<file>', 'overrides': 'stylesheet'}),
('Specify a uesr stylesheet file. See --stylesheet.',
['--user-stylesheet'],
{'default': '', 'metavar': '<file>',
'overrides': 'user_stylesheet_path'}),
('Specify a user stylesheet file. See --stylesheet-path.',
['--user-stylesheet-path'],
{'metavar': '<file>', 'overrides': 'user_stylesheet'})
),)
settings_defaults = {'output_encoding': 'latin-1',
'trim_footnote_reference_space': 1,
# Currently unsupported:
'docinfo_xform': 0,
# During development:
'traceback': 1}
relative_path_settings = ('stylesheet_path',)
config_section = 'newlatex2e writer'
config_section_dependencies = ('writers',)
output = None
"""Final translated form of `document`."""
def __init__(self):
writers.Writer.__init__(self)
self.translator_class = LaTeXTranslator
def translate(self):
visitor = self.translator_class(self.document)
self.document.walkabout(visitor)
assert not visitor.context, 'context not empty: %s' % visitor.context
self.output = visitor.astext()
self.head = visitor.header
self.body = visitor.body
class Babel:
"""Language specifics for LaTeX."""
# country code by a.schlock.
# partly manually converted from iso and babel stuff, dialects and some
_ISO639_TO_BABEL = {
'no': 'norsk', # added by hand ( forget about nynorsk?)
'gd': 'scottish', # added by hand
'hu': 'magyar', # added by hand
'pt': 'portuguese',# added by hand
'sl': 'slovenian',
'af': 'afrikaans',
'bg': 'bulgarian',
'br': 'breton',
'ca': 'catalan',
'cs': 'czech',
'cy': 'welsh',
'da': 'danish',
'fr': 'french',
# french, francais, canadien, acadian
'de': 'ngerman', # rather than german
# ngerman, naustrian, german, germanb, austrian
'el': 'greek',
'en': 'english',
# english, USenglish, american, UKenglish, british, canadian
'eo': 'esperanto',
'es': 'spanish',
'et': 'estonian',
'eu': 'basque',
'fi': 'finnish',
'ga': 'irish',
'gl': 'galician',
'he': 'hebrew',
'hr': 'croatian',
'hu': 'hungarian',
'is': 'icelandic',
'it': 'italian',
'la': 'latin',
'nl': 'dutch',
'pl': 'polish',
'pt': 'portuguese',
'ro': 'romanian',
'ru': 'russian',
'sk': 'slovak',
'sr': 'serbian',
'sv': 'swedish',
'tr': 'turkish',
'uk': 'ukrainian'
}
def __init__(self, lang):
self.language = lang
def get_language(self):
if self._ISO639_TO_BABEL.has_key(self.language):
return self._ISO639_TO_BABEL[self.language]
else:
# Support dialects.
l = self.language.split("_")[0]
if self._ISO639_TO_BABEL.has_key(l):
return self._ISO639_TO_BABEL[l]
return None
class LaTeXException(Exception):
"""
Exception base class to for exceptions which influence the
automatic generation of LaTeX code.
"""
class SkipAttrParentLaTeX(LaTeXException):
"""
Do not generate \Dattr and \renewcommand{\Dparent}{...} for this
node.
To be raised from before_... methods.
"""
class SkipParentLaTeX(LaTeXException):
"""
Do not generate \renewcommand{\DNparent}{...} for this node.
To be raised from before_... methods.
"""
class LaTeXTranslator(nodes.SparseNodeVisitor):
# Start with left double quote.
left_quote = 1
def __init__(self, document):
nodes.NodeVisitor.__init__(self, document)
self.settings = document.settings
self.header = []
self.body = []
self.context = []
self.stylesheet_path = utils.get_stylesheet_reference(
self.settings, os.path.join(os.getcwd(), 'dummy'))
if self.stylesheet_path:
self.settings.record_dependencies.add(self.stylesheet_path)
# This ugly hack will be cleaned up when refactoring the
# stylesheet mess.
self.settings.stylesheet = self.settings.user_stylesheet
self.settings.stylesheet_path = self.settings.user_stylesheet_path
self.user_stylesheet_path = utils.get_stylesheet_reference(
self.settings, os.path.join(os.getcwd(), 'dummy'))
if self.user_stylesheet_path:
self.settings.record_dependencies.add(self.user_stylesheet_path)
self.write_header()
for key, value in self.character_map.items():
self.character_map[key] = '{%s}' % value
def write_header(self):
a = self.header.append
a('%% Generated by Docutils %s <http://docutils.sourceforge.net>.\n'
% docutils.__version__)
if self.user_stylesheet_path:
a('% User stylesheet:')
a(r'\input{%s}' % self.user_stylesheet_path)
a('% Docutils stylesheet:')
a(r'\input{%s}' % self.stylesheet_path)
a('')
a('% Definitions for Docutils Nodes:')
for node_name in nodes.node_class_names:
a(r'\providecommand{\DN%s}[1]{#1}' % node_name.replace('_', ''))
a('')
a('% Auxiliary definitions:')
a(r'\providecommand{\Dsetattr}[2]{}')
a(r'\providecommand{\Dparent}{} % variable')
a(r'\providecommand{\Dattr}[5]{#5}')
a(r'\providecommand{\Dattrlen}{} % variable')
a(r'\providecommand{\Dtitleastext}{x}')
a(r'\providecommand{\Dsinglebackref}{} % variable')
a(r'\providecommand{\Dmultiplebackrefs}{} % variable')
a('\n\n')
def to_latex_encoding(self,docutils_encoding):
"""
Translate docutils encoding name into latex's.
Default fallback method is remove "-" and "_" chars from
docutils_encoding.
"""
tr = { "iso-8859-1": "latin1", # west european
"iso-8859-2": "latin2", # east european
"iso-8859-3": "latin3", # esperanto, maltese
"iso-8859-4": "latin4", # north european,scandinavian, baltic
"iso-8859-5": "iso88595", # cyrillic (ISO)
"iso-8859-9": "latin5", # turkish
"iso-8859-15": "latin9", # latin9, update to latin1.
"mac_cyrillic": "maccyr", # cyrillic (on Mac)
"windows-1251": "cp1251", # cyrillic (on Windows)
"koi8-r": "koi8-r", # cyrillic (Russian)
"koi8-u": "koi8-u", # cyrillic (Ukrainian)
"windows-1250": "cp1250", #
"windows-1252": "cp1252", #
"us-ascii": "ascii", # ASCII (US)
# unmatched encodings
#"": "applemac",
#"": "ansinew", # windows 3.1 ansi
#"": "ascii", # ASCII encoding for the range 32--127.
#"": "cp437", # dos latine us
#"": "cp850", # dos latin 1
#"": "cp852", # dos latin 2
#"": "decmulti",
#"": "latin10",
#"iso-8859-6": "" # arabic
#"iso-8859-7": "" # greek
#"iso-8859-8": "" # hebrew
#"iso-8859-10": "" # latin6, more complete iso-8859-4
}
if tr.has_key(docutils_encoding.lower()):
return tr[docutils_encoding.lower()]
return docutils_encoding.translate(string.maketrans("",""),"_-").lower()
def language_label(self, docutil_label):
return self.language.labels[docutil_label]
# To do: Use unimap.py from TeXML instead. Have to deal with
# legal cruft before, because it's LPGL.
character_map_string = r"""
\ \textbackslash
{ \{
} \}
$ \$
& \&
% \%
# \#
[ [
] ]
- -
` `
' '
, ,
" "
| \textbar
< \textless
> \textgreater
^ \textasciicircum
~ \textasciitilde
_ \Dtextunderscore
"""
#special_map = {'\n': ' ', '\r': ' ', '\t': ' ', '\v': ' ', '\f': ' '}
unicode_map = {
u'\u00A0': '~',
u'\u2009': '{\\,}',
u'\u2013': '{--}',
u'\u2014': '{---}',
u'\u2018': '`',
u'\u2019': '\'',
u'\u201A': ',',
u'\u201C': '``',
u'\u201D': "''",
u'\u201E': ',,',
u'\u2020': '{\\dag}',
u'\u2021': '{\\ddag}',
u'\u2026': '{\\dots}',
u'\u2122': '{\\texttrademark}',
u'\u21d4': '{$\\Leftrightarrow$}',
}
character_map = {}
for pair in character_map_string.strip().split('\n'):
char, replacement = pair.split()
character_map[char] = replacement
character_map.update(unicode_map)
#character_map.update(special_map)
def encode(self, text, attval=0):
"""
Encode special characters in ``text`` and return it.
If attval is true, preserve as much as possible verbatim (used in
attribute value encoding).
"""
if not attval:
get = self.character_map.get
else:
# According to
# <http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/teTeX/latex/latex2e-html/ltx-164.html>,
# the following characters are special: # $ % & ~ _ ^ \ { }
# These work without special treatment in macro parameters:
# $, &, ~, _, ^
get = {'#': '\\#',
'%': '\\%',
# We cannot do anything about backslashes.
'\\': '',
'{': '\\{',
'}': '\\}',
# The quotation mark may be redefined by babel.
'"': '"{}',
}.get
text = ''.join([get(c, c) for c in text])
if (self.literal_block or self.inline_literal) and not attval:
# NB: We can have inline literals within literal blocks.
# Shrink '\r\n'.
text = text.replace('\r\n', '\n')
# Convert space. If "{ }~~~~~" is wrapped (at the
# brace-enclosed space "{ }"), the following non-breaking
# spaces ("~~~~") do *not* wind up at the beginning of the
# next line. Also note that, for some not-so-obvious
# reason, no hyphenation is done if the breaking space ("{
# }") comes *after* the non-breaking spaces.
if self.literal_block:
# Replace newlines with real newlines.
text = text.replace('\n', '\mbox{}\\\\')
firstspace = '~'
else:
firstspace = '{ }'
text = re.sub(r'\s+', lambda m: firstspace +
'~' * (len(m.group()) - 1), text)
# Protect hyphens; if we don't, line breaks will be
# possible at the hyphens and even the \textnhtt macro
# from the hyphenat package won't change that.
text = text.replace('-', r'\mbox{-}')
text = text.replace("'", r'{\Dtextliteralsinglequote}')
return text
else:
if not attval:
# Replace space with single protected space.
text = re.sub(r'\s+', '{ }', text)
# Replace double quotes with macro calls.
L = []
for part in text.split('"'):
if L:
# Insert quote.
L.append(self.left_quote and r'\Dtextleftdblquote' or
r'\Dtextrightdblquote')
self.left_quote = not self.left_quote
L.append(part)
return ''.join(L)
else:
return text
def astext(self):
return '\n'.join(self.header) + (''.join(self.body))
def append(self, text, newline='%\n'):
"""
Append text, stripping newlines, producing nice LaTeX code.
"""
lines = [' ' * self.indentation_level + line + newline
for line in text.splitlines(0)]
self.body.append(''.join(lines))
def visit_Text(self, node):
self.append(self.encode(node.astext()))
def depart_Text(self, node):
pass
def before_title(self, node):
self.append(r'\renewcommand{\Dtitleastext}{%s}'
% self.encode(node.astext()))
self.append(r'\renewcommand{\Dhassubtitle}{%s}'
% ((len(node.parent) > 2 and
isinstance(node.parent[1], nodes.subtitle))
and 'true' or 'false'))
literal_block = 0
def visit_literal_block(self, node):
self.literal_block = 1
def depart_literal_block(self, node):
self.literal_block = 0
visit_doctest_block = visit_literal_block
depart_doctest_block = depart_literal_block
inline_literal = 0
def visit_literal(self, node):
self.inline_literal += 1
def depart_literal(self, node):
self.inline_literal -= 1
def visit_comment(self, node):
self.append('\n'.join(['% ' + line for line
in node.astext().splitlines(0)]), newline='\n')
raise nodes.SkipChildren
bullet_list_level = 0
def visit_bullet_list(self, node):
self.append(r'\Dsetbullet{\labelitem%s}' %
['i', 'ii', 'iii', 'iv'][min(self.bullet_list_level, 3)])
self.bullet_list_level += 1
def depart_bullet_list(self, node):
self.bullet_list_level -= 1
enum_styles = {'arabic': 'arabic', 'loweralpha': 'alph', 'upperalpha':
'Alph', 'lowerroman': 'roman', 'upperroman': 'Roman'}
enum_counter = 0
def visit_enumerated_list(self, node):
# We create our own enumeration list environment. This allows
# to set the style and starting value and unlimited nesting.
# Maybe this can be moved to the stylesheet?
self.enum_counter += 1
enum_prefix = self.encode(node['prefix'])
enum_suffix = self.encode(node['suffix'])
enum_type = '\\' + self.enum_styles.get(node['enumtype'], r'arabic')
start = node.get('start', 1) - 1
counter = 'Denumcounter%d' % self.enum_counter
self.append(r'\Dmakeenumeratedlist{%s}{%s}{%s}{%s}{%s}{'
% (enum_prefix, enum_type, enum_suffix, counter, start))
# for Emacs: }
def depart_enumerated_list(self, node):
self.append('}') # for Emacs: {
def before_list_item(self, node):
# XXX needs cleanup.
if (len(node) and (isinstance(node[-1], nodes.TextElement) or
isinstance(node[-1], nodes.Text)) and
node.parent.index(node) == len(node.parent) - 1):
node['lastitem'] = 'true'
before_line = before_list_item
def before_raw(self, node):
if 'latex' in node.get('format', '').split():
# We're inserting the text in before_raw and thus outside
# of \DN... and \Dattr in order to make grouping with
# curly brackets work.
self.append(node.astext())
raise nodes.SkipChildren
def process_backlinks(self, node, type):
self.append(r'\renewcommand{\Dsinglebackref}{}')
self.append(r'\renewcommand{\Dmultiplebackrefs}{}')
if len(node['backrefs']) > 1:
refs = []
for i in range(len(node['backrefs'])):
refs.append(r'\Dmulti%sbacklink{%s}{%s}'
% (type, node['backrefs'][i], i + 1))
self.append(r'\renewcommand{\Dmultiplebackrefs}{(%s){ }}'
% ', '.join(refs))
elif len(node['backrefs']) == 1:
self.append(r'\renewcommand{\Dsinglebackref}{%s}'
% node['backrefs'][0])
def visit_footnote(self, node):
self.process_backlinks(node, 'footnote')
def visit_citation(self, node):
self.process_backlinks(node, 'citation')
def before_table(self, node):
# A tables contains exactly one tgroup. See before_tgroup.
pass
def before_tgroup(self, node):
widths = []
total_width = 0
for i in range(int(node['cols'])):
assert isinstance(node[i], nodes.colspec)
widths.append(int(node[i]['colwidth']) + 1)
total_width += widths[-1]
del node[:len(widths)]
tablespec = '|'
for w in widths:
# 0.93 is probably wrong in many cases. XXX Find a
# solution which works *always*.
tablespec += r'p{%s\linewidth}|' % (0.93 * w /
max(total_width, 60))
self.append(r'\Dmaketable{%s}{' % tablespec)
self.context.append('}')
raise SkipAttrParentLaTeX
def depart_tgroup(self, node):
self.append(self.context.pop())
def before_row(self, node):
raise SkipAttrParentLaTeX
def before_thead(self, node):
raise SkipAttrParentLaTeX
def before_tbody(self, node):
raise SkipAttrParentLaTeX
def is_simply_entry(self, node):
return (len(node) == 1 and isinstance(node[0], nodes.paragraph) or
len(node) == 0)
def before_entry(self, node):
is_leftmost = 0
if node.hasattr('morerows'):
self.document.reporter.severe('Rowspans are not supported.')
# Todo: Add empty cells below rowspanning cell and issue
# warning instead of severe.
if node.hasattr('morecols'):
# The author got a headache trying to implement
# multicolumn support.
if not self.is_simply_entry(node):
self.document.reporter.severe(
'Colspanning table cells may only contain one paragraph.')
# Todo: Same as above.
# The number of columns this entry spans (as a string).
colspan = int(node['morecols']) + 1
del node['morecols']
else:
colspan = 1
# Macro to call.
macro_name = r'\Dcolspan'
if node.parent.index(node) == 0:
# Leftmost column.
macro_name += 'left'
is_leftmost = 1
if colspan > 1:
self.append('%s{%s}{' % (macro_name, colspan))
self.context.append('}')
else:
# Do not add a multicolumn with colspan 1 beacuse we need
# at least one non-multicolumn cell per column to get the
# desired column widths, and we can only do colspans with
# cells consisting of only one paragraph.
if not is_leftmost:
self.append(r'\Dsubsequententry{')
self.context.append('}')
else:
self.context.append('')
if isinstance(node.parent.parent, nodes.thead):
node['tableheaderentry'] = 'true'
# Don't add \renewcommand{\Dparent}{...} because there must
# not be any non-expandable commands in front of \multicolumn.
raise SkipParentLaTeX
def depart_entry(self, node):
self.append(self.context.pop())
def before_substitution_definition(self, node):
raise nodes.SkipNode
indentation_level = 0
def node_name(self, node):
return node.__class__.__name__.replace('_', '')
def propagate_attributes(self, node):
# Propagate attributes using \Dattr macros.
node_name = self.node_name(node)
attlist = []
if isinstance(node, nodes.Element):
attlist = node.attlist()
numatts = 0
pass_contents = self.pass_contents(node)
for key, value in attlist:
if isinstance(value, ListType):
self.append(r'\renewcommand{\Dattrlen}{%s}' % len(value))
for i in range(len(value)):
self.append(r'\Dattr{%s}{%s}{%s}{%s}{' %
(i+1, key, self.encode(value[i], attval=1),
node_name))
if not pass_contents:
self.append('}')
numatts += len(value)
else:
self.append(r'\Dattr{}{%s}{%s}{%s}{' %
(key, self.encode(unicode(value), attval=1),
node_name))
if not pass_contents:
self.append('}')
numatts += 1
if pass_contents:
self.context.append('}' * numatts) # for Emacs: {
else:
self.context.append('')
def visit_docinfo(self, node):
raise NotImplementedError('Docinfo not yet implemented.')
def visit_document(self, node):
document = node
# Move IDs into TextElements. This won't work for images.
# Need to review this.
for node in document.traverse(lambda n: isinstance(n, nodes.Element)):
if node.has_key('ids') and not isinstance(node,
nodes.TextElement):
next_text_element = node.next_node(
lambda n: isinstance(n, nodes.TextElement))
if next_text_element:
next_text_element['ids'].extend(node['ids'])
node['ids'] = []
def pass_contents(self, node):
r"""
Return true if the node contents should be passed in
parameters of \DN... and \Dattr.
"""
return not isinstance(node, (nodes.document, nodes.section))
def dispatch_visit(self, node):
skip_attr = skip_parent = 0
# TreePruningException to be propagated.
tree_pruning_exception = None
if hasattr(self, 'before_' + node.__class__.__name__):
try:
getattr(self, 'before_' + node.__class__.__name__)(node)
except SkipParentLaTeX:
skip_parent = 1
except SkipAttrParentLaTeX:
skip_attr = 1
skip_parent = 1
except nodes.SkipNode:
raise
except (nodes.SkipChildren, nodes.SkipSiblings), instance:
tree_pruning_exception = instance
except nodes.SkipDeparture:
raise NotImplementedError(
'SkipDeparture not usable in LaTeX writer')
if not isinstance(node, nodes.Text):
node_name = self.node_name(node)
# attribute_deleters will be appended to self.context.
attribute_deleters = []
if not skip_parent and not isinstance(node, nodes.document):
self.append(r'\renewcommand{\Dparent}{%s}'
% self.node_name(node.parent))
for name, value in node.attlist():
# @@@ Evaluate if this is really needed and refactor.
if not isinstance(value, ListType) and not ':' in name:
macro = r'\DcurrentN%sA%s' % (node_name, name)
self.append(r'\def%s{%s}' % (
macro, self.encode(unicode(value), attval=1)))
attribute_deleters.append(r'\let%s=\relax' % macro)
self.context.append('\n'.join(attribute_deleters))
if self.pass_contents(node):
self.append(r'\DN%s{' % node_name)
self.context.append('}')
else:
self.append(r'\Dvisit%s' % node_name)
self.context.append(r'\Ddepart%s' % node_name)
self.indentation_level += 1
if not skip_attr:
self.propagate_attributes(node)
else:
self.context.append('')
if (isinstance(node, nodes.TextElement) and
not isinstance(node.parent, nodes.TextElement)):
# Reset current quote to left.
self.left_quote = 1
# Call visit_... method.
try:
nodes.SparseNodeVisitor.dispatch_visit(self, node)
except LaTeXException:
raise NotImplementedError(
'visit_... methods must not raise LaTeXExceptions')
if tree_pruning_exception:
# Propagate TreePruningException raised in before_... method.
raise tree_pruning_exception
def is_invisible(self, node):
# Return true if node is invisible or moved away in the LaTeX
# rendering.
return (isinstance(node, nodes.Invisible) or
isinstance(node, nodes.footnote) or
isinstance(node, nodes.citation) or
# We never know what's inside raw nodes, and often
# they *are* invisible. So let's have the user take
# care of them.
isinstance(node, nodes.raw) or
# Horizontally aligned image or figure.
node.get('align', None) in ('left', 'center', 'right'))
def needs_space(self, node):
# Return true if node is a visible block-level element.
return ((isinstance(node, nodes.Body) or
isinstance(node, nodes.topic) or
#isinstance(node, nodes.rubric) or
isinstance(node, nodes.transition) or
isinstance(node, nodes.caption) or
isinstance(node, nodes.legend)) and
not (self.is_invisible(node) or
isinstance(node.parent, nodes.TextElement)))
def dispatch_departure(self, node):
# Call departure method.
nodes.SparseNodeVisitor.dispatch_departure(self, node)
if not isinstance(node, nodes.Text):
# Close attribute and node handler call (\DN...{...}).
self.indentation_level -= 1
self.append(self.context.pop() + self.context.pop())
# Delete \Dcurrent... attribute macros.
self.append(self.context.pop())
# Insert space.
if self.needs_space(node):
# Next sibling.
next_node = node.next_node(
ascend=0, siblings=1, descend=0,
condition=lambda n: not self.is_invisible(n))
if self.needs_space(next_node):
# Insert space.
if isinstance(next_node, nodes.paragraph):
if isinstance(node, nodes.paragraph):
# Space between paragraphs.
self.append(r'\Dparagraphspace')
else:
# Space in front of a paragraph.
self.append(r'\Dauxiliaryparspace')
else:
# Space in front of something else than a paragraph.
self.append(r'\Dauxiliaryspace')
# Author: David Goodger
# Contact: goodger@python.org
# Revision: $Revision: 3246 $
# Date: $Date: 2005-04-23 21:23:21 +0200 (Sat, 23 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
A do-nothing Writer.
"""
from docutils import writers
class Writer(writers.Writer):
supported = ('null',)
"""Formats this writer supports."""
config_section = 'null writer'
config_section_dependencies = ('writers',)
def translate(self):
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment