mirror of
https://github.com/moparisthebest/Simba
synced 2025-03-03 18:59:47 -05:00
Code hints work! Press ctrl + shift + space to activate it :).
This commit is contained in:
parent
422fc0b923
commit
d5c29d57ef
@ -29,7 +29,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll,
|
Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll,
|
||||||
mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType,MufasaBase, SynEditMarkupSpecialLine, Graphics, Controls,
|
mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType,MufasaBase, SynEditMarkupSpecialLine, Graphics, Controls,
|
||||||
v_ideCodeInsight, v_ideCodeParser, CastaliaPasLexTypes, CastaliaSimplePasPar, SynEditHighlighter;
|
v_ideCodeInsight, v_ideCodeParser, CastaliaPasLexTypes, CastaliaSimplePasPar, SynEditHighlighter,synedittextbase;
|
||||||
const
|
const
|
||||||
ecCodeCompletion = ecUserFirst;
|
ecCodeCompletion = ecUserFirst;
|
||||||
ecCodeHints = ecUserFirst + 1;
|
ecCodeHints = ecUserFirst + 1;
|
||||||
@ -125,6 +125,28 @@ begin
|
|||||||
Result := Copy(s, sp, ep - sp + 1);
|
Result := Copy(s, sp, ep - sp + 1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function PosToCaretXY(e : TSynEdit; pos : integer) : TPoint;
|
||||||
|
function llen(const data: string): integer;
|
||||||
|
begin
|
||||||
|
result := length(Data) + length(LineEnding);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
loop: integer;
|
||||||
|
count: integer;
|
||||||
|
Lines : TStrings;
|
||||||
|
begin
|
||||||
|
loop := 0;
|
||||||
|
count := 0;
|
||||||
|
Lines := e.Lines;
|
||||||
|
while (loop < Lines.Count) and (count + llen(Lines[loop]) < pos) do begin
|
||||||
|
count := count + llen(Lines[loop]);
|
||||||
|
inc(loop);
|
||||||
|
end;
|
||||||
|
result.x := pos - count;
|
||||||
|
result.y := loop + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TScriptFrame }
|
{ TScriptFrame }
|
||||||
|
|
||||||
procedure TScriptFrame.SynEditChange(Sender: TObject);
|
procedure TScriptFrame.SynEditChange(Sender: TObject);
|
||||||
@ -214,13 +236,15 @@ begin
|
|||||||
Form1.ActionFindNextExecute(Sender);
|
Form1.ActionFindNextExecute(Sender);
|
||||||
key := 0;
|
key := 0;
|
||||||
end;
|
end;
|
||||||
|
if key = VK_ESCAPE then
|
||||||
|
Form1.ParamHint.Hide;
|
||||||
|
|
||||||
Form1.CodeCompletionForm.HandleKeyDown(Sender, Key, Shift);
|
Form1.CodeCompletionForm.HandleKeyDown(Sender, Key, Shift);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScriptFrame.SynEditKeyPress(Sender: TObject; var Key: char);
|
procedure TScriptFrame.SynEditKeyPress(Sender: TObject; var Key: char);
|
||||||
begin
|
begin
|
||||||
Form1.CodeCompletionForm.HandleKeyPress(Sender, Key);
|
Form1.CodeCompletionForm.HandleKeyPress(Sender, Key);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScriptFrame.SynEditMouseLink(Sender: TObject; X, Y: Integer;
|
procedure TScriptFrame.SynEditMouseLink(Sender: TObject; X, Y: Integer;
|
||||||
@ -257,17 +281,15 @@ var
|
|||||||
mp: TCodeInsight;
|
mp: TCodeInsight;
|
||||||
ms: TMemoryStream;
|
ms: TMemoryStream;
|
||||||
ItemList, InsertList: TStringList;
|
ItemList, InsertList: TStringList;
|
||||||
sp, ep,bcc,cc,bck: Integer;
|
sp, ep,bcc,cc,bck,posi,bracketpos: Integer;
|
||||||
p: TPoint;
|
p: TPoint;
|
||||||
s, Filter: string;
|
s, Filter: string;
|
||||||
Attri: TSynHighlighterAttributes;
|
Attri: TSynHighlighterAttributes;
|
||||||
d: TDeclaration;
|
d: TDeclaration;
|
||||||
dd: TDeclaration;
|
dd: TDeclaration;
|
||||||
begin
|
begin
|
||||||
if ((not SynEdit.GetHighlighterAttriAtRowCol(SynEdit.CaretXY, s, Attri)) or (Attri.Name = 'Identifier')) then
|
if (Command = ecCodeCompletion) and ((not SynEdit.GetHighlighterAttriAtRowCol(SynEdit.CaretXY, s, Attri)) or (Attri.Name = 'Identifier')) then
|
||||||
begin
|
begin
|
||||||
if (Command = ecCodeCompletion) then
|
|
||||||
begin;
|
|
||||||
{form1.FunctionListShown(True);
|
{form1.FunctionListShown(True);
|
||||||
with form1.frmFunctionList do
|
with form1.frmFunctionList do
|
||||||
if editSearchList.CanFocus then
|
if editSearchList.CanFocus then
|
||||||
@ -305,95 +327,100 @@ begin
|
|||||||
SynEdit.SelectedColor.Background:= clWhite;
|
SynEdit.SelectedColor.Background:= clWhite;
|
||||||
Synedit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable;
|
Synedit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable;
|
||||||
end;}
|
end;}
|
||||||
mp := TCodeInsight.Create;
|
mp := TCodeInsight.Create;
|
||||||
mp.FileName := ScriptFile;
|
mp.FileName := ScriptFile;
|
||||||
mp.OnMessage := @Form1.OnCCMessage;
|
mp.OnMessage := @Form1.OnCCMessage;
|
||||||
mp.OnFindInclude := @Form1.OnCCFindInclude;
|
mp.OnFindInclude := @Form1.OnCCFindInclude;
|
||||||
|
|
||||||
ms := TMemoryStream.Create;
|
ms := TMemoryStream.Create;
|
||||||
ItemList := TStringList.Create;
|
ItemList := TStringList.Create;
|
||||||
InsertList := TStringList.Create;
|
InsertList := TStringList.Create;
|
||||||
InsertList.Sorted := True;
|
InsertList.Sorted := True;
|
||||||
|
|
||||||
Synedit.Lines.SaveToStream(ms);
|
Synedit.Lines.SaveToStream(ms);
|
||||||
|
|
||||||
try
|
try
|
||||||
Filter := WordAtCaret(Synedit, sp, ep);
|
Filter := WordAtCaret(Synedit, sp, ep);
|
||||||
Form1.CodeCompletionStart := Point(sp, Synedit.CaretY);
|
Form1.CodeCompletionStart := Point(sp, Synedit.CaretY);
|
||||||
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1);
|
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1);
|
||||||
|
|
||||||
s := mp.GetExpressionAtPos;
|
s := mp.GetExpressionAtPos;
|
||||||
if (s <> '') then
|
if (s <> '') then
|
||||||
begin
|
begin
|
||||||
sp := LastDelimiter('.', s);
|
sp := LastDelimiter('.', s);
|
||||||
if (sp > 0) then
|
if (sp > 0) then
|
||||||
Delete(s, sp, Length(s) - sp + 1)
|
Delete(s, sp, Length(s) - sp + 1)
|
||||||
else
|
else
|
||||||
s := '';
|
s := '';
|
||||||
end;
|
|
||||||
|
|
||||||
mp.FillSynCompletionProposal(ItemList, InsertList, s);
|
|
||||||
p := SynEdit.ClientToScreen(SynEdit.RowColumnToPixels(Point(ep, SynEdit.CaretY)));
|
|
||||||
p.y := p.y + SynEdit.LineHeight;
|
|
||||||
Form1.CodeCompletionForm.Show(p, ItemList, InsertList, Filter, SynEdit);
|
|
||||||
finally
|
|
||||||
FreeAndNil(ms);
|
|
||||||
FreeAndNil(mp);
|
|
||||||
ItemList.Free;
|
|
||||||
InsertList.Free;
|
|
||||||
end;
|
end;
|
||||||
end else
|
|
||||||
if command = ecCodeHints then
|
|
||||||
begin
|
|
||||||
mp := TCodeInsight.Create;
|
|
||||||
mp.OnMessage := @form1.OnCCMessage;
|
|
||||||
mp.OnFindInclude := @form1.OnCCFindInclude;
|
|
||||||
|
|
||||||
ms := TMemoryStream.Create;
|
mp.FillSynCompletionProposal(ItemList, InsertList, s);
|
||||||
synedit.Lines.SaveToStream(ms);
|
p := SynEdit.ClientToScreen(SynEdit.RowColumnToPixels(Point(ep, SynEdit.CaretY)));
|
||||||
|
p.y := p.y + SynEdit.LineHeight;
|
||||||
|
Form1.CodeCompletionForm.Show(p, ItemList, InsertList, Filter, SynEdit);
|
||||||
|
finally
|
||||||
|
FreeAndNil(ms);
|
||||||
|
FreeAndNil(mp);
|
||||||
|
ItemList.Free;
|
||||||
|
InsertList.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if command = ecCodeHints then
|
||||||
|
begin
|
||||||
|
if Form1.ParamHint.Visible = true then
|
||||||
|
form1.ParamHint.hide;
|
||||||
|
mp := TCodeInsight.Create;
|
||||||
|
mp.OnMessage := @form1.OnCCMessage;
|
||||||
|
mp.OnFindInclude := @form1.OnCCFindInclude;
|
||||||
|
|
||||||
try
|
ms := TMemoryStream.Create;
|
||||||
Synedit.GetWordBoundsAtRowCol(Synedit.CaretXY, sp, ep);
|
synedit.Lines.SaveToStream(ms);
|
||||||
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1);
|
try
|
||||||
//mp.Position := Synedit.SelStart + (ep - Synedit.CaretX) - 1;
|
Synedit.GetWordBoundsAtRowCol(Synedit.CaretXY, sp, ep);
|
||||||
|
mp.Run(ms, nil, Synedit.SelStart + (ep - Synedit.CaretX) - 1,true);
|
||||||
|
|
||||||
bcc := 1;
|
bcc := 1;bck := 0;cc := 0;
|
||||||
bck := 0;
|
s := mp.GetExpressionAtPos(bcc, bck, cc,posi, true);
|
||||||
cc := 0;
|
bracketpos := posi + length(s);
|
||||||
s := mp.GetExpressionAtPos(bcc, bck, cc, True);
|
if pos('(',s) > 0 then
|
||||||
if (s <> '') then
|
begin;
|
||||||
Delete(s, Length(s), 1);
|
bracketpos := pos('(',s) + posi;
|
||||||
|
delete(s,pos('(',s),length(s) - pos('(',s) + 1);
|
||||||
d := mp.FindVarBase(s);
|
end;
|
||||||
dd := nil;
|
d := mp.FindVarBase(s);
|
||||||
while (d <> nil) and (d <> dd) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) do
|
dd := nil;
|
||||||
|
//Find the declaration -> For example if one uses var x : TNotifyEvent..
|
||||||
|
//You have to get the owner of x, to find the declaration of TNotifyEvent etc..
|
||||||
|
while (d <> nil) and (d <> dd) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) do
|
||||||
|
begin
|
||||||
|
dd := d;
|
||||||
|
d := d.Owner.Items.GetFirstItemOfClass(TciTypeKind);
|
||||||
|
if (d <> nil) then
|
||||||
begin
|
begin
|
||||||
dd := d;
|
d := TciTypeKind(d).GetRealType;
|
||||||
d := d.Owner.Items.GetFirstItemOfClass(TciTypeKind);
|
if (d is TciReturnType) then
|
||||||
if (d <> nil) then
|
|
||||||
begin
|
|
||||||
d := TciTypeKind(d).GetRealType;
|
|
||||||
if (d is TciReturnType) then
|
|
||||||
d := d.Owner;
|
|
||||||
end;
|
|
||||||
if (d <> nil) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) then
|
|
||||||
d := mp.FindVarBase(d.CleanText)
|
|
||||||
else
|
|
||||||
Break;
|
|
||||||
end;
|
|
||||||
if (d <> nil) and (d <> dd) and (d.Owner <> nil) and ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration)) then
|
|
||||||
begin
|
|
||||||
if (not (d is TciProcedureDeclaration)) and (d.Owner is TciProcedureDeclaration) then
|
|
||||||
d := d.Owner;
|
d := d.Owner;
|
||||||
if (TciProcedureDeclaration(d).SynParams <> '') then
|
|
||||||
formWriteln(TciProcedureDeclaration(d).SynParams)
|
|
||||||
else
|
|
||||||
FormWriteln('<no parameters expected>');
|
|
||||||
end;
|
end;
|
||||||
finally
|
if (d <> nil) and (d.Owner <> nil) and (not ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration))) then
|
||||||
FreeAndNil(ms);
|
d := mp.FindVarBase(d.CleanText)
|
||||||
FreeAndNil(mp);
|
else
|
||||||
|
Break;
|
||||||
end;
|
end;
|
||||||
|
//Yeah, we should have found the procedureDeclaration now!
|
||||||
|
if (d <> nil) and (d <> dd) and (d.Owner <> nil) and ((d is TciProcedureDeclaration) or (d.Owner is TciProcedureDeclaration)) then
|
||||||
|
begin
|
||||||
|
if (not (d is TciProcedureDeclaration)) and (d.Owner is TciProcedureDeclaration) then
|
||||||
|
d := d.Owner;
|
||||||
|
if (TciProcedureDeclaration(d).Params <> '') then
|
||||||
|
Form1.ParamHint.Show(PosToCaretXY(synedit,posi + 1), PosToCaretXY(synedit,bracketpos),
|
||||||
|
TciProcedureDeclaration(d), synedit,mp)
|
||||||
|
else
|
||||||
|
FormWriteln('<no parameters expected>');
|
||||||
|
end;
|
||||||
|
except
|
||||||
|
on e : exception do
|
||||||
|
mDebugLn(e.message);
|
||||||
|
//Do not free the MP, we need to use this.
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if Form1.CodeCompletionForm.Visible then
|
if Form1.CodeCompletionForm.Visible then
|
||||||
@ -410,7 +437,6 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Form1.CodeCompletionForm.Hide;
|
Form1.CodeCompletionForm.Hide;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -344,6 +344,7 @@ type
|
|||||||
CurrTab : TMufasaTab; //The current TMufasaTab
|
CurrTab : TMufasaTab; //The current TMufasaTab
|
||||||
CodeCompletionForm: TAutoCompletePopup;
|
CodeCompletionForm: TAutoCompletePopup;
|
||||||
CodeCompletionStart: TPoint;
|
CodeCompletionStart: TPoint;
|
||||||
|
ParamHint : TParamHint;
|
||||||
Tabs : TList;
|
Tabs : TList;
|
||||||
Manager: TIOManager;
|
Manager: TIOManager;
|
||||||
OCR_Fonts: TMOCR;
|
OCR_Fonts: TMOCR;
|
||||||
@ -1831,6 +1832,8 @@ begin
|
|||||||
CodeCompletionForm := TAutoCompletePopup.Create(Self);
|
CodeCompletionForm := TAutoCompletePopup.Create(Self);
|
||||||
CodeCompletionForm.InsertProc := @OnCompleteCode;
|
CodeCompletionForm.InsertProc := @OnCompleteCode;
|
||||||
|
|
||||||
|
ParamHint := TParamHint.Create(self);
|
||||||
|
|
||||||
{$ifdef MSWindows}
|
{$ifdef MSWindows}
|
||||||
ConsoleVisible := True;
|
ConsoleVisible := True;
|
||||||
PrevWndProc := Windows.WNDPROC(GetWindowLong(self.handle,GWL_WNDPROC));
|
PrevWndProc := Windows.WNDPROC(GetWindowLong(self.handle,GWL_WNDPROC));
|
||||||
@ -1907,6 +1910,7 @@ begin
|
|||||||
SetLength(DebugStream, 0);
|
SetLength(DebugStream, 0);
|
||||||
RecentFiles.Free;
|
RecentFiles.Free;
|
||||||
DebugCriticalSection.Free;
|
DebugCriticalSection.Free;
|
||||||
|
ParamHint.Free;
|
||||||
{$ifdef MSWindows}
|
{$ifdef MSWindows}
|
||||||
if not UnRegisterHotkey(Self.Handle,0) then
|
if not UnRegisterHotkey(Self.Handle,0) then
|
||||||
mDebugLn('Unable to unregister ctrl + alt + s as global hotkey');
|
mDebugLn('Unable to unregister ctrl + alt + s as global hotkey');
|
||||||
|
@ -6,11 +6,12 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
|
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
|
||||||
StdCtrls, ExtCtrls, SynEdit, SynEditKeyCmds,
|
StdCtrls, ExtCtrls, SynEdit, SynEditKeyCmds, v_ideCodeParser, v_ideCodeInsight,
|
||||||
|
|
||||||
{$IFDEF FPC}
|
{$IFDEF FPC}
|
||||||
LMessages,
|
LMessages,
|
||||||
lcltype
|
lcltype,
|
||||||
|
mPasLex
|
||||||
{$ELSE}
|
{$ELSE}
|
||||||
Windows,
|
Windows,
|
||||||
Messages
|
Messages
|
||||||
@ -81,16 +82,34 @@ type
|
|||||||
property InsertProc: TInsertProc read getInsertProc write setInsertProc;
|
property InsertProc: TInsertProc read getInsertProc write setInsertProc;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TParamHint }
|
||||||
|
|
||||||
TParamHint = class(THintWindow)
|
TParamHint = class(THintWindow)
|
||||||
|
private
|
||||||
|
fPreparedString : string;
|
||||||
|
LastParameterIndex : integer;
|
||||||
|
FSynEdit : TSynedit;
|
||||||
|
FStartPoint : TPoint;
|
||||||
|
FBracketPoint : TPoint;
|
||||||
|
FMP : TCodeInsight;
|
||||||
|
FDecl : TciProcedureDeclaration;
|
||||||
|
FParameters : TDeclarationArray;
|
||||||
|
procedure ParamHintHide(Sender: TObject);
|
||||||
|
procedure ApplicationIdle(Sender: TObject; var Done: Boolean);
|
||||||
|
procedure DrawHints(var MaxWidth, MaxHeight: Integer; Draw: boolean);
|
||||||
|
function PrepareParamString(out Str : string; out MustHide : boolean) : integer;
|
||||||
public
|
public
|
||||||
constructor Create(TheOwner: TComponent); override;
|
constructor Create(TheOwner: TComponent); override;
|
||||||
|
procedure CalculateBounds;
|
||||||
|
procedure UpdateHint;
|
||||||
procedure Paint; override;
|
procedure Paint; override;
|
||||||
|
procedure Show(StartPoint,BracketPoint : TPoint;Decl : TciProcedureDeclaration; Editor : TSynedit; mp : TCodeInsight); reintroduce;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
StrUtils {$IFDEF FPC}, lclintf{$ENDIF}, Themes;
|
StrUtils {$IFDEF FPC}, lclintf{$ENDIF},math, Themes;
|
||||||
|
|
||||||
procedure TAutoCompleteListBox.setItemList(List: TStrings);
|
procedure TAutoCompleteListBox.setItemList(List: TStrings);
|
||||||
begin
|
begin
|
||||||
@ -553,61 +572,391 @@ begin
|
|||||||
Editor.SetFocus;
|
Editor.SetFocus;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function StringListPartToText(BeginPos, EndPos : TPoint; Strings :TStrings) : string;
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin;
|
||||||
|
result := '';
|
||||||
|
if endpos.y < beginpos.y then
|
||||||
|
exit;
|
||||||
|
if endpos.y >= strings.Count then
|
||||||
|
exit;
|
||||||
|
if beginpos.x > length(strings[beginpos.y]) then
|
||||||
|
exit;
|
||||||
|
if endpos.x > length(strings[endpos.y]) then
|
||||||
|
exit;
|
||||||
|
result := copy(strings[beginpos.y],beginpos.x, length(strings[beginpos.y]) - beginpos.x + 1);
|
||||||
|
for i := beginpos.y + 1 to endpos.y-1 do
|
||||||
|
result := result + strings[i];
|
||||||
|
if endpos.y <> beginpos.y then
|
||||||
|
result := result + copy(strings[endpos.y],0,endpos.x);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TParamHint.PrepareParamString(out Str: string; out MustHide : boolean): Integer;
|
||||||
|
var
|
||||||
|
Parser : TmwPasLex;
|
||||||
|
bracketcount, parameterindex,ParamC : integer;
|
||||||
|
ParamNames : TDeclarationArray;
|
||||||
|
typedecl : TDeclaration;
|
||||||
|
s,TypeStr,Params : string;//
|
||||||
|
i,ii :integer;
|
||||||
|
begin
|
||||||
|
result := -1;
|
||||||
|
MustHide := True;
|
||||||
|
Parser := TmwPasLex.Create;
|
||||||
|
parser.Origin:= PChar( StringListPartToText(Point(FBracketPoint.x,FBracketPoint.y-1),point(min(FSynEdit.LogicalCaretXY.x-1,length(FSynEdit.LineText)),FSynEdit.logicalcaretxy.y-1),FSynEdit.lines));
|
||||||
|
bracketcount := 0;
|
||||||
|
ParameterIndex := -1;
|
||||||
|
while parser.TokenID <> tkNull do
|
||||||
|
begin
|
||||||
|
case parser.tokenID of
|
||||||
|
tkRoundOpen,tkSquareOpen:
|
||||||
|
begin
|
||||||
|
inc(BracketCount);
|
||||||
|
if BracketCount = 1 then
|
||||||
|
ParameterIndex := 0;
|
||||||
|
end;
|
||||||
|
tkRoundClose, tkSquareClose:
|
||||||
|
begin
|
||||||
|
dec(BracketCount);
|
||||||
|
if bracketcount =0 then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
tkComma:
|
||||||
|
begin
|
||||||
|
if bracketcount = 1 then
|
||||||
|
inc(parameterIndex);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
parser.NextNoJunk;
|
||||||
|
end;
|
||||||
|
if parameterindex = -1 then
|
||||||
|
exit;
|
||||||
|
if parameterindex = LastParameterIndex then
|
||||||
|
begin
|
||||||
|
mustHide := false;
|
||||||
|
str := fPreparedString;
|
||||||
|
result := parameterindex;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
str := '';
|
||||||
|
ParamC := 0;
|
||||||
|
typedecl := FDecl.Name;
|
||||||
|
if typedecl = nil then
|
||||||
|
exit;
|
||||||
|
if typedecl.shorttext = '' then
|
||||||
|
exit;
|
||||||
|
for i := 0 to high(FParameters) do
|
||||||
|
begin
|
||||||
|
if (FParameters[i] is TciConstParameter) then
|
||||||
|
s := 'const '
|
||||||
|
else if (FParameters[i] is TciOutParameter) then
|
||||||
|
s := 'out '
|
||||||
|
else if (FParameters[i] is TciInParameter) then
|
||||||
|
s := 'in '
|
||||||
|
else if (FParameters[i] is TciVarParameter) then
|
||||||
|
s := 'var '
|
||||||
|
else
|
||||||
|
s := '';
|
||||||
|
ParamNames:= FParameters[i].Items.GetItemsOfClass(TciParameterName);
|
||||||
|
TypeDecl := FParameters[i].Items.GetFirstItemOfClass(TciParameterType);
|
||||||
|
if TypeDecl <> nil then
|
||||||
|
TypeStr := ': ' + typedecl.ShortText
|
||||||
|
else
|
||||||
|
TypeStr := '';
|
||||||
|
Params := '';
|
||||||
|
for ii := 0 to high(ParamNames) do
|
||||||
|
begin;
|
||||||
|
if parameterindex = ParamC then //Found the current parameter index in the parameterdecl!
|
||||||
|
begin;
|
||||||
|
if s <> '' then
|
||||||
|
s := '\' + s + '\'; //If it has a const/var/in/out thingy, bold this as well
|
||||||
|
if TypeStr <> '' then //If has a type then bold the type
|
||||||
|
TypeStr := '\' + TypeStr + '\';
|
||||||
|
if Params <> '' then
|
||||||
|
Params := Params +', \' + ParamNames[ii].ShortText + '\'
|
||||||
|
else
|
||||||
|
Params := '\' + ParamNames[ii].ShortText + '\';
|
||||||
|
end else
|
||||||
|
begin;
|
||||||
|
if Params <> '' then
|
||||||
|
Params := Params +', ' + ParamNames[ii].ShortText
|
||||||
|
else
|
||||||
|
Params := ParamNames[ii].ShortText;
|
||||||
|
end;
|
||||||
|
inc(ParamC);
|
||||||
|
end;
|
||||||
|
if str <> '' then
|
||||||
|
str := str + ';' + s + Params + typestr
|
||||||
|
else
|
||||||
|
str := s + params + typestr;
|
||||||
|
end;
|
||||||
|
TypeDecl := FDecl.Items.GetFirstItemOfClass(TciReturnType);
|
||||||
|
if TypeDecl <> nil then
|
||||||
|
TypeStr := ': ' + typedecl.ShortText
|
||||||
|
else
|
||||||
|
TypeStr := '';
|
||||||
|
str := FDecl.Name.ShortText + '(' + str + ')' + TypeStr + ';';
|
||||||
|
str := StringReplace(str,'\\','',[rfReplaceAll]); //Delete all the \\, something like \const \\x\ is the same as \const x\
|
||||||
|
MustHide := False;
|
||||||
|
Result := parameterindex;
|
||||||
|
fPreparedString := str;
|
||||||
|
Parser.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
constructor TParamHint.Create(TheOwner: TComponent);
|
constructor TParamHint.Create(TheOwner: TComponent);
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
|
|
||||||
{$IFDEF FPC}
|
{$IFDEF FPC}
|
||||||
AutoHide := False;
|
AutoHide := False;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
OnHide:=@ParamHintHide;
|
||||||
|
LastParameterIndex:= -1;
|
||||||
|
Application.AddOnIdleHandler(@ApplicationIdle);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TParamHint.CalculateBounds;
|
||||||
|
var
|
||||||
|
DrawWidth: LongInt;
|
||||||
|
DrawHeight: LongInt;
|
||||||
|
ScreenTextXY: TPoint;
|
||||||
|
ClientXY: TPoint;
|
||||||
|
ScreenXY: TPoint;
|
||||||
|
begin
|
||||||
|
ScreenTextXY := FSynEdit.LogicalToPhysicalPos(FStartPoint);
|
||||||
|
ClientXY := FSynEdit.RowColumnToPixels(ScreenTextXY);
|
||||||
|
DrawWidth := FSynEdit.ClientWidth; //Maximum width it can have..
|
||||||
|
DrawHeight := ClientXY.y; //Maximum height it can have..
|
||||||
|
DrawHints(DrawWidth,DrawHeight,false); //Calculate the max size we need!
|
||||||
|
if DrawWidth<20 then DrawWidth:=20; //Some default values!
|
||||||
|
if DrawHeight<5 then DrawHeight:=5;
|
||||||
|
|
||||||
|
if ClientXY.X+DrawWidth>FSynedit.ClientWidth then //If we go out of bounds, lets put it to the left a bit.
|
||||||
|
ClientXY.X:=FSynedit.ClientWidth-DrawWidth;
|
||||||
|
if ClientXY.X<0 then //If we go to the left a lil bit to much, go to the right!
|
||||||
|
ClientXY.X:=0;
|
||||||
|
dec(ClientXY.Y,DrawHeight); //Move this a lil bit up!
|
||||||
|
if ClientXY.y < 0 then
|
||||||
|
ClientXY.y := 0;
|
||||||
|
|
||||||
|
ScreenXY:=FSynedit.ClientToScreen(ClientXY); //Position on the screen
|
||||||
|
dec(ScreenXY.Y,4); //Move it up a lilttle bit above your text, to make the shade come out better?
|
||||||
|
|
||||||
|
//Set the new position
|
||||||
|
BoundsRect:=Bounds(ScreenXY.X,ScreenXY.Y,DrawWidth,DrawHeight);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TParamHint.UpdateHint;
|
||||||
|
var
|
||||||
|
MustHide : boolean;
|
||||||
|
CursorXY : TPoint;
|
||||||
|
Line : string;
|
||||||
|
begin
|
||||||
|
if not self.Visible then
|
||||||
|
exit;
|
||||||
|
try
|
||||||
|
MustHide := True;
|
||||||
|
if not Assigned(FSynEdit) then
|
||||||
|
exit;
|
||||||
|
if FSynEdit.Focused = false then //No focus, hide this hint
|
||||||
|
exit; //Exits to the finally statement ;)
|
||||||
|
CursorXY := FSynEdit.LogicalCaretXY;
|
||||||
|
if (CursorXY.x <= FBracketPoint.x) and (CursorXY.y <= FBracketPoint.y) then //Cursor moved in front of the bracket
|
||||||
|
exit;
|
||||||
|
Line:=FSynEdit.Lines[FBracketPoint.Y-1];
|
||||||
|
if (length(Line)<FBracketPoint.X) or (not (Line[FBracketPoint.X] in ['(','['])) then
|
||||||
|
exit;
|
||||||
|
if PrepareParamString(Line,MustHide) = LastParameterIndex then
|
||||||
|
exit
|
||||||
|
else if not MustHide then
|
||||||
|
Self.Invalidate;
|
||||||
|
finally
|
||||||
|
if MustHide then
|
||||||
|
Self.hide;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TParamHint.ParamHintHide(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if FMP <> nil then
|
||||||
|
freeandnil(Fmp);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TParamHint.DrawHints(var MaxWidth, MaxHeight: Integer;
|
||||||
|
Draw: boolean);
|
||||||
|
var
|
||||||
|
HorizontalSpace: Integer;
|
||||||
|
VerticalSpace: Integer;
|
||||||
|
BackgroundColor, TextGrayColor, TextColor, PenColor: TColor;
|
||||||
|
TextGrayStyle, TextStyle: TFontStyles;
|
||||||
|
|
||||||
|
procedure DrawHint(const Line: string; var AHintRect: TRect);
|
||||||
|
var
|
||||||
|
ATextRect: TRect; //The area we can use
|
||||||
|
TokenRect: TRect; //The area the text takes up
|
||||||
|
TokenSize: TPoint; //The W/H the text takes up
|
||||||
|
TokenPos: TPoint; //The position where the text is drawn
|
||||||
|
UsedWidth: Integer; // maximum right token position
|
||||||
|
LineHeight: Integer; // Current line height
|
||||||
|
Bolding : boolean; //If we are in a bolding part.
|
||||||
|
Pos : integer;
|
||||||
|
StartPos : integer;
|
||||||
|
//Text takes up it's own Width/Height + the space around the text.
|
||||||
|
begin
|
||||||
|
ATextRect:=Rect(AHintRect.Left+HorizontalSpace,
|
||||||
|
AHintRect.Top+VerticalSpace,
|
||||||
|
AHintRect.Right-HorizontalSpace,
|
||||||
|
AHintRect.Bottom-VerticalSpace);//Possible area!
|
||||||
|
UsedWidth:=0;
|
||||||
|
LineHeight:=0;
|
||||||
|
TokenPos:=Point(ATextRect.Left,ATextRect.Top); //StartPoint like (0,0)
|
||||||
|
Bolding := False;
|
||||||
|
Pos := 0;
|
||||||
|
//Split the drawing up in words, that way we can split the function if it gets to long ;).
|
||||||
|
while (Pos < Length(Line)) do
|
||||||
|
begin
|
||||||
|
inc(Pos);
|
||||||
|
if (Line[Pos] = '\') then //Bold from now
|
||||||
|
begin;
|
||||||
|
if Draw then
|
||||||
|
begin
|
||||||
|
if not Bolding then
|
||||||
|
begin
|
||||||
|
Canvas.Font.Color := TextColor;
|
||||||
|
Canvas.Font.Style := TextStyle;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
Canvas.Font.Color := TextGrayColor;
|
||||||
|
Canvas.Font.Style := TextGrayStyle;
|
||||||
|
end;
|
||||||
|
Bolding := not Bolding;
|
||||||
|
end;
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
StartPos := Pos;
|
||||||
|
if (Line[Pos] in ['a'..'z', 'A'..'Z', '0'..'9', '_']) then //We are in a word, lets draw that completely ;)
|
||||||
|
begin
|
||||||
|
while ((Pos < length(line)) and (Line[Pos + 1] in ['a'..'z', 'A'..'Z', '0'..'9', '_'])) do
|
||||||
|
inc(pos);
|
||||||
|
end else
|
||||||
|
while ((Pos < length(line)) and not(Line[Pos + 1] in ['a'..'z', 'A'..'Z', '0'..'9', '_','\'])) do
|
||||||
|
inc(pos);
|
||||||
|
TokenRect:=Bounds(0,0,12345,1234); //Random rect
|
||||||
|
DrawText(Canvas.Handle,@Line[StartPos],Pos-StartPos + 1,TokenRect,
|
||||||
|
DT_SINGLELINE+DT_CALCRECT+DT_NOCLIP); //Calculate the size it takes to draw this text
|
||||||
|
TokenSize:=Point(TokenRect.Right,TokenRect.Bottom); //The size it takes to draw this text
|
||||||
|
if (LineHeight>0) and (TokenPos.X+TokenSize.X>ATextRect.Right) then //It doesn't fit.. Text = 2 long
|
||||||
|
begin
|
||||||
|
if Draw and (TokenPos.X<AHintRect.Right) then //Fill the rest of the area with blank info,
|
||||||
|
//since we are going to draw this text on the next line
|
||||||
|
Canvas.FillRect(Rect(TokenPos.X,TokenPos.Y-VerticalSpace,
|
||||||
|
AHintRect.Right,TokenPos.Y+LineHeight+VerticalSpace));
|
||||||
|
TokenPos:=Point(ATextRect.Left,TokenPos.y+LineHeight+VerticalSpace);//Lets start on the left side, one row below ;)
|
||||||
|
LineHeight:=0;
|
||||||
|
end;
|
||||||
|
OffsetRect(TokenRect,TokenPos.x,TokenPos.y); //Move the tokenrectangle to the tokenposition
|
||||||
|
if Draw then
|
||||||
|
begin
|
||||||
|
Canvas.FillRect(Rect(TokenRect.Left,TokenRect.Top-VerticalSpace,
|
||||||
|
TokenRect.Right,TokenRect.Bottom+VerticalSpace));//Fill the entire rect (means including the spaces above and below
|
||||||
|
DrawText(Canvas.Handle,@Line[StartPos],Pos-StartPos + 1,
|
||||||
|
TokenRect,DT_SINGLELINE+DT_NOCLIP); //Draw the text!
|
||||||
|
end;
|
||||||
|
if LineHeight<TokenSize.y then
|
||||||
|
LineHeight:=TokenSize.y; //the line has a bigger height than before.. The text H is bigger.
|
||||||
|
inc(TokenPos.X,TokenSize.x); //Move the tokenposition text-width to the right
|
||||||
|
if UsedWidth<TokenPos.X then //Calculate the max-width we've used!
|
||||||
|
UsedWidth:=TokenPos.X;
|
||||||
|
end;
|
||||||
|
if Draw and (TokenPos.X<AHintRect.Right) and (LineHeight>0) then //Fill the rest of the unused area
|
||||||
|
Canvas.FillRect(Rect(TokenPos.X,TokenPos.Y-VerticalSpace,
|
||||||
|
AHintRect.Right,TokenPos.Y+LineHeight+VerticalSpace));
|
||||||
|
if (not Draw) and (UsedWidth>0) then
|
||||||
|
AHintRect.Right:=UsedWidth+HorizontalSpace; //Calculate the width we actually need
|
||||||
|
AHintRect.Bottom:=TokenPos.Y+LineHeight+VerticalSpace;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
CurHintRect: TRect;
|
||||||
|
MustHide : boolean;
|
||||||
|
hintstr: string;
|
||||||
|
begin
|
||||||
|
if Draw then
|
||||||
|
begin
|
||||||
|
BackgroundColor:=clInfoBk;
|
||||||
|
TextGrayColor:=clInfoText;
|
||||||
|
TextGrayStyle:=[];
|
||||||
|
TextColor:=clInfoText;
|
||||||
|
TextStyle:=[fsBold];
|
||||||
|
PenColor:=clBlack;
|
||||||
|
end;
|
||||||
|
HorizontalSpace:=2; //The spaces around the text
|
||||||
|
VerticalSpace:=2;
|
||||||
|
|
||||||
|
if Draw then begin
|
||||||
|
Canvas.Brush.Color:=BackgroundColor;
|
||||||
|
Canvas.Font.Color:=TextGrayColor;
|
||||||
|
Canvas.Font.Style:=TextGrayStyle;
|
||||||
|
Canvas.Pen.Color:=PenColor;
|
||||||
|
end else begin
|
||||||
|
Canvas.Font.Style:=[fsBold]; //Let us calculate the maximum width we need :)
|
||||||
|
end;
|
||||||
|
CurHintRect:=Rect(0,0,MaxWidth,MaxHeight);
|
||||||
|
PrepareParamString(HintStr,MustHide);
|
||||||
|
if MustHide then
|
||||||
|
begin;
|
||||||
|
Self.Hide;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
DrawHint(HintStr, CurHintRect);
|
||||||
|
|
||||||
|
if Draw then //Fill the rest if needed.. (Possible if we calculated we need 2 rows, but turns out we need only 1 this time).
|
||||||
|
begin
|
||||||
|
if CurHintRect.Bottom<MaxHeight then
|
||||||
|
Canvas.FillRect(Rect(0,CurHintRect.Bottom,MaxWidth,MaxHeight));
|
||||||
|
// draw frame around window
|
||||||
|
Canvas.Frame(Rect(0,0,MaxWidth-1,MaxHeight-1));
|
||||||
|
end;
|
||||||
|
if not Draw then //Adjust the maxwidth/maxheight needed to draw this thingy!
|
||||||
|
begin
|
||||||
|
if CurHintRect.right<MaxWidth then
|
||||||
|
MaxWidth:=CurHintRect.right;
|
||||||
|
if CurHintRect.Bottom<MaxHeight then
|
||||||
|
MaxHeight:=CurHintRect.Bottom;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TParamHint.Paint;
|
procedure TParamHint.Paint;
|
||||||
|
var
|
||||||
function GetDrawTextFlags: Cardinal;
|
MaxWidth,MaxHeight : integer;
|
||||||
var
|
begin
|
||||||
EffectiveAlignment: TAlignment;
|
MaxWidth:= ClientWidth;
|
||||||
begin
|
MaxHeight := ClientHeight;
|
||||||
Result := DT_NOPREFIX or DT_VCENTER or DT_WORDBREAK;
|
DrawHints(MaxWidth,MaxHeight,True);
|
||||||
EffectiveAlignment := Alignment;
|
|
||||||
if BiDiMode <> bdLeftToRight then
|
|
||||||
begin
|
|
||||||
Result := Result or DT_RTLREADING;
|
|
||||||
//change alignment if is RTL
|
|
||||||
if BiDiMode = bdRightToLeft then
|
|
||||||
begin
|
|
||||||
case Alignment of
|
|
||||||
taLeftJustify: EffectiveAlignment := taRightJustify;
|
|
||||||
taRightJustify: EffectiveAlignment := taLeftJustify;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
case EffectiveAlignment of
|
|
||||||
taLeftJustify: Result := Result or DT_LEFT;
|
|
||||||
taCenter: Result := Result or DT_CENTER;
|
|
||||||
taRightJustify: Result := Result or DT_RIGHT;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
procedure TParamHint.Show(StartPoint,BracketPoint: TPoint;Decl : TciProcedureDeclaration; Editor: TSynedit; mp : TCodeInsight);
|
||||||
ARect: TRect;
|
|
||||||
Details: TThemedElementDetails;
|
|
||||||
begin
|
begin
|
||||||
ARect := ClientRect;
|
if self.Visible then
|
||||||
if Color = clInfoBk then // draw using themes
|
self.hide;
|
||||||
begin
|
FDecl := Decl;
|
||||||
Details := ThemeServices.GetElementDetails(tttStandardLink);
|
Fmp := mp;
|
||||||
ThemeServices.DrawElement(Canvas.Handle, Details, ARect);
|
FParameters:= Decl.GetParamDeclarations;
|
||||||
end
|
if Length(FParameters) = 0 then //Method has no Parameters
|
||||||
else
|
exit;
|
||||||
begin
|
FSynEdit := Editor;
|
||||||
Canvas.Brush.Color := Color;
|
FStartPoint:= StartPoint;
|
||||||
Canvas.Pen.Width := 1;
|
FBracketPoint:= BracketPoint;
|
||||||
Canvas.FillRect(ARect);
|
CalculateBounds; //Calculate the size we need!
|
||||||
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDOUTER, BF_RECT);
|
self.Visible := true;
|
||||||
end;
|
end;
|
||||||
InflateRect(ARect, - 4, - 4);
|
|
||||||
Canvas.TextOut(ARect.Left, ARect.Top, Caption);
|
|
||||||
|
procedure TParamHint.ApplicationIdle(Sender: TObject; var Done: Boolean);
|
||||||
|
begin
|
||||||
|
if not Visible then exit;
|
||||||
|
UpdateHint;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -16,6 +16,8 @@ type
|
|||||||
|
|
||||||
TOnFindInclude = function(Sender: TObject; var FileName: string): Boolean of object;
|
TOnFindInclude = function(Sender: TObject; var FileName: string): Boolean of object;
|
||||||
|
|
||||||
|
{ TCodeInsight }
|
||||||
|
|
||||||
TCodeInsight = class(TCodeParser)
|
TCodeInsight = class(TCodeParser)
|
||||||
protected
|
protected
|
||||||
fFileName: string;
|
fFileName: string;
|
||||||
@ -49,6 +51,7 @@ type
|
|||||||
function GetFuncType(FuncName, FuncClass: string; out Decl: TDeclaration; Return: TVarBase): Boolean;
|
function GetFuncType(FuncName, FuncClass: string; out Decl: TDeclaration; Return: TVarBase): Boolean;
|
||||||
function FindStruct(s: string; out Decl: TDeclaration; Return: TVarBase; var ArrayCount: Integer): Boolean;
|
function FindStruct(s: string; out Decl: TDeclaration; Return: TVarBase; var ArrayCount: Integer): Boolean;
|
||||||
public
|
public
|
||||||
|
function GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; out sp : Integer; IgnoreBrackets: Boolean = False): string; overload;
|
||||||
function GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string; overload;
|
function GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string; overload;
|
||||||
function GetExpressionAtPos: string; overload;
|
function GetExpressionAtPos: string; overload;
|
||||||
function FindVarBase(s: string; GetStruct: Boolean = False; Return: TVarBase = vbName): TDeclaration;
|
function FindVarBase(s: string; GetStruct: Boolean = False; Return: TVarBase = vbName): TDeclaration;
|
||||||
@ -545,7 +548,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCodeInsight.GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string;
|
function TCodeInsight.GetExpressionAtPos(var BraceCount, BracketCount,CommaCount: Integer; out sp: Integer; IgnoreBrackets: Boolean): string;
|
||||||
var
|
var
|
||||||
i, StartPos, EndPos: Integer;
|
i, StartPos, EndPos: Integer;
|
||||||
s: string;
|
s: string;
|
||||||
@ -636,10 +639,17 @@ begin
|
|||||||
LastWasDot := False;
|
LastWasDot := False;
|
||||||
Dec(StartPos);
|
Dec(StartPos);
|
||||||
end;
|
end;
|
||||||
|
sp := startpos + d.StartPos;
|
||||||
Result := CompressWhiteSpace(Copy(s, StartPos + 1, EndPos - StartPos));
|
Result := CompressWhiteSpace(Copy(s, StartPos + 1, EndPos - StartPos));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCodeInsight.GetExpressionAtPos(var BraceCount, BracketCount, CommaCount: Integer; IgnoreBrackets: Boolean = False): string;
|
||||||
|
var
|
||||||
|
sp : integer;
|
||||||
|
begin
|
||||||
|
result := GetExpressionAtPos(bracecount,bracketcount,commacount,sp,ignorebrackets);
|
||||||
|
end;
|
||||||
|
|
||||||
function TCodeInsight.GetExpressionAtPos: string;
|
function TCodeInsight.GetExpressionAtPos: string;
|
||||||
var
|
var
|
||||||
bcc, bkc, cc: Integer;
|
bcc, bkc, cc: Integer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user