summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDennis Lambe Jr <malsyned@malsyned.net>2018-12-29 13:04:10 -0800
committerJim Meyering <meyering@fb.com>2018-12-30 22:22:10 -0800
commitaaf0efa70d9a72175e7847df196cda21ab3bd3a9 (patch)
treee7483ef990b0a19484c0f56f60b35e6e65af9534 /src
parentb9e2f4f3b395c8eff525a95e00ca14e7dd44a5b4 (diff)
downloaddiffutils-aaf0efa70d9a72175e7847df196cda21ab3bd3a9.tar.gz
diff: adjust ANSI escapes for compatibility with less -R
GNU less can display ANSI-colored text with the -R flag, but this support has some limitations. One of them is that if an escape sequence starts on one line and ends on a different line, only the first line will be colored in less. As a result, when diff creates colored output with multi-line deletes or adds, less will only color the first line. This change resets ANSI color to the default at the end of each line and restarts it at the beginning of the next. It patches normal and context mode. Side-by-side already worked in my testing. * src/context.c (print_context_label, pr_context_hunk): As above. (pr_unidiff_hunk, print_context_header): Likewise. * src/normal.c (print_normal_hunk): Likewise. * tests/colors: Adjust existing tests to accommodate this. * NEWS (Improvements): Mention it. Proposed in http://bugs.gnu.org/31105
Diffstat (limited to 'src')
-rw-r--r--src/context.c37
-rw-r--r--src/normal.c12
2 files changed, 19 insertions, 30 deletions
diff --git a/src/context.c b/src/context.c
index 4dd882d..d1930d9 100644
--- a/src/context.c
+++ b/src/context.c
@@ -43,8 +43,9 @@ print_context_label (char const *mark,
char const *name,
char const *label)
{
+ set_color_context (HEADER_CONTEXT);
if (label)
- fprintf (outfile, "%s %s\n", mark, label);
+ fprintf (outfile, "%s %s", mark, label);
else
{
char buf[MAX (INT_STRLEN_BOUND (int) + 32,
@@ -71,8 +72,10 @@ print_context_label (char const *mark,
sprintf (buf, "%"PRIuMAX".%.9d", sec, nsec);
}
}
- fprintf (outfile, "%s %s\t%s\n", mark, name, buf);
+ fprintf (outfile, "%s %s\t%s", mark, name, buf);
}
+ set_color_context (RESET_CONTEXT);
+ putc ('\n', outfile);
}
/* Print a header for a context diff, with the file names and dates. */
@@ -80,7 +83,6 @@ print_context_label (char const *mark,
void
print_context_header (struct file_data inf[], char const *const *names, bool unidiff)
{
- set_color_context (HEADER_CONTEXT);
if (unidiff)
{
print_context_label ("---", &inf[0], names[0], file_label[0]);
@@ -91,7 +93,6 @@ print_context_header (struct file_data inf[], char const *const *names, bool uni
print_context_label ("***", &inf[0], names[0], file_label[0]);
print_context_label ("---", &inf[1], names[1], file_label[1]);
}
- set_color_context (RESET_CONTEXT);
}
/* Print an edit script in context format. */
@@ -219,11 +220,10 @@ pr_context_hunk (struct change *hunk)
{
struct change *next = hunk;
- if (first0 <= last0)
- set_color_context (DELETE_CONTEXT);
-
for (i = first0; i <= last0; i++)
{
+ set_color_context (DELETE_CONTEXT);
+
/* Skip past changes that apply (in file 0)
only to lines before line I. */
@@ -241,8 +241,7 @@ pr_context_hunk (struct change *hunk)
prefix = (next->inserted > 0 ? "!" : "-");
}
print_1_line_nl (prefix, &files[0].linbuf[i], true);
- if (i == last0)
- set_color_context (RESET_CONTEXT);
+ set_color_context (RESET_CONTEXT);
if (files[0].linbuf[i + 1][-1] == '\n')
putc ('\n', out);
}
@@ -259,11 +258,10 @@ pr_context_hunk (struct change *hunk)
{
struct change *next = hunk;
- if (first1 <= last1)
- set_color_context (ADD_CONTEXT);
-
for (i = first1; i <= last1; i++)
{
+ set_color_context (ADD_CONTEXT);
+
/* Skip past changes that apply (in file 1)
only to lines before line I. */
@@ -281,8 +279,7 @@ pr_context_hunk (struct change *hunk)
prefix = (next->deleted > 0 ? "!" : "+");
}
print_1_line_nl (prefix, &files[1].linbuf[i], true);
- if (i == last1)
- set_color_context (RESET_CONTEXT);
+ set_color_context (RESET_CONTEXT);
if (files[1].linbuf[i + 1][-1] == '\n')
putc ('\n', out);
}
@@ -390,19 +387,17 @@ pr_unidiff_hunk (struct change *hunk)
/* For each difference, first output the deleted part. */
k = next->deleted;
- if (k)
- set_color_context (DELETE_CONTEXT);
while (k--)
{
char const * const *line = &files[0].linbuf[i++];
+ set_color_context (DELETE_CONTEXT);
putc ('-', out);
if (initial_tab && ! (suppress_blank_empty && **line == '\n'))
putc ('\t', out);
print_1_line_nl (NULL, line, true);
- if (!k)
- set_color_context (RESET_CONTEXT);
+ set_color_context (RESET_CONTEXT);
if (line[1][-1] == '\n')
putc ('\n', out);
@@ -411,19 +406,17 @@ pr_unidiff_hunk (struct change *hunk)
/* Then output the inserted part. */
k = next->inserted;
- if (k)
- set_color_context (ADD_CONTEXT);
while (k--)
{
char const * const *line = &files[1].linbuf[j++];
+ set_color_context (ADD_CONTEXT);
putc ('+', out);
if (initial_tab && ! (suppress_blank_empty && **line == '\n'))
putc ('\t', out);
print_1_line_nl (NULL, line, true);
- if (!k)
- set_color_context (RESET_CONTEXT);
+ set_color_context (RESET_CONTEXT);
if (line[1][-1] == '\n')
putc ('\n', out);
diff --git a/src/normal.c b/src/normal.c
index c6aac07..bdb718b 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -59,13 +59,11 @@ print_normal_hunk (struct change *hunk)
/* Print the lines that the first file has. */
if (changes & OLD)
{
- if (first0 <= last0)
- set_color_context (DELETE_CONTEXT);
for (i = first0; i <= last0; i++)
{
+ set_color_context (DELETE_CONTEXT);
print_1_line_nl ("<", &files[0].linbuf[i], true);
- if (i == last0)
- set_color_context (RESET_CONTEXT);
+ set_color_context (RESET_CONTEXT);
if (files[0].linbuf[i + 1][-1] == '\n')
putc ('\n', outfile);
}
@@ -77,13 +75,11 @@ print_normal_hunk (struct change *hunk)
/* Print the lines that the second file has. */
if (changes & NEW)
{
- if (first1 <= last1)
- set_color_context (ADD_CONTEXT);
for (i = first1; i <= last1; i++)
{
+ set_color_context (ADD_CONTEXT);
print_1_line_nl (">", &files[1].linbuf[i], true);
- if (i == last1)
- set_color_context (RESET_CONTEXT);
+ set_color_context (RESET_CONTEXT);
if (files[1].linbuf[i + 1][-1] == '\n')
putc ('\n', outfile);
}