Better external diff integration
已回答
Hi,
I am writing a diff tool and I am wondering if it is possible to integrate with IntellJ better than with the external diff tool functionality. I would like to be able to add features like partial git commits or jump to next file. I looked into the built-in diff tool's source and it all looks quite glued together with the rest of the IDEA.
What are my options? I am happy to write a plugin but it doesn't seem to be possible currently. Would I need to create a new API?
Thanks,
Kristof
请先登录再写评论。
Yes, it might be hard to integrate into existing implementations.
Probably, `com.intellij.diff.DiffExtension` and a couple of customizable ActionGroups is the best you can get here.
It should be easier to add functionality "nearby" existing one though.
Ex: by registering completely new `com.intellij.diff.FrameDiffTool` or creating view for some data with `com.intellij.diff.impl.DiffRequestProcessor` or both.
Yes, it is possible to send a PR on https://github.com/JetBrains/intellij-community/pulls if some bits are missing.
It's hard to suggest any details, as it's not clear what "partial git commits" or "jump to next file" should look like.
Thanks for your quick reply. I will have a look on the points you have suggested, thanks.
Sorry, I was probably not very clear with "partial git commits" or "jump to next file". I was referring of existing features of the current build-in diff tool. Partial git commits is this one: basically the ability to select/deselect a change in the diff tool and not commit the deselected one on commit. Given the external tool doesn't have a channel to send anything back to IDEA it's impossible to implement it without a plugin.
By jump to next file I meant the left/right arrows at the top of the built-in tool. Basically they enable you to go through all the changes of a commit without leaving the diff tool.
So, you're trying to improve integration with a specific tool, that is currently registered in "File | Settings | Tools | Diff & Merge | External Diff Tools" ?
I do not think, it it possible to do from a plugin right now.
It should not be hard to add an API though. Ex:
Add an ExtensionPoint in `com.intellij.diff.DiffManagerImpl#showDiff(Project, DiffRequestChain, DiffDialogHints)`, that would allow to catch the request and handle it completely (rather that passing it to `showDiffBuiltin` or `ExternalDiffTool`).
A plugin will register EP, extract affected contents from request, spawn an external tool and communicate with it in some way (RPC, I assume?).
This will allow to support prev/next file navigation (as plugin will have access to the `DiffRequestChain`, rather that single `DiffRequest`.
Supporting partial commits will be tough.
It is tightly tied to the internal data representation, and lines can't be toggled arbitrary. They have to belong to the predefined "changed line ranges" (same ranges, that are shown in Editor gutter).
Therefore, external tool won't be able to compare files itself, likely losing its main selling point.
Also, API here is not stable an can be changed in the future.
And these checkbox states are meaningful only while commit dialog is shown, making integration even harder.
So, while this is not impossible, I wouldn't advise to do it.
OK, makes sense, thank you. This is plenty of help so I can probably do the prev/next file and I will probably give up on the partial commit for now.
Actually I got an idea for partial commits: I could use IDEA's changelist feature to move changes to a different changelist and the commit would only happen with my current changelist. It would be slightly annoying as the change wouldn't appear at all so I would need to manage that but do you see any other reason why that wouldn't work?
Thanks,
Kristof
Actually, same thing applies to "partial changelists".
Internally, they are implemented in the same way (and you'll face same issues, as described above).
Anyway, you can take a look at `com.intellij.openapi.vcs.impl.LineStatusTrackerManager#getLineStatusTracker` and `com.intellij.openapi.vcs.ex.PartialLocalLineStatusTracker`. See `tracker.setExcludedFromCommit` / `tracker.getRanges` / `LocalRange.isExcludedFromCommit` (and `changelistId` methods nearby).
Also, you can take a look at `SimpleLocalChangeListDiffViewer` as an usage sample.
Probably, it would be better to integrate with "native" "git add -p" routine, directly modifying staging area (and implementing some way to commit staged changes from IDE).
Related issue: https://youtrack.jetbrains.com/issue/IDEA-63391
Unfortunately, I can't give any estimations right now, if/when it will be implemented.
But limited implementation of "commit some changes" via staged area should be easier, than fighting with limitations of `LineStatusTrackerManager`.
Ping me if you'd need a hint on stating points.
I see, thank you for explaining these to me. I think it will be a while before I will actually start to work on this, so I will let you know if I need help with staging points or anything else.
Thanks