# HG changeset patch # User Matt Mackall # Date 1394572748 18000 # Node ID 0084fcd5d7e25d26662bb261d1bf64489882b440 # Parent 870d60294b047bab8b616af981777c1e90a97ef7# Parent 5ab28a2e9962f78f90cf3e38483af1bd24035e1a merge with stable diff -r 870d60294b04 -r 0084fcd5d7e2 hgext/color.py --- a/hgext/color.py Mon Mar 10 15:00:41 2014 -0500 +++ b/hgext/color.py Tue Mar 11 16:19:08 2014 -0500 @@ -393,9 +393,7 @@ if isinstance(repo, str): return thing - label = templater.stringify(args[0][0](context, mapping, args[0][1])) - label = templater.runtemplate(context, mapping, - templater.compiletemplate(label, context)) + label = templater._evalifliteral(args[0], context, mapping) thing = templater.stringify(thing) label = templater.stringify(label) diff -r 870d60294b04 -r 0084fcd5d7e2 mercurial/templater.py --- a/mercurial/templater.py Mon Mar 10 15:00:41 2014 -0500 +++ b/mercurial/templater.py Tue Mar 11 16:19:08 2014 -0500 @@ -21,6 +21,7 @@ ")": (0, None, None), "symbol": (0, ("symbol",), None), "string": (0, ("string",), None), + "rawstring": (0, ("rawstring",), None), "end": (0, None, None), } @@ -50,7 +51,7 @@ continue if d == c: if not decode: - yield ('string', program[s:pos].replace('\\', r'\\'), s) + yield ('rawstring', program[s:pos], s) break yield ('string', program[s:pos], s) break @@ -76,23 +77,22 @@ pos += 1 yield ('end', None, pos) -def compiletemplate(tmpl, context): +def compiletemplate(tmpl, context, strtoken="string"): parsed = [] pos, stop = 0, len(tmpl) p = parser.parser(tokenizer, elements) while pos < stop: n = tmpl.find('{', pos) if n < 0: - parsed.append(("string", tmpl[pos:].decode("string-escape"))) + parsed.append((strtoken, tmpl[pos:])) break if n > 0 and tmpl[n - 1] == '\\': # escaped - parsed.append(("string", - (tmpl[pos:n - 1] + "{").decode("string-escape"))) + parsed.append((strtoken, (tmpl[pos:n - 1] + "{"))) pos = n + 1 continue if n > pos: - parsed.append(("string", tmpl[pos:n].decode("string-escape"))) + parsed.append((strtoken, tmpl[pos:n])) pd = [tmpl, n + 1, stop] parseres, pos = p.parse(pd) @@ -127,13 +127,16 @@ return context._filters[f] def gettemplate(exp, context): - if exp[0] == 'string': - return compiletemplate(exp[1], context) + if exp[0] == 'string' or exp[0] == 'rawstring': + return compiletemplate(exp[1], context, strtoken=exp[0]) if exp[0] == 'symbol': return context._load(exp[1]) raise error.ParseError(_("expected template specifier")) def runstring(context, mapping, data): + return data.decode("string-escape") + +def runrawstring(context, mapping, data): return data def runsymbol(context, mapping, key): @@ -234,12 +237,8 @@ except ValueError: raise error.ParseError(_("fill expects an integer width")) try: - initindent = stringify(args[2][0](context, mapping, args[2][1])) - initindent = stringify(runtemplate(context, mapping, - compiletemplate(initindent, context))) - hangindent = stringify(args[3][0](context, mapping, args[3][1])) - hangindent = stringify(runtemplate(context, mapping, - compiletemplate(hangindent, context))) + initindent = stringify(_evalifliteral(args[2], context, mapping)) + hangindent = stringify(_evalifliteral(args[3], context, mapping)) except IndexError: pass @@ -285,8 +284,9 @@ def _evalifliteral(arg, context, mapping): t = stringify(arg[0](context, mapping, arg[1])) - if arg[0] == runstring: - yield runtemplate(context, mapping, compiletemplate(t, context)) + if arg[0] == runstring or arg[0] == runrawstring: + yield runtemplate(context, mapping, + compiletemplate(t, context, strtoken='rawstring')) else: yield t @@ -338,7 +338,7 @@ joiner = " " if len(args) > 1: - joiner = args[1][0](context, mapping, args[1][1]) + joiner = stringify(args[1][0](context, mapping, args[1][1])) first = True for x in joinset: @@ -447,9 +447,9 @@ if not (1 <= len(args) <= 2): raise error.ParseError(_("strip expects one or two arguments")) - text = args[0][0](context, mapping, args[0][1]) + text = stringify(args[0][0](context, mapping, args[0][1])) if len(args) == 2: - chars = args[1][0](context, mapping, args[1][1]) + chars = stringify(args[1][0](context, mapping, args[1][1])) return text.strip(chars) return text.strip() @@ -460,13 +460,12 @@ pat = stringify(args[0][0](context, mapping, args[0][1])) rpl = stringify(args[1][0](context, mapping, args[1][1])) - src = stringify(args[2][0](context, mapping, args[2][1])) - src = stringify(runtemplate(context, mapping, - compiletemplate(src, context))) + src = stringify(_evalifliteral(args[2], context, mapping)) yield re.sub(pat, rpl, src) methods = { "string": lambda e, c: (runstring, e[1]), + "rawstring": lambda e, c: (runrawstring, e[1]), "symbol": lambda e, c: (runsymbol, e[1]), "group": lambda e, c: compileexp(e[1], c), # ".": buildmember, diff -r 870d60294b04 -r 0084fcd5d7e2 tests/test-command-template.t --- a/tests/test-command-template.t Mon Mar 10 15:00:41 2014 -0500 +++ b/tests/test-command-template.t Tue Mar 11 16:19:08 2014 -0500 @@ -1633,6 +1633,92 @@ <>\n<]> <>\n< +"string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice) + + $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n' + \x6e + $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n' + \x5c\x786e + $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n' + \x6e + $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n' + \x5c\x786e + + $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n' + \x6e + $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n' + \x5c\x786e + $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n' + \x6e + $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n' + \x5c\x786e + + $ hg log -R a -r 8 --template '{join(files, "\n")}\n' + fourth + second + third + $ hg log -R a -r 8 --template '{join(files, r"\n")}\n' + fourth\nsecond\nthird + + $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}' +

