diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -245,14 +245,16 @@ except error.ParseError as inst: if len(inst.args) > 1: # has location loc = inst.args[1] - # TODO: Opportunity for improvement! If there is a newline in the - # template, this hint does not point to the right place, so skip. - if '\n' not in tmpl: - # 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") - # to line up the caret with the location of the error. - inst.hint = tmpl + '\n' + ' ' * (loc) + '^ ' + _('here') + # if there are newlines in front of the location of the error, + # offset the caret location by that number, since we will next + # replace newlines with the two-char literal r'\n'. + offset = tmpl[:loc].count('\n') + tmpl = tmpl.replace('\n', r'\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") + # to line up the caret with the location of the error. + inst.hint = tmpl + '\n' + ' ' * (loc + offset) + '^ ' + _('here') raise yield ('end', None, pos) diff --git a/tests/test-parse-errors.t b/tests/test-parse-errors.t --- a/tests/test-parse-errors.t +++ b/tests/test-parse-errors.t @@ -16,4 +16,7 @@ > {shortest(node} > line4\nline5' hg: parse error at 28: unexpected token: end + (line 1\nline2\n{shortest(node}\nline4 + ^ here) [255] +