mercurial/templatefilters.py
author Matt Harbison <matt_harbison@yahoo.com>
Fri, 13 Jul 2018 12:33:06 -0400
changeset 39250 7a88643bc0ef
parent 38823 e7aa113b14f7
child 40030 e2697acd9381
permissions -rw-r--r--
tests: show added/modified/removed files when logging repos converted from bzr There's a bug related to incorrect status values that can be triggered by an octopus fixup merge. Seeing what the current status is (instead of just the aggregate list) will hopefully help track this down.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
32760
ae0ebe93ac70 templatefilers: correct filename in header comment
Yuya Nishihara <yuya@tcha.org>
parents: 32181
diff changeset
     1
# templatefilters.py - common template expansion filters
5976
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
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8158
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9722
diff changeset
     6
# GNU General Public License version 2 or any later version.
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
25983
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
     8
from __future__ import absolute_import
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
     9
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    10
import os
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    11
import re
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    12
import time
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    13
37231
05db42732fce templatefilters: handle TypeError by count()
Yuya Nishihara <yuya@tcha.org>
parents: 37229
diff changeset
    14
from .i18n import _
25983
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    15
from . import (
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    16
    encoding,
34837
4fdc4adbc838 templatefilters: defend against evil unicode strs in json filter
Augie Fackler <augie@google.com>
parents: 34695
diff changeset
    17
    error,
25983
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    18
    node,
32179
e37fd5be0fed py3: alias long to int on Python 3
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32039
diff changeset
    19
    pycompat,
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    20
    registrar,
36926
6ff6e1d6b5b8 templater: move stringify() to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36839
diff changeset
    21
    templateutil,
34695
e178fcaa3933 python3: use our bytes-only version of cgi.escape everywhere
Augie Fackler <augie@google.com>
parents: 34146
diff changeset
    22
    url,
25983
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    23
    util,
1245049da5f3 templatefilters: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25778
diff changeset
    24
)
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
    25
from .utils import (
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
    26
    dateutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
    27
    stringutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
    28
)
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
28883
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28693
diff changeset
    30
urlerr = util.urlerr
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28693
diff changeset
    31
urlreq = util.urlreq
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28693
diff changeset
    32
32179
e37fd5be0fed py3: alias long to int on Python 3
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32039
diff changeset
    33
if pycompat.ispy3:
e37fd5be0fed py3: alias long to int on Python 3
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32039
diff changeset
    34
    long = int
e37fd5be0fed py3: alias long to int on Python 3
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32039
diff changeset
    35
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    36
# filters are callables like:
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    37
#   fn(obj)
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    38
# with:
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    39
#   obj - object to be filtered (text, date, list and so on)
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    40
filters = {}
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    41
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    42
templatefilter = registrar.templatefilter(filters)
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    43
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
    44
