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:
commit
5fb249aec7
@ -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.
|
||||
|
||||
|
@ -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
32
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.
|
||||
*/
|
||||
|
1
grep.h
1
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];
|
||||
|
@ -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 &&
|
||||
(
|
||||
|
Loading…
Reference in New Issue
Block a user