mercurial/templater.py
author Manuel Jacob <me@manueljacob.de>
Thu, 15 Sep 2022 01:48:38 +0200
changeset 49494 c96ed4029fda
parent 48946 642e31cb55f0
child 49803 55d45d0de4e7
permissions -rw-r--r--
templates: add filter to reverse list The filter supports only lists because for lists, it’s straightforward to implement. Reversing text doesn’t seem very useful and is hard to implement. Reversing the bytes would break multi-bytes encodings. Reversing the code points would break characters consisting of multiple code points. Reversing graphemes is non-trivial without using a library not included in the standard library.
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
#
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46424
diff changeset
     3
# Copyright 2005, 2006 Olivia Mackall <olivia@selenic.com>
1909
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
37014
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
     8
"""Slightly complicated template engine for commands and hgweb
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
     9
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    10
This module provides low-level interface to the template engine. See the
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    11
formatter and cmdutil modules if you are looking for high-level functions
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    12
such as ``cmdutil.rendertemplate(ctx, tmpl)``.
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    13
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    14
Internal Data Types
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    15
-------------------
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    16
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    17
Template keywords and functions take a dictionary of current symbols and
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    18
resources (a "mapping") and return result. Inputs and outputs must be one
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    19
of the following data types:
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    20
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    21
bytes
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    22
    a byte string, which is generally a human-readable text in local encoding.
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    23
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    24
generator
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    25
    a lazily-evaluated byte string, which is a possibly nested generator of
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    26
    values of any printable types, and  will be folded by ``stringify()``
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    27
    or ``flatten()``.
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    28
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    29
None
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    30
    sometimes represents an empty value, which can be stringified to ''.
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    31
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    32
True, False, int, float
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    33
    can be stringified as such.
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    34
38226
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
    35
wrappedbytes, wrappedvalue
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
    36
    a wrapper for the above printable types.
7824783a6d5e templater: add wrapped types for pure non-list/dict values
Yuya Nishihara <yuya@tcha.org>
parents: 38225
diff changeset
    37
38285
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
    38
date
8d6109b49b31 templater: introduce a wrapper for date tuple (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 38283
diff changeset
    39
    represents a (unixtime, offset) tuple.
37014
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    40
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    41
hybrid
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    42
    represents a list/dict of printable values, which can also be converted
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    43
    to mappings by % operator.
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    44
38283
0e0d03d09ecd templater: rename mappable to hybriditem as it is the primary use case
Yuya Nishihara <yuya@tcha.org>
parents: 38226
diff changeset
    45
hybriditem
37014
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    46
    represents a scalar printable value, also supports % operator.
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37398
diff changeset
    47
44589
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43674
diff changeset
    48
revslist
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43674
diff changeset
    49
    represents a list of revision numbers.
fc1fa3a07af6 templater: introduce wrapper for smartset (API)
Yuya Nishihara <yuya@tcha.org>
parents: 43674
diff changeset
    50
37399
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37398
diff changeset
    51
mappinggenerator, mappinglist
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37398
diff changeset
    52
    represents mappings (i.e. a list of dicts), which may have default
0b64416224d9 templater: add class representing a nested mappings
Yuya Nishihara <yuya@tcha.org>
parents: 37398
diff changeset
    53
    output format.
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37399
diff changeset
    54
40475
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
    55
mappingdict
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
    56
    represents a single mapping (i.e. a dict), which may have default output
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
    57
    format.
8fa26f3baf30 templater: add wrapper for a single template mapping
Yuya Nishihara <yuya@tcha.org>
parents: 39582
diff changeset
    58
40935
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40618
diff changeset
    59
mappingnone
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40618
diff changeset
    60
    represents None of Optional[mappable], which will be mapped to an empty
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40618
diff changeset
    61
    string by % operation.
4591c9791a82 templatefuncs: specialize "no match" value of search() to allow % operation
Yuya Nishihara <yuya@tcha.org>
parents: 40618
diff changeset
    62
37499
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37399
diff changeset
    63
mappedgenerator
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37399
diff changeset
    64
    a lazily-evaluated list of byte strings, which is e.g. a result of %
75c13343cf38 templater: wrap result of '%' operation so it never looks like a thunk
Yuya Nishihara <yuya@tcha.org>
parents: 37399
diff changeset
    65
    operation.
37014
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    66
"""
a5311d7f4af8 templater: add brief doc about internal data types
Yuya Nishihara <yuya@tcha.org>
parents: 36989
diff changeset
    67
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    68
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
    69
import abc
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    70
import os
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    71
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    72
from .i18n import _
47857
2b76255a4f74 template: FileNotFoundError is actually a built in exception
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47836
diff changeset
    73
from .pycompat import (
2b76255a4f74 template: FileNotFoundError is actually a built in exception
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47836
diff changeset
    74
    FileNotFoundError,
2b76255a4f74 template: FileNotFoundError is actually a built in exception
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47836
diff changeset
    75
    getattr,
2b76255a4f74 template: FileNotFoundError is actually a built in exception
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47836
diff changeset
    76
)
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    77
from . import (
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    78
    config,
31520
6f150bb19317 templater: make pad() compute actual width
Yuya Nishihara <yuya@tcha.org>
parents: 31519
diff changeset
    79
    encoding,
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    80
    error,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    81
    parser,
30615
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
    82
    pycompat,
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    83
    templatefilters,
36922
521f6c7e1756 templater: split template functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36921
diff changeset
    84
    templatefuncs,
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
    85
    templateutil,
25985
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    86
    util,
7eb357b5f774 templater: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25815
diff changeset
    87
)
43674
5be909dbe385 util: remove datapath and swith users over to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43474
diff changeset
    88
from .utils import (
5be909dbe385 util: remove datapath and swith users over to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43474
diff changeset
    89
    resourceutil,
5be909dbe385 util: remove datapath and swith users over to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43474
diff changeset
    90
    stringutil,
5be909dbe385 util: remove datapath and swith users over to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43474
diff changeset
    91
)
36443
8dbd97aef915 templater: move specialized exception types to top
Yuya Nishihara <yuya@tcha.org>
parents: 36245
diff changeset
    92
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    93
# template parsing
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    94
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
    95
