not a very informative error message
Yuya Nishihara
yuya at tcha.org
Mon Aug 10 11:45:32 UTC 2015
On Sun, 09 Aug 2015 22:45:44 -0400, Matt Harbison wrote:
> On Sun, 09 Aug 2015 13:16:12 -0400, Gregory Szorc
> <gregory.szorc at gmail.com> wrote:
>
> > On Sun, Aug 9, 2015 at 1:25 AM, Yuya Nishihara <yuya at tcha.org> wrote:
> >
> >> On Sat, 08 Aug 2015 22:58:23 -0400, Matt Harbison wrote:
> >> > On Sat, 08 Aug 2015 22:13:04 -0400, Cameron Simpson <cs at zip.com.au>
> >> wrote:
> >> > > On 08Aug2015 21:11, Matt Harbison <mharbison72 at gmail.com> wrote:
> >> > >> On Fri, 07 Aug 2015 07:19:38 -0400, Neal Becker
> >> <ndbecker2 at gmail.com>
> >> > >> wrote:
> >> > >>
> >> > >>> $ hg id
> >> > >>> 1f8f96084e75+ (collision) tip
> >> > >>>
> >> > >>> $ hg cat -r 1f8f96084e75+ test_awgn.py > /dev/null
> >> > >> 01234567890123
> >> > >>
> >> > >>> hg: parse error at 13: not a prefix: end
> >>
> >> > I pretty much agree that it isn't helpful, but it looks like the same
> >> > parser code is used for revsets, filesets and templates. Therefore it
> >> > really can't know about common mistakes specific to one of these in
> >> order
> >> > to make suggestions. It's just parsing based on language tokens it
> >> has
> >> > been told about for which ever module is using it, and bails when it
> >> gets
> >> > confused. I'm not sure if this part can be made better.
> >> >
> >> > That said, it would be nice if it would say that the revision arg is
> >> bad.
> >> > Debugging a command that used a revision, files and a template would
> >> be a
> >> > headache. I wonder if we can catch the parse error and prefix the
> >> message
> >> > with 'revision:' or whatever. Bad commands are caught and offer a
> >> > suggestion if you misspell cat, for example. I'm not sure what would
> >> > happen if multiple --rev args are given, but we would be no worse off
> >> I
> >> > guess.
> >>
> >> Maybe a ParseError could have more verbose output:
> >>
> >> % hg log -r 1f8f96084e75+
> >> hg: parse error at 13: not a prefix: end
> >> 1f8f96084e75+
> >> ~^
> >
> > +1. I tried to implement this a while back, thinking it would be an easy
> > feature and gave up because it required some invasive changes for the
> > raised exceptions to capture context necessary for reporting. Maybe I
> > wasn't approaching the problem correctly. I'm sure Yuya would know better
> > than me.
No, I have no idea to implement it without touching ParseError. And we'll
have to refactor ParseError because it is created with different types of
arguments:
(message)
(message, "filename:lineno")
(context, "filename:lineno")
(message, pos)
> It seems like at least some paths can give reasonable feedback:
>
> $ ../hg log -r '1234#'
> hg: parse error at 4: syntax error in revset '1234#'
>
> (Though this is caught in revset.tokenize, prior to being run through
> parser. Parse and tokenize are both are called on the same line, so care
> needs to be taken if the solution is to catch ParseError outside of the
> parser to add on the string being parsed.)
I think the easiest (but ugly) hack is to reraise ParseError with the context
attached.
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -45,6 +45,10 @@ def _formatparse(write, inst):
(inst.args[1], inst.args[0]))
if (inst.args[0][0] == ' '):
write(_("unexpected leading whitespace\n"))
+ context = getattr(inst, 'context')
+ if context:
+ write(context + '\n')
+ write(' ' * inst.args[1] + '\033[1;32m^\033[m\n') # XXX want ui.label()
else:
write(_("hg: parse error: %s\n") % inst.args[0])
if similar:
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2651,9 +2651,13 @@ def foldconcat(tree):
def parse(spec, lookup=None):
p = parser.parser(elements)
- tree, pos = p.parse(tokenize(spec, lookup=lookup))
- if pos != len(spec):
- raise error.ParseError(_("invalid token"), pos)
+ try:
+ tree, pos = p.parse(tokenize(spec, lookup=lookup))
+ if pos != len(spec):
+ raise error.ParseError(_("invalid token"), pos)
+ except error.ParseError as inst:
+ inst.context = spec # XXX ugly
+ raise
return parser.simplifyinfixops(tree, ('or',))
def posttreebuilthook(tree, repo):
More information about the Mercurial
mailing list