mirror of
https://github.com/moparisthebest/Simba
synced 2024-11-25 02:32:19 -05:00
076f12e2c8
Edited the way Errors are shown (thread-safe now), When error occurs in an include Simba will open the tab(if not yet open) and go to the error, Added Writeln that accepts chars,strings and all kind of integers.. (not sure whether to keep it) Added format! git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@423 3f818213-9676-44b0-a9b4-5e4c4e03d09d
356 lines
11 KiB
ObjectPascal
356 lines
11 KiB
ObjectPascal
{
|
|
This file is part of the Mufasa Macro Library (MML)
|
|
Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
|
|
|
|
MML is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
MML is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with MML. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
See the file COPYING, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
framescript for the Mufasa Macro Library
|
|
}
|
|
unit framescript;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll,
|
|
mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType, SynEditMarkupSpecialLine, Graphics, Controls;
|
|
const
|
|
ecCodeCompletion = ecUserFirst;
|
|
type
|
|
TScriptState = (ss_None,ss_Running,ss_Paused,ss_Stopping);
|
|
{
|
|
ss_None: Means the script either hasn't been run yet, or it has ended (Succesfully or terminated)
|
|
ss_Running: Means the script is running as we speak :-)
|
|
ss_Paused: Means the script is currently in pause modus.
|
|
ss_Stopping: Means we've asked PS-Script politely to stop the script (next time we press the stop button we won't be that nice).
|
|
}
|
|
|
|
{ TScriptFrame }
|
|
|
|
TScriptFrame = class(TFrame)
|
|
SynEdit: TSynEdit;
|
|
SynFreePascalSyn1: TSynFreePascalSyn;
|
|
procedure SynEditChange(Sender: TObject);
|
|
procedure SynEditDragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
procedure SynEditDragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
procedure SynEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
|
|
);
|
|
procedure SynEditProcessCommand(Sender: TObject;
|
|
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
|
procedure SynEditProcessUserCommand(Sender: TObject;
|
|
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
|
procedure SynEditSpecialLineColors(Sender: TObject; Line: integer;
|
|
var Special: boolean; var FG, BG: TColor);
|
|
procedure SynEditStatusChange(Sender: TObject; Changes: TSynStatusChanges);
|
|
private
|
|
OwnerPage : TPageControl;
|
|
OwnerSheet : TTabSheet;//The owner TTabsheet -> For title setting
|
|
public
|
|
ErrorData : TErrorData; //For threadsafestuff
|
|
ScriptErrorLine : integer; //Highlight the error line!
|
|
ScriptFile : string;//The path to the saved/opened file currently in the SynEdit
|
|
StartText : string;//The text synedit holds upon start/open/save
|
|
ScriptName : string;//The name of the currently opened/saved file.
|
|
ScriptDefault : string;//The default script e.g. program new; begin end.
|
|
ScriptChanged : boolean;//We need this for that little * (edited star).
|
|
ScriptThread : TMMLPSThread;//Just one thread for now..
|
|
FScriptState : TScriptState;//Stores the ScriptState, if you want the Run/Pause/Start buttons to change accordingly, acces through Form1
|
|
procedure undo;
|
|
procedure redo;
|
|
procedure HandleErrorData;
|
|
procedure MakeActiveScriptFrame;
|
|
procedure ScriptThreadTerminate(Sender: TObject);
|
|
constructor Create(TheOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
{ public declarations }
|
|
end;
|
|
|
|
implementation
|
|
uses
|
|
TestUnit, SynEditTypes, LCLIntF, StrUtils,framefunctionlist;
|
|
|
|
{ TScriptFrame }
|
|
|
|
procedure TScriptFrame.SynEditChange(Sender: TObject);
|
|
begin
|
|
ScriptErrorLine:= -1;
|
|
if not ScriptChanged then
|
|
begin;
|
|
ScriptChanged:= True;
|
|
Form1.Caption:= Format(WindowTitle,[ScriptName + '*']);
|
|
OwnerSheet.Caption:=ScriptName + '*';
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditDragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
begin
|
|
if TFunctionListFrame(Source).DraggingNode.Data <> nil then
|
|
SynEdit.InsertTextAtCaret( GetMethodName(PChar(TFunctionListFrame(Source).DraggingNode.Data),true));
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditDragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
begin
|
|
Accept := Source = Form1.frmFunctionList;
|
|
if(Accept)then
|
|
begin
|
|
SynEdit.CaretXY := SynEdit.PixelsToLogicalPos(point(x, y));
|
|
if(not(Form1.Active))then Form1.BringToFront;
|
|
if(Form1.ActiveControl <> SynEdit)then Form1.ActiveControl := SynEdit;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
begin
|
|
if key = VK_F3 then
|
|
begin;
|
|
Form1.ActionFindNextExecute(Sender);
|
|
key := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditProcessCommand(Sender: TObject;
|
|
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
|
begin
|
|
if Command = ecUndo then
|
|
begin;
|
|
Command:= ecNone;
|
|
Self.Undo;
|
|
end else
|
|
if Command = ecRedo then
|
|
begin;
|
|
Command := ecNone;
|
|
Self.Redo;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditProcessUserCommand(Sender: TObject;
|
|
var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
|
var
|
|
LineText,SearchText : string;
|
|
Caret : TPoint;
|
|
i,endI : integer;
|
|
begin
|
|
if Command = ecCodeCompletion then
|
|
begin
|
|
form1.FunctionListShown(True);
|
|
with form1.frmFunctionList do
|
|
if editSearchList.CanFocus then
|
|
begin;
|
|
editSearchList.SetFocus;
|
|
LineText := SynEdit.LineText;
|
|
Caret:=SynEdit.LogicalCaretXY;
|
|
i := Caret.X - 1;
|
|
endi := caret.x;
|
|
if (i > length(LineText)) or ((i = 0) and (length(lineText) = 0)) then
|
|
begin
|
|
SearchText:= '';
|
|
CompletionLine := PadRight(linetext,caret.x);
|
|
end
|
|
else begin
|
|
while (i > 0) and (LineText[i] in ['a'..'z','A'..'Z','0'..'9','_']) do
|
|
dec(i);
|
|
while LineText[endi] in ['a'..'z','A'..'Z','0'..'9','_'] do
|
|
inc(endi);
|
|
SearchText := Trim(copy(LineText, i + 1, Caret.X - i - 1));
|
|
CompletionLine := LineText;
|
|
end;
|
|
CompletionStart:= LineText;
|
|
Delete(CompletionLine,i+1,endi - i - 1);
|
|
Insert('%s',CompletionLine,i+1);
|
|
CompletionCaret := Point(endi,Caret.y);
|
|
StartWordCompletion:= Point(i+1,caret.y);
|
|
Writeln(CompletionLine);
|
|
Writeln(CompletionStart);
|
|
InCodeCompletion := true;
|
|
editSearchList.Text:= SearchText;
|
|
editSearchList.SelStart:= Length(searchText);
|
|
SynEdit.SelectedColor.Style:= [fsUnderline];
|
|
SynEdit.SelectedColor.Foreground:= clBlack;
|
|
SynEdit.SelectedColor.Background:= clWhite;
|
|
Synedit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditSpecialLineColors(Sender: TObject;
|
|
Line: integer; var Special: boolean; var FG, BG: TColor);
|
|
begin
|
|
if line = ScriptErrorLine then
|
|
begin;
|
|
Special := true;
|
|
BG := $50a0ff;
|
|
FG := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.SynEditStatusChange(Sender: TObject;
|
|
Changes: TSynStatusChanges);
|
|
begin
|
|
{$IFDEF UpdateEditButtons}
|
|
if scSelection in changes then
|
|
begin;
|
|
Form1.TT_Cut.Enabled := SynEdit.SelAvail;
|
|
form1.TT_Copy.Enabled:= Form1.TT_Cut.Enabled;
|
|
form1.TT_Paste.Enabled:= SynEdit.CanPaste;
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
procedure TScriptFrame.undo;
|
|
begin
|
|
SynEdit.Undo;
|
|
if ScriptChanged then
|
|
if SynEdit.Lines.Text = StartText then
|
|
begin;
|
|
Form1.Caption:= format(WindowTitle,[ScriptName]);
|
|
OwnerSheet.Caption:= ScriptName;
|
|
ScriptChanged := false;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.redo;
|
|
begin
|
|
SynEdit.Redo;
|
|
if ScriptChanged then
|
|
if SynEdit.Lines.Text = StartText then
|
|
begin;
|
|
Form1.Caption:= format(WindowTitle,[ScriptName]);
|
|
OwnerSheet.Caption := ScriptName;
|
|
ScriptChanged := false;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.HandleErrorData;
|
|
var
|
|
i : integer;
|
|
begin
|
|
if ErrorData.Module <> '' then
|
|
begin;
|
|
if not FileExists(ErrorData.Module) then
|
|
ErrorData.Module := ErrorData.IncludePath + ErrorData.Module;
|
|
if not FileExists(ErrorData.Module) then
|
|
Writeln('ERROR comes from a non-existing file....')
|
|
else
|
|
begin
|
|
ErrorData.Module:= SetDirSeparators(ErrorData.Module);// Set it right ;-)
|
|
for i := 0 to Form1.Tabs.Count - 1 do
|
|
if lowercase(TMufasaTab(Form1.Tabs[i]).ScriptFrame.ScriptFile) = lowercase(ErrorData.Module) then
|
|
begin;
|
|
ErrorData.Module:= '';
|
|
TMufasaTab(Form1.Tabs[i]).ScriptFrame.ErrorData := Self.ErrorData;
|
|
TMufasaTab(Form1.Tabs[i]).ScriptFrame.HandleErrorData;
|
|
Exit;
|
|
end;
|
|
Form1.AddTab;
|
|
Form1.LoadScriptFile(ErrorData.Module);
|
|
ErrorData.Module:= '';
|
|
Form1.CurrScript.ErrorData := Self.ErrorData;
|
|
Form1.CurrScript.HandleErrorData;
|
|
exit;
|
|
end;
|
|
end;
|
|
MakeActiveScriptFrame;
|
|
ScriptErrorLine:= ErrorData.Line;
|
|
SynEdit.Invalidate;
|
|
SynEdit.SelStart:= ErrorData.Position;
|
|
if pos('error',lowercase(ErrorData.Error)) > 0 then
|
|
formWriteln(Format('%s at line %d',[ErrorData.Error,ErrorData.Line]))
|
|
else
|
|
formWriteln(Format('Error: %s at line %d',[ErrorData.Error,ErrorData.Line]));
|
|
end;
|
|
|
|
procedure TScriptFrame.MakeActiveScriptFrame;
|
|
var
|
|
i : integer;
|
|
begin
|
|
if Form1.Visible then
|
|
for i := 0 to OwnerPage.PageCount - 1 do
|
|
if OwnerPage.Pages[i] = OwnerSheet then
|
|
begin;
|
|
OwnerPage.TabIndex := i;
|
|
if OwnerSheet.CanFocus then
|
|
OwnerSheet.SetFocus;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
procedure TScriptFrame.ScriptThreadTerminate(Sender: TObject);
|
|
begin
|
|
FScriptState:= ss_None;
|
|
Form1.RefreshTab;
|
|
end;
|
|
procedure AddKey(const SynEdit : TSynEdit; const ACmd: TSynEditorCommand; const AKey: word;const AShift: TShiftState);
|
|
begin
|
|
with SynEdit.KeyStrokes.Add do
|
|
begin
|
|
Key := AKey;
|
|
Shift := AShift;
|
|
Command := ACmd;
|
|
end;
|
|
end;
|
|
constructor TScriptFrame.Create(TheOwner: TComponent);
|
|
var
|
|
MarkCaret : TSynEditMarkupHighlightAllCaret;
|
|
begin
|
|
inherited Create(TheOwner);
|
|
OwnerSheet := TTabSheet(TheOwner);
|
|
OwnerPage := TPageControl(OwnerSheet.Owner);
|
|
StartText:= SynEdit.Lines.text;
|
|
ScriptDefault:= StartText;
|
|
ScriptName:= 'Untitled';
|
|
ScriptChanged := false;
|
|
FScriptState:= ss_None;
|
|
ScriptErrorLine:= -1;
|
|
OwnerSheet.Caption:= ScriptName;
|
|
SynEdit.Options:= SynEdit.Options- [eoGroupUndo];
|
|
SynEdit.Options:= SynEdit.Options+ [eoGroupUndo];
|
|
SynEdit.IncrementColor.Background := $30D070;
|
|
SynEdit.HighlightAllColor.Background:= clYellow;
|
|
SynEdit.HighlightAllColor.Foreground:= clDefault;
|
|
MarkCaret := TSynEditMarkupHighlightAllCaret(SynEdit.MarkupByClass[TSynEditMarkupHighlightAllCaret]);
|
|
if assigned(MarkCaret) then
|
|
begin
|
|
with MarkCaret.MarkupInfo do
|
|
begin;
|
|
Background :=$E6E6E6;
|
|
FrameColor := clGray;
|
|
end;
|
|
MarkCaret.Enabled := True;
|
|
MarkCaret.FullWord:= True;
|
|
MarkCaret.FullWordMaxLen:= 3;
|
|
MarkCaret.WaitTime := 1500;
|
|
MarkCaret.IgnoreKeywords := true;
|
|
end;
|
|
AddKey(SynEdit,ecCodeCompletion,VK_SPACE,[ssCtrl]);
|
|
end;
|
|
|
|
destructor TScriptFrame.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
initialization
|
|
{$I framescript.lrs}
|
|
|
|
end.
|
|
|