PageRenderTime 30ms CodeModel.GetById 10ms app.highlight 18ms RepoModel.GetById 0ms app.codeStats 0ms

/console/app/pygments/formatters/latex.py

https://bitbucket.org/alex_muscar/myspace-competition-radar
Python | 248 lines | 226 code | 11 blank | 11 comment | 16 complexity | e91a94f0c2e5f3009ed7d394f23eb201 MD5 | raw file
Possible License(s): GPL-3.0
  1# -*- coding: utf-8 -*-
  2"""
  3    pygments.formatters.latex
  4    ~~~~~~~~~~~~~~~~~~~~~~~~~
  5
  6    Formatter for LaTeX fancyvrb output.
  7
  8    :copyright: 2006-2007 by Georg Brandl.
  9    :license: BSD, see LICENSE for more details.
 10"""
 11import StringIO
 12
 13from pygments.formatter import Formatter
 14from pygments.token import Token
 15from pygments.util import get_bool_opt, get_int_opt
 16
 17
 18__all__ = ['LatexFormatter']
 19
 20
 21def escape_tex(text):
 22    return text.replace('@', '\x00').    \
 23                replace('[', '\x01').    \
 24                replace(']', '\x02').    \
 25                replace('\x00', '@at[]').\
 26                replace('\x01', '@lb[]').\
 27                replace('\x02', '@rb[]')
 28
 29
 30DOC_TEMPLATE = r'''
 31\documentclass{%(docclass)s}
 32\usepackage{fancyvrb}
 33\usepackage{color}
 34\usepackage[%(encoding)s]{inputenc}
 35%(preamble)s
 36
 37%(styledefs)s
 38
 39\begin{document}
 40
 41\section*{%(title)s}
 42
 43%(code)s
 44\end{document}
 45'''
 46
 47
 48class LatexFormatter(Formatter):
 49    r"""
 50    Format tokens as LaTeX code. This needs the `fancyvrb` and `color`
 51    standard packages.
 52
 53    Without the `full` option, code is formatted as one ``Verbatim``
 54    environment, like this:
 55
 56    .. sourcecode:: latex
 57
 58        \begin{Verbatim}[commandchars=@\[\]]
 59        @PYan[def ]@PYax[foo](bar):
 60            @PYan[pass]
 61        \end{Verbatim}
 62
 63    The command sequences used here (``@PYan`` etc.) are generated from the given
 64    `style` and can be retrieved using the `get_style_defs` method.
 65
 66    With the `full` option, a complete LaTeX document is output, including
 67    the command definitions in the preamble.
 68
 69    The `get_style_defs()` method of a `LatexFormatter` returns a string
 70    containing ``\newcommand`` commands defining the commands used inside the
 71    ``Verbatim`` environments.
 72
 73    Additional options accepted:
 74
 75    `style`
 76        The style to use, can be a string or a Style subclass (default:
 77        ``'default'``).
 78
 79    `full`
 80        Tells the formatter to output a "full" document, i.e. a complete
 81        self-contained document (default: ``False``).
 82
 83    `title`
 84        If `full` is true, the title that should be used to caption the
 85        document (default: ``''``).
 86
 87    `docclass`
 88        If the `full` option is enabled, this is the document class to use
 89        (default: ``'article'``).
 90
 91    `preamble`
 92        If the `full` option is enabled, this can be further preamble commands,
 93        e.g. ``\usepackage`` (default: ``''``).
 94
 95    `linenos`
 96        If set to ``True``, output line numbers (default: ``False``).
 97
 98    `linenostart`
 99        The line number for the first line (default: ``1``).
100
101    `linenostep`
102        If set to a number n > 1, only every nth line number is printed.
103
104    `verboptions`
105        Additional options given to the Verbatim environment (see the *fancyvrb*
106        docs for possible values) (default: ``''``).
107
108    `commandprefix`
109        The LaTeX commands used to produce colored output are constructed
110        using this prefix and some letters (default: ``'PY'``).
111        *New in Pygments 0.7.*
112
113        *New in Pygments 0.10:* the default is now ``'PY'`` instead of ``'C'``.
114    """
115    name = 'LaTeX'
116    aliases = ['latex', 'tex']
117    filenames = ['*.tex']
118
119    def __init__(self, **options):
120        Formatter.__init__(self, **options)
121        self.docclass = options.get('docclass', 'article')
122        self.preamble = options.get('preamble', '')
123        self.linenos = get_bool_opt(options, 'linenos', False)
124        self.linenostart = abs(get_int_opt(options, 'linenostart', 1))
125        self.linenostep = abs(get_int_opt(options, 'linenostep', 1))
126        self.verboptions = options.get('verboptions', '')
127        self.nobackground = get_bool_opt(options, 'nobackground', False)
128        self.commandprefix = options.get('commandprefix', 'PY')
129
130        self._create_stylecmds()
131
132
133    def _create_stylecmds(self):
134        t2c = self.ttype2cmd = {Token: ''}
135        c2d = self.cmd2def = {}
136        cp = self.commandprefix
137
138        letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
139        first = iter(letters)
140        second = iter(letters)
141        firstl = first.next()
142
143        def rgbcolor(col):
144            if col:
145                return ','.join(['%.2f' %(int(col[i] + col[i + 1], 16) / 255.0)
146                                 for i in (0, 2, 4)])
147            else:
148                return '1,1,1'
149
150        for ttype, ndef in self.style:
151            cmndef = '#1'
152            if ndef['bold']:
153                cmndef = r'\textbf{' + cmndef + '}'
154            if ndef['italic']:
155                cmndef = r'\textit{' + cmndef + '}'
156            if ndef['underline']:
157                cmndef = r'\underline{' + cmndef + '}'
158            if ndef['roman']:
159                cmndef = r'\textrm{' + cmndef + '}'
160            if ndef['sans']:
161                cmndef = r'\textsf{' + cmndef + '}'
162            if ndef['mono']:
163                cmndef = r'\texttt{' + cmndef + '}'
164            if ndef['color']:
165                cmndef = r'\textcolor[rgb]{%s}{%s}' % (
166                    rgbcolor(ndef['color']),
167                    cmndef
168                )
169            if ndef['border']:
170                cmndef = r'\fcolorbox[rgb]{%s}{%s}{%s}' % (
171                    rgbcolor(ndef['border']),
172                    rgbcolor(ndef['bgcolor']),
173                    cmndef
174                )
175            elif ndef['bgcolor']:
176                cmndef = r'\colorbox[rgb]{%s}{%s}' % (
177                    rgbcolor(ndef['bgcolor']),
178                    cmndef
179                )
180            if cmndef == '#1':
181                continue
182            try:
183                alias = cp + firstl + second.next()
184            except StopIteration:
185                firstl = first.next()
186                second = iter(letters)
187                alias = cp + firstl + second.next()
188            t2c[ttype] = alias
189            c2d[alias] = cmndef
190
191    def get_style_defs(self, arg=''):
192        """
193        Return the \\newcommand sequences needed to define the commands
194        used to format text in the verbatim environment. ``arg`` is ignored.
195        """
196        nc = '\\newcommand'
197        return '%s\\at{@}\n%s\\lb{[}\n%s\\rb{]}\n' % (nc, nc, nc) + \
198               '\n'.join(['\\newcommand\\%s[1]{%s}' % (alias, cmndef)
199                          for alias, cmndef in self.cmd2def.iteritems()
200                          if cmndef != '#1'])
201
202    def format(self, tokensource, outfile):
203        # TODO: add support for background colors
204        enc = self.encoding
205
206        if self.full:
207            realoutfile = outfile
208            outfile = StringIO.StringIO()
209
210        outfile.write(r'\begin{Verbatim}[commandchars=@\[\]')
211        if self.linenos:
212            start, step = self.linenostart, self.linenostep
213            outfile.write(',numbers=left' +
214                          (start and ',firstnumber=%d' % start or '') +
215                          (step and ',stepnumber=%d' % step or ''))
216        if self.verboptions:
217            outfile.write(',' + self.verboptions)
218        outfile.write(']\n')
219
220        for ttype, value in tokensource:
221            if enc:
222                value = value.encode(enc)
223            value = escape_tex(value)
224            cmd = self.ttype2cmd.get(ttype)
225            while cmd is None:
226                ttype = ttype.parent
227                cmd = self.ttype2cmd.get(ttype)
228            if cmd:
229                spl = value.split('\n')
230                for line in spl[:-1]:
231                    if line:
232                        outfile.write("@%s[%s]" % (cmd, line))
233                    outfile.write('\n')
234                if spl[-1]:
235                    outfile.write("@%s[%s]" % (cmd, spl[-1]))
236            else:
237                outfile.write(value)
238
239        outfile.write('\\end{Verbatim}\n')
240
241        if self.full:
242            realoutfile.write(DOC_TEMPLATE %
243                dict(docclass  = self.docclass,
244                     preamble  = self.preamble,
245                     title     = self.title,
246                     encoding  = self.encoding or 'latin1',
247                     styledefs = self.get_style_defs(),
248                     code      = outfile.getvalue()))