improve ext mod detection, diff visualizer + md5 content checker, close #72, close #123

This commit is contained in:
Basile Burg 2017-03-05 09:54:22 +01:00
parent 6726fe176e
commit e7ca586d77
No known key found for this signature in database
GPG Key ID: 1868039F415CB8CF
9 changed files with 316 additions and 33 deletions

View File

@ -244,7 +244,7 @@
<PackageName Value="LCL"/>
</Item7>
</RequiredPackages>
<Units Count="56">
<Units Count="58">
<Unit0>
<Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/>
@ -533,6 +533,18 @@
<Filename Value="..\src\ce_halstead.pas"/>
<IsPartOfProject Value="True"/>
</Unit55>
<Unit56>
<Filename Value="..\src\ce_diff.pas"/>
<IsPartOfProject Value="True"/>
<HasResources Value="True"/>
</Unit56>
<Unit57>
<Filename Value="..\src\ce_diff.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="CEDiffViewer"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit57>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -12,7 +12,7 @@ uses
ce_dockoptions, ce_shortcutseditor, ce_mru, ce_processes,
ce_dialogs, ce_dubprojeditor, ce_controls, ce_dfmt, ce_lcldragdrop,
ce_stringrange, ce_dlangmaps, ce_projgroup, ce_projutils, ce_d2synpresets,
ce_dastworx, ce_dbgitf, ce_ddemangle, ce_dubproject, ce_halstead;
ce_dastworx, ce_dbgitf, ce_ddemangle, ce_dubproject, ce_halstead, ce_diff;
{$R *.res}

173
src/ce_diff.lfm Normal file
View File

@ -0,0 +1,173 @@
object CEDiffViewer: TCEDiffViewer
Left = 534
Height = 441
Top = 292
Width = 516
Caption = 'External file modification'
ClientHeight = 441
ClientWidth = 516
LCLVersion = '1.6.4.0'
inline editor: TSynEdit
Left = 4
Height = 320
Top = 76
Width = 508
Align = alClient
BorderSpacing.Around = 4
Font.Height = 13
Font.Name = 'DejaVu Sans Mono'
Font.Pitch = fpFixed
Font.Quality = fqNonAntialiased
ParentColor = False
ParentFont = False
TabOrder = 0
Gutter.Width = 57
Gutter.MouseActions = <>
RightGutter.Width = 0
RightGutter.MouseActions = <>
Highlighter = diffHl
Keystrokes = <>
MouseActions = <>
MouseTextActions = <>
MouseSelActions = <>
VisibleSpecialChars = [vscSpace, vscTabAtLast]
ReadOnly = True
SelectedColor.BackPriority = 50
SelectedColor.ForePriority = 50
SelectedColor.FramePriority = 50
SelectedColor.BoldPriority = 50
SelectedColor.ItalicPriority = 50
SelectedColor.UnderlinePriority = 50
SelectedColor.StrikeOutPriority = 50
BracketHighlightStyle = sbhsBoth
BracketMatchColor.Background = clNone
BracketMatchColor.Foreground = clNone
BracketMatchColor.Style = [fsBold]
FoldedCodeColor.Background = clNone
FoldedCodeColor.Foreground = clGray
FoldedCodeColor.FrameColor = clGray
MouseLinkColor.Background = clNone
MouseLinkColor.Foreground = clBlue
LineHighlightColor.Background = clNone
LineHighlightColor.Foreground = clNone
inline SynLeftGutterPartList1: TSynGutterPartList
object SynGutterMarks1: TSynGutterMarks
Width = 24
MouseActions = <>
end
object SynGutterLineNumber1: TSynGutterLineNumber
Width = 17
MouseActions = <>
MarkupInfo.Background = clBtnFace
MarkupInfo.Foreground = clNone
DigitCount = 2
ShowOnlyLineNumbersMultiplesOf = 1
ZeroStart = False
LeadingZeros = False
end
object SynGutterChanges1: TSynGutterChanges
Width = 4
MouseActions = <>
ModifiedColor = 59900
SavedColor = clGreen
end
object SynGutterSeparator1: TSynGutterSeparator
Width = 2
MouseActions = <>
MarkupInfo.Background = clWhite
MarkupInfo.Foreground = clGray
end
object SynGutterCodeFolding1: TSynGutterCodeFolding
MouseActions = <>
MarkupInfo.Background = clNone
MarkupInfo.Foreground = clGray
MouseActionsExpanded = <>
MouseActionsCollapsed = <>
end
end
end
object Panel1: TPanel
Left = 4
Height = 37
Top = 400
Width = 508
Align = alBottom
BorderSpacing.Around = 4
BevelOuter = bvLowered
ClientHeight = 37
ClientWidth = 508
TabOrder = 1
object btnIgnore: TBitBtn
Left = 114
Height = 33
Hint = 'Don''t show this dialog until more modifications are detected'
Top = 2
Width = 130
Align = alRight
BorderSpacing.Around = 1
Caption = 'Never ask again'
ModalResult = 5
ParentShowHint = False
ShowHint = True
TabOrder = 0
end
object btnAccept: TBitBtn
Left = 245
Height = 33
Hint = 'Load the new version'
Top = 2
Width = 130
Align = alRight
BorderSpacing.Around = 1
Caption = 'Load new version'
ModalResult = 1
ParentShowHint = False
ShowHint = True
TabOrder = 1
end
object btnCancel: TBitBtn
Left = 376
Height = 33
Hint = 'Don''t reload the modifications for now'
Top = 2
Width = 130
Align = alRight
BorderSpacing.Around = 1
Caption = 'Keep current'
ModalResult = 2
ParentShowHint = False
ShowHint = True
TabOrder = 2
end
end
object Panel2: TPanel
Left = 4
Height = 68
Top = 4
Width = 508
Align = alTop
BorderSpacing.Around = 4
BevelOuter = bvLowered
ClientHeight = 68
ClientWidth = 508
TabOrder = 2
object lbl: TLabel
Left = 3
Height = 62
Top = 3
Width = 502
Align = alClient
Alignment = taCenter
BorderSpacing.Around = 2
Caption = 'lbl'
Layout = tlCenter
ParentColor = False
WordWrap = True
end
end
object diffHl: TSynDiffSyn
Enabled = False
left = 8
top = 64
end
end

