[RFC] [PATCH] Support arguments in template expandos (v3)
Rocco Rutte
pdmef at gmx.net
Sat May 16 11:05:35 CDT 2009
Hi,
* Martin Geisler wrote:
> Rocco Rutte <pdmef at gmx.net> writes:
> > - 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\"[^\"]*\")*)*))[#}]")
> Wow, this regexp is starting to become a little complicated :-) I don't
> know if it could be simplified, but we loose some speed here.
Yes, it took some time for me to understand it.
> > + args_re = re.compile(r"\"\s\"")
> I think it better to write this as r'"\s"' -- it's confusing when raw
> strings contain both raw backslashes and backslashes which escape stuff.
Done.
> > 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)
> Using *args when calling filter[key] would be nice because it allows the
> nonempty filter to be defined as
Done.
I updated the patch (attached) and did some more timings though I'm not
sure why both got closer (except I made a mistake).
Unpatched:
wall 2.734970 comb 4.566667 user 4.316667 sys 0.250000 (best of 4)
Patched:
wall 2.797045 comb 4.650000 user 4.416667 sys 0.233333 (best of 4)
Rocco
# HG changeset patch
# User Rocco Rutte <pdmef at gmx.net>
# Date 1242489612 -7200
# Node ID a3983675ce793350b961a40e6bb82c5fe0626ba0
# Parent 3acc6279b3648fc587db571c531ba102d735686f
Support arguments for template filters
The syntax for arguments is:
{key|filter1 ["arg1" ["arg2" ...]]|...}
Existing filters don't have to be changed unless
they want to accept arguments.
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
@@ -171,8 +171,8 @@ def stripdir(text):
else:
return dir
-def nonempty(str):
- return str or "(none)"
+def nonempty(str, default="(none)"):
+ return str or default
filters = {
"addbreaks": nl2br,
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -40,10 +40,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
@@ -102,7 +105,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
engines = {'default': engine}
More information about the Mercurial-devel
mailing list