Hello!
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.
I've attached a patch to reset ANSI color to the default at the end of
every line and restart it at the beginning of the next. It patches
normal and context mode. Side-by-side already worked in my testing.
I hope it's useful to you. Please let me know if there are changes you
would like made before you can accept it.
--Dennis Lambe Jr.
--- a/src/normal.c
+++ b/src/normal.c
@@ -60,12 +60,11 @@
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 +76,11 @@
/* 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);
}
--- a/src/context.c
+++ b/src/context.c
@@ -43,8 +43,11 @@
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 +74,10 @@
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);
+ fprintf (outfile, "\n");
}
/* Print a header for a context diff, with the file names and dates. */
@@ -80,7 +85,6 @@
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 +95,6 @@
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 +222,10 @@
{
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 +243,7 @@
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 +260,10 @@
{
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 +281,7 @@
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 +389,17 @@
/* 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 +408,17 @@
/* 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);
--- a/tests/colors
+++ b/tests/colors
@@ -25,9 +25,9 @@
local de=$(printf "$e[${de}m")
local ln=$(printf "$e[${ln}m")
printf '%s' \
-"$hd--- a$tab$epoch_plus
-+++ b$tab$epoch_plus
-$rs${ln}@@ -1 +1 @@$rs
+"$hd--- a$tab$epoch_plus$rs
+$hd+++ b$tab$epoch_plus$rs
+${ln}@@ -1 +1 @@$rs
$de-a$rs
$ad+b$rs
"
@@ -42,9 +42,9 @@
local de=$(printf "$e[${de}m")
local ln=$(printf "$e[${ln}m")
printf '%s' \
-"$hd*** a$tab$epoch_posix_1003_1_2001
---- b$tab$epoch_posix_1003_1_2001
-$rs***************
+"$hd*** a$tab$epoch_posix_1003_1_2001$rs
+$hd--- b$tab$epoch_posix_1003_1_2001$rs
+***************
$ln*** 1 ****$rs
$de! a$rs
$ln--- 1 ----$rs