grep: show non-empty lines before functions with -W

Non-empty lines before a function definition are most likely comments for that function and thus relevant. Include them in function context. Such a non-empty line might also belong to the preceding function if there is no separating blank line. Stop extending the context upwards also at the next function line to make sure only one extra function body is shown at most. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Nov 18, 2017 at 19:08 UTC a5dc20b0701cee53b2c37a4aa3a339b48d5bb298
2 files changed +24 -5
grep.c
+23 -4
@@ -1476,33 +1476,52 @@ static void show_funcname_line(struct grep_opt *opt, struct grep_source *gs,
1476 }
1477 }
1478
1479 +static int is_empty_line(const char *bol, const char *eol);
1480 +
1481 static void show_pre_context(struct grep_opt *opt, struct grep_source *gs,
1482 char *bol, char *end, unsigned lno)
1483 {
1484 unsigned cur = lno, from = 1, funcname_lno = 0, orig_from;
1483 - int funcname_needed = !!opt->funcname;
1485 + int funcname_needed = !!opt->funcname, comment_needed = 0;
1486
1487 if (opt->pre_context < lno)
1488 from = lno - opt->pre_context;
1489 if (from <= opt->last_shown)
1490 from = opt->last_shown + 1;
1491 orig_from = from;
1490 - if (opt->funcbody && !match_funcname(opt, gs, bol, end)) {
1491 - funcname_needed = 1;
1492 + if (opt->funcbody) {
1493 + if (match_funcname(opt, gs, bol, end))
1494 + comment_needed = 1;
1495 + else
1496 + funcname_needed = 1;
1497 from = opt->last_shown + 1;
1498 }
1499
1500 /* Rewind. */
1501 while (bol > gs->buf && cur > from) {
1502 + char *next_bol = bol;
1503 char *eol = --bol;
1504
1505 while (bol > gs->buf && bol[-1] != '\n')
1506 bol--;
1507 cur--;
1508 + if (comment_needed && (is_empty_line(bol, eol) ||
1509 + match_funcname(opt, gs, bol, eol))) {
1510 + comment_needed = 0;
1511 + from = orig_from;
1512 + if (cur < from) {
1513 + cur++;
1514 + bol = next_bol;
1515 + break;
1516 + }
1517 + }
1518 if (funcname_needed && match_funcname(opt, gs, bol, eol)) {
1519 funcname_lno = cur;
1520 funcname_needed = 0;
1505 - from = orig_from;
1521 + if (opt->funcbody)
1522 + comment_needed = 1;
1523 + else
1524 + from = orig_from;
1525 }
1526 }
1527
t/t7810-grep.sh
+1 -1
@@ -785,7 +785,7 @@ test_expect_success 'grep -W with userdiff' '
785 git grep -W echo >function-context-userdiff-actual
786 '
787
788 -test_expect_failure ' includes preceding comment' '
788 +test_expect_success ' includes preceding comment' '
789 grep "# Say hello" function-context-userdiff-actual
790 '
791