buildframework/helium/external/python/lib/common/docutils-0.5-py2.5.egg/docutils/writers/newlatex2e/__init__.py
author wbernard
Wed, 23 Dec 2009 19:29:07 +0200
changeset 179 d8ac696cc51f
permissions -rw-r--r--
helium_7.0-r14027
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
179
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     1
# $Id: __init__.py 5174 2007-05-31 00:01:52Z wiemann $
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     2
# Author: Lea Wiemann <LeWiemann@gmail.com>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     3
# Copyright: This module has been placed in the public domain.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     4
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     5
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     6
LaTeX2e document tree Writer.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
# Thanks to Engelbert Gruber and various contributors for the original
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
# LaTeX writer, some code and many ideas of which have been used for
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
# this writer.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
__docformat__ = 'reStructuredText'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
import re
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
import os.path
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
from types import ListType
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
import docutils
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
from docutils import nodes, writers, utils
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
from docutils.writers.newlatex2e import unicode_map
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
from docutils.transforms import writer_aux
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
class Writer(writers.Writer):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
    supported = ('newlatex', 'newlatex2e')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
    """Formats this writer supports."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
    default_stylesheet = 'base.tex'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
    default_stylesheet_path = utils.relative_path(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
        os.path.join(os.getcwd(), 'dummy'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
        os.path.join(os.path.dirname(__file__), default_stylesheet))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
    settings_spec = (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
        'LaTeX-Specific Options',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
        'Note that this LaTeX writer is still EXPERIMENTAL and not '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
        'feature-complete. ',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
        (('Specify a stylesheet file.  The path is used verbatim to include '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
          'the file.  Overrides --stylesheet-path.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
          ['--stylesheet'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
          {'default': '', 'metavar': '<file>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
           'overrides': 'stylesheet_path'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
         ('Specify a stylesheet file, relative to the current working '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
          'directory.  Overrides --stylesheet.  Default: "%s"'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
          % default_stylesheet_path,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
          ['--stylesheet-path'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
          {'metavar': '<file>', 'overrides': 'stylesheet',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
           'default': default_stylesheet_path}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
         ('Specify a user stylesheet file.  See --stylesheet.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
          ['--user-stylesheet'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
          {'default': '', 'metavar': '<file>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
           'overrides': 'user_stylesheet_path'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
         ('Specify a user stylesheet file.  See --stylesheet-path.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
          ['--user-stylesheet-path'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
          {'metavar': '<file>', 'overrides': 'user_stylesheet'})
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
         ),)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
    settings_defaults = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
        # Many Unicode characters are provided by unicode_map.py, so
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
        # we can default to latin-1.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
        'output_encoding': 'latin-1',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
        'output_encoding_error_handler': 'strict',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
        # Since we are using superscript footnotes, it is necessary to
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
        # trim whitespace in front of footnote references.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
        'trim_footnote_reference_space': 1,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
        # Currently unsupported:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
        'docinfo_xform': 0,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
        # During development:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
        'traceback': 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
        }
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
    relative_path_settings = ('stylesheet_path', 'user_stylesheet_path')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
    config_section = 'newlatex2e writer'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
    config_section_dependencies = ('writers',)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
    output = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
    """Final translated form of `document`."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
    def get_transforms(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
        return writers.Writer.get_transforms(self) + [
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
            writer_aux.Compound, writer_aux.Admonitions]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
    def __init__(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
        writers.Writer.__init__(self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
        self.translator_class = LaTeXTranslator
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
    def translate(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
        visitor = self.translator_class(self.document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
        self.document.walkabout(visitor)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
        assert not visitor.context, 'context not empty: %s' % visitor.context
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
        self.output = visitor.astext()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
        self.head = visitor.header
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
        self.body = visitor.body
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
class LaTeXException(Exception):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
    Exception base class to for exceptions which influence the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
    automatic generation of LaTeX code.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
class SkipAttrParentLaTeX(LaTeXException):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
    Do not generate ``\DECattr`` and ``\renewcommand{\DEVparent}{...}`` for this
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
    node.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
    To be raised from ``before_...`` methods.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
class SkipParentLaTeX(LaTeXException):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
    Do not generate ``\renewcommand{\DEVparent}{...}`` for this node.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
    To be raised from ``before_...`` methods.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
class LaTeXTranslator(nodes.SparseNodeVisitor):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
    # Country code by a.schlock.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
    # Partly manually converted from iso and babel stuff.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
    iso639_to_babel = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
        'no': 'norsk',     # added by hand
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
        'gd': 'scottish',  # added by hand
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
        'sl': 'slovenian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
        'af': 'afrikaans',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
        'bg': 'bulgarian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
        'br': 'breton',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
        'ca': 'catalan',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
        'cs': 'czech',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
        'cy': 'welsh',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
        'da': 'danish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
        'fr': 'french',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
        # french, francais, canadien, acadian
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
        'de': 'ngerman',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        # ngerman, naustrian, german, germanb, austrian
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
        'el': 'greek',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
        'en': 'english',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
        # english, USenglish, american, UKenglish, british, canadian
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
        'eo': 'esperanto',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
        'es': 'spanish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
        'et': 'estonian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
        'eu': 'basque',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
        'fi': 'finnish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
        'ga': 'irish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
        'gl': 'galician',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
        'he': 'hebrew',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
        'hr': 'croatian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
        'hu': 'hungarian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
        'is': 'icelandic',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
        'it': 'italian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
        'la': 'latin',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
        'nl': 'dutch',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
        'pl': 'polish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
        'pt': 'portuguese',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
        'ro': 'romanian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
        'ru': 'russian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
        'sk': 'slovak',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
        'sr': 'serbian',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
        'sv': 'swedish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
        'tr': 'turkish',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
        'uk': 'ukrainian'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
    }
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
    # Start with left double quote.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
    left_quote = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
    def __init__(self, document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
        nodes.NodeVisitor.__init__(self, document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
        self.settings = document.settings
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
        self.header = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
        self.body = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
        self.context = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
        self.stylesheet_path = utils.get_stylesheet_reference(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
            self.settings, os.path.join(os.getcwd(), 'dummy'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
        if self.stylesheet_path:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
            self.settings.record_dependencies.add(self.stylesheet_path)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
        # This ugly hack will be cleaned up when refactoring the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
        # stylesheet mess.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
        self.settings.stylesheet = self.settings.user_stylesheet
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
        self.settings.stylesheet_path = self.settings.user_stylesheet_path
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
        self.user_stylesheet_path = utils.get_stylesheet_reference(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
            self.settings, os.path.join(os.getcwd(), 'dummy'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
        if self.user_stylesheet_path:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
            self.settings.record_dependencies.add(self.user_stylesheet_path)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
        self.write_header()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
    def write_header(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
        a = self.header.append
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
        a('%% Generated by Docutils %s <http://docutils.sourceforge.net>.'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
          % docutils.__version__)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
        a('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
        a('% Docutils settings:')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
        lang = self.settings.language_code or ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
        a(r'\providecommand{\DEVlanguageiso}{%s}' % lang)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
        a(r'\providecommand{\DEVlanguagebabel}{%s}' % self.iso639_to_babel.get(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
            lang, self.iso639_to_babel.get(lang.split('_')[0], '')))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
        a('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
        if self.user_stylesheet_path:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
            a('% User stylesheet:')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
            a(r'\input{%s}' % self.user_stylesheet_path)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
        a('% Docutils stylesheet:')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
        a(r'\input{%s}' % self.stylesheet_path)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
        a('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
        a('% Default definitions for Docutils nodes:')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
        for node_name in nodes.node_class_names:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
            a(r'\providecommand{\DN%s}[1]{#1}' % node_name.replace('_', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
        a('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
        a('% Auxiliary definitions:')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
        for attr in (r'\DEVparent \DEVattrlen \DEVtitleastext '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
                     r'\DEVsinglebackref \DEVmultiplebackrefs'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
                     ).split():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
            # Later set using \renewcommand.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
            a(r'\providecommand{%s}{DOCUTILSUNINITIALIZEDVARIABLE}' % attr)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
        for attr in (r'\DEVparagraphindented \DEVhassubtitle').split():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
            # Initialize as boolean variables.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
            a(r'\providecommand{%s}{false}' % attr)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
        a('\n\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
    unicode_map = unicode_map.unicode_map # comprehensive Unicode map
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
    # Fix problems with unimap.py.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
    unicode_map.update({
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
        # We have AE or T1 encoding, so "``" etc. work.  The macros
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
        # from unimap.py may *not* work.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
        u'\u201C': '{``}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
        u'\u201D': "{''}",
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
        u'\u201E': '{,,}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
        })
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
    character_map = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
        '\\': r'{\textbackslash}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
        '{': r'{\{}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
        '}': r'{\}}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
        '$': r'{\$}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
        '&': r'{\&}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
        '%': r'{\%}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
        '#': r'{\#}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
        '[': r'{[}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
        ']': r'{]}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
        '-': r'{-}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
        '`': r'{`}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
        "'": r"{'}",
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
        ',': r'{,}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
        '"': r'{"}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
        '|': r'{\textbar}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
        '<': r'{\textless}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
        '>': r'{\textgreater}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
        '^': r'{\textasciicircum}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
        '~': r'{\textasciitilde}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
        '_': r'{\DECtextunderscore}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
        }
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
    character_map.update(unicode_map)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
    #character_map.update(special_map)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
    
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
    # `att_map` is for encoding attributes.  According to
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
    # <http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/teTeX/latex/latex2e-html/ltx-164.html>,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
    # the following characters are special: # $ % & ~ _ ^ \ { }
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
    # These work without special treatment in macro parameters:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
    # $, &, ~, _, ^
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   266
    att_map = {'#': '\\#',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   267
               '%': '\\%',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   268
               # We cannot do anything about backslashes.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
               '\\': '',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
               '{': '\\{',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
               '}': '\\}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
               # The quotation mark may be redefined by babel.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
               '"': '"{}',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
               }
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
    att_map.update(unicode_map)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
    def encode(self, text, attval=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
        Encode special characters in ``text`` and return it.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
        If attval is true, preserve as much as possible verbatim (used
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
        in attribute value encoding).  If attval is 'width' or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
        'height', `text` is interpreted as a length value.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
        if attval in ('width', 'height'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
            match = re.match(r'([0-9.]+)(\S*)$', text)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
            assert match, '%s="%s" must be a length' % (attval, text)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
            value, unit = match.groups()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
            if unit == '%':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
                value = str(float(value) / 100)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
                unit = r'\DECrelativeunit'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
            elif unit in ('', 'px'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
                # If \DECpixelunit is "pt", this gives the same notion
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
                # of pixels as graphicx.  This is a bit of a hack.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
                value = str(float(value) * 0.75)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
                unit = '\DECpixelunit'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
            return '%s%s' % (value, unit)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
        if attval:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
            get = self.att_map.get
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
            get = self.character_map.get
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
        text = ''.join([get(c, c) for c in text])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
        if (self.literal_block or self.inline_literal) and not attval:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
            # NB: We can have inline literals within literal blocks.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
            # Shrink '\r\n'.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
            text = text.replace('\r\n', '\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
            # Convert space.  If "{ }~~~~~" is wrapped (at the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
            # brace-enclosed space "{ }"), the following non-breaking
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
            # spaces ("~~~~") do *not* wind up at the beginning of the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
            # next line.  Also note that no hyphenation is done if the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
            # breaking space ("{ }") comes *after* the non-breaking
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
            # spaces.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
            if self.literal_block:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
                # Replace newlines with real newlines.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
                text = text.replace('\n', '\mbox{}\\\\{}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
                replace_fn = self.encode_replace_for_literal_block_spaces
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
                replace_fn = self.encode_replace_for_inline_literal_spaces
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
            text = re.sub(r'\s+', replace_fn, text)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
            # Protect hyphens; if we don't, line breaks will be
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
            # possible at the hyphens and even the \textnhtt macro
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
            # from the hyphenat package won't change that.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
            text = text.replace('-', r'\mbox{-}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
            text = text.replace("'", r'{\DECtextliteralsinglequote}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
            return text
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
            if not attval:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
                # Replace space with single protected space.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
                text = re.sub(r'\s+', '{ }', text)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
                # Replace double quotes with macro calls.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
                L = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
                for part in text.split(self.character_map['"']):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
                    if L:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
                        # Insert quote.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
                        L.append(self.left_quote and r'{\DECtextleftdblquote}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
                                 or r'{\DECtextrightdblquote}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
                        self.left_quote = not self.left_quote
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
                    L.append(part)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
                return ''.join(L)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
                return text
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
    def encode_replace_for_literal_block_spaces(self, match):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
        return '~' * len(match.group())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
    def encode_replace_for_inline_literal_spaces(self, match):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
        return '{ }' + '~' * (len(match.group()) - 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
    def astext(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
        return '\n'.join(self.header) + (''.join(self.body))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
    def append(self, text, newline='%\n'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
        Append text, stripping newlines, producing nice LaTeX code.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
        lines = ['  ' * self.indentation_level + line + newline
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
                 for line in text.splitlines(0)]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
        self.body.append(''.join(lines))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
    def visit_Text(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
        self.append(self.encode(node.astext()))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
    def depart_Text(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
    def is_indented(self, paragraph):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
        """Return true if `paragraph` should be first-line-indented."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   368
        assert isinstance(paragraph, nodes.paragraph)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   369
        siblings = [n for n in paragraph.parent if
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   370
                    self.is_visible(n) and not isinstance(n, nodes.Titular)]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   371
        index = siblings.index(paragraph)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   372
        if ('continued' in paragraph['classes'] or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   373
            index > 0 and isinstance(siblings[index-1], nodes.transition)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   374
            return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   375
        # Indent all but the first paragraphs.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   376
        return index > 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   377
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   378
    def before_paragraph(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   379
        self.append(r'\renewcommand{\DEVparagraphindented}{%s}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   380
                    % (self.is_indented(node) and 'true' or 'false'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   381
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   382
    def before_title(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   383
        self.append(r'\renewcommand{\DEVtitleastext}{%s}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   384
                    % self.encode(node.astext()))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   385
        self.append(r'\renewcommand{\DEVhassubtitle}{%s}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   386
                    % ((len(node.parent) > 2 and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   387
                        isinstance(node.parent[1], nodes.subtitle))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   388
                       and 'true' or 'false'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   389
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   390
    def before_generated(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   391
        if 'sectnum' in node['classes']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   392
            node[0] = node[0].strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   393
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   394
    literal_block = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   395
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   396
    def visit_literal_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   397
        self.literal_block = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   398
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   399
    def depart_literal_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   400
        self.literal_block = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   401
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   402
    visit_doctest_block = visit_literal_block
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   403
    depart_doctest_block = depart_literal_block
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   404
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   405
    inline_literal = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   406
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   407
    def visit_literal(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   408
        self.inline_literal += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   409
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   410
    def depart_literal(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   411
        self.inline_literal -= 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   412
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   413
    def _make_encodable(self, text):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   414
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   415
        Return text (a unicode object) with all unencodable characters
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   416
        replaced with '?'.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   417
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   418
        Thus, the returned unicode string is guaranteed to be encodable.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   419
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   420
        encoding = self.settings.output_encoding
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   421
        return text.encode(encoding, 'replace').decode(encoding)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   422
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   423
    def visit_comment(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   424
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   425
        Insert the comment unchanged into the document, replacing
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   426
        unencodable characters with '?'.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   427
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   428
        (This is done in order not to fail if comments contain unencodable
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   429
        characters, because our default encoding is not UTF-8.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   430
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   431
        self.append('\n'.join(['% ' + self._make_encodable(line) for line
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   432
                               in node.astext().splitlines(0)]), newline='\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   433
        raise nodes.SkipChildren
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   434
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   435
    def before_topic(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   436
        if 'contents' in node['classes']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   437
            for bullet_list in list(node.traverse(nodes.bullet_list)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   438
                p = bullet_list.parent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   439
                if isinstance(p, nodes.list_item):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   440
                    p.parent.insert(p.parent.index(p) + 1, bullet_list)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   441
                    del p[1]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   442
            for paragraph in node.traverse(nodes.paragraph):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   443
                paragraph.attributes.update(paragraph[0].attributes)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   444
                paragraph[:] = paragraph[0]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   445
                paragraph.parent['tocrefid'] = paragraph['refid']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   446
            node['contents'] = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   447
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   448
            node['contents'] = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   449
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   450
    bullet_list_level = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   451
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   452
    def visit_bullet_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   453
        self.append(r'\DECsetbullet{\labelitem%s}' %
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   454
                    ['i', 'ii', 'iii', 'iv'][min(self.bullet_list_level, 3)])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   455
        self.bullet_list_level += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   456
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   457
    def depart_bullet_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   458
        self.bullet_list_level -= 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   459
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   460
    enum_styles = {'arabic': 'arabic', 'loweralpha': 'alph', 'upperalpha':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   461
                   'Alph', 'lowerroman': 'roman', 'upperroman': 'Roman'}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   462
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   463
    enum_counter = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   464
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   465
    def visit_enumerated_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   466
        # We create our own enumeration list environment.  This allows
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   467
        # to set the style and starting value and unlimited nesting.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   468
        # Maybe the actual creation (\DEC) can be moved to the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   469
        # stylesheet?
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   470
        self.enum_counter += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   471
        enum_prefix = self.encode(node['prefix'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   472
        enum_suffix = self.encode(node['suffix'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   473
        enum_type = '\\' + self.enum_styles.get(node['enumtype'], r'arabic')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   474
        start = node.get('start', 1) - 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   475
        counter = 'Denumcounter%d' % self.enum_counter
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   476
        self.append(r'\DECmakeenumeratedlist{%s}{%s}{%s}{%s}{%s}{'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   477
                    % (enum_prefix, enum_type, enum_suffix, counter, start))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   478
                    # for Emacs: }
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   479
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   480
    def depart_enumerated_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   481
        self.append('}')  # for Emacs: {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   482
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   483
    def before_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   484
        # XXX needs cleanup.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   485
        if (len(node) and (isinstance(node[-1], nodes.TextElement) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   486
                           isinstance(node[-1], nodes.Text)) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   487
            node.parent.index(node) == len(node.parent) - 1):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   488
            node['lastitem'] = 'true'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   489
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   490
    before_line = before_list_item
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   491
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   492
    def before_raw(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   493
        if 'latex' in node.get('format', '').split():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   494
            # We're inserting the text in before_raw and thus outside
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   495
            # of \DN... and \DECattr in order to make grouping with
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   496
            # curly brackets work.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   497
            self.append(node.astext())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   498
        raise nodes.SkipChildren
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   499
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   500
    def process_backlinks(self, node, type):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   501
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   502
        Add LaTeX handling code for backlinks of footnote or citation
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   503
        node `node`.  `type` is either 'footnote' or 'citation'.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   504
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   505
        self.append(r'\renewcommand{\DEVsinglebackref}{}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   506
        self.append(r'\renewcommand{\DEVmultiplebackrefs}{}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   507
        if len(node['backrefs']) > 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   508
            refs = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   509
            for i in range(len(node['backrefs'])):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   510
                # \DECmulticitationbacklink or \DECmultifootnotebacklink.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   511
                refs.append(r'\DECmulti%sbacklink{%s}{%s}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   512
                            % (type, node['backrefs'][i], i + 1))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   513
            self.append(r'\renewcommand{\DEVmultiplebackrefs}{(%s){ }}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   514
                        % ', '.join(refs))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   515
        elif len(node['backrefs']) == 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   516
            self.append(r'\renewcommand{\DEVsinglebackref}{%s}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   517
                        % node['backrefs'][0])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   518
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   519
    def visit_footnote(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   520
        self.process_backlinks(node, 'footnote')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   521
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   522
    def visit_citation(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   523
        self.process_backlinks(node, 'citation')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   524
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   525
    def before_table(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   526
        # A table contains exactly one tgroup.  See before_tgroup.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   527
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   528
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   529
    def before_tgroup(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   530
        widths = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   531
        total_width = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   532
        for i in range(int(node['cols'])):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   533
            assert isinstance(node[i], nodes.colspec)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   534
            widths.append(int(node[i]['colwidth']) + 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   535
            total_width += widths[-1]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   536
        del node[:len(widths)]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   537
        tablespec = '|'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   538
        for w in widths:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   539
            # 0.93 is probably wrong in many cases.  XXX Find a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   540
            # solution which works *always*.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   541
            tablespec += r'p{%s\textwidth}|' % (0.93 * w /
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   542
                                                max(total_width, 60))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   543
        self.append(r'\DECmaketable{%s}{' % tablespec)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   544
        self.context.append('}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   545
        raise SkipAttrParentLaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   546
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   547
    def depart_tgroup(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   548
        self.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   549
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   550
    def before_row(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   551
        raise SkipAttrParentLaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   552
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   553
    def before_thead(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   554
        raise SkipAttrParentLaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   555
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   556
    def before_tbody(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   557
        raise SkipAttrParentLaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   558
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   559
    def is_simply_entry(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   560
        return (len(node) == 1 and isinstance(node[0], nodes.paragraph) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   561
                len(node) == 0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   562
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   563
    def before_entry(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   564
        is_leftmost = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   565
        if node.hasattr('morerows'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   566
            self.document.reporter.severe('Rowspans are not supported.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   567
            # Todo: Add empty cells below rowspanning cell and issue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   568
            # warning instead of severe.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   569
        if node.hasattr('morecols'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   570
            # The author got a headache trying to implement
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   571
            # multicolumn support.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   572
            if not self.is_simply_entry(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   573
                self.document.reporter.severe(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   574
                    'Colspanning table cells may only contain one paragraph.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   575
                # Todo: Same as above.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   576
            # The number of columns this entry spans (as a string).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   577
            colspan = int(node['morecols']) + 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   578
            del node['morecols']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   579
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   580
            colspan = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   581
        # Macro to call -- \DECcolspan or \DECcolspanleft.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   582
        macro_name = r'\DECcolspan'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   583
        if node.parent.index(node) == 0:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   584
            # Leftmost column.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   585
            macro_name += 'left'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   586
            is_leftmost = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   587
        if colspan > 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   588
            self.append('%s{%s}{' % (macro_name, colspan))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   589
            self.context.append('}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   590
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   591
            # Do not add a multicolumn with colspan 1 beacuse we need
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   592
            # at least one non-multicolumn cell per column to get the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   593
            # desired column widths, and we can only do colspans with
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   594
            # cells consisting of only one paragraph.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   595
            if not is_leftmost:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   596
                self.append(r'\DECsubsequententry{')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   597
                self.context.append('}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   598
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   599
                self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   600
        if isinstance(node.parent.parent, nodes.thead):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   601
            node['tableheaderentry'] = 'true'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   602
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   603
        # Don't add \renewcommand{\DEVparent}{...} because there must
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   604
        # not be any non-expandable commands in front of \multicolumn.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   605
        raise SkipParentLaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   606
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   607
    def depart_entry(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   608
        self.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   609
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   610
    def before_substitution_definition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   611
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   612
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   613
    indentation_level = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   614
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   615
    def node_name(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   616
        return node.__class__.__name__.replace('_', '')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   617
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   618
    # Attribute propagation order.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   619
    attribute_order = ['align', 'classes', 'ids']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   620
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   621
    def attribute_cmp(self, a1, a2):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   622
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   623
        Compare attribute names `a1` and `a2`.  Used in
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   624
        propagate_attributes to determine propagation order.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   625
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   626
        See built-in function `cmp` for return value.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   627
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   628
        if a1 in self.attribute_order and a2 in self.attribute_order:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   629
            return cmp(self.attribute_order.index(a1),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   630
                       self.attribute_order.index(a2))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   631
        if (a1 in self.attribute_order) != (a2 in self.attribute_order):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   632
            # Attributes not in self.attribute_order come last.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   633
            return a1 in self.attribute_order and -1 or 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   634
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   635
            return cmp(a1, a2)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   636
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   637
    def propagate_attributes(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   638
        # Propagate attributes using \DECattr macros.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   639
        node_name = self.node_name(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   640
        attlist = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   641
        if isinstance(node, nodes.Element):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   642
            attlist = node.attlist()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   643
        attlist.sort(lambda pair1, pair2: self.attribute_cmp(pair1[0],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   644
                                                             pair2[0]))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   645
        # `numatts` may be greater than len(attlist) due to list
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   646
        # attributes.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   647
        numatts = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   648
        pass_contents = self.pass_contents(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   649
        for key, value in attlist:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   650
            if isinstance(value, ListType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   651
                self.append(r'\renewcommand{\DEVattrlen}{%s}' % len(value))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   652
                for i in range(len(value)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   653
                    self.append(r'\DECattr{%s}{%s}{%s}{%s}{' %
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   654
                                (i+1, key, self.encode(value[i], attval=key),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   655
                                 node_name))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   656
                    if not pass_contents:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   657
                        self.append('}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   658
                numatts += len(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   659
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   660
                self.append(r'\DECattr{}{%s}{%s}{%s}{' %
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   661
                            (key, self.encode(unicode(value), attval=key),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   662
                             node_name))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   663
                if not pass_contents:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   664
                    self.append('}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   665
                numatts += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   666
        if pass_contents:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   667
            self.context.append('}' * numatts)  # for Emacs: {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   668
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   669
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   670
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   671
    def visit_docinfo(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   672
        raise NotImplementedError('Docinfo not yet implemented.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   673
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   674
    def visit_document(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   675
        document = node
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   676
        # Move IDs into TextElements.  This won't work for images.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   677
        # Need to review this.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   678
        for node in document.traverse(nodes.Element):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   679
            if node.has_key('ids') and not isinstance(node,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   680
                                                      nodes.TextElement):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   681
                next_text_element = node.next_node(nodes.TextElement)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   682
                if next_text_element:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   683
                    next_text_element['ids'].extend(node['ids'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   684
                    node['ids'] = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   685
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   686
    def pass_contents(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   687
        r"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   688
        Return True if the node contents should be passed in
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   689
        \DN<nodename>{<contents>} and \DECattr{}{}{}{}{<contents>}.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   690
        Return False if the node contents should be passed in
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   691
        \DECvisit<nodename> <contents> \DECdepart<nodename>, and no
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   692
        attribute handler should be called.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   693
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   694
        # Passing the whole document or whole sections as parameters
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   695
        # to \DN... or \DECattr causes LaTeX to run out of memory.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   696
        return not isinstance(node, (nodes.document, nodes.section))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   697
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   698
    def dispatch_visit(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   699
        skip_attr = skip_parent = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   700
        # TreePruningException to be propagated.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   701
        tree_pruning_exception = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   702
        if hasattr(self, 'before_' + node.__class__.__name__):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   703
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   704
                getattr(self, 'before_' + node.__class__.__name__)(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   705
            except SkipParentLaTeX:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   706
                skip_parent = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   707
            except SkipAttrParentLaTeX:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   708
                skip_attr = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   709
                skip_parent = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   710
            except nodes.SkipNode:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   711
                raise
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   712
            except (nodes.SkipChildren, nodes.SkipSiblings), instance:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   713
                tree_pruning_exception = instance
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   714
            except nodes.SkipDeparture:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   715
                raise NotImplementedError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   716
                    'SkipDeparture not usable in LaTeX writer')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   717
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   718
        if not isinstance(node, nodes.Text):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   719
            node_name = self.node_name(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   720
            # attribute_deleters will be appended to self.context.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   721
            attribute_deleters = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   722
            if not skip_parent and not isinstance(node, nodes.document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   723
                self.append(r'\renewcommand{\DEVparent}{%s}'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   724
                            % self.node_name(node.parent))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   725
                for name, value in node.attlist():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   726
                    if not isinstance(value, ListType) and not ':' in name:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   727
                        # For non-list and non-special (like
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   728
                        # 'xml:preserve') attributes, set
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   729
                        # \DEVcurrentN<nodename>A<attribute> to the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   730
                        # attribute value, so that the value of the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   731
                        # attribute is available in the node handler
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   732
                        # and all children.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   733
                        macro = r'\DEVcurrentN%sA%s' % (node_name, name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   734
                        self.append(r'\def%s{%s}' % (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   735
                            macro, self.encode(unicode(value), attval=name)))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   736
                        # Make the attribute undefined afterwards.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   737
                        attribute_deleters.append(r'\let%s=\relax' % macro)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   738
            self.context.append('\n'.join(attribute_deleters))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   739
            if self.pass_contents(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   740
                # Call \DN<nodename>{<contents>}.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   741
                self.append(r'\DN%s{' % node_name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   742
                self.context.append('}')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   743
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   744
                # Call \DECvisit<nodename> <contents>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   745
                # \DECdepart<nodename>.  (Maybe we should use LaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   746
                # environments for this?)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   747
                self.append(r'\DECvisit%s' % node_name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   748
                self.context.append(r'\DECdepart%s' % node_name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   749
            self.indentation_level += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   750
            if not skip_attr:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   751
                self.propagate_attributes(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   752
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   753
                self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   754
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   755
        if (isinstance(node, nodes.TextElement) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   756
            not isinstance(node.parent, nodes.TextElement)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   757
            # Reset current quote to left.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   758
            self.left_quote = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   759
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   760
        # Call visit_... method.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   761
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   762
            nodes.SparseNodeVisitor.dispatch_visit(self, node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   763
        except LaTeXException:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   764
            raise NotImplementedError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   765
                'visit_... methods must not raise LaTeXExceptions')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   766
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   767
        if tree_pruning_exception:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   768
            # Propagate TreePruningException raised in before_... method.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   769
            raise tree_pruning_exception
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   770
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   771
    def is_invisible(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   772
        # Return true if node is invisible or moved away in the LaTeX
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   773
        # rendering.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   774
        return (not isinstance(node, nodes.Text) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   775
                (isinstance(node, nodes.Invisible) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   776
                 isinstance(node, nodes.footnote) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   777
                 isinstance(node, nodes.citation) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   778
                 # Assume raw nodes to be invisible.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   779
                 isinstance(node, nodes.raw) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   780
                 # Floating image or figure.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   781
                 node.get('align') in ('left', 'right')))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   782
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   783
    def is_visible(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   784
        return not self.is_invisible(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   785
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   786
    def needs_space(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   787
        """Two nodes for which `needs_space` is true need auxiliary space."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   788
        # Return true if node is a visible block-level element.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   789
        return ((isinstance(node, nodes.Body) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   790
                 isinstance(node, nodes.topic)) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   791
                not (self.is_invisible(node) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   792
                     isinstance(node.parent, nodes.TextElement)))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   793
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   794
    def always_needs_space(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   795
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   796
        Always add space around nodes for which `always_needs_space()`
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   797
        is true, regardless of whether the other node needs space as
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   798
        well.  (E.g. transition next to section.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   799
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   800
        return isinstance(node, nodes.transition)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   801
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   802
    def dispatch_departure(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   803
        # Call departure method.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   804
        nodes.SparseNodeVisitor.dispatch_departure(self, node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   805
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   806
        if not isinstance(node, nodes.Text):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   807
            # Close attribute and node handler call (\DN...{...}).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   808
            self.indentation_level -= 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   809
            self.append(self.context.pop() + self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   810
            # Delete \DECcurrentN... attribute macros.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   811
            self.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   812
            # Get next sibling.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   813
            next_node = node.next_node(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   814
                ascend=0, siblings=1, descend=0,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   815
                condition=self.is_visible)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   816
            # Insert space if necessary.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   817
            if  (self.needs_space(node) and self.needs_space(next_node) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   818
                 self.always_needs_space(node) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   819
                 self.always_needs_space(next_node)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   820
                if isinstance(node, nodes.paragraph) and isinstance(next_node, nodes.paragraph):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   821
                    # Space between paragraphs.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   822
                    self.append(r'\DECparagraphspace')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   823
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   824
                    # One of the elements is not a paragraph.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   825
                    self.append(r'\DECauxiliaryspace')