Skip to content

Conversation

gerhardol
Copy link
Member

@gerhardol gerhardol commented Feb 15, 2024

Fixes #11464
Fixes #11517

Proposed changes

TBD, opened to get feedback.
Description will be improved too, as well as screenshots.

--
FileViewer: Restructure HighlightService

Move handling of "normal" patches from the shared
DiffHighlightService to PatchHighlightService.

Various code cleanups.

This commit is a preparation for Git coloring and git-grep.

--
Git diff coloring

Use the coloring by git-diff instead of GE internal algorithm,
by using Git ANSI terminal escape sequences.
This enables for instance view moved code.

Configuration: Git coloring is set by default, the existing engine is still available.
The GE theme colors for added/removed code (reverse green/red) is applied by default (default Git to just set foreground text is can be configured).
Git by default warns about white space, this is disabled by default (diff.colorMovedWS).
A user can override the Git colors for each "slot" (see below), but this is not available in GE UI.

--
Git word diff coloring

Enable Git word diff coloring view.
This is an alternative view for diff, not in patch format.
The differences are coded on the same line.

Configuration: "GE word highlighting" is the default, "Git diff highlighting" can be enabled.
By default Git highlights changed words. If the user has not set diff.wordRegex, change by character is used ('.').

--

What is not in this PR:

  • Documentation for the changes, how colors etc can be changed by Git config
  • Tests are added for the "decoding escape sequence handling". The status for other parts is the same as before (there are no major benefits for adding tests)
  • Tuned colors fully matching theming
  • A more generic way to display diff in other ways, like using diff-so-fancy or delta. That is probably a different view, similar to Blame in diff (but using the same FileViewer).

Screenshots

TBD, see #11464 for now

moved

The third is "Git default", no GE theme override, whitespace errors
image image image

image image

image image

range diff - the GE coloring is very limited

image image

A missed merge (color should have been yellow, I have modified it). Dual color makes these diffs easier to read.
image image

Git word diff

image image

The word diff is best used to toggle the view back and forward to see details, only worddiff is confusing

image image

ANSI Color theme

Git uses "slots" like old, new, oldMoved etc to set situations.
https://git-scm.com/docs/git-config#Documentation/git-config.txt-colordiffltslotgt
The slots are translated to named colors (8) that can be normal/bright/dim (and more, not really used in Git) as well as background/foreground. A terminal uses a "theme" to translate these colors.
The "theme" for these colors in this PR is displayed below as well as the GE theme colors overriding the default. (Note that the GE colors DiffAddedExtra and DiffRemovedExtra has no direct fit in the ANSI colors, maybe bright is the closest).

image

Test methodology

Manual, tests to be added, maybe in a followup PR

Merge strategy

  • Rebase merge (PR submitter must change the commit message for the last commit).

✒️ I contribute this code under The Developer Certificate of Origin.

@ghost ghost assigned gerhardol Feb 15, 2024
@gerhardol gerhardol marked this pull request as draft February 15, 2024 23:12
@gerhardol gerhardol mentioned this pull request Feb 15, 2024
@gerhardol gerhardol force-pushed the feature/git-coloring branch from ada71da to e19be0c Compare February 16, 2024 23:29
@gerhardol gerhardol changed the title WIP Git coloring Git diff coloring Feb 16, 2024
@gerhardol gerhardol marked this pull request as ready for review February 16, 2024 23:30
mstv

This comment was marked as resolved.

@@ -242,7 +242,7 @@ public interface IGitModule
/// <param name="cancellationToken">A cancellation token.</param>
/// <returns>the Git output.</returns>
string GetCustomDiffMergeTools(bool isDiff, CancellationToken cancellationToken);
Task<(Patch? patch, string? errorMessage)> GetSingleDiffAsync(ObjectId? firstId, ObjectId? secondId, string? fileName, string? oldFileName, string extraDiffArguments, Encoding encoding, bool cacheResult, bool isTracked, CancellationToken cancellationToken);
Task<(Patch? patch, string? errorMessage)> GetSingleDiffAsync(ObjectId? firstId, ObjectId? secondId, string? fileName, string? oldFileName, string extraDiffArguments, Encoding encoding, bool cacheResult, bool isTracked, bool useGitColoring, GitCommandConfiguration commandConfiguration, CancellationToken cancellationToken);
int? GetCommitCount(string parent, string child, bool cache, bool throwOnErrorExit);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These API were already long and now they are bordering on "gross" long... We'll need to revisit these.

Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, few minor comments and nits

