codetools: completeblock: complete if unindent and cursor at unindent or in empty line

git-svn-id: trunk@26594 -
This commit is contained in:
mattias 2010-07-11 11:27:44 +00:00
parent ad682260a7
commit b4b5016f20
3 changed files with 79 additions and 13 deletions

View File

@ -64,6 +64,7 @@ function ExtractCommentContent(const ASource: string; CommentStart: integer;
TrimStart: boolean = false; TrimEnd: boolean = false;
TrimPasDoc: boolean = false): string;
function FindMainUnitHint(const ASource: string; out Filename: string): boolean;
function InEmptyLine(const ASource: string; StartPos: integer): boolean;
// indent
function GetLineIndent(const Source: string; Position: integer): integer;
@ -3287,6 +3288,34 @@ begin
Result:=true;
end;
function InEmptyLine(const ASource: string; StartPos: integer): boolean;
var
p: LongInt;
SrcLen: Integer;
begin
Result:=false;
SrcLen:=length(ASource);
if (StartPos<1) or (StartPos>SrcLen) or (not IsSpaceChar[ASource[StartPos]])
then exit;
p:=StartPos;
while (p>1) do begin
case ASource[p-1] of
' ',#9: dec(p);
#10,#13: break;
else exit;
end;
end;
p:=StartPos;
while p<=SrcLen do begin
case ASource[p] of
' ',#9: inc(p);
#10,#13: break;
else exit;
end;
end;
Result:=true;
end;
function CompareIdentifiers(Identifier1, Identifier2: PChar): integer;
begin
if (Identifier1<>nil) then begin

View File

@ -154,7 +154,7 @@ var
: TKeyWordFunctionList;
UpChars: array[char] of char;
IsSpaceChar,
IsSpaceChar, // [#0..#32]
IsLineEndChar,
IsWordChar, // ['a'..'z','A'..'Z']
IsNonWordChar, // [#0..#127]-IsIdentChar

View File

@ -5105,6 +5105,7 @@ type
var
CleanCursorPos: integer;
StartNode: TCodeTreeNode;
CursorInEmptyLine: Boolean;
procedure InitStack(out Stack: TBlockStack);
begin
@ -5351,14 +5352,44 @@ var
if (Indent<CursorBlockOuterIndent) and (NeedCompletion=0) then begin
// for example:
// begin
// |
// Code;
// end;
//DebugLn(['ReadStatements Indent=',Indent,' < CursorBlockIndent=',CursorBlockIndent]);
{$IFDEF ShowCompleteBlock}
DebugLn(['ReadStatements NeedCompletion: at ',CleanPosToStr(CurPos.StartPos),' Indent=',Indent,' < CursorBlockOuterIndent=',CursorBlockOuterIndent]);
{$ENDIF}
NeedCompletion:=CleanCursorPos;
// |end;
//DebugLn(['ReadStatements Indent=',Indent,' < CursorBlockOuterIndent=',CursorBlockOuterIndent,' CursorBlockInnerIndent=',CursorBlockInnerIndent,' CursorInEmptyLine=',CursorInEmptyLine,' CursorInEmptyStatement=',CursorInEmptyStatement]);
if CursorBlockOuterIndent<CursorBlockInnerIndent then begin
// for example:
// begin
// Code;
// |end;
{$IFDEF ShowCompleteBlock}
DebugLn(['ReadStatements NeedCompletion: at out indented ',CleanPosToStr(CurPos.StartPos),' Indent=',Indent,' < CursorBlockOuterIndent=',CursorBlockOuterIndent,' < CursorBlockInnerIndent=',CursorBlockInnerIndent]);
{$ENDIF}
NeedCompletion:=CurPos.StartPos;
end else if CursorInEmptyLine or CursorInEmptyStatement
or (FindNextNonSpace(Src,CleanCursorPos)=CurPos.StartPos) then begin
{ for example:
begin
|
Code;
end;
begin
Code;
|
end;
}
{$IFDEF ShowCompleteBlock}
DebugLn(['ReadStatements NeedCompletion: at empty line ',CleanPosToStr(CleanCursorPos),' Indent=',Indent,' < CursorBlockOuterIndent=',CursorBlockOuterIndent,' < CursorBlockInnerIndent=',CursorBlockInnerIndent]);
{$ENDIF}
NeedCompletion:=CleanCursorPos;
end else begin
{ It needs completion, but where?
for example:
begin
begin|
Code;
end;
}
end;
end;
end;
@ -5555,9 +5586,6 @@ var
// and first atom of a line
// => check indent
if (Indent<CursorBlockInnerIndent) and (NeedCompletion=0) then begin
{$IFDEF ShowCompleteBlock}
DebugLn(['ReadStatements NeedCompletion: at ',CleanPosToStr(CurPos.StartPos),' Indent=',Indent,' < CursorBlockInnerIndent=',CursorBlockInnerIndent]);
{$ENDIF}
if CursorBlockOuterIndent<CursorBlockInnerIndent then begin
// for example:
// begin
@ -5566,14 +5594,20 @@ var
// Code;
// Code;
//DebugLn(['ReadStatements Indent=',Indent,' < CursorBlockIndent=',CursorBlockIndent]);
{$IFDEF ShowCompleteBlock}
DebugLn(['ReadStatements NeedCompletion: at ',CleanPosToStr(CurPos.StartPos),' Indent=',Indent,' < CursorBlockInnerIndent=',CursorBlockInnerIndent]);
{$ENDIF}
NeedCompletion:=CurPos.StartPos;
end else begin
// for example:
// begin
// |
// Code;
{$IFDEF ShowCompleteBlock}
DebugLn(['ReadStatements NeedCompletion: at ',CleanPosToStr(CleanCursorPos),' Indent=',Indent,' CursorBlockInnerIndent=',CursorBlockInnerIndent]);
{$ENDIF}
NeedCompletion:=CleanCursorPos;
// Note: if the end is coming later, NeedCompletion is diabled
// Note: if the end is coming later, NeedCompletion is disabled
end;
end;
end;
@ -5617,8 +5651,9 @@ var
// repeat
// |
// DoSomething;
debugln(['CompleteStatements BehindPos ',dbgstr(copy(Src,BehindPos-8,8)),'|',dbgstr(copy(Src,BehindPos,8))]);
{$IFDEF ShowCompleteBlock}
DebugLn(['CompleteStatements code behind is indented more => skip']);
DebugLn(['CompleteStatements code behind is indented more (Behind=',GetLineIndent(Src,BehindPos),' > Indent=',Indent,') => skip']);
{$ENDIF}
exit;
end;
@ -5767,6 +5802,8 @@ begin
[btSetIgnoreErrorPos]);
StartNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
CursorInEmptyLine:=InEmptyLine(Src,CleanCursorPos);
//debugln(['TStandardCodeTool.CompleteBlock ',CursorInEmptyLine,' ',dbgstr(copy(Src,CleanCursorPos-10,10)),'|',dbgstr(copy(Src,CleanCursorPos,10))]);
SourceChangeCache.MainScanner:=Scanner;
InitStack(Stack);
try