[PATCH] templater: fix position of terminator character in error message

Yuya Nishihara yuya at tcha.org
Sun Mar 4 14:22:29 UTC 2018


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1520165030 18000
#      Sun Mar 04 07:03:50 2018 -0500
# Node ID dad68a609114750b5963a8e46563a0b73620156f
# Parent  2a258985ffeb5ccdef17f437a6dc50cce68f6f8e
templater: fix position of terminator character in error message

Since a template expression starts after the '{' character, the expression
should be considered to end immediately before the terminator '{'.

diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
--- a/mercurial/revsetlang.py
+++ b/mercurial/revsetlang.py
@@ -543,16 +543,14 @@ def parse(spec, lookup=None):
         return _parsewith(spec, lookup=lookup)
     except error.ParseError as inst:
         if len(inst.args) > 1:  # has location
-            # Add 1 to location because unlike templates, revset parse errors
-            # point to the char where the error happened, not the char after.
-            loc = inst.args[1] + 1
+            loc = inst.args[1]
             # Remove newlines -- spaces are equivalent whitespace.
             spec = spec.replace('\n', ' ')
             # We want the caret to point to the place in the template that
             # failed to parse, but in a hint we get a open paren at the
             # start. Therefore, we print "loc + 1" spaces (instead of "loc")
             # to line up the caret with the location of the error.
-            inst.hint = spec + '\n' + ' ' * loc + '^ ' + _('here')
+            inst.hint = spec + '\n' + ' ' * (loc + 1) + '^ ' + _('here')
         raise
 
 def _quote(s):
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -145,7 +145,7 @@ def tokenize(program, start, end, term=N
             yield ('symbol', sym, s)
             pos -= 1
         elif c == term:
-            yield ('end', None, pos + 1)
+            yield ('end', None, pos)
             return
         else:
             raise error.ParseError(_("syntax error"), pos)
@@ -237,9 +237,10 @@ def _scantemplate(tmpl, start, stop, quo
                 return
 
             parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}'))
-            if not tmpl.endswith('}', n + 1, pos):
+            if not tmpl.startswith('}', pos):
                 raise error.ParseError(_("invalid token"), pos)
             yield ('template', parseres, n)
+            pos += 1
 
         if quote:
             raise error.ParseError(_("unterminated string"), start)
@@ -253,9 +254,10 @@ def _scantemplate(tmpl, start, stop, quo
             tmpl = tmpl.replace('\n', br'\n')
             # We want the caret to point to the place in the template that
             # failed to parse, but in a hint we get a open paren at the
-            # start. Therefore, we print "loc" spaces (instead of "loc - 1")
+            # start. Therefore, we print "loc + 1" spaces (instead of "loc")
             # to line up the caret with the location of the error.
-            inst.hint = tmpl + '\n' + ' ' * (loc + offset) + '^ ' + _('here')
+            inst.hint = (tmpl + '\n'
+                         + ' ' * (loc + 1 + offset) + '^ ' + _('here'))
         raise
     yield ('end', None, pos)
 
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -2767,26 +2767,26 @@ Error on syntax:
   $ hg log -T '{date'
   hg: parse error at 1: unterminated template expansion
   ({date
-   ^ here)
+    ^ here)
   [255]
   $ hg log -T '{date(}'
-  hg: parse error at 7: not a prefix: end
+  hg: parse error at 6: not a prefix: end
   ({date(}
          ^ here)
   [255]
   $ hg log -T '{date)}'
   hg: parse error at 5: invalid token
   ({date)}
-       ^ here)
+        ^ here)
   [255]
   $ hg log -T '{date date}'
   hg: parse error at 6: invalid token
   ({date date}
-        ^ here)
+         ^ here)
   [255]
 
   $ hg log -T '{}'
-  hg: parse error at 2: not a prefix: end
+  hg: parse error at 1: not a prefix: end
   ({}
     ^ here)
   [255]
@@ -2838,13 +2838,13 @@ Error in nested template:
   $ hg log -T '{"date'
   hg: parse error at 2: unterminated string
   ({"date
-    ^ here)
+     ^ here)
   [255]
 
   $ hg log -T '{"foo{date|?}"}'
   hg: parse error at 11: syntax error
   ({"foo{date|?}"}
-             ^ here)
+              ^ here)
   [255]
 
 Thrown an error if a template function doesn't exist
@@ -3377,7 +3377,7 @@ Test integer literal:
   $ hg debugtemplate '{(-)}\n'
   hg: parse error at 3: not a prefix: )
   ({(-)}\n
-     ^ here)
+      ^ here)
   [255]
   $ hg debugtemplate '{(-a)}\n'
   hg: parse error: negation needs an integer argument
@@ -3544,7 +3544,7 @@ escaped single quotes and errors:
   $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
   hg: parse error at 21: unterminated string
   ({if(rev, "{if(rev, \")}")}\n
-                       ^ here)
+                        ^ here)
   [255]
   $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
   hg: parse error: trailing \ in string
diff --git a/tests/test-export.t b/tests/test-export.t
--- a/tests/test-export.t
+++ b/tests/test-export.t
@@ -219,7 +219,7 @@ Invalid pattern in file name:
   $ hg export -o '%m{' tip
   hg: parse error at 3: unterminated template expansion
   (%m{
-     ^ here)
+      ^ here)
   [255]
   $ hg export -o '%\' tip
   abort: invalid format spec '%\' in output filename
diff --git a/tests/test-log.t b/tests/test-log.t
--- a/tests/test-log.t
+++ b/tests/test-log.t
@@ -2293,7 +2293,7 @@ Templater parse errors:
 
 simple error
   $ hg log -r . -T '{shortest(node}'
-  hg: parse error at 15: unexpected token: end
+  hg: parse error at 14: unexpected token: end
   ({shortest(node}
                  ^ here)
   [255]
@@ -2303,7 +2303,7 @@ multi-line template with error
   > line2
   > {shortest(node}
   > line4\nline5'
-  hg: parse error at 28: unexpected token: end
+  hg: parse error at 27: unexpected token: end
   (line 1\nline2\n{shortest(node}\nline4\nline5
                                 ^ here)
   [255]


More information about the Mercurial-devel mailing list