From ba8ea7496f2b95c49fccb72ed6b332afbd865e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Mon, 1 Aug 2011 19:20:53 +0200 Subject: [PATCH 1/2] grep: add option to show whole function as context Add a new option, -W, to show the whole surrounding function of a match. It uses the same regular expressions as -p and diff to find the beginning of sections. Currently it will not display comments in front of a function, but those that are following one. Despite this shortcoming it is already useful, e.g. to simply see a more complete applicable context or to extract whole functions. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Documentation/git-grep.txt | 6 ++++++ builtin/grep.c | 5 ++++- grep.c | 32 ++++++++++++++++++++++---------- grep.h | 1 + t/t7810-grep.sh | 14 ++++++++++++++ 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 07b3c6a086..6cd0c503f6 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -172,6 +172,12 @@ OPTIONS patch hunk headers (see 'Defining a custom hunk-header' in linkgit:gitattributes[5]). +-W:: + Show the surrounding text from the previous line containing a + function name up to the one before the next function name, + effectively showing the whole function in which the match was + found. + -f :: Read patterns from , one per line. diff --git a/builtin/grep.c b/builtin/grep.c index cccf8da6d2..1fae66262f 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -838,6 +838,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) context_callback), OPT_BOOLEAN('p', "show-function", &opt.funcname, "show a line with the function name before matches"), + OPT_BOOLEAN('W', NULL, &opt.funcbody, + "show the surrounding function"), OPT_GROUP(""), OPT_CALLBACK('f', NULL, &opt, "file", "read patterns from file", file_callback), @@ -980,7 +982,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) use_threads = 0; if (use_threads) { - if (opt.pre_context || opt.post_context || opt.file_break) + if (opt.pre_context || opt.post_context || opt.file_break || + opt.funcbody) skip_first_line = 1; start_threads(&opt); } diff --git a/grep.c b/grep.c index 04e9ba4ec4..26e8d8ec4c 100644 --- a/grep.c +++ b/grep.c @@ -724,7 +724,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol, if (opt->file_break && opt->last_shown == 0) { if (opt->show_hunk_mark) opt->output(opt, "\n", 1); - } else if (opt->pre_context || opt->post_context) { + } else if (opt->pre_context || opt->post_context || opt->funcbody) { if (opt->last_shown == 0) { if (opt->show_hunk_mark) { output_color(opt, "--", 2, opt->color_sep); @@ -819,10 +819,13 @@ static void show_funcname_line(struct grep_opt *opt, const char *name, } static void show_pre_context(struct grep_opt *opt, const char *name, char *buf, - char *bol, unsigned lno) + char *bol, char *end, unsigned lno) { unsigned cur = lno, from = 1, funcname_lno = 0; - int funcname_needed = opt->funcname; + int funcname_needed = !!opt->funcname; + + if (opt->funcbody && !match_funcname(opt, bol, end)) + funcname_needed = 2; if (opt->pre_context < lno) from = lno - opt->pre_context; @@ -830,7 +833,8 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf, from = opt->last_shown + 1; /* Rewind. */ - while (bol > buf && cur > from) { + while (bol > buf && + cur > (funcname_needed == 2 ? opt->last_shown + 1 : from)) { char *eol = --bol; while (bol > buf && bol[-1] != '\n') @@ -942,13 +946,15 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, int binary_match_only = 0; unsigned count = 0; int try_lookahead = 0; + int show_function = 0; enum grep_context ctx = GREP_CONTEXT_HEAD; xdemitconf_t xecfg; if (!opt->output) opt->output = std_output; - if (opt->pre_context || opt->post_context || opt->file_break) { + if (opt->pre_context || opt->post_context || opt->file_break || + opt->funcbody) { /* Show hunk marks, except for the first file. */ if (opt->last_shown) opt->show_hunk_mark = 1; @@ -1004,7 +1010,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, */ if (try_lookahead && !(last_hit - && lno <= last_hit + opt->post_context) + && (show_function || + lno <= last_hit + opt->post_context)) && look_ahead(opt, &left, &lno, &bol)) break; eol = end_of_line(bol, &left); @@ -1051,15 +1058,20 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, /* Hit at this line. If we haven't shown the * pre-context lines, we would need to show them. */ - if (opt->pre_context) - show_pre_context(opt, name, buf, bol, lno); + if (opt->pre_context || opt->funcbody) + show_pre_context(opt, name, buf, bol, eol, lno); else if (opt->funcname) show_funcname_line(opt, name, buf, bol, lno); show_line(opt, bol, eol, name, lno, ':'); last_hit = lno; + if (opt->funcbody) + show_function = 1; + goto next_line; } - else if (last_hit && - lno <= last_hit + opt->post_context) { + if (show_function && match_funcname(opt, bol, eol)) + show_function = 0; + if (show_function || + (last_hit && lno <= last_hit + opt->post_context)) { /* If the last hit is within the post context, * we need to show this line. */ diff --git a/grep.h b/grep.h index c5682973ea..ae50c45a4d 100644 --- a/grep.h +++ b/grep.h @@ -98,6 +98,7 @@ struct grep_opt { int color; int max_depth; int funcname; + int funcbody; char color_context[COLOR_MAXLEN]; char color_filename[COLOR_MAXLEN]; char color_function[COLOR_MAXLEN]; diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index a29ae45b39..0d600163c8 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -509,6 +509,20 @@ test_expect_success 'grep -p -B5' ' test_cmp expected actual ' +cat >expected <actual && + test_cmp expected actual +' + test_expect_success 'grep from a subdirectory to search wider area (1)' ' mkdir -p s && ( From 317f63c21c8eac46813eacf487485445f2f79a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Mon, 1 Aug 2011 19:22:52 +0200 Subject: [PATCH 2/2] grep: long context options Take long option names for -A (--after-context), -B (--before-context) and -C (--context) from GNU grep and add a similar long option name for -W (--function-context). Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Documentation/git-grep.txt | 26 +++++++++++++++++--------- builtin/grep.c | 8 ++++---- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 6cd0c503f6..af501d2424 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -155,15 +155,6 @@ OPTIONS Show the filename above the matches in that file instead of at the start of each shown line. --[ABC] :: - Show `context` trailing (`A` -- after), or leading (`B` - -- before), or both (`C` -- context) lines, and place a - line containing `--` between contiguous groups of - matches. - --:: - A shortcut for specifying `-C`. - -p:: --show-function:: Show the preceding line that contains the function name of @@ -172,7 +163,24 @@ OPTIONS patch hunk headers (see 'Defining a custom hunk-header' in linkgit:gitattributes[5]). +-:: +-C :: +--context :: + Show leading and trailing lines, and place a line + containing `--` between contiguous groups of matches. + +-A :: +--after-context :: + Show trailing lines, and place a line containing + `--` between contiguous groups of matches. + +-B :: +--before-context :: + Show leading lines, and place a line containing + `--` between contiguous groups of matches. + -W:: +--function-context:: Show the surrounding text from the previous line containing a function name up to the one before the next function name, effectively showing the whole function in which the match was diff --git a/builtin/grep.c b/builtin/grep.c index 1fae66262f..1851797540 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -827,18 +827,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix) OPT_BOOLEAN(0, "heading", &opt.heading, "show filename only once above matches from same file"), OPT_GROUP(""), - OPT_CALLBACK('C', NULL, &opt, "n", + OPT_CALLBACK('C', "context", &opt, "n", "show context lines before and after matches", context_callback), - OPT_INTEGER('B', NULL, &opt.pre_context, + OPT_INTEGER('B', "before-context", &opt.pre_context, "show context lines before matches"), - OPT_INTEGER('A', NULL, &opt.post_context, + OPT_INTEGER('A', "after-context", &opt.post_context, "show context lines after matches"), OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM", context_callback), OPT_BOOLEAN('p', "show-function", &opt.funcname, "show a line with the function name before matches"), - OPT_BOOLEAN('W', NULL, &opt.funcbody, + OPT_BOOLEAN('W', "function-context", &opt.funcbody, "show the surrounding function"), OPT_GROUP(""), OPT_CALLBACK('f', NULL, &opt, "file",