mercurial/templater.py
author Martin von Zweigbergk <martinvonz@google.com>
Tue, 30 Aug 2016 09:22:53 -0700
changeset 29889 6f447b9ec263
parent 29848 b1f69dbdd76b
child 30008 e83f89d3b1f7
permissions -rw-r--r--
util: rename checkcase() to fscasesensitive() (API) I always read the name "checkcase(path)" as "do we need to check for case folding at this path", but it's actually (I think) meant to be read "check if the file system cares about case at this path". I'm clearly not the only one confused by this as the dirstate has this property: def _checkcase(self): return not util.checkcase(self._join('.hg')) Maybe we should even inverse the function and call it fscasefolding() since that's what all callers care about?
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     1
# templater.py - template expansion for output
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     2
#
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     3
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8223
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: 9842
diff changeset
     6
# GNU General Public License version 2 or any later version.
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
     7
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
     8
from __future__ import absolute_import
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
     9
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    10
import os
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    11
import re
17982
e06e9fd2d99f template engine: convert generator-based iterator to list-based iterator
Weiwen <weiwen@fb.com>
parents: 17890
diff changeset
    12
import types
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    13
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    14
from .i18n import _
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    15
from . import (
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    16
    config,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    17
    error,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    18
    minirst,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    19
    parser,
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
    20
    registrar,
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    21
    revset as revsetmod,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    22
    templatefilters,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    23
    templatekw,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    24
    util,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    25
)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    26
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    27
# template parsing
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    28
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    29
elements = {
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    30
    # token-type: binding-strength, primary, prefix, infix, suffix
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    31
    "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    32
    ",": (2, None, None, ("list", 2), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    33
    "|": (5, None, None, ("|", 5), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    34
    "%": (6, None, None, ("%", 6), None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    35
    ")": (0, None, None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    36
    "integer": (0, "integer", None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    37
    "symbol": (0, "symbol", None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    38
    "string": (0, "string", None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    39
    "template": (0, "template", None, None, None),
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    40
    "end": (0, None, None, None, None),
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    41
}
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    42
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
    43
def tokenize(program, start, end, term=None):
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
    44
    """Parse a template expression into a stream of tokens, which must end
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
    45
    with term if specified"""
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    46
    pos = start
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    47
    while pos < end:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    48
        c = program[pos]
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    49
        if c.isspace(): # skip inter-token whitespace
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    50
            pass
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    51
        elif c in "(,)%|": # handle simple operators
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    52
            yield (c, None, pos)
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
    53
        elif c in '"\'': # handle quoted templates
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
    54
            s = pos + 1
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
    55
            data, pos = _parsetemplate(program, s, end, c)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
    56
            yield ('template', data, s)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
    57
            pos -= 1
25784
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
    58
        elif c == 'r' and program[pos:pos + 2] in ("r'", 'r"'):
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
    59
            # handle quoted strings
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
    60
            c = program[pos + 1]
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
    61
            s = pos = pos + 2
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    62
            while pos < end: # find closing quote
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    63
                d = program[pos]
25638
6047b60cdd09 templater: fix handling of \-escapes in raw string literals
Yuya Nishihara <yuya@tcha.org>
parents: 25637
diff changeset
    64
                if d == '\\': # skip over escaped characters
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    65
                    pos += 2
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    66
                    continue
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    67
                if d == c:
25785
f976b7dc5e7b templater: unify "string" and "rawstring"
Yuya Nishihara <yuya@tcha.org>
parents: 25784
diff changeset
    68
                    yield ('string', program[s:pos], s)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    69
                    break
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    70
                pos += 1
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    71
            else:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    72
                raise error.ParseError(_("unterminated string"), s)
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    73
        elif c.isdigit() or c == '-':
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    74
            s = pos
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    75
            if c == '-': # simply take negate operator as part of integer
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    76
                pos += 1
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    77
            if pos >= end or not program[pos].isdigit():
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    78
                raise error.ParseError(_("integer literal without digits"), s)
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    79
            pos += 1
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    80
            while pos < end:
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    81
                d = program[pos]
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    82
                if not d.isdigit():
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    83
                    break
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    84
                pos += 1
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    85
            yield ('integer', program[s:pos], s)
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
    86
            pos -= 1
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    87
        elif (c == '\\' and program[pos:pos + 2] in (r"\'", r'\"')
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    88
              or c == 'r' and program[pos:pos + 3] in (r"r\'", r'r\"')):
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    89
            # handle escaped quoted strings for compatibility with 2.9.2-3.4,
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    90
            # where some of nested templates were preprocessed as strings and
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    91
            # then compiled. therefore, \"...\" was allowed. (issue4733)
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    92
            #
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    93
            # processing flow of _evalifliteral() at 5ab28a2e9962:
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    94
            # outer template string    -> stringify()  -> compiletemplate()
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    95
            # ------------------------    ------------    ------------------
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    96
            # {f("\\\\ {g(\"\\\"\")}"}    \\ {g("\"")}    [r'\\', {g("\"")}]
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    97
            #             ~~~~~~~~
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    98
            #             escaped quoted string
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
    99
            if c == 'r':
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   100
                pos += 1
25785
f976b7dc5e7b templater: unify "string" and "rawstring"
Yuya Nishihara <yuya@tcha.org>
parents: 25784
diff changeset
   101
                token = 'string'
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   102
            else:
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   103
                token = 'template'
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   104
            quote = program[pos:pos + 2]
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   105
            s = pos = pos + 2
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   106
            while pos < end: # find closing escaped quote
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   107
                if program.startswith('\\\\\\', pos, end):
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   108
                    pos += 4 # skip over double escaped characters
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   109
                    continue
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   110
                if program.startswith(quote, pos, end):
26215
72aad184f061 templater: create string unescape helper (issue4798)
Matt Mackall <mpm@selenic.com>
parents: 26197
diff changeset
   111
                    # interpret as if it were a part of an outer string
26231
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 26215
diff changeset
   112
                    data = parser.unescapestr(program[s:pos])
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   113
                    if token == 'template':
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   114
                        data = _parsetemplate(data, 0, len(data))[0]
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   115
                    yield (token, data, s)
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   116
                    pos += 1
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   117
                    break
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   118
                pos += 1
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   119
            else:
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   120
                raise error.ParseError(_("unterminated string"), s)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   121
        elif c.isalnum() or c in '_':
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   122
            s = pos
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   123
            pos += 1
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   124
            while pos < end: # find end of symbol
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   125
                d = program[pos]
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   126
                if not (d.isalnum() or d == "_"):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   127
                    break
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   128
                pos += 1
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   129
            sym = program[s:pos]
18893
74ea61318ea8 templater: back out 0615b22da148, it breaks schemes ({1})
Brendan Cully <brendan@kublai.com>
parents: 18889
diff changeset
   130
            yield ('symbol', sym, s)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   131
            pos -= 1
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   132
        elif c == term:
25782
babd2c93bd99 templater: check existence of closing brace of template string
Yuya Nishihara <yuya@tcha.org>
parents: 25781
diff changeset
   133
            yield ('end', None, pos + 1)
babd2c93bd99 templater: check existence of closing brace of template string
Yuya Nishihara <yuya@tcha.org>
parents: 25781
diff changeset
   134
            return
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   135
        else:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   136
            raise error.ParseError(_("syntax error"), pos)
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   137
        pos += 1
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   138
    if term:
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   139
        raise error.ParseError(_("unterminated template expansion"), start)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   140
    yield ('end', None, pos)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   141
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   142
def _parsetemplate(tmpl, start, stop, quote=''):
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   143
    r"""
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   144
    >>> _parsetemplate('foo{bar}"baz', 0, 12)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   145
    ([('string', 'foo'), ('symbol', 'bar'), ('string', '"baz')], 12)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   146
    >>> _parsetemplate('foo{bar}"baz', 0, 12, quote='"')
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   147
    ([('string', 'foo'), ('symbol', 'bar')], 9)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   148
    >>> _parsetemplate('foo"{bar}', 0, 9, quote='"')
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   149
    ([('string', 'foo')], 4)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   150
    >>> _parsetemplate(r'foo\"bar"baz', 0, 12, quote='"')
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   151
    ([('string', 'foo"'), ('string', 'bar')], 9)
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   152
    >>> _parsetemplate(r'foo\\"bar', 0, 10, quote='"')
25785
f976b7dc5e7b templater: unify "string" and "rawstring"
Yuya Nishihara <yuya@tcha.org>
parents: 25784
diff changeset
   153
    ([('string', 'foo\\')], 6)
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   154
    """
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   155
    parsed = []
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   156
    sepchars = '{' + quote
25781
82c918509ef5 templater: extract function that parses template string
Yuya Nishihara <yuya@tcha.org>
parents: 25780
diff changeset
   157
    pos = start
25654
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25599
diff changeset
   158
    p = parser.parser(elements)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   159
    while pos < stop:
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   160
        n = min((tmpl.find(c, pos, stop) for c in sepchars),
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   161
                key=lambda n: (n < 0, n))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   162
        if n < 0:
26231
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 26215
diff changeset
   163
            parsed.append(('string', parser.unescapestr(tmpl[pos:stop])))
25780
8b900b937e1c templater: respect stop position while parsing template string
Yuya Nishihara <yuya@tcha.org>
parents: 25696
diff changeset
   164
            pos = stop
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   165
            break
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   166
        c = tmpl[n]
24949
890845af1ac2 templater: strictly parse leading backslashes of '{' (issue4569) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 24948
diff changeset
   167
        bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
25598
55c2cb65bdfa templater: drop strtoken argument from compiletemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 25597
diff changeset
   168
        if bs % 2 == 1:
55c2cb65bdfa templater: drop strtoken argument from compiletemplate()
Yuya Nishihara <yuya@tcha.org>
parents: 25597
diff changeset
   169
            # escaped (e.g. '\{', '\\\{', but not '\\{')
26231
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 26215
diff changeset
   170
            parsed.append(('string', parser.unescapestr(tmpl[pos:n - 1]) + c))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   171
            pos = n + 1
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   172
            continue
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   173
        if n > pos:
26231
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 26215
diff changeset
   174
            parsed.append(('string', parser.unescapestr(tmpl[pos:n])))
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   175
        if c == quote:
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   176
            return parsed, n + 1
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   177
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   178
        parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}'))
13665
e798e430c5e5 revset: report a parse error if a revset is not parsed completely (issue2654)
Bernhard Leiner <bleiner@gmail.com>
parents: 13187
diff changeset
   179
        parsed.append(parseres)
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   180
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   181
    if quote:
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   182
        raise error.ParseError(_("unterminated string"), start)
25781
82c918509ef5 templater: extract function that parses template string
Yuya Nishihara <yuya@tcha.org>
parents: 25780
diff changeset
   183
    return parsed, pos
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   184
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   185
def _unnesttemplatelist(tree):
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   186
    """Expand list of templates to node tuple
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   187
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   188
    >>> def f(tree):
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   189
    ...     print prettyformat(_unnesttemplatelist(tree))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   190
    >>> f(('template', []))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   191
    ('string', '')
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   192
    >>> f(('template', [('string', 'foo')]))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   193
    ('string', 'foo')
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   194
    >>> f(('template', [('string', 'foo'), ('symbol', 'rev')]))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   195
    (template
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   196
      ('string', 'foo')
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   197
      ('symbol', 'rev'))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   198
    >>> f(('template', [('symbol', 'rev')]))  # template(rev) -> str
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   199
    (template
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   200
      ('symbol', 'rev'))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   201
    >>> f(('template', [('template', [('string', 'foo')])]))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   202
    ('string', 'foo')
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   203
    """
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   204
    if not isinstance(tree, tuple):
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   205
        return tree
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   206
    op = tree[0]
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   207
    if op != 'template':
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   208
        return (op,) + tuple(_unnesttemplatelist(x) for x in tree[1:])
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   209
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   210
    assert len(tree) == 2
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   211
    xs = tuple(_unnesttemplatelist(x) for x in tree[1])
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   212
    if not xs:
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   213
        return ('string', '')  # empty template ""
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   214
    elif len(xs) == 1 and xs[0][0] == 'string':
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   215
        return xs[0]  # fast path for string with no template fragment "x"
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   216
    else:
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   217
        return (op,) + xs
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   218
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   219
def parse(tmpl):
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   220
    """Parse template string into tree"""
25781
82c918509ef5 templater: extract function that parses template string
Yuya Nishihara <yuya@tcha.org>
parents: 25780
diff changeset
   221
    parsed, pos = _parsetemplate(tmpl, 0, len(tmpl))
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   222
    assert pos == len(tmpl), 'unquoted template should be consumed'
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   223
    return _unnesttemplatelist(('template', parsed))
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   224
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   225
def _parseexpr(expr):
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   226
    """Parse a template expression into tree
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   227
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   228
    >>> _parseexpr('"foo"')
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   229
    ('string', 'foo')
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   230
    >>> _parseexpr('foo(bar)')
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   231
    ('func', ('symbol', 'foo'), ('symbol', 'bar'))
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   232
    >>> _parseexpr('foo(')
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   233
    Traceback (most recent call last):
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   234
      ...
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   235
    ParseError: ('not a prefix: end', 4)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   236
    >>> _parseexpr('"foo" "bar"')
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   237
    Traceback (most recent call last):
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   238
      ...
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   239
    ParseError: ('invalid token', 7)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   240
    """
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   241
    p = parser.parser(elements)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   242
    tree, pos = p.parse(tokenize(expr, 0, len(expr)))
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   243
    if pos != len(expr):
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   244
        raise error.ParseError(_('invalid token'), pos)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   245
    return _unnesttemplatelist(tree)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   246
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   247
def prettyformat(tree):
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   248
    return parser.prettyformat(tree, ('integer', 'string', 'symbol'))
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   249
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   250
def compileexp(exp, context, curmethods):
28956
eea98190ed73 templater: inline compiletemplate() function into engine
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   251
    """Compile parsed template tree to (func, data) pair"""
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   252
    t = exp[0]
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   253
    if t in curmethods:
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   254
        return curmethods[t](exp, context)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   255
    raise error.ParseError(_("unknown method '%s'") % t)
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   256
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   257
# template evaluation
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   258
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   259
def getsymbol(exp):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   260
    if exp[0] == 'symbol':
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   261
        return exp[1]
21822
028a48105191 templater: add symbol to error
Ryan McElroy <rmcelroy@fb.com>
parents: 21821
diff changeset
   262
    raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   263
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   264
def getlist(x):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   265
    if not x:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   266
        return []
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   267
    if x[0] == 'list':
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   268
        return getlist(x[1]) + [x[2]]
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   269
    return [x]
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   270
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   271
def gettemplate(exp, context):
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   272
    """Compile given template tree or load named template from map file;
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   273
    returns (func, data) pair"""
28546
1987ed32efca templater: relax type of mapped template
Yuya Nishihara <yuya@tcha.org>
parents: 28545
diff changeset
   274
    if exp[0] in ('template', 'string'):
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   275
        return compileexp(exp, context, methods)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   276
    if exp[0] == 'symbol':
25599
695b93a79d17 templater: comment that gettemplate() has different name resolution order
Yuya Nishihara <yuya@tcha.org>
parents: 25598
diff changeset
   277
        # unlike runsymbol(), here 'symbol' is always taken as template name
695b93a79d17 templater: comment that gettemplate() has different name resolution order
Yuya Nishihara <yuya@tcha.org>
parents: 25598
diff changeset
   278
        # even if it exists in mapping. this allows us to override mapping
695b93a79d17 templater: comment that gettemplate() has different name resolution order
Yuya Nishihara <yuya@tcha.org>
parents: 25598
diff changeset
   279
        # by web templates, e.g. 'changelogtag' is redefined in map file.
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   280
        return context._load(exp[1])
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   281
    raise error.ParseError(_("expected template specifier"))
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   282
26124
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   283
def evalfuncarg(context, mapping, arg):
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   284
    func, data = arg
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   285
    # func() may return string, generator of strings or arbitrary object such
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   286
    # as date tuple, but filter does not want generator.
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   287
    thing = func(context, mapping, data)
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   288
    if isinstance(thing, types.GeneratorType):
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   289
        thing = stringify(thing)
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   290
    return thing
604a7c941103 templater: extract helper that evaluates filter or function argument
Yuya Nishihara <yuya@tcha.org>
parents: 26106
diff changeset
   291
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   292
def evalboolean(context, mapping, arg):
29817
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   293
    """Evaluate given argument as boolean, but also takes boolean literals"""
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   294
    func, data = arg
29817
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   295
    if func is runsymbol:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   296
        thing = func(context, mapping, data, default=None)
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   297
        if thing is None:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   298
            # not a template keyword, takes as a boolean literal
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   299
            thing = util.parsebool(data)
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   300
    else:
cc11079644fc templater: make pad() evaluate boolean argument (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 29816
diff changeset
   301
        thing = func(context, mapping, data)
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   302
    if isinstance(thing, bool):
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   303
        return thing
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   304
    # other objects are evaluated as strings, which means 0 is True, but
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   305
    # empty dict/list should be False as they are expected to be ''
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   306
    return bool(stringify(thing))
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   307
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   308
def evalinteger(context, mapping, arg, err):
28344
ac371d4c007f templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents: 28343
diff changeset
   309
    v = evalfuncarg(context, mapping, arg)
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   310
    try:
28344
ac371d4c007f templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents: 28343
diff changeset
   311
        return int(v)
ac371d4c007f templater: drop redundant type conversion when evaluating integer argument
Yuya Nishihara <yuya@tcha.org>
parents: 28343
diff changeset
   312
    except (TypeError, ValueError):
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   313
        raise error.ParseError(err)
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   314
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   315
def evalstring(context, mapping, arg):
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   316
    func, data = arg
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   317
    return stringify(func(context, mapping, data))
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   318
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   319
def evalstringliteral(context, mapping, arg):
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   320
    """Evaluate given argument as string template, but returns symbol name
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   321
    if it is unknown"""
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   322
    func, data = arg
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   323
    if func is runsymbol:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   324
        thing = func(context, mapping, data, default=data)
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   325
    else:
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   326
        thing = func(context, mapping, data)
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   327
    return stringify(thing)
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   328
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   329
def runinteger(context, mapping, data):
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   330
    return int(data)
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   331
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   332
def runstring(context, mapping, data):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   333
    return data
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   334
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   335
def _recursivesymbolblocker(key):
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   336
    def showrecursion(**args):
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   337
        raise error.Abort(_("recursive reference '%s' in template") % key)
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   338
    return showrecursion
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   339
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   340
def _runrecursivesymbol(context, mapping, key):
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   341
    raise error.Abort(_("recursive reference '%s' in template") % key)
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   342
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   343
def runsymbol(context, mapping, key, default=''):
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   344
    v = mapping.get(key)
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   345
    if v is None:
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   346
        v = context._defaults.get(key)
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   347
    if v is None:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   348
        # put poison to cut recursion. we can't move this to parsing phase
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   349
        # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   350
        safemapping = mapping.copy()
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   351
        safemapping[key] = _recursivesymbolblocker(key)
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   352
        try:
27939
7ed3a3c0cef1 templater: abort if infinite recursion detected while evaluation (issue4758)
Yuya Nishihara <yuya@tcha.org>
parents: 27892
diff changeset
   353
            v = context.process(key, safemapping)
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
   354
        except TemplateNotFound:
28373
9a9dd71e882c templater: make label() take unknown symbol as color literal
Yuya Nishihara <yuya@tcha.org>
parents: 28349
diff changeset
   355
            v = default
21798
f2c617ff2abc templater: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21540
diff changeset
   356
    if callable(v):
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   357
        return v(**mapping)
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   358
    return v
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   359
25596
c1975809a6b5 templater: take any string literals as template, but not for rawstring (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25595
diff changeset
   360
def buildtemplate(exp, context):
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   361
    ctmpl = [compileexp(e, context, methods) for e in exp[1:]]
25596
c1975809a6b5 templater: take any string literals as template, but not for rawstring (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25595
diff changeset
   362
    return (runtemplate, ctmpl)
c1975809a6b5 templater: take any string literals as template, but not for rawstring (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25595
diff changeset
   363
25595
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   364
def runtemplate(context, mapping, template):
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   365
    for func, data in template:
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   366
        yield func(context, mapping, data)
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   367
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   368
def buildfilter(exp, context):
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   369
    arg = compileexp(exp[1], context, methods)
26104
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   370
    n = getsymbol(exp[2])
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   371
    if n in context._filters:
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   372
        filt = context._filters[n]
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   373
        return (runfilter, (arg, filt))
26105
d67341f55429 templater: introduce unified filter syntax for unary functions
Yuya Nishihara <yuya@tcha.org>
parents: 26104
diff changeset
   374
    if n in funcs:
d67341f55429 templater: introduce unified filter syntax for unary functions
Yuya Nishihara <yuya@tcha.org>
parents: 26104
diff changeset
   375
        f = funcs[n]
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   376
        return (f, [arg])
26104
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   377
    raise error.ParseError(_("unknown function '%s'") % n)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   378
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   379
def runfilter(context, mapping, data):
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   380
    arg, filt = data
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   381
    thing = evalfuncarg(context, mapping, arg)
17383
099c778ceb33 templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents: 17334
diff changeset
   382
    try:
24280
6c55e37ba5f2 templater: allow piping generator-type function output to filters
Yuya Nishihara <yuya@tcha.org>
parents: 24240
diff changeset
   383
        return filt(thing)
17383
099c778ceb33 templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents: 17334
diff changeset
   384
    except (ValueError, AttributeError, TypeError):
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   385
        if isinstance(arg[1], tuple):
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   386
            dt = arg[1][1]
17383
099c778ceb33 templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents: 17334
diff changeset
   387
        else:
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   388
            dt = arg[1]
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26564
diff changeset
   389
        raise error.Abort(_("template filter '%s' is not compatible with "
17383
099c778ceb33 templater: abort when a template filter raises an exception (issue2987)
Neil Kodner <neilk@fb.com>
parents: 17334
diff changeset
   390
                           "keyword '%s'") % (filt.func_name, dt))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   391
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   392
def buildmap(exp, context):
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   393
    func, data = compileexp(exp[1], context, methods)
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   394
    tfunc, tdata = gettemplate(exp[2], context)
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   395
    return (runmap, (func, data, tfunc, tdata))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   396
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   397
def runmap(context, mapping, data):
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   398
    func, data, tfunc, tdata = data
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   399
    d = func(context, mapping, data)
27891
ac8c0ee5c3b8 templater: make _hybrid not callable to avoid conflicting semantics
Yuya Nishihara <yuya@tcha.org>
parents: 27637
diff changeset
   400
    if util.safehasattr(d, 'itermaps'):
28349
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   401
        diter = d.itermaps()
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   402
    else:
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   403
        try:
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   404
            diter = iter(d)
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   405
        except TypeError:
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   406
            if func is runsymbol:
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   407
                raise error.ParseError(_("keyword '%s' is not iterable") % data)
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   408
            else:
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   409
                raise error.ParseError(_("%r is not iterable") % d)
17631
0b241d7a8c62 templating: make new-style templating features work with command line lists
Matt Mackall <mpm@selenic.com>
parents: 17383
diff changeset
   410
28349
7cb2f2438f85 templater: handle exception when applying map operator to non-iterable object
Yuya Nishihara <yuya@tcha.org>
parents: 28348
diff changeset
   411
    for i in diter:
28225
5c11702fe2a3 templater: fix list templating bug
Kostia Balytskyi <ikostia@fb.com>
parents: 28178
diff changeset
   412
        lm = mapping.copy()
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   413
        if isinstance(i, dict):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   414
            lm.update(i)
17991
d605a82cf189 hgweb: display diff for a changeset against any parents (issue2810)
Weiwen <weiwen@fb.com>
parents: 17982
diff changeset
   415
            lm['originalnode'] = mapping.get('node')
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   416
            yield tfunc(context, lm, tdata)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   417
        else:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   418
            # v is not an iterable of dicts, this happen when 'key'
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   419
            # has been fully expanded already and format is useless.
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   420
            # If so, return the expanded value.
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   421
            yield i
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   422
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   423
def buildfunc(exp, context):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   424
    n = getsymbol(exp[1])
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   425
    args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
14925
ab545a15d807 templater: use a global funcs table
Matt Mackall <mpm@selenic.com>
parents: 14168
diff changeset
   426
    if n in funcs:
ab545a15d807 templater: use a global funcs table
Matt Mackall <mpm@selenic.com>
parents: 14168
diff changeset
   427
        f = funcs[n]
ab545a15d807 templater: use a global funcs table
Matt Mackall <mpm@selenic.com>
parents: 14168
diff changeset
   428
        return (f, args)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   429
    if n in context._filters:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   430
        if len(args) != 1:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   431
            raise error.ParseError(_("filter %s expects one argument") % n)
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   432
        f = context._filters[n]
26125
c990afab2243 templater: drop unneeded destructuring of argument tuple at buildfilter
Yuya Nishihara <yuya@tcha.org>
parents: 26124
diff changeset
   433
        return (runfilter, (args[0], f))
20857
6eb55310fcbc templater: raise error for unknown func
Sean Farley <sean.michael.farley@gmail.com>
parents: 20663
diff changeset
   434
    raise error.ParseError(_("unknown function '%s'") % n)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   435
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   436
# dict of template built-in functions
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   437
funcs = {}
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   438
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   439
templatefunc = registrar.templatefunc(funcs)
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   440
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   441
@templatefunc('date(date[, fmt])')
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   442
def date(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   443
    """Format a date. See :hg:`help dates` for formatting
26106
c568c4db036f templatefilters: remove redundant 'date' and 'strip' filters
Yuya Nishihara <yuya@tcha.org>
parents: 26105
diff changeset
   444
    strings. The default is a Unix date format, including the timezone:
c568c4db036f templatefilters: remove redundant 'date' and 'strip' filters
Yuya Nishihara <yuya@tcha.org>
parents: 26105
diff changeset
   445
    "Mon Sep 04 15:13:13 2006 0700"."""
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   446
    if not (1 <= len(args) <= 2):
23112
3226ed457928 i18n: add i18n comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22844
diff changeset
   447
        # i18n: "date" is a keyword
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   448
        raise error.ParseError(_("date expects one or two arguments"))
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   449
28334
9dc340f51e06 templater: make date() use helper function to evaluate argument
Yuya Nishihara <yuya@tcha.org>
parents: 28333
diff changeset
   450
    date = evalfuncarg(context, mapping, args[0])
24903
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   451
    fmt = None
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   452
    if len(args) == 2:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   453
        fmt = evalstring(context, mapping, args[1])
24903
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   454
    try:
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   455
        if fmt is None:
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   456
            return util.datestr(date)
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   457
        else:
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   458
            return util.datestr(date, fmt)
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   459
    except (TypeError, ValueError):
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   460
        # i18n: "date" is a keyword
09124cce913f templater: fix crash by passing invalid object to date() function
Yuya Nishihara <yuya@tcha.org>
parents: 24886
diff changeset
   461
        raise error.ParseError(_("date expects a date information"))
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   462
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   463
@templatefunc('diff([includepattern [, excludepattern]])')
22434
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   464
def diff(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   465
    """Show a diff, optionally
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   466
    specifying files to include or exclude."""
22434
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   467
    if len(args) > 2:
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   468
        # i18n: "diff" is a keyword
27293
9e06e7fb037d grammar: favor zero, one, two over ... or no
timeless <timeless@mozdev.org>
parents: 26587
diff changeset
   469
        raise error.ParseError(_("diff expects zero, one, or two arguments"))
22434
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   470
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   471
    def getpatterns(i):
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   472
        if i < len(args):
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   473
            s = evalstring(context, mapping, args[i]).strip()
22434
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   474
            if s:
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   475
                return [s]
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   476
        return []
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   477
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   478
    ctx = mapping['ctx']
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   479
    chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   480
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   481
    return ''.join(chunks)
40ce05b50148 templater: add "diff" template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22304
diff changeset
   482
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   483
@templatefunc('fill(text[, width[, initialident[, hangindent]]])')
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   484
def fill(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   485
    """Fill many
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   486
    paragraphs with optional indentation. See the "fill" filter."""
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   487
    if not (1 <= len(args) <= 4):
23112
3226ed457928 i18n: add i18n comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22844
diff changeset
   488
        # i18n: "fill" is a keyword
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   489
        raise error.ParseError(_("fill expects one to four arguments"))
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   490
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   491
    text = evalstring(context, mapping, args[0])
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   492
    width = 76
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   493
    initindent = ''
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   494
    hangindent = ''
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   495
    if 2 <= len(args) <= 4:
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   496
        width = evalinteger(context, mapping, args[1],
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   497
                            # i18n: "fill" is a keyword
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   498
                            _("fill expects an integer width"))
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   499
        try:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   500
            initindent = evalstring(context, mapping, args[2])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   501
            hangindent = evalstring(context, mapping, args[3])
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   502
        except IndexError:
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   503
            pass
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   504
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   505
    return templatefilters.fill(text, width, initindent, hangindent)
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   506
29818
407879b0893b templater: rename "right" argument of pad() function
Yuya Nishihara <yuya@tcha.org>
parents: 29817
diff changeset
   507
@templatefunc('pad(text, width[, fillchar=\' \'[, left=False]])')
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   508
def pad(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   509
    """Pad text with a
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   510
    fill character."""
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   511
    if not (2 <= len(args) <= 4):
23112
3226ed457928 i18n: add i18n comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22844
diff changeset
   512
        # i18n: "pad" is a keyword
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   513
        raise error.ParseError(_("pad() expects two to four arguments"))
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   514
28345
d81437c91a26 templater: fix pad() to evaluate int argument and handle error
Yuya Nishihara <yuya@tcha.org>
parents: 28344
diff changeset
   515
    width = evalinteger(context, mapping, args[1],
d81437c91a26 templater: fix pad() to evaluate int argument and handle error
Yuya Nishihara <yuya@tcha.org>
parents: 28344
diff changeset
   516
                        # i18n: "pad" is a keyword
d81437c91a26 templater: fix pad() to evaluate int argument and handle error
Yuya Nishihara <yuya@tcha.org>
parents: 28344
diff changeset
   517
                        _("pad() expects an integer width"))
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   518
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   519
    text = evalstring(context, mapping, args[0])
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   520
29818
407879b0893b templater: rename "right" argument of pad() function
Yuya Nishihara <yuya@tcha.org>
parents: 29817
diff changeset
   521
    left = False
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   522
    fillchar = ' '
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   523
    if len(args) > 2:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   524
        fillchar = evalstring(context, mapping, args[2])
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   525
    if len(args) > 3:
29818
407879b0893b templater: rename "right" argument of pad() function
Yuya Nishihara <yuya@tcha.org>
parents: 29817
diff changeset
   526
        left = evalboolean(context, mapping, args[3])
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   527
29818
407879b0893b templater: rename "right" argument of pad() function
Yuya Nishihara <yuya@tcha.org>
parents: 29817
diff changeset
   528
    if left:
20370
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   529
        return text.rjust(width, fillchar)
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   530
    else:
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   531
        return text.ljust(width, fillchar)
aa51392da507 template: add pad function for padding output
Durham Goode <durham@fb.com>
parents: 20369
diff changeset
   532
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   533
@templatefunc('indent(text, indentchars[, firstline])')
25489
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   534
def indent(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   535
    """Indents all non-empty lines
25489
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   536
    with the characters given in the indentchars string. An optional
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   537
    third parameter will override the indent for the first line only
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   538
    if present."""
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   539
    if not (2 <= len(args) <= 3):
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   540
        # i18n: "indent" is a keyword
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   541
        raise error.ParseError(_("indent() expects two or three arguments"))
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   542
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   543
    text = evalstring(context, mapping, args[0])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   544
    indent = evalstring(context, mapping, args[1])
25489
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   545
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   546
    if len(args) == 3:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   547
        firstline = evalstring(context, mapping, args[2])
25489
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   548
    else:
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   549
        firstline = indent
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   550
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   551
    # the indent function doesn't indent the first line, so we do it here
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   552
    return templatefilters.indent(firstline + text, indent)
ef8956aa8755 templater: introduce indent function
Ryan McElroy <rmcelroy@fb.com>
parents: 25096
diff changeset
   553
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   554
@templatefunc('get(dict, key)')
18582
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   555
def get(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   556
    """Get an attribute/key from an object. Some keywords
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   557
    are complex types. This function allows you to obtain the value of an
26197
fb6c08a9b40a templater: fix get English
timeless@mozdev.org
parents: 26188
diff changeset
   558
    attribute on these types."""
18582
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   559
    if len(args) != 2:
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   560
        # i18n: "get" is a keyword
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   561
        raise error.ParseError(_("get() expects two arguments"))
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   562
28331
2874db5462d3 templater: fix get() to evaluate arguments eagerly
Yuya Nishihara <yuya@tcha.org>
parents: 28225
diff changeset
   563
    dictarg = evalfuncarg(context, mapping, args[0])
18582
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   564
    if not util.safehasattr(dictarg, 'get'):
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   565
        # i18n: "get" is a keyword
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   566
        raise error.ParseError(_("get() expects a dict as first argument"))
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   567
28331
2874db5462d3 templater: fix get() to evaluate arguments eagerly
Yuya Nishihara <yuya@tcha.org>
parents: 28225
diff changeset
   568
    key = evalfuncarg(context, mapping, args[1])
27892
83aef8d5bc1b templater: make get(dict, key) return a single value
Yuya Nishihara <yuya@tcha.org>
parents: 27891
diff changeset
   569
    return dictarg.get(key)
18582
ef78450c8df6 templater: add get() function to access dict element (e.g. extra)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 18289
diff changeset
   570
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   571
@templatefunc('if(expr, then[, else])')
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   572
def if_(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   573
    """Conditionally execute based on the result of
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   574
    an expression."""
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   575
    if not (2 <= len(args) <= 3):
17890
ca6850b9dd9e i18n: add "i18n" comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17729
diff changeset
   576
        # i18n: "if" is a keyword
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   577
        raise error.ParseError(_("if expects two or three arguments"))
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   578
29816
034412ca28c3 templater: fix if() to not evaluate False as bool('False')
Yuya Nishihara <yuya@tcha.org>
parents: 29815
diff changeset
   579
    test = evalboolean(context, mapping, args[0])
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   580
    if test:
25597
fd5bc660c9f0 templater: do not reevaluate rawstring as template (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25596
diff changeset
   581
        yield args[1][0](context, mapping, args[1][1])
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   582
    elif len(args) == 3:
25597
fd5bc660c9f0 templater: do not reevaluate rawstring as template (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25596
diff changeset
   583
        yield args[2][0](context, mapping, args[2][1])
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   584
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   585
@templatefunc('ifcontains(search, thing, then[, else])')
20518
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   586
def ifcontains(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   587
    """Conditionally execute based
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   588
    on whether the item "search" is in "thing"."""
20518
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   589
    if not (3 <= len(args) <= 4):
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   590
        # i18n: "ifcontains" is a keyword
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   591
        raise error.ParseError(_("ifcontains expects three or four arguments"))
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   592
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   593
    item = evalstring(context, mapping, args[0])
28332
e91371633127 templater: fix ifcontains() to evaluate items argument eagerly
Yuya Nishihara <yuya@tcha.org>
parents: 28331
diff changeset
   594
    items = evalfuncarg(context, mapping, args[1])
20518
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   595
24240
bd504d90588d templater: implement _hybrid.__contains__ so that ifcontains can accept dict
Yuya Nishihara <yuya@tcha.org>
parents: 24114
diff changeset
   596
    if item in items:
25597
fd5bc660c9f0 templater: do not reevaluate rawstring as template (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25596
diff changeset
   597
        yield args[2][0](context, mapping, args[2][1])
20518
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   598
    elif len(args) == 4:
25597
fd5bc660c9f0 templater: do not reevaluate rawstring as template (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25596
diff changeset
   599
        yield args[3][0](context, mapping, args[3][1])
20518
1e43f15a647f template: add ifcontains template function
Durham Goode <durham@fb.com>
parents: 20371
diff changeset
   600
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   601
@templatefunc('ifeq(expr1, expr2, then[, else])')
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   602
def ifeq(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   603
    """Conditionally execute based on
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   604
    whether 2 items are equivalent."""
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   605
    if not (3 <= len(args) <= 4):
17890
ca6850b9dd9e i18n: add "i18n" comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17729
diff changeset
   606
        # i18n: "ifeq" is a keyword
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   607
        raise error.ParseError(_("ifeq expects three or four arguments"))
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   608
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   609
    test = evalstring(context, mapping, args[0])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   610
    match = evalstring(context, mapping, args[1])
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   611
    if test == match:
25597
fd5bc660c9f0 templater: do not reevaluate rawstring as template (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25596
diff changeset
   612
        yield args[2][0](context, mapping, args[2][1])
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   613
    elif len(args) == 4:
25597
fd5bc660c9f0 templater: do not reevaluate rawstring as template (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25596
diff changeset
   614
        yield args[3][0](context, mapping, args[3][1])
17636
ce18dbcd91c8 templater: add if/ifeq conditionals
Matt Mackall <mpm@selenic.com>
parents: 17635
diff changeset
   615
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   616
@templatefunc('join(list, sep)')
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   617
def join(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   618
    """Join items in a list with a delimiter."""
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   619
    if not (1 <= len(args) <= 2):
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   620
        # i18n: "join" is a keyword
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   621
        raise error.ParseError(_("join expects one or two arguments"))
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   622
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   623
    joinset = args[0][0](context, mapping, args[0][1])
27891
ac8c0ee5c3b8 templater: make _hybrid not callable to avoid conflicting semantics
Yuya Nishihara <yuya@tcha.org>
parents: 27637
diff changeset
   624
    if util.safehasattr(joinset, 'itermaps'):
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   625
        jf = joinset.joinfmt
27891
ac8c0ee5c3b8 templater: make _hybrid not callable to avoid conflicting semantics
Yuya Nishihara <yuya@tcha.org>
parents: 27637
diff changeset
   626
        joinset = [jf(x) for x in joinset.itermaps()]
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   627
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   628
    joiner = " "
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   629
    if len(args) > 1:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   630
        joiner = evalstring(context, mapping, args[1])
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   631
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   632
    first = True
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   633
    for x in joinset:
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   634
        if first:
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   635
            first = False
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   636
        else:
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   637
            yield joiner
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   638
        yield x
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   639
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   640
@templatefunc('label(label, expr)')
18289
9bfb53106328 templater: add no-op template function 'label'
Sean Farley <sean.michael.farley@gmail.com>
parents: 17991
diff changeset
   641
def label(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   642
    """Apply a label to generated content. Content with
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   643
    a label applied can result in additional post-processing, such as
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   644
    automatic colorization."""
18289
9bfb53106328 templater: add no-op template function 'label'
Sean Farley <sean.michael.farley@gmail.com>
parents: 17991
diff changeset
   645
    if len(args) != 2:
9bfb53106328 templater: add no-op template function 'label'
Sean Farley <sean.michael.farley@gmail.com>
parents: 17991
diff changeset
   646
        # i18n: "label" is a keyword
9bfb53106328 templater: add no-op template function 'label'
Sean Farley <sean.michael.farley@gmail.com>
parents: 17991
diff changeset
   647
        raise error.ParseError(_("label expects two arguments"))
9bfb53106328 templater: add no-op template function 'label'
Sean Farley <sean.michael.farley@gmail.com>
parents: 17991
diff changeset
   648
28462
dbba18ba26d4 templater: make label() just fail if ui object isn't available
Yuya Nishihara <yuya@tcha.org>
parents: 28403
diff changeset
   649
    ui = mapping['ui']
28374
af3bd9d1dbc1 templater: move label() function from color extension
Yuya Nishihara <yuya@tcha.org>
parents: 28373
diff changeset
   650
    thing = evalstring(context, mapping, args[1])
af3bd9d1dbc1 templater: move label() function from color extension
Yuya Nishihara <yuya@tcha.org>
parents: 28373
diff changeset
   651
    # preserve unknown symbol as literal so effects like 'red', 'bold',
af3bd9d1dbc1 templater: move label() function from color extension
Yuya Nishihara <yuya@tcha.org>
parents: 28373
diff changeset
   652
    # etc. don't need to be quoted
af3bd9d1dbc1 templater: move label() function from color extension
Yuya Nishihara <yuya@tcha.org>
parents: 28373
diff changeset
   653
    label = evalstringliteral(context, mapping, args[0])
af3bd9d1dbc1 templater: move label() function from color extension
Yuya Nishihara <yuya@tcha.org>
parents: 28373
diff changeset
   654
28384
3356bf61fa25 formatter: make labels work with templated output
Kostia Balytskyi <ikostia@fb.com>
parents: 28374
diff changeset
   655
    return ui.label(thing, label)
18289
9bfb53106328 templater: add no-op template function 'label'
Sean Farley <sean.michael.farley@gmail.com>
parents: 17991
diff changeset
   656
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   657
@templatefunc('latesttag([pattern])')
26485
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   658
def latesttag(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   659
    """The global tags matching the given pattern on the
26485
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   660
    most recent globally tagged ancestor of this changeset."""
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   661
    if len(args) > 1:
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   662
        # i18n: "latesttag" is a keyword
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   663
        raise error.ParseError(_("latesttag expects at most one argument"))
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   664
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   665
    pattern = None
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   666
    if len(args) == 1:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   667
        pattern = evalstring(context, mapping, args[0])
26485
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   668
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   669
    return templatekw.showlatesttags(pattern, **mapping)
43bf9471fae9 templater: introduce {latesttag()} function to match a pattern (issue4184)
Matt Harbison <matt_harbison@yahoo.com>
parents: 26334
diff changeset
   670
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   671
@templatefunc('localdate(date[, tz])')
26127
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   672
def localdate(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   673
    """Converts a date to the specified timezone.
26128
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   674
    The default is local date."""
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   675
    if not (1 <= len(args) <= 2):
26127
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   676
        # i18n: "localdate" is a keyword
26128
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   677
        raise error.ParseError(_("localdate expects one or two arguments"))
26127
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   678
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   679
    date = evalfuncarg(context, mapping, args[0])
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   680
    try:
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   681
        date = util.parsedate(date)
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   682
    except AttributeError:  # not str nor date tuple
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   683
        # i18n: "localdate" is a keyword
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   684
        raise error.ParseError(_("localdate expects a date information"))
26128
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   685
    if len(args) >= 2:
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   686
        tzoffset = None
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   687
        tz = evalfuncarg(context, mapping, args[1])
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   688
        if isinstance(tz, str):
29636
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29085
diff changeset
   689
            tzoffset, remainder = util.parsetimezone(tz)
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29085
diff changeset
   690
            if remainder:
84ef4517de03 date: refactor timezone parsing
Matt Mackall <mpm@selenic.com>
parents: 29085
diff changeset
   691
                tzoffset = None
26128
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   692
        if tzoffset is None:
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   693
            try:
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   694
                tzoffset = int(tz)
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   695
            except (TypeError, ValueError):
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   696
                # i18n: "localdate" is a keyword
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   697
                raise error.ParseError(_("localdate expects a timezone"))
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   698
    else:
51f6940d3b4f templater: add optional timezone argument to localdate()
Yuya Nishihara <yuya@tcha.org>
parents: 26127
diff changeset
   699
        tzoffset = util.makedate()[1]
26127
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   700
    return (date[0], tzoffset)
7012be5ab5bd templater: port localdate filter to a function
Yuya Nishihara <yuya@tcha.org>
parents: 26125
diff changeset
   701
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   702
@templatefunc('revset(query[, formatargs...])')
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   703
def revset(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   704
    """Execute a revision set query. See
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   705
    :hg:`help revset`."""
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   706
    if not len(args) > 0:
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   707
        # i18n: "revset" is a keyword
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   708
        raise error.ParseError(_("revset expects one or more arguments"))
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   709
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   710
    raw = evalstring(context, mapping, args[0])
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   711
    ctx = mapping['ctx']
24337
696ab1a24ae0 templater: replace 'ctx._repo' with 'ctx.repo()'
Matt Harbison <matt_harbison@yahoo.com>
parents: 24306
diff changeset
   712
    repo = ctx.repo()
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   713
22304
5678b0e3608f templater: enable alias predicates to be used in "revset()" function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21960
diff changeset
   714
    def query(expr):
5678b0e3608f templater: enable alias predicates to be used in "revset()" function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21960
diff changeset
   715
        m = revsetmod.match(repo.ui, expr)
24114
fafd9a1284cf revset: make match function initiate query from full set by default
Yuya Nishihara <yuya@tcha.org>
parents: 23167
diff changeset
   716
        return m(repo)
22304
5678b0e3608f templater: enable alias predicates to be used in "revset()" function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21960
diff changeset
   717
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   718
    if len(args) > 1:
28333
41373244f4e5 templater: fix revset() to evaluate format arguments eagerly
Yuya Nishihara <yuya@tcha.org>
parents: 28332
diff changeset
   719
        formatargs = [evalfuncarg(context, mapping, a) for a in args[1:]]
22304
5678b0e3608f templater: enable alias predicates to be used in "revset()" function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21960
diff changeset
   720
        revs = query(revsetmod.formatspec(raw, *formatargs))
28178
96f2d50fb9f6 templater: factor out type conversion of revset() result
Yuya Nishihara <yuya@tcha.org>
parents: 27940
diff changeset
   721
        revs = list(revs)
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   722
    else:
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   723
        revsetcache = mapping['cache'].setdefault("revsetcache", {})
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   724
        if raw in revsetcache:
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   725
            revs = revsetcache[raw]
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   726
        else:
22304
5678b0e3608f templater: enable alias predicates to be used in "revset()" function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21960
diff changeset
   727
            revs = query(raw)
28178
96f2d50fb9f6 templater: factor out type conversion of revset() result
Yuya Nishihara <yuya@tcha.org>
parents: 27940
diff changeset
   728
            revs = list(revs)
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   729
            revsetcache[raw] = revs
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   730
26234
e4609ec959f8 templater: switch ctx of list expression to rev of revset() (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
   731
    return templatekw.showrevslist("revision", revs, **mapping)
20519
cda9d2b6beab template: add revset() template function
Durham Goode <durham@fb.com>
parents: 20518
diff changeset
   732
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   733
@templatefunc('rstdoc(text, style)')
18747
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   734
def rstdoc(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   735
    """Format ReStructuredText."""
18747
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   736
    if len(args) != 2:
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   737
        # i18n: "rstdoc" is a keyword
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   738
        raise error.ParseError(_("rstdoc expects two arguments"))
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   739
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   740
    text = evalstring(context, mapping, args[0])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   741
    style = evalstring(context, mapping, args[1])
18747
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   742
19079
1e433b5457fd hgweb: make help verbose again (issue3899)
Alexander Plavin <me@aplavin.ru>
parents: 19058
diff changeset
   743
    return minirst.format(text, style=style, keep=['verbose'])
18747
f5db3092790f hgweb: generate HTML documentation
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18582
diff changeset
   744
29085
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   745
@templatefunc('separate(sep, args)')
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   746
def separate(context, mapping, args):
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   747
    """Add a separator between non-empty arguments."""
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   748
    if not args:
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   749
        # i18n: "separate" is a keyword
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   750
        raise error.ParseError(_("separate expects at least one argument"))
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   751
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   752
    sep = evalstring(context, mapping, args[0])
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   753
    first = True
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   754
    for arg in args[1:]:
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   755
        argstr = evalstring(context, mapping, arg)
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   756
        if not argstr:
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   757
            continue
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   758
        if first:
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   759
            first = False
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   760
        else:
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   761
            yield sep
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   762
        yield argstr
df838803c1d4 templater: add separate() template function
Martin von Zweigbergk <martinvonz@google.com>
parents: 28957
diff changeset
   763
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   764
@templatefunc('shortest(node, minlength=4)')
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   765
def shortest(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   766
    """Obtain the shortest representation of
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   767
    a node."""
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   768
    if not (1 <= len(args) <= 2):
23112
3226ed457928 i18n: add i18n comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22844
diff changeset
   769
        # i18n: "shortest" is a keyword
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   770
        raise error.ParseError(_("shortest() expects one or two arguments"))
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   771
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   772
    node = evalstring(context, mapping, args[0])
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   773
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   774
    minlength = 4
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   775
    if len(args) > 1:
28346
542d200bd261 templater: fix shortest() to evaluate int argument and handle error
Yuya Nishihara <yuya@tcha.org>
parents: 28345
diff changeset
   776
        minlength = evalinteger(context, mapping, args[1],
542d200bd261 templater: fix shortest() to evaluate int argument and handle error
Yuya Nishihara <yuya@tcha.org>
parents: 28345
diff changeset
   777
                                # i18n: "shortest" is a keyword
542d200bd261 templater: fix shortest() to evaluate int argument and handle error
Yuya Nishihara <yuya@tcha.org>
parents: 28345
diff changeset
   778
                                _("shortest() expects an integer minlength"))
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   779
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   780
    cl = mapping['ctx']._repo.changelog
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   781
    def isvalid(test):
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   782
        try:
20371
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   783
            try:
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   784
                cl.index.partialmatch(test)
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   785
            except AttributeError:
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   786
                # Pure mercurial doesn't support partialmatch on the index.
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   787
                # Fallback to the slow way.
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   788
                if cl._partialmatch(test) is None:
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   789
                    return False
6f3fb6a974e0 template: fix shortest(node) function in pure mercurial
Durham Goode <durham@fb.com>
parents: 20370
diff changeset
   790
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   791
            try:
20539
aa021ece4506 templater: shorten pure integers
Sean Farley <sean.michael.farley@gmail.com>
parents: 20519
diff changeset
   792
                i = int(test)
aa021ece4506 templater: shorten pure integers
Sean Farley <sean.michael.farley@gmail.com>
parents: 20519
diff changeset
   793
                # if we are a pure int, then starting with zero will not be
aa021ece4506 templater: shorten pure integers
Sean Farley <sean.michael.farley@gmail.com>
parents: 20519
diff changeset
   794
                # confused as a rev; or, obviously, if the int is larger than
aa021ece4506 templater: shorten pure integers
Sean Farley <sean.michael.farley@gmail.com>
parents: 20519
diff changeset
   795
                # the value of the tip rev
aa021ece4506 templater: shorten pure integers
Sean Farley <sean.michael.farley@gmail.com>
parents: 20519
diff changeset
   796
                if test[0] == '0' or i > len(cl):
aa021ece4506 templater: shorten pure integers
Sean Farley <sean.michael.farley@gmail.com>
parents: 20519
diff changeset
   797
                    return True
20369
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   798
                return False
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   799
            except ValueError:
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   800
                return True
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   801
        except error.RevlogError:
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   802
            return False
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   803
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   804
    shortest = node
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   805
    startlength = max(6, minlength)
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   806
    length = startlength
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   807
    while True:
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   808
        test = node[:length]
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   809
        if isvalid(test):
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   810
            shortest = test
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   811
            if length == minlength or length > startlength:
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   812
                return shortest
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   813
            length -= 1
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   814
        else:
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   815
            length += 1
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   816
            if len(shortest) <= length:
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   817
                return shortest
9c6b86dd2ed2 template: add shortest(node) template function
Durham Goode <durham@fb.com>
parents: 20312
diff changeset
   818
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   819
@templatefunc('strip(text[, chars])')
19330
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   820
def strip(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   821
    """Strip characters from a string. By default,
26106
c568c4db036f templatefilters: remove redundant 'date' and 'strip' filters
Yuya Nishihara <yuya@tcha.org>
parents: 26105
diff changeset
   822
    strips all leading and trailing whitespace."""
19330
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   823
    if not (1 <= len(args) <= 2):
23112
3226ed457928 i18n: add i18n comment to error messages of template functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 22844
diff changeset
   824
        # i18n: "strip" is a keyword
19330
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   825
        raise error.ParseError(_("strip expects one or two arguments"))
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   826
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   827
    text = evalstring(context, mapping, args[0])
19330
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   828
    if len(args) == 2:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   829
        chars = evalstring(context, mapping, args[1])
19330
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   830
        return text.strip(chars)
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   831
    return text.strip()
867b9957d895 templater: add strip function with chars as an extra argument
Alexander Plavin <me@aplavin.ru>
parents: 19228
diff changeset
   832
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   833
@templatefunc('sub(pattern, replacement, expression)')
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   834
def sub(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   835
    """Perform text substitution
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   836
    using regular expressions."""
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   837
    if len(args) != 3:
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   838
        # i18n: "sub" is a keyword
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   839
        raise error.ParseError(_("sub expects three arguments"))
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   840
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   841
    pat = evalstring(context, mapping, args[0])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   842
    rpl = evalstring(context, mapping, args[1])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   843
    src = evalstring(context, mapping, args[2])
26188
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   844
    try:
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   845
        patre = re.compile(pat)
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   846
    except re.error:
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   847
        # i18n: "sub" is a keyword
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   848
        raise error.ParseError(_("sub got an invalid pattern: %s") % pat)
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   849
    try:
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   850
        yield patre.sub(rpl, src)
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   851
    except re.error:
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   852
        # i18n: "sub" is a keyword
662ea52d5dca templater: catch regexp error at sub() function
Yuya Nishihara <yuya@tcha.org>
parents: 26128
diff changeset
   853
        raise error.ParseError(_("sub got an invalid replacement: %s") % rpl)
19390
3af3a165db18 templater: sort functions alphabetically, as filters are
Alexander Plavin <me@aplavin.ru>
parents: 19330
diff changeset
   854
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   855
@templatefunc('startswith(pattern, text)')
21821
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   856
def startswith(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   857
    """Returns the value from the "text" argument
24586
90e3f5d22dad templater: add consistent docstrings to functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24337
diff changeset
   858
    if it begins with the content from the "pattern" argument."""
21821
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   859
    if len(args) != 2:
21960
2896d450fec4 templater: add i18n comments to error messages of newly added functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21846
diff changeset
   860
        # i18n: "startswith" is a keyword
21821
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   861
        raise error.ParseError(_("startswith expects two arguments"))
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   862
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   863
    patn = evalstring(context, mapping, args[0])
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   864
    text = evalstring(context, mapping, args[1])
21821
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   865
    if text.startswith(patn):
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   866
        return text
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   867
    return ''
4a445dc5abff templater: introduce startswith function
Ryan McElroy <rmcelroy@fb.com>
parents: 21798
diff changeset
   868
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   869
@templatefunc('word(number, text[, separator])')
21846
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   870
def word(context, mapping, args):
28696
efa192203623 templater: use templatefunc to mark a function as template function
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28695
diff changeset
   871
    """Return the nth word from a string."""
21846
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   872
    if not (2 <= len(args) <= 3):
21960
2896d450fec4 templater: add i18n comments to error messages of newly added functions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21846
diff changeset
   873
        # i18n: "word" is a keyword
21846
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   874
        raise error.ParseError(_("word expects two or three arguments, got %d")
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   875
                               % len(args))
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   876
28343
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   877
    num = evalinteger(context, mapping, args[0],
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   878
                      # i18n: "word" is a keyword
a6c2310b3827 templater: factor out function that evaluates argument as integer
Yuya Nishihara <yuya@tcha.org>
parents: 28334
diff changeset
   879
                      _("word expects an integer index"))
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   880
    text = evalstring(context, mapping, args[1])
21846
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   881
    if len(args) == 3:
28348
ccedb17a5657 templater: factor out thin helper that evaluates argument as string
Yuya Nishihara <yuya@tcha.org>
parents: 28346
diff changeset
   882
        splitter = evalstring(context, mapping, args[2])
21846
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   883
    else:
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   884
        splitter = None
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   885
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   886
    tokens = text.split(splitter)
26502
4ca98a389152 templater: protect word() from crashing on out of range negative value
Matt Harbison <matt_harbison@yahoo.com>
parents: 25815
diff changeset
   887
    if num >= len(tokens) or num < -len(tokens):
21846
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   888
        return ''
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   889
    else:
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   890
        return tokens[num]
8f23f8096606 templater: introduce word function
Ryan McElroy <rmcelroy@fb.com>
parents: 21822
diff changeset
   891
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   892
# methods to interpret function arguments or inner expressions (e.g. {_(x)})
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   893
exprmethods = {
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   894
    "integer": lambda e, c: (runinteger, e[1]),
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   895
    "string": lambda e, c: (runstring, e[1]),
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   896
    "symbol": lambda e, c: (runsymbol, e[1]),
25596
c1975809a6b5 templater: take any string literals as template, but not for rawstring (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25595
diff changeset
   897
    "template": buildtemplate,
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   898
    "group": lambda e, c: compileexp(e[1], c, exprmethods),
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   899
#    ".": buildmember,
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   900
    "|": buildfilter,
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   901
    "%": buildmap,
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   902
    "func": buildfunc,
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   903
    }
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   904
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   905
# methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   906
methods = exprmethods.copy()
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   907
methods["integer"] = exprmethods["symbol"]  # '{1}' as variable
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   908
28912
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   909
class _aliasrules(parser.basealiasrules):
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   910
    """Parsing and expansion rule set of template aliases"""
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   911
    _section = _('template alias')
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   912
    _parse = staticmethod(_parseexpr)
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   913
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   914
    @staticmethod
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   915
    def _trygetfunc(tree):
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   916
        """Return (name, args) if tree is func(...) or ...|filter; otherwise
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   917
        None"""
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   918
        if tree[0] == 'func' and tree[1][0] == 'symbol':
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   919
            return tree[1][1], getlist(tree[2])
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   920
        if tree[0] == '|' and tree[2][0] == 'symbol':
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   921
            return tree[2][1], [tree[1]]
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   922
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   923
def expandaliases(tree, aliases):
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   924
    """Return new tree of aliases are expanded"""
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   925
    aliasmap = _aliasrules.buildmap(aliases)
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   926
    return _aliasrules.expand(aliasmap, tree)
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   927
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   928
# template engine
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
   929
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
   930
stringify = templatefilters.stringify
7107
125c8fedcbe0 Allow hgweb to search for templates in more than one path.
Brendan Cully <brendan@kublai.com>
parents: 6783
diff changeset
   931
10850
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   932
def _flatten(thing):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   933
    '''yield a single stream from a possibly nested set of iterators'''
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   934
    if isinstance(thing, str):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   935
        yield thing
29815
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   936
    elif thing is None:
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   937
        pass
14944
e2c413bde8a5 globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__')
Augie Fackler <durin42@gmail.com>
parents: 14943
diff changeset
   938
    elif not util.safehasattr(thing, '__iter__'):
29815
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   939
        yield str(thing)
10852
0d50586a9d31 templater: raise nested functions
Matt Mackall <mpm@selenic.com>
parents: 10850
diff changeset
   940
    else:
10850
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   941
        for i in thing:
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   942
            if isinstance(i, str):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   943
                yield i
29815
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   944
            elif i is None:
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   945
                pass
14944
e2c413bde8a5 globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__')
Augie Fackler <durin42@gmail.com>
parents: 14943
diff changeset
   946
            elif not util.safehasattr(i, '__iter__'):
29815
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   947
                yield str(i)
0d5cc0c18b4e templater: make it clearer that _flatten() omits None
Yuya Nishihara <yuya@tcha.org>
parents: 29812
diff changeset
   948
            else:
10850
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   949
                for j in _flatten(i):
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   950
                    yield j
a63391e26284 templater: use recursive flattening
Matt Mackall <mpm@selenic.com>
parents: 10849
diff changeset
   951
24988
e8ff0b09acac templater: rename parsestring() to unquotestring() (API)
Yuya Nishihara <yuya@tcha.org>
parents: 24987
diff changeset
   952
def unquotestring(s):
28630
bf35644b9f3a templater: relax unquotestring() to fall back to bare string
Yuya Nishihara <yuya@tcha.org>
parents: 28628
diff changeset
   953
    '''unwrap quotes if any; otherwise returns unmodified string'''
28687
29c249dfb4ef templater: do not strip non-quote characters from template config
Yuya Nishihara <yuya@tcha.org>
parents: 28630
diff changeset
   954
    if len(s) < 2 or s[0] not in "'\"" or s[0] != s[-1]:
28630
bf35644b9f3a templater: relax unquotestring() to fall back to bare string
Yuya Nishihara <yuya@tcha.org>
parents: 28628
diff changeset
   955
        return s
25696
c1cac25ad1a6 templater: remove workaround for escaped quoted string in quoted template
Yuya Nishihara <yuya@tcha.org>
parents: 25695
diff changeset
   956
    return s[1:-1]
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   957
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   958
class engine(object):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   959
    '''template expansion engine.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   960
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   961
    template expansion works like this. a map file contains key=value
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   962
    pairs. if value is quoted, it is treated as string. otherwise, it
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   963
    is treated as name of template file.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   964
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   965
    templater is asked to expand a key in map. it looks up key, and
4334
66a3fe30f9fc minor typo fix in templater's docstring
TK Soh <teekaysoh@yahoo.com>
parents: 3904
diff changeset
   966
    looks for strings like this: {foo}. it expands {foo} by looking up
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   967
    foo in map, and substituting it. expansion is recursive: it stops
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   968
    when there is no more {foo} to replace.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   969
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   970
    expansion also allows formatting and filtering.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   971
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   972
    format uses key to expand each item in list. syntax is
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   973
    {key%format}.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   974
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   975
    filter uses function to transform value. syntax is
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   976
    {key|filter1|filter2|...}.'''
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   977
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
   978
    def __init__(self, loader, filters=None, defaults=None, aliases=()):
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
   979
        self._loader = loader
26330
ec4f3755d997 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26234
diff changeset
   980
        if filters is None:
ec4f3755d997 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26234
diff changeset
   981
            filters = {}
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
   982
        self._filters = filters
26331
2c6a741bf05e templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26330
diff changeset
   983
        if defaults is None:
2c6a741bf05e templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26330
diff changeset
   984
            defaults = {}
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
   985
        self._defaults = defaults
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
   986
        self._aliasmap = _aliasrules.buildmap(aliases)
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   987
        self._cache = {}  # key: (func, data)
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   988
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   989
    def _load(self, t):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   990
        '''load, parse, and cache a template'''
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   991
        if t not in self._cache:
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   992
            # put poison to cut recursion while compiling 't'
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   993
            self._cache[t] = (_runrecursivesymbol, t)
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   994
            try:
28956
eea98190ed73 templater: inline compiletemplate() function into engine
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   995
                x = parse(self._loader(t))
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
   996
                if self._aliasmap:
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
   997
                    x = _aliasrules.expand(self._aliasmap, x)
28956
eea98190ed73 templater: inline compiletemplate() function into engine
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   998
                self._cache[t] = compileexp(x, self, methods)
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   999
            except: # re-raises
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
  1000
                del self._cache[t]
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
  1001
                raise
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1002
        return self._cache[t]
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
  1003
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
  1004
    def process(self, t, mapping):
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
  1005
        '''Perform expansion. t is name of map element to expand.
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
  1006
        mapping contains added elements for use during expansion. Is a
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
  1007
        generator.'''
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
  1008
        func, data = self._load(t)
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
  1009
        return _flatten(func(self, mapping, data))
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
  1010
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
  1011
engines = {'default': engine}
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
  1012
19125
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1013
def stylelist():
22634
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1014
    paths = templatepaths()
20312
268a5ab5c27b templater: selecting a style with no templates does not crash (issue4140)
Simon Heimberg <simohe@besonet.ch>
parents: 20067
diff changeset
  1015
    if not paths:
268a5ab5c27b templater: selecting a style with no templates does not crash (issue4140)
Simon Heimberg <simohe@besonet.ch>
parents: 20067
diff changeset
  1016
        return _('no templates found, try `hg debuginstall` for more info')
27637
b502138f5faa cleanup: remove superfluous space after space after equals (python)
timeless <timeless@mozdev.org>
parents: 27293
diff changeset
  1017
    dirlist = os.listdir(paths[0])
19125
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1018
    stylelist = []
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1019
    for file in dirlist:
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1020
        split = file.split(".")
28403
d2e154dddb6e templater: ignore orig/rej files
timeless <timeless@mozdev.org>
parents: 28384
diff changeset
  1021
        if split[-1] in ('orig', 'rej'):
d2e154dddb6e templater: ignore orig/rej files
timeless <timeless@mozdev.org>
parents: 28384
diff changeset
  1022
            continue
19125
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1023
        if split[0] == "map-cmdline":
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1024
            stylelist.append(split[1])
19127
d982edcfe7f0 templater: fix output instability from gsoc patches
Augie Fackler <raf@durin42.com>
parents: 19125
diff changeset
  1025
    return ", ".join(sorted(stylelist))
19125
6ba6e345961e templater: show the style list when I try to use a wrong one
Iulian Stana <julian.stana@gmail.com>
parents: 19079
diff changeset
  1026
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1027
def _readmapfile(mapfile):
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1028
    """Load template elements from the given map file"""
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1029
    if not os.path.exists(mapfile):
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1030
        raise error.Abort(_("style '%s' not found") % mapfile,
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1031
                          hint=_("available styles: %s") % stylelist())
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1032
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1033
    base = os.path.dirname(mapfile)
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1034
    conf = config.config(includepaths=templatepaths())
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1035
    conf.read(mapfile)
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1036
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1037
    cache = {}
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1038
    tmap = {}
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1039
    for key, val in conf[''].items():
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1040
        if not val:
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1041
            raise error.ParseError(_('missing value'), conf.source('', key))
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1042
        if val[0] in "'\"":
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1043
            if val[0] != val[-1]:
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1044
                raise error.ParseError(_('unmatched quotes'),
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1045
                                       conf.source('', key))
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1046
            cache[key] = unquotestring(val)
29812
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1047
        elif key == "__base__":
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1048
            # treat as a pointer to a base class for this style
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1049
            path = util.normpath(os.path.join(base, val))
29848
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1050
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1051
            # fallback check in template paths
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1052
            if not os.path.exists(path):
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1053
                for p in templatepaths():
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1054
                    p2 = util.normpath(os.path.join(p, val))
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1055
                    if os.path.isfile(p2):
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1056
                        path = p2
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1057
                        break
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1058
                    p3 = util.normpath(os.path.join(p2, "map"))
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1059
                    if os.path.isfile(p3):
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1060
                        path = p3
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1061
                        break
b1f69dbdd76b templater: add template path to __base__ search
Matt Mackall <mpm@selenic.com>
parents: 29818
diff changeset
  1062
29812
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1063
            bcache, btmap = _readmapfile(path)
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1064
            for k in bcache:
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1065
                if k not in cache:
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1066
                    cache[k] = bcache[k]
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1067
            for k in btmap:
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1068
                if k not in tmap:
01f036f0e40b templater: add inheritance support to style maps
Matt Mackall <mpm@selenic.com>
parents: 29636
diff changeset
  1069
                    tmap[k] = btmap[k]
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1070
        else:
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1071
            val = 'default', val
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1072
            if ':' in val[1]:
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1073
                val = val[1].split(':', 1)
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1074
            tmap[key] = val[0], os.path.join(base, val[1])
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1075
    return cache, tmap
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1076
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26564
diff changeset
  1077
class TemplateNotFound(error.Abort):
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
  1078
    pass
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
  1079
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
  1080
class templater(object):
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
  1081
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1082
    def __init__(self, filters=None, defaults=None, cache=None, aliases=(),
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1083
                 minchunk=1024, maxchunk=65536):
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
  1084
        '''set up template engine.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
  1085
        filters is dict of functions. each transforms a value into another.
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1086
        defaults is dict of default map definitions.
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1087
        aliases is list of alias (name, replacement) pairs.
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1088
        '''
26332
66221730d372 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26331
diff changeset
  1089
        if filters is None:
66221730d372 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26331
diff changeset
  1090
            filters = {}
26333
727d57e94cda templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26332
diff changeset
  1091
        if defaults is None:
727d57e94cda templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26332
diff changeset
  1092
            defaults = {}
26334
0a5a774f5956 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26333
diff changeset
  1093
        if cache is None:
0a5a774f5956 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26333
diff changeset
  1094
            cache = {}
1975
6e1a8ea5d717 Duplicate cache when creating templater.
Shun-ichi Goto <shunichi.goto@gmail.com>
parents: 1964
diff changeset
  1095
        self.cache = cache.copy()
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
  1096
        self.map = {}
8360
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
  1097
        self.filters = templatefilters.filters.copy()
acc202b71619 templater: provide the standard template filters by default
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8312
diff changeset
  1098
        self.filters.update(filters)
1964
778281d46bb2 fix template bug that made hgweb break.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1955
diff changeset
  1099
        self.defaults = defaults
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1100
        self._aliases = aliases
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1101
        self.minchunk, self.maxchunk = minchunk, maxchunk
13187
e3b87fb34d00 templater: clarify engine caching
Matt Mackall <mpm@selenic.com>
parents: 13176
diff changeset
  1102
        self.ecache = {}
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
  1103
28954
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1104
    @classmethod
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1105
    def frommapfile(cls, mapfile, filters=None, defaults=None, cache=None,
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1106
                    minchunk=1024, maxchunk=65536):
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1107
        """Create templater from the specified map file"""
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1108
        t = cls(filters, defaults, cache, [], minchunk, maxchunk)
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
  1109
        cache, tmap = _readmapfile(mapfile)
28954
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1110
        t.cache.update(cache)
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1111
        t.map = tmap
f97a0bcfd7a1 templater: separate function to create templater from map file (API)
Yuya Nishihara <yuya@tcha.org>
parents: 28953
diff changeset
  1112
        return t
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
  1113
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
  1114
    def __contains__(self, key):
3637
e7639888bb2f templater: simplify cache and remove filter argument in __call__
Matt Mackall <mpm@selenic.com>
parents: 3636
diff changeset
  1115
        return key in self.cache or key in self.map
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
  1116
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
  1117
    def load(self, t):
6783
6d824dc86907 templater: make a template a string-only iterator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6434
diff changeset
  1118
        '''Get the template for the given template name. Use a local cache.'''
16686
67964cda8701 cleanup: "not x in y" -> "x not in y"
Brodie Rao <brodie@sf.io>
parents: 14944
diff changeset
  1119
        if t not in self.cache:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
  1120
            try:
14168
135e244776f0 prevent transient leaks of file handle by using new helper functions
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13665
diff changeset
  1121
                self.cache[t] = util.readfile(self.map[t][1])
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25654
diff changeset
  1122
            except KeyError as inst:
19770
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
  1123
                raise TemplateNotFound(_('"%s" not in template map') %
0361163efbaf templater: support using templates with non-standard names from map file
Alexander Plavin <alexander@plav.in>
parents: 19390
diff changeset
  1124
                                       inst.args[0])
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25654
diff changeset
  1125
            except IOError as inst:
1905
0c760737b996 improve template errors when something is wrong.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1904
diff changeset
  1126
                raise IOError(inst.args[0], _('template file %s: %s') %
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
  1127
                              (self.map[t][1], inst.args[1]))
6783
6d824dc86907 templater: make a template a string-only iterator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6434
diff changeset
  1128
        return self.cache[t]
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
  1129
10847
90f4367535a5 templater: map -> mapping
Matt Mackall <mpm@selenic.com>
parents: 10846
diff changeset
  1130
    def __call__(self, t, **mapping):
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
  1131
        ttype = t in self.map and self.map[t][0] or 'default'
13187
e3b87fb34d00 templater: clarify engine caching
Matt Mackall <mpm@selenic.com>
parents: 13176
diff changeset
  1132
        if ttype not in self.ecache:
28831
6b86ce3e3576 templater: give better error message for invalid engine type
Yuya Nishihara <yuya@tcha.org>
parents: 28696
diff changeset
  1133
            try:
6b86ce3e3576 templater: give better error message for invalid engine type
Yuya Nishihara <yuya@tcha.org>
parents: 28696
diff changeset
  1134
                ecls = engines[ttype]
6b86ce3e3576 templater: give better error message for invalid engine type
Yuya Nishihara <yuya@tcha.org>
parents: 28696
diff changeset
  1135
            except KeyError:
6b86ce3e3576 templater: give better error message for invalid engine type
Yuya Nishihara <yuya@tcha.org>
parents: 28696
diff changeset
  1136
                raise error.Abort(_('invalid template engine: %s') % ttype)
28957
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1137
            self.ecache[ttype] = ecls(self.load, self.filters, self.defaults,
d813132ea361 templater: load and expand aliases by template engine (API) (issue4842)
Yuya Nishihara <yuya@tcha.org>
parents: 28956
diff changeset
  1138
                                      self._aliases)
13187
e3b87fb34d00 templater: clarify engine caching
Matt Mackall <mpm@selenic.com>
parents: 13176
diff changeset
  1139
        proc = self.ecache[ttype]
8361
d8c5a7f25a40 templater: make the templating engine pluggable to some extent
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8360
diff changeset
  1140
10847
90f4367535a5 templater: map -> mapping
Matt Mackall <mpm@selenic.com>
parents: 10846
diff changeset
  1141
        stream = proc.process(t, mapping)
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1142
        if self.minchunk:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1143
            stream = util.increasingchunks(stream, min=self.minchunk,
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1144
                                           max=self.maxchunk)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1145
        return stream
7434
cf7741aa1e96 kill some trailing spaces
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7396
diff changeset
  1146
22634
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1147
def templatepaths():
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1148
    '''return locations used for template files.'''
22636
d844e220792a templater: don't search randomly for templates - trust util.datapath
Mads Kiilerich <madski@unity3d.com>
parents: 22635
diff changeset
  1149
    pathsrel = ['templates']
22635
660861a6fad4 templater: inline global 'path' list in templatepaths
Mads Kiilerich <madski@unity3d.com>
parents: 22634
diff changeset
  1150
    paths = [os.path.normpath(os.path.join(util.datapath, f))
660861a6fad4 templater: inline global 'path' list in templatepaths
Mads Kiilerich <madski@unity3d.com>
parents: 22634
diff changeset
  1151
             for f in pathsrel]
660861a6fad4 templater: inline global 'path' list in templatepaths
Mads Kiilerich <madski@unity3d.com>
parents: 22634
diff changeset
  1152
    return [p for p in paths if os.path.isdir(p)]
2189
e3eba577a0ae move changeset_templater into templater module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2001
diff changeset
  1153
22634
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1154
def templatepath(name):
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1155
    '''return location of template file. returns None if not found.'''
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1156
    for p in templatepaths():
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1157
        f = os.path.join(p, name)
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1158
        if os.path.exists(f):
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1159
            return f
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1160
    return None
2189
e3eba577a0ae move changeset_templater into templater module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2001
diff changeset
  1161
9842
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1162
def stylemap(styles, paths=None):
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1163
    """Return path to mapfile for a given style.
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1164
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1165
    Searches mapfile in the following locations:
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1166
    1. templatepath/style/map
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1167
    2. templatepath/map-style
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1168
    3. templatepath/map
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1169
    """
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1170
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1171
    if paths is None:
22634
e48a5d3996c2 templater: introduce templatepaths for getting paths searched for templates
Mads Kiilerich <madski@unity3d.com>
parents: 22633
diff changeset
  1172
        paths = templatepaths()
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1173
    elif isinstance(paths, str):
8223
02145b700fe4 templater: fix little problem from stylemap() changes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8218
diff changeset
  1174
        paths = [paths]
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1175
9842
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1176
    if isinstance(styles, str):
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1177
        styles = [styles]
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1178
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1179
    for style in styles:
24296
b73a22d1d9bf hgweb: prevent loading style map from directories other than specified paths
Yuya Nishihara <yuya@tcha.org>
parents: 23167
diff changeset
  1180
        # only plain name is allowed to honor template paths
b73a22d1d9bf hgweb: prevent loading style map from directories other than specified paths
Yuya Nishihara <yuya@tcha.org>
parents: 23167
diff changeset
  1181
        if (not style
b73a22d1d9bf hgweb: prevent loading style map from directories other than specified paths
Yuya Nishihara <yuya@tcha.org>
parents: 23167
diff changeset
  1182
            or style in (os.curdir, os.pardir)
b73a22d1d9bf hgweb: prevent loading style map from directories other than specified paths
Yuya Nishihara <yuya@tcha.org>
parents: 23167
diff changeset
  1183
            or os.sep in style
b73a22d1d9bf hgweb: prevent loading style map from directories other than specified paths
Yuya Nishihara <yuya@tcha.org>
parents: 23167
diff changeset
  1184
            or os.altsep and os.altsep in style):
9842
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1185
            continue
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1186
        locations = [os.path.join(style, 'map'), 'map-' + style]
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1187
        locations.append('map')
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1188
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1189
        for path in paths:
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1190
            for location in locations:
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1191
                mapfile = os.path.join(path, location)
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1192
                if os.path.isfile(mapfile):
d3dbdca92458 hgweb: don't choke when an inexistent style is requested (issue1901)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9372
diff changeset
  1193
                    return style, mapfile
7966
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1194
aa983c3d94a9 templater: move stylemap function from hgweb to templater
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7434
diff changeset
  1195
    raise RuntimeError("No hgweb templates found in %r" % paths)
24601
d80819f67d59 templater: tell hggettext to collect help of template functions
Yuya Nishihara <yuya@tcha.org>
parents: 24586
diff changeset
  1196
28695
cc103bd0dbf9 registrar: add templatefunc to mark a function as template function (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28687
diff changeset
  1197
def loadfunction(ui, extname, registrarobj):
cc103bd0dbf9 registrar: add templatefunc to mark a function as template function (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28687
diff changeset
  1198
    """Load template function from specified registrarobj
cc103bd0dbf9 registrar: add templatefunc to mark a function as template function (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28687
diff changeset
  1199
    """
cc103bd0dbf9 registrar: add templatefunc to mark a function as template function (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28687
diff changeset
  1200
    for name, func in registrarobj._table.iteritems():
cc103bd0dbf9 registrar: add templatefunc to mark a function as template function (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28687
diff changeset
  1201
        funcs[name] = func
cc103bd0dbf9 registrar: add templatefunc to mark a function as template function (API)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28687
diff changeset
  1202
24601
d80819f67d59 templater: tell hggettext to collect help of template functions
Yuya Nishihara <yuya@tcha.org>
parents: 24586
diff changeset
  1203
# tell hggettext to extract docstrings from these functions:
d80819f67d59 templater: tell hggettext to collect help of template functions
Yuya Nishihara <yuya@tcha.org>
parents: 24586
diff changeset
  1204
i18nfunctions = funcs.values()