##// END OF EJS Templates
templater: make strings in template expressions be "string-escape"-ed correctly...
FUJIWARA Katsunori -
r20663:5ab28a2e stable
parent child Browse files
Show More
@@ -21,6 +21,7 b' elements = {'
21 ")": (0, None, None),
21 ")": (0, None, None),
22 "symbol": (0, ("symbol",), None),
22 "symbol": (0, ("symbol",), None),
23 "string": (0, ("string",), None),
23 "string": (0, ("string",), None),
24 "rawstring": (0, ("rawstring",), None),
24 "end": (0, None, None),
25 "end": (0, None, None),
25 }
26 }
26
27
@@ -50,7 +51,7 b' def tokenizer(data):'
50 continue
51 continue
51 if d == c:
52 if d == c:
52 if not decode:
53 if not decode:
53 yield ('string', program[s:pos].replace('\\', r'\\'), s)
54 yield ('rawstring', program[s:pos], s)
54 break
55 break
55 yield ('string', program[s:pos], s)
56 yield ('string', program[s:pos], s)
56 break
57 break
@@ -76,23 +77,22 b' def tokenizer(data):'
76 pos += 1
77 pos += 1
77 yield ('end', None, pos)
78 yield ('end', None, pos)
78
79
79 def compiletemplate(tmpl, context):
80 def compiletemplate(tmpl, context, strtoken="string"):
80 parsed = []
81 parsed = []
81 pos, stop = 0, len(tmpl)
82 pos, stop = 0, len(tmpl)
82 p = parser.parser(tokenizer, elements)
83 p = parser.parser(tokenizer, elements)
83 while pos < stop:
84 while pos < stop:
84 n = tmpl.find('{', pos)
85 n = tmpl.find('{', pos)
85 if n < 0:
86 if n < 0:
86 parsed.append(("string", tmpl[pos:].decode("string-escape")))
87 parsed.append((strtoken, tmpl[pos:]))
87 break
88 break
88 if n > 0 and tmpl[n - 1] == '\\':
89 if n > 0 and tmpl[n - 1] == '\\':
89 # escaped
90 # escaped
90 parsed.append(("string",
91 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
91 (tmpl[pos:n - 1] + "{").decode("string-escape")))
92 pos = n + 1
92 pos = n + 1
93 continue
93 continue
94 if n > pos:
94 if n > pos:
95 parsed.append(("string", tmpl[pos:n].decode("string-escape")))
95 parsed.append((strtoken, tmpl[pos:n]))
96
96
97 pd = [tmpl, n + 1, stop]
97 pd = [tmpl, n + 1, stop]
98 parseres, pos = p.parse(pd)
98 parseres, pos = p.parse(pd)
@@ -127,13 +127,16 b' def getfilter(exp, context):'
127 return context._filters[f]
127 return context._filters[f]
128
128
129 def gettemplate(exp, context):
129 def gettemplate(exp, context):
130 if exp[0] == 'string':
130 if exp[0] == 'string' or exp[0] == 'rawstring':
131 return compiletemplate(exp[1], context)
131 return compiletemplate(exp[1], context, strtoken=exp[0])
132 if exp[0] == 'symbol':
132 if exp[0] == 'symbol':
133 return context._load(exp[1])
133 return context._load(exp[1])
134 raise error.ParseError(_("expected template specifier"))
134 raise error.ParseError(_("expected template specifier"))
135
135
136 def runstring(context, mapping, data):
136 def runstring(context, mapping, data):
137 return data.decode("string-escape")
138
139 def runrawstring(context, mapping, data):
137 return data
140 return data
138
141
139 def runsymbol(context, mapping, key):
142 def runsymbol(context, mapping, key):
@@ -256,8 +259,9 b' def get(context, mapping, args):'
256
259
257 def _evalifliteral(arg, context, mapping):
260 def _evalifliteral(arg, context, mapping):
258 t = stringify(arg[0](context, mapping, arg[1]))
261 t = stringify(arg[0](context, mapping, arg[1]))
259 if arg[0] == runstring:
262 if arg[0] == runstring or arg[0] == runrawstring:
260 yield runtemplate(context, mapping, compiletemplate(t, context))
263 yield runtemplate(context, mapping,
264 compiletemplate(t, context, strtoken='rawstring'))
261 else:
265 else:
262 yield t
266 yield t
263
267
@@ -346,6 +350,7 b' def sub(context, mapping, args):'
346
350
347 methods = {
351 methods = {
348 "string": lambda e, c: (runstring, e[1]),
352 "string": lambda e, c: (runstring, e[1]),
353 "rawstring": lambda e, c: (runrawstring, e[1]),
349 "symbol": lambda e, c: (runsymbol, e[1]),
354 "symbol": lambda e, c: (runsymbol, e[1]),
350 "group": lambda e, c: compileexp(e[1], c),
355 "group": lambda e, c: compileexp(e[1], c),
351 # ".": buildmember,
356 # ".": buildmember,
@@ -1610,6 +1610,92 b' Test string escaping:'
1610 <>\n<]>
1610 <>\n<]>
1611 <>\n<
1611 <>\n<
1612
1612
1613 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
1614
1615 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
1616 \x6e
1617 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
1618 \x5c\x786e
1619 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
1620 \x6e
1621 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
1622 \x5c\x786e
1623
1624 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
1625 \x6e
1626 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
1627 \x5c\x786e
1628 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
1629 \x6e
1630 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
1631 \x5c\x786e
1632
1633 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
1634 fourth
1635 second
1636 third
1637 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
1638 fourth\nsecond\nthird
1639
1640 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
1641 <p>
1642 1st
1643 </p>
1644 <p>
1645 2nd
1646 </p>
1647 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
1648 <p>
1649 1st\n\n2nd
1650 </p>
1651 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
1652 1st
1653
1654 2nd
1655
1656 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
1657 o perso
1658 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
1659 no person
1660 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
1661 o perso
1662 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
1663 no perso
1664
1665 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
1666 -o perso-
1667 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
1668 no person
1669 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
1670 \x2do perso\x2d
1671 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
1672 -o perso-
1673 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
1674 \x2do perso\x6e
1675
1676 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
1677 fourth
1678 second
1679 third
1680 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
1681 fourth\nsecond\nthird\n
1682
1683 Test string escapeing in nested expression:
1684
1685 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
1686 fourth\x6esecond\x6ethird
1687 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
1688 fourth\x6esecond\x6ethird
1689
1690 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
1691 fourth\x6esecond\x6ethird
1692 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
1693 fourth\x5c\x786esecond\x5c\x786ethird
1694
1695 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
1696 3:\x6eo user, \x6eo domai\x6e
1697 4:\x5c\x786eew bra\x5c\x786ech
1698
1613 Test recursive evaluation:
1699 Test recursive evaluation:
1614
1700
1615 $ hg init r
1701 $ hg init r
General Comments 0
You need to be logged in to leave comments. Login now