diff options
Diffstat (limited to 'pygments/formatters/latex.py')
-rw-r--r-- | pygments/formatters/latex.py | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/pygments/formatters/latex.py b/pygments/formatters/latex.py new file mode 100644 index 00000000..84fe5d12 --- /dev/null +++ b/pygments/formatters/latex.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +""" + pygments.formatters.latex + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Formatter for LaTeX fancyvrb output. + + :copyright: 2006 by Georg Brandl. + :license: GNU LGPL, see LICENSE for more details. +""" +import StringIO + +from pygments.formatter import Formatter +from pygments.token import Token +from pygments.util import get_bool_opt, get_int_opt + + +__all__ = ['LatexFormatter'] + + +def escape_tex(text): + return text.replace('@', '\x00'). \ + replace('[', '\x01'). \ + replace(']', '\x02'). \ + replace('\x00', '@at[]').\ + replace('\x01', '@lb[]').\ + replace('\x02', '@rb[]') + + +DOC_TEMPLATE = r''' +\documentclass{%(docclass)s} +\usepackage{fancyvrb} +\usepackage{color} +%(preamble)s + +%(styledefs)s + +\begin{document} + +\section*{%(title)s} + +%(code)s +\end{document} +''' + + +class LatexFormatter(Formatter): + """ + Output LaTeX "color" and "fancyvrb" control sequences. + """ + + def __init__(self, **options): + """ + Additional options accepted: + + ``docclass`` + If ``full`` is true, this is the document class to use (default: 'article'). + ``preamble`` + If ``full`` is true, this can be further preamble commands (default: ''). + ``linenos`` + If true, output line numbers (default: False). + ``linenostart`` + The line number for the first line (default: 1). + ``linenostep`` + If set to a number n > 1, only every nth line number is printed (default: 1). + ``verboptions`` + Additional options given to the Verbatim environment (default: ''). + ``nobackground`` + If set to ``True`` the formatter won't output the background color + for the overall element (default: ``False``) + Note that light colors on dark background with this option disabled + won't be readable very good. + """ + Formatter.__init__(self, **options) + self.docclass = options.get('docclass', 'article') + self.preamble = options.get('preamble', '') + self.linenos = get_bool_opt(options, 'linenos', False) + self.linenostart = abs(get_int_opt(options, 'linenostart', 1)) + self.linenostep = abs(get_int_opt(options, 'linenostep', 1)) + self.verboptions = options.get('verboptions', '') + self.nobackground = get_bool_opt(options, 'nobackground', False) + + self._create_stylecmds() + + + def _create_stylecmds(self): + t2c = self.ttype2cmd = {Token: ''} + c2d = self.cmd2def = {} + + letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + first = iter(letters) + second = iter(letters) + firstl = first.next() + + def rgbcolor(col): + if col: + return ','.join(['%.2f' %(int(col[i] + col[i + 1], 16) / 255.0) + for i in (0, 2, 4)]) + else: + return '1,1,1' + + for ttype, ndef in self.style: + cmndef = '#1' + if ndef['bold']: + cmndef = r'\textbf{' + cmndef + '}' + if ndef['italic']: + cmndef = r'\textit{' + cmndef + '}' + if ndef['underline']: + cmndef = r'\underline{' + cmndef + '}' + if ndef['color']: + cmndef = r'\textcolor[rgb]{%s}{%s}' % ( + rgbcolor(ndef['color']), + cmndef + ) + if ndef['border']: + cmndef = r'\fcolorbox[rgb]{%s}{%s}{%s}' % ( + rgbcolor(ndef['border']), + rgbcolor(ndef['bgcolor']), + cmndef + ) + elif ndef['bgcolor']: + cmndef = r'\colorbox[rgb]{%s}{%s}' % ( + rgbcolor(ndef['bgcolor']), + cmndef + ) + if cmndef == '#1': + continue + try: + alias = 'C' + firstl + second.next() + except StopIteration: + firstl = first.next() + second = iter(letters) + alias = 'C' + firstl + second.next() + t2c[ttype] = alias + c2d[alias] = cmndef + + def get_style_defs(self, arg=''): + """ + Return the \\newcommand sequences needed to define the commands + used to format text in the verbatim environment. If ``arg`` is + given and true, use \\renewcommand instead. + """ + nc = (arg and r'\renewcommand' or r'\newcommand') + return '%s\\at{@}\n%s\\lb{[}\n%s\\rb{]}\n' % (nc, nc, nc) + \ + '\n'.join(['%s\\%s[1]{%s}' % (nc, alias, cmndef) + for alias, cmndef in self.cmd2def.iteritems() + if cmndef != '#1']) + + def format(self, tokensource, outfile): + #XXX: add support for background colors!!!!!!!111!1 + + if self.full: + realoutfile = outfile + outfile = StringIO.StringIO() + + outfile.write(r'\begin{Verbatim}[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.verboptions: + outfile.write(',' + self.verboptions) + outfile.write(']\n') + + for ttype, value in tokensource: + value = escape_tex(value) + cmd = self.ttype2cmd.get(ttype) + while cmd is None: + ttype = ttype.parent + cmd = self.ttype2cmd.get(ttype) + if cmd: + spl = value.split('\n') + for line in spl[:-1]: + if line: + outfile.write("@%s[%s]" % (cmd, line)) + outfile.write('\n') + if spl[-1]: + outfile.write("@%s[%s]" % (cmd, spl[-1])) + else: + outfile.write(value) + + outfile.write('\n\\end{Verbatim}\n') + + if self.full: + realoutfile.write(DOC_TEMPLATE % + dict(docclass = self.docclass, + preamble = self.preamble, + title = self.title, + styledefs = self.get_style_defs(), + code = outfile.getvalue())) |