Support diff -f
AKA --show-function-line
diff --git a/tests/diff.test b/tests/diff.test
index bbef9d3..ddca476 100644
--- a/tests/diff.test
+++ b/tests/diff.test
@@ -55,6 +55,54 @@
+3
' "" ""
+echo -e 'int bar() {
+}
+
+int foo() {
+}
+
+int baz() {
+ 1
+ {2
+ 3
+ 4
+ foo
+}
+'> a
+echo -e 'int barbar() {
+}
+
+int foo() {
+}
+
+int baz() {
+ 1a
+ {2
+ 3
+ 4
+ bar
+}
+'> b
+testcmd 'show function' "--show-function-line=' {$' -U1 -L lll -L rrr a b" \
+'--- lll
++++ rrr
+@@ -1,2 +1,2 @@
+-int bar() {
++int barbar() {
+ }
+@@ -7,3 +7,3 @@ int foo() {
+ int baz() {
+- 1
++ 1a
+ {2
+@@ -11,3 +11,3 @@ int baz() {
+ 4
+- foo
++ bar
+ }
+' \
+'' ''
+
seq 1 100000 > one
seq 1 4 100000 > two
testcmd 'big hunk' '-u --label nope --label nope one two' \
diff --git a/toys/pending/diff.c b/toys/pending/diff.c
index 0ea8fc3..f12b4a3 100644
--- a/toys/pending/diff.c
+++ b/toys/pending/diff.c
@@ -8,18 +8,19 @@
*
* Deviations from posix: always does -u
-USE_DIFF(NEWTOY(diff, "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):L(label)*N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_DIFF(NEWTOY(diff, "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
config DIFF
bool "diff"
default n
help
- usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2
+ usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] [-F REGEX ] FILE1 FILE2
-a Treat all files as text
-b Ignore changes in the amount of whitespace
-B Ignore changes whose lines are all blank
-d Try hard to find a smaller set of changes
+ -F Show the most recent line matching the regex
-i Ignore case differences
-L Use LABEL instead of the filename in the unified header
-N Treat absent files as empty
@@ -48,7 +49,7 @@
GLOBALS(
long U;
struct arg_list *L;
- char *S, *new_line_format, *old_line_format, *unchanged_line_format;
+ char *F, *S, *new_line_format, *old_line_format, *unchanged_line_format;
int dir_num, size, is_binary, differ, change, len[2], *offset[2];
struct stat st[2];
@@ -383,6 +384,33 @@
return create_j_vector();
}
+static void print_line_matching_regex(int a, regex_t *reg, int *off_set, FILE *fp) {
+ int i = 0, j = 0, line_buf_size = 100, cc = 0;
+ char* line = xzalloc(line_buf_size * sizeof(char));
+ for (i = a; a > 0; --i) {
+ int line_len = 0;
+ if (fseek(fp, off_set[i - 1], SEEK_SET)) perror_exit("fseek failed");
+ for (j = 0; j < (off_set[i] - off_set[i - 1]); j++) {
+ cc = fgetc(fp);
+ if (cc == EOF || cc == '\n') {
+ break;
+ }
+ ++line_len;
+ if (line_len >= line_buf_size) {
+ line_buf_size = line_buf_size * 11 / 10;
+ line = xrealloc(line, line_buf_size*sizeof(char));
+ }
+ line[j] = cc;
+ }
+ line[line_len] = '\0';
+ if (!regexec0(reg, line, line_len, 0, NULL, 0)) {
+ printf(" %s", line);
+ break;
+ }
+ }
+ free(line);
+}
+
static void print_diff(int a, int b, char c, int *off_set, FILE *fp)
{
int i, j, cc, cl;
@@ -557,12 +585,17 @@
struct diff *d;
struct arg_list *llist = TT.L;
int *J;
+ regex_t reg;
TT.offset[0] = TT.offset[1] = NULL;
J = diff(files);
if (!J) return; //No need to compare, have to status only
+ if (TT.F) {
+ xregcomp(®, TT.F, 0);
+ }
+
d = xzalloc(size *sizeof(struct diff));
do {
ignore_white = 0;
@@ -656,6 +689,9 @@
else putchar(' ');
printf("@@");
if (FLAG(color)) printf("\e[0m");
+ if (TT.F) {
+ print_line_matching_regex(ptr1->suff-1, ®, TT.offset[0], TT.file[0].fp);
+ }
putchar('\n');
}