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
|
Show the filename above the matches in that file instead of
|
||||||
at the start of each shown line.
|
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::
|
-p::
|
||||||
--show-function::
|
--show-function::
|
||||||
Show the preceding line that contains the function name of
|
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
|
patch hunk headers (see 'Defining a custom hunk-header' in
|
||||||
linkgit:gitattributes[5]).
|
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>::
|
-f <file>::
|
||||||
Read patterns from <file>, one per line.
|
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,
|
OPT_BOOLEAN(0, "heading", &opt.heading,
|
||||||
"show filename only once above matches from same file"),
|
"show filename only once above matches from same file"),
|
||||||
OPT_GROUP(""),
|
OPT_GROUP(""),
|
||||||
OPT_CALLBACK('C', NULL, &opt, "n",
|
OPT_CALLBACK('C', "context", &opt, "n",
|
||||||
"show <n> context lines before and after matches",
|
"show <n> context lines before and after matches",
|
||||||
context_callback),
|
context_callback),
|
||||||
OPT_INTEGER('B', NULL, &opt.pre_context,
|
OPT_INTEGER('B', "before-context", &opt.pre_context,
|
||||||
"show <n> context lines before matches"),
|
"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"),
|
"show <n> context lines after matches"),
|
||||||
OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
|
OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
|
||||||
context_callback),
|
context_callback),
|
||||||
OPT_BOOLEAN('p', "show-function", &opt.funcname,
|
OPT_BOOLEAN('p', "show-function", &opt.funcname,
|
||||||
"show a line with the function name before matches"),
|
"show a line with the function name before matches"),
|
||||||
|
OPT_BOOLEAN('W', "function-context", &opt.funcbody,
|
||||||
|
"show the surrounding function"),
|
||||||
OPT_GROUP(""),
|
OPT_GROUP(""),
|
||||||
OPT_CALLBACK('f', NULL, &opt, "file",
|
OPT_CALLBACK('f', NULL, &opt, "file",
|
||||||
"read patterns from file", file_callback),
|
"read patterns from file", file_callback),
|
||||||
@ -980,7 +982,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||||||
use_threads = 0;
|
use_threads = 0;
|
||||||
|
|
||||||
if (use_threads) {
|
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;
|
skip_first_line = 1;
|
||||||
start_threads(&opt);
|
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->file_break && opt->last_shown == 0) {
|
||||||
if (opt->show_hunk_mark)
|
if (opt->show_hunk_mark)
|
||||||
opt->output(opt, "\n", 1);
|
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->last_shown == 0) {
|
||||||
if (opt->show_hunk_mark) {
|
if (opt->show_hunk_mark) {
|
||||||
output_color(opt, "--", 2, opt->color_sep);
|
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,
|
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;
|
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)
|
if (opt->pre_context < lno)
|
||||||
from = lno - opt->pre_context;
|
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;
|
from = opt->last_shown + 1;
|
||||||
|
|
||||||
/* Rewind. */
|
/* Rewind. */
|
||||||
while (bol > buf && cur > from) {
|
while (bol > buf &&
|
||||||
|
cur > (funcname_needed == 2 ? opt->last_shown + 1 : from)) {
|
||||||
char *eol = --bol;
|
char *eol = --bol;
|
||||||
|
|
||||||
while (bol > buf && bol[-1] != '\n')
|
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;
|
int binary_match_only = 0;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
int try_lookahead = 0;
|
int try_lookahead = 0;
|
||||||
|
int show_function = 0;
|
||||||
enum grep_context ctx = GREP_CONTEXT_HEAD;
|
enum grep_context ctx = GREP_CONTEXT_HEAD;
|
||||||
xdemitconf_t xecfg;
|
xdemitconf_t xecfg;
|
||||||
|
|
||||||
if (!opt->output)
|
if (!opt->output)
|
||||||
opt->output = std_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. */
|
/* Show hunk marks, except for the first file. */
|
||||||
if (opt->last_shown)
|
if (opt->last_shown)
|
||||||
opt->show_hunk_mark = 1;
|
opt->show_hunk_mark = 1;
|
||||||
@ -1004,7 +1010,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
|
|||||||
*/
|
*/
|
||||||
if (try_lookahead
|
if (try_lookahead
|
||||||
&& !(last_hit
|
&& !(last_hit
|
||||||
&& lno <= last_hit + opt->post_context)
|
&& (show_function ||
|
||||||
|
lno <= last_hit + opt->post_context))
|
||||||
&& look_ahead(opt, &left, &lno, &bol))
|
&& look_ahead(opt, &left, &lno, &bol))
|
||||||
break;
|
break;
|
||||||
eol = end_of_line(bol, &left);
|
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
|
/* Hit at this line. If we haven't shown the
|
||||||
* pre-context lines, we would need to show them.
|
* pre-context lines, we would need to show them.
|
||||||
*/
|
*/
|
||||||
if (opt->pre_context)
|
if (opt->pre_context || opt->funcbody)
|
||||||
show_pre_context(opt, name, buf, bol, lno);
|
show_pre_context(opt, name, buf, bol, eol, lno);
|
||||||
else if (opt->funcname)
|
else if (opt->funcname)
|
||||||
show_funcname_line(opt, name, buf, bol, lno);
|
show_funcname_line(opt, name, buf, bol, lno);
|
||||||
show_line(opt, bol, eol, name, lno, ':');
|
show_line(opt, bol, eol, name, lno, ':');
|
||||||
last_hit = lno;
|
last_hit = lno;
|
||||||
|
if (opt->funcbody)
|
||||||
|
show_function = 1;
|
||||||
|
goto next_line;
|
||||||
}
|
}
|
||||||
else if (last_hit &&
|
if (show_function && match_funcname(opt, bol, eol))
|
||||||
lno <= last_hit + opt->post_context) {
|
show_function = 0;
|
||||||
|
if (show_function ||
|
||||||
|
(last_hit && lno <= last_hit + opt->post_context)) {
|
||||||
/* If the last hit is within the post context,
|
/* If the last hit is within the post context,
|
||||||
* we need to show this line.
|
* we need to show this line.
|
||||||
*/
|
*/
|
||||||
|
1
grep.h
1
grep.h
@ -98,6 +98,7 @@ struct grep_opt {
|
|||||||
int color;
|
int color;
|
||||||
int max_depth;
|
int max_depth;
|
||||||
int funcname;
|
int funcname;
|
||||||
|
int funcbody;
|
||||||
char color_context[COLOR_MAXLEN];
|
char color_context[COLOR_MAXLEN];
|
||||||
char color_filename[COLOR_MAXLEN];
|
char color_filename[COLOR_MAXLEN];
|
||||||
char color_function[COLOR_MAXLEN];
|
char color_function[COLOR_MAXLEN];
|
||||||
|
@ -509,6 +509,20 @@ test_expect_success 'grep -p -B5' '
|
|||||||
test_cmp expected actual
|
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)' '
|
test_expect_success 'grep from a subdirectory to search wider area (1)' '
|
||||||
mkdir -p s &&
|
mkdir -p s &&
|
||||||
(
|
(
|
||||||
|
Loading…
Reference in New Issue
Block a user