[RFC] [PATCH] Support arguments in template expandos (v2)

Rocco Rutte pdmef at gmx.net
Fri May 8 11:03:18 CDT 2009


Hi,

* Rocco Rutte wrote:

[...]

Attached is a polished version that only supports arguments for filters.
It's also a bit simpler than the first one.

The only change in functionality is that as soon there's an argument,
the filter gets it and not when the filter is defined to accept
them. The idea behind this is to signal bad filter usage through an
exception.

Timings: unchanged crew tip:
  wall 2.835437 comb 4.733333 user 4.466667 sys 0.266667 (best of 4)

Changed, not using arguments
  wall 2.980397 comb 4.966667 user 4.700000 sys 0.266667 (best of 4)

Changed, using arguments
  wall 2.983410 comb 4.983333 user 4.700000 sys 0.283333 (best of 4)

Rocco

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -110,7 +110,8 @@ def perftemplating(ui, repo):
     ui.pushbuffer()
     timer(lambda: commands.log(ui, repo, rev=[], date='', user='',
                                template='{date|shortdate} [{rev}:{node|short}]'
-                               ' {author|person}: {desc|firstline}\n'))
+                               ' {author|person}: '
+                               '{desc|firstline|nonempty "(no description)"}\n'))
     ui.popbuffer()
 
 cmdtable = {
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -165,8 +165,8 @@ def stripdir(text):
     else:
         return dir
 
-def nonempty(str):
-  return str or "(none)"
+def nonempty(str, args=None):
+  return str or (args and args[0]) or "(none)"
 
 filters = {
     "addbreaks": nl2br,
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -39,10 +39,13 @@ class engine(object):
     {key%format}.
 
     filter uses function to transform value. syntax is
-    {key|filter1|filter2|...}.'''
+    {key|filter1 ["arg1" ["arg2" ...]]|filter2 ["arg1" ["arg2" ...]]|...}.'''
 
-    template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
-                             r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]")
+    template_re = re.compile(r"(?:(?:#(?=[\w\s\"\|%()]+#))|(?:{(?=[\w\s\"\|%()]+})))"
+                             r"(\w+)(?:(?:%(\w+(?:\s\"[^\"]*\")*))|"
+                             r"((?:\|\w+(?:\s\"[^\"]*\")*)*))[#}]")
+
+    args_re = re.compile(r"\"\s\"")
 
     def __init__(self, loader, filters={}, defaults={}):
         self.loader = loader
@@ -101,7 +104,13 @@ class engine(object):
             else:
                 if fl:
                     for f in fl.split("|")[1:]:
-                        v = self.filters[f](v)
+                        key = f.split(' ')[0]
+                        if '"' in f:
+                            # remove initial ' "' and trailing '"'
+                            args = self.args_re.split(f[len(key)+2:-1])
+                            v = self.filters[key](v, args)
+                        else:
+                            v = self.filters[key](v)
                 yield v
 
 class templater(object):


More information about the Mercurial-devel mailing list