diff: fix "multiple regexp" semantics to find hunk header comment
When multiple regular expressions are concatenated with "\n", they were traditionally AND'ed together, and only a line that matches _all_ of them is taken as a match. This however is unwieldy when multiple regexp feature is used to specify alternatives. This fixes the semantics to take the first match. A nagative pattern, if matches, makes the line to fail as before. A match with a positive pattern will be the final match, and what it captures in $1 is used as the hunk header comment. We could write alternatives using "|" in ERE, but the machinery can only use captured $1 as the hunk header comment (or $0 if there is no match in $1), so you cannot write: "junk ( A | B ) | garbage ( C | D )" and expect both "junk" and "garbage" to get stripped with the existing code. With this fix, you can write it as: "junk ( A | B ) \n garbage ( C | D )" and the way capture works would match the user expectation more naturally. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
1883a0d3b7
commit
3d8dccd74a
2
diff.c
2
diff.c
@ -1414,7 +1414,7 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
|
|||||||
{ "pascal",
|
{ "pascal",
|
||||||
"^((procedure|function|constructor|destructor|interface|"
|
"^((procedure|function|constructor|destructor|interface|"
|
||||||
"implementation|initialization|finalization)[ \t]*.*)$"
|
"implementation|initialization|finalization)[ \t]*.*)$"
|
||||||
"|"
|
"\n"
|
||||||
"^(.*=[ \t]*(class|record).*)$",
|
"^(.*=[ \t]*(class|record).*)$",
|
||||||
REG_EXTENDED },
|
REG_EXTENDED },
|
||||||
{ "php", "^[\t ]*((function|class).*)", REG_EXTENDED },
|
{ "php", "^[\t ]*((function|class).*)", REG_EXTENDED },
|
||||||
|
@ -194,26 +194,29 @@ static long ff_regexp(const char *line, long len,
|
|||||||
char *line_buffer = xstrndup(line, len); /* make NUL terminated */
|
char *line_buffer = xstrndup(line, len); /* make NUL terminated */
|
||||||
struct ff_regs *regs = priv;
|
struct ff_regs *regs = priv;
|
||||||
regmatch_t pmatch[2];
|
regmatch_t pmatch[2];
|
||||||
int result = 0, i;
|
int i;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
for (i = 0; i < regs->nr; i++) {
|
for (i = 0; i < regs->nr; i++) {
|
||||||
struct ff_reg *reg = regs->array + i;
|
struct ff_reg *reg = regs->array + i;
|
||||||
if (reg->negate ^ !!regexec(®->re,
|
if (!regexec(®->re, line_buffer, 2, pmatch, 0)) {
|
||||||
line_buffer, 2, pmatch, 0)) {
|
if (reg->negate)
|
||||||
free(line_buffer);
|
goto fail;
|
||||||
return -1;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (regs->nr <= i)
|
||||||
|
goto fail;
|
||||||
i = pmatch[1].rm_so >= 0 ? 1 : 0;
|
i = pmatch[1].rm_so >= 0 ? 1 : 0;
|
||||||
line += pmatch[i].rm_so;
|
line += pmatch[i].rm_so;
|
||||||
result = pmatch[i].rm_eo - pmatch[i].rm_so;
|
result = pmatch[i].rm_eo - pmatch[i].rm_so;
|
||||||
if (result > buffer_size)
|
if (result > buffer_size)
|
||||||
result = buffer_size;
|
result = buffer_size;
|
||||||
else
|
else
|
||||||
while (result > 0 && (isspace(line[result - 1]) ||
|
while (result > 0 && (isspace(line[result - 1])))
|
||||||
line[result - 1] == '\n'))
|
|
||||||
result--;
|
result--;
|
||||||
memcpy(buffer, line, result);
|
memcpy(buffer, line, result);
|
||||||
|
fail:
|
||||||
free(line_buffer);
|
free(line_buffer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user