summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 49de321)
raw | patch | inline | side by side (parent: 49de321)
author | René Scharfe <rene.scharfe@lsrfire.ath.cx> | |
Wed, 1 Jul 2009 22:06:34 +0000 (00:06 +0200) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Thu, 2 Jul 2009 02:16:49 +0000 (19:16 -0700) |
The new option -p instructs git grep to print the previous function
definition as a context line, similar to diff -p. Such context lines
are marked with an equal sign instead of a dash. This option
complements the existing context options -A, -B, -C.
Function definitions are detected using the same heuristic that diff
uses. User defined regular expressions are not supported, yet.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
definition as a context line, similar to diff -p. Such context lines
are marked with an equal sign instead of a dash. This option
complements the existing context options -A, -B, -C.
Function definitions are detected using the same heuristic that diff
uses. User defined regular expressions are not supported, yet.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-grep.txt | patch | blob | history | |
builtin-grep.c | patch | blob | history | |
grep.c | patch | blob | history | |
grep.h | patch | blob | history | |
t/t7002-grep.sh | patch | blob | history |
index fccb82deb48ec75d25f948e7caa69a44e09f5832..b3bb2836444fff2964deb47d1e8e2f6c36b1fe50 100644 (file)
-<num>::
A shortcut for specifying -C<num>.
+-p::
+--show-function::
+ Show the preceding line that contains the function name of
+ the match, unless the matching line is a function name itself.
+
-f <file>::
Read patterns from <file>, one per line.
diff --git a/builtin-grep.c b/builtin-grep.c
index 48998af9115379f97403e0aeb63ac46f041906eb..037452ec79475244f4cae7cfc936695e1de58a63 100644 (file)
--- a/builtin-grep.c
+++ b/builtin-grep.c
argc -= 2;
}
- if (opt->pre_context || opt->post_context) {
+ if (opt->pre_context || opt->post_context || opt->funcname) {
/*
* grep handles hunk marks between files, but we need to
* do that ourselves between multiple calls.
*/
if (opt->show_hunk_mark)
- write_or_die(1, "--\n", 3);
+ write_or_die(1, opt->funcname ? "==\n" : "--\n", 3);
else
opt->show_hunk_mark = 1;
}
"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_GROUP(""),
OPT_CALLBACK('f', NULL, &opt, "file",
"read patterns from file", file_callback),
argc--;
}
- if (opt.color && !opt.color_external)
+ if ((opt.color && !opt.color_external) || opt.funcname)
external_grep_allowed = 0;
if (!opt.pattern_list)
die("no pattern given.");
index 9b9d2e39f8ae71e6e9a394f2b0566d7a137082e2..3a5c138476e5bc643656ec7a6e41da9fa3168969 100644 (file)
--- a/grep.c
+++ b/grep.c
{
int rest = eol - bol;
- if (opt->pre_context || opt->post_context) {
+ if (opt->pre_context || opt->post_context || opt->funcname) {
if (opt->last_shown == 0) {
if (opt->show_hunk_mark)
- fputs("--\n", stdout);
+ fputs(opt->funcname ? "==\n" : "--\n", stdout);
else
opt->show_hunk_mark = 1;
- } else if (lno > opt->last_shown + 1)
- fputs("--\n", stdout);
+ } else if (lno > opt->last_shown + 1) {
+ if (opt->pre_context || opt->post_context)
+ fputs((sign == '=') ? "==\n" : "--\n", stdout);
+ else if (sign == '=')
+ fputs("==\n", stdout);
+ }
}
opt->last_shown = lno;
printf("%.*s\n", rest, bol);
}
+static int match_funcname(char *bol, char *eol)
+{
+ if (bol == eol)
+ return 0;
+ if (isalpha(*bol) || *bol == '_' || *bol == '$')
+ return 1;
+ return 0;
+}
+
+static void show_funcname_line(struct grep_opt *opt, const char *name,
+ char *buf, char *bol, unsigned lno)
+{
+ while (bol > buf) {
+ char *eol = --bol;
+
+ while (bol > buf && bol[-1] != '\n')
+ bol--;
+ lno--;
+
+ if (lno <= opt->last_shown)
+ break;
+
+ if (match_funcname(bol, eol)) {
+ show_line(opt, bol, eol, name, lno, '=');
+ break;
+ }
+ }
+}
+
static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
char *bol, unsigned lno)
{
- unsigned cur = lno, from = 1;
+ unsigned cur = lno, from = 1, funcname_lno = 0;
+ int funcname_needed = opt->funcname;
if (opt->pre_context < lno)
from = lno - opt->pre_context;
@@ -543,19 +577,28 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
/* Rewind. */
while (bol > buf && cur > from) {
- bol--;
+ char *eol = --bol;
+
while (bol > buf && bol[-1] != '\n')
bol--;
cur--;
+ if (funcname_needed && match_funcname(bol, eol)) {
+ funcname_lno = cur;
+ funcname_needed = 0;
+ }
}
+ /* We need to look even further back to find a function signature. */
+ if (opt->funcname && funcname_needed)
+ show_funcname_line(opt, name, buf, bol, cur);
+
/* Back forward. */
while (cur < lno) {
- char *eol = bol;
+ char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
while (*eol != '\n')
eol++;
- show_line(opt, bol, eol, name, cur, '-');
+ show_line(opt, bol, eol, name, cur, sign);
bol = eol + 1;
cur++;
}
*/
if (opt->pre_context)
show_pre_context(opt, name, buf, bol, lno);
+ else if (opt->funcname)
+ show_funcname_line(opt, name, buf, bol, lno);
if (!opt->count)
show_line(opt, bol, eol, name, lno, ':');
last_hit = lno;
index 730ffd6f531d99787f33ca3fc9b1f49be090ab7f..3f75e3a3d4d3136d850b8c0204206f5ac9459a1d 100644 (file)
--- a/grep.h
+++ b/grep.h
int pathname;
int null_following_name;
int color;
+ int funcname;
char color_match[COLOR_MAXLEN];
const char *color_external;
int regflags;
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 155bfdb7d75c17daae23229d87c7c3e84668f3a4..ef59ab9941ffb3bafc0bd45ebbee02e7a117c527 100755 (executable)
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
. ./test-lib.sh
+cat >hello.c <<EOF
+#include <stdio.h>
+int main(int argc, const char **argv)
+{
+ printf("Hello world.\n");
+ return 0;
+}
+EOF
+
test_expect_success setup '
{
echo foo mmap bar
echo zzz > z &&
mkdir t &&
echo test >t/t &&
- git add file w x y z t/t &&
+ git add file w x y z t/t hello.c &&
test_tick &&
git commit -m initial
'
test_expect_success 'grep with CE_VALID file' '
git update-index --assume-unchanged t/t &&
rm t/t &&
- test "$(git grep --no-ext-grep t)" = "t/t:test" &&
+ test "$(git grep --no-ext-grep test)" = "t/t:test" &&
git update-index --no-assume-unchanged t/t &&
git checkout t/t
'
+cat >expected <<EOF
+hello.c=int main(int argc, const char **argv)
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p' '
+ git grep -p return >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=int main(int argc, const char **argv)
+hello.c-{
+hello.c- printf("Hello world.\n");
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p -B5' '
+ git grep -p -B5 return >actual &&
+ test_cmp expected actual
+'
+
test_done