@templatefilter('addbreaks', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
    45
def addbreaks(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    46
    """Any text. Add an XHTML "<br />" tag before the end of
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
    47
    every line except the last.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
    48
    """
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
    49
    return text.replace('\n', '<br/>\n')
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8234
diff changeset
    50
19736
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    51
agescales = [("year", 3600 * 24 * 365, 'Y'),
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    52
             ("month", 3600 * 24 * 30, 'M'),
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    53
             ("week", 3600 * 24 * 7, 'W'),
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    54
             ("day", 3600 * 24, 'd'),
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    55
             ("hour", 3600, 'h'),
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    56
             ("minute", 60, 'm'),
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    57
             ("second", 1, 's')]
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
    59
@templatefilter('age', intype=templateutil.date)
19736
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    60
def age(date, abbrev=False):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    61
    """Date. Returns a human-readable date/time difference between the
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
    62
    given date/time and the current date/time.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
    63
    """
5976
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 plural(t, c):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
        if c == 1:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
            return t
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
        return t + "s"
19736
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    69
    def fmt(t, c, a):
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    70
        if abbrev:
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    71
            return "%d%s" % (c, a)
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
        return "%d %s" % (c, plural(t, c))
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
    now = time.time()
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
    then = date[0]
13666
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    76
    future = False
7682
9c8bbae02e9c templater: fix age filter to state the obvious on future timestamps
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6691
diff changeset
    77
    if then > now:
13666
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    78
        future = True
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    79
        delta = max(1, int(then - now))
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    80
        if delta > agescales[0][1] * 30:
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    81
            return 'in the distant future'
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    82
    else:
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    83
        delta = max(1, int(now - then))
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    84
        if delta > agescales[0][1] * 2:
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36602
diff changeset
    85
            return dateutil.shortdate(date)
9722
4d9dea174b84 templater: readable dates older than 24 months revert to ISO8601 (issue1006)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9721
diff changeset
    86
19736
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    87
    for t, s, a in agescales:
9029
0001e49f1c11 compat: use // for integer division
Alejandro Santos <alejolp@alejolp.com>
parents: 8697
diff changeset
    88
        n = delta // s
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
        if n >= 2 or s == 1:
13666
c49cddce0a81 templates: provide granularity for future values for age filter
timeless <timeless@gmail.com>
parents: 13593
diff changeset
    90
            if future:
19736
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    91
                return '%s from now' % fmt(t, n, a)
f08e542ce918 templatefilters: add short format for age formatting
David Soria Parra <dsp@experimentalworks.net>
parents: 19467
diff changeset
    92
            return '%s ago' % fmt(t, n, a)
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
    94
@templatefilter('basename', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
    95
def basename(path):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
    96
    """Any text. Treats the text as a path, and returns the last
35009
d1aae6d4efc5 templatefilters: fix doc of basename()
Yuya Nishihara <yuya@tcha.org>
parents: 34837
diff changeset
    97
    component of the path after splitting by the path separator.
d1aae6d4efc5 templatefilters: fix doc of basename()
Yuya Nishihara <yuya@tcha.org>
parents: 34837
diff changeset
    98
    For example, "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "".
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
    99
    """
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   100
    return os.path.basename(path)
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   101
38313
fabfbbf4dee2 templatefilters: rename commonprefix to commondir
Martin von Zweigbergk <martinvonz@google.com>
parents: 38311
diff changeset
   102
@templatefilter('commondir')
fabfbbf4dee2 templatefilters: rename commonprefix to commondir
Martin von Zweigbergk <martinvonz@google.com>
parents: 38311
diff changeset
   103
def commondir(filelist):
38213
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   104
    """List of text. Treats each list item as file name with /
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   105
    as path separator and returns the longest common directory
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   106
    prefix shared by all list items.
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   107
    Returns the empty string if no common prefix exists.
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   108
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   109
    The list items are not normalized, i.e. "foo/../bar" is handled as
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   110
    file "bar" in the directory "foo/..". Leading slashes are ignored.
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   111
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   112
    For example, ["foo/bar/baz", "foo/baz/bar"] becomes "foo" and
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   113
    ["foo/bar", "baz"] becomes "".
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   114
    """
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   115
    def common(a, b):
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   116
        if len(a) > len(b):
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   117
            a = b[:len(a)]
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   118
        elif len(b) > len(a):
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   119
            b = b[:len(a)]
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   120
        if a == b:
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   121
            return a
38823
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38313
diff changeset
   122
        for i in pycompat.xrange(len(a)):
38213
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   123
            if a[i] != b[i]:
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   124
                return a[:i]
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   125
        return a
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   126
    try:
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   127
        if not filelist:
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   128
            return ""
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   129
        dirlist = [f.lstrip('/').split('/')[:-1] for f in filelist]
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   130
        if len(dirlist) == 1:
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   131
            return '/'.join(dirlist[0])
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   132
        a = min(dirlist)
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   133
        b = max(dirlist)
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   134
        # The common prefix of a and b is shared with all
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   135
        # elements of the list since Python sorts lexicographical
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   136
        # and [1, x] after [1].
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   137
        return '/'.join(common(a, b))
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   138
    except TypeError:
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   139
        raise error.ParseError(_('argument is not a list of text'))
56dd15178190 templatefilters: add commonprefix
Joerg Sonnenberger <joerg@bec.de>
parents: 38066
diff changeset
   140
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   141
@templatefilter('count')
22668
13e3f07d74a3 templater: add count template filter, plus tests
Anton Shestakov <engored@ya.ru>
parents: 21873
diff changeset
   142
def count(i):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   143
    """List or text. Returns the length as an integer."""
37231
05db42732fce templatefilters: handle TypeError by count()
Yuya Nishihara <yuya@tcha.org>
parents: 37229
diff changeset
   144
    try:
05db42732fce templatefilters: handle TypeError by count()
Yuya Nishihara <yuya@tcha.org>
parents: 37229
diff changeset
   145
        return len(i)
05db42732fce templatefilters: handle TypeError by count()
Yuya Nishihara <yuya@tcha.org>
parents: 37229
diff changeset
   146
    except TypeError:
05db42732fce templatefilters: handle TypeError by count()
Yuya Nishihara <yuya@tcha.org>
parents: 37229
diff changeset
   147
        raise error.ParseError(_('not countable'))
22668
13e3f07d74a3 templater: add count template filter, plus tests
Anton Shestakov <engored@ya.ru>
parents: 21873
diff changeset
   148
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   149
@templatefilter('dirname', intype=bytes)
36279
9ee10b3284da templatefilters: add dirname() filter
Yuya Nishihara <yuya@tcha.org>
parents: 35751
diff changeset
   150
def dirname(path):
9ee10b3284da templatefilters: add dirname() filter
Yuya Nishihara <yuya@tcha.org>
parents: 35751
diff changeset
   151
    """Any text. Treats the text as a path, and strips the last
9ee10b3284da templatefilters: add dirname() filter
Yuya Nishihara <yuya@tcha.org>
parents: 35751
diff changeset
   152
    component of the path after splitting by the path separator.
9ee10b3284da templatefilters: add dirname() filter
Yuya Nishihara <yuya@tcha.org>
parents: 35751
diff changeset
   153
    """
9ee10b3284da templatefilters: add dirname() filter
Yuya Nishihara <yuya@tcha.org>
parents: 35751
diff changeset
   154
    return os.path.dirname(path)
9ee10b3284da templatefilters: add dirname() filter
Yuya Nishihara <yuya@tcha.org>
parents: 35751
diff changeset
   155
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   156
@templatefilter('domain', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   157
def domain(author):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   158
    """Any text. Finds the first string that looks like an email
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   159
    address, and extracts just the domain component. Example: ``User
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   160
    <user@example.com>`` becomes ``example.com``.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   161
    """
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   162
    f = author.find('@')
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   163
    if f == -1:
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   164
        return ''
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   165
    author = author[f + 1:]
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   166
    f = author.find('>')
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   167
    if f >= 0:
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   168
        author = author[:f]
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   169
    return author
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   170
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   171
@templatefilter('email', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   172
def email(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   173
    """Any text. Extracts the first string that looks like an email
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   174
    address. Example: ``User <user@example.com>`` becomes
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   175
    ``user@example.com``.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   176
    """
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   177
    return stringutil.email(text)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   178
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   179
@templatefilter('escape', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   180
def escape(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   181
    """Any text. Replaces the special XML/XHTML characters "&", "<"
17772
823a7d79ef82 hgweb: make the escape filter remove null characters (issue2567)
Siddharth Agarwal <sid0@fb.com>
parents: 17755
diff changeset
   182
    and ">" with XML entities, and filters out NUL characters.
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   183
    """
34695
e178fcaa3933 python3: use our bytes-only version of cgi.escape everywhere
Augie Fackler <augie@google.com>
parents: 34146
diff changeset
   184
    return url.escape(text.replace('\0', ''), True)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   185
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   186
para_re = None
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   187
space_re = None
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   188
19872
681f7b9213a4 check-code: check for spaces around = for named parameters
Mads Kiilerich <madski@unity3d.com>
parents: 19736
diff changeset
   189
def fill(text, width, initindent='', hangindent=''):
19228
889807c79384 templater: add indentation arguments to the fill function
Sean Farley <sean.michael.farley@gmail.com>
parents: 19227
diff changeset
   190
    '''fill many paragraphs with optional indentation.'''
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   191
    global para_re, space_re
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   192
    if para_re is None:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
        para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
36528
b546181ae451 py3: make regexp literal bytes in templatefilters.py
Yuya Nishihara <yuya@tcha.org>
parents: 36527
diff changeset
   194
        space_re = re.compile(br'  +')
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   195
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   196
    def findparas():
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   197
        start = 0
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   198
        while True:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   199
            m = para_re.search(text, start)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   200
            if not m:
36527
b2e54b257832 templatefilters: use encoding.unifromlocal/unitolocal() for py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 36279
diff changeset
   201
                uctext = encoding.unifromlocal(text[start:])
11297
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10787
diff changeset
   202
                w = len(uctext)
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10787
diff changeset
   203
                while 0 < w and uctext[w - 1].isspace():
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   204
                    w -= 1
36527
b2e54b257832 templatefilters: use encoding.unifromlocal/unitolocal() for py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 36279
diff changeset
   205
                yield (encoding.unitolocal(uctext[:w]),
b2e54b257832 templatefilters: use encoding.unifromlocal/unitolocal() for py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 36279
diff changeset
   206
                       encoding.unitolocal(uctext[w:]))
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
                break
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
            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
   209
            start = m.end(1)
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   210
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   211
    return "".join([stringutil.wrap(space_re.sub(' ',
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   212
                                                 stringutil.wrap(para, width)),
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   213
                                    width, initindent, hangindent) + rest
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
                    for para, rest in findparas()])
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   215
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   216
@templatefilter('fill68', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   217
def fill68(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   218
    """Any text. Wraps the text to fit in 68 columns."""
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   219
    return fill(text, 68)
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   220
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   221
@templatefilter('fill76', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   222
def fill76(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   223
    """Any text. Wraps the text to fit in 76 columns."""
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   224
    return fill(text, 76)
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   225
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   226
@templatefilter('firstline', intype=bytes)
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   227
def firstline(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   228
    """Any text. Returns the first line of text."""
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   229
    try:
9136
31177742f54a for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9029
diff changeset
   230
        return text.splitlines(True)[0].rstrip('\r\n')
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   231
    except IndexError:
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   232
        return ''
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   233
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   234
@templatefilter('hex', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   235
def hexfilter(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   236
    """Any text. Convert a binary Mercurial node identifier into
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   237
    its long hexadecimal representation.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   238
    """
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   239
    return node.hex(text)
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   240
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
   241
@templatefilter('hgdate', intype=templateutil.date)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   242
def hgdate(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   243
    """Date. Returns the date as a pair of numbers: "1157407993
38311
74b4a54002ec templatefilters: undeprecate hgdate
Yuya Nishihara <yuya@tcha.org>
parents: 38299
diff changeset
   244
    25200" (Unix timestamp, timezone offset).
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   245
    """
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   246
    return "%d %d" % text
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   247
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
   248
@templatefilter('isodate', intype=templateutil.date)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   249
def isodate(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   250
    """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   251
    +0200".
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   252
    """
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36602
diff changeset
   253
    return dateutil.datestr(text, '%Y-%m-%d %H:%M %1%2')
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   254
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
   255
@templatefilter('isodatesec', intype=templateutil.date)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   256
def isodatesec(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   257
    """Date. Returns the date in ISO 8601 format, including
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   258
    seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   259
    filter.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   260
    """
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36602
diff changeset
   261
    return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   262
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   263
def indent(text, prefix):
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   264
    '''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
   265
    lines = text.splitlines()
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   266
    num_lines = len(lines)
9387
20ed9909dbd9 templatefilters: indent: do not compute text.endswith('\n') in each iteration
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9136
diff changeset
   267
    endswithnewline = text[-1:] == '\n'
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   268
    def indenter():
38823
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38313
diff changeset
   269
        for i in pycompat.xrange(num_lines):
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   270
            l = lines[i]
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   271
            if i and l.strip():
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   272
                yield prefix
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   273
            yield l
9387
20ed9909dbd9 templatefilters: indent: do not compute text.endswith('\n') in each iteration
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9136
diff changeset
   274
            if i < num_lines - 1 or endswithnewline:
5976
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   275
                yield '\n'
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   276
    return "".join(indenter())
9f1e6ab76069 templates: move filters to their own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   277
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   278
@templatefilter('json')
31785
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31784
diff changeset
   279
def json(obj, paranoid=True):
37992
a25513263075 templatefilters: document the json filter
Yuya Nishihara <yuya@tcha.org>
parents: 37232
diff changeset
   280
    """Any object. Serializes the object to a JSON formatted text."""
31783
8d9eafe01111 templatefilters: unroll handling of None/False/True
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   281
    if obj is None:
8d9eafe01111 templatefilters: unroll handling of None/False/True
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   282
        return 'null'
8d9eafe01111 templatefilters: unroll handling of None/False/True
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   283
    elif obj is False:
8d9eafe01111 templatefilters: unroll handling of None/False/True
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   284
        return 'false'
8d9eafe01111 templatefilters: unroll handling of None/False/True
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   285
    elif obj is True:
8d9eafe01111 templatefilters: unroll handling of None/False/True
Yuya Nishihara <yuya@tcha.org>
parents: 31782
diff changeset
   286
        return 'true'
31733
35eb8f112c88 templatefilter: add support for 'long' to json()
Matt Harbison <matt_harbison@yahoo.com>
parents: 31460
diff changeset
   287
    elif isinstance(obj, (int, long, float)):
32180
964e7427a691 py3: use pycompat.bytestr() instead of str()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32179
diff changeset
   288
        return pycompat.bytestr(obj)
32181
c3342c177211 py3: replace str with bytes in isinstance()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32180
diff changeset
   289
    elif isinstance(obj, bytes):
31785
654e9a1c8a6c formatter: use templatefilters.json()
Yuya Nishihara <yuya@tcha.org>
parents: 31784
diff changeset
   290
        return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid)
38066
f5a1aa8c6987 json: reject unicode on py2 as well
Martin von Zweigbergk <martinvonz@google.com>
parents: 37992
diff changeset
   291
    elif isinstance(obj, type(u'')):
34837
4fdc4adbc838 templatefilters: defend against evil unicode strs in json filter
Augie Fackler <augie@google.com>
parents: 34695
diff changeset
   292
        raise error.ProgrammingError(
38066
f5a1aa8c6987 json: reject unicode on py2 as well
Martin von Zweigbergk <martinvonz@google.com>
parents: 37992
diff changeset
   293
            'Mercurial only does output with bytes: %r' % obj)
14967
376091a4ad23 templatefilters: use safehasattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14944
diff changeset
   294
    elif util.safehasattr(obj, 'keys'):
32763
f924dd043974 json: pass formatting options recursively
Yuya Nishihara <yuya@tcha.org>
parents: 32762
diff changeset
   295
        out = ['"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid),
f924dd043974 json: pass formatting options recursively
Yuya Nishihara <yuya@tcha.org>
parents: 32762
diff changeset
   296
                             json(v, paranoid))
31784
47925b63be70 templatefilters: use list comprehension in json()
Yuya Nishihara <yuya@tcha.org>
parents: 31783
diff changeset
   297
               for k, v in sorted(obj.iteritems())]
6691
0dba955c2636 add graph page to hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6319
diff changeset
   298
        return '{' + ', '.join(out) + '}'
14944
e2c413bde8a5 globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__')
Augie Fackler <durin42@gmail.com>
parents: 14318
diff changeset
   299
    elif util.safehasattr(obj, '__iter__'):
32763
f924dd043974 json: pass formatting options recursively
Yuya Nishihara <yuya@tcha.org>
parents: 32762
diff changeset
   300
        out = [json(i, paranoid) for i in obj]
6691
0dba955c2636 add graph page to hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6319
diff changeset
   301
        return '[' + ', '.join(out) + ']'
37232
63144f33c8bb templatefilters: raise ProgrammingError if unencodable type passed to json()
Yuya Nishihara <yuya@tcha.org>
parents: 37231
diff changeset
   302
    raise error.ProgrammingError('cannot encode %r' % obj)
6691
0dba955c2636 add graph page to hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6319
diff changeset
   303
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   304
@templatefilter('lower', intype=bytes)
24566
6abce80e6cbf templatefilters: add "upper" and "lower" for case conversion
Yuya Nishihara <yuya@tcha.org>
parents: 23708
diff changeset
   305
def lower(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   306
    """Any text. Converts the text to lowercase."""
24566
6abce80e6cbf templatefilters: add "upper" and "lower" for case conversion
Yuya Nishihara <yuya@tcha.org>
parents: 23708
diff changeset
   307
    return encoding.lower(text)
6abce80e6cbf templatefilters: add "upper" and "lower" for case conversion
Yuya Nishihara <yuya@tcha.org>
parents: 23708
diff changeset
   308
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   309
@templatefilter('nonempty', intype=bytes)
36581
a185b1af207c templatefilters: stop using str as a variable name
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36528
diff changeset
   310
def nonempty(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   311
    """Any text. Returns '(none)' if the string is empty."""
36581
a185b1af207c templatefilters: stop using str as a variable name
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36528
diff changeset
   312
    return text or "(none)"
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   313
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   314
@templatefilter('obfuscate', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   315
def obfuscate(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   316
    """Any text. Returns the input text rendered as a sequence of
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   317
    XML entities.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   318
    """
36592
9d71bd25554b templatefilters: convert arguments to sysstrs for unicode() ctor
Augie Fackler <augie@google.com>
parents: 36581
diff changeset
   319
    text = unicode(text, pycompat.sysstr(encoding.encoding), r'replace')
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   320
    return ''.join(['&#%d;' % ord(c) for c in text])
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   321
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   322
@templatefilter('permissions', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   323
def permissions(flags):
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   324
    if "l" in flags:
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   325
        return "lrwxrwxrwx"
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   326
    if "x" in flags:
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   327
        return "-rwxr-xr-x"
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   328
    return "-rw-r--r--"
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   329
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   330
@templatefilter('person', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   331
def person(author):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   332
    """Any text. Returns the name before an email address,
16235
eb39bbda167b templates/filters: strip quotes from {author|person}
"Yann E. MORIN" <yann.morin.1998@free.fr>
parents: 15155
diff changeset
   333
    interpreting it as per RFC 5322.
eb39bbda167b templates/filters: strip quotes from {author|person}
"Yann E. MORIN" <yann.morin.1998@free.fr>
parents: 15155
diff changeset
   334
    """
37158
fb7140f1d09d stringutil: move person function from templatefilters
Connor Sheehan <sheehan@mozilla.com>
parents: 37087
diff changeset
   335
    return stringutil.person(author)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   336
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   337
@templatefilter('revescape', intype=bytes)
25778
3a33412792f1 templates: introduce revescape filter for escaping symbolic revisions
Anton Shestakov <av6@dwimlabs.net>
parents: 25000
diff changeset
   338
def revescape(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   339
    """Any text. Escapes all "special" characters, except @.
25778
3a33412792f1 templates: introduce revescape filter for escaping symbolic revisions
Anton Shestakov <av6@dwimlabs.net>
parents: 25000
diff changeset
   340
    Forward slashes are escaped twice to prevent web servers from prematurely
3a33412792f1 templates: introduce revescape filter for escaping symbolic revisions
Anton Shestakov <av6@dwimlabs.net>
parents: 25000
diff changeset
   341
    unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
3a33412792f1 templates: introduce revescape filter for escaping symbolic revisions
Anton Shestakov <av6@dwimlabs.net>
parents: 25000
diff changeset
   342
    """
28883
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28693
diff changeset
   343
    return urlreq.quote(text, safe='/@').replace('/', '%252F')
25778
3a33412792f1 templates: introduce revescape filter for escaping symbolic revisions
Anton Shestakov <av6@dwimlabs.net>
parents: 25000
diff changeset
   344
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
   345
@templatefilter('rfc3339date', intype=templateutil.date)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   346
def rfc3339date(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   347
    """Date. Returns a date using the Internet date format
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   348
    specified in RFC 3339: "2009-08-18T13:00:13+02:00".
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   349
    """
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36602
diff changeset
   350
    return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   351
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
   352
@templatefilter('rfc822date', intype=templateutil.date)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   353
def rfc822date(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   354
    """Date. Returns a date using the same format used in email
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   355
    headers: "Tue, 18 Aug 2009 13:00:13 +0200".
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   356
    """
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36602
diff changeset
   357
    return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   358
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   359
@templatefilter('short', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   360
def short(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   361
    """Changeset hash. Returns the short form of a changeset hash,
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   362
    i.e. a 12 hexadecimal digit string.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   363
    """
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   364
    return text[:12]
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   365
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   366
@templatefilter('shortbisect', intype=bytes)
36838
71f189941791 templatefilters: inline hbisect.shortlabel()
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   367
def shortbisect(label):
71f189941791 templatefilters: inline hbisect.shortlabel()
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   368
    """Any text. Treats `label` as a bisection status, and
15155
f4a8d754cd0a templates: add 'bisect' keyword to return a cset's bisect status
"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
parents: 14967
diff changeset
   369
    returns a single-character representing the status (G: good, B: bad,
f4a8d754cd0a templates: add 'bisect' keyword to return a cset's bisect status
"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
parents: 14967
diff changeset
   370
    S: skipped, U: untested, I: ignored). Returns single space if `text`
f4a8d754cd0a templates: add 'bisect' keyword to return a cset's bisect status
"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
parents: 14967
diff changeset
   371
    is not a valid bisection status.
f4a8d754cd0a templates: add 'bisect' keyword to return a cset's bisect status
"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
parents: 14967
diff changeset
   372
    """
36838
71f189941791 templatefilters: inline hbisect.shortlabel()
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   373
    if label:
36839
82af07e1ae16 py3: fix slicing of bisect label in templatefilters.shortbisect()
Yuya Nishihara <yuya@tcha.org>
parents: 36838
diff changeset
   374
        return label[0:1].upper()
36838
71f189941791 templatefilters: inline hbisect.shortlabel()
Yuya Nishihara <yuya@tcha.org>
parents: 36636
diff changeset
   375
    return ' '
15155
f4a8d754cd0a templates: add 'bisect' keyword to return a cset's bisect status
"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
parents: 14967
diff changeset
   376
37229
9bcf096a2da2 templatefilters: declare input type as date where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37225
diff changeset
   377
@templatefilter('shortdate', intype=templateutil.date)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   378
def shortdate(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   379
    """Date. Returns a date like "2006-09-18"."""
36636
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36602
diff changeset
   380
    return dateutil.shortdate(text)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   381
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   382
@templatefilter('slashpath', intype=bytes)
35448
dad8a5071b0a templatefilters: add slashpath() to convert path separator to slash
Yuya Nishihara <yuya@tcha.org>
parents: 34837
diff changeset
   383
def slashpath(path):
dad8a5071b0a templatefilters: add slashpath() to convert path separator to slash
Yuya Nishihara <yuya@tcha.org>
parents: 34837
diff changeset
   384
    """Any text. Replaces the native path separator with slash."""
dad8a5071b0a templatefilters: add slashpath() to convert path separator to slash
Yuya Nishihara <yuya@tcha.org>
parents: 34837
diff changeset
   385
    return util.pconvert(path)
dad8a5071b0a templatefilters: add slashpath() to convert path separator to slash
Yuya Nishihara <yuya@tcha.org>
parents: 34837
diff changeset
   386
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   387
@templatefilter('splitlines', intype=bytes)
21820
cce404b0c918 templatefilter: add splitlines function
Ryan McElroy <rmcelroy@fb.com>
parents: 19886
diff changeset
   388
def splitlines(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   389
    """Any text. Split text into a list of lines."""
36927
32f9b7e3f056 templater: move hybrid class and functions to templateutil module
Yuya Nishihara <yuya@tcha.org>
parents: 36926
diff changeset
   390
    return templateutil.hybridlist(text.splitlines(), name='line')
21820
cce404b0c918 templatefilter: add splitlines function
Ryan McElroy <rmcelroy@fb.com>
parents: 19886
diff changeset
   391
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   392
@templatefilter('stringescape', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   393
def stringescape(text):
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   394
    return stringutil.escapestr(text)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   395
37224
54355c243042 templatefilters: allow declaration of input data type
Yuya Nishihara <yuya@tcha.org>
parents: 37158
diff changeset
   396
@templatefilter('stringify', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   397
def stringify(thing):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   398
    """Any type. Turns the value into text by converting values into
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   399
    text and concatenating them.
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   400
    """
37224
54355c243042 templatefilters: allow declaration of input data type
Yuya Nishihara <yuya@tcha.org>
parents: 37158
diff changeset
   401
    return thing  # coerced by the intype
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   402
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   403
@templatefilter('stripdir', intype=bytes)
8158
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   404
def stripdir(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   405
    """Treat the text as path and strip a directory level, if
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   406
    possible. For example, "foo" and "foo/bar" becomes "foo".
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   407
    """
8158
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   408
    dir = os.path.dirname(text)
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   409
    if dir == "":
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   410
        return os.path.basename(text)
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   411
    else:
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   412
        return dir
1bef3656d9fe templatefilters: add new stripdir filter
Aleix Conchillo Flaque <aleix@member.fsf.org>
parents: 8014
diff changeset
   413
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   414
@templatefilter('tabindent', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   415
def tabindent(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   416
    """Any text. Returns the text, with every non-empty line
19467
1afe5d3939db template: fix tabindent docstring (issue2880)
Matt Mackall <mpm@selenic.com>
parents: 19228
diff changeset
   417
    except the first starting with a tab character.
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   418
    """
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   419
    return indent(text, '\t')
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   420
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   421
@templatefilter('upper', intype=bytes)
24566
6abce80e6cbf templatefilters: add "upper" and "lower" for case conversion
Yuya Nishihara <yuya@tcha.org>
parents: 23708
diff changeset
   422
def upper(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   423
    """Any text. Converts the text to uppercase."""
24566
6abce80e6cbf templatefilters: add "upper" and "lower" for case conversion
Yuya Nishihara <yuya@tcha.org>
parents: 23708
diff changeset
   424
    return encoding.upper(text)
6abce80e6cbf templatefilters: add "upper" and "lower" for case conversion
Yuya Nishihara <yuya@tcha.org>
parents: 23708
diff changeset
   425
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   426
@templatefilter('urlescape', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   427
def urlescape(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   428
    """Any text. Escapes all "special" characters. For example,
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   429
    "foo bar" becomes "foo%20bar".
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   430
    """
28883
032c4c2f802a pycompat: switch to util.urlreq/util.urlerr for py3 compat
timeless <timeless@mozdev.org>
parents: 28693
diff changeset
   431
    return urlreq.quote(text)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   432
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   433
@templatefilter('user', intype=bytes)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   434
def userfilter(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   435
    """Any text. Returns a short representation of a user name or email
16360
e5788269741a templates/filters: extracting the user portion of an email address
Matteo Capobianco <m.capobianco@gmail.com>
parents: 16251
diff changeset
   436
    address."""
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   437
    return stringutil.shortuser(text)
13590
1a752dcfe062 templatefilters: wrap all filters in dedicated functions
Patrick Mezard <pmezard@gmail.com>
parents: 13589
diff changeset
   438
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   439
@templatefilter('emailuser', intype=bytes)
16360
e5788269741a templates/filters: extracting the user portion of an email address
Matteo Capobianco <m.capobianco@gmail.com>
parents: 16251
diff changeset
   440
def emailuser(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   441
    """Any text. Returns the user portion of an email address."""
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36927
diff changeset
   442
    return stringutil.emailuser(text)
16360
e5788269741a templates/filters: extracting the user portion of an email address
Matteo Capobianco <m.capobianco@gmail.com>
parents: 16251
diff changeset
   443
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   444
@templatefilter('utf8', intype=bytes)
28209
8ddf893560fa templatefilters: add "utf8" to get utf-8 bytes from local-encoding text
Yuya Nishihara <yuya@tcha.org>
parents: 28208
diff changeset
   445
def utf8(text):
28693
11f623b5668f templatefilters: use templatefilter to mark a function as template filter
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28692
diff changeset
   446
    """Any text. Converts from the local character encoding to UTF-8."""
28209
8ddf893560fa templatefilters: add "utf8" to get utf-8 bytes from local-encoding text
Yuya Nishihara <yuya@tcha.org>
parents: 28208
diff changeset
   447
    return encoding.fromlocal(text)
8ddf893560fa templatefilters: add "utf8" to get utf-8 bytes from local-encoding text
Yuya Nishihara <yuya@tcha.org>
parents: 28208
diff changeset
   448
37225
08e042f0a67c templatefilters: declare input type as bytes where appropriate
Yuya Nishihara <yuya@tcha.org>
parents: 37224
diff changeset
   449
@templatefilter('xmlescape', intype=bytes)
13588
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   450
def xmlescape(text):
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   451
    text = (text
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   452
            .replace('&', '&amp;')
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   453
            .replace('<', '&lt;')
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   454
            .replace('>', '&gt;')
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   455
            .replace('"', '&quot;')
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   456
            .replace("'", '&#39;')) # &apos; invalid in HTML
b8b881f3f3a7 templatefilters: sort function definitions
Patrick Mezard <pmezard@gmail.com>
parents: 13587
diff changeset
   457
    return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
8234
27dbe534397b templatefilters: add "nonempty" template filter
Rocco Rutte <pdmef@gmx.net>
parents: 8225
diff changeset
   458
18627
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   459
def websub(text, websubtable):
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   460
    """:websub: Any text. Only applies to hgweb. Applies the regular
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   461
    expression replacements defined in the websub section.
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   462
    """
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   463
    if websubtable:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   464
        for regexp, format in websubtable:
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   465
            text = regexp.sub(format, text)
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   466
    return text
4e949b8e0930 hgweb: add websub template filter
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 17772
diff changeset
   467
28692
6b3b958daf03 registrar: add templatefilter to mark a function as template filter (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28213
diff changeset
   468
def loadfilter(ui, extname, registrarobj):
6b3b958daf03 registrar: add templatefilter to mark a function as template filter (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28213
diff changeset
   469
    """Load template filter from specified registrarobj
6b3b958daf03 registrar: add templatefilter to mark a function as template filter (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28213
diff changeset
   470
    """
6b3b958daf03 registrar: add templatefilter to mark a function as template filter (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28213
diff changeset
   471
    for name, func in registrarobj._table.iteritems():
6b3b958daf03 registrar: add templatefilter to mark a function as template filter (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28213
diff changeset
   472
        filters[name] = func
6b3b958daf03 registrar: add templatefilter to mark a function as template filter (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28213
diff changeset
   473
13591
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   474
# tell hggettext to extract docstrings from these functions:
264f292a0c6f templatefilters: move doc from templates.txt to docstrings
Patrick Mezard <pmezard@gmail.com>
parents: 13590
diff changeset
   475
i18nfunctions = filters.values()