Show More
@@ -393,9 +393,7 b' def templatelabel(context, mapping, args' | |||
|
393 | 393 | if isinstance(repo, str): |
|
394 | 394 | return thing |
|
395 | 395 | |
|
396 |
label = templater. |
|
|
397 | label = templater.runtemplate(context, mapping, | |
|
398 | templater.compiletemplate(label, context)) | |
|
396 | label = templater._evalifliteral(args[0], context, mapping) | |
|
399 | 397 | |
|
400 | 398 | thing = templater.stringify(thing) |
|
401 | 399 | label = templater.stringify(label) |
@@ -21,6 +21,7 b' elements = {' | |||
|
21 | 21 | ")": (0, None, None), |
|
22 | 22 | "symbol": (0, ("symbol",), None), |
|
23 | 23 | "string": (0, ("string",), None), |
|
24 | "rawstring": (0, ("rawstring",), None), | |
|
24 | 25 | "end": (0, None, None), |
|
25 | 26 | } |
|
26 | 27 | |
@@ -50,7 +51,7 b' def tokenizer(data):' | |||
|
50 | 51 | continue |
|
51 | 52 | if d == c: |
|
52 | 53 | if not decode: |
|
53 |
yield ('string', program[s:pos] |
|
|
54 | yield ('rawstring', program[s:pos], s) | |
|
54 | 55 | break |
|
55 | 56 | yield ('string', program[s:pos], s) |
|
56 | 57 | break |
@@ -76,23 +77,22 b' def tokenizer(data):' | |||
|
76 | 77 | pos += 1 |
|
77 | 78 | yield ('end', None, pos) |
|
78 | 79 | |
|
79 | def compiletemplate(tmpl, context): | |
|
80 | def compiletemplate(tmpl, context, strtoken="string"): | |
|
80 | 81 | parsed = [] |
|
81 | 82 | pos, stop = 0, len(tmpl) |
|
82 | 83 | p = parser.parser(tokenizer, elements) |
|
83 | 84 | while pos < stop: |
|
84 | 85 | n = tmpl.find('{', pos) |
|
85 | 86 | if n < 0: |
|
86 |
parsed.append(( |
|
|
87 | parsed.append((strtoken, tmpl[pos:])) | |
|
87 | 88 | break |
|
88 | 89 | if n > 0 and tmpl[n - 1] == '\\': |
|
89 | 90 | # escaped |
|
90 |
parsed.append((" |
|
|
91 | (tmpl[pos:n - 1] + "{").decode("string-escape"))) | |
|
91 | parsed.append((strtoken, (tmpl[pos:n - 1] + "{"))) | |
|
92 | 92 | pos = n + 1 |
|
93 | 93 | continue |
|
94 | 94 | if n > pos: |
|
95 |
parsed.append(( |
|
|
95 | parsed.append((strtoken, tmpl[pos:n])) | |
|
96 | 96 | |
|
97 | 97 | pd = [tmpl, n + 1, stop] |
|
98 | 98 | parseres, pos = p.parse(pd) |
@@ -127,13 +127,16 b' def getfilter(exp, context):' | |||
|
127 | 127 | return context._filters[f] |
|
128 | 128 | |
|
129 | 129 | def gettemplate(exp, context): |
|
130 | if exp[0] == 'string': | |
|
131 | return compiletemplate(exp[1], context) | |
|
130 | if exp[0] == 'string' or exp[0] == 'rawstring': | |
|
131 | return compiletemplate(exp[1], context, strtoken=exp[0]) | |
|
132 | 132 | if exp[0] == 'symbol': |
|
133 | 133 | return context._load(exp[1]) |
|
134 | 134 | raise error.ParseError(_("expected template specifier")) |
|
135 | 135 | |
|
136 | 136 | def runstring(context, mapping, data): |
|
137 | return data.decode("string-escape") | |
|
138 | ||
|
139 | def runrawstring(context, mapping, data): | |
|
137 | 140 | return data |
|
138 | 141 | |
|
139 | 142 | def runsymbol(context, mapping, key): |
@@ -234,12 +237,8 b' def fill(context, mapping, args):' | |||
|
234 | 237 | except ValueError: |
|
235 | 238 | raise error.ParseError(_("fill expects an integer width")) |
|
236 | 239 | try: |
|
237 |
initindent = stringify(args[2] |
|
|
238 |
|
|
|
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))) | |
|
240 | initindent = stringify(_evalifliteral(args[2], context, mapping)) | |
|
241 | hangindent = stringify(_evalifliteral(args[3], context, mapping)) | |
|
243 | 242 | except IndexError: |
|
244 | 243 | pass |
|
245 | 244 | |
@@ -285,8 +284,9 b' def get(context, mapping, args):' | |||
|
285 | 284 | |
|
286 | 285 | def _evalifliteral(arg, context, mapping): |
|
287 | 286 | t = stringify(arg[0](context, mapping, arg[1])) |
|
288 | if arg[0] == runstring: | |
|
289 |
yield runtemplate(context, mapping, |
|
|
287 | if arg[0] == runstring or arg[0] == runrawstring: | |
|
288 | yield runtemplate(context, mapping, | |
|
289 | compiletemplate(t, context, strtoken='rawstring')) | |
|
290 | 290 | else: |
|
291 | 291 | yield t |
|
292 | 292 | |
@@ -338,7 +338,7 b' def join(context, mapping, args):' | |||
|
338 | 338 | |
|
339 | 339 | joiner = " " |
|
340 | 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 | 343 | first = True |
|
344 | 344 | for x in joinset: |
@@ -447,9 +447,9 b' def strip(context, mapping, args):' | |||
|
447 | 447 | if not (1 <= len(args) <= 2): |
|
448 | 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 | 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 | 453 | return text.strip(chars) |
|
454 | 454 | return text.strip() |
|
455 | 455 | |
@@ -460,13 +460,12 b' def sub(context, mapping, args):' | |||
|
460 | 460 | |
|
461 | 461 | pat = stringify(args[0][0](context, mapping, args[0][1])) |
|
462 | 462 | rpl = stringify(args[1][0](context, mapping, args[1][1])) |
|
463 |
src = stringify(args[2] |
|
|
464 | src = stringify(runtemplate(context, mapping, | |
|
465 | compiletemplate(src, context))) | |
|
463 | src = stringify(_evalifliteral(args[2], context, mapping)) | |
|
466 | 464 | yield re.sub(pat, rpl, src) |
|
467 | 465 | |
|
468 | 466 | methods = { |
|
469 | 467 | "string": lambda e, c: (runstring, e[1]), |
|
468 | "rawstring": lambda e, c: (runrawstring, e[1]), | |
|
470 | 469 | "symbol": lambda e, c: (runsymbol, e[1]), |
|
471 | 470 | "group": lambda e, c: compileexp(e[1], c), |
|
472 | 471 | # ".": buildmember, |
@@ -1633,6 +1633,92 b' Test string escaping:' | |||
|
1633 | 1633 | <>\n<]> |
|
1634 | 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 | 1722 | Test recursive evaluation: |
|
1637 | 1723 | |
|
1638 | 1724 | $ hg init r |
@@ -1645,6 +1731,39 b' Test recursive evaluation:' | |||
|
1645 | 1731 | $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n' |
|
1646 | 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 | 1767 | Test branches inside if statement: |
|
1649 | 1768 | |
|
1650 | 1769 | $ hg log -r 0 --template '{if(branches, "yes", "no")}\n' |
@@ -1655,43 +1774,56 b' Test shortest(node) function:' | |||
|
1655 | 1774 | $ echo b > b |
|
1656 | 1775 | $ hg ci -qAm b |
|
1657 | 1776 | $ hg log --template '{shortest(node)}\n' |
|
1658 | d97c | |
|
1777 | e777 | |
|
1778 | bcc7 | |
|
1659 | 1779 | f776 |
|
1660 | 1780 | $ hg log --template '{shortest(node, 10)}\n' |
|
1661 | d97c383ae3 | |
|
1781 | e777603221 | |
|
1782 | bcc7ff960b | |
|
1662 | 1783 | f7769ec2ab |
|
1663 | 1784 | |
|
1664 | 1785 | Test pad function |
|
1665 | 1786 | |
|
1666 | 1787 | $ hg log --template '{pad(rev, 20)} {author|user}\n' |
|
1667 |
|
|
|
1788 | 2 test | |
|
1789 | 1 {node|short} | |
|
1668 | 1790 | 0 test |
|
1669 | 1791 | |
|
1670 | 1792 | $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n' |
|
1671 |
|
|
|
1793 | 2 test | |
|
1794 | 1 {node|short} | |
|
1672 | 1795 | 0 test |
|
1673 | 1796 | |
|
1674 | 1797 | $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n' |
|
1675 |
|
|
|
1798 | 2------------------- test | |
|
1799 | 1------------------- {node|short} | |
|
1676 | 1800 | 0------------------- test |
|
1677 | 1801 | |
|
1678 | 1802 | Test ifcontains function |
|
1679 | 1803 | |
|
1680 | 1804 | $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n' |
|
1805 | 2 did not add a | |
|
1681 | 1806 | 1 did not add a |
|
1682 | 1807 | 0 added a |
|
1683 | 1808 | |
|
1684 | 1809 | Test revset function |
|
1685 | 1810 | |
|
1686 | 1811 | $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n' |
|
1687 |
|
|
|
1812 | 2 current rev | |
|
1813 | 1 not current rev | |
|
1688 | 1814 | 0 not current rev |
|
1689 | 1815 | |
|
1690 | 1816 | $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n' |
|
1817 | 2 Parents: 1 | |
|
1691 | 1818 | 1 Parents: 0 |
|
1692 | 1819 | 0 Parents: |
|
1693 | 1820 | |
|
1694 | 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 | 1827 | Rev: 1 |
|
1696 | 1828 | Ancestor: 0 |
|
1697 | 1829 | Ancestor: 1 |
@@ -1704,5 +1836,15 b' Test current bookmark templating' | |||
|
1704 | 1836 | $ hg book foo |
|
1705 | 1837 | $ hg book bar |
|
1706 | 1838 | $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n" |
|
1707 |
|
|
|
1839 | 2 bar* foo | |
|
1840 | 1 | |
|
1708 | 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