grep: -W: don't extend context to trailing empty lines

Empty lines between functions are shown by grep -W, as it considers them to be part of the function preceding them. They are not interesting in most languages. The previous patches stopped showing them for diff -W. Stop showing empty lines trailing a function with grep -W. Grep scans the lines of a buffer from top to bottom and prints matching lines immediately. Thus we need to peek ahead in order to determine if an empty line is part of a function body and worth showing or not. Remember how far ahead we peeked in order to avoid having to do so repeatedly when handling multiple consecutive empty lines. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed May 28, 2016 at 17:06 UTC 4aa2c4753d152aef810eaf3f3f4fa1df7035d9b0
2 files changed +27 -3
grep.c
+26 -2
@@ -1396,9 +1396,17 @@ static int fill_textconv_grep(struct userdiff_driver *driver,
1396 return 0;
1397 }
1398
1399 +static int is_empty_line(const char *bol, const char *eol)
1400 +{
1401 + while (bol < eol && isspace(*bol))
1402 + bol++;
1403 + return bol == eol;
1404 +}
1405 +
1406 static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int collect_hits)
1407 {
1408 char *bol;
1409 + char *peek_bol = NULL;
1410 unsigned long left;
1411 unsigned lno = 1;
1412 unsigned last_hit = 0;
@@ -1543,8 +1551,24 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
1551 show_function = 1;
1552 goto next_line;
1553 }
1546 - if (show_function && match_funcname(opt, gs, bol, eol))
1547 - show_function = 0;
1554 + if (show_function && (!peek_bol || peek_bol < bol)) {
1555 + unsigned long peek_left = left;
1556 + char *peek_eol = eol;
1557 +
1558 + /*
1559 + * Trailing empty lines are not interesting.
1560 + * Peek past them to see if they belong to the
1561 + * body of the current function.
1562 + */
1563 + peek_bol = bol;
1564 + while (is_empty_line(peek_bol, peek_eol)) {
1565 + peek_bol = peek_eol + 1;
1566 + peek_eol = end_of_line(peek_bol, &peek_left);
1567 + }
1568 +
1569 + if (match_funcname(opt, gs, peek_bol, peek_eol))
1570 + show_function = 0;
1571 + }
1572 if (show_function ||
1573 (last_hit && lno <= last_hit + opt->post_context)) {
1574 /* If the last hit is within the post context,
t/t7810-grep.sh
+1 -1
@@ -748,7 +748,7 @@ hello.c-#include <assert.h>
748 hello.c:#include <stdio.h>
749 EOF
750
751 -test_expect_failure 'grep -W shows no trailing empty lines' '
751 +test_expect_success 'grep -W shows no trailing empty lines' '
752 git grep -W stdio >actual &&
753 test_cmp expected actual
754 '