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

https://bitbucket.org/alex_muscar/myspace-competition-radar · Python · 248 lines · 189 code · 16 blank · 43 comment · 31 complexity · e91a94f0c2e5f3009ed7d394f23eb201 MD5 · raw file

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