UI: Add UIDiffView for specialized diff/patch visualization

- Integrated dtl into thirdparty for native string diffing
- Implemented UIDiffView, a composite wrapper for UICodeEditor with a custom plugin (UIDiffEditorPlugin)
- Handles dynamic string diffing and standard .patch file parsing
- Automatically extracts target filename from patch headers for proper syntax highlighting
- Corrects line numbers in gutter to match the diff origins while hiding patch headers
- Wired into App::loadDiffFromPath and GitPlugin
- Added exhaustive unit tests in uidiffview_test.cpp
This commit is contained in:
Martín Lucas Golini
2026-03-23 18:12:23 -03:00
parent bfb1fd66b6
commit 0e923adea9
12 changed files with 1839 additions and 8 deletions

View File

@@ -7,6 +7,7 @@
#include <eepp/system/luapattern.hpp>
#include <eepp/system/scopedop.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
#include <eepp/ui/tools/uidiffview.hpp>
#include <eepp/ui/uicheckbox.hpp>
#include <eepp/ui/uidropdownlist.hpp>
#include <eepp/ui/uiiconthememanager.hpp>
@@ -1115,14 +1116,18 @@ void GitPlugin::diff( const std::string& file, bool isStaged ) {
return;
getUISceneNode()->runOnMainThread( [this, file, res] {
auto ret = mManager->getSplitter()->createEditorInNewTab();
auto doc = ret.second->getDocumentRef();
doc->setDefaultFileName( FileSystem::fileNameFromPath( file ) + ".diff" );
doc->textInput( res.result, false );
doc->moveToStartOfDoc();
doc->resetUndoRedo();
ret.second->setSyntaxDefinition(
SyntaxDefinitionManager::instance()->getByLSPName( "diff" ) );
auto* diffView = Tools::UIDiffView::New();
auto [tab, iv] = getPluginContext()->getSplitter()->createWidget(
diffView, i18n( "diff_viewer", "Diff Viewer" ) );
std::string fileName = FileSystem::fileNameFromPath( file );
tab->setText( fileName )->setTooltipText( file );
UIIcon* icon = getUISceneNode()->findIcon(
UIIconThemeManager::getIconNameFromFileName( fileName ) );
if ( !icon )
icon = getUISceneNode()->findIcon( "file" );
if ( icon )
tab->setIcon( icon->getSize( getPluginContext()->getMenuIconSize() ) );
diffView->loadFromPatch( res.result );
} );
} );
}