UPD: Lines compare algorithm

This commit is contained in:
Alexander Koblov 2011-04-15 03:33:20 +00:00
commit 4e197c053c
4 changed files with 70 additions and 71 deletions

View file

@ -1613,10 +1613,12 @@ object frmDiffer: TfrmDiffer
object actIgnoreCase: TAction
AutoCheck = True
Caption = 'Ignore Case'
DisableIfNoHandler = False
end
object actIgnoreWhiteSpace: TAction
AutoCheck = True
Caption = 'Ignore Blanks'
DisableIfNoHandler = False
end
object actKeepScrolling: TAction
AutoCheck = True

View file

@ -394,7 +394,9 @@ begin
begin
SynDiffEditLeft.PaintStyle:= psForeground;
SynDiffEditRight.PaintStyle:= psForeground;
end
end;
SynDiffHighlighterLeft.UpdateColors;
SynDiffHighlighterRight.UpdateColors;
end;
procedure TfrmDiffer.actPrevDiffExecute(Sender: TObject);

View file

@ -67,7 +67,6 @@ type
function GetEditor: TSynDiffEdit;
procedure ComputeTokens(const aOldLine, aNewLine: String);
protected
procedure UpdateColors;
function GetDefaultAttribute(Index: Integer): TSynHighlighterAttributes; override;
public
constructor Create(aOwner: TSynDiffEdit); reintroduce; overload;
@ -77,6 +76,8 @@ type
procedure ResetRange; override;
procedure SetLine(const aNewValue: String; aLineNumber: Integer); override;
procedure UpdateColors;
function GetEol: Boolean; override;
function GetToken: String; override;
procedure GetTokenEx(out TokenStart: PChar; out TokenLength: Integer); override;
@ -90,83 +91,73 @@ type
implementation
uses
SynEditTypes, Graphics, uHash;
SynEditTypes, Graphics;
{ TSynDiffHighlighter }
procedure TSynDiffHighlighter.ComputeTokens(const aOldLine, aNewLine: String);
procedure Tokenize(const aText: String; aList: TStrings);
var
vTokenStart: PChar;
vRun: PChar;
vToken: String;
begin
vTokenStart := PChar(aText);
vRun := vTokenStart;
while vRun^ <> #0 do
begin
while vRun^ in [#32,#9] do
Inc(vRun);
if vTokenStart <> vRun then
begin
SetString(vToken, vTokenStart, vRun - vTokenStart);
aList.Add(vToken);
vTokenStart := vRun;
end;
{}
while vRun^ in TSynValidStringChars do
Inc(vRun);
if vTokenStart <> vRun then
begin
SetString(vToken, vTokenStart, vRun - vTokenStart);
aList.Add(vToken);
vTokenStart := vRun;
end;
{}
if vRun^ in [#33..#255] - TSynValidStringChars then
begin
aList.Add(vRun^);
Inc(vRun);
vTokenStart := vRun;
end;
end;
end;
const
skipChar = #10;
var
vOldTokens: TStringList;
vArray1: array of Integer;
vArray2: array of Integer;
i: Integer;
vChange: TCompareRec;
cChange, cLine: Integer;
begin
{ Tokenize fOldLine }
vOldTokens := TStringList.Create;
try
Tokenize(aOldLine, vOldTokens);
SetLength(vArray1, vOldTokens.Count);
for i := Length(vArray1) -1 downto 0 do
vArray1[i] := PtrInt(HashString(vOldTokens[i], False, False));
finally
vOldTokens.Free;
end;
{ Tokenize fNewLine }
Tokenize(aNewLine, fTokens);
SetLength(vArray2, fTokens.Count);
for i := Length(vArray2) -1 downto 0 do
vArray2[i] := PtrInt(HashString(fTokens[i], False, False));
{ Calculate diffs }
fDiff.Execute( PInteger(@(vArray1[0])), PInteger(@(vArray2[0])),
Length(vArray1), Length(vArray2) );
for cChange := 0 to fDiff.Count -1 do
I: Integer;
lastKind: TChangeKind;
lastToken: String;
procedure AddTokenIfNeed(Symbol: Char; Kind: TChangeKind);
begin
vChange := fDiff.Compares[cChange];
if vChange.Kind <> ckDelete then
for cLine := vChange.oldIndex1 to vChange.oldIndex2 do
fTokens.Objects[cLine] := TObject(PtrInt(vChange.Kind));
if (Kind = lastKind) then // Same Kind, no need to change colors
begin
if Symbol = skipChar then
lastToken:= #32
else
lastToken := lastToken + Symbol;
end
else
begin
fTokens.AddObject(lastToken, TObject(PtrInt(lastKind)));
if Symbol = skipChar then
lastToken:= #32
else
lastToken := Symbol;
lastKind := Kind;
end;
end;
fDiff.Clear;
begin
// Compare lines
if not Assigned(Editor.OriginalFile) then // Original file
fDiff.Execute(PChar(aNewLine), PChar(aOldLine), Length(aNewLine), Length(aOldLine))
else if not Assigned(Editor.ModifiedFile) then // Modified file
fDiff.Execute(PChar(aOldLine), PChar(aNewLine), Length(aOldLine), Length(aNewLine));
// Prepare diffs to display
lastKind := ckNone;
lastToken:= EmptyStr;
for I := 0 to fDiff.Count - 1 do
with fDiff.Compares[I] do
begin
if not Assigned(Editor.OriginalFile) then // Original file
begin
// Show changes for original file
// with spaces for adds to align with modified file
if Kind = ckAdd then
AddTokenIfNeed(skipChar, Kind)
else
AddTokenIfNeed(chr1, Kind);
end
else if not Assigned(Editor.ModifiedFile) then // Modified file
begin
// Show changes for modified file
// with spaces for deletes to align with original file
if Kind = ckDelete then
AddTokenIfNeed(skipChar, Kind)
else
AddTokenIfNeed(chr2, Kind);
end;
end;
// Add last token
fTokens.AddObject(lastToken, TObject(PtrInt(lastKind)));
end;
constructor TSynDiffHighlighter.Create(aOwner: TComponent);
@ -246,6 +237,8 @@ begin
Result := fAddedAttriPointer;
ckModify:
Result := fModifiedAttribute;
ckDelete:
Result := fAddedAttriPointer;
else
Result := fDefaultAttriPointer;
end;
@ -343,7 +336,7 @@ begin
fModifiedAttribute.Foreground := Editor.Colors.Modified;
fModifiedAttribute.Background := clBtnFace;
fUnmodifiedAttribute.Foreground := clNone;
fUnmodifiedAttribute.Background := clBtnFace;
fUnmodifiedAttribute.Background := clNone;
end
else begin
fAddedAttribute.Foreground := clNone;
@ -361,4 +354,4 @@ begin
end;
end.

View file

@ -110,7 +110,7 @@ type
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure InsertFakeLine(AIndex: Integer; ADiffKind: PtrInt);
procedure RemoveFakeLines(Strings: TStringList);
procedure RemoveFakeLines(Strings: TStrings);
procedure BeginCompare(ADiff: TDiff);
procedure EndCompare(ADiffCount: Integer);
function DiffBegin(ALine: Integer): Integer;
@ -270,6 +270,8 @@ procedure TSynDiffEdit.BeginCompare(ADiff: TDiff);
begin
FDiff:= ADiff;
BeginUpdate;
// Remove fake lines
RemoveFakeLines(Lines);
end;
procedure TSynDiffEdit.EndCompare(ADiffCount: Integer);
@ -331,7 +333,7 @@ begin
Lines.InsertObject(AIndex, EmptyStr, TObject(ADiffKind));
end;
procedure TSynDiffEdit.RemoveFakeLines(Strings: TStringList);
procedure TSynDiffEdit.RemoveFakeLines(Strings: TStrings);
var
I: Integer;
begin