Show More
@@ -234,7 +234,7 b' class templatefunc(_templateregistrarbas' | |||||
234 |
|
234 | |||
235 | templatefunc = registrar.templatefunc() |
|
235 | templatefunc = registrar.templatefunc() | |
236 |
|
236 | |||
237 | @templatefunc('myfunc(arg1, arg2[, arg3])') |
|
237 | @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3') | |
238 | def myfuncfunc(context, mapping, args): |
|
238 | def myfuncfunc(context, mapping, args): | |
239 | '''Explanation of this template function .... |
|
239 | '''Explanation of this template function .... | |
240 | ''' |
|
240 | ''' | |
@@ -242,6 +242,10 b' class templatefunc(_templateregistrarbas' | |||||
242 |
|
242 | |||
243 | The first string argument is used also in online help. |
|
243 | The first string argument is used also in online help. | |
244 |
|
244 | |||
|
245 | If optional 'argspec' is defined, the function will receive 'args' as | |||
|
246 | a dict of named arguments. Otherwise 'args' is a list of positional | |||
|
247 | arguments. | |||
|
248 | ||||
245 | 'templatefunc' instance in example above can be used to |
|
249 | 'templatefunc' instance in example above can be used to | |
246 | decorate multiple functions. |
|
250 | decorate multiple functions. | |
247 |
|
251 | |||
@@ -252,3 +256,6 b' class templatefunc(_templateregistrarbas' | |||||
252 | Otherwise, explicit 'templater.loadfunction()' is needed. |
|
256 | Otherwise, explicit 'templater.loadfunction()' is needed. | |
253 | """ |
|
257 | """ | |
254 | _getname = _funcregistrarbase._parsefuncdecl |
|
258 | _getname = _funcregistrarbase._parsefuncdecl | |
|
259 | ||||
|
260 | def _extrasetup(self, name, func, argspec=None): | |||
|
261 | func._argspec = argspec |
@@ -370,14 +370,15 b' def runtemplate(context, mapping, templa' | |||||
370 | yield func(context, mapping, data) |
|
370 | yield func(context, mapping, data) | |
371 |
|
371 | |||
372 | def buildfilter(exp, context): |
|
372 | def buildfilter(exp, context): | |
373 | arg = compileexp(exp[1], context, methods) |
|
|||
374 | n = getsymbol(exp[2]) |
|
373 | n = getsymbol(exp[2]) | |
375 | if n in context._filters: |
|
374 | if n in context._filters: | |
376 | filt = context._filters[n] |
|
375 | filt = context._filters[n] | |
|
376 | arg = compileexp(exp[1], context, methods) | |||
377 | return (runfilter, (arg, filt)) |
|
377 | return (runfilter, (arg, filt)) | |
378 | if n in funcs: |
|
378 | if n in funcs: | |
379 | f = funcs[n] |
|
379 | f = funcs[n] | |
380 | return (f, [arg]) |
|
380 | args = _buildfuncargs(exp[1], context, methods, n, f._argspec) | |
|
381 | return (f, args) | |||
381 | raise error.ParseError(_("unknown function '%s'") % n) |
|
382 | raise error.ParseError(_("unknown function '%s'") % n) | |
382 |
|
383 | |||
383 | def runfilter(context, mapping, data): |
|
384 | def runfilter(context, mapping, data): | |
@@ -452,17 +453,41 b' def runarithmetic(context, mapping, data' | |||||
452 |
|
453 | |||
453 | def buildfunc(exp, context): |
|
454 | def buildfunc(exp, context): | |
454 | n = getsymbol(exp[1]) |
|
455 | n = getsymbol(exp[1]) | |
455 | args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])] |
|
|||
456 | if n in funcs: |
|
456 | if n in funcs: | |
457 | f = funcs[n] |
|
457 | f = funcs[n] | |
|
458 | args = _buildfuncargs(exp[2], context, exprmethods, n, f._argspec) | |||
458 | return (f, args) |
|
459 | return (f, args) | |
459 | if n in context._filters: |
|
460 | if n in context._filters: | |
|
461 | args = _buildfuncargs(exp[2], context, exprmethods, n, argspec=None) | |||
460 | if len(args) != 1: |
|
462 | if len(args) != 1: | |
461 | raise error.ParseError(_("filter %s expects one argument") % n) |
|
463 | raise error.ParseError(_("filter %s expects one argument") % n) | |
462 | f = context._filters[n] |
|
464 | f = context._filters[n] | |
463 | return (runfilter, (args[0], f)) |
|
465 | return (runfilter, (args[0], f)) | |
464 | raise error.ParseError(_("unknown function '%s'") % n) |
|
466 | raise error.ParseError(_("unknown function '%s'") % n) | |
465 |
|
467 | |||
|
468 | def _buildfuncargs(exp, context, curmethods, funcname, argspec): | |||
|
469 | """Compile parsed tree of function arguments into list or dict of | |||
|
470 | (func, data) pairs""" | |||
|
471 | def compiledict(xs): | |||
|
472 | return dict((k, compileexp(x, context, curmethods)) | |||
|
473 | for k, x in xs.iteritems()) | |||
|
474 | def compilelist(xs): | |||
|
475 | return [compileexp(x, context, curmethods) for x in xs] | |||
|
476 | ||||
|
477 | if not argspec: | |||
|
478 | # filter or function with no argspec: return list of positional args | |||
|
479 | return compilelist(getlist(exp)) | |||
|
480 | ||||
|
481 | # function with argspec: return dict of named args | |||
|
482 | _poskeys, varkey, _keys = argspec = parser.splitargspec(argspec) | |||
|
483 | treeargs = parser.buildargsdict(getlist(exp), funcname, argspec, | |||
|
484 | keyvaluenode='keyvalue', keynode='symbol') | |||
|
485 | compargs = {} | |||
|
486 | if varkey: | |||
|
487 | compargs[varkey] = compilelist(treeargs.pop(varkey)) | |||
|
488 | compargs.update(compiledict(treeargs)) | |||
|
489 | return compargs | |||
|
490 | ||||
466 | def buildkeyvaluepair(exp, content): |
|
491 | def buildkeyvaluepair(exp, content): | |
467 | raise error.ParseError(_("can't use a key-value pair in this context")) |
|
492 | raise error.ParseError(_("can't use a key-value pair in this context")) | |
468 |
|
493 | |||
@@ -832,16 +857,16 b' def rstdoc(context, mapping, args):' | |||||
832 |
|
857 | |||
833 | return minirst.format(text, style=style, keep=['verbose']) |
|
858 | return minirst.format(text, style=style, keep=['verbose']) | |
834 |
|
859 | |||
835 | @templatefunc('separate(sep, args)') |
|
860 | @templatefunc('separate(sep, args)', argspec='sep *args') | |
836 | def separate(context, mapping, args): |
|
861 | def separate(context, mapping, args): | |
837 | """Add a separator between non-empty arguments.""" |
|
862 | """Add a separator between non-empty arguments.""" | |
838 | if not args: |
|
863 | if 'sep' not in args: | |
839 | # i18n: "separate" is a keyword |
|
864 | # i18n: "separate" is a keyword | |
840 | raise error.ParseError(_("separate expects at least one argument")) |
|
865 | raise error.ParseError(_("separate expects at least one argument")) | |
841 |
|
866 | |||
842 |
sep = evalstring(context, mapping, args[ |
|
867 | sep = evalstring(context, mapping, args['sep']) | |
843 | first = True |
|
868 | first = True | |
844 |
for arg in args[ |
|
869 | for arg in args['args']: | |
845 | argstr = evalstring(context, mapping, arg) |
|
870 | argstr = evalstring(context, mapping, arg) | |
846 | if not argstr: |
|
871 | if not argstr: | |
847 | continue |
|
872 | continue |
@@ -146,6 +146,13 b' Keyword arguments:' | |||||
146 | hg: parse error: can't use a key-value pair in this context |
|
146 | hg: parse error: can't use a key-value pair in this context | |
147 | [255] |
|
147 | [255] | |
148 |
|
148 | |||
|
149 | Call function which takes named arguments by filter syntax: | |||
|
150 | ||||
|
151 | $ hg debugtemplate '{" "|separate}' | |||
|
152 | $ hg debugtemplate '{("not", "an", "argument", "list")|separate}' | |||
|
153 | hg: parse error: unknown method 'list' | |||
|
154 | [255] | |||
|
155 | ||||
149 | Second branch starting at nullrev: |
|
156 | Second branch starting at nullrev: | |
150 |
|
157 | |||
151 | $ hg update null |
|
158 | $ hg update null |
General Comments 0
You need to be logged in to leave comments.
Login now