elements = {
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
    96
    # token-type: binding-strength, primary, prefix, infix, suffix
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    97
    b"(": (20, None, (b"group", 1, b")"), (b"func", 1, b")"), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    98
    b".": (18, None, None, (b".", 18), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    99
    b"%": (15, None, None, (b"%", 15), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   100
    b"|": (15, None, None, (b"|", 15), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   101
    b"*": (5, None, None, (b"*", 5), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   102
    b"/": (5, None, None, (b"/", 5), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   103
    b"+": (4, None, None, (b"+", 4), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   104
    b"-": (4, None, (b"negate", 19), (b"-", 4), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   105
    b"=": (3, None, None, (b"keyvalue", 3), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   106
    b",": (2, None, None, (b"list", 2), None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   107
    b")": (0, None, None, None, None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   108
    b"integer": (0, b"integer", None, None, None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   109
    b"symbol": (0, b"symbol", None, None, None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   110
    b"string": (0, b"string", None, None, None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   111
    b"template": (0, b"template", None, None, None),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   112
    b"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
   113
}
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   114
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   115
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   116
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
   117
    """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
   118
    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
   119
    pos = start
32154
52e222eef646 py3: use pycompat.bytestr instead of bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32037
diff changeset
   120
    program = pycompat.bytestr(program)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   121
    while pos < end:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   122
        c = program[pos]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   123
        if c.isspace():  # skip inter-token whitespace
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   124
            pass
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   125
        elif c in b"(=,).%|+-*/":  # handle simple operators
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   126
            yield (c, None, pos)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   127
        elif c in b'"\'':  # handle quoted templates
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   128
            s = pos + 1
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   129
            data, pos = _parsetemplate(program, s, end, c)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   130
            yield (b'template', data, s)
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   131
            pos -= 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   132
        elif c == b'r' and program[pos : pos + 2] in (b"r'", b'r"'):
25784
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
   133
            # handle quoted strings
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
   134
            c = program[pos + 1]
33e613687dab templater: remove processing of "string" literals from tokenizer
Yuya Nishihara <yuya@tcha.org>
parents: 25783
diff changeset
   135
            s = pos = pos + 2
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   136
            while pos < end:  # find closing quote
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   137
                d = program[pos]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   138
                if d == b'\\':  # 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
   139
                    pos += 2
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   140
                    continue
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   141
                if d == c:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   142
                    yield (b'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
   143
                    break
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   144
                pos += 1
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   145
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   146
                raise error.ParseError(_(b"unterminated string"), s)
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   147
        elif c.isdigit():
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   148
            s = pos
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   149
            while pos < end:
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   150
                d = program[pos]
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   151
                if not d.isdigit():
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   152
                    break
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   153
                pos += 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   154
            yield (b'integer', program[s:pos], s)
25002
829faf8ab605 templater: tokenize decimal integer literal (issue4638) (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25001
diff changeset
   155
            pos -= 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   156
        elif (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   157
            c == b'\\'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   158
            and program[pos : pos + 2] in (br"\'", br'\"')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   159
            or c == b'r'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   160
            and program[pos : pos + 3] in (br"r\'", br'r\"')
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   161
        ):
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   162
            # 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
   163
            # 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
   164
            # 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
   165
            #
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   166
            # 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
   167
            # 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
   168
            # ------------------------    ------------    ------------------
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   169
            # {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
   170
            #             ~~~~~~~~
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   171
            #             escaped quoted string
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   172
            if c == b'r':
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   173
                pos += 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   174
                token = b'string'
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   175
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   176
                token = b'template'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   177
            quote = program[pos : pos + 2]
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   178
            s = pos = pos + 2
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   179
            while pos < end:  # find closing escaped quote
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   180
                if program.startswith(b'\\\\\\', pos, end):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   181
                    pos += 4  # skip over double escaped characters
25676
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   182
                    continue
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   183
                if program.startswith(quote, pos, end):
26215
72aad184f061 templater: create string unescape helper (issue4798)
Matt Mackall <mpm@selenic.com>
parents: 26197
diff changeset
   184
                    # 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
   185
                    data = parser.unescapestr(program[s:pos])
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   186
                    if token == b'template':
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   187
                        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
   188
                    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
   189
                    pos += 1
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   190
                    break
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   191
                pos += 1
ec9c258e666d templater: parse \"...\" as string for 2.9.2-3.4 compatibility (issue4733)
Yuya Nishihara <yuya@tcha.org>
parents: 25638
diff changeset
   192
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   193
                raise error.ParseError(_(b"unterminated string"), s)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   194
        elif c.isalnum() or c in b'_':
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   195
            s = pos
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   196
            pos += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   197
            while pos < end:  # find end of symbol
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   198
                d = program[pos]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   199
                if not (d.isalnum() or d == b"_"):
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   200
                    break
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   201
                pos += 1
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   202
            sym = program[s:pos]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   203
            yield (b'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
   204
            pos -= 1
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   205
        elif c == term:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   206
            yield (b'end', None, pos)
25782
babd2c93bd99 templater: check existence of closing brace of template string
Yuya Nishihara <yuya@tcha.org>
parents: 25781
diff changeset
   207
            return
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   208
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   209
            raise error.ParseError(_(b"syntax error"), pos)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   210
        pos += 1
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   211
    if term:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   212
        raise error.ParseError(_(b"unterminated template expansion"), start)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   213
    yield (b'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
   214
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   215
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   216
def _parsetemplate(tmpl, start, stop, quote=b''):
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   217
    r"""
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   218
    >>> _parsetemplate(b'foo{bar}"baz', 0, 12)
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   219
    ([('string', 'foo'), ('symbol', 'bar'), ('string', '"baz')], 12)
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   220
    >>> _parsetemplate(b'foo{bar}"baz', 0, 12, quote=b'"')
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   221
    ([('string', 'foo'), ('symbol', 'bar')], 9)
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   222
    >>> _parsetemplate(b'foo"{bar}', 0, 9, quote=b'"')
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   223
    ([('string', 'foo')], 4)
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   224
    >>> _parsetemplate(br'foo\"bar"baz', 0, 12, quote=b'"')
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   225
    ([('string', 'foo"'), ('string', 'bar')], 9)
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   226
    >>> _parsetemplate(br'foo\\"bar', 0, 10, quote=b'"')
25785
f976b7dc5e7b templater: unify "string" and "rawstring"
Yuya Nishihara <yuya@tcha.org>
parents: 25784
diff changeset
   227
    ([('string', 'foo\\')], 6)
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   228
    """
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   229
    parsed = []
36244
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   230
    for typ, val, pos in _scantemplate(tmpl, start, stop, quote):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   231
        if typ == b'string':
36244
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   232
            parsed.append((typ, val))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   233
        elif typ == b'template':
36244
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   234
            parsed.append(val)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   235
        elif typ == b'end':
36244
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   236
            return parsed, pos
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   237
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   238
            raise error.ProgrammingError(b'unexpected type: %s' % typ)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   239
    raise error.ProgrammingError(b'unterminated scanning of template')
36244
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   240
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   241
36509
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   242
def scantemplate(tmpl, raw=False):
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   243
    r"""Scan (type, start, end) positions of outermost elements in template
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   244
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   245
    If raw=True, a backslash is not taken as an escape character just like
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   246
    r'' string in Python. Note that this is different from r'' literal in
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   247
    template in that no template fragment can appear in r'', e.g. r'{foo}'
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   248
    is a literal '{foo}', but ('{foo}', raw=True) is a template expression
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   249
    'foo'.
36245
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   250
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   251
    >>> list(scantemplate(b'foo{bar}"baz'))
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   252
    [('string', 0, 3), ('template', 3, 8), ('string', 8, 12)]
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   253
    >>> list(scantemplate(b'outer{"inner"}outer'))
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   254
    [('string', 0, 5), ('template', 5, 14), ('string', 14, 19)]
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   255
    >>> list(scantemplate(b'foo\\{escaped}'))
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   256
    [('string', 0, 5), ('string', 5, 13)]
36509
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   257
    >>> list(scantemplate(b'foo\\{escaped}', raw=True))
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   258
    [('string', 0, 4), ('template', 4, 13)]
36245
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   259
    """
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   260
    last = None
36509
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   261
    for typ, val, pos in _scantemplate(tmpl, 0, len(tmpl), raw=raw):
36245
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   262
        if last:
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   263
            yield last + (pos,)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   264
        if typ == b'end':
36245
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   265
            return
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   266
        else:
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   267
            last = (typ, pos)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   268
    raise error.ProgrammingError(b'unterminated scanning of template')
36245
c6ce479f7a28 templater: add function to help substituting patterns in template string
Yuya Nishihara <yuya@tcha.org>
parents: 36244
diff changeset
   269
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   270
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   271
def _scantemplate(tmpl, start, stop, quote=b'', raw=False):
36244
18bdfad8506e templater: extract function scanning template string
Yuya Nishihara <yuya@tcha.org>
parents: 35744
diff changeset
   272
    """Parse template string into chunks of strings and template expressions"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   273
    sepchars = b'{' + quote
36509
638c012a87ef templater: add option to parse template string just like raw string literal
Yuya Nishihara <yuya@tcha.org>
parents: 36500
diff changeset
   274
    unescape = [parser.unescapestr, pycompat.identity][raw]
25781
82c918509ef5 templater: extract function that parses template string
Yuya Nishihara <yuya@tcha.org>
parents: 25780
diff changeset
   275
    pos = start
25654
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25599
diff changeset
   276
    p = parser.parser(elements)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   277
    try:
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   278
        while pos < stop:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   279
            n = min(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   280
                (tmpl.find(c, pos, stop) for c in pycompat.bytestr(sepchars)),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   281
                key=lambda n: (n < 0, n),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   282
            )
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   283
            if n < 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   284
                yield (b'string', unescape(tmpl[pos:stop]), pos)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   285
                pos = stop
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   286
                break
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   287
            c = tmpl[n : n + 1]
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   288
            bs = 0  # count leading backslashes
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   289
            if not raw:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   290
                bs = (n - pos) - len(tmpl[pos:n].rstrip(b'\\'))
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   291
            if bs % 2 == 1:
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   292
                # escaped (e.g. '\{', '\\\{', but not '\\{')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   293
                yield (b'string', unescape(tmpl[pos : n - 1]) + c, pos)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   294
                pos = n + 1
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   295
                continue
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   296
            if n > pos:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   297
                yield (b'string', unescape(tmpl[pos:n]), pos)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   298
            if c == quote:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   299
                yield (b'end', None, n + 1)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   300
                return
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   301
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   302
            parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, b'}'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   303
            if not tmpl.startswith(b'}', pos):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   304
                raise error.ParseError(_(b"invalid token"), pos)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   305
            yield (b'template', parseres, n)
36691
1b179d151578 templater: fix position of terminator character in error message
Yuya Nishihara <yuya@tcha.org>
parents: 36670
diff changeset
   306
            pos += 1
25783
1f6878c87c25 templater: introduce one-pass parsing of nested template strings
Yuya Nishihara <yuya@tcha.org>
parents: 25782
diff changeset
   307
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   308
        if quote:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   309
            raise error.ParseError(_(b"unterminated string"), start)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   310
    except error.ParseError as inst:
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   311
        _addparseerrorhint(inst, tmpl)
36669
80d7fb6c2dec templater: add hint to template parse errors to help locate issues
Ryan McElroy <rmcelroy@fb.com>
parents: 36648
diff changeset
   312
        raise
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   313
    yield (b'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
   314
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   315
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   316
def _addparseerrorhint(inst, tmpl):
45776
0fc8b066928a errors: name arguments to ParseError constructor
Martin von Zweigbergk <martinvonz@google.com>
parents: 45451
diff changeset
   317
    if inst.location is None:
0fc8b066928a errors: name arguments to ParseError constructor
Martin von Zweigbergk <martinvonz@google.com>
parents: 45451
diff changeset
   318
        return
0fc8b066928a errors: name arguments to ParseError constructor
Martin von Zweigbergk <martinvonz@google.com>
parents: 45451
diff changeset
   319
    loc = inst.location
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   320
    # Offset the caret location by the number of newlines before the
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   321
    # location of the error, since we will replace one-char newlines
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   322
    # with the two-char literal r'\n'.
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   323
    offset = tmpl[:loc].count(b'\n')
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   324
    tmpl = tmpl.replace(b'\n', br'\n')
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   325
    # We want the caret to point to the place in the template that
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   326
    # failed to parse, but in a hint we get a open paren at the
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   327
    # start. Therefore, we print "loc + 1" spaces (instead of "loc")
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   328
    # to line up the caret with the location of the error.
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   329
    inst.hint = tmpl + b'\n' + b' ' * (loc + 1 + offset) + b'^ ' + _(b'here')
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   330
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   331
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   332
def _unnesttemplatelist(tree):
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   333
    """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
   334
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   335
    >>> def f(tree):
34137
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
   336
    ...     print(pycompat.sysstr(prettyformat(_unnesttemplatelist(tree))))
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   337
    >>> f((b'template', []))
34073
7bbc4e113e5f parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents: 34071
diff changeset
   338
    (string '')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   339
    >>> f((b'template', [(b'string', b'foo')]))
34073
7bbc4e113e5f parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents: 34071
diff changeset
   340
    (string 'foo')
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   341
    >>> f((b'template', [(b'string', b'foo'), (b'symbol', b'rev')]))
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   342
    (template
34073
7bbc4e113e5f parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents: 34071
diff changeset
   343
      (string 'foo')
7bbc4e113e5f parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents: 34071
diff changeset
   344
      (symbol 'rev'))
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   345
    >>> f((b'template', [(b'symbol', b'rev')]))  # template(rev) -> str
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   346
    (template
34073
7bbc4e113e5f parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents: 34071
diff changeset
   347
      (symbol 'rev'))
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   348
    >>> f((b'template', [(b'template', [(b'string', b'foo')])]))
34073
7bbc4e113e5f parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents: 34071
diff changeset
   349
    (string 'foo')
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   350
    """
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   351
    if not isinstance(tree, tuple):
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   352
        return tree
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   353
    op = tree[0]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   354
    if op != b'template':
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   355
        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
   356
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   357
    assert len(tree) == 2
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   358
    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
   359
    if not xs:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   360
        return (b'string', b'')  # empty template ""
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   361
    elif len(xs) == 1 and xs[0][0] == b'string':
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   362
        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
   363
    else:
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   364
        return (op,) + xs
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   365
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   366
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   367
def parse(tmpl):
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   368
    """Parse template string into tree"""
25781
82c918509ef5 templater: extract function that parses template string
Yuya Nishihara <yuya@tcha.org>
parents: 25780
diff changeset
   369
    parsed, pos = _parsetemplate(tmpl, 0, len(tmpl))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   370
    assert pos == len(tmpl), b'unquoted template should be consumed'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   371
    return _unnesttemplatelist((b'template', parsed))
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   372
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   373
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   374
def parseexpr(expr):
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   375
    """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
   376
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   377
    >>> parseexpr(b'"foo"')
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   378
    ('string', 'foo')
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   379
    >>> parseexpr(b'foo(bar)')
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   380
    ('func', ('symbol', 'foo'), ('symbol', 'bar'))
45886
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   381
    >>> from . import error
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   382
    >>> from . import pycompat
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   383
    >>> try:
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   384
    ...   parseexpr(b'foo(')
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   385
    ... except error.ParseError as e:
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   386
    ...   pycompat.sysstr(e.message)
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   387
    ...   e.location
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   388
    'not a prefix: end'
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   389
    4
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   390
    >>> try:
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   391
    ...   parseexpr(b'"foo" "bar"')
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   392
    ... except error.ParseError as e:
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   393
    ...   pycompat.sysstr(e.message)
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   394
    ...   e.location
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   395
    'invalid token'
18489e26d9a0 tests: make doctests not depend on str(ParseError()) format
Martin von Zweigbergk <martinvonz@google.com>
parents: 45776
diff changeset
   396
    7
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   397
    """
43098
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   398
    try:
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   399
        return _parseexpr(expr)
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   400
    except error.ParseError as inst:
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   401
        _addparseerrorhint(inst, expr)
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   402
        raise
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   403
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   404
9691fc764bdc templater: add public parseexpr() function to parse "-Tjson(...)"
Yuya Nishihara <yuya@tcha.org>
parents: 43089
diff changeset
   405
def _parseexpr(expr):
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   406
    p = parser.parser(elements)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   407
    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
   408
    if pos != len(expr):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   409
        raise error.ParseError(_(b'invalid token'), pos)
28911
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   410
    return _unnesttemplatelist(tree)
35da19348143 templater: add function to parse whole string as template expression
Yuya Nishihara <yuya@tcha.org>
parents: 28837
diff changeset
   411
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   412
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   413
def prettyformat(tree):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   414
    return parser.prettyformat(tree, (b'integer', b'string', b'symbol'))
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   415
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   416
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   417
def compileexp(exp, context, curmethods):
28956
eea98190ed73 templater: inline compiletemplate() function into engine
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   418
    """Compile parsed template tree to (func, data) pair"""
35744
8685192a8733 templater: fix crash by empty group expression
Yuya Nishihara <yuya@tcha.org>
parents: 35680
diff changeset
   419
    if not exp:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   420
        raise error.ParseError(_(b"missing argument"))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   421
    t = exp[0]
40618
ff8b2886c492 templater: check invalid use of list expression properly (issue5920)
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   422
    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
   423
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   424
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   425
# template evaluation
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   426
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   427
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   428
def getsymbol(exp):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   429
    if exp[0] == b'symbol':
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   430
        return exp[1]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   431
    raise error.ParseError(_(b"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
   432
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   433
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   434
def getlist(x):
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   435
    if not x:
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   436
        return []
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   437
    if x[0] == b'list':
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   438
        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
   439
    return [x]
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   440
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   441
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   442
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
   443
    """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
   444
    returns (func, data) pair"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   445
    if exp[0] in (b'template', b'string'):
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   446
        return compileexp(exp, context, methods)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   447
    if exp[0] == b'symbol':
25599
695b93a79d17 templater: comment that gettemplate() has different name resolution order
Yuya Nishihara <yuya@tcha.org>
parents: 25598
diff changeset
   448
        # 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
   449
        # 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
   450
        # 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
   451
        return context._load(exp[1])
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   452
    raise error.ParseError(_(b"expected template specifier"))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   453
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   454
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   455
def _runrecursivesymbol(context, mapping, key):
46120
c000eff2c635 errors: raise InputError on recursive template definition
Martin von Zweigbergk <martinvonz@google.com>
parents: 45942
diff changeset
   456
    raise error.InputError(_(b"recursive reference '%s' in template") % key)
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   457
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   458
25596
c1975809a6b5 templater: take any string literals as template, but not for rawstring (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 25595
diff changeset
   459
def buildtemplate(exp, context):
28547
73d01cba5810 templater: expand list of parsed templates to template node
Yuya Nishihara <yuya@tcha.org>
parents: 28546
diff changeset
   460
    ctmpl = [compileexp(e, context, methods) for e in exp[1:]]
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   461
    return (templateutil.runtemplate, ctmpl)
25595
a7dd6692e5cb templater: move runtemplate function out of buildmap/runmap pair
Yuya Nishihara <yuya@tcha.org>
parents: 25580
diff changeset
   462
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   463
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   464
def buildfilter(exp, context):
26104
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   465
    n = getsymbol(exp[2])
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   466
    if n in context._filters:
0f1bc7faa50d templater: inline getfilter() to buildfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 25985
diff changeset
   467
        filt = context._filters[n]
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   468
        arg = compileexp(exp[1], context, methods)
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   469
        return (templateutil.runfilter, (arg, filt))
36912
543afbdc8e59 templater: move function table to the "context" object
Yuya Nishihara <yuya@tcha.org>
parents: 36712
diff changeset
   470
    if n in context._funcs:
543afbdc8e59 templater: move function table to the "context" object
Yuya Nishihara <yuya@tcha.org>
parents: 36712
diff changeset
   471
        f = context._funcs[n]
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   472
        args = _buildfuncargs(exp[1], context, methods, n, f._argspec)
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   473
        return (f, args)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   474
    raise error.ParseError(_(b"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
   475
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   476
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   477
def buildmap(exp, context):
34325
86d050abd5c1 templater: do not destructure operands in buildmap()
Yuya Nishihara <yuya@tcha.org>
parents: 34324
diff changeset
   478
    darg = compileexp(exp[1], context, methods)
86d050abd5c1 templater: do not destructure operands in buildmap()
Yuya Nishihara <yuya@tcha.org>
parents: 34324
diff changeset
   479
    targ = gettemplate(exp[2], context)
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   480
    return (templateutil.runmap, (darg, targ))
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   481
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   482
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   483
def buildmember(exp, context):
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   484
    darg = compileexp(exp[1], context, methods)
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   485
    memb = getsymbol(exp[2])
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   486
    return (templateutil.runmember, (darg, memb))
34535
78590585c0db templater: add dot operator to easily access a sub item
Yuya Nishihara <yuya@tcha.org>
parents: 34534
diff changeset
   487
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   488
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   489
def buildnegate(exp, context):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   490
    arg = compileexp(exp[1], context, exprmethods)
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   491
    return (templateutil.runnegate, arg)
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   492
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   493
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   494
def buildarithmetic(exp, context, func):
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   495
    left = compileexp(exp[1], context, exprmethods)
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   496
    right = compileexp(exp[2], context, exprmethods)
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   497
    return (templateutil.runarithmetic, (func, left, right))
30115
8e42dfde93d1 templater: provide arithmetic operations on integers
Simon Farnsworth <simonfar@fb.com>
parents: 30083
diff changeset
   498
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   499
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   500
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
   501
    n = getsymbol(exp[1])
36912
543afbdc8e59 templater: move function table to the "context" object
Yuya Nishihara <yuya@tcha.org>
parents: 36712
diff changeset
   502
    if n in context._funcs:
543afbdc8e59 templater: move function table to the "context" object
Yuya Nishihara <yuya@tcha.org>
parents: 36712
diff changeset
   503
        f = context._funcs[n]
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   504
        args = _buildfuncargs(exp[2], context, exprmethods, n, f._argspec)
14925
ab545a15d807 templater: use a global funcs table
Matt Mackall <mpm@selenic.com>
parents: 14168
diff changeset
   505
        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
   506
    if n in context._filters:
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   507
        args = _buildfuncargs(exp[2], context, exprmethods, n, argspec=None)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   508
        if len(args) != 1:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   509
            raise error.ParseError(_(b"filter %s expects one argument") % n)
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   510
        f = context._filters[n]
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   511
        return (templateutil.runfilter, (args[0], f))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   512
    raise error.ParseError(_(b"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
   513
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   514
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   515
def _buildfuncargs(exp, context, curmethods, funcname, argspec):
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   516
    """Compile parsed tree of function arguments into list or dict of
31921
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   517
    (func, data) pairs
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   518
36987
4b744c7b35ce templater: fix invalid reference of runsymbol in doctest
Yuya Nishihara <yuya@tcha.org>
parents: 36983
diff changeset
   519
    >>> context = engine(lambda t: (templateutil.runsymbol, t))
31921
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   520
    >>> def fargs(expr, argspec):
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   521
    ...     x = _parseexpr(expr)
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   522
    ...     n = getsymbol(x[1])
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   523
    ...     return _buildfuncargs(x[2], context, exprmethods, n, argspec)
34139
be00af4a1ac5 doctest: coerce dict.keys() to list
Yuya Nishihara <yuya@tcha.org>
parents: 34137
diff changeset
   524
    >>> list(fargs(b'a(l=1, k=2)', b'k l m').keys())
31922
0f41f1e3c75c parser: preserve order of keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31921
diff changeset
   525
    ['l', 'k']
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 34073
diff changeset
   526
    >>> args = fargs(b'a(opts=1, k=2)', b'**opts')
34139
be00af4a1ac5 doctest: coerce dict.keys() to list
Yuya Nishihara <yuya@tcha.org>
parents: 34137
diff changeset
   527
    >>> list(args.keys()), list(args[b'opts'].keys())
31922
0f41f1e3c75c parser: preserve order of keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31921
diff changeset
   528
    (['opts'], ['opts', 'k'])
31921
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   529
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   530
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   531
    def compiledict(xs):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   532
        return util.sortdict(
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   533
            (k, compileexp(x, context, curmethods)) for k, x in xs.items()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   534
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   535
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   536
    def compilelist(xs):
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   537
        return [compileexp(x, context, curmethods) for x in xs]
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   538
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   539
    if not argspec:
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   540
        # filter or function with no argspec: return list of positional args
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   541
        return compilelist(getlist(exp))
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   542
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   543
    # function with argspec: return dict of named args
31921
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   544
    _poskeys, varkey, _keys, optkey = argspec = parser.splitargspec(argspec)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   545
    treeargs = parser.buildargsdict(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   546
        getlist(exp),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   547
        funcname,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   548
        argspec,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   549
        keyvaluenode=b'keyvalue',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   550
        keynode=b'symbol',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   551
    )
31922
0f41f1e3c75c parser: preserve order of keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31921
diff changeset
   552
    compargs = util.sortdict()
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   553
    if varkey:
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   554
        compargs[varkey] = compilelist(treeargs.pop(varkey))
31921
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   555
    if optkey:
2156934b7917 parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents: 31887
diff changeset
   556
        compargs[optkey] = compiledict(treeargs.pop(optkey))
31886
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   557
    compargs.update(compiledict(treeargs))
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   558
    return compargs
bdda942f4b9c templater: add support for keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 31885
diff changeset
   559
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   560
31885
d18b624c1c06 templater: add parsing rule for key-value pair
Yuya Nishihara <yuya@tcha.org>
parents: 31884
diff changeset
   561
def buildkeyvaluepair(exp, content):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   562
    raise error.ParseError(_(b"can't use a key-value pair in this context"))
31885
d18b624c1c06 templater: add parsing rule for key-value pair
Yuya Nishihara <yuya@tcha.org>
parents: 31884
diff changeset
   563
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   564
40618
ff8b2886c492 templater: check invalid use of list expression properly (issue5920)
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   565
def buildlist(exp, context):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   566
    raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   567
        _(b"can't use a list in this context"),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   568
        hint=_(b'check place of comma and parens'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   569
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   570
40618
ff8b2886c492 templater: check invalid use of list expression properly (issue5920)
Yuya Nishihara <yuya@tcha.org>
parents: 40475
diff changeset
   571
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   572
# 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
   573
exprmethods = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   574
    b"integer": lambda e, c: (templateutil.runinteger, e[1]),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   575
    b"string": lambda e, c: (templateutil.runstring, e[1]),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   576
    b"symbol": lambda e, c: (templateutil.runsymbol, e[1]),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   577
    b"template": buildtemplate,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   578
    b"group": lambda e, c: compileexp(e[1], c, exprmethods),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   579
    b".": buildmember,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   580
    b"|": buildfilter,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   581
    b"%": buildmap,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   582
    b"func": buildfunc,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   583
    b"keyvalue": buildkeyvaluepair,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   584
    b"list": buildlist,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   585
    b"+": lambda e, c: buildarithmetic(e, c, lambda a, b: a + b),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   586
    b"-": lambda e, c: buildarithmetic(e, c, lambda a, b: a - b),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   587
    b"negate": buildnegate,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   588
    b"*": lambda e, c: buildarithmetic(e, c, lambda a, b: a * b),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   589
    b"/": lambda e, c: buildarithmetic(e, c, lambda a, b: a // b),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   590
}
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   591
25001
9668c1a433b3 templater: switch methods table on compileexp() of func args and inner expr
Yuya Nishihara <yuya@tcha.org>
parents: 24988
diff changeset
   592
# 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
   593
methods = exprmethods.copy()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   594
methods[b"integer"] = exprmethods[b"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
   595
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   596
28912
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   597
class _aliasrules(parser.basealiasrules):
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   598
    """Parsing and expansion rule set of template aliases"""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   599
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   600
    _section = _(b'template alias')
28912
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   601
    _parse = staticmethod(_parseexpr)
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   602
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   603
    @staticmethod
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   604
    def _trygetfunc(tree):
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   605
        """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
   606
        None"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   607
        if tree[0] == b'func' and tree[1][0] == b'symbol':
28912
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   608
            return tree[1][1], getlist(tree[2])
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   609
        if tree[0] == b'|' and tree[2][0] == b'symbol':
28912
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   610
            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
   611
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   612
28912
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   613
def expandaliases(tree, aliases):
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   614
    """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
   615
    aliasmap = _aliasrules.buildmap(aliases)
867d6ba2353d templater: add parsing and expansion rules to process "templatealias" section
Yuya Nishihara <yuya@tcha.org>
parents: 28911
diff changeset
   616
    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
   617
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   618
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   619
# template engine
1901
c64bef3d7043 use safer string parser for template engine.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1900
diff changeset
   620
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   621
24988
e8ff0b09acac templater: rename parsestring() to unquotestring() (API)
Yuya Nishihara <yuya@tcha.org>
parents: 24987
diff changeset
   622
def unquotestring(s):
28630
bf35644b9f3a templater: relax unquotestring() to fall back to bare string
Yuya Nishihara <yuya@tcha.org>
parents: 28628
diff changeset
   623
    '''unwrap quotes if any; otherwise returns unmodified string'''
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   624
    if len(s) < 2 or s[0] not in b"'\"" 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
   625
        return s
25696
c1cac25ad1a6 templater: remove workaround for escaped quoted string in quoted template
Yuya Nishihara <yuya@tcha.org>
parents: 25695
diff changeset
   626
    return s[1:-1]
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   627
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   628
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   629
class resourcemapper:  # pytype: disable=ignored-metaclass
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   630
    """Mapper of internal template resources"""
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   631
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   632
    __metaclass__ = abc.ABCMeta
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   633
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   634
    @abc.abstractmethod
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   635
    def availablekeys(self, mapping):
37075
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   636
        """Return a set of available resource keys based on the given mapping"""
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   637
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   638
    @abc.abstractmethod
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   639
    def knownkeys(self):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   640
        """Return a set of supported resource keys"""
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   641
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   642
    @abc.abstractmethod
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   643
    def lookup(self, mapping, key):
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   644
        """Return a resource for the key if available; otherwise None"""
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   645
37102
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   646
    @abc.abstractmethod
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   647
    def populatemap(self, context, origmapping, newmapping):
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   648
        """Return a dict of additional mapping items which should be paired
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   649
        with the given new mapping"""
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   650
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   651
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   652
class nullresourcemapper(resourcemapper):
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   653
    def availablekeys(self, mapping):
37075
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   654
        return set()
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   655
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   656
    def knownkeys(self):
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   657
        return set()
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   658
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   659
    def lookup(self, mapping, key):
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   660
        return None
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   661
37102
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   662
    def populatemap(self, context, origmapping, newmapping):
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   663
        return {}
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   664
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   665
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   666
class engine:
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   667
    """template expansion engine.
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   668
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   669
    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
   670
    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
   671
    is treated as name of template file.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   672
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   673
    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
   674
    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
   675
    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
   676
    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
   677
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   678
    expansion also allows formatting and filtering.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   679
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   680
    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
   681
    {key%format}.
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   682
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   683
    filter uses function to transform value. syntax is
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   684
    {key|filter1|filter2|...}."""
1909
37b9f80a5fbb add doc comments to template code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1906
diff changeset
   685
38354
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   686
    def __init__(self, loader, filters=None, defaults=None, resources=None):
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
   687
        self._loader = loader
26330
ec4f3755d997 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26234
diff changeset
   688
        if filters is None:
ec4f3755d997 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26234
diff changeset
   689
            filters = {}
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
   690
        self._filters = filters
36922
521f6c7e1756 templater: split template functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36921
diff changeset
   691
        self._funcs = templatefuncs.funcs  # make this a parameter if needed
26331
2c6a741bf05e templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26330
diff changeset
   692
        if defaults is None:
2c6a741bf05e templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26330
diff changeset
   693
            defaults = {}
35468
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35467
diff changeset
   694
        if resources is None:
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   695
            resources = nullresourcemapper()
10848
01346cea5485 templater: privatize class variables
Matt Mackall <mpm@selenic.com>
parents: 10847
diff changeset
   696
        self._defaults = defaults
35468
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35467
diff changeset
   697
        self._resources = resources
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   698
        self._cache = {}  # key: (func, data)
37398
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   699
        self._tmplcache = {}  # literal template: (func, data)
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   700
37074
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   701
    def overlaymap(self, origmapping, newmapping):
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   702
        """Create combined mapping from the original mapping and partial
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   703
        mapping to override the original"""
37075
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   704
        # do not copy symbols which overrides the defaults depending on
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   705
        # new resources, so the defaults will be re-evaluated (issue5612)
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   706
        knownres = self._resources.knownkeys()
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   707
        newres = self._resources.availablekeys(newmapping)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   708
        mapping = {
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   709
            k: v
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   710
            for k, v in origmapping.items()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   711
            if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   712
                k in knownres  # not a symbol per self.symbol()
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   713
                or newres.isdisjoint(self._defaultrequires(k))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   714
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   715
        }
37074
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   716
        mapping.update(newmapping)
37102
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   717
        mapping.update(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   718
            self._resources.populatemap(self, origmapping, newmapping)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   719
        )
37074
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   720
        return mapping
2891079fb0c0 templater: factor out function to create mapping dict for nested evaluation
Yuya Nishihara <yuya@tcha.org>
parents: 37073
diff changeset
   721
37075
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   722
    def _defaultrequires(self, key):
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   723
        """Resource keys required by the specified default symbol function"""
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   724
        v = self._defaults.get(key)
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   725
        if v is None or not callable(v):
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   726
            return ()
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   727
        return getattr(v, '_requires', ())
46859b437697 templater: drop symbols which should be overridden by new 'ctx' (issue5612)
Yuya Nishihara <yuya@tcha.org>
parents: 37074
diff changeset
   728
35467
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   729
    def symbol(self, mapping, key):
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   730
        """Resolve symbol to value or function; None if nothing found"""
35470
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   731
        v = None
37073
44757e6dad93 templater: introduce resourcemapper class
Yuya Nishihara <yuya@tcha.org>
parents: 37070
diff changeset
   732
        if key not in self._resources.knownkeys():
35470
a33be093ec62 templater: look up symbols/resources as if they were separated (issue5699)
Yuya Nishihara <yuya@tcha.org>
parents: 35468
diff changeset
   733
            v = mapping.get(key)
35467
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   734
        if v is None:
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   735
            v = self._defaults.get(key)
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   736
        return v
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   737
37501
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   738
    def availableresourcekeys(self, mapping):
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   739
        """Return a set of available resource keys based on the given mapping"""
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   740
        return self._resources.availablekeys(mapping)
37501
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   741
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   742
    def knownresourcekeys(self):
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   743
        """Return a set of supported resource keys"""
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   744
        return self._resources.knownkeys()
0f4de9c27973 templater: add public interface returning a set of resource keys
Yuya Nishihara <yuya@tcha.org>
parents: 37499
diff changeset
   745
35467
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   746
    def resource(self, mapping, key):
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   747
        """Return internal data (e.g. cache) used for keyword/function
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   748
        evaluation"""
39582
28f974d83c0a templater: remove unused context argument from most resourcemapper functions
Yuya Nishihara <yuya@tcha.org>
parents: 38440
diff changeset
   749
        v = self._resources.lookup(mapping, key)
35468
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35467
diff changeset
   750
        if v is None:
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   751
            raise templateutil.ResourceUnavailable(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   752
                _(b'template resource not available: %s') % key
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   753
            )
35468
32c278eb876f templater: keep default resources per template engine (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35467
diff changeset
   754
        return v
35467
d6cfa722b044 templater: look up mapping table through template engine
Yuya Nishihara <yuya@tcha.org>
parents: 35414
diff changeset
   755
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   756
    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
   757
        '''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
   758
        if t not in self._cache:
38354
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   759
            x = self._loader(t)
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   760
            # 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
   761
            self._cache[t] = (_runrecursivesymbol, t)
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   762
            try:
28956
eea98190ed73 templater: inline compiletemplate() function into engine
Yuya Nishihara <yuya@tcha.org>
parents: 28954
diff changeset
   763
                self._cache[t] = compileexp(x, self, methods)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   764
            except:  # re-raises
27940
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   765
                del self._cache[t]
cfe7da66f555 templater: abort if infinite recursion detected while compiling
Yuya Nishihara <yuya@tcha.org>
parents: 27939
diff changeset
   766
                raise
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 13175
diff changeset
   767
        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
   768
37398
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   769
    def _parse(self, tmpl):
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   770
        """Parse and cache a literal template"""
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   771
        if tmpl not in self._tmplcache:
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   772
            x = parse(tmpl)
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   773
            self._tmplcache[tmpl] = compileexp(x, self, methods)
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   774
        return self._tmplcache[tmpl]
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   775
37067
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   776
    def preload(self, t):
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   777
        """Load, parse, and cache the specified template if available"""
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   778
        try:
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   779
            self._load(t)
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   780
            return True
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   781
        except templateutil.TemplateNotFound:
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   782
            return False
04aafcec00b9 templater: add context.preload(t) to test if the specified template exists
Yuya Nishihara <yuya@tcha.org>
parents: 37019
diff changeset
   783
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   784
    def process(self, t, mapping):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   785
        """Perform expansion. t is name of map element to expand.
10853
b6f6d9fd53d6 templater: drop raw method
Matt Mackall <mpm@selenic.com>
parents: 10852
diff changeset
   786
        mapping contains added elements for use during expansion. Is a
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   787
        generator."""
28545
1d461ee26e1b templater: lift parsed and compiled templates to generic data types
Yuya Nishihara <yuya@tcha.org>
parents: 28462
diff changeset
   788
        func, data = self._load(t)
37398
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   789
        return self._expand(func, data, mapping)
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   790
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   791
    def expand(self, tmpl, mapping):
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   792
        """Perform expansion over a literal template
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   793
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   794
        No user aliases will be expanded since this is supposed to be called
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   795
        with an internal template string.
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   796
        """
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   797
        func, data = self._parse(tmpl)
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   798
        return self._expand(func, data, mapping)
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   799
3235afdfcf1c templater: add function that expands internal literal templates
Yuya Nishihara <yuya@tcha.org>
parents: 37272
diff changeset
   800
    def _expand(self, func, data, mapping):
37102
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   801
        # populate additional items only if they don't exist in the given
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   802
        # mapping. this is slightly different from overlaymap() because the
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   803
        # initial 'revcache' may contain pre-computed items.
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   804
        extramapping = self._resources.populatemap(self, {}, mapping)
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   805
        if extramapping:
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   806
            extramapping.update(mapping)
638a241202a3 templater: add hook point to populate additional mapping items
Yuya Nishihara <yuya@tcha.org>
parents: 37084
diff changeset
   807
            mapping = extramapping
37272
7d3bc1d4e871 templater: pass (context, mapping) down to unwraphybrid()
Yuya Nishihara <yuya@tcha.org>
parents: 37159
diff changeset
   808
        return templateutil.flatten(self, mapping, func(self, mapping, data))
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   809
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   810
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
   811
def stylelist():
45199
91aa9bba3dc9 templater: make templatepaths() return a single path, or None
Martin von Zweigbergk <martinvonz@google.com>
parents: 45198
diff changeset
   812
    path = templatedir()
91aa9bba3dc9 templater: make templatepaths() return a single path, or None
Martin von Zweigbergk <martinvonz@google.com>
parents: 45198
diff changeset
   813
    if not path:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   814
        return _(b'no templates found, try `hg debuginstall` for more info')
45199
91aa9bba3dc9 templater: make templatepaths() return a single path, or None
Martin von Zweigbergk <martinvonz@google.com>
parents: 45198
diff changeset
   815
    dirlist = os.listdir(path)
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
   816
    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
   817
    for file in dirlist:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   818
        split = file.split(b".")
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   819
        if split[-1] in (b'orig', b'rej'):
28403
d2e154dddb6e templater: ignore orig/rej files
timeless <timeless@mozdev.org>
parents: 28384
diff changeset
   820
            continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   821
        if split[0] == b"map-cmdline":
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
   822
            stylelist.append(split[1])
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   823
    return b", ".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
   824
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   825
45308
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   826
def _open_mapfile(mapfile):
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   827
    if os.path.exists(mapfile):
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   828
        return util.posixfile(mapfile, b'rb')
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   829
    raise error.Abort(
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   830
        _(b"style '%s' not found") % mapfile,
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   831
        hint=_(b"available styles: %s") % stylelist(),
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   832
    )
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   833
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   834
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   835
def _readmapfile(fp, mapfile):
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   836
    """Load template elements from the given map file"""
47830
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   837
    if pycompat.iswindows:
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   838
        # quick hack to make sure we can process '/' in the code dealing with
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   839
        # ressource. Ideally we would make sure we use `/` instead of `ossep`
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   840
        # in the templater code, but that seems a bigger and less certain
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   841
        # change that we better left for the default branch.
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   842
        name_paths = mapfile.split(pycompat.ossep)
981cef5188c3 templater: swap `\` with `/` in more location
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47829
diff changeset
   843
        mapfile = b'/'.join(name_paths)
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   844
    base = os.path.dirname(mapfile)
45210
4ccd5ec565c2 templater: do search for include of unqualified builtin outside of config code
Martin von Zweigbergk <martinvonz@google.com>
parents: 45209
diff changeset
   845
    conf = config.config()
45209
8ec3062b7047 templater: switch to lower-level config.parse() in _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45200
diff changeset
   846
45257
668af67bfd18 config: remove now-unused `abs` argument from `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45213
diff changeset
   847
    def include(rel, remap, sections):
45312
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   848
        subresource = None
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   849
        if base:
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   850
            abs = os.path.normpath(os.path.join(base, rel))
45210
4ccd5ec565c2 templater: do search for include of unqualified builtin outside of config code
Martin von Zweigbergk <martinvonz@google.com>
parents: 45209
diff changeset
   851
            if os.path.isfile(abs):
45312
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   852
                subresource = util.posixfile(abs, b'rb')
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   853
        if not subresource:
45313
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   854
            if pycompat.ossep not in rel:
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   855
                abs = rel
47836
f3b1df44b716 template: handle missing resource in `_readmapfile`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47830
diff changeset
   856
                try:
f3b1df44b716 template: handle missing resource in `_readmapfile`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47830
diff changeset
   857
                    subresource = resourceutil.open_resource(
f3b1df44b716 template: handle missing resource in `_readmapfile`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47830
diff changeset
   858
                        b'mercurial.templates', rel
f3b1df44b716 template: handle missing resource in `_readmapfile`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47830
diff changeset
   859
                    )
47857
2b76255a4f74 template: FileNotFoundError is actually a built in exception
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47836
diff changeset
   860
                except FileNotFoundError:
47836
f3b1df44b716 template: handle missing resource in `_readmapfile`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47830
diff changeset
   861
                    subresource = None
45313
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   862
            else:
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   863
                dir = templatedir()
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   864
                if dir:
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   865
                    abs = os.path.normpath(os.path.join(dir, rel))
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   866
                    if os.path.isfile(abs):
fef64d7a4a84 templater: try to read %include in mapfiles from resources
Martin von Zweigbergk <martinvonz@google.com>
parents: 45312
diff changeset
   867
                        subresource = util.posixfile(abs, b'rb')
45312
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   868
        if subresource:
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   869
            data = subresource.read()
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   870
            conf.parse(
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   871
                abs,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   872
                data,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   873
                sections=sections,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   874
                remap=remap,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
   875
                include=include,
45312
d9a502a0a9ca templater: unroll loop over mapfile directories
Martin von Zweigbergk <martinvonz@google.com>
parents: 45311
diff changeset
   876
            )
45209
8ec3062b7047 templater: switch to lower-level config.parse() in _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45200
diff changeset
   877
45308
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   878
    data = fp.read()
45209
8ec3062b7047 templater: switch to lower-level config.parse() in _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45200
diff changeset
   879
    conf.parse(mapfile, data, remap={b'': b'templates'}, include=include)
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   880
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   881
    cache = {}
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   882
    tmap = {}
34715
f17a0e18c47e templater: load aliases from [templatealias] section in map file
Yuya Nishihara <yuya@tcha.org>
parents: 34714
diff changeset
   883
    aliases = []
34712
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   884
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   885
    val = conf.get(b'templates', b'__base__')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   886
    if val and val[0] not in b"'\"":
34712
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   887
        # treat as a pointer to a base class for this style
45261
28840ef52f71 templater: don't normalize path separators to '/' when interacting with OS
Martin von Zweigbergk <martinvonz@google.com>
parents: 45259
diff changeset
   888
        path = os.path.normpath(os.path.join(base, val))
34712
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   889
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   890
        # fallback check in template paths
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   891
        if not os.path.exists(path):
45213
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   892
            dir = templatedir()
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   893
            if dir is not None:
45261
28840ef52f71 templater: don't normalize path separators to '/' when interacting with OS
Martin von Zweigbergk <martinvonz@google.com>
parents: 45259
diff changeset
   894
                p2 = os.path.normpath(os.path.join(dir, val))
45213
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   895
                if os.path.isfile(p2):
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   896
                    path = p2
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   897
                else:
45261
28840ef52f71 templater: don't normalize path separators to '/' when interacting with OS
Martin von Zweigbergk <martinvonz@google.com>
parents: 45259
diff changeset
   898
                    p3 = os.path.normpath(os.path.join(p2, b"map"))
45213
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   899
                    if os.path.isfile(p3):
d5ccc059fbcd templater: handle None returned from templatedir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45210
diff changeset
   900
                        path = p3
34712
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   901
45308
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   902
        fp = _open_mapfile(path)
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
   903
        cache, tmap, aliases = _readmapfile(fp, path)
34712
56f085334611 templater: simplify merge of __base__ dicts by reading it first
Yuya Nishihara <yuya@tcha.org>
parents: 34693
diff changeset
   904
46424
5272542196cc config: use the right API to access template access
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46120
diff changeset
   905
    for key, val in conf.items(b'templates'):
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   906
        if not val:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   907
            raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   908
                _(b'missing value'), conf.source(b'templates', key)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   909
            )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   910
        if val[0] in b"'\"":
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   911
            if val[0] != val[-1]:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   912
                raise error.ParseError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   913
                    _(b'unmatched quotes'), conf.source(b'templates', key)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   914
                )
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   915
            cache[key] = unquotestring(val)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   916
        elif key != b'__base__':
38353
48289eafb37d templater: drop extension point of engine classes (API)
Yuya Nishihara <yuya@tcha.org>
parents: 38352
diff changeset
   917
            tmap[key] = os.path.join(base, val)
46424
5272542196cc config: use the right API to access template access
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46120
diff changeset
   918
    aliases.extend(conf.items(b'templatealias'))
34715
f17a0e18c47e templater: load aliases from [templatealias] section in map file
Yuya Nishihara <yuya@tcha.org>
parents: 34714
diff changeset
   919
    return cache, tmap, aliases
28953
7f6b8ec691e3 templater: extract function that loads template map file
Yuya Nishihara <yuya@tcha.org>
parents: 28952
diff changeset
   920
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   921
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   922
class loader:
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   923
    """Load template fragments optionally from a map file"""
35481
964510dcdc2a templater: rewrite docstring of templater.__init__()
Yuya Nishihara <yuya@tcha.org>
parents: 35470
diff changeset
   924
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   925
    def __init__(self, cache, aliases):
26334
0a5a774f5956 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26333
diff changeset
   926
        if cache is None:
0a5a774f5956 templater: remove a mutable default argument
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26333
diff changeset
   927
            cache = {}
1975
6e1a8ea5d717 Duplicate cache when creating templater.
Shun-ichi Goto <shunichi.goto@gmail.com>
parents: 1964
diff changeset
   928
        self.cache = cache.copy()
38351
de089e3eb328 templater: mark most attributes as private
Yuya Nishihara <yuya@tcha.org>
parents: 38285
diff changeset
   929
        self._map = {}
38354
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   930
        self._aliasmap = _aliasrules.buildmap(aliases)
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   931
1899
888d298ddb91 many small changes to templater.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1897
diff changeset
   932
    def __contains__(self, key):
38351
de089e3eb328 templater: mark most attributes as private
Yuya Nishihara <yuya@tcha.org>
parents: 38285
diff changeset
   933
        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
   934
8218
e61cb2813d2a templater: separate template management and actual string processing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8198
diff changeset
   935
    def load(self, t):
38354
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   936
        """Get parsed tree 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
   937
        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
   938
            try:
45322
c3376a724e32 templater: teach template loader to use open_template() function
Martin von Zweigbergk <martinvonz@google.com>
parents: 45321
diff changeset
   939
                mapfile, fp = open_template(self._map[t])
c3376a724e32 templater: teach template loader to use open_template() function
Martin von Zweigbergk <martinvonz@google.com>
parents: 45321
diff changeset
   940
                self.cache[t] = fp.read()
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25654
diff changeset
   941
            except KeyError as inst:
36913
da2977e674a3 templater: extract template evaluation utility to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36912
diff changeset
   942
                raise templateutil.TemplateNotFound(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   943
                    _(b'"%s" not in template map') % inst.args[0]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   944
                )
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25654
diff changeset
   945
            except IOError as inst:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   946
                reason = _(b'template file %s: %s') % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   947
                    self._map[t],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   948
                    stringutil.forcebytestr(inst.args[1]),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   949
                )
36500
43e108027b0d py3: move between bytes and unicode when re-raising IOError
Yuya Nishihara <yuya@tcha.org>
parents: 36445
diff changeset
   950
                raise IOError(inst.args[0], encoding.strfromlocal(reason))
38354
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   951
        return self._parse(self.cache[t])
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   952
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   953
    def _parse(self, tmpl):
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   954
        x = parse(tmpl)
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   955
        if self._aliasmap:
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   956
            x = _aliasrules.expand(self._aliasmap, x)
e637dc0b3b1f templater: parse template string to tree by templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38353
diff changeset
   957
        return x
1896
f8f818a04f5b move hgweb template code out to templater
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   958
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   959
    def _findsymbolsused(self, tree, syms):
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   960
        if not tree:
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   961
            return
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   962
        op = tree[0]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   963
        if op == b'symbol':
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   964
            s = tree[1]
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   965
            if s in syms[0]:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   966
                return  # avoid recursion: s -> cache[s] -> s
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   967
            syms[0].add(s)
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   968
            if s in self.cache or s in self._map:
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   969
                # s may be a reference for named template
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   970
                self._findsymbolsused(self.load(s), syms)
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   971
            return
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   972
        if op in {b'integer', b'string'}:
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   973
            return
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   974
        # '{arg|func}' == '{func(arg)}'
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   975
        if op == b'|':
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   976
            syms[1].add(getsymbol(tree[2]))
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   977
            self._findsymbolsused(tree[1], syms)
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   978
            return
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   979
        if op == b'func':
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   980
            syms[1].add(getsymbol(tree[1]))
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   981
            self._findsymbolsused(tree[2], syms)
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   982
            return
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   983
        for x in tree[1:]:
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   984
            self._findsymbolsused(x, syms)
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
   985
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   986
    def symbolsused(self, t):
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   987
        """Look up (keywords, filters/functions) referenced from the name
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   988
        template 't'
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   989
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   990
        This may load additional templates from the map file.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   991
        """
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   992
        syms = (set(), set())
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   993
        self._findsymbolsused(self.load(t), syms)
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   994
        return syms
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
   995
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   996
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   997
class templater:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   998
    def __init__(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
   999
        self,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1000
        filters=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1001
        defaults=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1002
        resources=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1003
        cache=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1004
        aliases=(),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1005
        minchunk=1024,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1006
        maxchunk=65536,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1007
    ):
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1008
        """Create template engine optionally with preloaded template fragments
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1009
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1010
        - ``filters``: a dict of functions to transform a value into another.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1011
        - ``defaults``: a dict of symbol values/functions; may be overridden
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1012
          by a ``mapping`` dict.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1013
        - ``resources``: a resourcemapper object to look up internal data
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1014
          (e.g. cache), inaccessible from user template.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1015
        - ``cache``: a dict of preloaded template fragments.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1016
        - ``aliases``: a list of alias (name, replacement) pairs.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1017
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1018
        self.cache may be updated later to register additional template
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1019
        fragments.
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1020
        """
38440
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1021
        allfilters = templatefilters.filters.copy()
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1022
        if filters:
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1023
            allfilters.update(filters)
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1024
        self._loader = loader(cache, aliases)
38440
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1025
        self._proc = engine(self._loader.load, allfilters, defaults, resources)
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1026
        self._minchunk, self._maxchunk = minchunk, maxchunk
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1027
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1028
    @classmethod
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1029
    def frommapfile(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1030
        cls,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1031
        mapfile,
45310
f3481e4fcc3a templater: pass opened file-like object to templatespec
Martin von Zweigbergk <martinvonz@google.com>
parents: 45309
diff changeset
  1032
        fp=None,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1033
        filters=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1034
        defaults=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1035
        resources=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1036
        cache=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1037
        minchunk=1024,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1038
        maxchunk=65536,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1039
    ):
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1040
        """Create templater from the specified map file"""
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1041
        t = cls(filters, defaults, resources, cache, [], minchunk, maxchunk)
45310
f3481e4fcc3a templater: pass opened file-like object to templatespec
Martin von Zweigbergk <martinvonz@google.com>
parents: 45309
diff changeset
  1042
        if not fp:
f3481e4fcc3a templater: pass opened file-like object to templatespec
Martin von Zweigbergk <martinvonz@google.com>
parents: 45309
diff changeset
  1043
            fp = _open_mapfile(mapfile)
45308
dc10bcd5c08d templater: start passing resource to read from into _readmapfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45307
diff changeset
  1044
        cache, tmap, aliases = _readmapfile(fp, mapfile)
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1045
        t._loader.cache.update(cache)
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1046
        t._loader._map = tmap
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1047
        t._loader._aliasmap = _aliasrules.buildmap(aliases)
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1048
        return t
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1049
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1050
    def __contains__(self, key):
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1051
        return key in self._loader
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1052
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1053
    @property
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1054
    def cache(self):
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1055
        return self._loader.cache
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1056
38440
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1057
    # for highlight extension to insert one-time 'colorize' filter
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1058
    @property
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1059
    def _filters(self):
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1060
        return self._proc._filters
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1061
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1062
    @property
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1063
    def defaults(self):
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1064
        return self._proc._defaults
3813c6b7337c templater: remove redundant member variables from templater class
Yuya Nishihara <yuya@tcha.org>
parents: 38439
diff changeset
  1065
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1066
    def load(self, t):
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1067
        """Get parsed tree for the given template name. Use a local cache."""
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1068
        return self._loader.load(t)
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1069
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1070
    def symbolsuseddefault(self):
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1071
        """Look up (keywords, filters/functions) referenced from the default
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1072
        unnamed template
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1073
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1074
        This may load additional templates from the map file.
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1075
        """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1076
        return self.symbolsused(b'')
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1077
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1078
    def symbolsused(self, t):
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1079
        """Look up (keywords, filters/functions) referenced from the name
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1080
        template 't'
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1081
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1082
        This may load additional templates from the map file.
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1083
        """
38438
f79237942dec templater: extract template loader to separate class
Yuya Nishihara <yuya@tcha.org>
parents: 38355
diff changeset
  1084
        return self._loader.symbolsused(t)
38355
d4fae9a0ab1f templater: add function to look up symbols used in template
Yuya Nishihara <yuya@tcha.org>
parents: 38354
diff changeset
  1085
36988
317382151ac3 templater: rename .render(mapping) to .renderdefault(mapping) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 36987
diff changeset
  1086
    def renderdefault(self, mapping):
32873
2ecce24dfcd3 templater: add simple interface for unnamed template (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32684
diff changeset
  1087
        """Render the default unnamed template and return result as string"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1088
        return self.render(b'', mapping)
36989
de117f579431 templater: factor out helper that renders named template as string
Yuya Nishihara <yuya@tcha.org>
parents: 36988
diff changeset
  1089
de117f579431 templater: factor out helper that renders named template as string
Yuya Nishihara <yuya@tcha.org>
parents: 36988
diff changeset
  1090
    def render(self, t, mapping):
de117f579431 templater: factor out helper that renders named template as string
Yuya Nishihara <yuya@tcha.org>
parents: 36988
diff changeset
  1091
        """Render the specified named template and return result as string"""
37159
b56b79185aad templater: do not use stringify() to concatenate flattened template output
Yuya Nishihara <yuya@tcha.org>
parents: 37157
diff changeset
  1092
        return b''.join(self.generate(t, mapping))
32873
2ecce24dfcd3 templater: add simple interface for unnamed template (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32684
diff changeset
  1093
37019
c97b936d8bb5 templater: use named function to expand template against mapping dict (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37014
diff changeset
  1094
    def generate(self, t, mapping):
c97b936d8bb5 templater: use named function to expand template against mapping dict (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37014
diff changeset
  1095
        """Return a generator that renders the specified named template and
c97b936d8bb5 templater: use named function to expand template against mapping dict (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37014
diff changeset
  1096
        yields chunks"""
38439
256581484c7f templater: resurrect cache of engine instance
Yuya Nishihara <yuya@tcha.org>
parents: 38438
diff changeset
  1097
        stream = self._proc.process(t, mapping)
38351
de089e3eb328 templater: mark most attributes as private
Yuya Nishihara <yuya@tcha.org>
parents: 38285
diff changeset
  1098
        if self._minchunk:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1099
            stream = util.increasingchunks(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1100
                stream, min=self._minchunk, max=self._maxchunk
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1101
            )
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7107
diff changeset
  1102
        return stream
7434
cf7741aa1e96 kill some trailing spaces
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7396
diff changeset
  1103
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1104
45199
91aa9bba3dc9 templater: make templatepaths() return a single path, or None
Martin von Zweigbergk <martinvonz@google.com>
parents: 45198
diff changeset
  1105
def templatedir():
91aa9bba3dc9 templater: make templatepaths() return a single path, or None
Martin von Zweigbergk <martinvonz@google.com>
parents: 45198
diff changeset
  1106
    '''return the directory used for template files, or None.'''
45198
e2ec36167151 templater: simplify templatepaths() to avoid iterating a singleton list
Martin von Zweigbergk <martinvonz@google.com>
parents: 44589
diff changeset
  1107
    path = os.path.normpath(os.path.join(resourceutil.datapath, b'templates'))
45199
91aa9bba3dc9 templater: make templatepaths() return a single path, or None
Martin von Zweigbergk <martinvonz@google.com>
parents: 45198
diff changeset
  1108
    return path if os.path.isdir(path) else None
2189
e3eba577a0ae move changeset_templater into templater module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2001
diff changeset
  1109
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40935
diff changeset
  1110
45316
1b983985edd9 hgweb: open mapfile using templater.open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45313
diff changeset
  1111
def open_template(name, templatepath=None):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
  1112
    """returns a file-like object for the given template, and its full path
45311
3b27ed8e324e templater: make open_template() read from resources if in frozen binary
Martin von Zweigbergk <martinvonz@google.com>
parents: 45310
diff changeset
  1113
3b27ed8e324e templater: make open_template() read from resources if in frozen binary
Martin von Zweigbergk <martinvonz@google.com>
parents: 45310
diff changeset
  1114
    If the name is a relative path and we're in a frozen binary, the template
3b27ed8e324e templater: make open_template() read from resources if in frozen binary
Martin von Zweigbergk <martinvonz@google.com>
parents: 45310
diff changeset
  1115
    will be read from the mercurial.templates package instead. The returned path
3b27ed8e324e templater: make open_template() read from resources if in frozen binary
Martin von Zweigbergk <martinvonz@google.com>
parents: 45310
diff changeset
  1116
    will then be the relative path.
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45886
diff changeset
  1117
    """
45321
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1118
    # Does the name point directly to a map file?
45322
c3376a724e32 templater: teach template loader to use open_template() function
Martin von Zweigbergk <martinvonz@google.com>
parents: 45321
diff changeset
  1119
    if os.path.isfile(name) or os.path.isabs(name):
45321
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1120
        return name, open(name, mode='rb')
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1121
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1122
    # Does the name point to a template in the provided templatepath, or
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1123
    # in mercurial/templates/ if no path was provided?
45316
1b983985edd9 hgweb: open mapfile using templater.open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45313
diff changeset
  1124
    if templatepath is None:
1b983985edd9 hgweb: open mapfile using templater.open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45313
diff changeset
  1125
        templatepath = templatedir()
45321
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1126
    if templatepath is not None:
45309
65a812ed9e9f templater: replace templatepath() with function that also opens the file
Martin von Zweigbergk <martinvonz@google.com>
parents: 45308
diff changeset
  1127
        f = os.path.join(templatepath, name)
45320
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1128
        return f, open(f, mode='rb')
45321
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1129
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1130
    # Otherwise try to read it using the resources API
47829
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1131
    if pycompat.iswindows:
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1132
        # quick hack to make sure we can process '/' in the code dealing with
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1133
        # ressource. Ideally we would make sure we use `/` instead of `ossep`
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1134
        # in the templater code, but that seems a bigger and less certain
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1135
        # change that we better left for the default branch.
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1136
        name_paths = name.split(pycompat.ossep)
7ab7f73a7f0a templater: swap `\` with `/` to allow the resource logic to kicks in
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
  1137
        name = b'/'.join(name_paths)
45451
e53a3d0ef416 templater: fix reading of templates in frozen binaries with py3 < 3.7
Martin von Zweigbergk <martinvonz@google.com>
parents: 45322
diff changeset
  1138
    name_parts = name.split(b'/')
e53a3d0ef416 templater: fix reading of templates in frozen binaries with py3 < 3.7
Martin von Zweigbergk <martinvonz@google.com>
parents: 45322
diff changeset
  1139
    package_name = b'.'.join([b'mercurial', b'templates'] + name_parts[:-1])
45321
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1140
    return (
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1141
        name,
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1142
        resourceutil.open_resource(package_name, name_parts[-1]),
735756ecda8c templater: restructure open_template() a little to prepare for relative paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 45320
diff changeset
  1143
    )
45320
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1144
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1145
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1146
def try_open_template(name, templatepath=None):
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1147
    try:
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1148
        return open_template(name, templatepath)
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1149
    except (EnvironmentError, ImportError):
4aa484efc926 templater: add exception-raising version of open_template()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45319
diff changeset
  1150
        return None, None