mercurial/templatefilters.py
author Christian Ebert <blacktrash@gmx.net>
Sun, 10 Feb 2008 04:24:59 +0100
changeset 6072 e521ec1ad985
parent 5976 9f1e6ab76069
child 6134 7b937b26adf7
permissions -rw-r--r--
keyword: no expansion in web diffs Expansion in hgweb view of changesets and diffs is not needed and only distracting. Expansion stays enable in file and archive requests where it makes sense.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# template-filters.py - common template expansion filters
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
import cgi, re, os, time, urllib, textwrap
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     9
import util, templater
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    10
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
agescales = [("second", 1),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
             ("minute", 60),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
             ("hour", 3600),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
             ("day", 3600 * 24),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
             ("week", 3600 * 24 * 7),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
             ("month", 3600 * 24 * 30),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
             ("year", 3600 * 24 * 365)]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
agescales.reverse()
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
def age(date):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
    '''turn a (timestamp, tzoff) tuple into an age string.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
    def plural(t, c):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
        if c == 1:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
            return t
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
        return t + "s"
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
    def fmt(t, c):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
        return "%d %s" % (c, plural(t, c))
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
    now = time.time()
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
    then = date[0]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
    delta = max(1, int(now - then))
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
    for t, s in agescales:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
        n = delta / s
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
        if n >= 2 or s == 1:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
            return fmt(t, n)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
para_re = None
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
space_re = None
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
def fill(text, width):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
    '''fill many paragraphs.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
    global para_re, space_re
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
    if para_re is None:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
        para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
        space_re = re.compile(r'  +')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
    def findparas():
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
        start = 0
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
        while True:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
            m = para_re.search(text, start)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
            if not m:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
                w = len(text)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
                while w > start and text[w-1].isspace(): w -= 1
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
                yield text[start:w], text[w:]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
                break
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
            yield text[start:m.start(0)], m.group(1)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
            start = m.end(1)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
    return "".join([space_re.sub(' ', textwrap.fill(para, width)) + rest
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
                    for para, rest in findparas()])
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
def firstline(text):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
    '''return the first line of text'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
    try:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
        return text.splitlines(1)[0].rstrip('\r\n')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
    except IndexError:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
        return ''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
def isodate(date):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
    '''turn a (timestamp, tzoff) tuple into an iso 8631 date and time.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
    return util.datestr(date, format='%Y-%m-%d %H:%M')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
def hgdate(date):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
    '''turn a (timestamp, tzoff) tuple into an hg cset timestamp.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
    return "%d %d" % date
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
def nl2br(text):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
    '''replace raw newlines with xhtml line breaks.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    return text.replace('\n', '<br/>\n')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
def obfuscate(text):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
    text = unicode(text, util._encoding, 'replace')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
    return ''.join(['&#%d;' % ord(c) for c in text])
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
def domain(author):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
    '''get domain of author, or empty string if none.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
    f = author.find('@')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
    if f == -1: return ''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
    author = author[f+1:]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
    f = author.find('>')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    94
    if f >= 0: author = author[:f]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
    return author
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
def person(author):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
    '''get name of author, or else username.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
    f = author.find('<')
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
    if f == -1: return util.shortuser(author)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
    return author[:f].rstrip()
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
def shortdate(date):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
    '''turn (timestamp, tzoff) tuple into iso 8631 date.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
    return util.datestr(date, format='%Y-%m-%d', timezone=False)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
def indent(text, prefix):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
    '''indent each non-empty line of text after first with prefix.'''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   109
    lines = text.splitlines()
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
    num_lines = len(lines)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
    def indenter():
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
        for i in xrange(num_lines):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
            l = lines[i]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
            if i and l.strip():
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
                yield prefix
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   116
            yield l
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
            if i < num_lines - 1 or text.endswith('\n'):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
                yield '\n'
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
    return "".join(indenter())
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
def permissions(flags):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
    if "l" in flags:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
        return "lrwxrwxrwx"
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
    if "x" in flags:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
        return "-rwxr-xr-x"
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
    return "-rw-r--r--"
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   128
filters = {
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   129
    "addbreaks": nl2br,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
    "basename": os.path.basename,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   131
    "age": age,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   132
    "date": lambda x: util.datestr(x),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   133
    "domain": domain,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   134
    "email": util.email,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   135
    "escape": lambda x: cgi.escape(x, True),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   136
    "fill68": lambda x: fill(x, width=68),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   137
    "fill76": lambda x: fill(x, width=76),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   138
    "firstline": firstline,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   139
    "tabindent": lambda x: indent(x, '\t'),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   140
    "hgdate": hgdate,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   141
    "isodate": isodate,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   142
    "obfuscate": obfuscate,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   143
    "permissions": permissions,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
    "person": person,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   145
    "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S"),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   146
    "rfc3339date": lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S", True, "%+03d:%02d"),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   147
    "short": lambda x: x[:12],
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   148
    "shortdate": shortdate,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   149
    "stringify": templater.stringify,
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   150
    "strip": lambda x: x.strip(),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   151
    "urlescape": lambda x: urllib.quote(x),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   152
    "user": lambda x: util.shortuser(x),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
    "stringescape": lambda x: x.encode('string_escape'),
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   154
    }
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   155