I expect the lines identified as different to be displayed on the same screen lines as they usually are.
The diff algorithm clearly has identified the differing lines and the differences between them as it shows the differing lines and their differences in both windows. However, the lines are not always aligned side-by-side as they should be and as they were before 9.1.1753.
I've seen numerous instances of this problem before, but this time I had time to investigate and report it. It has existed since 9.1.1753.
9.1.1839
Operating system: Ubuntu 24.04.3 LTS
Terminal: XTerm(389)
Value of $TERM: xterm-256color
Shell: GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I get this with linematch:100:
set diffopt+=hiddenoff,algorithm:histogram,linematch:100
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
I have just tried version before v9.1.1753 and it is worse than a current one provided you have set big enough linematch. However, with default linematch older version looks a bit better.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
sidenote, looks like there is an issue with mouse wheel scrolling of non active diff window: it doesn't scroll active window -- scrollbind has no effect.
https://asciinema.org/a/FkPvBsk5NXzGR9WEnuoSl9t2J
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I was expecting diff to just work, as it always has, without tweaks. Otherwise, I like the new algorithm in that it's much easier to see multiple differences in a line.
I am not 100% sure this is a good idea, but what about increasing default linematch value?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
linematch isn't enabled by default.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
linematch isn't enabled by default.
yes, but even if enabled with suggested 60, it wouldn't help in OP's scenario:
image.png (view on web)Although with 60 it looks like pre v9.1.1753
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
linematch isn't enabled by default.
It certainly seems to be. It doesn't appear in 'diffopts', but the diff feature now behaves as if it is enabled. The alignment between corresponding lines in two diffed windows is definitely broken if linediff is not set at all.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
@ychin fyi
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
sidenote, looks like there is an issue with mouse wheel scrolling of non active diff window: it doesn't scroll active window -- scrollbind has no effect.
Yes, it has been annoying me for ages! Been meaning to look into fixing it.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
sidenote, looks like there is an issue with mouse wheel scrolling of non active diff window: it doesn't scroll active window -- scrollbind has no effect.
Yes, it has been annoying me for ages! Been meaning to look into fixing it.
See #13189
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
Oh, that is documented.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
There are really multiple things going on here, so let me try to break down my thoughts:
The diff algorithm clearly has identified the differing lines and the differences between them as it shows the differing lines and their differences in both windows. However, the lines are not always aligned side-by-side as they should be and as they were before 9.1.1753.
The diff algorithm does not know which line is matched with which, and there is no simple answer for what should be matched with each other. This is because every line has 'csv' changed to 'txt', so technically every line is different. The algorithm can guess (which is what linematch does) but there's a limit to that.
Before 9.1.1753, the default diffopt was "inline:simple". Note that previously it did not align texts side-by-side as @ghgary may have thought. If you take a closer look, this is what it looks like:
image.png (view on web)Note how the lines are not actually matching? The dates are completely off. It makes you think it's aligning it but the actual matching ones (the 2024-) ones are not actually side-by-side. If you still want the old behavior (which I have to repeat: it doesn't match "matching lines" as you may think), you can set diffopt to use inline:simple.
I've seen numerous instances of this problem before, but this time I had time to investigate and report it. It has existed since 9.1.1753.
Do you have other examples? I suspect if you take a closer look to a lot of them the old behavior was not actually matching up the way you expect them to.
That said, there is a degenerate case that I think could be improved and have been working on. It looks like this:
image.png (view on web)The second line should ideally be highlighted as an "add" rather than "changed". I don't think it's worth it to dive into the details here, but there are ways to fix it.
I was expecting diff to just work, as it always has, without tweaks. Otherwise, I like the new algorithm in that it's much easier to see multiple differences in a line.
It's difficult to have things "just work" when a diff algorithm does not know the user intent and needs to work in all kinds of situations, and it's hard to infer that unless we have a sophisticated algorithm to auto-set things on and off. No one setting is going to do it for everyone. It's easy to have degenerate cases where it looks like one option is obviously better than the others. And as I mentioned, the old setting was not "just working" either.
For line match itself, I think setting it on by default will lead to more issues (at least as of how it's implemented now):
diffget and diffput less intuitive. See neovim/neovim#22696.I looked at a few diff tools while researching inline highlight's implementations, and different tools handle this type of behaviors differently. For example, Beyond Compare works in a strictly line-based diffing but it does not do multi-line highlight. Meld works in a strictly block-based system and just do inline highlighting similar to what we have without line-match. VSCode is mostly block based and in this example it just refuses to highlight anything by showing the whole thing as changed. I guess my point is that there are certain choices you have to make when choosing how to present the information which may or may not work for a situation. This is why we have linematch available as an option.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
For line match itself, I think setting it on by default will lead to more issues (at least as of how it's implemented now):
- It breaks multi-line inline highlighting (inline:char / inline:word), as it breaks each diff block into multiple smaller ones. If you are diff'ing texts where texts could move across lines, line match tends to make them worse, not better. It's more designed for strictly line-based inputs like this example. There may be ways to make inline highlighting work better with it, but it's unclear what the "correct" solution is as some people may explicitly want line match to not do multi-line highlight.
Just to explain this part a bit to provide more context. If you diff Vim commit b32da7d for example, this is what it looks like with the inline:char defaults:
image.png (view on web)Whereas turning on linematch would split up the diff block into two, breaking inline highlight (it also makes diffget/diffput odd to use):
image.png (view on web)—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
There are really multiple things going on here, so let me try to break down my thoughts:
The diff algorithm clearly has identified the differing lines and the differences between them as it shows the differing lines and their differences in both windows. However, the lines are not always aligned side-by-side as they should be and as they were before 9.1.1753.
The diff algorithm does not know which line is matched with which, and there is no simple answer for what should be matched with each other. This is because every line has 'csv' changed to 'txt', so technically every line is different. The algorithm can guess (which is what linematch does) but there's a limit to that.
It knows which lines should be matched with which when linematch is large enough, as pointed out above. In my experimentation so far, linematch must be at least as large as the sum of the lines in both buffers. It's just not at all obvious that one must fiddle with the value of linematch to get good results, at least in the cases I've been investigating.
Before 9.1.1753, the default diffopt was "inline:simple". Note that previously it did not align texts side-by-side as @ghgary may have thought. If you take a closer look, this is what it looks like:
[...]
Note how the lines are not actually matching? The dates are completely off. It makes you think it's aligning it but the actual matching ones (the 2024-) ones are not actually side-by-side. If you still want the old behavior (which I have to repeat: it doesn't match "matching lines" as you may think), you can set
diffoptto useinline:simple.
I guess I wasn't very clear in my statement. I didn't mean the that old algorithm would properly align the lines in my example files--every line is different. What I meant was that when the old algorithm recognized small-enough differences between lines, it knew to place those lines side-by-side. The new algorithm doesn't seem to know to do that until linematch is large enough, which requires fiddling by the user and hence, does not "just work".
I've seen numerous instances of this problem before, but this time I had time to investigate and report it. It has existed since 9.1.1753.
Do you have other examples? I suspect if you take a closer look to a lot of them the old behavior was not actually matching up the way you expect them to.
Again, I did not misunderstand how the old algorithm matched lines--I did not explain clearly how I was comparing the old and new behavior.
The only other examples I still have can be fixed by increasing linematch, so they may not matter anymore. If I see any oddities that can't be fixed that way, I'll let you know.
I was expecting diff to just work, as it always has, without tweaks. Otherwise, I like the new algorithm in that it's much easier to see multiple differences in a line.
It's difficult to have things "just work" when a diff algorithm does not know the user intent and needs to work in all kinds of situations, and it's hard to infer that unless we have a sophisticated algorithm to auto-set things on and off. No one setting is going to do it for everyone. It's easy to have degenerate cases where it looks like one option is obviously better than the others. And as I mentioned, the old setting was not "just working" either.
For line match itself, I think setting it on by default will lead to more issues (at least as of how it's implemented now):
[...]
Are you sure it's not on by default now? With the files I've been comparing over the last day, I can't see any difference in the diff display between 'diffopt' not containing linematch at all (the default) and with linematch set to a small value, e.g., smaller than the sum of the number of lines in both files.
Thanks for the explanations.
I now have linematch set to 300, which has fixed the problems I've seen so far. Is there any reason other than performance to limit the value of linematch?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
What I meant was that when the old algorithm recognized small-enough differences between lines, it knew to place those lines side-by-side. The new algorithm doesn't seem to know to do that until linematch is large enough, which requires fiddling by the user and hence, does not "just work".
No, it did not do that before.
Again, I did not misunderstand how the old algorithm matched lines--I did not explain clearly how I was comparing the old and new behavior.
I think you may be misremembering how the old algorithm works. I don't want to dismiss your concern, but I think you are unhappy with the diff results but misunderstand the cause. Do you have an example so it's easier to talk about the issue if the original example you gave does not suffice? It's hard to discuss about hypothetical diff results.
Are you sure it's not on by default now? With the files I've been comparing over the last day, I can't see any difference in the diff display between 'diffopt' not containing linematch at all (the default) and with linematch set to a small value, e.g., smaller than the sum of the number of lines in both files.
Yes, I'm sure. You don't see a difference there because a line match with a small value just means line match doesn't do anything.
I now have linematch set to 300, which has fixed the problems I've seen so far. Is there any reason other than performance to limit the value of linematch?
I believe I already explained it in the above comment (#18670 (comment)) why I feel that way, under bullet point 1 and 2. My point is turning on line match could also objectively make the diff worse in other situations, and there is no default setting that works for everyone, unless we do some extra tuning (which may again change the behavior which will never be a strict improvement):
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
Following workaround can help in many cases including for above:
Add below to vimrc
set diffopt+=anchor def SetDiffAnchor() exe $"setlocal diffanchors+={line('.')}" enddef nnoremap <silent><Leader>da <ScriptCmd>call SetDiffAnchor()<CR>
/24-04-03\da (leader may be different for you)ctrl w w, then n to search, then \davim anchor's on the correct line:
image.png (view on web)—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.![]()
The above workaround will indeed work. Just to clarify for others, as diff anchors is a new feature: Diff anchors essentially allow you to split and anchor specific lines with each other. You may want to do that if linematch fails to match lines up to your liking, or you have some other reasons for wanting to split up a diff in exactly the way you want. It's even more manual than what the original poster would want (since he was more asking for an "it just works ™" diff configuration) but it does allow you a lot of control in controlling the diff result to show up exactly how you want.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.![]()