--- a/ThirdParty/Pygments/pygments/formatters/latex.py Wed Mar 11 18:25:37 2015 +0100 +++ b/ThirdParty/Pygments/pygments/formatters/latex.py Wed Mar 11 18:32:27 2015 +0100 @@ -5,13 +5,17 @@ Formatter for LaTeX fancyvrb output. - :copyright: Copyright 2006-2013 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ +from __future__ import division + from pygments.formatter import Formatter +from pygments.lexer import Lexer from pygments.token import Token, STANDARD_TYPES -from pygments.util import get_bool_opt, get_int_opt, StringIO +from pygments.util import get_bool_opt, get_int_opt, StringIO, xrange, \ + iteritems __all__ = ['LatexFormatter'] @@ -152,7 +156,7 @@ .. sourcecode:: latex - \begin{Verbatim}[commandchars=\\{\}] + \begin{Verbatim}[commandchars=\\\{\}] \PY{k}{def }\PY{n+nf}{foo}(\PY{n}{bar}): \PY{k}{pass} \end{Verbatim} @@ -205,19 +209,40 @@ `commandprefix` The LaTeX commands used to produce colored output are constructed using this prefix and some letters (default: ``'PY'``). - *New in Pygments 0.7.* - *New in Pygments 0.10:* the default is now ``'PY'`` instead of ``'C'``. + .. versionadded:: 0.7 + .. versionchanged:: 0.10 + The default is now ``'PY'`` instead of ``'C'``. `texcomments` If set to ``True``, enables LaTeX comment lines. That is, LaTex markup in comment tokens is not escaped so that LaTeX can render it (default: - ``False``). *New in Pygments 1.2.* + ``False``). + + .. versionadded:: 1.2 `mathescape` If set to ``True``, enables LaTeX math mode escape in comments. That is, ``'$...$'`` inside a comment will trigger math mode (default: - ``False``). *New in Pygments 1.2.* + ``False``). + + .. versionadded:: 1.2 + + `escapeinside` + If set to a string of length 2, enables escaping to LaTeX. Text + delimited by these 2 characters is read as LaTeX code and + typeset accordingly. It has no effect in string literals. It has + no effect in comments if `texcomments` or `mathescape` is + set. (default: ``''``). + + .. versionadded:: 2.0 + + `envname` + Allows you to pick an alternative environment name replacing Verbatim. + The alternate environment still has to support Verbatim's option syntax. + (default: ``'Verbatim'``). + + .. versionadded:: 2.0 """ name = 'LaTeX' aliases = ['latex', 'tex'] @@ -235,10 +260,16 @@ self.commandprefix = options.get('commandprefix', 'PY') self.texcomments = get_bool_opt(options, 'texcomments', False) self.mathescape = get_bool_opt(options, 'mathescape', False) + self.escapeinside = options.get('escapeinside', '') + if len(self.escapeinside) == 2: + self.left = self.escapeinside[0] + self.right = self.escapeinside[1] + else: + self.escapeinside = '' + self.envname = options.get('envname', u'Verbatim') self._create_stylesheet() - def _create_stylesheet(self): t2n = self.ttype2name = {Token: ''} c2d = self.cmd2def = {} @@ -246,7 +277,7 @@ def rgbcolor(col): if col: - return ','.join(['%.2f' %(int(col[i] + col[i + 1], 16) / 255.0) + return ','.join(['%.2f' % (int(col[i] + col[i + 1], 16) / 255.0) for i in (0, 2, 4)]) else: return '1,1,1' @@ -291,7 +322,7 @@ """ cp = self.commandprefix styles = [] - for name, definition in self.cmd2def.items(): + for name, definition in iteritems(self.cmd2def): styles.append(r'\expandafter\def\csname %s@tok@%s\endcsname{%s}' % (cp, name, definition)) return STYLE_TEMPLATE % {'cp': self.commandprefix, @@ -306,24 +337,24 @@ realoutfile = outfile outfile = StringIO() - outfile.write(r'\begin{Verbatim}[commandchars=\\\{\}') + outfile.write(u'\\begin{' + self.envname + u'}[commandchars=\\\\\\{\\}') if self.linenos: start, step = self.linenostart, self.linenostep - outfile.write(',numbers=left' + - (start and ',firstnumber=%d' % start or '') + - (step and ',stepnumber=%d' % step or '')) - if self.mathescape or self.texcomments: - outfile.write(r',codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}') + outfile.write(u',numbers=left' + + (start and u',firstnumber=%d' % start or u'') + + (step and u',stepnumber=%d' % step or u'')) + if self.mathescape or self.texcomments or self.escapeinside: + outfile.write(u',codes={\\catcode`\\$=3\\catcode`\\^=7\\catcode`\\_=8}') if self.verboptions: - outfile.write(',' + self.verboptions) - outfile.write(']\n') + outfile.write(u',' + self.verboptions) + outfile.write(u']\n') for ttype, value in tokensource: if ttype in Token.Comment: if self.texcomments: # Try to guess comment starting lexeme and escape it ... start = value[0:1] - for i in range(1, len(value)): + for i in xrange(1, len(value)): if start[0] != value[i]: break start += value[i] @@ -342,9 +373,22 @@ parts[i] = escape_tex(part, self.commandprefix) in_math = not in_math value = '$'.join(parts) + elif self.escapeinside: + text = value + value = '' + while len(text) > 0: + a, sep1, text = text.partition(self.left) + if len(sep1) > 0: + b, sep2, text = text.partition(self.right) + if len(sep2) > 0: + value += escape_tex(a, self.commandprefix) + b + else: + value += escape_tex(a + sep1 + b, self.commandprefix) + else: + value = value + escape_tex(a, self.commandprefix) else: value = escape_tex(value, self.commandprefix) - else: + elif ttype not in Token.Escape: value = escape_tex(value, self.commandprefix) styles = [] while ttype is not Token: @@ -366,13 +410,67 @@ else: outfile.write(value) - outfile.write('\\end{Verbatim}\n') + outfile.write(u'\\end{' + self.envname + u'}\n') if self.full: realoutfile.write(DOC_TEMPLATE % dict(docclass = self.docclass, preamble = self.preamble, title = self.title, - encoding = self.encoding or 'latin1', + encoding = self.encoding or 'utf8', styledefs = self.get_style_defs(), code = outfile.getvalue())) + + +class LatexEmbeddedLexer(Lexer): + r""" + + This lexer takes one lexer as argument, the lexer for the language + being formatted, and the left and right delimiters for escaped text. + + First everything is scanned using the language lexer to obtain + strings and comments. All other consecutive tokens are merged and + the resulting text is scanned for escaped segments, which are given + the Token.Escape type. Finally text that is not escaped is scanned + again with the language lexer. + """ + def __init__(self, left, right, lang, **options): + self.left = left + self.right = right + self.lang = lang + Lexer.__init__(self, **options) + + def get_tokens_unprocessed(self, text): + buf = '' + idx = 0 + for i, t, v in self.lang.get_tokens_unprocessed(text): + if t in Token.Comment or t in Token.String: + if buf: + for x in self.get_tokens_aux(idx, buf): + yield x + buf = '' + yield i, t, v + else: + if not buf: + idx = i + buf += v + if buf: + for x in self.get_tokens_aux(idx, buf): + yield x + + def get_tokens_aux(self, index, text): + while text: + a, sep1, text = text.partition(self.left) + if a: + for i, t, v in self.lang.get_tokens_unprocessed(a): + yield index + i, t, v + index += len(a) + if sep1: + b, sep2, text = text.partition(self.right) + if sep2: + yield index + len(sep1), Token.Escape, b + index += len(sep1) + len(b) + len(sep2) + else: + yield index, Token.Error, sep1 + index += len(sep1) + text = b