diff --git a/components/codetools/codebeautifier.pas b/components/codetools/codebeautifier.pas index 0ef3471a85..326e48606b 100644 --- a/components/codetools/codebeautifier.pas +++ b/components/codetools/codebeautifier.pas @@ -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 LastAtomStartnil) 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=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} diff --git a/ide/sourceeditor.pp b/ide/sourceeditor.pp index 7e474910e1..0c77f103bc 100644 --- a/ide/sourceeditor.pp +++ b/ide/sourceeditor.pp @@ -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.Ynil) 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 LastLinePosecLineBreak 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);