31 "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), |
31 "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), |
32 ",": (2, None, None, ("list", 2), None), |
32 ",": (2, None, None, ("list", 2), None), |
33 "|": (5, None, None, ("|", 5), None), |
33 "|": (5, None, None, ("|", 5), None), |
34 "%": (6, None, None, ("%", 6), None), |
34 "%": (6, None, None, ("%", 6), None), |
35 ")": (0, None, None, None, None), |
35 ")": (0, None, None, None, None), |
|
36 "+": (3, None, None, ("+", 3), None), |
|
37 "-": (3, None, ("negate", 10), ("-", 3), None), |
|
38 "*": (4, None, None, ("*", 4), None), |
|
39 "/": (4, None, None, ("/", 4), None), |
36 "integer": (0, "integer", None, None, None), |
40 "integer": (0, "integer", None, None, None), |
37 "symbol": (0, "symbol", None, None, None), |
41 "symbol": (0, "symbol", None, None, None), |
38 "string": (0, "string", None, None, None), |
42 "string": (0, "string", None, None, None), |
39 "template": (0, "template", None, None, None), |
43 "template": (0, "template", None, None, None), |
40 "end": (0, None, None, None, None), |
44 "end": (0, None, None, None, None), |
418 # v is not an iterable of dicts, this happen when 'key' |
417 # v is not an iterable of dicts, this happen when 'key' |
419 # has been fully expanded already and format is useless. |
418 # has been fully expanded already and format is useless. |
420 # If so, return the expanded value. |
419 # If so, return the expanded value. |
421 yield i |
420 yield i |
422 |
421 |
|
422 def buildnegate(exp, context): |
|
423 arg = compileexp(exp[1], context, exprmethods) |
|
424 return (runnegate, arg) |
|
425 |
|
426 def runnegate(context, mapping, data): |
|
427 data = evalinteger(context, mapping, data, |
|
428 _('negation needs an integer argument')) |
|
429 return -data |
|
430 |
|
431 def buildarithmetic(exp, context, func): |
|
432 left = compileexp(exp[1], context, exprmethods) |
|
433 right = compileexp(exp[2], context, exprmethods) |
|
434 return (runarithmetic, (func, left, right)) |
|
435 |
|
436 def runarithmetic(context, mapping, data): |
|
437 func, left, right = data |
|
438 left = evalinteger(context, mapping, left, |
|
439 _('arithmetic only defined on integers')) |
|
440 right = evalinteger(context, mapping, right, |
|
441 _('arithmetic only defined on integers')) |
|
442 return func(left, right) |
|
443 |
423 def buildfunc(exp, context): |
444 def buildfunc(exp, context): |
424 n = getsymbol(exp[1]) |
445 n = getsymbol(exp[1]) |
425 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])] |
446 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])] |
426 if n in funcs: |
447 if n in funcs: |
427 f = funcs[n] |
448 f = funcs[n] |
711 raise error.ParseError(_("localdate expects a timezone")) |
732 raise error.ParseError(_("localdate expects a timezone")) |
712 else: |
733 else: |
713 tzoffset = util.makedate()[1] |
734 tzoffset = util.makedate()[1] |
714 return (date[0], tzoffset) |
735 return (date[0], tzoffset) |
715 |
736 |
|
737 @templatefunc('mod(a, b)') |
|
738 def mod(context, mapping, args): |
|
739 """Calculate a mod b such that a / b + a mod b == a""" |
|
740 if not len(args) == 2: |
|
741 # i18n: "mod" is a keyword |
|
742 raise error.ParseError(_("mod expects two arguments")) |
|
743 |
|
744 left = evalinteger(context, mapping, args[0], |
|
745 _('arithmetic only defined on integers')) |
|
746 right = evalinteger(context, mapping, args[1], |
|
747 _('arithmetic only defined on integers')) |
|
748 |
|
749 return left % right |
|
750 |
716 @templatefunc('relpath(path)') |
751 @templatefunc('relpath(path)') |
717 def relpath(context, mapping, args): |
752 def relpath(context, mapping, args): |
718 """Convert a repository-absolute path into a filesystem path relative to |
753 """Convert a repository-absolute path into a filesystem path relative to |
719 the current working directory.""" |
754 the current working directory.""" |
720 if len(args) != 1: |
755 if len(args) != 1: |
924 "group": lambda e, c: compileexp(e[1], c, exprmethods), |
959 "group": lambda e, c: compileexp(e[1], c, exprmethods), |
925 # ".": buildmember, |
960 # ".": buildmember, |
926 "|": buildfilter, |
961 "|": buildfilter, |
927 "%": buildmap, |
962 "%": buildmap, |
928 "func": buildfunc, |
963 "func": buildfunc, |
|
964 "+": lambda e, c: buildarithmetic(e, c, lambda a, b: a + b), |
|
965 "-": lambda e, c: buildarithmetic(e, c, lambda a, b: a - b), |
|
966 "negate": buildnegate, |
|
967 "*": lambda e, c: buildarithmetic(e, c, lambda a, b: a * b), |
|
968 "/": lambda e, c: buildarithmetic(e, c, lambda a, b: a // b), |
929 } |
969 } |
930 |
970 |
931 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"}) |
971 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"}) |
932 methods = exprmethods.copy() |
972 methods = exprmethods.copy() |
933 methods["integer"] = exprmethods["symbol"] # '{1}' as variable |
973 methods["integer"] = exprmethods["symbol"] # '{1}' as variable |