diffview.nvim icon indicating copy to clipboard operation
diffview.nvim copied to clipboard

[feature] Highlight moved lines in a different way

Open Gelio opened this issue 4 years ago • 8 comments

Hey! Thanks for making this plugin, I really appreciate it. It looks like a more robust solution to what I had done locally in my init.vim, but uses nicer UI 👍

I have an idea about a feature for the way diffs are displayed, and I'm not sure how to tackle it. It's probably not related to this plugin, but I don't have certainty, so maybe you could at least point me in the right direction.

Background

Git has a color-moved functionality that highlights moved code in a different way than regular additions/deletions.

After I enable it in my git config, the functionality works well in the terminal using regular git diff and using delta: image (notice the blue/purple lines - those represent the move)

However, it does not affect the way diffs are shown inside neovim - the moved code is highlighted as if it was a delete/add operation, there is no way to distinguish them from actual deletes/adds:

image

Feature

Ideally, there would be a separate highlight for code that is moved in a diff

Gelio avatar May 03 '21 08:05 Gelio

Glad you like it!

~As far as I know, vim relies on GNU diff for its diff mode~*, and GNU diff does not support detection of moved lines. Solving this problem would require us to either write our own file diff implementation in Lua using an algorithm that supports detecting moved blocks. Or we would have to write a parser for the output of another diff tool that supports it.

I wouldn't be opposed to adding this if someone opens a PR with a clean, performant solution, but I won't prioritize it myself. I also want to keep requirements to a minimum, so any solution that uses an external tool would have to be optional and not on by default.

* Correction: vim's internal diff relies on the xdiff library.

sindrets avatar May 03 '21 14:05 sindrets

I see, thanks for the answer and for providing some clarity 👍

Gelio avatar May 03 '21 15:05 Gelio

In my opinion, the best move would be to use git diff's output to build the visualization yourself.

The blocker I think is that AFAIK neovim does not have apis (yet?) to allow plugins to make the special deleted lines (that show up when using vim's diff) arbitrarily in a buffer, so you can't replicate the visuals of the builtin' diff mode yourself.

bew avatar May 03 '21 17:05 bew

I'm trying to figure out the same thing right now.

I think it can be achieved with a combination of diffexpr and diffopt, but haven't really looked into it.

folke avatar May 08 '21 07:05 folke

When you use diffexpr vim still expects either an ed-style or a unified style diff output. Neither of which support giving information about whether or not a block has been moved as far as I'm aware.

sindrets avatar May 08 '21 12:05 sindrets

@sindrets maybe I have another issue then.

As you can see in the screenshot, according to vim, all lines were changed, but in vscode, there's better alignment of the diff.

DiffView: image

vscode: image

folke avatar May 08 '21 12:05 folke

@folke That could be either the diff algorithm used, or diffopt's. I'm not sure. Vim offers a few different algorithms that you can specify with diffopt. I don't know if it would solve the scenario you pictured above, but just for reference, these are the options I use:

set diffopt=internal,filler,closeoff,iwhite

Maybe try the patience algorithm?

sindrets avatar May 08 '21 13:05 sindrets

Both git diff and vim diff use the myers algorithm as the default. Just tried with your settings and the result is the same. Will play around with settings to see if I can fix it.

Thanks!

folke avatar May 08 '21 13:05 folke

@folke @sindrets I just opened an issue that is related, i was just reading this thread now. I noticed this problem a while ago and setting iwhiteall improved the vim diff result as sindred states however vscode still manages wrapped lines in a better way as shown in the issue i just created.

https://github.com/sindrets/diffview.nvim/issues/198

juliogarciap avatar Aug 30 '22 21:08 juliogarciap

I'm closing this as I believe this should be discussed in a feature request upstream, or implemented in a separate plugin. As a plugin I think implementing it separately makes a lot more sense than implementing here. If it's made as a general extension of diff-mode then all diffs outside this plugin would benefit from it as well.

If someone sees this, and wants to explore the plugin idea: I'm fairly certain this can be achieved by doing additional processing on the output produced by :h vim.diff() (which is a lua binding to the xdiff library), and then the moved lines could be highlighted with extmarks (:h api-extmarks).

sindrets avatar Aug 31 '22 11:08 sindrets