mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-13 21:39:39 +02:00
implemented tab completion for word and identifier completion
git-svn-id: trunk@5031 -
This commit is contained in:
parent
f8cac4fbb4
commit
2a402038bb
@ -159,6 +159,7 @@ type
|
||||
function CreateIdentifier(const Ident: string): PChar;
|
||||
function StartUpAtomInFrontIs(const s: string): boolean;
|
||||
function StartUpAtomBehindIs(const s: string): boolean;
|
||||
function CompletePrefix(const OldPrefix: string): string;
|
||||
public
|
||||
property Context: TFindContext read FContext write FContext;
|
||||
property ContextFlags: TIdentifierListContextFlags
|
||||
@ -577,6 +578,41 @@ begin
|
||||
Result:=StartContext.Tool.FreeUpAtomIs(StartAtomBehind,s);
|
||||
end;
|
||||
|
||||
function TIdentifierList.CompletePrefix(const OldPrefix: string): string;
|
||||
// search all identifiers beginning with Prefix
|
||||
// and return the biggest prefix of all of them
|
||||
var
|
||||
AnAVLNode: TAVLTreeNode;
|
||||
CurItem: TIdentifierListItem;
|
||||
FoundFirst: Boolean;
|
||||
SamePos: Integer;
|
||||
begin
|
||||
Result:=Prefix;
|
||||
FoundFirst:=false;
|
||||
AnAVLNode:=FItems.FindLowest;
|
||||
while AnAVLNode<>nil do begin
|
||||
CurItem:=TIdentifierListItem(AnAVLNode.Data);
|
||||
if (CurItem.Identifier<>nil)
|
||||
and ComparePrefixIdent(PChar(Prefix),CurItem.Identifier) then begin
|
||||
if not FoundFirst then begin
|
||||
Result:=GetIdentifier(CurItem.Identifier);
|
||||
FoundFirst:=true;
|
||||
end else begin
|
||||
SamePos:=length(Prefix);
|
||||
while (SamePos<length(Result))
|
||||
and (UpChars[CurItem.Identifier[SamePos]]=UpChars[Result[SamePos+1]])
|
||||
do
|
||||
inc(SamePos);
|
||||
if SamePos<length(Result) then begin
|
||||
Result:=copy(Result,1,SamePos);
|
||||
if length(Result)=length(Prefix) then exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
AnAVLNode:=FItems.FindSuccessor(AnAVLNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TIdentCompletionTool }
|
||||
|
||||
function TIdentCompletionTool.CollectAllIdentifiers(
|
||||
|
@ -79,6 +79,7 @@ type
|
||||
FAnsi: boolean;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
FOnSearchPosition:TSynBaseCompletionSearchPosition;
|
||||
FOnKeyCompletePrefix: TNotifyEvent;
|
||||
FTextColor: TColor;
|
||||
FTextSelectedColor: TColor;
|
||||
{$ENDIF}
|
||||
@ -125,6 +126,7 @@ type
|
||||
property FontHeight:integer read FFontHeight write SetFontHeight;
|
||||
property OnSearchPosition:TSynBaseCompletionSearchPosition
|
||||
read FOnSearchPosition write FOnSearchPosition;
|
||||
property OnKeyCompletePrefix: TNotifyEvent read FOnKeyCompletePrefix write FOnKeyCompletePrefix;
|
||||
property TextColor: TColor read FTextColor write FTextColor;
|
||||
property TextSelectedColor: TColor
|
||||
read FTextSelectedColor write FTextSelectedColor;
|
||||
@ -165,6 +167,8 @@ type
|
||||
procedure SetFontHeight(NewFontHeight :integer);
|
||||
function GetOnSearchPosition:TSynBaseCompletionSearchPosition;
|
||||
procedure SetOnSearchPosition(NewValue :TSynBaseCompletionSearchPosition);
|
||||
function GetOnKeyCompletePrefix: TNotifyEvent;
|
||||
procedure SetOnKeyCompletePrefix(const AValue: TNotifyEvent);
|
||||
{$ENDIF}
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
@ -192,6 +196,8 @@ type
|
||||
property FontHeight: integer read GetFontHeight write SetFontHeight;
|
||||
property OnSearchPosition: TSynBaseCompletionSearchPosition
|
||||
read GetOnSearchPosition write SetOnSearchPosition;
|
||||
property OnKeyCompletePrefix: TNotifyEvent read GetOnKeyCompletePrefix
|
||||
write SetOnKeyCompletePrefix;
|
||||
{$ENDIF}
|
||||
property ClSelect: TColor read GetClSelect write SetClSelect;
|
||||
property AnsiStrings: boolean read SFAnsi write RFAnsi;
|
||||
@ -372,6 +378,13 @@ begin
|
||||
if Assigned(OnKeyDelete) then OnKeyDelete(Self);
|
||||
CurrentString := Copy(CurrentString, 1, Length(CurrentString) - 1);
|
||||
end;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
VK_TAB:
|
||||
begin
|
||||
if Assigned(OnKeyCompletePrefix) then OnKeyCompletePrefix(Self);
|
||||
Key:=VK_UNKNOWN;
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
{$ifdef SYN_LAZARUS}
|
||||
Invalidate;
|
||||
@ -385,7 +398,7 @@ begin
|
||||
if Assigned(OnKeyPress) then
|
||||
OnKeyPress(self, Key);
|
||||
{$ifdef SYN_LAZARUS}
|
||||
if Key in [#33..'z'] then
|
||||
if Key in [#33..#255] then
|
||||
CurrentString := CurrentString + key;
|
||||
{$else}
|
||||
CurrentString := CurrentString + key;
|
||||
@ -661,6 +674,16 @@ procedure TSynBaseCompletion.SetOnSearchPosition(
|
||||
begin
|
||||
Form.OnSearchPosition:=NewValue;
|
||||
end;
|
||||
|
||||
function TSynBaseCompletion.GetOnKeyCompletePrefix: TNotifyEvent;
|
||||
begin
|
||||
Result:=Form.OnKeyCompletePrefix;
|
||||
end;
|
||||
|
||||
procedure TSynBaseCompletion.SetOnKeyCompletePrefix(const AValue: TNotifyEvent);
|
||||
begin
|
||||
Form.OnKeyCompletePrefix:=AValue;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
procedure TSynBaseCompletion.Execute(s: string; x, y: integer);
|
||||
|
@ -2253,7 +2253,7 @@ procedure TEnvironmentOptionsDialog.SetupFormEditorPage(Page: integer);
|
||||
Parent:=GridGroupBox;
|
||||
Left:=GridColorButton.Left+GridColorButton.Width+5;
|
||||
Top:=GridColorButton.Top+2;
|
||||
Width:=80;
|
||||
Width:=100;
|
||||
Caption:=dlgGridColor;
|
||||
end;
|
||||
|
||||
@ -2274,7 +2274,7 @@ procedure TEnvironmentOptionsDialog.SetupFormEditorPage(Page: integer);
|
||||
Parent:=GridGroupBox;
|
||||
Left:=ShowGridCheckBox.Left;
|
||||
Top:=SnapToGridCheckBox.Top+SnapToGridCheckBox.Height+5;
|
||||
Width:=80;
|
||||
Width:=100;
|
||||
Caption:=dlgGridX;
|
||||
end;
|
||||
|
||||
|
@ -432,7 +432,8 @@ type
|
||||
procedure ccComplete(var Value: ansistring; Shift: TShiftState);
|
||||
function OnSynCompletionPaintItem(const AKey: string; ACanvas: TCanvas;
|
||||
X, Y: integer; ItemSelected: boolean; Index: integer): boolean;
|
||||
procedure OnSynCompletionSearchPosition(var APosition:integer);
|
||||
procedure OnSynCompletionSearchPosition(var APosition: integer);
|
||||
procedure OnSynCompletionCompletePrefix(Sender : TObject);
|
||||
procedure DeactivateCompletionForm;
|
||||
procedure InitIdentCompletion(S: TStrings);
|
||||
|
||||
@ -554,7 +555,7 @@ type
|
||||
procedure OnCodeTemplateTokenNotFound(Sender: TObject; AToken: string;
|
||||
AnEditor: TCustomSynEdit; var Index:integer);
|
||||
procedure OnWordCompletionGetSource(
|
||||
var Source:TStrings; SourceIndex:integer);
|
||||
var Source: TStrings; SourceIndex: integer);
|
||||
|
||||
function Empty: boolean;
|
||||
property FormEditor : TFormEditor read FFormEditor write FFormEditor;
|
||||
@ -654,13 +655,13 @@ var
|
||||
// aCompletion:
|
||||
// The component controlling the completion form. It is created on demand
|
||||
// and killed when the IDE ends.
|
||||
aCompletion : TSynCompletion;
|
||||
aCompletion: TSynCompletion;
|
||||
// CurCompletionControl contains aCompletion whenever the completion form is
|
||||
// active
|
||||
CurCompletionControl : TSynBaseCompletion;
|
||||
CurCompletionControl : TSynCompletion;
|
||||
CurrentCompletionType: TCompletionType;
|
||||
IdentCompletionTimer : TTimer;
|
||||
AWordCompletion : TWordCompletion;
|
||||
AWordCompletion: TWordCompletion;
|
||||
|
||||
GotoDialog : TfrmGoto;
|
||||
|
||||
@ -2114,6 +2115,7 @@ begin
|
||||
OnCodeCompletion := @ccComplete;
|
||||
OnPaintItem:=@OnSynCompletionPaintItem;
|
||||
OnSearchPosition:=@OnSynCompletionSearchPosition;
|
||||
OnKeyCompletePrefix:=@OnSynCompletionCompletePrefix;
|
||||
ShortCut:=Menus.ShortCut(VK_UNKNOWN,[]);
|
||||
end;
|
||||
|
||||
@ -2215,8 +2217,8 @@ begin
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
procedure TSourceNotebook.OnWordCompletionGetSource(var Source:TStrings;
|
||||
SourceIndex:integer);
|
||||
procedure TSourceNotebook.OnWordCompletionGetSource(var Source: TStrings;
|
||||
SourceIndex: integer);
|
||||
var TempEditor: TSourceEditor;
|
||||
i:integer;
|
||||
begin
|
||||
@ -2272,7 +2274,7 @@ begin
|
||||
SL:=TStringList.Create;
|
||||
try
|
||||
for i:=0 to ItemCnt-1 do
|
||||
SL.Add('Dummy');
|
||||
SL.Add('Dummy'); // these entries are not shown
|
||||
CurCompletionControl.ItemList:=SL;
|
||||
finally
|
||||
SL.Free;
|
||||
@ -2306,7 +2308,7 @@ begin
|
||||
CurStr:=CurCompletionControl.CurrentString;
|
||||
SL:=TStringList.Create;
|
||||
try
|
||||
aWordCompletion.GetWordList(SL, CurStr, false, 30);
|
||||
aWordCompletion.GetWordList(SL, CurStr, false, 100);
|
||||
CurCompletionControl.ItemList:=SL;
|
||||
finally
|
||||
SL.Free;
|
||||
@ -2316,6 +2318,47 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSourceNotebook.OnSynCompletionCompletePrefix(Sender: TObject);
|
||||
var
|
||||
OldPrefix: String;
|
||||
NewPrefix: String;
|
||||
SL: TStringList;
|
||||
AddPrefix: String;
|
||||
begin
|
||||
if CurCompletionControl=nil then exit;
|
||||
OldPrefix:=CurCompletionControl.CurrentString;
|
||||
NewPrefix:=OldPrefix;
|
||||
|
||||
case CurrentCompletionType of
|
||||
|
||||
ctIdentCompletion:
|
||||
begin
|
||||
NewPrefix:=CodeToolBoss.IdentifierList.CompletePrefix(OldPrefix);
|
||||
end;
|
||||
|
||||
ctWordCompletion:
|
||||
begin
|
||||
aWordCompletion.CompletePrefix(OldPrefix,NewPrefix,false);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
if NewPrefix<>OldPrefix then begin
|
||||
AddPrefix:=copy(NewPrefix,length(OldPrefix)+1,length(NewPrefix));
|
||||
CurCompletionControl.Editor.SelText:=AddPrefix;
|
||||
CurCompletionControl.Editor.CaretXY:=
|
||||
CurCompletionControl.Editor.BlockBegin;
|
||||
SL:=TStringList.Create;
|
||||
try
|
||||
aWordCompletion.GetWordList(SL, NewPrefix, false, 100);
|
||||
CurCompletionControl.ItemList:=SL;
|
||||
finally
|
||||
SL.Free;
|
||||
end;
|
||||
CurCompletionControl.CurrentString:=NewPrefix;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSourceNotebook.DeactivateCompletionForm;
|
||||
begin
|
||||
CurCompletionControl.Deactivate;
|
||||
@ -2587,7 +2630,7 @@ var
|
||||
NewStr: String;
|
||||
ActiveEditor: TSynEdit;
|
||||
Begin
|
||||
CurCompletionControl := TSynBaseCompletion(Sender);
|
||||
CurCompletionControl := Sender as TSynCompletion;
|
||||
S := TStringList.Create;
|
||||
Prefix := CurCompletionControl.CurrentString;
|
||||
ActiveEditor:=GetActiveSE.EditorComponent;
|
||||
|
@ -37,17 +37,21 @@ type
|
||||
FOnGetSource:TWordCompletionGetSource;
|
||||
function GetWordBufferCapacity:integer;
|
||||
procedure SetWordBufferCapacity(NewCapacity: integer);
|
||||
function CaseInsensitiveIndexOf(const AWord:string):integer;
|
||||
function CaseInsensitiveIndexOf(const AWord: string):integer;
|
||||
function CaseSensitiveIndexOf(const AWord: string):integer;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure AddWord(const AWord:string);
|
||||
property WordBufferCapacity:integer
|
||||
read GetWordBufferCapacity write SetWordBufferCapacity;
|
||||
procedure GetWordList(AWordList:TStrings; const Prefix:String;
|
||||
CaseSensitive:boolean; MaxResults:integer);
|
||||
procedure CompletePrefix(const Prefix: string; var CompletedPrefix: string;
|
||||
CaseSensitive:boolean);
|
||||
public
|
||||
property OnGetSource:TWordCompletionGetSource
|
||||
read FOnGetSource write FOnGetSource;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -90,7 +94,7 @@ var i, j, Line, x, PrefixLen, MaxHash, LineLen: integer;
|
||||
Hash:=0;
|
||||
a:=1;
|
||||
while (a<=length(ALowWord)) and (a<20) do begin
|
||||
inc(Hash,ord(ALowWord[a]) and $3f);
|
||||
inc(Hash,ord(ALowWord[a]) and $7f);
|
||||
inc(a);
|
||||
end;
|
||||
Hash:=(Hash*137) mod MaxHash;
|
||||
@ -128,7 +132,7 @@ begin
|
||||
if CaseSensitive then begin
|
||||
if copy(NewWord,1,PrefixLen)=Prefix then
|
||||
Add(NewWord);
|
||||
end else if uppercase(copy(NewWord,1,PrefixLen))=UpPrefix then begin
|
||||
end else if CompareText(copy(NewWord,1,PrefixLen),UpPrefix)=0 then begin
|
||||
if NewWord<>Prefix then
|
||||
Add(NewWord)
|
||||
end;
|
||||
@ -193,6 +197,51 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWordCompletion.CompletePrefix(const Prefix: string;
|
||||
var CompletedPrefix: string; CaseSensitive: boolean);
|
||||
var
|
||||
WordList: TStringList;
|
||||
s: string;
|
||||
SamePos: Integer;
|
||||
MaxPos: Integer;
|
||||
i: Integer;
|
||||
begin
|
||||
CompletedPrefix:=Prefix;
|
||||
WordList:=TStringList.Create;
|
||||
try
|
||||
// fetch all words with Prefix
|
||||
GetWordList(WordList,Prefix,CaseSensitive,10000);
|
||||
if WordList.Count=0 then exit;
|
||||
// find the biggest prefix of all available words
|
||||
CompletedPrefix:=WordList[0];
|
||||
for i:=1 to WordList.Count-1 do begin
|
||||
// stop, when it can't get shorter
|
||||
if CompletedPrefix=Prefix then exit;
|
||||
s:=WordList[i];
|
||||
if length(s)<length(Prefix) then continue;
|
||||
// count same
|
||||
SamePos:=0;
|
||||
MaxPos:=length(s);
|
||||
if MaxPos>length(CompletedPrefix) then MaxPos:=length(CompletedPrefix);
|
||||
while (SamePos<MaxPos) do begin
|
||||
if CaseSensitive then begin
|
||||
if s[SamePos+1]<>CompletedPrefix[SamePos+1] then
|
||||
break;
|
||||
end else begin
|
||||
if upcase(s[SamePos+1])<>upcase(CompletedPrefix[SamePos+1]) then
|
||||
break;
|
||||
end;
|
||||
inc(SamePos);
|
||||
end;
|
||||
if SamePos<length(Prefix) then continue;
|
||||
if SamePos<length(CompletedPrefix) then
|
||||
CompletedPrefix:=copy(CompletedPrefix,1,SamePos);
|
||||
end;
|
||||
finally
|
||||
WordList.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TWordCompletion.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
@ -235,7 +284,7 @@ end;
|
||||
procedure TWordCompletion.AddWord(const AWord:string);
|
||||
var OldIndex:integer;
|
||||
begin
|
||||
OldIndex:=FWordBuffer.IndexOf(AWord);
|
||||
OldIndex:=CaseSensitiveIndexOf(AWord);
|
||||
if OldIndex>=0 then begin
|
||||
// move word to the top
|
||||
FWordBuffer.Move(OldIndex,FWordBuffer.Count-1);
|
||||
@ -248,11 +297,16 @@ begin
|
||||
end;
|
||||
|
||||
function TWordCompletion.CaseInsensitiveIndexOf(const AWord:string):integer;
|
||||
var LowWord: string;
|
||||
begin
|
||||
LowWord:=lowercase(AWord);
|
||||
Result:=FWordBuffer.Count-1;
|
||||
while (Result>=0) and (lowercase(FWordBuffer[Result])<>LowWord) do
|
||||
while (Result>=0) and (CompareText(FWordBuffer[Result],AWord)<>0) do
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
function TWordCompletion.CaseSensitiveIndexOf(const AWord: string): integer;
|
||||
begin
|
||||
Result:=FWordBuffer.Count-1;
|
||||
while (Result>=0) and (FWordBuffer[Result]<>AWord) do
|
||||
dec(Result);
|
||||
end;
|
||||
|
||||
|
@ -1,15 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Wrapper for the strip command
|
||||
#
|
||||
# Author: Mattias Gaertner
|
||||
#
|
||||
# Normally just calls strip with the same parameters. Special files, which can
|
||||
# not be stripped are skipped
|
||||
# The redhat rpm scripts try to strip files, that can't be stripped.
|
||||
# This wrapper simply skips some files.
|
||||
|
||||
set -e
|
||||
#set -x
|
||||
|
||||
Params=$@
|
||||
|
||||
#echo "SMART STRIP $Params"
|
||||
|
||||
# The last parameter is the file
|
||||
for p in $Params; do
|
||||
File=$p
|
||||
done
|
||||
echo $File | grep -q '\bpalmos\b' || strip $PARAMS
|
||||
echo $File | grep -q '\bpalmos\b' && exit
|
||||
echo $File | grep -q '\.a$' && exit
|
||||
|
||||
strip $Params
|
||||
|
||||
# end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user