@@ -1598,6 +1614,10 @@ The primary difftool can still be selected by clicking the main menu entry.</sou
<source>Show &amp;entire file</source>
<target />
</trans-unit>
<trans-unit id="showGitWordColoringToolStripMenuItem.Text">
<source>Show Git word coloring</source>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assigned hotkey should be displayed in the menu item.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is shown
Setting accelerator to D

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is shown

👍 (In other files, the regarding lines are not that spread over the files as here. So, I missed the already existing line.)

Setting accelerator to D

Then double use of D: for "&Decrease the number of lines of context"

@gerhardol
Copy link
Member Author

@mstv Can I squash and rebase (as in tmp/git-coloring)?

Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have not tested in detail

@gerhardol
Copy link
Member Author

I have added some tests to def59df, will maybe add some sequence tests before adding to this PR.
This could be merged together with #11350 if you want to use some more

@gerhardol gerhardol force-pushed the feature/git-coloring branch from bb68c11 to 578837e Compare February 25, 2024 22:36
Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 tests fail (due to difference in linebreak?)

@gerhardol
Copy link
Member Author

@RussKie any comments on the tests or anything else?

@mstv mstv self-requested a review February 28, 2024 20:00
@mstv
Copy link
Member

mstv commented Feb 28, 2024

It would be good to have "(go to) next / previous change" image
also when "showing Git word coloring".

image


Copied text contains both the old and the new "words". This may be hard to circumvent, i.e. I am not requesting a change.

        textMarkers[2].Offset.Should().Be(6259);

@gerhardol
Copy link
Member Author

It would be good to have "(go to) next / previous change"

With Git word diff, there is no notion about changed lines in the Git output.
The simplest workaround would maybe be a separate diff type and go to start of diff "@@". But that is useless when you need it the most, showing the complete file.
You could maybe guess that if a line has markers it is a change. A little to much guessing for me. But could be considered.

I probably miss the markers on the line numbers more, not sure how to guess. First or last color on line? most dominant color? rainbow?

I have not thought about this in detail, would like to get this and git-diff "ready" before I divert again. Maybe using Delta viewer as an alternative is a step forward (with even more limitations in navigating and copying).

For git-word-diff, it is probably easier to modify Git directly than to patch the output. I almost got it working guessing how to convert back to word format.

Copied text contains both the old and the new "words". This may be hard to circumvent, i.e. I am not requesting a change.

Even harder, then you need to know what the change is and set unique color codes for old/new that are weird or check all Git colors so they are not used for other purposes too.
So I do not see this as likely ever.
The workflow could be to toggle back to patch view.

@mstv
Copy link
Member

mstv commented Feb 29, 2024

The simplest workaround would maybe be a separate diff type and go to start of diff "@@". But that is useless when you need it the most, showing the complete file.

exactly

You could maybe guess that if a line has markers it is a change. A little to much guessing for me. But could be considered.

Would be good in a follow-up.

I probably miss the markers on the line numbers more, not sure how to guess. First or last color on line? most dominant color? rainbow?

' ', '+', '-', '~'

The workflow could be to toggle back to patch view.

acceptable
I use to mark the text using the mouse. So, a toolbar button would be helpful because the hotkey and the context menu are the second and the third choice only.
But when switching, the wrong line numbers (old/new) are used for restoring the position.

@gerhardol
Copy link
Member Author

gerhardol commented Mar 1, 2024

You could maybe guess that if a line has markers it is a change. A little to much guessing for me. But could be considered.

Would be good in a follow-up.

I probably miss the markers on the line numbers more, not sure how to guess. First or last color on line? most dominant color? rainbow?

' ', '+', '-', '~'

Maybe just "context" color. could be used for next/previous too. But it may require a new "Highlight strategy", something that I have avoided so far.

Edit: there is no + etc at the start of the line.

The workflow could be to toggle back to patch view.

acceptable I use to mark the text using the mouse. So, a toolbar button would be helpful because the hotkey and the context menu are the second and the third choice only. But when switching, the wrong line numbers (old/new) are used for restoring the position.

