1# -*- coding: utf-8 -*-
2"""
3    pygments.filter
4    ~~~~~~~~~~~~~~~
5
6    Module that implements the default filter.
7
8    :copyright: Copyright 2006-2017 by the Pygments team, see AUTHORS.
9    :license: BSD, see LICENSE for details.
10"""
11
12
13def apply_filters(stream, filters, lexer=None):
14    """
15    Use this method to apply an iterable of filters to
16    a stream. If lexer is given it's forwarded to the
17    filter, otherwise the filter receives `None`.
18    """
19    def _apply(filter_, stream):
20        for token in filter_.filter(lexer, stream):
21            yield token
22    for filter_ in filters:
23        stream = _apply(filter_, stream)
24    return stream
25
26
27def simplefilter(f):
28    """
29    Decorator that converts a function into a filter::
30
31        @simplefilter
32        def lowercase(self, lexer, stream, options):
33            for ttype, value in stream:
34                yield ttype, value.lower()
35    """
36    return type(f.__name__, (FunctionFilter,), {
37        '__module__': getattr(f, '__module__'),
38        '__doc__': f.__doc__,
39        'function': f,
40    })
41
42
43class Filter(object):
44    """
45    Default filter. Subclass this class or use the `simplefilter`
46    decorator to create own filters.
47    """
48
49    def __init__(self, **options):
50        self.options = options
51
52    def filter(self, lexer, stream):
53        raise NotImplementedError()
54
55
56class FunctionFilter(Filter):
57    """
58    Abstract class used by `simplefilter` to create simple
59    function filters on the fly. The `simplefilter` decorator
60    automatically creates subclasses of this class for
61    functions passed to it.
62    """
63    function = None
64
65    def __init__(self, **options):
66        if not hasattr(self, 'function'):
67            raise TypeError('%r used without bound function' %
68                            self.__class__.__name__)
69        Filter.__init__(self, **options)
70
71    def filter(self, lexer, stream):
72        # pylint: disable=not-callable
73        for ttype, value in self.function(lexer, stream, self.options):
74            yield ttype, value
75