dandavison / delta

A syntax-highlighting pager for git, diff, grep, and blame output
https://dandavison.github.io/delta/
MIT License
24.62k stars 395 forks source link

🐛Clear to EOL, the loss of the last character, & empty-line highlighting #1021

Open WayneD opened 2 years ago

WayneD commented 2 years ago

Delta likes to output clear-to-eol character sequences at the end of each line in an attempt to color the trailing characters (which my chromeos terminal apparently ignores). This can cause a bug where the final character on a line of a wide diff line is lost when the terminal has the xterm/vt100 style of line wrapping (indicated by the xn termcap flag).

To be more explicit, if a line being diffed is exactly long enough to fill the terminal width, the final char on the line leaves the cursor at the end of the line (pending either more characters, which wrap, or some kind of line movement). Unfortunately, a clear-to-EOL escape sequence then turns the final character on the line into a space, losing information. For example, my terminal is 128-chars wide, and the following diff loses the trailing "8" from each long line (I use the --keep-plus-minus-markers setting):

width128-diff.txt

A proper fix would probably require delta to compute the current column position each time it is going to clear-to-eol and skip it when a termcap-xn terminal is in the nebulous state of being 1-past the column width but actually in the final column.

On a related note, I enabled --keep-plus-minus-markers because delta would not show me when an empty line was added or removed. I can now surmise that this is because my terminal doesn't color the empty lines via the clear-to-eol idiom, as that would apparently give them the lightest red/green background color. So, we should probably also have an option to make delta output spaces instead of a clear sequence when ending an green or a red line (I tried tabs, but while they can color the screen with fewer characters, my terminal is apparently confused by the 256-color ansi sequences, which makes the use of tabs later on the line color to inconsistent column positions). If this were fixed, I would give the non-plus/minus output mode another try.

WayneD commented 2 years ago

Actually, I just noticed that it is GNU screen that is the primary failure point in most of these issues -- my terminal is much better at getting them right (it even avoids the loss of the last character on the line when a clear-to-eol occurs in that nebulous xn wrap mode). They both get tab positions wrong after complex color escape sequences, though. I guess I should also look into some screen fixes. Or maybe just switch to tmux -- it also does a much better job.

th1000s commented 2 years ago

For side-by-side mode there already is --line-fill-method=spaces (or ansi), but since delta does not take the terminal width into account in unified mode it can't know the number of spaces, thus the ANSI sequence. This is also nice when resizing the terminal. As for terminal multiplexers, there is also Zellij.