Line numbers are not accurate, only the line numbers before the differences are correct.
image

Assuming that code is added rather than removed, the new line numbers is a better choice than old line numbers.

But this raises the question if only new line numbers should be shown or really any numbers at all?

This is one reason why I did not want to promote the function with a toolbar button yet. (I use 'z' as hotkey. this is useful to interpret diffs when reviewing.)
But a button could be added. The obstacle is to decide on an icon.

Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing features which require heuristics could be added in follow-ups.

@gerhardol
Copy link
Member Author

Missing features which require heuristics could be added in follow-ups.

@mstv See tmp/git-coloring 5cae497
Separate or add to this PR?
There are quite some changes (but simplifications too)
I believe this is working correctly, will add one more test. If adding to this PR, I need to squash the current commits, then split this PR
(range-diff navigation is aligned with other diffs and get line numbers)

@RussKie Any comments on the tests, I would like to proceed with this and the dependent git-grep PR

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Mar 10, 2024
Enable Git word diff coloring view.
This is an alternative view for diff, not in patch format.
The differences are coded on the same line.
@gerhardol gerhardol force-pushed the feature/git-coloring branch from f8fbb2a to 7e2c953 Compare March 10, 2024 13:43
@gerhardol
Copy link
Member Author

rebased, squashed and added xmldoc

@mstv to decide if e7b1fd3 is to be added or be a separate PR

@mstv
Copy link
Member

mstv commented Mar 10, 2024

Let's merge this now and separately review e7b1fd3.

Move handling of "normal" patches from the shared
DiffHighlightService to PatchHighlightService.

File-structure namespaces.
Various code cleanups.

This commit is a preparation for Git coloring and git-grep.
Use the coloring by git-diff instead of GE internal algorithm,
by using Git ANSI terminal escape sequences.
This enables for instance view moved code.
Enable Git word diff coloring view.
This is an alternative view for diff, not in patch format.
The differences are coded on the same line.
@gerhardol gerhardol force-pushed the feature/git-coloring branch from 7e2c953 to 4c0d640 Compare March 10, 2024 21:31
@gerhardol gerhardol merged commit 7296021 into gitextensions:master Mar 10, 2024
@gerhardol gerhardol deleted the feature/git-coloring branch March 10, 2024 22:01
@ghost ghost added this to the vNext milestone Mar 10, 2024
@mstv mstv mentioned this pull request Mar 12, 2024
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Apr 6, 2024
as well as range-diff and git-grep.

git coloring of command output was added in gitextensions#11590.
The patch view (default) is configurable, keeping the current
GE coloring if a user prefers.

This removes the GE coloring for some commands ans the GE
coloring is very limited and adding to the complexity.
* git-word-diff (gitextensions#11590)
* git-grep (gitextensions#11359)
* git-range-diff (very limited GE coloring).
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Apr 7, 2024
as well as range-diff and git-grep.

Use of Git coloring of command output was added in gitextensions#11590.
The patch view (default) is configurable, setting to keep the current
GE coloring.

This removes the GE coloring for some commands ans the GE
coloring is very limited and is adding complexity.
* git-word-diff (gitextensions#11590)
* git-grep (gitextensions#11359)
* git-range-diff (very limited GE coloring).
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Apr 10, 2024
as well as range-diff and git-grep.

Use of Git coloring of command output was added in gitextensions#11590.
The patch view (default) is configurable, setting to keep the current
GE coloring.

This removes the GE coloring for some commands ans the GE
coloring is very limited and is adding complexity.
* git-word-diff (gitextensions#11590)
* git-grep (gitextensions#11359)
* git-range-diff (very limited GE coloring).
gerhardol added a commit that referenced this pull request Apr 10, 2024
as well as range-diff and git-grep.

Use of Git coloring of command output was added in #11590.
The patch view (default) is configurable, setting to keep the current
GE coloring.

This removes the GE coloring for some commands ans the GE
coloring is very limited and is adding complexity.
* git-word-diff (#11590)
* git-grep (#11359)
* git-range-diff (very limited GE coloring).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve diff word highlighting Highlight with Git diff implementation - highlight moved code
3 participants