65
src/ce_diff.pas Normal file
View File

@ -0,0 +1,65 @@
unit ce_diff;
{$I ce_defines.inc}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
SynEdit, SynHighlighterDiff, process,
ce_common, ComCtrls, StdCtrls, ExtCtrls, Buttons;
type
TCEDiffViewer = class(TForm)
btnIgnore: TBitBtn;
btnAccept: TBitBtn;
btnCancel: TBitBtn;
editor: TSynEdit;
diffHl: TSynDiffSyn;
lbl: TLabel;
Panel1: TPanel;
Panel2: TPanel;
private
public
constructor construct(const fname1, fname2: string);
end;
implementation
{$R *.lfm}
constructor TCEDiffViewer.construct(const fname1, fname2: string);
var
p: TProcess;
r: TStringList;
begin
inherited create(nil);
p := TProcess.Create(self);
p.Executable:= 'diff' + exeExt;
lbl.Caption:= 'The file: "' + fname2 + '" has been modified by another program.'
+ LineEnding + 'Use the following diff to decide if the content should be '
+ 'reloaded.';
if exeInSysPath(p.Executable) then
begin
p.Parameters.Add('-u');
p.Parameters.Add(fname1);
p.Parameters.Add(fname2);
p.Options:= [poUsePipes];
p.ShowWindow:= swoHIDE;
p.Execute;
r := TStringList.Create;
try
processOutputToStrings(p,r);
editor.Lines.Assign(r);
finally
r.Free;
end;
end
else editor.Lines.Add('(The "diff" tool cannot be found)');
end;
end.

View File

@ -1,21 +1,21 @@
inherited CEInfoWidget: TCEInfoWidget
Left = 713
Height = 471
Height = 496
Top = 245
Width = 411
BorderIcons = [biSystemMenu, biMinimize, biMaximize]
Caption = 'About'
ClientHeight = 471
ClientHeight = 496
ClientWidth = 411
inherited Back: TPanel
Height = 471
Height = 496
Width = 411
ClientHeight = 471
ClientHeight = 496
ClientWidth = 411
inherited Content: TPanel
Height = 435
Height = 460
Width = 411
ClientHeight = 435
ClientHeight = 460
ClientWidth = 411
object GroupBox1: TGroupBox[0]
Left = 4
@ -45,18 +45,18 @@ inherited CEInfoWidget: TCEInfoWidget
end
object GroupBox2: TGroupBox[1]
Left = 4
Height = 318
Height = 343
Top = 113
Width = 403
Align = alClient
BorderSpacing.Around = 4
Caption = 'tools status'
ClientHeight = 288
ClientHeight = 313
ClientWidth = 399
TabOrder = 1
object boxTools: TScrollBox
Left = 4
Height = 280
Height = 305
Top = 4
Width = 391
HorzScrollBar.Page = 1

