grep: improve errors for unmatched ( and )

Imagine you want to grep for (. Easy:

  $ git grep '('
  fatal: unmatched parenthesis

uhoh. This is plainly wrong. Unless you know specifically that

 (a) git grep has expression groups and '(' ... ')' are used for them.
 (b) you can use -e '(' to explicitly say '(' is what you are looking
     for, not the beginning of a group.

Similarly,

  $ git grep ')'
  fatal: incomplete pattern expression: )

is somehow worse. ")" is a complete regular expression pattern.
Of course, the error wants to say "group" here.
In this case it is also not "incomplete", it is unmatched.

Make them say

  $ ./git grep '('
  fatal: unmatched ( for expression group
  $ ./git grep ')'
  fatal: incomplete pattern expression group: )

which are clearer in indicating that it is not the expression that
is wrong (since no pattern had been parsed at all), but rather that
it is been misconstrued as a grouping operator.

Link: https://bugs.debian.org/1051205
Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ahelenia Ziemiańska 2024-03-23 14:18:08 +01:00 committed by Junio C Hamano
parent 3c2a3fdc38
commit 0d527842b7

4
grep.c
View file

@ -621,7 +621,7 @@ static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
*list = p->next; *list = p->next;
x = compile_pattern_or(list); x = compile_pattern_or(list);
if (!*list || (*list)->token != GREP_CLOSE_PAREN) if (!*list || (*list)->token != GREP_CLOSE_PAREN)
die("unmatched parenthesis"); die("unmatched ( for expression group");
*list = (*list)->next; *list = (*list)->next;
return x; return x;
default: default:
@ -792,7 +792,7 @@ void compile_grep_patterns(struct grep_opt *opt)
if (p) if (p)
opt->pattern_expression = compile_pattern_expr(&p); opt->pattern_expression = compile_pattern_expr(&p);
if (p) if (p)
die("incomplete pattern expression: %s", p->pattern); die("incomplete pattern expression group: %s", p->pattern);
if (opt->no_body_match && opt->pattern_expression) if (opt->no_body_match && opt->pattern_expression)
opt->pattern_expression = grep_not_expr(opt->pattern_expression); opt->pattern_expression = grep_not_expr(opt->pattern_expression);