mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 04:16:06 +02:00
IDE: auto indent: using SynEdit.OnPaste event
git-svn-id: trunk@22452 -
This commit is contained in:
parent
c9f863d3a3
commit
166ccb9e94
@ -296,11 +296,13 @@ type
|
||||
procedure ParseSource(const Src: string; StartPos, EndPos: integer;
|
||||
NestedComments: boolean;
|
||||
Stack: TFABBlockStack; Policies: TFABPolicies;
|
||||
out LastAtomStart, LastAtomEnd: integer // set if LastAtomStart<EndPos<LastAtomEnd
|
||||
out LastAtomStart, LastAtomEnd: integer; // set if LastAtomStart<EndPos<LastAtomEnd
|
||||
LearnFromFirstLine: boolean = true
|
||||
);
|
||||
procedure ParseSource(const Src: string; StartPos, EndPos: integer;
|
||||
NestedComments: boolean;
|
||||
Stack: TFABBlockStack; Policies: TFABPolicies);
|
||||
Stack: TFABBlockStack; Policies: TFABPolicies;
|
||||
LearnFromFirstLine: boolean = true);
|
||||
function FindPolicyInExamples(StartCode: TCodeBuffer;
|
||||
ParentTyp, Typ: TFABBlockType): TFABPolicies;
|
||||
function GetNestedCommentsForCode(Code: TCodeBuffer): boolean;
|
||||
@ -316,7 +318,8 @@ type
|
||||
function GetIndent(const Source: string; CleanPos: integer;
|
||||
NewNestedComments: boolean; UseLineStart: boolean;
|
||||
out Indent: TFABIndentationPolicy;
|
||||
ContextLearn: boolean = true // true = learn policies from Source
|
||||
ContextLearn: boolean = true; // true = learn policies from Source
|
||||
const InsertText: string = ''
|
||||
): boolean;
|
||||
function GetIndents(const Source: string; Positions: TFABPositionIndents;
|
||||
NewNestedComments: boolean; UseLineStart: boolean;
|
||||
@ -438,11 +441,13 @@ end;
|
||||
|
||||
procedure TFullyAutomaticBeautifier.ParseSource(const Src: string;
|
||||
StartPos, EndPos: integer; NestedComments: boolean; Stack: TFABBlockStack;
|
||||
Policies: TFABPolicies; out LastAtomStart, LastAtomEnd: integer);
|
||||
Policies: TFABPolicies; out LastAtomStart, LastAtomEnd: integer;
|
||||
LearnFromFirstLine: boolean);
|
||||
var
|
||||
p: Integer;
|
||||
AtomStart: integer;
|
||||
FirstAtomOnNewLine: Boolean;
|
||||
InFirstLine: boolean;
|
||||
|
||||
{$IFDEF ShowCodeBeautifierLearn}
|
||||
function PosToStr(p: integer): string;
|
||||
@ -484,7 +489,8 @@ var
|
||||
and (Policies<>nil) then begin
|
||||
if Block^.InnerIdent<0 then UpdateBlockInnerIndent;
|
||||
if Block^.InnerIdent>=0 then begin
|
||||
Policies.AddIndent(Block^.Typ,Typ,p,Block^.InnerIdent);
|
||||
if LearnFromFirstLine or (not InFirstLine) then
|
||||
Policies.AddIndent(Block^.Typ,Typ,p,Block^.InnerIdent);
|
||||
{$IFDEF ShowCodeBeautifierLearn}
|
||||
DebugLn([GetIndentStr(Stack.Top*2),'nested indentation learned ',FABBlockTypeNames[Block^.Typ],'/',FABBlockTypeNames[Typ],': ',GetAtomString(@Src[AtomStart],NestedComments),' at ',PosToStr(p),' Indent=',Block^.InnerIdent]);
|
||||
{$ENDIF}
|
||||
@ -642,10 +648,13 @@ begin
|
||||
p:=StartPos;
|
||||
if EndPos>length(Src) then EndPos:=length(Src)+1;
|
||||
AtomStart:=p;
|
||||
InFirstLine:=true;
|
||||
repeat
|
||||
LastAtomStart:=AtomStart;
|
||||
LastAtomEnd:=p;
|
||||
ReadRawNextPascalAtom(Src,p,AtomStart,NestedComments);
|
||||
if InFirstLine and (not PositionsInSameLine(Src,LastAtomEnd,AtomStart)) then
|
||||
InFirstLine:=false;
|
||||
//DebugLn(['TFullyAutomaticBeautifier.ParseSource Atom=',copy(Src,AtomStart,p-AtomStart)]);
|
||||
if p>EndPos then begin
|
||||
if (AtomStart<EndPos) then begin
|
||||
@ -1037,7 +1046,8 @@ begin
|
||||
|
||||
if FirstAtomOnNewLine then begin
|
||||
UpdateBlockInnerIndent;
|
||||
if Block^.InnerIdent>=0 then begin
|
||||
if (Block^.InnerIdent>=0)
|
||||
and (LearnFromFirstLine or (not InFirstLine)) then begin
|
||||
Policies.AddIndent(Block^.Typ,bbtNone,p,Block^.InnerIdent);
|
||||
{$IFDEF ShowCodeBeautifierLearn}
|
||||
DebugLn([GetIndentStr(Stack.Top*2),'Indentation learned for statements: ',FABBlockTypeNames[Block^.Typ],' Indent=',Block^.InnerIdent,' at ',PosToStr(p)]);
|
||||
@ -1049,12 +1059,12 @@ end;
|
||||
|
||||
procedure TFullyAutomaticBeautifier.ParseSource(const Src: string; StartPos,
|
||||
EndPos: integer; NestedComments: boolean; Stack: TFABBlockStack;
|
||||
Policies: TFABPolicies);
|
||||
Policies: TFABPolicies; LearnFromFirstLine: boolean);
|
||||
var
|
||||
LastAtomStart, LastAtomEnd: integer;
|
||||
begin
|
||||
ParseSource(Src,StartPos,EndPos,NestedComments,Stack,Policies,
|
||||
LastAtomStart,LastAtomEnd);
|
||||
LastAtomStart,LastAtomEnd,LearnFromFirstLine);
|
||||
end;
|
||||
|
||||
function TFullyAutomaticBeautifier.FindPolicyInExamples(StartCode: TCodeBuffer;
|
||||
@ -1406,7 +1416,7 @@ end;
|
||||
function TFullyAutomaticBeautifier.GetIndent(const Source: string;
|
||||
CleanPos: integer; NewNestedComments: boolean;
|
||||
UseLineStart: boolean; out Indent: TFABIndentationPolicy;
|
||||
ContextLearn: boolean): boolean;
|
||||
ContextLearn: boolean; const InsertText: string): boolean;
|
||||
var
|
||||
Block: TBlock;
|
||||
|
||||
@ -1444,7 +1454,7 @@ begin
|
||||
CleanPos:=FindStartOfAtom(Source,CleanPos);
|
||||
if CleanPos<1 then exit;
|
||||
|
||||
if UseLineStart then begin
|
||||
if UseLineStart and (InsertText='') then begin
|
||||
while (CleanPos<=length(Source)) and (Source[CleanPos] in [' ',#9]) do
|
||||
inc(CleanPos);
|
||||
end;
|
||||
@ -1480,10 +1490,15 @@ begin
|
||||
if LastAtomStart>0 then CleanPos:=LastAtomStart;
|
||||
|
||||
StackIndex:=Stack.Top;
|
||||
if UseLineStart then
|
||||
StackIndex:=FindStackPosForBlockCloseAtPos(Source,CleanPos,
|
||||
NewNestedComments,Stack);
|
||||
|
||||
if UseLineStart then begin
|
||||
if InsertText='' then begin
|
||||
StackIndex:=FindStackPosForBlockCloseAtPos(Source,CleanPos,
|
||||
NewNestedComments,Stack);
|
||||
end else begin
|
||||
StackIndex:=FindStackPosForBlockCloseAtPos(InsertText,1,
|
||||
NewNestedComments,Stack);
|
||||
end;
|
||||
end;
|
||||
if (StackIndex<0) then begin
|
||||
// no context
|
||||
{$IFDEF VerboseIndenter}
|
||||
@ -1504,7 +1519,8 @@ begin
|
||||
|
||||
if ContextLearn then begin
|
||||
// parse source behind
|
||||
ParseSource(Source,CleanPos,length(Source)+1,NewNestedComments,Stack,Policies);
|
||||
ParseSource(Source,CleanPos,length(Source)+1,NewNestedComments,Stack,
|
||||
Policies,false);
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TFullyAutomaticBeautifier.GetIndent parsed source behind']);
|
||||
{$ENDIF}
|
||||
@ -1660,7 +1676,8 @@ begin
|
||||
|
||||
if Policies<>nil then begin
|
||||
// parse source behind
|
||||
ParseSource(Source,Item^.CleanPos,length(Source)+1,NewNestedComments,Stack,Policies);
|
||||
ParseSource(Source,Item^.CleanPos,length(Source)+1,NewNestedComments,
|
||||
Stack,Policies,false);
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TFullyAutomaticBeautifier.GetIndent parsed source behind']);
|
||||
{$ENDIF}
|
||||
|
@ -166,6 +166,9 @@ type
|
||||
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
||||
procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
procedure EditorStatusChanged(Sender: TObject; Changes: TSynStatusChanges);
|
||||
procedure EditorPaste(Sender: TObject; var AText: String;
|
||||
var AMode: TSynSelectionMode; ALogStartPos: TPoint;
|
||||
var AnAction: TSynCopyPasteAction);
|
||||
procedure SetCodeBuffer(NewCodeBuffer: TCodeBuffer);
|
||||
function GetSource: TStrings;
|
||||
procedure SetPageName(const AValue: string);
|
||||
@ -2565,6 +2568,7 @@ Begin
|
||||
OnClickLink := @EditorClickLink;
|
||||
OnMouseLink := @EditorMouseLink;
|
||||
OnKeyDown := @EditorKeyDown;
|
||||
OnPaste:=@EditorPaste;
|
||||
// IMPORTANT: when you change above, don't forget updating UnbindEditor
|
||||
end;
|
||||
if FCodeTemplates<>nil then
|
||||
@ -2956,6 +2960,52 @@ begin
|
||||
Result:=CodeBuffer;
|
||||
end;
|
||||
|
||||
procedure TSourceEditor.EditorPaste(Sender: TObject; var AText: String;
|
||||
var AMode: TSynSelectionMode; ALogStartPos: TPoint;
|
||||
var AnAction: TSynCopyPasteAction);
|
||||
var
|
||||
p: integer;
|
||||
NestedComments: Boolean;
|
||||
NewIndent: TFABIndentationPolicy;
|
||||
Indent: LongInt;
|
||||
NewSrc: string;
|
||||
begin
|
||||
if AMode<>smNormal then exit;
|
||||
if SyncroEdit.Active then exit;
|
||||
if TemplateEdit.Active then exit;
|
||||
if not CodeToolsOpts.IndentOnPaste then exit;
|
||||
{$IFDEF VerboseIndenter}
|
||||
debugln(['TSourceEditor.EditorPaste LogCaret=',dbgs(ALogStartPos)]);
|
||||
{$ENDIF}
|
||||
if ALogStartPos.X>1 then exit;
|
||||
UpdateCodeBuffer;
|
||||
CodeBuffer.LineColToPosition(ALogStartPos.Y,ALogStartPos.X,p);
|
||||
if p<1 then exit;
|
||||
{$IFDEF VerboseIndenter}
|
||||
if ALogStartPos.Y>0 then
|
||||
DebugLn(['TSourceEditor.EditorPaste Y-1=',Lines[ALogStartPos.Y-2]]);
|
||||
DebugLn(['TSourceEditor.EditorPaste Y+0=',Lines[ALogStartPos.Y-1]]);
|
||||
if ALogStartPos.Y<LineCount then
|
||||
DebugLn(['TSourceEditor.EditorPaste Y+1=',Lines[ALogStartPos.Y+0]]);
|
||||
{$ENDIF}
|
||||
NestedComments:=CodeToolBoss.GetNestedCommentsFlagForFile(CodeBuffer.Filename);
|
||||
if not CodeToolBoss.Indenter.GetIndent(CodeBuffer.Source,p,NestedComments,
|
||||
true,NewIndent,CodeToolsOpts.IndentContextSensitive,AText)
|
||||
then exit;
|
||||
if not NewIndent.IndentValid then exit;
|
||||
Indent:=NewIndent.Indent-GetLineIndentWithTabs(AText,1,EditorComponent.TabWidth);
|
||||
{$IFDEF VerboseIndenter}
|
||||
debugln(AText);
|
||||
DebugLn(['TSourceEditor.EditorPaste Indent=',Indent]);
|
||||
{$ENDIF}
|
||||
IndentText(AText,Indent,EditorComponent.TabWidth,NewSrc);
|
||||
AText:=NewSrc;
|
||||
{$IFDEF VerboseIndenter}
|
||||
debugln(AText);
|
||||
DebugLn(['TSourceEditor.EditorPaste END']);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
Procedure TSourceEditor.EditorMouseMoved(Sender: TObject;
|
||||
Shift: TShiftState; X,Y: Integer);
|
||||
begin
|
||||
@ -6830,10 +6880,6 @@ var
|
||||
NewIndent: TFABIndentationPolicy;
|
||||
Indent: LongInt;
|
||||
CodeBuf: TCodeBuffer;
|
||||
Line: string;
|
||||
OldIndent: LongInt;
|
||||
CurIndent: LongInt;
|
||||
i: LongInt;
|
||||
begin
|
||||
Result:=false;
|
||||
SrcEdit:=GetActiveSE;
|
||||
@ -6846,34 +6892,15 @@ begin
|
||||
if (SrcEdit.TemplateEdit<>nil) and SrcEdit.TemplateEdit.Active then exit;
|
||||
if not (SrcEdit.SyntaxHighlighterType in [lshFreePascal, lshDelphi]) then
|
||||
exit;
|
||||
case Reason of
|
||||
ecLineBreak:
|
||||
if not CodeToolsOpts.IndentOnLineBreak then exit;
|
||||
ecPaste:
|
||||
begin
|
||||
if not CodeToolsOpts.IndentOnPaste then exit;
|
||||
if SrcEdit.EditorComponent.SelectionMode<>smNormal then exit;
|
||||
if LogCaret.X>1 then
|
||||
inc(FirstLinePos);
|
||||
if LogCaret.Y=LastLinePos then
|
||||
dec(LastLinePos);
|
||||
if LastLinePos<FirstLinePos then exit; // not a whole line
|
||||
end
|
||||
else
|
||||
exit;
|
||||
end;
|
||||
if Reason<>ecLineBreak then exit;
|
||||
if not CodeToolsOpts.IndentOnLineBreak then exit;
|
||||
{$IFDEF VerboseIndenter}
|
||||
debugln(['TSourceNotebook.EditorGetIndent LogCaret=',dbgs(LogCaret),' FirstLinePos=',FirstLinePos,' LastLinePos=',LastLinePos]);
|
||||
{$ENDIF}
|
||||
Result := True;
|
||||
SrcEdit.UpdateCodeBuffer;
|
||||
CodeBuf:=SrcEdit.CodeBuffer;
|
||||
case Reason of
|
||||
ecLineBreak,ecInsertLine:
|
||||
CodeBuf.LineColToPosition(LogCaret.Y,LogCaret.X,p);
|
||||
ecPaste:
|
||||
CodeBuf.LineColToPosition(FirstLinePos,1,p);
|
||||
end;
|
||||
CodeBuf.LineColToPosition(LogCaret.Y,LogCaret.X,p);
|
||||
if p<1 then exit;
|
||||
{$IFDEF VerboseIndenter}
|
||||
if FirstLinePos>0 then
|
||||
@ -6884,51 +6911,18 @@ begin
|
||||
{$ENDIF}
|
||||
NestedComments:=CodeToolBoss.GetNestedCommentsFlagForFile(CodeBuf.Filename);
|
||||
if not CodeToolBoss.Indenter.GetIndent(CodeBuf.Source,p,NestedComments,
|
||||
true,NewIndent,CodeToolsOpts.IndentContextSensitive)
|
||||
True,NewIndent,CodeToolsOpts.IndentContextSensitive)
|
||||
then exit;
|
||||
if not NewIndent.IndentValid then exit;
|
||||
Indent:=NewIndent.Indent;
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent Indent=',Indent]);
|
||||
{$ENDIF}
|
||||
case Reason of
|
||||
ecLineBreak,ecInsertLine:
|
||||
begin
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent Apply to FirstLinePos+1']);
|
||||
{$ENDIF}
|
||||
SetIndentProc(LogCaret.Y, Indent, 0,' ');
|
||||
SrcEdit.CursorScreenXY:=Point(Indent+1,SrcEdit.CursorScreenXY.Y);
|
||||
end;
|
||||
ecPaste:
|
||||
begin
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent Apply to lines ',FirstLinePos,' .. ',LastLinePos]);
|
||||
{$ENDIF}
|
||||
Line:=SrcEdit.EditorComponent.Lines[FirstLinePos-1];
|
||||
OldIndent:=GetLineIndentWithTabs(Line,1,SrcEdit.EditorComponent.TabWidth);
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent OldIndent=',OldIndent,' Line=',dbgstr(Line)]);
|
||||
{$ENDIF}
|
||||
for i:=FirstLinePos to LastLinePos do begin
|
||||
if i>=SrcEdit.EditorComponent.Lines.Count then break;
|
||||
Line:=SrcEdit.EditorComponent.Lines[i-1];
|
||||
CurIndent:=GetLineIndentWithTabs(Line,1,SrcEdit.EditorComponent.TabWidth);
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent CurIndent=',CurIndent,' OldIndent=',OldIndent,' Indent=',Indent,' Line="',Line,'"']);
|
||||
{$ENDIF}
|
||||
CurIndent:=CurIndent-OldIndent+Indent;
|
||||
if CurIndent<0 then begin
|
||||
dec(Indent,CurIndent);
|
||||
CurIndent:=0;
|
||||
end;
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent ']);
|
||||
{$ENDIF}
|
||||
SetIndentProc(i, CurIndent, 0,' ');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$IFDEF VerboseIndenter}
|
||||
DebugLn(['TSourceNotebook.EditorGetIndent Apply to FirstLinePos+1']);
|
||||
{$ENDIF}
|
||||
SetIndentProc(LogCaret.Y, Indent, 0,' ');
|
||||
SrcEdit.CursorScreenXY:=Point(Indent+1,SrcEdit.CursorScreenXY.Y);
|
||||
end;
|
||||
|
||||
Procedure TSourceNotebook.HintTimer(sender: TObject);
|
||||
|
Loading…
Reference in New Issue
Block a user