View File

@ -199,6 +199,10 @@ begin
free;
end;
//
itm := TToolInfo.Construct(self, tikOptional, 'diff',
'The diff tool as included in linux or msysgit');
itm.Parent := boxTools;
itm.ReAlign;
{$IFDEF UNIX}
itm := TToolInfo.Construct(self, tikOptional, 'gdb',
'optional, the GNU debugger');

View File

@ -1468,7 +1468,7 @@ object CEMainForm: TCEMainForm
OnCloseQuery = FormCloseQuery
OnDropFiles = FormDropFiles
ShowHint = True
LCLVersion = '1.6.2.0'
LCLVersion = '1.6.4.0'
object mainMenu: TMainMenu
Images = imgList
top = 1

View File

@ -1879,6 +1879,7 @@ begin
for i := 0 to fMultidoc.documentCount-1 do
begin
d := fMultidoc.getDocument(i);
d.disableFileDateCheck := true;
if d.modified or (d.fileName = d.tempFilename) then
begin
files += #9 + shortenPath(d.filename) + LineEnding;
@ -1909,7 +1910,14 @@ begin
if MessageDlg('Modified content', format(s, [files, projs, group]),
TMsgDlgType.mtConfirmation, [mbOk, mbCancel], '') <> mrOk then
exit;
begin
for i := 0 to fMultidoc.documentCount-1 do
begin
d := fMultidoc.getDocument(i);
d.disableFileDateCheck := false;
end;
exit;
end;
end;
CanClose:= true;

View File

@ -9,10 +9,11 @@ uses
SynEdit, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText,
SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView,
SynEditMarks, SynEditTypes, SynHighlighterJScript, SynBeautifier, dialogs,
md5,
//SynEditMarkupFoldColoring,
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs,
ce_sharedres, ce_dlang, ce_stringrange, ce_dbgitf, ce_observer;
ce_sharedres, ce_dlang, ce_stringrange, ce_dbgitf, ce_observer, ce_diff;
type
@ -1127,7 +1128,8 @@ var
numSpac: integer = 0;
begin
if not fIsDSource and not alwaysAdvancedFeatures then
exit;
exit;
i := CaretY - 1;
while true do
begin
@ -2352,30 +2354,49 @@ end;
procedure TCESynMemo.checkFileDate;
var
mr: TModalResult;
newDate: double;
newMd5: TMDDigest;
curMd5: TMDDigest;
str: TStringList;
txt: string;
begin
if fFilename = fTempFileName then exit;
if fDisableFileDateCheck then exit;
if not FileAge(fFilename, newDate) then exit;
if fFileDate = newDate then exit;
if fFileDate <> 0.0 then
if (fFilename = fTempFileName) or fDisableFileDateCheck
or not FileAge(fFilename, newDate) or (fFileDate = newDate) then
exit;
if (fFileDate <> 0.0) then
begin
// note: this could cause a bug during the DST switch.
// e.g: save at 2h59, 3h00 reset to 2h00, set the focus on the doc: new version message.
if dlgYesNo(format('"%s" has been modified by another program, load the new version ?',
[shortenPath(fFilename, 25)])) = mrYes then
begin
str := TStringList.Create;
try
str.LoadFromFile(fFilename);
replaceUndoableContent(str.strictText);
finally
str.Free;
str := TStringList.Create;
try
str.LoadFromFile(fFilename);
txt := str.strictText;
newMd5 := MD5String(txt);
txt := lines.strictText;
curMd5 := MD5String(txt);
if not MDMatch(curMd5, newMd5) then
begin
lines.SaveToFile(tempFilename);
With TCEDiffViewer.construct(fTempFileName, fFilename) do
try
mr := ShowModal;
case mr of
mrOK:
begin
replaceUndoableContent(str.strictText);
fFileDate := newDate;
end;
mrIgnore: fFileDate := newDate;
mrCancel:;
end;
finally
free;
end;
end;
finally
str.Free;
end;
end;
fFileDate := newDate;
end
else fFileDate := newDate;
end;
function TCESynMemo.getMouseBytePosition: Integer;