summaryrefslogtreecommitdiff
path: root/doc/docs/filterdevelopment.rst
blob: fbcd0a09e28d208935db1bf0b5f95997e10bc1db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
.. -*- mode: rst -*-

=====================
Write your own filter
=====================

.. versionadded:: 0.7

Writing own filters is very easy. All you have to do is to subclass
the `Filter` class and override the `filter` method. Additionally a
filter is instantiated with some keyword arguments you can use to
adjust the behavior of your filter.


Subclassing Filters
===================

As an example, we write a filter that converts all `Name.Function` tokens
to normal `Name` tokens to make the output less colorful.

.. sourcecode:: python

    from pygments.util import get_bool_opt
    from pygments.token import Name
    from pygments.filter import Filter

    class UncolorFilter(Filter):

        def __init__(self, **options):
            Filter.__init__(self, **options)
            self.class_too = get_bool_opt(options, 'classtoo')

        def filter(self, lexer, stream):
            for ttype, value in stream:
                if ttype is Name.Function or (self.class_too and
                                              ttype is Name.Class):
                    ttype = Name
                yield ttype, value

Some notes on the `lexer` argument: that can be quite confusing since it doesn't
need to be a lexer instance. If a filter was added by using the `add_filter()`
function of lexers, that lexer is registered for the filter. In that case
`lexer` will refer to the lexer that has registered the filter. It *can* be used
to access options passed to a lexer. Because it could be `None` you always have
to check for that case if you access it.


Using a decorator
=================

You can also use the `simplefilter` decorator from the `pygments.filter` module:

.. sourcecode:: python

    from pygments.util import get_bool_opt
    from pygments.token import Name
    from pygments.filter import simplefilter


    @simplefilter
    def uncolor(self, lexer, stream, options):
        class_too = get_bool_opt(options, 'classtoo')
        for ttype, value in stream:
            if ttype is Name.Function or (class_too and
                                          ttype is Name.Class):
                ttype = Name
            yield ttype, value

The decorator automatically subclasses an internal filter class and uses the
decorated function as a method for filtering.  (That's why there is a `self`
argument that you probably won't end up using in the method.)