Code snippets are bits of re-usable code submitted by the ReportLab community. We don't promise that they are accurate, up-to-date or correct - use them at your own risk!

We'd love it if you could participate by submitting your own snippets and sharing your experience with others by commenting. You will need to create a user account by filling out our very simple form.

View all snippets

Colourising code with Pygments

17 Dec 2009
opensource rl-toolkit

A long time ago, Dinu Gherman created a demo to output colourised Python code in PDF. Since then the Pygments library has become the standard, and does most of the heavy work for us. It turned out that its output only needs modest tweaks to work within our own XPreformatted flowables.

The attached script shows how Pygments can be used to transform Python code.

The 'pygments2xpre' function is available in reportlab.lib.pygments2xpre as of revision 3622 (17 Dec 2009); for anyone on older versions, just use the code in this snippet.

"""Helps you output colourised code snippets in ReportLab documents.

Platypus has an 'XPreformatted' flowable for handling preformatted
text, with variations in fonts and colors.   If Pygments is installed,
calling 'pygments2xpre' will return content suitable for display in
an XPreformatted object.  If it's not installed, you won't get colours.

__all__ = ('pygments2xpre',)

def _2xpre(s,styles):
    "Helper to transform Pygments HTML output to ReportLab markup"
    s = s.replace('<div class="highlight">','')
    s = s.replace('</div>','')
    s = s.replace('<pre>','')
    s = s.replace('</pre>','')
    s = s.replace('</span>','</font>')
    for k,c in styles+[('p','#000000'),('n','#000000')]:
        s = s.replace('<span class="%s">' % k,'<font color="%s">' % c)
    return s

def pygments2xpre(s):
    "Return markup suitable for XPreformatted"
        from pygments import highlight
        from pygments.lexers import PythonLexer
        from pygments.formatters import HtmlFormatter
    except ImportError:
        return s

    l = PythonLexer()
    h = HtmlFormatter()
    from StringIO import StringIO
    out = StringIO()
    styles = [(cls, style.split(';')[0].split(':')[1].strip())
                for cls, (style, ttype, level) in h.class2style.iteritems()
                if cls and style and style.startswith('color:')]
    return _2xpre(out.getvalue(),styles)

def convertSourceFiles(filenames):
    "Helper function - makes minimal PDF document"

    from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, XPreformatted
    from reportlab.lib.styles import getSampleStyleSheet
    doc = SimpleDocTemplate("pygments2xpre.pdf")
    S = [].append
    for filename in filenames:
        src = open(filename, 'r').read()
        fmt = pygments2xpre(src)
        S(XPreformatted(fmt, style=styC))
    print 'saved pygments2xpre.pdf'

if __name__=='__main__':
    import sys
    filenames = sys.argv[1:]
    if not filenames:
        print 'usage: [] [...]'