##// END OF EJS Templates
merge with stable
Matt Mackall -
r20670:0084fcd5 merge default
parent child Browse files
Show More
@@ -393,9 +393,7 b' def templatelabel(context, mapping, args'
393 if isinstance(repo, str):
393 if isinstance(repo, str):
394 return thing
394 return thing
395
395
396 label = templater.stringify(args[0][0](context, mapping, args[0][1]))
396 label = templater._evalifliteral(args[0], context, mapping)
397 label = templater.runtemplate(context, mapping,
398 templater.compiletemplate(label, context))
399
397
400 thing = templater.stringify(thing)
398 thing = templater.stringify(thing)
401 label = templater.stringify(label)
399 label = templater.stringify(label)
@@ -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):
@@ -234,12 +237,8 b' def fill(context, mapping, args):'
234 except ValueError:
237 except ValueError:
235 raise error.ParseError(_("fill expects an integer width"))
238 raise error.ParseError(_("fill expects an integer width"))
236 try:
239 try:
237 initindent = stringify(args[2][0](context, mapping, args[2][1]))
240 initindent = stringify(_evalifliteral(args[2], context, mapping))
238 initindent = stringify(runtemplate(context, mapping,
241 hangindent = stringify(_evalifliteral(args[3], context, mapping))
239 compiletemplate(initindent, context)))
240 hangindent = stringify(args[3][0](context, mapping, args[3][1]))
241 hangindent = stringify(runtemplate(context, mapping,
242 compiletemplate(hangindent, context)))
243 except IndexError:
242 except IndexError:
244 pass
243 pass
245
244
@@ -285,8 +284,9 b' def get(context, mapping, args):'
285
284
286 def _evalifliteral(arg, context, mapping):
285 def _evalifliteral(arg, context, mapping):
287 t = stringify(arg[0](context, mapping, arg[1]))
286 t = stringify(arg[0](context, mapping, arg[1]))
288 if arg[0] == runstring:
287 if arg[0] == runstring or arg[0] == runrawstring:
289 yield runtemplate(context, mapping, compiletemplate(t, context))
288 yield runtemplate(context, mapping,
289 compiletemplate(t, context, strtoken='rawstring'))
290 else:
290 else:
291 yield t
291 yield t
292
292
@@ -338,7 +338,7 b' def join(context, mapping, args):'
338
338
339 joiner = " "
339 joiner = " "
340 if len(args) > 1:
340 if len(args) > 1:
341 joiner = args[1][0](context, mapping, args[1][1])
341 joiner = stringify(args[1][0](context, mapping, args[1][1]))
342
342
343 first = True
343 first = True
344 for x in joinset:
344 for x in joinset:
@@ -447,9 +447,9 b' def strip(context, mapping, args):'
447 if not (1 <= len(args) <= 2):
447 if not (1 <= len(args) <= 2):
448 raise error.ParseError(_("strip expects one or two arguments"))
448 raise error.ParseError(_("strip expects one or two arguments"))
449
449
450 text = args[0][0](context, mapping, args[0][1])
450 text = stringify(args[0][0](context, mapping, args[0][1]))
451 if len(args) == 2:
451 if len(args) == 2:
452 chars = args[1][0](context, mapping, args[1][1])
452 chars = stringify(args[1][0](context, mapping, args[1][1]))
453 return text.strip(chars)
453 return text.strip(chars)
454 return text.strip()
454 return text.strip()
455
455
@@ -460,13 +460,12 b' def sub(context, mapping, args):'
460
460
461 pat = stringify(args[0][0](context, mapping, args[0][1]))
461 pat = stringify(args[0][0](context, mapping, args[0][1]))
462 rpl = stringify(args[1][0](context, mapping, args[1][1]))
462 rpl = stringify(args[1][0](context, mapping, args[1][1]))
463 src = stringify(args[2][0](context, mapping, args[2][1]))
463 src = stringify(_evalifliteral(args[2], context, mapping))
464 src = stringify(runtemplate(context, mapping,
465 compiletemplate(src, context)))
466 yield re.sub(pat, rpl, src)
464 yield re.sub(pat, rpl, src)
467
465
468 methods = {
466 methods = {
469 "string": lambda e, c: (runstring, e[1]),
467 "string": lambda e, c: (runstring, e[1]),
468 "rawstring": lambda e, c: (runrawstring, e[1]),
470 "symbol": lambda e, c: (runsymbol, e[1]),
469 "symbol": lambda e, c: (runsymbol, e[1]),
471 "group": lambda e, c: compileexp(e[1], c),
470 "group": lambda e, c: compileexp(e[1], c),
472 # ".": buildmember,
471 # ".": buildmember,
@@ -1633,6 +1633,92 b' Test string escaping:'
1633 <>\n<]>
1633 <>\n<]>
1634 <>\n<
1634 <>\n<
1635
1635
1636 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
1637
1638 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
1639 \x6e
1640 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
1641 \x5c\x786e
1642 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
1643 \x6e
1644 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
1645 \x5c\x786e
1646
1647 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
1648 \x6e
1649 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
1650 \x5c\x786e
1651 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
1652 \x6e
1653 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
1654 \x5c\x786e
1655
1656 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
1657 fourth
1658 second
1659 third
1660 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
1661 fourth\nsecond\nthird
1662
1663 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
1664 <p>
1665 1st
1666 </p>
1667 <p>
1668 2nd
1669 </p>
1670 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
1671 <p>
1672 1st\n\n2nd
1673 </p>
1674 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
1675 1st
1676
1677 2nd
1678
1679 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
1680 o perso
1681 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
1682 no person
1683 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
1684 o perso
1685 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
1686 no perso
1687
1688 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
1689 -o perso-
1690 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
1691 no person
1692 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
1693 \x2do perso\x2d
1694 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
1695 -o perso-
1696 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
1697 \x2do perso\x6e
1698
1699 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
1700 fourth
1701 second
1702 third
1703 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
1704 fourth\nsecond\nthird\n
1705
1706 Test string escapeing in nested expression:
1707
1708 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
1709 fourth\x6esecond\x6ethird
1710 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
1711 fourth\x6esecond\x6ethird
1712
1713 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
1714 fourth\x6esecond\x6ethird
1715 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
1716 fourth\x5c\x786esecond\x5c\x786ethird
1717
1718 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
1719 3:\x6eo user, \x6eo domai\x6e
1720 4:\x5c\x786eew bra\x5c\x786ech
1721
1636 Test recursive evaluation:
1722 Test recursive evaluation:
1637
1723
1638 $ hg init r
1724 $ hg init r
@@ -1645,6 +1731,39 b' Test recursive evaluation:'
1645 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
1731 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
1646 test 0
1732 test 0
1647
1733
1734 $ hg branch -q 'text.{rev}'
1735 $ echo aa >> aa
1736 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
1737
1738 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
1739 {node|short}desc to
1740 text.{rev}be wrapped
1741 text.{rev}desc to be
1742 text.{rev}wrapped (no-eol)
1743 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
1744 bcc7ff960b8e:desc to
1745 text.1:be wrapped
1746 text.1:desc to be
1747 text.1:wrapped (no-eol)
1748
1749 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
1750 {node|short} (no-eol)
1751 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
1752 bcc-ff---b-e (no-eol)
1753
1754 $ cat >> .hg/hgrc <<EOF
1755 > [extensions]
1756 > color=
1757 > [color]
1758 > mode=ansi
1759 > text.{rev} = red
1760 > text.1 = green
1761 > EOF
1762 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
1763 \x1b[0;31mtext\x1b[0m (esc)
1764 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
1765 \x1b[0;32mtext\x1b[0m (esc)
1766
1648 Test branches inside if statement:
1767 Test branches inside if statement:
1649
1768
1650 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
1769 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
@@ -1655,43 +1774,56 b' Test shortest(node) function:'
1655 $ echo b > b
1774 $ echo b > b
1656 $ hg ci -qAm b
1775 $ hg ci -qAm b
1657 $ hg log --template '{shortest(node)}\n'
1776 $ hg log --template '{shortest(node)}\n'
1658 d97c
1777 e777
1778 bcc7
1659 f776
1779 f776
1660 $ hg log --template '{shortest(node, 10)}\n'
1780 $ hg log --template '{shortest(node, 10)}\n'
1661 d97c383ae3
1781 e777603221
1782 bcc7ff960b
1662 f7769ec2ab
1783 f7769ec2ab
1663
1784
1664 Test pad function
1785 Test pad function
1665
1786
1666 $ hg log --template '{pad(rev, 20)} {author|user}\n'
1787 $ hg log --template '{pad(rev, 20)} {author|user}\n'
1667 1 test
1788 2 test
1789 1 {node|short}
1668 0 test
1790 0 test
1669
1791
1670 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
1792 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
1671 1 test
1793 2 test
1794 1 {node|short}
1672 0 test
1795 0 test
1673
1796
1674 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
1797 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
1675 1------------------- test
1798 2------------------- test
1799 1------------------- {node|short}
1676 0------------------- test
1800 0------------------- test
1677
1801
1678 Test ifcontains function
1802 Test ifcontains function
1679
1803
1680 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
1804 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
1805 2 did not add a
1681 1 did not add a
1806 1 did not add a
1682 0 added a
1807 0 added a
1683
1808
1684 Test revset function
1809 Test revset function
1685
1810
1686 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
1811 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
1687 1 current rev
1812 2 current rev
1813 1 not current rev
1688 0 not current rev
1814 0 not current rev
1689
1815
1690 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
1816 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
1817 2 Parents: 1
1691 1 Parents: 0
1818 1 Parents: 0
1692 0 Parents:
1819 0 Parents:
1693
1820
1694 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
1821 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
1822 Rev: 2
1823 Ancestor: 0
1824 Ancestor: 1
1825 Ancestor: 2
1826
1695 Rev: 1
1827 Rev: 1
1696 Ancestor: 0
1828 Ancestor: 0
1697 Ancestor: 1
1829 Ancestor: 1
@@ -1704,5 +1836,15 b' Test current bookmark templating'
1704 $ hg book foo
1836 $ hg book foo
1705 $ hg book bar
1837 $ hg book bar
1706 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
1838 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
1707 1 bar* foo
1839 2 bar* foo
1840 1
1708 0
1841 0
1842
1843 Test stringify on sub expressions
1844
1845 $ cd ..
1846 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
1847 fourth, second, third
1848 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
1849 abc
1850
General Comments 0
You need to be logged in to leave comments. Login now