diff --git a/components/codetools/codetoolmanager.pas b/components/codetools/codetoolmanager.pas index d0b4b0b0b9..5b176876c6 100644 --- a/components/codetools/codetoolmanager.pas +++ b/components/codetools/codetoolmanager.pas @@ -354,6 +354,9 @@ type function GuessUnclosedBlock(Code: TCodeBuffer; X,Y: integer; out NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer): boolean; + function CompleteBlock(Code: TCodeBuffer; X,Y: integer; + out NewCode: TCodeBuffer; + out NewX, NewY, NewTopLine: integer): boolean; // method jumping function JumpToMethod(Code: TCodeBuffer; X,Y: integer; @@ -3036,6 +3039,36 @@ begin {$ENDIF} end; +function TCodeToolManager.CompleteBlock(Code: TCodeBuffer; X, Y: integer; out + NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer): boolean; +var + CursorPos, NewPos: TCodeXYPosition; +begin + Result:=false; + NewCode:=Code; + NewX:=X; + NewY:=Y; + NewTopLine:=-1; + {$IFDEF CTDEBUG} + DebugLn('TCodeToolManager.CompleteBlock A ',Code.Filename,' x=',dbgs(X),' y=',dbgs(Y)); + {$ENDIF} + if not InitCurCodeTool(Code) then exit; + CursorPos.X:=X; + CursorPos.Y:=Y; + CursorPos.Code:=Code; + try + Result:=FCurCodeTool.CompleteBlock(CursorPos,SourceChangeCache, + NewPos,NewTopLine); + if Result then begin + NewCode:=NewPos.Code; + NewX:=NewPos.X; + NewY:=NewPos.Y; + end; + except + on e: Exception do HandleException(e); + end; +end; + function TCodeToolManager.GetCompatiblePublishedMethods(Code: TCodeBuffer; const AClassName: string; TypeData: PTypeData; Proc: TGetStringProc): boolean; begin diff --git a/components/codetools/stdcodetools.pas b/components/codetools/stdcodetools.pas index 4dee385d86..e2cd38b61a 100644 --- a/components/codetools/stdcodetools.pas +++ b/components/codetools/stdcodetools.pas @@ -200,6 +200,9 @@ type out NewPos: TCodeXYPosition; out NewTopLine: integer): boolean; function FindBlockCleanBounds(const CursorPos: TCodeXYPosition; out BlockCleanStart, BlockCleanEnd: integer): boolean; + function CompleteBlock(const CursorPos: TCodeXYPosition; + SourceChangeCache: TSourceChangeCache; + out NewPos: TCodeXYPosition; out NewTopLine: integer): boolean; // compiler directives function GuessMisplacedIfdefEndif(const CursorPos: TCodeXYPosition; @@ -5080,6 +5083,37 @@ begin Result:=true; end; +function TStandardCodeTool.CompleteBlock(const CursorPos: TCodeXYPosition; + SourceChangeCache: TSourceChangeCache; + out NewPos: TCodeXYPosition; out NewTopLine: integer): boolean; +{ begin: end; + asm: end; + try: finally end; + finally: end; + except: end; + repeat: until ; + case of: end; + case :: ; + case else: end; + (: ) + [: ] + record: end; + class: end; + object: end; + interface: end; +} +var + CleanCursorPos: integer; + Node: TCodeTreeNode; +begin + Result:=false; + BuildTreeAndGetCleanPos(trTillCursor,CursorPos,CleanCursorPos, + [{$IFNDEF DisableIgnoreErrorAfter}btSetIgnoreErrorPos{$ENDIF}]); + Node:=FindDeepestNodeAtPos(CleanCursorPos,true); + + DebugLn(['TStandardCodeTool.CompleteBlock ',Node.DescAsString]); +end; + function TStandardCodeTool.GuessMisplacedIfdefEndif( const CursorPos: TCodeXYPosition; out NewPos: TCodeXYPosition; out NewTopLine: integer): boolean; diff --git a/ide/editoroptions.pp b/ide/editoroptions.pp index 196dc3bef4..d0102c1c59 100644 --- a/ide/editoroptions.pp +++ b/ide/editoroptions.pp @@ -640,14 +640,15 @@ type FMarkupCurWordNoTimer: Boolean; // Code tools options (MG: these will move to an unit of their own) - fAutoIdentifierCompletion: Boolean; + fAutoBlockCompletion: Boolean; fAutoCodeParameters: Boolean; + fAutoDelayInMSec: Integer; + fAutoIdentifierCompletion: Boolean; + FAutoRemoveEmptyMethods: Boolean; fAutoToolTipExprEval: Boolean; fAutoToolTipSymbTools: Boolean; - fAutoDelayInMSec: Integer; fCodeTemplateFileName: String; fCTemplIndentToTokenStart: Boolean; - FAutoRemoveEmptyMethods: Boolean; // Code Folding FUseCodeFolding: Boolean; @@ -791,6 +792,8 @@ type // Code Tools options property AutoIdentifierCompletion: Boolean read fAutoIdentifierCompletion write fAutoIdentifierCompletion default True; + property AutoBlockCompletion: Boolean + read fAutoBlockCompletion write FAutoBlockCompletion default True; property AutoCodeParameters: Boolean read fAutoCodeParameters write fAutoCodeParameters default True; property AutoToolTipExprEval: Boolean @@ -1825,6 +1828,9 @@ begin fAutoIdentifierCompletion := XMLConfig.GetValue( 'EditorOptions/CodeTools/AutoIdentifierCompletion', True); + fAutoBlockCompletion := + XMLConfig.GetValue( + 'EditorOptions/CodeTools/AutoBlockCompletion', True); fAutoCodeParameters := XMLConfig.GetValue('EditorOptions/CodeTools/AutoCodeParameters', True); fAutoToolTipExprEval := @@ -2055,6 +2061,8 @@ begin // Code Tools options XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoIdentifierCompletion' , fAutoIdentifierCompletion, True); + XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoBlockCompletion' + , fAutoBlockCompletion, True); XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoCodeParameters' , fAutoCodeParameters, True); XMLConfig.SetDeleteValue('EditorOptions/CodeTools/AutoToolTipExprEval' diff --git a/ide/main.pp b/ide/main.pp index b594a6ddb7..87dfe5064d 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -12274,11 +12274,14 @@ var i: integer; AnUnitInfo: TUnitInfo; begin GetUnitWithPageIndex(APageIndex,SrcEdit,AnUnitInfo); - if (SrcEdit<>nil) and (AnUnitInfo<>nil) and SrcEdit.NeedsUpdateCodeBuffer then + if (SrcEdit<>nil) and (AnUnitInfo<>nil) then begin - SrcEdit.UpdateCodeBuffer; - AnUnitInfo.Modified:=true; SaveSourceEditorChangesToCodeCache:=true; + if SrcEdit.NeedsUpdateCodeBuffer then + begin + SrcEdit.UpdateCodeBuffer; + AnUnitInfo.Modified:=true; + end; end; end; diff --git a/ide/sourceeditor.pp b/ide/sourceeditor.pp index 4a3a99f294..c5d339ccdb 100644 --- a/ide/sourceeditor.pp +++ b/ide/sourceeditor.pp @@ -43,8 +43,8 @@ uses {$ENDIF} Classes, SysUtils, Math, Controls, LCLProc, LCLType, LResources, LCLIntf, FileUtil, Forms, Buttons, ComCtrls, Dialogs, StdCtrls, GraphType, Graphics, - Translations, ClipBrd, TypInfo, Extctrls, Menus, HelpIntfs, LazHelpIntf, - LConvEncoding, LDockCtrl, + Translations, ClipBrd, TypInfo, types, Extctrls, Menus, HelpIntfs, + LazHelpIntf, LConvEncoding, LDockCtrl, // codetools CodeToolManager, CodeCache, SourceLog, // synedit @@ -192,6 +192,7 @@ type procedure ccAddMessage(Texts: String); function AutoCompleteChar(Char: TUTF8Char; var AddChar: boolean; Category: TAutoCompleteOption): boolean; + procedure AutoCompleteBlock; procedure FocusEditor;// called by TSourceNotebook when the Notebook page // changes so the editor is focused @@ -1549,6 +1550,10 @@ begin if AutoCompleteChar(aChar,AddChar,acoLineBreak) then ; //DebugLn(['TSourceEditor.ProcessCommand ecLineBreak AddChar=',AddChar]); if not AddChar then Command:=ecNone; + {$IFDEF EnableCompleteBlock} + if EditorOpts.AutoBlockCompletion then + AutoCompleteBlock; + {$ENDIF} end; ecPrevBookmark: // Note: book mark commands lower than ecUserFirst must be handled here @@ -2329,6 +2334,20 @@ begin end; end; +procedure TSourceEditor.AutoCompleteBlock; +var + XY: TPoint; + NewCode: TCodeBuffer; + NewX, NewY, NewTopLine: integer; +begin + if not LazarusIDE.SaveSourceEditorChangesToCodeCache(PageIndex) then exit; + XY:=FEditor.LogicalCaretXY; + if not CodeToolBoss.CompleteBlock(CodeBuffer,XY.X,XY.Y, + NewCode,NewX,NewY,NewTopLine) then exit; + if (NewCode<>CodeBuffer) or (NewX<>XY.X) or (NewY<>XY.Y) or (NewTopLine>0) + then ; +end; + Procedure TSourceEditor.CreateEditor(AOwner: TComponent; AParent: TWinControl); var NewName: string;