Wilfred / difftastic

a structural diff that understands syntax 🟥🟩
https://difftastic.wilfred.me.uk/
MIT License
20.59k stars 333 forks source link

Wrong diff highlights for a lot of unchanged lines #729

Open c02y opened 3 months ago

c02y commented 3 months ago

Thanks for reporting a bug! Please include all of the following:

(1) A description of the issue. A screenshot is often helpful too.

(2) A copy of what you're diffing. If you're diffing files, include the before and after files. If you're using difftastic with a VCS repository (e.g. git), include the URL and commit hash.

(3) The version of difftastic you're using (see difft --version) and your operating system.

When I use difft as the diff pager in lazygit, I see that a lot of unchanged lines are highlight inside lazygit difftastioc version: Difftastic 0.58.0 (0c9277108 2024-05-10, built with rustc 1.78.0)

For reference from lazygit: https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md

When using difft as the pager in lazygit/config.yml

git:
  paging:
    externalDiffCommand: difft --color=always --display=inline --syntax-highlight=off

screenshot: https://imgur.com/a/rydgHOJ

When using delta as the pager in lazygit/config.yml

git:
  paging:
    pager: delta --dark --paging=never --true-color=never --line-numbers

screenshot: https://imgur.com/KLPP6oS

Wilfred commented 2 months ago

That's correct behaviour I'm afraid. You have a large string (starting at the EOF heredoc), which has partially changed.

I'd like to improve the highlighting of large multiline strings, but the basic syntactic diff is behaving as intended.

menixator commented 1 month ago

I've seen similar behaviour with large strings while diffing nix files too. Nix files has a similar construct to heredoc that people use to embed large chunks of text within nix code.

{} : ''
# like so
''

Difftastic knows that these are strings so it never breaks them down for me any further. While you could use some kind of heuristic to use an make the differences between these strings more granular than just on the string node level using some kind of size-based heuristic, you could also rely on some kind of tree-sitter injection based heuristic as well.

Nix code on the right. Treesitter parsed tree on the left. Highlighted node is lua code embedded within a nix string and neovim highlights it because the tree-sitter plugin for nix lets users change the language of the big text blocks like this using a comment that precedes the multiline text block. Injections are being done using a query here. image

This MIGHT be an avenue to fix this issue in certain cases by using already defined injections like this and potentially even having difftastic-specific injections like this but I should mention that injections are not perfect. For instance, nix allows you to interpolate into that multiline string using ${variableHere} and this sometimes borks the parser.

image