comparison MoinMoin/support/pygments/formatters/latex.py @ 6097:815981fad7fd

upgrade pygments from 1.6 to 2.1.3
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 05 Sep 2016 23:55:33 +0200
parents b48a69886ca4
children
comparison
equal deleted inserted replaced
6096:86a41c2bedec 6097:815981fad7fd
3 pygments.formatters.latex 3 pygments.formatters.latex
4 ~~~~~~~~~~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 Formatter for LaTeX fancyvrb output. 6 Formatter for LaTeX fancyvrb output.
7 7
8 :copyright: Copyright 2006-2013 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2015 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11 11
12 from __future__ import division
13
12 from pygments.formatter import Formatter 14 from pygments.formatter import Formatter
15 from pygments.lexer import Lexer
13 from pygments.token import Token, STANDARD_TYPES 16 from pygments.token import Token, STANDARD_TYPES
14 from pygments.util import get_bool_opt, get_int_opt, StringIO 17 from pygments.util import get_bool_opt, get_int_opt, StringIO, xrange, \
18 iteritems
15 19
16 20
17 __all__ = ['LatexFormatter'] 21 __all__ = ['LatexFormatter']
18 22
19 23
150 Without the `full` option, code is formatted as one ``Verbatim`` 154 Without the `full` option, code is formatted as one ``Verbatim``
151 environment, like this: 155 environment, like this:
152 156
153 .. sourcecode:: latex 157 .. sourcecode:: latex
154 158
155 \begin{Verbatim}[commandchars=\\{\}] 159 \begin{Verbatim}[commandchars=\\\{\}]
156 \PY{k}{def }\PY{n+nf}{foo}(\PY{n}{bar}): 160 \PY{k}{def }\PY{n+nf}{foo}(\PY{n}{bar}):
157 \PY{k}{pass} 161 \PY{k}{pass}
158 \end{Verbatim} 162 \end{Verbatim}
159 163
160 The special command used here (``\PY``) and all the other macros it needs 164 The special command used here (``\PY``) and all the other macros it needs
203 docs for possible values) (default: ``''``). 207 docs for possible values) (default: ``''``).
204 208
205 `commandprefix` 209 `commandprefix`
206 The LaTeX commands used to produce colored output are constructed 210 The LaTeX commands used to produce colored output are constructed
207 using this prefix and some letters (default: ``'PY'``). 211 using this prefix and some letters (default: ``'PY'``).
208 *New in Pygments 0.7.* 212
209 213 .. versionadded:: 0.7
210 *New in Pygments 0.10:* the default is now ``'PY'`` instead of ``'C'``. 214 .. versionchanged:: 0.10
215 The default is now ``'PY'`` instead of ``'C'``.
211 216
212 `texcomments` 217 `texcomments`
213 If set to ``True``, enables LaTeX comment lines. That is, LaTex markup 218 If set to ``True``, enables LaTeX comment lines. That is, LaTex markup
214 in comment tokens is not escaped so that LaTeX can render it (default: 219 in comment tokens is not escaped so that LaTeX can render it (default:
215 ``False``). *New in Pygments 1.2.* 220 ``False``).
221
222 .. versionadded:: 1.2
216 223
217 `mathescape` 224 `mathescape`
218 If set to ``True``, enables LaTeX math mode escape in comments. That 225 If set to ``True``, enables LaTeX math mode escape in comments. That
219 is, ``'$...$'`` inside a comment will trigger math mode (default: 226 is, ``'$...$'`` inside a comment will trigger math mode (default:
220 ``False``). *New in Pygments 1.2.* 227 ``False``).
228
229 .. versionadded:: 1.2
230
231 `escapeinside`
232 If set to a string of length 2, enables escaping to LaTeX. Text
233 delimited by these 2 characters is read as LaTeX code and
234 typeset accordingly. It has no effect in string literals. It has
235 no effect in comments if `texcomments` or `mathescape` is
236 set. (default: ``''``).
237
238 .. versionadded:: 2.0
239
240 `envname`
241 Allows you to pick an alternative environment name replacing Verbatim.
242 The alternate environment still has to support Verbatim's option syntax.
243 (default: ``'Verbatim'``).
244
245 .. versionadded:: 2.0
221 """ 246 """
222 name = 'LaTeX' 247 name = 'LaTeX'
223 aliases = ['latex', 'tex'] 248 aliases = ['latex', 'tex']
224 filenames = ['*.tex'] 249 filenames = ['*.tex']
225 250
233 self.verboptions = options.get('verboptions', '') 258 self.verboptions = options.get('verboptions', '')
234 self.nobackground = get_bool_opt(options, 'nobackground', False) 259 self.nobackground = get_bool_opt(options, 'nobackground', False)
235 self.commandprefix = options.get('commandprefix', 'PY') 260 self.commandprefix = options.get('commandprefix', 'PY')
236 self.texcomments = get_bool_opt(options, 'texcomments', False) 261 self.texcomments = get_bool_opt(options, 'texcomments', False)
237 self.mathescape = get_bool_opt(options, 'mathescape', False) 262 self.mathescape = get_bool_opt(options, 'mathescape', False)
263 self.escapeinside = options.get('escapeinside', '')
264 if len(self.escapeinside) == 2:
265 self.left = self.escapeinside[0]
266 self.right = self.escapeinside[1]
267 else:
268 self.escapeinside = ''
269 self.envname = options.get('envname', u'Verbatim')
238 270
239 self._create_stylesheet() 271 self._create_stylesheet()
240
241 272
242 def _create_stylesheet(self): 273 def _create_stylesheet(self):
243 t2n = self.ttype2name = {Token: ''} 274 t2n = self.ttype2name = {Token: ''}
244 c2d = self.cmd2def = {} 275 c2d = self.cmd2def = {}
245 cp = self.commandprefix 276 cp = self.commandprefix
246 277
247 def rgbcolor(col): 278 def rgbcolor(col):
248 if col: 279 if col:
249 return ','.join(['%.2f' %(int(col[i] + col[i + 1], 16) / 255.0) 280 return ','.join(['%.2f' % (int(col[i] + col[i + 1], 16) / 255.0)
250 for i in (0, 2, 4)]) 281 for i in (0, 2, 4)])
251 else: 282 else:
252 return '1,1,1' 283 return '1,1,1'
253 284
254 for ttype, ndef in self.style: 285 for ttype, ndef in self.style:
289 Return the command sequences needed to define the commands 320 Return the command sequences needed to define the commands
290 used to format text in the verbatim environment. ``arg`` is ignored. 321 used to format text in the verbatim environment. ``arg`` is ignored.
291 """ 322 """
292 cp = self.commandprefix 323 cp = self.commandprefix
293 styles = [] 324 styles = []
294 for name, definition in self.cmd2def.iteritems(): 325 for name, definition in iteritems(self.cmd2def):
295 styles.append(r'\expandafter\def\csname %s@tok@%s\endcsname{%s}' % 326 styles.append(r'\expandafter\def\csname %s@tok@%s\endcsname{%s}' %
296 (cp, name, definition)) 327 (cp, name, definition))
297 return STYLE_TEMPLATE % {'cp': self.commandprefix, 328 return STYLE_TEMPLATE % {'cp': self.commandprefix,
298 'styles': '\n'.join(styles)} 329 'styles': '\n'.join(styles)}
299 330
304 335
305 if self.full: 336 if self.full:
306 realoutfile = outfile 337 realoutfile = outfile
307 outfile = StringIO() 338 outfile = StringIO()
308 339
309 outfile.write(ur'\begin{Verbatim}[commandchars=\\\{\}') 340 outfile.write(u'\\begin{' + self.envname + u'}[commandchars=\\\\\\{\\}')
310 if self.linenos: 341 if self.linenos:
311 start, step = self.linenostart, self.linenostep 342 start, step = self.linenostart, self.linenostep
312 outfile.write(u',numbers=left' + 343 outfile.write(u',numbers=left' +
313 (start and u',firstnumber=%d' % start or u'') + 344 (start and u',firstnumber=%d' % start or u'') +
314 (step and u',stepnumber=%d' % step or u'')) 345 (step and u',stepnumber=%d' % step or u''))
315 if self.mathescape or self.texcomments: 346 if self.mathescape or self.texcomments or self.escapeinside:
316 outfile.write(ur',codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8}') 347 outfile.write(u',codes={\\catcode`\\$=3\\catcode`\\^=7\\catcode`\\_=8}')
317 if self.verboptions: 348 if self.verboptions:
318 outfile.write(u',' + self.verboptions) 349 outfile.write(u',' + self.verboptions)
319 outfile.write(u']\n') 350 outfile.write(u']\n')
320 351
321 for ttype, value in tokensource: 352 for ttype, value in tokensource:
327 if start[0] != value[i]: 358 if start[0] != value[i]:
328 break 359 break
329 start += value[i] 360 start += value[i]
330 361
331 value = value[len(start):] 362 value = value[len(start):]
332 start = escape_tex(start, self.commandprefix) 363 start = escape_tex(start, cp)
333 364
334 # ... but do not escape inside comment. 365 # ... but do not escape inside comment.
335 value = start + value 366 value = start + value
336 elif self.mathescape: 367 elif self.mathescape:
337 # Only escape parts not inside a math environment. 368 # Only escape parts not inside a math environment.
338 parts = value.split('$') 369 parts = value.split('$')
339 in_math = False 370 in_math = False
340 for i, part in enumerate(parts): 371 for i, part in enumerate(parts):
341 if not in_math: 372 if not in_math:
342 parts[i] = escape_tex(part, self.commandprefix) 373 parts[i] = escape_tex(part, cp)
343 in_math = not in_math 374 in_math = not in_math
344 value = '$'.join(parts) 375 value = '$'.join(parts)
376 elif self.escapeinside:
377 text = value
378 value = ''
379 while text:
380 a, sep1, text = text.partition(self.left)
381 if sep1:
382 b, sep2, text = text.partition(self.right)
383 if sep2:
384 value += escape_tex(a, cp) + b
385 else:
386 value += escape_tex(a + sep1 + b, cp)
387 else:
388 value += escape_tex(a, cp)
345 else: 389 else:
346 value = escape_tex(value, self.commandprefix) 390 value = escape_tex(value, cp)
347 else: 391 elif ttype not in Token.Escape:
348 value = escape_tex(value, self.commandprefix) 392 value = escape_tex(value, cp)
349 styles = [] 393 styles = []
350 while ttype is not Token: 394 while ttype is not Token:
351 try: 395 try:
352 styles.append(t2n[ttype]) 396 styles.append(t2n[ttype])
353 except KeyError: 397 except KeyError:
364 if spl[-1]: 408 if spl[-1]:
365 outfile.write("\\%s{%s}{%s}" % (cp, styleval, spl[-1])) 409 outfile.write("\\%s{%s}{%s}" % (cp, styleval, spl[-1]))
366 else: 410 else:
367 outfile.write(value) 411 outfile.write(value)
368 412
369 outfile.write(u'\\end{Verbatim}\n') 413 outfile.write(u'\\end{' + self.envname + u'}\n')
370 414
371 if self.full: 415 if self.full:
416 encoding = self.encoding or 'utf8'
417 # map known existings encodings from LaTeX distribution
418 encoding = {
419 'utf_8': 'utf8',
420 'latin_1': 'latin1',
421 'iso_8859_1': 'latin1',
422 }.get(encoding.replace('-', '_'), encoding)
372 realoutfile.write(DOC_TEMPLATE % 423 realoutfile.write(DOC_TEMPLATE %
373 dict(docclass = self.docclass, 424 dict(docclass = self.docclass,
374 preamble = self.preamble, 425 preamble = self.preamble,
375 title = self.title, 426 title = self.title,
376 encoding = self.encoding or 'latin1', 427 encoding = encoding,
377 styledefs = self.get_style_defs(), 428 styledefs = self.get_style_defs(),
378 code = outfile.getvalue())) 429 code = outfile.getvalue()))
430
431
432 class LatexEmbeddedLexer(Lexer):
433 """
434 This lexer takes one lexer as argument, the lexer for the language
435 being formatted, and the left and right delimiters for escaped text.
436
437 First everything is scanned using the language lexer to obtain
438 strings and comments. All other consecutive tokens are merged and
439 the resulting text is scanned for escaped segments, which are given
440 the Token.Escape type. Finally text that is not escaped is scanned
441 again with the language lexer.
442 """
443 def __init__(self, left, right, lang, **options):
444 self.left = left
445 self.right = right
446 self.lang = lang
447 Lexer.__init__(self, **options)
448
449 def get_tokens_unprocessed(self, text):
450 buf = ''
451 idx = 0
452 for i, t, v in self.lang.get_tokens_unprocessed(text):
453 if t in Token.Comment or t in Token.String:
454 if buf:
455 for x in self.get_tokens_aux(idx, buf):
456 yield x
457 buf = ''
458 yield i, t, v
459 else:
460 if not buf:
461 idx = i
462 buf += v
463 if buf:
464 for x in self.get_tokens_aux(idx, buf):
465 yield x
466
467 def get_tokens_aux(self, index, text):
468 while text:
469 a, sep1, text = text.partition(self.left)
470 if a:
471 for i, t, v in self.lang.get_tokens_unprocessed(a):
472 yield index + i, t, v
473 index += len(a)
474 if sep1:
475 b, sep2, text = text.partition(self.right)
476 if sep2:
477 yield index + len(sep1), Token.Escape, b
478 index += len(sep1) + len(b) + len(sep2)
479 else:
480 yield index, Token.Error, sep1
481 index += len(sep1)
482 text = b