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<Mapping>, 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.
--- 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))
--- 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.
--- 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
--- 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