using more than one highlight color in pygments
<p>I'm using pygments to highlight lines from a file, but I want to highlight different lines with different colors.</p>

<p><strong>note</strong> While I was writing this question I tried different things until I found what looks like a decent solution that solves my problem. I'll post it in the answers.</p>

<p>My first attempt at altering the default yellow (which is very pale) was:</p>

<pre class="lang-py prettyprint-override"><code>HIGHLIGHT_COLOR = '#F4E004'

formatter = HtmlFormatter(linenos='inline', hl_lines=hl_lines, lineanchors='foo')
style = formatter.get_style_defs()
with open(the_xml_fullpath) as f:
    highlighted = highlight(f.read(), XmlLexer(), formatter)
# make the yellow more ...yellow
_style = re.sub(r'background-color: \#.+ ', 'background-color: {} '.format(HIGHLIGHT_COLOR), style)
</code></pre>

<p>Now I am fully aware of <a href="http://stackoverflow.com/a/1732454/204634">the perils of using a regular expression to parse HTML</a> but I thought the only alternative was to use the <code>noclasses=True</code> option of <code>highlight()</code> which does not use CSS classes inline CSS and then iterate through the entire file and replace the background colour of the lines I want.</p>

<p>So my question is: how can I highlight different set of lines using pygments with different colors?</p>

<p>My solution subclassed the <code>HtmlFormatter</code> class as suggested by the documentation like this:</p>

<pre class="lang-py prettyprint-override"><code>class MyFormatter(HtmlFormatter):
    """Overriding formatter to highlight more than one kind of lines"""
    def __init__(self, **kwargs):
        super(MyFormatter, self).__init__(**kwargs)
        # a list of [ (highlight_colour, [lines]) ]
        self.highlight_groups = kwargs.get('highlight_groups', [])

    def wrap(self, source, outfile):
        return self._wrap_code(source)

    # generator: returns 0, html if it's not a source line; 1, line if it is
    def _wrap_code(self, source):
        _prefix = ''
        if self.cssclass is not None:
            _prefix += '&lt;div class="highlight"&gt;'
        if self.filename is not None:
            _prefix += '&lt;span class="filename"&gt;{}&lt;/span&gt;'.format(self.filename)
        yield 0, _prefix + '&lt;pre&gt;'

        for count, _t in enumerate(source):
            i, t = _t
            if i == 1:
                # it's a line of formatted code
                for highlight_group in self.highlight_groups:
                    col, lines = highlight_group
                    # count starts from 0...
                    if (count + 1) in lines:
                        # it's a highlighted line - set the colour
                        _row = '&lt;span style="background-color:{}"&gt;{}&lt;/span&gt;'.format(col, t)
                        t = _row
            yield i, t

        # close open things
        _postfix = ''
        if self.cssclass is not None:
            _postfix += '&lt;/div&gt;'
        yield 0, '&lt;/pre&gt;' + _postfix
</code></pre>

<p>To use it:</p>

<pre class="lang-py prettyprint-override"><code># dark yellow
HIGHLIGHT_COLOUR = '#F4E004'
# pinkish
DEPRECATED_COLOUR = '#FF4ED1'

formatter = MyFormatter(
    linenos='inline',
    # no need to highlight lines - we take care of it in the formatter
    # hl_lines=hl_lines,
    filename="sourcefile",
    # a list of tuples (color, [lines]) indicating which colur to use
    highlight_groups=[
        (HIGHLIGHT_COLOR, hl_lines),
        (DEPRECATED_COLOR, deprecated_lines),
    ]
)
</code></pre>

python css pygments