Merge branch 'rs/grep-function-context'

* rs/grep-function-context:
  grep: long context options
  grep: add option to show whole function as context
This commit is contained in:
Junio C Hamano 2011-08-11 11:03:09 -07:00
commit 5fb249aec7
5 changed files with 67 additions and 23 deletions

View file

@ -155,15 +155,6 @@ OPTIONS
Show the filename above the matches in that file instead of
at the start of each shown line.
-[ABC] <context>::
Show `context` trailing (`A` -- after), or leading (`B`
-- before), or both (`C` -- context) lines, and place a
line containing `--` between contiguous groups of
matches.
-<num>::
A shortcut for specifying `-C<num>`.
-p::
--show-function::
Show the preceding line that contains the function name of
@ -172,6 +163,29 @@ OPTIONS
patch hunk headers (see 'Defining a custom hunk-header' in
linkgit:gitattributes[5]).
-<num>::
-C <num>::
--context <num>::
Show <num> leading and trailing lines, and place a line
containing `--` between contiguous groups of matches.
-A <num>::
--after-context <num>::
Show <num> trailing lines, and place a line containing
`--` between contiguous groups of matches.
-B <num>::
--before-context <num>::
Show <num> 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
found.
-f <file>::
Read patterns from <file>, one per line.

View file

@ -827,17 +827,19 @@ 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 <n> context lines before and after matches",
context_callback),
OPT_INTEGER('B', NULL, &opt.pre_context,
OPT_INTEGER('B', "before-context", &opt.pre_context,
"show <n> context lines before matches"),
OPT_INTEGER('A', NULL, &opt.post_context,
OPT_INTEGER('A', "after-context", &opt.post_context,
"show <n> 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', "function-context", &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);
}

32
grep.c
View file

@ -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.
*/

1
grep.h
View file

@ -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];

View file

@ -509,6 +509,20 @@ test_expect_success 'grep -p -B5' '
test_cmp expected actual
'
cat >expected <<EOF
hello.c=int main(int argc, const char **argv)
hello.c-{
hello.c- printf("Hello world.\n");
hello.c: return 0;
hello.c- /* char ?? */
hello.c-}
EOF
test_expect_success 'grep -W' '
git grep -W return >actual &&
test_cmp expected actual
'
test_expect_success 'grep from a subdirectory to search wider area (1)' '
mkdir -p s &&
(