Show More
@@ -213,35 +213,48 b' def _scantemplate(tmpl, start, stop, quo' | |||||
213 | unescape = [parser.unescapestr, pycompat.identity][raw] |
|
213 | unescape = [parser.unescapestr, pycompat.identity][raw] | |
214 | pos = start |
|
214 | pos = start | |
215 | p = parser.parser(elements) |
|
215 | p = parser.parser(elements) | |
216 | while pos < stop: |
|
216 | try: | |
217 | n = min((tmpl.find(c, pos, stop) for c in sepchars), |
|
217 | while pos < stop: | |
218 | key=lambda n: (n < 0, n)) |
|
218 | n = min((tmpl.find(c, pos, stop) for c in sepchars), | |
219 | if n < 0: |
|
219 | key=lambda n: (n < 0, n)) | |
220 | yield ('string', unescape(tmpl[pos:stop]), pos) |
|
220 | if n < 0: | |
221 | pos = stop |
|
221 | yield ('string', unescape(tmpl[pos:stop]), pos) | |
222 | break |
|
222 | pos = stop | |
223 | c = tmpl[n:n + 1] |
|
223 | break | |
224 | bs = 0 # count leading backslashes |
|
224 | c = tmpl[n:n + 1] | |
225 | if not raw: |
|
225 | bs = 0 # count leading backslashes | |
226 | bs = (n - pos) - len(tmpl[pos:n].rstrip('\\')) |
|
226 | if not raw: | |
227 | if bs % 2 == 1: |
|
227 | bs = (n - pos) - len(tmpl[pos:n].rstrip('\\')) | |
228 | # escaped (e.g. '\{', '\\\{', but not '\\{') |
|
228 | if bs % 2 == 1: | |
229 | yield ('string', unescape(tmpl[pos:n - 1]) + c, pos) |
|
229 | # escaped (e.g. '\{', '\\\{', but not '\\{') | |
230 | pos = n + 1 |
|
230 | yield ('string', unescape(tmpl[pos:n - 1]) + c, pos) | |
231 | continue |
|
231 | pos = n + 1 | |
232 | if n > pos: |
|
232 | continue | |
233 | yield ('string', unescape(tmpl[pos:n]), pos) |
|
233 | if n > pos: | |
234 | if c == quote: |
|
234 | yield ('string', unescape(tmpl[pos:n]), pos) | |
235 | yield ('end', None, n + 1) |
|
235 | if c == quote: | |
236 | return |
|
236 | yield ('end', None, n + 1) | |
|
237 | return | |||
237 |
|
238 | |||
238 | parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}')) |
|
239 | parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}')) | |
239 | if not tmpl.endswith('}', n + 1, pos): |
|
240 | if not tmpl.endswith('}', n + 1, pos): | |
240 | raise error.ParseError(_("invalid token"), pos) |
|
241 | raise error.ParseError(_("invalid token"), pos) | |
241 | yield ('template', parseres, n) |
|
242 | yield ('template', parseres, n) | |
242 |
|
243 | |||
243 | if quote: |
|
244 | if quote: | |
244 | raise error.ParseError(_("unterminated string"), start) |
|
245 | raise error.ParseError(_("unterminated string"), start) | |
|
246 | except error.ParseError as inst: | |||
|
247 | if len(inst.args) > 1: # has location | |||
|
248 | loc = inst.args[1] | |||
|
249 | # TODO: Opportunity for improvement! If there is a newline in the | |||
|
250 | # template, this hint does not point to the right place, so skip. | |||
|
251 | if '\n' not in tmpl: | |||
|
252 | # We want the caret to point to the place in the template that | |||
|
253 | # failed to parse, but in a hint we get a open paren at the | |||
|
254 | # start. Therefore, we print "loc" spaces (instead of "loc - 1") | |||
|
255 | # to line up the caret with the location of the error. | |||
|
256 | inst.hint = tmpl + '\n' + ' ' * (loc) + '^ ' + _('here') | |||
|
257 | raise | |||
245 | yield ('end', None, pos) |
|
258 | yield ('end', None, pos) | |
246 |
|
259 | |||
247 | def _unnesttemplatelist(tree): |
|
260 | def _unnesttemplatelist(tree): |
@@ -2766,19 +2766,29 b' Error on syntax:' | |||||
2766 |
|
2766 | |||
2767 | $ hg log -T '{date' |
|
2767 | $ hg log -T '{date' | |
2768 | hg: parse error at 1: unterminated template expansion |
|
2768 | hg: parse error at 1: unterminated template expansion | |
|
2769 | ({date | |||
|
2770 | ^ here) | |||
2769 | [255] |
|
2771 | [255] | |
2770 | $ hg log -T '{date(}' |
|
2772 | $ hg log -T '{date(}' | |
2771 | hg: parse error at 7: not a prefix: end |
|
2773 | hg: parse error at 7: not a prefix: end | |
|
2774 | ({date(} | |||
|
2775 | ^ here) | |||
2772 | [255] |
|
2776 | [255] | |
2773 | $ hg log -T '{date)}' |
|
2777 | $ hg log -T '{date)}' | |
2774 | hg: parse error at 5: invalid token |
|
2778 | hg: parse error at 5: invalid token | |
|
2779 | ({date)} | |||
|
2780 | ^ here) | |||
2775 | [255] |
|
2781 | [255] | |
2776 | $ hg log -T '{date date}' |
|
2782 | $ hg log -T '{date date}' | |
2777 | hg: parse error at 6: invalid token |
|
2783 | hg: parse error at 6: invalid token | |
|
2784 | ({date date} | |||
|
2785 | ^ here) | |||
2778 | [255] |
|
2786 | [255] | |
2779 |
|
2787 | |||
2780 | $ hg log -T '{}' |
|
2788 | $ hg log -T '{}' | |
2781 | hg: parse error at 2: not a prefix: end |
|
2789 | hg: parse error at 2: not a prefix: end | |
|
2790 | ({} | |||
|
2791 | ^ here) | |||
2782 | [255] |
|
2792 | [255] | |
2783 | $ hg debugtemplate -v '{()}' |
|
2793 | $ hg debugtemplate -v '{()}' | |
2784 | (template |
|
2794 | (template | |
@@ -2827,10 +2837,14 b' Error in nested template:' | |||||
2827 |
|
2837 | |||
2828 | $ hg log -T '{"date' |
|
2838 | $ hg log -T '{"date' | |
2829 | hg: parse error at 2: unterminated string |
|
2839 | hg: parse error at 2: unterminated string | |
|
2840 | ({"date | |||
|
2841 | ^ here) | |||
2830 | [255] |
|
2842 | [255] | |
2831 |
|
2843 | |||
2832 |
$ hg log -T '{"foo{date|?}"}' |
|
2844 | $ hg log -T '{"foo{date|?}"}' | |
2833 | hg: parse error at 11: syntax error |
|
2845 | hg: parse error at 11: syntax error | |
|
2846 | ({"foo{date|?}"} | |||
|
2847 | ^ here) | |||
2834 | [255] |
|
2848 | [255] | |
2835 |
|
2849 | |||
2836 | Thrown an error if a template function doesn't exist |
|
2850 | Thrown an error if a template function doesn't exist | |
@@ -3362,6 +3376,8 b' Test integer literal:' | |||||
3362 | -4 |
|
3376 | -4 | |
3363 | $ hg debugtemplate '{(-)}\n' |
|
3377 | $ hg debugtemplate '{(-)}\n' | |
3364 | hg: parse error at 3: not a prefix: ) |
|
3378 | hg: parse error at 3: not a prefix: ) | |
|
3379 | ({(-)}\n | |||
|
3380 | ^ here) | |||
3365 | [255] |
|
3381 | [255] | |
3366 | $ hg debugtemplate '{(-a)}\n' |
|
3382 | $ hg debugtemplate '{(-a)}\n' | |
3367 | hg: parse error: negation needs an integer argument |
|
3383 | hg: parse error: negation needs an integer argument | |
@@ -3527,6 +3543,8 b' escaped single quotes and errors:' | |||||
3527 | foo |
|
3543 | foo | |
3528 | $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n' |
|
3544 | $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n' | |
3529 | hg: parse error at 21: unterminated string |
|
3545 | hg: parse error at 21: unterminated string | |
|
3546 | ({if(rev, "{if(rev, \")}")}\n | |||
|
3547 | ^ here) | |||
3530 | [255] |
|
3548 | [255] | |
3531 | $ hg log -r 2 -T '{if(rev, \"\\"")}\n' |
|
3549 | $ hg log -r 2 -T '{if(rev, \"\\"")}\n' | |
3532 | hg: parse error: trailing \ in string |
|
3550 | hg: parse error: trailing \ in string |
@@ -218,6 +218,8 b' Invalid pattern in file name:' | |||||
218 | [255] |
|
218 | [255] | |
219 | $ hg export -o '%m{' tip |
|
219 | $ hg export -o '%m{' tip | |
220 | hg: parse error at 3: unterminated template expansion |
|
220 | hg: parse error at 3: unterminated template expansion | |
|
221 | (%m{ | |||
|
222 | ^ here) | |||
221 | [255] |
|
223 | [255] | |
222 | $ hg export -o '%\' tip |
|
224 | $ hg export -o '%\' tip | |
223 | abort: invalid format spec '%\' in output filename |
|
225 | abort: invalid format spec '%\' in output filename |
@@ -2289,6 +2289,23 b' Check that adding an arbitrary name show' | |||||
2289 | $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n' |
|
2289 | $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n' | |
2290 | foo |
|
2290 | foo | |
2291 |
|
2291 | |||
|
2292 | Templater parse errors: | |||
|
2293 | ||||
|
2294 | simple error | |||
|
2295 | $ hg log -r . -T '{shortest(node}' | |||
|
2296 | hg: parse error at 15: unexpected token: end | |||
|
2297 | ({shortest(node} | |||
|
2298 | ^ here) | |||
|
2299 | [255] | |||
|
2300 | ||||
|
2301 | multi-line template with error | |||
|
2302 | $ hg log -r . -T 'line 1 | |||
|
2303 | > line2 | |||
|
2304 | > {shortest(node} | |||
|
2305 | > line4\nline5' | |||
|
2306 | hg: parse error at 28: unexpected token: end | |||
|
2307 | [255] | |||
|
2308 | ||||
2292 | $ cd .. |
|
2309 | $ cd .. | |
2293 |
|
2310 | |||
2294 | hg log -f dir across branches |
|
2311 | hg log -f dir across branches |
General Comments 0
You need to be logged in to leave comments.
Login now