Mercurial > hg
comparison mercurial/templater.py @ 34330:89aec1834a86
templatekw: add new-style template expansion to {manifest}
The goal is to allow us to easily access to nested data. The dot operator
will be introduced later so we can write '{p1.files}' instead of
'{revset("p1()") % "{files}"}' for example.
In the example above, 'p1' needs to carry a mapping dict along with its
string representation. If it were a list or a dict, it could be wrapped
semi-transparently with the _hybrid class, but for non-list/dict types,
it would be difficult to proxy all necessary functions to underlying value
type because several core operations may conflict with the ones of the
underlying value:
- hash(value) should be different from hash(wrapped(value)), which means
dict[wrapped(value)] would be invalid
- 'value == wrapped(value)' would be false, breaks 'ifcontains'
- len(wrapped(value)) may be either len(value) or len(iter(wrapped(value)))
So the wrapper has no proxy functions and its scope designed to be minimal.
It's unwrapped at eval*() functions so we don't have to care for a wrapped
object unless it's really needed:
# most template functions just call evalfuncarg()
unwrapped_value = evalfuncarg(context, mapping, args[n])
# if wrapped value is needed, use evalrawexp()
maybe_wrapped_value = evalrawexp(context, mapping, args[n])
Another idea was to wrap every template variable with a tagging class, but
which seemed uneasy without a static type checker.
This patch updates {manifest} to a mappable as an example.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 24 Apr 2016 18:41:23 +0900 |
parents | 6367318327f0 |
children | 46f45b7efa30 |
comparison
equal
deleted
inserted
replaced
34329:6367318327f0 | 34330:89aec1834a86 |
---|---|
305 return func(context, mapping, data) | 305 return func(context, mapping, data) |
306 | 306 |
307 def evalfuncarg(context, mapping, arg): | 307 def evalfuncarg(context, mapping, arg): |
308 """Evaluate given argument as value type""" | 308 """Evaluate given argument as value type""" |
309 thing = evalrawexp(context, mapping, arg) | 309 thing = evalrawexp(context, mapping, arg) |
310 thing = templatekw.unwrapvalue(thing) | |
310 # evalrawexp() may return string, generator of strings or arbitrary object | 311 # evalrawexp() may return string, generator of strings or arbitrary object |
311 # such as date tuple, but filter does not want generator. | 312 # such as date tuple, but filter does not want generator. |
312 if isinstance(thing, types.GeneratorType): | 313 if isinstance(thing, types.GeneratorType): |
313 thing = stringify(thing) | 314 thing = stringify(thing) |
314 return thing | 315 return thing |
321 if thing is None: | 322 if thing is None: |
322 # not a template keyword, takes as a boolean literal | 323 # not a template keyword, takes as a boolean literal |
323 thing = util.parsebool(data) | 324 thing = util.parsebool(data) |
324 else: | 325 else: |
325 thing = func(context, mapping, data) | 326 thing = func(context, mapping, data) |
327 thing = templatekw.unwrapvalue(thing) | |
326 if isinstance(thing, bool): | 328 if isinstance(thing, bool): |
327 return thing | 329 return thing |
328 # other objects are evaluated as strings, which means 0 is True, but | 330 # other objects are evaluated as strings, which means 0 is True, but |
329 # empty dict/list should be False as they are expected to be '' | 331 # empty dict/list should be False as they are expected to be '' |
330 return bool(stringify(thing)) | 332 return bool(stringify(thing)) |
766 raise error.ParseError(_("join expects one or two arguments")) | 768 raise error.ParseError(_("join expects one or two arguments")) |
767 | 769 |
768 # TODO: perhaps this should be evalfuncarg(), but it can't because hgweb | 770 # TODO: perhaps this should be evalfuncarg(), but it can't because hgweb |
769 # abuses generator as a keyword that returns a list of dicts. | 771 # abuses generator as a keyword that returns a list of dicts. |
770 joinset = evalrawexp(context, mapping, args[0]) | 772 joinset = evalrawexp(context, mapping, args[0]) |
773 joinset = templatekw.unwrapvalue(joinset) | |
771 joinfmt = getattr(joinset, 'joinfmt', pycompat.identity) | 774 joinfmt = getattr(joinset, 'joinfmt', pycompat.identity) |
772 joiner = " " | 775 joiner = " " |
773 if len(args) > 1: | 776 if len(args) > 1: |
774 joiner = evalstring(context, mapping, args[1]) | 777 joiner = evalstring(context, mapping, args[1]) |
775 | 778 |