+ 1st +

+

+ 2nd +

+ $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}' +

+ 1st\n\n2nd +

+ $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}' + 1st + + 2nd + + $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n' + o perso + $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n' + no person + $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n' + o perso + $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n' + no perso + + $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n' + -o perso- + $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n' + no person + $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n' + \x2do perso\x2d + $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n' + -o perso- + $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n' + \x2do perso\x6e + + $ hg log -R a -r 8 --template '{files % "{file}\n"}' + fourth + second + third + $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n' + fourth\nsecond\nthird\n + +Test string escapeing in nested expression: + + $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n' + fourth\x6esecond\x6ethird + $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n' + fourth\x6esecond\x6ethird + + $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n' + fourth\x6esecond\x6ethird + $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n' + fourth\x5c\x786esecond\x5c\x786ethird + + $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n' + 3:\x6eo user, \x6eo domai\x6e + 4:\x5c\x786eew bra\x5c\x786ech + Test recursive evaluation: $ hg init r @@ -1645,6 +1731,39 @@ $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n' test 0 + $ hg branch -q 'text.{rev}' + $ echo aa >> aa + $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped' + + $ hg log -l1 --template '{fill(desc, "20", author, branch)}' + {node|short}desc to + text.{rev}be wrapped + text.{rev}desc to be + text.{rev}wrapped (no-eol) + $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}' + bcc7ff960b8e:desc to + text.1:be wrapped + text.1:desc to be + text.1:wrapped (no-eol) + + $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}' + {node|short} (no-eol) + $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}' + bcc-ff---b-e (no-eol) + + $ cat >> .hg/hgrc < [extensions] + > color= + > [color] + > mode=ansi + > text.{rev} = red + > text.1 = green + > EOF + $ hg log --color=always -l 1 --template '{label(branch, "text\n")}' + \x1b[0;31mtext\x1b[0m (esc) + $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}' + \x1b[0;32mtext\x1b[0m (esc) + Test branches inside if statement: $ hg log -r 0 --template '{if(branches, "yes", "no")}\n' @@ -1655,43 +1774,56 @@ $ echo b > b $ hg ci -qAm b $ hg log --template '{shortest(node)}\n' - d97c + e777 + bcc7 f776 $ hg log --template '{shortest(node, 10)}\n' - d97c383ae3 + e777603221 + bcc7ff960b f7769ec2ab Test pad function $ hg log --template '{pad(rev, 20)} {author|user}\n' - 1 test + 2 test + 1 {node|short} 0 test $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n' - 1 test + 2 test + 1 {node|short} 0 test $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n' - 1------------------- test + 2------------------- test + 1------------------- {node|short} 0------------------- test Test ifcontains function $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n' + 2 did not add a 1 did not add a 0 added a Test revset function $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n' - 1 current rev + 2 current rev + 1 not current rev 0 not current rev $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n' + 2 Parents: 1 1 Parents: 0 0 Parents: $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n' + Rev: 2 + Ancestor: 0 + Ancestor: 1 + Ancestor: 2 + Rev: 1 Ancestor: 0 Ancestor: 1 @@ -1704,5 +1836,15 @@ $ hg book foo $ hg book bar $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n" - 1 bar* foo + 2 bar* foo + 1 0 + +Test stringify on sub expressions + + $ cd .. + $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n' + fourth, second, third + $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n' + abc +