From 0a9b5e5202536caa754a952f51e9d2c12ead8971 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 1 Nov 2009 04:16:22 +0000 Subject: [PATCH] SynEdit: Added tests for Beautifier, indent git-svn-id: trunk@22366 - --- .gitattributes | 1 + components/synedit/test/SynTest.lpr | 4 +- components/synedit/test/testbase.pas | 49 +- components/synedit/test/testsynbeautifier.pas | 445 ++++++++++++++++++ components/synedit/test/testsynselection.pas | 9 +- 5 files changed, 498 insertions(+), 10 deletions(-) create mode 100644 components/synedit/test/testsynbeautifier.pas diff --git a/.gitattributes b/.gitattributes index 8a5f495478..511321bf43 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2015,6 +2015,7 @@ components/synedit/syntextdrawer.pp svneol=native#text/pascal components/synedit/test/SynTest.lpi svneol=native#text/plain components/synedit/test/SynTest.lpr svneol=native#text/pascal components/synedit/test/testbase.pas svneol=native#text/pascal +components/synedit/test/testsynbeautifier.pas svneol=native#text/pascal components/synedit/test/testsynselection.pas svneol=native#text/pascal components/synunihighlighter/CHANGES.txt svneol=native#text/plain components/synunihighlighter/CREDITS.txt svneol=native#text/plain diff --git a/components/synedit/test/SynTest.lpr b/components/synedit/test/SynTest.lpr index 1cd860f804..a6e6619b51 100644 --- a/components/synedit/test/SynTest.lpr +++ b/components/synedit/test/SynTest.lpr @@ -3,7 +3,9 @@ program SynTest; {$mode objfpc}{$H+} uses - Interfaces, Forms, GuiTestRunner, TestSynSelection, LResources, TestBase; + Interfaces, Forms, GuiTestRunner, LResources, + TestBase, + TestSynSelection, TestSynBeautifier; {$IFDEF WINDOWS}{$R SynTest.rc}{$ENDIF} diff --git a/components/synedit/test/testbase.pas b/components/synedit/test/testbase.pas index 07ab2321d5..e53b810e7f 100644 --- a/components/synedit/test/testbase.pas +++ b/components/synedit/test/testbase.pas @@ -1,6 +1,7 @@ unit TestBase; {$mode objfpc}{$H+} +{ $DEFINE WITH_APPMSG} interface @@ -34,8 +35,14 @@ type protected function LinesToText(Lines: Array of String; Separator: String = LineEnding; SeparatorAtEnd: Boolean = False): String; - // Relpl,must be an alteration of LineNum, LineText+ + (* Relpl,must be an alteration of LineNum, LineText+ + [ 3, 'a' ] => replace line 3 with 'a' (old line 3 is deleted) + [ 3, 'a', 'b' ] => replace line 3 with 2 new lines 'a', 'b' (only one old line is deleted) + [ 3 ] => replace line 3 with nothing => delete line 3 + [ -3, 'a' ] => insert a line 'a', at line 3 (current line 3 becomes line 4) + *) function LinesReplace(Lines: Array of String; Repl: Array of const): TStringArray; + function LinesReplaceText(Lines: Array of String; Repl: Array of const): String; protected procedure ReCreateEdit; procedure SetLines(Lines: Array of String); @@ -48,7 +55,8 @@ type procedure SetCaretPhys(X, Y: Integer); procedure SetCaretAndSelPhys(X1, Y1, X2, Y2: Integer; DoLock: Boolean = False); procedure SetCaretAndSelPhysBackward(X1, Y1, X2, Y2: Integer; DoLock: Boolean = False); - procedure DoKeyPress(Key: Word; Shift: TShiftState); + procedure DoKeyPress(Key: Word; Shift: TShiftState = []); + procedure DoKeyPressAtPos(X, Y: Integer; Key: Word; Shift: TShiftState = []); procedure TestFail(Name, Func, Expect, Got: String; Result: Boolean = False); procedure PushBaseName(Add: String); @@ -61,7 +69,7 @@ type procedure SetUp; override; procedure TearDown; override; public - procedure TestIsCaret(Name: String; X, Y: Integer); + procedure TestIsCaret(Name: String; X, Y: Integer); // logical caret procedure TestIsCaretPhys(Name: String; X, Y: Integer); // exclude trimspaces, as seen by other objects @@ -107,6 +115,7 @@ begin if c <> '' then UTF8KeyPress(c); KeyUp(Key, Shift); + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; function TTestSynEdit.TestFullText: String; @@ -254,9 +263,13 @@ begin vtInteger: begin j := Repl[i].vinteger - 1; - for k := j to high(Result) - 1 do - Result[k] := Result[k+1]; - SetLength(Result, length(Result)-1); + if j < 0 + then j := -j-2 + else begin + for k := j to high(Result) - 1 do + Result[k] := Result[k+1]; + SetLength(Result, length(Result)-1); + end; end; vtString, vtAnsiString, vtChar: begin @@ -277,6 +290,12 @@ begin end; end; +function TTestBase.LinesReplaceText(Lines: array of String; + Repl: array of const): String; +begin + Result := LinesToText(LinesReplace(Lines, Repl)); +end; + procedure TTestBase.ReCreateEdit; begin FreeAndNil(FSynEdit); @@ -285,18 +304,20 @@ begin FSynEdit.Top := 0; FSynEdit.Left := 0; FSynEdit.Width:= 500; - FSynEdit.Height := FSynEdit.Font.Height * 20 + 2; + FSynEdit.Height := 200; // FSynEdit.Font.Height * 20 + 2; end; procedure TTestBase.SetLines(Lines: array of String); begin SynEdit.Text := LinesToText(Lines); + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; procedure TTestBase.SetCaret(X, Y: Integer); begin SynEdit.BlockBegin := Point(X, Y); SynEdit.LogicalCaretXY := Point(X, Y); + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; procedure TTestBase.SetCaretAndSel(X1, Y1, X2, Y2: Integer; DoLock: Boolean = False); @@ -316,6 +337,7 @@ begin SynEdit.BlockEnd := Point(X2, Y2); if DoLock then SynEdit.EndUpdate; + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; procedure TTestBase.SetCaretAndSelBackward(X1, Y1, X2, Y2: Integer; DoLock: Boolean = False); @@ -335,12 +357,14 @@ begin SynEdit.BlockEnd := Point(X2, Y2); if DoLock then SynEdit.EndUpdate; + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; procedure TTestBase.SetCaretPhys(X, Y: Integer); begin SynEdit.LogicalCaretXY := Point(X, Y); SynEdit.BlockBegin := SynEdit.LogicalCaretXY; + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; procedure TTestBase.SetCaretAndSelPhys(X1, Y1, X2, Y2: Integer; DoLock: Boolean); @@ -360,6 +384,7 @@ begin SynEdit.BlockEnd := SynEdit.PhysicalToLogicalPos(Point(X2, Y2)); if DoLock then SynEdit.EndUpdate; + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; procedure TTestBase.SetCaretAndSelPhysBackward(X1, Y1, X2, Y2: Integer; DoLock: Boolean); @@ -379,11 +404,19 @@ begin SynEdit.BlockEnd := SynEdit.PhysicalToLogicalPos(Point(X2, Y2)); if DoLock then SynEdit.EndUpdate; + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} end; -procedure TTestBase.DoKeyPress(Key: Word; Shift: TShiftState); +procedure TTestBase.DoKeyPress(Key: Word; Shift: TShiftState = []); begin SynEdit.TestKeyPress(Key, Shift); + {$IFDEF WITH_APPMSG}Application.ProcessMessages;{$ENDIF} +end; + +procedure TTestBase.DoKeyPressAtPos(X, Y: Integer; Key: Word; Shift: TShiftState = []); +begin + SetCaret(X, Y); + DoKeyPress(Key, Shift); end; procedure TTestBase.PushBaseName(Add: String); diff --git a/components/synedit/test/testsynbeautifier.pas b/components/synedit/test/testsynbeautifier.pas new file mode 100644 index 0000000000..4408bececc --- /dev/null +++ b/components/synedit/test/testsynbeautifier.pas @@ -0,0 +1,445 @@ +unit TestSynBeautifier; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, fpcunit, testutils, testregistry, TestBase, + SynEdit, SynEditTypes, SynEditTextTrimmer, SynEditKeyCmds, SynBeautifier, + LCLType, LCLProc; + +type + + { TTestSynSelection } + + { TTestSynBeautifier } + + TTestSynBeautifier = class(TTestBase) + protected + procedure TestRedoUndo(Name: String; Text: Array of String; X, Y: Integer; Data: Array of const); + published + (* Test includes: + - no indent if switched off + - indent after VK_RETURN + - indent after CTRL-VK_N (TODO) + * handling split indent (return in the middle of the leading space; next line is already part indented) + * VK_Return on pos=1, keeps indent. line without indent will *not* be indented + * with/without trim spaces + * undo/redo/group-undo + * correct indent from tabs (include split indent) + * correct indent from several lines above (skip empty lines to find indent) VK_RETURN only + * indent modes: sbitSpace, sbitCopySpaceTab, sbitPositionCaret + *) + procedure DefaultIndent; + (* + - no unindent, if selection (none persistent) (TODO) + *) + //procedure DefaultUnIndent; + + + end; + + +implementation + +{ TTestSynBeautifier } + +procedure TTestSynBeautifier.TestRedoUndo(Name: String; Text: Array of String; + X, Y: Integer; Data: array of const); + + function data2txt(n: Integer): String; + begin + if n < 0 then exit(LinesToText(Text)); + Result := ''; + case data[n].VType of + vtString: Result := data[n].VString^; + vtAnsiString: Result := AnsiString(data[n].VAnsiString); + vtChar: Result := data[n].VChar; + end; + end; + +var + i: integer; + st: TShiftState; +begin + PushBaseName(Name + '(no group-undo)'); + SetLines(Text); + SetCaret(X, Y); + SynEdit.Options := SynEdit.Options - [eoGroupUndo]; + for i := 0 to length(data) div 4 - 1 do begin + st := []; + if data[i*4+0].vinteger = VK_N then st := [ssCtrl]; + DoKeyPress(data[i*4+0].vinteger, st); + TestIsCaret('Key #'+IntToStr(i), data[i*4+1].vinteger, data[i*4+2].vinteger); + TestIsFullText('Key #'+IntToStr(i), data2txt(i*4+3)); + end; + + for i := length(data) div 4 - 2 downto -1 do begin + SynEdit.Undo; + if i >= 0 + then TestIsCaret('Undo #'+IntToStr(i+1), data[i*4+1].vinteger, data[i*4+2].vinteger) + else TestIsCaret('Undo #'+IntToStr(i+1), x, y); + TestIsFullText('Undo #'+IntToStr(i+1), data2txt(i*4+3)); + end; + + for i := 0 to length(data) div 4 - 1 do begin + SynEdit.Redo; + TestIsCaret('Redo #'+IntToStr(i), data[i*4+1].vinteger, data[i*4+2].vinteger); + TestIsFullText('Redo #'+IntToStr(i), data2txt(i*4+3)); + end; + + for i := length(data) div 4 - 2 downto -1 do begin + SynEdit.Undo; + if i >= 0 + then TestIsCaret('2nd Undo Key #'+IntToStr(i+1), data[i*4+1].vinteger, data[i*4+2].vinteger) + else TestIsCaret('2nd Undo Key #'+IntToStr(i+1), x, y); + TestIsFullText('2nd Undo #'+IntToStr(i+1), data2txt(i*4+3)); + end; + + PopPushBaseName(Name + '(group-undo)'); + SetLines(Text); + SetCaret(X, Y); + SynEdit.Options := SynEdit.Options + [eoGroupUndo]; + for i := 0 to length(data) div 4 - 1 do begin + st := []; + if data[i*4+0].vinteger = VK_N then st := [ssCtrl]; + DoKeyPress(data[i*4+0].vinteger, st); + TestIsCaret('Key #'+IntToStr(i), data[i*4+1].vinteger, data[i*4+2].vinteger); + TestIsFullText('Key #'+IntToStr(i), data2txt(i*4+3)); + end; + + SynEdit.Undo; + TestIsCaret('Undo', x, y); + TestIsFullText('Undo', Text); + + SynEdit.Redo; + i := length(data) div 4 - 1; + TestIsCaret('Redo', data[i*4+1].vinteger, data[i*4+2].vinteger); + TestIsFullText('Redo', data2txt(i*4+3)); + + SynEdit.Undo; + TestIsCaret('2nd Undo', x, y); + TestIsFullText('2nd Undo', Text); + + PopBaseName; +end; + +procedure TTestSynBeautifier.DefaultIndent; + function TestText: TStringArray; + begin + SetLength(Result, 11); + Result[0] := ' a;'; + Result[1] := ' b'; + Result[2] := ''; + Result[3] := ' c'; + Result[5] := ''; + Result[6] := ''; + Result[7] := #9+'x'; + Result[8] := #32#9#32#32#9+'x'; // 8 indent ( 5 logical) + Result[9] := ' c'; + Result[10] := ''; + end; + function ExpText(rpl: array of const): String; + begin + Result := LinesToText(LinesReplace(TestText, rpl)) + end; + + function TestText2: TStringArray; + begin + SetLength(Result, 6); + Result[0] := ' a;'; + Result[1] := 'b'; // not indent + Result[2] := ' a;'; + Result[3] := ''; + Result[4] := 'b'; // not indent, after empty line + Result[5] := ''; + end; + function ExpText2(rpl: array of const): String; + begin + Result := LinesToText(LinesReplace(TestText2, rpl)) + end; + +begin + ReCreateEdit; + SynEdit.TabWidth := 4; + SynEdit.TrimSpaceType := settMoveCaret; + {%region ***** Test WITHOUT indent (no trim) *****} + BaseTestName := 'DefaultIndent (no indent, no trim)'; + SynEdit.Options := SynEdit.Options - [eoTrimTrailingSpaces, eoScrollPastEol, eoAutoIndent]; + + TestRedoUndo('Return EOL', TestText, 5,1, [ VK_RETURN, 1, 2, ExpText([ -2, '']) ] ); + TestRedoUndo('Return empty line', TestText, 1,3, [ VK_RETURN, 1, 4, ExpText([ -4, '']) ] ); + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 1, 3, ExpText([ 2, ' ', 'b']) ] ); // NOT trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 1, 3, ExpText([ 2, ' ', ' b']) ] ); // NOT trimmed + // VK_N will be ctrl-n (special detection in TestRedoUndo + TestRedoUndo('CTRL-N EOL', TestText, 5,1, [ VK_N, 5, 1, ExpText([ -2, '']) ] ); + {%endregion} + + {%region ***** Test WITHOUT indent (trim) *****} + BaseTestName := 'DefaultIndent (trim, no indent)'; + SynEdit.Options := SynEdit.Options - [eoScrollPastEol, eoAutoIndent] + [eoTrimTrailingSpaces]; + + TestRedoUndo('Return EOL', TestText, 5,1, [ VK_RETURN, 1, 2, ExpText([ -2, '']) ] ); + TestRedoUndo('Return empty line', TestText, 1,3, [ VK_RETURN, 1, 4, ExpText([ -4, '']) ] ); + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 1, 3, ExpText([ 2, '', 'b']) ] ); // trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 1, 3, ExpText([ 2, '', ' b']) ] ); // trimmed + {%endregion} + + {%region ***** Test WITHOUT trim *****} + {%region sbitSpaces} + BaseTestName := 'DefaultIndent (no trim)'; + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitSpace; + + SynEdit.Options := SynEdit.Options - [eoTrimTrailingSpaces, eoScrollPastEol, eoTabsToSpaces] + [eoAutoIndent]; + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitSpace; + + + + TestRedoUndo('Return EOL', TestText, 5,1, [ VK_RETURN, 3, 2, ExpText([ -2, ' ']) ] ); + TestRedoUndo('Return EOL+EOT', TestText, 5,10,[ VK_RETURN, 4,11, ExpText([ -11,' ']) ] ); + TestRedoUndo('Return empty line', TestText, 1,3, [ VK_RETURN, 5, 4, ExpText([ -4, ' ']) ] ); + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 5, 3, ExpText([ -2, ' ']) ] ); // NOT trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 4, 3, ExpText([ -2, ' ']) ] ); // NOT trimmed + + TestRedoUndo('Many Return EOL', TestText, 5,1, [ + VK_RETURN, 3, 2, ExpText([ -2, ' ']), + VK_RETURN, 3, 3, ExpText([ -2, ' ', ' ']), + VK_RETURN, 3, 4, ExpText([ -2, ' ', ' ', ' ']) + ]); + TestRedoUndo('Many Return EOL+EOT', TestText, 5,10, [ + VK_RETURN, 4,11, ExpText([ -11, ' ']), + VK_RETURN, 4,12, ExpText([ -11, ' ', ' ']), + VK_RETURN, 4,13, ExpText([ -11, ' ', ' ', ' ']) + ]); + TestRedoUndo('Many Return empty line', TestText, 1,3, [ + VK_RETURN, 5, 4, ExpText([ -4, ' ']), + VK_RETURN, 5, 5, ExpText([ -4, ' ', ' ']), + VK_RETURN, 5, 6, ExpText([ -4, ' ', ' ', ' ']) + ]); + TestRedoUndo('Many Return after space', TestText, 5,2, [ + VK_RETURN, 5, 3, ExpText([ -2, ' ']), // NOT trimmed + VK_RETURN, 5, 4, ExpText([ -2, ' ', ' ']), // NOT trimmed + VK_RETURN, 5, 5, ExpText([ -2, ' ', ' ', ' ']) // NOT trimmed + ]); + TestRedoUndo('Many Return before space', TestText, 1,2, [ + VK_RETURN, 1, 3, ExpText([ -2, '']), + VK_RETURN, 1, 4, ExpText([ -2, '', '']), + VK_RETURN, 1, 5, ExpText([ -2, '', '', '']) + ]); + TestRedoUndo('Many Return mid space', TestText, 4,2, [ + VK_RETURN, 4, 3, ExpText([ -2, ' ']), // NOT trimmed + VK_RETURN, 4, 4, ExpText([ -2, ' ', ' ']), // NOT trimmed + VK_RETURN, 4, 5, ExpText([ -2, ' ', ' ', ' ']) // NOT trimmed + ]); + + TestRedoUndo('Return multi empty', TestText, 1,7, [ VK_RETURN, 4, 8, ExpText([ -8, ' ']) ] ); + TestRedoUndo('Return at pos1 of unindeted', TestText2, 1,2, [ VK_RETURN, 1, 3, ExpText2([ -2, '']) ] ); + TestRedoUndo('Return at pos1 of unindeted 2', TestText2, 1,5, [ VK_RETURN, 1, 6, ExpText2([ -5, '']) ] ); + + // caret pos are logical + TestRedoUndo('Return after tab', TestText, 6,9, [ VK_RETURN, 9,10, ExpText([ 9, #32#9#32#32#9, ' x']) ] ); + TestRedoUndo('Return before tab', TestText, 1,9, [ VK_RETURN, 1,10, ExpText([-9, '']) ] ); + TestRedoUndo('Return middle tab 1', TestText, 3,9, [ VK_RETURN, 5,10, ExpText([ 9, #32#9, ' '+#32#32#9+'x']) ] ); + TestRedoUndo('Return middle tab 2', TestText, 4,9, [ VK_RETURN, 6,10, ExpText([ 9, #32#9#32, ' '+#32#9+'x']) ] ); + TestRedoUndo('Return tab EOL', TestText, 7,9, [ VK_RETURN, 9,10, ExpText([-10, ' ']) ] ); + {%endregion} + + (* *** *) + {%region sbitCopySpaceTab} + PushBaseName('CopySpaceTab'); + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitCopySpaceTab; + + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 5, 3, ExpText([ -2, ' ']) ] ); // NOT trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 4, 3, ExpText([ -2, ' ']) ] ); // NOT trimmed + + TestRedoUndo('Return after tab', TestText, 6,9, [ VK_RETURN, 6,10, ExpText([ 9, #32#9#32#32#9, #32#9#32#32#9+'x']) ] ); + TestRedoUndo('Return before tab', TestText, 1,9, [ VK_RETURN, 1,10, ExpText([-9, '']) ] ); + TestRedoUndo('Return middle tab 1', TestText, 3,9, [ VK_RETURN, 3,10, ExpText([ 9, #32#9, #32#9#32#32#9+'x']) ] ); + TestRedoUndo('Return middle tab 2', TestText, 4,9, [ VK_RETURN, 4,10, ExpText([ 9, #32#9#32, #32#9#32#32#9+'x']) ] ); + TestRedoUndo('Return tab EOL', TestText, 7,9, [ VK_RETURN, 6,10, ExpText([-10, #32#9#32#32#9]) ] ); + TestRedoUndo('Many Return tab EOL', TestText, 7,9, [ + VK_RETURN, 6,10, ExpText([-10, #32#9#32#32#9]), + VK_RETURN, 6,11, ExpText([-10, #32#9#32#32#9, #32#9#32#32#9]), + VK_RETURN, 6,12, ExpText([-10, #32#9#32#32#9, #32#9#32#32#9, #32#9#32#32#9]) + ]); + {%endregion} + + (* *** *) + {%region sbitPosCaret} + PopPushBaseName('PosCaret'); + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitPositionCaret; + + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 5, 3, ExpText([ -2, ' ']) ] ); // NOT trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 4, 3, ExpText([ -2, ' ']) ] ); // NOT trimmed + TestRedoUndo('Return eol', TestText, 6,2, [ VK_RETURN, 5, 3, ExpText([ -3, '']) ] ); // position only + TestRedoUndo('Many Return eol', TestText, 6,2, [ // position only + VK_RETURN, 5, 3, ExpText([ -3, '']), + VK_RETURN, 5, 4, ExpText([ -3, '', '']), + VK_RETURN, 5, 5, ExpText([ -3, '', '', '']) + ]); + + TestRedoUndo('Return after tab', TestText, 6,9, [ VK_RETURN, 9,10, ExpText([ 9, #32#9#32#32#9, ' '+'x']) ] ); + TestRedoUndo('Return before tab', TestText, 1,9, [ VK_RETURN, 1,10, ExpText([-9, '']) ] ); + TestRedoUndo('Return middle tab 1', TestText, 3,9, [ VK_RETURN, 5,10, ExpText([ 9, #32#9, ' '+#32#32#9+'x']) ] ); + TestRedoUndo('Return middle tab 2', TestText, 4,9, [ VK_RETURN, 6,10, ExpText([ 9, #32#9#32, ' '+#32#9+'x']) ] ); + TestRedoUndo('Return tab EOL', TestText, 7,9, [ VK_RETURN, 9,10, ExpText([-10, '']) ] ); // pos only + TestRedoUndo('Many Return tab EOL', TestText, 7,9, [ + VK_RETURN, 9,10, ExpText([-10, '']), // pos only + VK_RETURN, 9,11, ExpText([-10, '', '']), + VK_RETURN, 9,12, ExpText([-10, '', '', '']) + ]); + {%endregion} + + {%region CTRL-N} + PopPushBaseName('SpaceOnly'); + // VK_N will be ctrl-n (special detection in TestRedoUndo + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitSpace; + TestRedoUndo('CTRL-N EOL', TestText, 5,1, [ VK_N, 5, 1, ExpText([ -2, ' ']) ] ); + TestRedoUndo('Many CTRL-N EOL', TestText, 5,1, [ + VK_N, 5, 1, ExpText([ -2, ' ']), + VK_N, 5, 1, ExpText([ -2, ' ', ' ']), + VK_N, 5, 1, ExpText([ -2, ' ', ' ', ' ']) + ]); + + TestRedoUndo('CTRL-N empty line', TestText, 1,3, [ VK_N, 1, 3, ExpText([ -4, ' ']) ] ); // TODO: should it? + //TestRedoUndo('CTRL-N pos1 unindeted',TestText2, 1,2, [ VK_N, 1, 2, ExpText2([ -2, '']) ] ); // TODO: must not + + TestRedoUndo('CTRL-N after space', TestText, 5,2, [ VK_N, 5, 2, ExpText([ -2, ' ']) ] ); // NOT trimmed + //TestRedoUndo('CTRL-N before space', TestText, 1,2, [ VK_N, 1, 2, ExpText([ -2, '']) ] ); // TODO: indents too much + TestRedoUndo('CTRL-N mid space', TestText, 4,2, [ VK_N, 4, 2, ExpText([ -2, ' ']) ] ); // NOT trimmed + + + PopPushBaseName('CopySpacetab'); + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitCopySpaceTab; + TestRedoUndo('CTRL-N EOL', TestText, 5,1, [ VK_N, 5, 1, ExpText([ -2, ' ']) ] ); + + PopPushBaseName('PosOnly'); + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitPositionCaret; + TestRedoUndo('CTRL-N EOL', TestText, 5,1, [ VK_N, 5, 1, ExpText([ -2, '']) ] ); + + {%endregion} + + {%endregion} + + {%region ***** Test WITH trim *****} + {%region sbitSpaces} + BaseTestName := 'DefaultIndent (trim)'; + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitSpace; + + SynEdit.Options := SynEdit.Options - [eoScrollPastEol] + [eoTrimTrailingSpaces, eoAutoIndent]; + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitSpace; //, sbitCopySpaceTab, sbitPositionCaret + + + TestRedoUndo('Return EOL', TestText, 5,1, [ VK_RETURN, 3, 2, ExpText([ -2, ' ']) ] ); + TestRedoUndo('Return EOL+EOT', TestText, 5,10,[ VK_RETURN, 4,11, ExpText([ -11,' ']) ] ); + TestRedoUndo('Return empty line', TestText, 1,3, [ VK_RETURN, 5, 4, ExpText([ -4, ' ']) ] ); + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 5, 3, ExpText([ -2, '']) ] ); // trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 4, 3, ExpText([ -2, '']) ] ); // trimmed + + TestRedoUndo('Many Return EOL', TestText, 5,1, [ + VK_RETURN, 3, 2, ExpText([ -2, ' ']), + VK_RETURN, 3, 3, ExpText([ -2, '', ' ']), // trimmed + VK_RETURN, 3, 4, ExpText([ -2, '', '', ' ']) + ]); + TestRedoUndo('Many Return EOL+EOT', TestText, 5,10, [ + VK_RETURN, 4,11, ExpText([ -11, ' ']), + VK_RETURN, 4,12, ExpText([ -11, '', ' ']), // trimmed + VK_RETURN, 4,13, ExpText([ -11, '', '', ' ']) + ]); + TestRedoUndo('Many Return empty line', TestText, 1,3, [ + VK_RETURN, 5, 4, ExpText([ -4, ' ']), + VK_RETURN, 5, 5, ExpText([ -4, '', ' ']), // trimmed + VK_RETURN, 5, 6, ExpText([ -4, '', '', ' ']) + ]); + TestRedoUndo('Many Return after space', TestText, 5,2, [ + VK_RETURN, 5, 3, ExpText([ -2, '']), // trimmed + VK_RETURN, 5, 4, ExpText([ -2, '', '']), // trimmed + VK_RETURN, 5, 5, ExpText([ -2, '', '', '']) // trimmed + ]); + TestRedoUndo('Many Return before space', TestText, 1,2, [ + VK_RETURN, 1, 3, ExpText([ -2, '']), + VK_RETURN, 1, 4, ExpText([ -2, '', '']), + VK_RETURN, 1, 5, ExpText([ -2, '', '', '']) + ]); + TestRedoUndo('Many Return mid space', TestText, 4,2, [ + VK_RETURN, 4, 3, ExpText([ -2, '']), // trimmed + VK_RETURN, 4, 4, ExpText([ -2, '', '']), // trimmed + VK_RETURN, 4, 5, ExpText([ -2, '', '', '']) // trimmed + ]); + + TestRedoUndo('Return multi empty', TestText, 1,7, [ VK_RETURN, 4, 8, ExpText([ -8, ' ']) ] ); + TestRedoUndo('Return at pos1 of unindeted', TestText2, 1,2, [ VK_RETURN, 1, 3, ExpText2([ -2, '']) ] ); + TestRedoUndo('Return at pos1 of unindeted 2', TestText2, 1,5, [ VK_RETURN, 1, 6, ExpText2([ -5, '']) ] ); + + // caret pos are logical + TestRedoUndo('Return after tab', TestText, 6,9, [ VK_RETURN, 9,10, ExpText([ 9, '', ' x']) ] ); + TestRedoUndo('Return before tab', TestText, 1,9, [ VK_RETURN, 1,10, ExpText([-9, '']) ] ); + TestRedoUndo('Return middle tab 1', TestText, 3,9, [ VK_RETURN, 5,10, ExpText([ 9, '', ' '+#32#32#9+'x']) ] ); + TestRedoUndo('Return middle tab 2', TestText, 4,9, [ VK_RETURN, 6,10, ExpText([ 9, '', ' '+#32#9+'x']) ] ); + TestRedoUndo('Return tab EOL', TestText, 7,9, [ VK_RETURN, 9,10, ExpText([-10, ' ']) ] ); + {%endregion} + + (* *** *) + {%region sbitCopySpaceTab} + PushBaseName('CopySpaceTab'); + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitCopySpaceTab; + + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 5, 3, ExpText([ -2, '']) ] ); // trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 4, 3, ExpText([ -2, '']) ] ); // trimmed + + TestRedoUndo('Return after tab', TestText, 6,9, [ VK_RETURN, 6,10, ExpText([ 9, '', #32#9#32#32#9+'x']) ] ); + TestRedoUndo('Return before tab', TestText, 1,9, [ VK_RETURN, 1,10, ExpText([-9, '']) ] ); + TestRedoUndo('Return middle tab 1', TestText, 3,9, [ VK_RETURN, 3,10, ExpText([ 9, '', #32#9#32#32#9+'x']) ] ); + TestRedoUndo('Return middle tab 2', TestText, 4,9, [ VK_RETURN, 4,10, ExpText([ 9, '', #32#9#32#32#9+'x']) ] ); + TestRedoUndo('Return tab EOL', TestText, 7,9, [ VK_RETURN, 6,10, ExpText([-10, #32#9#32#32#9]) ] ); + TestRedoUndo('Many Return tab EOL', TestText, 7,9, [ + VK_RETURN, 6,10, ExpText([-10, #32#9#32#32#9]), + VK_RETURN, 6,11, ExpText([-10, '', #32#9#32#32#9]), + VK_RETURN, 6,12, ExpText([-10, '', '', #32#9#32#32#9]) + ]); + {%endregion} + + (* *** *) + {%region sbitPosCaret} + PopPushBaseName('PosCaret'); + TSynBeautifier(SynEdit.Beautifier).IndentType := sbitPositionCaret; + + TestRedoUndo('Return after space', TestText, 5,2, [ VK_RETURN, 5, 3, ExpText([ -2, '']) ] ); // trimmed + TestRedoUndo('Return before space', TestText, 1,2, [ VK_RETURN, 1, 3, ExpText([ -2, '']) ] ); + TestRedoUndo('Return mid space', TestText, 4,2, [ VK_RETURN, 4, 3, ExpText([ -2, '']) ] ); //trimmed + TestRedoUndo('Return eol', TestText, 6,2, [ VK_RETURN, 5, 3, ExpText([ -3, '']) ] ); // position only + TestRedoUndo('Many Return eol', TestText, 6,2, [ // position only + VK_RETURN, 5, 3, ExpText([ -3, '']), + VK_RETURN, 5, 4, ExpText([ -3, '', '']), + VK_RETURN, 5, 5, ExpText([ -3, '', '', '']) + ]); + + TestRedoUndo('Return after tab', TestText, 6,9, [ VK_RETURN, 9,10, ExpText([ 9, '', ' '+'x']) ] ); + TestRedoUndo('Return before tab', TestText, 1,9, [ VK_RETURN, 1,10, ExpText([-9, '']) ] ); + TestRedoUndo('Return middle tab 1', TestText, 3,9, [ VK_RETURN, 5,10, ExpText([ 9, '', ' '+#32#32#9+'x']) ] ); + TestRedoUndo('Return middle tab 2', TestText, 4,9, [ VK_RETURN, 6,10, ExpText([ 9, '', ' '+#32#9+'x']) ] ); + TestRedoUndo('Return tab EOL', TestText, 7,9, [ VK_RETURN, 9,10, ExpText([-10, '']) ] ); // pos only + TestRedoUndo('Many Return tab EOL', TestText, 7,9, [ + VK_RETURN, 9,10, ExpText([-10, '']), // pos only + VK_RETURN, 9,11, ExpText([-10, '', '']), + VK_RETURN, 9,12, ExpText([-10, '', '', '']) + ]); + {%endregion} + + {%endregion} + +end; + +initialization + + RegisterTest(TTestSynBeautifier); +end. + diff --git a/components/synedit/test/testsynselection.pas b/components/synedit/test/testsynselection.pas index 3ec0475aeb..90a1e85b46 100644 --- a/components/synedit/test/testsynselection.pas +++ b/components/synedit/test/testsynselection.pas @@ -34,8 +34,15 @@ type procedure TestIsNoBlock(Name: String); published procedure SelectByKey; + + (* Test for selection via the following Methods: + SelectWord /.SelectLine / SelectParagraph / SelectAll / SelectToBrace + [ BeginUpdate; BlockBegin := ; BlockEnd := ; EndUpdatel ] + *) procedure SelectByMethod; + procedure ReplaceSelText; + //Temporarily here, till we have more units procedure TextDelCmd; end; @@ -1224,7 +1231,7 @@ procedure TTestSynSelection.ReplaceSelText; TestReplace('3 Line Middle, y2 past eol = X/Y/Z', 8,3, 12,5, ['a',' ','ö'], ['X','Y','Z'], 9,5, [3,' Foo(bXr);', 4,' abc; Y', 5,' // äüZäabc']); TestReplace('3 Line Middle (bck), y2 past eol = X/Y/Z', 9,3, 10,5, ['a',' ','ö'], ['X','Y','Z'], 9,5, [3,' Foo(bXr);', 4,' abc; Y', 5,' // äüZäabc']); - // Todo: multiline insert at last line of text + // multiline insert at last line of text TestReplace('Below Last Line = X/Y', 1,7,-1,-1, [''], ['X','Y','Z'], 2,9, [7, 'X', 'Y', 'Z']); {%endregion}