# HG changeset patch # User Yuya Nishihara # Date 1544622302 -32400 # Node ID 4591c9791a829e927388ba92a64971ae9ab301ec # Parent d3e688b9ef2e4b33e94be1359a5c57befdff5833 templatefuncs: specialize "no match" value of search() to allow % operation If Python had Maybe or Option, the type of the search() result would be Option, which can be considered as a 0/1 container of a Mapping. So it makes sense that {search(r'no match pattern', x) % "whatever"} is mapped to an empty string. diff -r d3e688b9ef2e -r 4591c9791a82 mercurial/templatefuncs.py --- a/mercurial/templatefuncs.py Wed Dec 12 22:19:57 2018 +0900 +++ b/mercurial/templatefuncs.py Wed Dec 12 22:45:02 2018 +0900 @@ -609,7 +609,7 @@ match = patre.search(src) if not match: - return + return templateutil.mappingnone() lm = {b'0': match.group(0)} lm.update((b'%d' % i, v) for i, v in enumerate(match.groups(), 1)) diff -r d3e688b9ef2e -r 4591c9791a82 mercurial/templater.py --- a/mercurial/templater.py Wed Dec 12 22:19:57 2018 +0900 +++ b/mercurial/templater.py Wed Dec 12 22:45:02 2018 +0900 @@ -53,6 +53,10 @@ represents a single mapping (i.e. a dict), which may have default output format. +mappingnone + represents None of Optional[mappable], which will be mapped to an empty + string by % operation. + mappedgenerator a lazily-evaluated list of byte strings, which is e.g. a result of % operation. diff -r d3e688b9ef2e -r 4591c9791a82 mercurial/templateutil.py --- a/mercurial/templateutil.py Wed Dec 12 22:19:57 2018 +0900 +++ b/mercurial/templateutil.py Wed Dec 12 22:45:02 2018 +0900 @@ -495,6 +495,19 @@ def tovalue(self, context, mapping): return super(mappingdict, self).tovalue(context, mapping)[0] +class mappingnone(wrappedvalue): + """Wrapper for None, but supports map operation + + This represents None of Optional[mappable]. It's similar to + mapplinglist([]), but the underlying value is not [], but None. + """ + + def __init__(self): + super(mappingnone, self).__init__(None) + + def itermaps(self, context): + return iter([]) + class mappedgenerator(wrapped): """Wrapper for generator of strings which acts as a list diff -r d3e688b9ef2e -r 4591c9791a82 tests/test-template-functions.t --- a/tests/test-template-functions.t Wed Dec 12 22:19:57 2018 +0900 +++ b/tests/test-template-functions.t Wed Dec 12 22:45:02 2018 +0900 @@ -635,11 +635,9 @@ no group reference with no match - (TODO: we'll probably want to map it to an empty value) $ hg log -R a -r2 -T '{search(r"q", desc) % "match: {0}"}\n' - hg: parse error: None is not iterable of mappings - [255] + bad group names