mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-06 05:37:38 +01:00
IDE: word identifier completion: gather words on filter - and search in all units
git-svn-id: trunk@58167 -
This commit is contained in:
parent
899548c919
commit
8b29af0724
@ -223,11 +223,15 @@ type
|
||||
);
|
||||
TIdentifierListContextFlags = set of TIdentifierListContextFlag;
|
||||
|
||||
TOnGatherUserIdentifiersToFilteredList = procedure(Sender: TIdentifierList;
|
||||
FilteredList: TFPList; PriorityCount: Integer) of object;
|
||||
|
||||
TIdentifierList = class
|
||||
private
|
||||
FContext: TFindContext;
|
||||
FNewMemberVisibility: TCodeTreeNodeDesc;
|
||||
FContextFlags: TIdentifierListContextFlags;
|
||||
FOnGatherUserIdentifiersToFilteredList: TOnGatherUserIdentifiersToFilteredList;
|
||||
FSortForHistory: boolean;
|
||||
FSortForScope: boolean;
|
||||
FStartAtom: TAtomPosition;
|
||||
@ -263,6 +267,7 @@ type
|
||||
function HasIdentifier(Identifier: PChar; const ParamList: string): boolean;
|
||||
function FindIdentifier(Identifier: PChar; const ParamList: string): TIdentifierListItem;
|
||||
function FindIdentifier(Identifier: PChar; PreferProc: boolean): TIdentifierListItem;
|
||||
function FindIdentifier(Identifier: PChar): TIdentifierListItem;
|
||||
function FindCreatedIdentifier(const Ident: string): integer;
|
||||
function CreateIdentifier(const Ident: string): PChar;
|
||||
function StartUpAtomInFrontIs(const s: string): boolean;
|
||||
@ -290,6 +295,8 @@ type
|
||||
property StartContextPos: TCodeXYPosition
|
||||
read FStartContextPos write FStartContextPos;
|
||||
property ContainsFilter: Boolean read FContainsFilter write FContainsFilter;
|
||||
property OnGatherUserIdentifiersToFilteredList: TOnGatherUserIdentifiersToFilteredList
|
||||
read FOnGatherUserIdentifiersToFilteredList write FOnGatherUserIdentifiersToFilteredList;
|
||||
end;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -667,6 +674,8 @@ begin
|
||||
end;
|
||||
AnAVLNode:=FItems.FindSuccessor(AnAVLNode);
|
||||
end;
|
||||
if Assigned(FOnGatherUserIdentifiersToFilteredList) then
|
||||
FOnGatherUserIdentifiersToFilteredList(Self, FFilteredList, cPriorityCount);
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn(['TIdentifierList.UpdateFilteredList ',dbgs(FFilteredList.Count),' of ',dbgs(FItems.Count)]);
|
||||
{$ENDIF}
|
||||
@ -866,6 +875,19 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TIdentifierList.FindIdentifier(Identifier: PChar): TIdentifierListItem;
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
FIdentSearchItem.Identifier:=Identifier;
|
||||
// ignore ParamList
|
||||
Node:=FIdentView.FindKey(FIdentSearchItem,@CompareIdentListSearchWithItemsWithoutParams);
|
||||
if Assigned(Node) then
|
||||
Result := TIdentifierListItem(Node.Data)
|
||||
else
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TIdentifierList.CreateIdentifier(const Ident: string): PChar;
|
||||
var
|
||||
i: Integer;
|
||||
|
||||
41
ide/main.pp
41
ide/main.pp
@ -619,6 +619,8 @@ type
|
||||
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
|
||||
procedure CodeToolBossGatherUserIdentifiers(Sender: TIdentCompletionTool;
|
||||
const ContextFlags: TIdentifierListContextFlags);
|
||||
procedure CodeToolBossGatherUserIdentifiersToFilteredList(
|
||||
Sender: TIdentifierList; FilteredList: TFPList; PriorityCount: Integer);
|
||||
|
||||
function CTMacroFunctionProject(Data: Pointer): boolean;
|
||||
procedure CompilerParseStampIncHandler;
|
||||
@ -653,7 +655,7 @@ type
|
||||
OIChangedTimer: TIdleTimer;
|
||||
|
||||
FIdentifierWordCompletionWordList: TStringList;
|
||||
FIdentifierWordCompletion: TWordCompletion;
|
||||
FIdentifierWordCompletionEnabled: Boolean;
|
||||
|
||||
procedure DoDropFilesAsync(Data: PtrInt);
|
||||
procedure RenameInheritedMethods(AnUnitInfo: TUnitInfo; List: TStrings);
|
||||
@ -661,7 +663,8 @@ type
|
||||
procedure IdentifierWordCompletionGetSource(var Source: TStrings;
|
||||
var SourceTopLine,SourceBottomLine: integer;
|
||||
var IgnoreWordEndPos: TPoint; SourceIndex: integer);
|
||||
procedure DoAddWordsToIdentCompletion;
|
||||
procedure DoAddWordsToIdentCompletion(Sender: TIdentifierList;
|
||||
FilteredList: TFPList; PriorityCount: Integer);
|
||||
// form editor and designer
|
||||
procedure DoBringToFrontFormOrUnit;
|
||||
procedure DoBringToFrontFormOrInspector(ForceInspector: boolean);
|
||||
@ -1675,7 +1678,6 @@ begin
|
||||
FreeThenNil(ObjectInspector1);
|
||||
FreeThenNil(SourceEditorManagerIntf);
|
||||
FreeAndNil(FIdentifierWordCompletionWordList);
|
||||
FreeAndNil(FIdentifierWordCompletion);
|
||||
|
||||
// disconnect handlers
|
||||
Application.RemoveAllHandlersOfObject(Self);
|
||||
@ -2032,8 +2034,14 @@ procedure TMainIDE.CodeToolBossGatherUserIdentifiers(
|
||||
Sender: TIdentCompletionTool; const ContextFlags: TIdentifierListContextFlags
|
||||
);
|
||||
begin
|
||||
if not (ilcfStartIsSubIdent in ContextFlags) then
|
||||
DoAddWordsToIdentCompletion;
|
||||
FIdentifierWordCompletionEnabled := not (ilcfStartIsSubIdent in ContextFlags);
|
||||
end;
|
||||
|
||||
procedure TMainIDE.CodeToolBossGatherUserIdentifiersToFilteredList(
|
||||
Sender: TIdentifierList; FilteredList: TFPList; PriorityCount: Integer);
|
||||
begin
|
||||
if FIdentifierWordCompletionEnabled then
|
||||
DoAddWordsToIdentCompletion(Sender, FilteredList, PriorityCount);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
@ -6473,27 +6481,29 @@ begin
|
||||
Result := SourceFileMgr.AddUnitToProject(AEditor);
|
||||
end;
|
||||
|
||||
procedure TMainIDE.DoAddWordsToIdentCompletion;
|
||||
procedure TMainIDE.DoAddWordsToIdentCompletion(Sender: TIdentifierList;
|
||||
FilteredList: TFPList; PriorityCount: Integer);
|
||||
var
|
||||
New: TIdentifierListItem;
|
||||
I: Integer;
|
||||
begin
|
||||
if FIdentifierWordCompletionWordList=nil then
|
||||
FIdentifierWordCompletionWordList:=TStringList.Create
|
||||
else
|
||||
FIdentifierWordCompletionWordList.Clear;
|
||||
if FIdentifierWordCompletion=nil then
|
||||
begin
|
||||
FIdentifierWordCompletion := TWordCompletion.Create;
|
||||
FIdentifierWordCompletion.OnGetSource := @IdentifierWordCompletionGetSource;
|
||||
end;
|
||||
FIdentifierWordCompletionWordList:=TStringList.Create;
|
||||
FIdentifierWordCompletionWordList.OwnsObjects := True;
|
||||
end else
|
||||
FIdentifierWordCompletionWordList.Clear;
|
||||
|
||||
FIdentifierWordCompletion.GetWordList(FIdentifierWordCompletionWordList, '', False, 1000); // do not get words with prefix because the identifier list isn't reloaded when prefix changes
|
||||
AWordCompletion.GetWordList(FIdentifierWordCompletionWordList, Sender.Prefix, Sender.ContainsFilter, False, 100);
|
||||
for I := FIdentifierWordCompletionWordList.Count-1 downto 0 do
|
||||
begin
|
||||
if Sender.FindIdentifier(PChar(FIdentifierWordCompletionWordList[I]))=nil then
|
||||
begin
|
||||
New := CIdentifierListItem.Create(WordCompatibility, False, WordHistoryIndex,
|
||||
PChar(FIdentifierWordCompletionWordList[I]), WordLevel, nil, nil, ctnWord);
|
||||
CodeToolBoss.IdentifierList.Add(New);
|
||||
FIdentifierWordCompletionWordList.Objects[I] := New;
|
||||
FilteredList.Add(New);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -9284,6 +9294,7 @@ begin
|
||||
CodeToolBoss.DefineTree.OnGetVirtualDirectoryDefines:=
|
||||
@CodeToolBossGetVirtualDirectoryDefines;
|
||||
CodeToolBoss.DefineTree.OnPrepareTree:=@CodeToolBossPrepareTree;
|
||||
CodeToolBoss.IdentifierList.OnGatherUserIdentifiersToFilteredList := @CodeToolBossGatherUserIdentifiersToFilteredList;
|
||||
|
||||
CodeToolBoss.DefineTree.MacroFunctions.AddExtended(
|
||||
'PROJECT',nil,@CTMacroFunctionProject);
|
||||
|
||||
@ -1404,6 +1404,9 @@ var
|
||||
EnglishModifiedLGPLNotice: string;
|
||||
EnglishMITNotice: string;
|
||||
|
||||
var
|
||||
AWordCompletion: TWordCompletion = nil;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.lfm}
|
||||
@ -1423,7 +1426,6 @@ const
|
||||
SoftCenterMaximum = 8;
|
||||
|
||||
var
|
||||
AWordCompletion: TWordCompletion = nil;
|
||||
AutoStartCompletionBoxTimer: TIdleTimer = nil;
|
||||
SourceCompletionCaretXY: TPoint;
|
||||
PasBeautifier: TSynBeautifierPascal;
|
||||
@ -2532,7 +2534,7 @@ begin
|
||||
CurStr:=CurrentString;
|
||||
SL:=TStringList.Create;
|
||||
try
|
||||
aWordCompletion.GetWordList(SL, CurStr, false, 100);
|
||||
aWordCompletion.GetWordList(SL, CurStr, CodeToolBoss.IdentifierList.ContainsFilter, false, 100);
|
||||
ItemList:=SL;
|
||||
finally
|
||||
SL.Free;
|
||||
@ -2577,7 +2579,7 @@ begin
|
||||
if CurrentCompletionType=ctWordCompletion then begin
|
||||
SL:=TStringList.Create;
|
||||
try
|
||||
aWordCompletion.GetWordList(SL, NewPrefix, false, 100);
|
||||
aWordCompletion.GetWordList(SL, NewPrefix, CodeToolBoss.IdentifierList.ContainsFilter, false, 100);
|
||||
ItemList:=SL;
|
||||
finally
|
||||
SL.Free;
|
||||
|
||||
@ -40,8 +40,8 @@ type
|
||||
procedure AddWord(const AWord:string);
|
||||
property WordBufferCapacity:integer
|
||||
read GetWordBufferCapacity write SetWordBufferCapacity;
|
||||
procedure GetWordList(AWordList:TStrings; const Prefix:String;
|
||||
CaseSensitive:boolean; MaxResults:integer);
|
||||
procedure GetWordList(AWordList:TStrings; const Filter: String;
|
||||
ContainsFilter, CaseSensitive:boolean; MaxResults:integer);
|
||||
procedure CompletePrefix(const Prefix: string; var CompletedPrefix: string;
|
||||
CaseSensitive:boolean);
|
||||
public
|
||||
@ -72,9 +72,10 @@ end;
|
||||
{ TWordCompletion }
|
||||
|
||||
procedure TWordCompletion.GetWordList(AWordList: TStrings;
|
||||
const Prefix: String; CaseSensitive: boolean; MaxResults: integer);
|
||||
var i, j, Line, x, PrefixLen, MaxHash, LineLen: integer;
|
||||
UpPrefix, LineText, UpLineText, NewWord: string;
|
||||
const Filter: String; ContainsFilter, CaseSensitive: boolean;
|
||||
MaxResults: integer);
|
||||
var i, j, Line, x, FilterLen, MaxHash, LineLen: integer;
|
||||
UpFilter, LineText, UpLineText, NewWord: string;
|
||||
SourceText: TStringList;
|
||||
HashList: ^integer;// index list. Every entry points to a word in the AWordList
|
||||
SourceTextIndex, SourceTopLine, SourceBottomLine:integer;
|
||||
@ -110,6 +111,28 @@ var i, j, Line, x, PrefixLen, MaxHash, LineLen: integer;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AddIfMatch(const AWord:string);
|
||||
begin
|
||||
if CaseSensitive then begin
|
||||
if ContainsFilter then
|
||||
begin
|
||||
if pos(Filter, AWord)>0 then
|
||||
Add(NewWord);
|
||||
end else
|
||||
if copy(AWord,1,FilterLen)=Filter then
|
||||
Add(NewWord);
|
||||
end else
|
||||
begin
|
||||
if ContainsFilter then
|
||||
begin
|
||||
if pos(UpFilter, UpperCase(AWord))>0 then
|
||||
Add(AWord);
|
||||
end else
|
||||
if CompareText(copy(NewWord,1,FilterLen),UpFilter)=0 then
|
||||
Add(NewWord)
|
||||
end;
|
||||
end;
|
||||
|
||||
// TWordCompletion.GetWordList
|
||||
begin
|
||||
AWordList.Clear;
|
||||
@ -118,19 +141,13 @@ begin
|
||||
GetMem(HashList,MaxHash*SizeOf(Integer));
|
||||
try
|
||||
for i:=0 to MaxHash-1 do HashList[i]:=-1;
|
||||
PrefixLen:=length(Prefix);
|
||||
FilterLen:=length(Filter);
|
||||
AWordList.Capacity:=MaxResults;
|
||||
UpPrefix:=uppercase(Prefix);
|
||||
UpFilter:=uppercase(Filter);
|
||||
// first add all recently used words
|
||||
i:=FWordBuffer.Count-1;
|
||||
while (i>=0) and (AWordList.Count<MaxResults) do begin
|
||||
NewWord:=FWordBuffer[i];
|
||||
if CaseSensitive then begin
|
||||
if copy(NewWord,1,PrefixLen)=Prefix then
|
||||
Add(NewWord);
|
||||
end else if CompareText(copy(NewWord,1,PrefixLen),UpPrefix)=0 then begin
|
||||
Add(NewWord)
|
||||
end;
|
||||
AddIfMatch(FWordBuffer[i]);
|
||||
dec(i);
|
||||
end;
|
||||
if AWordList.Count>=MaxResults then exit;
|
||||
@ -163,20 +180,8 @@ begin
|
||||
repeat
|
||||
inc(i);
|
||||
until (i>LineLen) or (CharTable[LineText[i]]=ctNone);
|
||||
if i-x>=PrefixLen then begin
|
||||
if CaseSensitive then begin
|
||||
j:=1;
|
||||
while (j<=PrefixLen) and (Prefix[j]=LineText[x+j-1]) do
|
||||
inc(j);
|
||||
if (j>PrefixLen) and (Line<>IgnoreWordEndPos.Y) and (i<>IgnoreWordEndPos.X) then
|
||||
Add(copy(LineText,x,i-x));
|
||||
end else begin
|
||||
j:=1;
|
||||
while (j<=PrefixLen) and (UpPrefix[j]=UpLineText[x+j-1]) do
|
||||
inc(j);
|
||||
if (j>PrefixLen) and (Line<>IgnoreWordEndPos.Y) and (i<>IgnoreWordEndPos.X) then
|
||||
Add(copy(LineText,x,i-x))
|
||||
end;
|
||||
if (i-x>=FilterLen) and (Line<>IgnoreWordEndPos.Y) and (i<>IgnoreWordEndPos.X) then begin
|
||||
AddIfMatch(copy(LineText,x,i-x));
|
||||
if AWordList.Count>=MaxResults then exit;
|
||||
end;
|
||||
x:=i;
|
||||
@ -213,7 +218,7 @@ begin
|
||||
WordList:=TStringList.Create;
|
||||
try
|
||||
// fetch all words with Prefix
|
||||
GetWordList(WordList,Prefix,CaseSensitive,10000);
|
||||
GetWordList(WordList,Prefix,False,CaseSensitive,10000);
|
||||
if WordList.Count=0 then exit;
|
||||
// find the biggest prefix of all available words
|
||||
CompletedPrefix:=WordList[0];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user