mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-27 13:00:17 +02:00
SynEdit: Cleanup (Beautifier)
git-svn-id: trunk@20471 -
This commit is contained in:
parent
7a9d3e8f22
commit
dd531e749d
@ -40,27 +40,26 @@ unit SynBeautifier;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, SynEditMiscClasses, SynEditTextBase;
|
||||
Classes, SysUtils, SynEditMiscClasses, SynEditTextBase, SynEditPointClasses;
|
||||
|
||||
type
|
||||
{ TSynCustomBeautifier }
|
||||
|
||||
TSynCustomBeautifier = class(TComponent)
|
||||
public
|
||||
function CanUnindent(const Editor: TSynEditBase; const Line: string;
|
||||
const PhysCaretX: Integer): Boolean; virtual; abstract;
|
||||
function UnIndentLine(const Editor: TSynEditBase; const Line: string;
|
||||
const Lines: TSynEditStrings; const PhysCaret: TPoint;
|
||||
out DelChars, InsChars: String;
|
||||
out CaretNewX: Integer): String; virtual; abstract; // Todo InsChar are not supprted for undo
|
||||
function IndentLine(const Editor: TSynEditBase; Line: string;
|
||||
const Lines: TSynEditStrings; const PhysCaret: TPoint;
|
||||
out DelChars, InsChars: String; out CaretNewX: Integer;
|
||||
RemoveCurrentIndent: Boolean = False): String;
|
||||
virtual; abstract; // Todo DelChar are not supprted for undo
|
||||
function GetIndentForLine(Editor: TSynEditBase; const Line: string;
|
||||
const Lines: TSynEditStrings;
|
||||
const PhysCaret: TPoint): Integer; virtual; abstract;
|
||||
function CanUnindent(const Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret): Boolean; virtual; abstract;
|
||||
function UnIndentLine(const Editor: TSynEditBase;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret;
|
||||
out CaretNewX: Integer): Boolean; virtual; abstract; // Todo InsChar are not supprted for undo
|
||||
function IndentLine(const Editor: TSynEditBase;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret;
|
||||
out CaretNewX: Integer): Boolean; virtual; abstract; // Todo DelChar are not supprted for undo
|
||||
function GetDesiredIndentForLine(Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret): Integer; virtual; abstract;
|
||||
function GetDesiredIndentForLine(Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret;
|
||||
out DesiredIndent: String): Integer; virtual; abstract;
|
||||
end;
|
||||
|
||||
TSynBeautifierIndentType = (sbitSpace, sbitCopySpaceTab, sbitPositionCaret);
|
||||
@ -71,21 +70,20 @@ type
|
||||
private
|
||||
FIndentType: TSynBeautifierIndentType;
|
||||
public
|
||||
function LeftSpaces(Editor: TSynEditBase; const Line: string;
|
||||
function GetCurrentIndent(Editor: TSynEditBase; const Line: string;
|
||||
Physical: boolean): Integer;
|
||||
function CanUnindent(const Editor: TSynEditBase; const Line: string;
|
||||
const PhysCaretX: Integer): Boolean; override;
|
||||
function UnIndentLine(const Editor: TSynEditBase; const Line: string;
|
||||
const Lines: TSynEditStrings; const PhysCaret: TPoint;
|
||||
out DelChars, InsChars: String;
|
||||
out CaretNewX: Integer): String; override; // Todo InsChar are not supprted for undo
|
||||
function IndentLine(const Editor: TSynEditBase; Line: string;
|
||||
const Lines: TSynEditStrings; const PhysCaret: TPoint;
|
||||
out DelChars, InsChars: String; out CaretNewX: Integer;
|
||||
RemoveCurrentIndent: Boolean = False): String; override; // Todo DelChar are not supprted for undo
|
||||
function GetIndentForLine(Editor: TSynEditBase; const Line: string;
|
||||
const Lines: TSynEditStrings;
|
||||
const PhysCaret: TPoint): Integer; override;
|
||||
function CanUnindent(const Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret): Boolean; override;
|
||||
function UnIndentLine(const Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret; out CaretNewX: Integer
|
||||
): Boolean; override; // Todo InsChar are not supprted for undo
|
||||
function IndentLine(const Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret; out CaretNewX: Integer): Boolean; override; // Todo DelChar are not supprted for undo
|
||||
function GetDesiredIndentForLine(Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret): Integer; override;
|
||||
function GetDesiredIndentForLine(Editor: TSynEditBase; const Lines: TSynEditStrings;
|
||||
const ACaret: TSynEditCaret;
|
||||
out DesiredIndent: String): Integer; override;
|
||||
published
|
||||
property IndentType: TSynBeautifierIndentType read FIndentType write FIndentType;
|
||||
end;
|
||||
@ -95,7 +93,7 @@ uses SynEdit;
|
||||
|
||||
{ TSynBeautifier }
|
||||
|
||||
function TSynBeautifier.LeftSpaces(Editor: TSynEditBase; const Line: string; Physical: boolean): Integer;
|
||||
function TSynBeautifier.GetCurrentIndent(Editor: TSynEditBase; const Line: string; Physical: boolean): Integer;
|
||||
var
|
||||
p: PChar;
|
||||
begin
|
||||
@ -113,25 +111,27 @@ begin
|
||||
end;
|
||||
|
||||
function TSynBeautifier.CanUnindent(const Editor: TSynEditBase;
|
||||
const Line: string; const PhysCaretX: Integer): Boolean;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret): Boolean;
|
||||
begin
|
||||
Result := (LeftSpaces(Editor, Line, True) = PhysCaretX - 1);
|
||||
Result := (GetCurrentIndent(Editor, ACaret.LineText, True) = ACaret.CharPos - 1);
|
||||
end;
|
||||
|
||||
function TSynBeautifier.UnIndentLine(const Editor: TSynEditBase;
|
||||
const Line: string; const Lines: TSynEditStrings; const PhysCaret: TPoint;
|
||||
out DelChars, InsChars: String; out CaretNewX: Integer): String;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret;
|
||||
out CaretNewX: Integer): Boolean;
|
||||
var
|
||||
SpaceCount1, SpaceCount2: Integer;
|
||||
BackCounter, LogSpacePos: Integer;
|
||||
LogCaret: TPoint;
|
||||
Line: String;
|
||||
begin
|
||||
SpaceCount1 := LeftSpaces(Editor, Line, true);
|
||||
Line := ACaret.LineText;
|
||||
SpaceCount1 := GetCurrentIndent(Editor, Line, true);
|
||||
SpaceCount2 := 0;
|
||||
if (SpaceCount1 > 0) then begin
|
||||
BackCounter := PhysCaret.Y - 2;
|
||||
BackCounter := ACaret.LinePos - 2;
|
||||
while BackCounter >= 0 do begin
|
||||
SpaceCount2 := LeftSpaces(Editor, Lines[BackCounter], true);
|
||||
SpaceCount2 := GetCurrentIndent(Editor, Lines[BackCounter], true);
|
||||
if SpaceCount2 < SpaceCount1 then
|
||||
break;
|
||||
Dec(BackCounter);
|
||||
@ -140,61 +140,63 @@ begin
|
||||
if SpaceCount2 = SpaceCount1 then
|
||||
SpaceCount2 := 0;
|
||||
// remove visible spaces
|
||||
LogSpacePos := TSynEdit(Editor).PhysicalToLogicalCol(Line, PhysCaret.y-1, SpaceCount2 + 1);
|
||||
LogCaret := TSynEdit(Editor).PhysicalToLogicalPos(PhysCaret);
|
||||
LogSpacePos := TSynEdit(Editor).PhysicalToLogicalCol(Line, ACaret.LinePos-1, SpaceCount2 + 1);
|
||||
LogCaret := ACaret.LineBytePos;
|
||||
CaretNewX := SpaceCount2 + 1;
|
||||
Lines.EditDelete(LogSpacePos, PhysCaret.Y, LogCaret.X - LogSpacePos);
|
||||
DelChars := copy(Line, LogSpacePos, LogCaret.X - LogSpacePos);
|
||||
InsChars := ''; // TODO: if tabs were removed, maybe fill-up with spaces
|
||||
Result :=copy(Line, 1, LogSpacePos-1) + copy(Line, LogCaret.X, MaxInt);
|
||||
Lines.EditDelete(LogSpacePos, ACaret.LinePos, LogCaret.X - LogSpacePos);
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TSynBeautifier.IndentLine(const Editor: TSynEditBase; Line: string;
|
||||
const Lines: TSynEditStrings; const PhysCaret: TPoint; out DelChars,
|
||||
InsChars: String; out CaretNewX: Integer; RemoveCurrentIndent: Boolean): String;
|
||||
function TSynBeautifier.IndentLine(const Editor: TSynEditBase;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret;
|
||||
out CaretNewX: Integer): Boolean;
|
||||
var
|
||||
IndentPos: Integer;
|
||||
InsChars: String;
|
||||
begin
|
||||
IndentPos := GetDesiredIndentForLine(Editor, Lines, ACaret, InsChars);
|
||||
if IndentPos < 0 then
|
||||
exit(False);
|
||||
|
||||
if (FIndentType = sbitPositionCaret) and (ACaret.LineText = '') then
|
||||
InsChars := '';
|
||||
|
||||
Lines.EditInsert(1, ACaret.LinePos, InsChars);
|
||||
CaretNewX := IndentPos;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TSynBeautifier.GetDesiredIndentForLine(Editor: TSynEditBase;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret; out
|
||||
DesiredIndent: String): Integer;
|
||||
var
|
||||
SpaceCount1, SpaceCount2: Integer;
|
||||
BackCounter: Integer;
|
||||
Temp: string;
|
||||
begin
|
||||
DelChars := '';
|
||||
If RemoveCurrentIndent then begin
|
||||
SpaceCount1 := LeftSpaces(Editor, Line, False);
|
||||
DelChars := copy(Line, 1, SpaceCount1);
|
||||
Line := copy(Line, SpaceCount1 + 1, MaxInt);
|
||||
end;
|
||||
|
||||
SpaceCount2 := 0;
|
||||
BackCounter := PhysCaret.Y - 1;
|
||||
Result := 0;
|
||||
BackCounter := ACaret.LinePos - 1;
|
||||
if BackCounter > 0 then
|
||||
repeat
|
||||
Dec(BackCounter);
|
||||
Temp := Lines[BackCounter];
|
||||
SpaceCount2 := LeftSpaces(Editor, Temp, True);
|
||||
Result := GetCurrentIndent(Editor, Temp, True) + 1;
|
||||
until (BackCounter = 0) or (Temp <> '');
|
||||
|
||||
case FIndentType of
|
||||
sbitSpace:
|
||||
InsChars := StringOfChar(' ', SpaceCount2);
|
||||
sbitCopySpaceTab:
|
||||
InsChars := copy(Temp, 1, TSynEdit(Editor).PhysicalToLogicalCol(Temp,
|
||||
BackCounter, SpaceCount2+1)-1);
|
||||
sbitPositionCaret:
|
||||
if Line <> '' then
|
||||
InsChars := StringOfChar(' ', SpaceCount2)
|
||||
else
|
||||
InsChars := '';
|
||||
DesiredIndent := copy(Temp, 1,
|
||||
TSynEdit(Editor).PhysicalToLogicalCol(Temp, BackCounter, Result) - 1);
|
||||
else
|
||||
DesiredIndent := StringOfChar(' ', Result - 1);
|
||||
end;
|
||||
Result := InsChars;
|
||||
CaretNewX := TSynEdit(Editor).LogicalToPhysicalCol(Result + Line, PhysCaret.y - 1, SpaceCount2+1);
|
||||
end;
|
||||
|
||||
function TSynBeautifier.GetIndentForLine(Editor: TSynEditBase;
|
||||
const Line: string; const Lines: TSynEditStrings; const PhysCaret: TPoint): Integer;
|
||||
function TSynBeautifier.GetDesiredIndentForLine(Editor: TSynEditBase;
|
||||
const Lines: TSynEditStrings; const ACaret: TSynEditCaret): Integer;
|
||||
var
|
||||
s1, s2: string;
|
||||
Dummy: String;
|
||||
begin
|
||||
IndentLine(Editor, Line, Lines, PhysCaret, s1, s2, Result, False);
|
||||
Result := GetDesiredIndentForLine(Editor, Lines, ACaret, Dummy);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -6007,11 +6007,10 @@ begin
|
||||
end else begin
|
||||
// delete text before the caret
|
||||
if (eoAutoIndent in fOptions) and
|
||||
FBeautifier.CanUnindent(Self, Temp, CaretX) then
|
||||
FBeautifier.CanUnindent(Self, FTheLinesView , FCaret) then
|
||||
begin
|
||||
// unindent
|
||||
FBeautifier.UnIndentLine(Self, Temp, ViewedTextBuffer,
|
||||
CaretXY, Helper, Temp2, CX);
|
||||
FBeautifier.UnIndentLine(Self, ViewedTextBuffer, FCaret, CX);
|
||||
CaretX := CX;
|
||||
fLastCaretX := CaretX;
|
||||
StatusChanged([scCaretX]);
|
||||
@ -6137,12 +6136,11 @@ begin
|
||||
FTheLinesView.EditLineBreak(LogCaretXY.X, LogCaretXY.Y);
|
||||
if (eoAutoIndent in fOptions) and ((LogCaretXY.X > 1) or (Len = 0)) then
|
||||
begin
|
||||
Caret := CaretXY;
|
||||
Caret.Y := Caret.Y + 1;
|
||||
FTheLinesView.EditInsert(1, LogCaretXY.Y + 1,
|
||||
FBeautifier.IndentLine
|
||||
(Self, FTheLinesView[CaretY], ViewedTextBuffer,
|
||||
Caret, Helper, Temp, CX, False));
|
||||
FInternalCaret.AssignFrom(FCaret);
|
||||
FInternalCaret.IncForcePastEOL;
|
||||
FInternalCaret.LinePos := FInternalCaret.LinePos + 1;
|
||||
FBeautifier.IndentLine(Self, ViewedTextBuffer, FInternalCaret, CX);
|
||||
FInternalCaret.DecForcePastEOL;
|
||||
end else
|
||||
CX := 1;
|
||||
if Command = ecLineBreak then begin
|
||||
@ -8098,7 +8096,7 @@ begin
|
||||
begin
|
||||
// this line is blank
|
||||
// -> use automatic line indent
|
||||
LineStart := FBeautifier.GetIndentForLine(Self, FTheLinesView[CaretY-1], FTheLinesView, CaretXY);
|
||||
LineStart := FBeautifier.GetDesiredIndentForLine(Self, FTheLinesView, FCaret);
|
||||
end;
|
||||
|
||||
NewPos.X:=LineStart;
|
||||
@ -8145,7 +8143,7 @@ begin
|
||||
end else begin
|
||||
// this line is blank
|
||||
// -> use automatic line indent
|
||||
LineEnd := FBeautifier.GetIndentForLine(Self, FTheLinesView[CaretY-1], FTheLinesView, CaretXY);
|
||||
LineEnd := FBeautifier.GetDesiredIndentForLine(Self, FTheLinesView, FCaret);
|
||||
end;
|
||||
|
||||
NewPos.X:=LineEnd;
|
||||
|
Loading…
Reference in New Issue
Block a user