##// END OF EJS Templates
templater: add function to look up symbols used in template...
Yuya Nishihara -
r38374:d4fae9a0 default
parent child Browse files
Show More
@@ -2488,9 +2488,17 b' def debugtemplate(ui, repo, tmpl, **opts'
2488 if revs is None:
2488 if revs is None:
2489 tres = formatter.templateresources(ui, repo)
2489 tres = formatter.templateresources(ui, repo)
2490 t = formatter.maketemplater(ui, tmpl, resources=tres)
2490 t = formatter.maketemplater(ui, tmpl, resources=tres)
2491 if ui.verbose:
2492 kwds, funcs = t.symbolsuseddefault()
2493 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2494 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2491 ui.write(t.renderdefault(props))
2495 ui.write(t.renderdefault(props))
2492 else:
2496 else:
2493 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2497 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2498 if ui.verbose:
2499 kwds, funcs = displayer.t.symbolsuseddefault()
2500 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2501 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2494 for r in revs:
2502 for r in revs:
2495 displayer.show(repo[r], **pycompat.strkwargs(props))
2503 displayer.show(repo[r], **pycompat.strkwargs(props))
2496 displayer.close()
2504 displayer.close()
@@ -842,6 +842,51 b' class templater(object):'
842 x = _aliasrules.expand(self._aliasmap, x)
842 x = _aliasrules.expand(self._aliasmap, x)
843 return x
843 return x
844
844
845 def _findsymbolsused(self, tree, syms):
846 if not tree:
847 return
848 op = tree[0]
849 if op == 'symbol':
850 s = tree[1]
851 if s in syms[0]:
852 return # avoid recursion: s -> cache[s] -> s
853 syms[0].add(s)
854 if s in self.cache or s in self._map:
855 # s may be a reference for named template
856 self._findsymbolsused(self.load(s), syms)
857 return
858 if op in {'integer', 'string'}:
859 return
860 # '{arg|func}' == '{func(arg)}'
861 if op == '|':
862 syms[1].add(getsymbol(tree[2]))
863 self._findsymbolsused(tree[1], syms)
864 return
865 if op == 'func':
866 syms[1].add(getsymbol(tree[1]))
867 self._findsymbolsused(tree[2], syms)
868 return
869 for x in tree[1:]:
870 self._findsymbolsused(x, syms)
871
872 def symbolsuseddefault(self):
873 """Look up (keywords, filters/functions) referenced from the default
874 unnamed template
875
876 This may load additional templates from the map file.
877 """
878 return self.symbolsused('')
879
880 def symbolsused(self, t):
881 """Look up (keywords, filters/functions) referenced from the name
882 template 't'
883
884 This may load additional templates from the map file.
885 """
886 syms = (set(), set())
887 self._findsymbolsused(self.load(t), syms)
888 return syms
889
845 def renderdefault(self, mapping):
890 def renderdefault(self, mapping):
846 """Render the default unnamed template and return result as string"""
891 """Render the default unnamed template and return result as string"""
847 return self.render('', mapping)
892 return self.render('', mapping)
@@ -50,6 +50,8 b' Test division:'
50 (integer '5')
50 (integer '5')
51 (integer '2')))
51 (integer '2')))
52 (string '\n'))
52 (string '\n'))
53 * keywords:
54 * functions: mod
53 2 1
55 2 1
54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
56 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
55 (template
57 (template
@@ -65,6 +67,8 b' Test division:'
65 (negate
67 (negate
66 (integer '2'))))
68 (integer '2'))))
67 (string '\n'))
69 (string '\n'))
70 * keywords:
71 * functions: mod
68 -3 -1
72 -3 -1
69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
73 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
70 (template
74 (template
@@ -80,6 +84,8 b' Test division:'
80 (integer '5'))
84 (integer '5'))
81 (integer '2')))
85 (integer '2')))
82 (string '\n'))
86 (string '\n'))
87 * keywords:
88 * functions: mod
83 -3 1
89 -3 1
84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
90 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
85 (template
91 (template
@@ -97,6 +103,8 b' Test division:'
97 (negate
103 (negate
98 (integer '2'))))
104 (integer '2'))))
99 (string '\n'))
105 (string '\n'))
106 * keywords:
107 * functions: mod
100 2 -1
108 2 -1
101
109
102 Filters bind closer than arithmetic:
110 Filters bind closer than arithmetic:
@@ -111,6 +119,8 b' Filters bind closer than arithmetic:'
111 (symbol 'count'))
119 (symbol 'count'))
112 (integer '1'))
120 (integer '1'))
113 (string '\n'))
121 (string '\n'))
122 * keywords:
123 * functions: count, revset
114 0
124 0
115
125
116 But negate binds closer still:
126 But negate binds closer still:
@@ -123,6 +133,8 b' But negate binds closer still:'
123 (integer '3')
133 (integer '3')
124 (symbol 'stringify')))
134 (symbol 'stringify')))
125 (string '\n'))
135 (string '\n'))
136 * keywords:
137 * functions: stringify
126 hg: parse error: arithmetic only defined on integers
138 hg: parse error: arithmetic only defined on integers
127 [255]
139 [255]
128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
140 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
@@ -132,6 +144,8 b' But negate binds closer still:'
132 (integer '3'))
144 (integer '3'))
133 (symbol 'stringify'))
145 (symbol 'stringify'))
134 (string '\n'))
146 (string '\n'))
147 * keywords:
148 * functions: stringify
135 -3
149 -3
136
150
137 Filters bind as close as map operator:
151 Filters bind as close as map operator:
@@ -145,6 +159,8 b' Filters bind as close as map operator:'
145 (template
159 (template
146 (symbol 'line')
160 (symbol 'line')
147 (string '\n'))))
161 (string '\n'))))
162 * keywords: desc, line
163 * functions: splitlines
148 line 1
164 line 1
149 line 2
165 line 2
150
166
@@ -157,6 +173,8 b' Keyword arguments:'
157 (|
173 (|
158 (symbol 'bar')
174 (symbol 'bar')
159 (symbol 'baz'))))
175 (symbol 'baz'))))
176 * keywords: bar, foo
177 * functions: baz
160 hg: parse error: can't use a key-value pair in this context
178 hg: parse error: can't use a key-value pair in this context
161 [255]
179 [255]
162
180
@@ -2800,6 +2818,8 b' Error on syntax:'
2800 (template
2818 (template
2801 (group
2819 (group
2802 None))
2820 None))
2821 * keywords:
2822 * functions:
2803 hg: parse error: missing argument
2823 hg: parse error: missing argument
2804 [255]
2824 [255]
2805
2825
@@ -3369,6 +3389,8 b' Test dot operator precedence:'
3369 (symbol 'node'))
3389 (symbol 'node'))
3370 (symbol 'short'))
3390 (symbol 'short'))
3371 (string '\n'))
3391 (string '\n'))
3392 * keywords: manifest, node, rev
3393 * functions: formatnode, short
3372 89f4071fec70
3394 89f4071fec70
3373
3395
3374 (the following examples are invalid, but seem natural in parsing POV)
3396 (the following examples are invalid, but seem natural in parsing POV)
@@ -3390,6 +3412,8 b' Test dot operator precedence:'
3390 (symbol 'bar')
3412 (symbol 'bar')
3391 None))
3413 None))
3392 (string '\n'))
3414 (string '\n'))
3415 * keywords: foo
3416 * functions: bar
3393 [255]
3417 [255]
3394
3418
3395 Test evaluation of dot operator:
3419 Test evaluation of dot operator:
@@ -3480,12 +3504,16 b' Test integer literal:'
3480 (group
3504 (group
3481 (integer '0'))
3505 (integer '0'))
3482 (string '\n'))
3506 (string '\n'))
3507 * keywords:
3508 * functions:
3483 0
3509 0
3484 $ hg debugtemplate -v '{(123)}\n'
3510 $ hg debugtemplate -v '{(123)}\n'
3485 (template
3511 (template
3486 (group
3512 (group
3487 (integer '123'))
3513 (integer '123'))
3488 (string '\n'))
3514 (string '\n'))
3515 * keywords:
3516 * functions:
3489 123
3517 123
3490 $ hg debugtemplate -v '{(-4)}\n'
3518 $ hg debugtemplate -v '{(-4)}\n'
3491 (template
3519 (template
@@ -3493,6 +3521,8 b' Test integer literal:'
3493 (negate
3521 (negate
3494 (integer '4')))
3522 (integer '4')))
3495 (string '\n'))
3523 (string '\n'))
3524 * keywords:
3525 * functions:
3496 -4
3526 -4
3497 $ hg debugtemplate '{(-)}\n'
3527 $ hg debugtemplate '{(-)}\n'
3498 hg: parse error at 3: not a prefix: )
3528 hg: parse error at 3: not a prefix: )
@@ -3509,6 +3539,8 b' top-level integer literal is interpreted'
3509 (template
3539 (template
3510 (integer '1')
3540 (integer '1')
3511 (string '\n'))
3541 (string '\n'))
3542 * keywords:
3543 * functions:
3512 one
3544 one
3513 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3545 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3514 (template
3546 (template
@@ -3519,6 +3551,8 b' top-level integer literal is interpreted'
3519 (template
3551 (template
3520 (integer '1'))))
3552 (integer '1'))))
3521 (string '\n'))
3553 (string '\n'))
3554 * keywords:
3555 * functions: if
3522 one
3556 one
3523 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3557 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3524 (template
3558 (template
@@ -3526,6 +3560,8 b' top-level integer literal is interpreted'
3526 (integer '1')
3560 (integer '1')
3527 (symbol 'stringify'))
3561 (symbol 'stringify'))
3528 (string '\n'))
3562 (string '\n'))
3563 * keywords:
3564 * functions: stringify
3529 one
3565 one
3530
3566
3531 unless explicit symbol is expected:
3567 unless explicit symbol is expected:
@@ -3543,6 +3579,8 b' Test string literal:'
3543 (template
3579 (template
3544 (string 'string with no template fragment')
3580 (string 'string with no template fragment')
3545 (string '\n'))
3581 (string '\n'))
3582 * keywords:
3583 * functions:
3546 string with no template fragment
3584 string with no template fragment
3547 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3585 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3548 (template
3586 (template
@@ -3550,11 +3588,15 b' Test string literal:'
3550 (string 'template: ')
3588 (string 'template: ')
3551 (symbol 'rev'))
3589 (symbol 'rev'))
3552 (string '\n'))
3590 (string '\n'))
3591 * keywords: rev
3592 * functions:
3553 template: 0
3593 template: 0
3554 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3594 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3555 (template
3595 (template
3556 (string 'rawstring: {rev}')
3596 (string 'rawstring: {rev}')
3557 (string '\n'))
3597 (string '\n'))
3598 * keywords:
3599 * functions:
3558 rawstring: {rev}
3600 rawstring: {rev}
3559 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3601 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3560 (template
3602 (template
@@ -3562,6 +3604,8 b' Test string literal:'
3562 (symbol 'files')
3604 (symbol 'files')
3563 (string 'rawstring: {file}'))
3605 (string 'rawstring: {file}'))
3564 (string '\n'))
3606 (string '\n'))
3607 * keywords: files
3608 * functions:
3565 rawstring: {file}
3609 rawstring: {file}
3566
3610
3567 Test string escaping:
3611 Test string escaping:
@@ -4681,6 +4725,8 b' Templater supports aliases of symbol and'
4681 (string 'UTC')))
4725 (string 'UTC')))
4682 (symbol 'isodate'))
4726 (symbol 'isodate'))
4683 (string '\n'))
4727 (string '\n'))
4728 * keywords: date, node, rev
4729 * functions: isodate, localdate, short
4684 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4730 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4685
4731
4686 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4732 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
@@ -4699,6 +4745,8 b' Templater supports aliases of symbol and'
4699 (string ' ')
4745 (string ' ')
4700 (symbol 'file')
4746 (symbol 'file')
4701 (string '\n'))))
4747 (string '\n'))))
4748 * keywords: file, file_adds
4749 * functions:
4702 A a
4750 A a
4703
4751
4704 A unary function alias can be called as a filter:
4752 A unary function alias can be called as a filter:
@@ -4721,6 +4769,8 b' A unary function alias can be called as '
4721 (string 'UTC')))
4769 (string 'UTC')))
4722 (symbol 'isodate'))
4770 (symbol 'isodate'))
4723 (string '\n'))
4771 (string '\n'))
4772 * keywords: date
4773 * functions: isodate, localdate
4724 1970-01-12 13:46 +0000
4774 1970-01-12 13:46 +0000
4725
4775
4726 Aliases should be applied only to command arguments and templates in hgrc.
4776 Aliases should be applied only to command arguments and templates in hgrc.
General Comments 0
You need to be logged in to leave comments. Login now