Table of Contents

Working with scripter

This chapter explains how to use the scripter component in your application: how to run scripts, call subroutines, pass parameters back and forth, configure where script libraries are loaded from, and debug a running script.

To make your own Delphi classes, objects, functions, variables and libraries available to scripts, see Extending Scripter. For the script language itself — syntax, forms and classes declared in script — see Writing Scripts.

Getting started

To start using scripter, you just need to know one property (TatCustomScripter.​Source​Code) and one method (TatCustomScripter.​Execute). To execute a simple script, drop a scripter component on a form and use the following code (in a button click event, for example):

Scripter.SourceCode.Text := 'ShowMessage(''Hello world!'');';
Scripter.Execute;

You will get a "Hello world!" message after calling the Execute method. That's it — from now on you can execute scripts. To make it more interesting, drop a TAdvMemo component on the form and change the code to:

Scripter.SourceCode := AdvMemo1.Lines;
Scripter.Execute;

C++Builder example

Now you can type scripts at runtime and execute them.

From this point on, any reference to the scripter object (its methods, properties and events) refers to TatScripter. The script examples are given in Pascal syntax.

Cross-language feature: TatScripter and TIDEScripter

TatScripter is a single scripter component that supports cross-language and cross-platform scripting: a script written in Basic can call a procedure written in Pascal and vice-versa, transparently, within the same scripter.

The language of each script in the TatScripter component is controlled by two members:

TatBaseScripter.​Default​Language is the language used for scripts created the usual way (Scripter.Scripts.Add). Its type is TScriptLanguage (slPascal or slBasic) and it defaults to slPascal. Set it to slBasic to make new scripts use Basic by default.

TScriptLanguage = (slPascal, slBasic);
property DefaultLanguage: TScriptLanguage;

TatBaseScripter.​Add​Script creates a new script with an explicit language, regardless of DefaultLanguage. For example, to create one Pascal and one Basic script in the same component:

MyPascalScript := atScripter1.AddScript(slPascal);
MyBasicScript := atScripter1.AddScript(slBasic);

C++Builder example

Two compilation options affect how scripts are interpreted, both True by default:

Note

TIDEScripter is a TatScripter descendant with the same scripting capabilities plus the ability to integrate with the Scripter Studio IDE. Use it instead of TatScripter when you embed the IDE; it adds no overhead otherwise. The legacy single-language components TatPascalScripter and TatBasicScripter remain available for backward compatibility.

Common tasks

Calling a subroutine in script

If the script declares one or more functions or procedures, you can call them directly with TatCustomScripter.​Execute​Subroutine:

Pascal script:

procedure DisplayHelloWorld;
begin
  ShowMessage('Hello world!');
end;
 
procedure DisplayByeWorld;
begin
  ShowMessage('Bye world!');
end;

Basic script:

sub DisplayHelloWorld
   ShowMessage("Hello world!")
end sub
 
sub DisplayByeWorld
   ShowMessage("Bye world!")
end sub

CODE:

Scripter.ExecuteSubroutine('DisplayHelloWorld');
Scripter.ExecuteSubroutine('DisplayByeWorld');

C++Builder example

This displays the "Hello world!" and "Bye world!" message dialogs.

Returning a value from script

TatCustomScripter.​Execute is a function whose result is a Variant. If the script returns a value, it can be read from Delphi code. For example, calling a script function Calculate:

Pascal script:

function Calculate;
begin
  result := (10+6)/4;
end;

Basic script:

function Calculate
   Calculate = (10+6)/4
end function

CODE:

FunctionValue := Scripter.ExecuteSubroutine('Calculate');

FunctionValue receives 4. You don't need to declare a function to return a value; the script main block can return a value directly:

Pascal script:

result := (10+6)/4;

CODE:

FunctionValue := Scripter.Execute;

C++Builder example

Tip

In Basic syntax, to return a function value use the FunctionName = Value syntax. You can also return a value without declaring a function by using the reserved word MAIN: MAIN = (10+6)/4.

Passing parameters to script

To pass values to a script, use the same TatCustomScripter.​Execute and TatCustomScripter.​Execute​Subroutine methods with their overloaded forms. Parameters are Variant types:

Pascal script:

function Double(Num);
begin
  result := Num*2;
end;

Basic script:

function Double(Num)
  Double = Num*2
End function

CODE:

FunctionValue := Scripter.ExecuteSubroutine('Double', 5);

FunctionValue receives 10. To pass more than one parameter, use a Variant array or an array of const:

Pascal script:

function MaxValue(A,B);
begin
  if A > B then
    result := A
  else
    result := B;
end;
 
procedure Increase(var C; AInc);
begin
  C := C + AInc;
end;

CODE:

var
  MyVar: Variant;
begin
  FunctionValue := Scripter.ExecuteSubroutine('MaxValue', VarArrayOf([5,8]));
  Scripter.ExecuteSubroutine('Increase', [MyVar, 3]);
end;

C++Builder example

Note

To pass a parameter by reference when calling a script subroutine, the Delphi variable must be declared as a Variant. In the example above, MyVar must be of Variant type, otherwise the script will not update its value.

Note

Script parameters don't need types; you just declare their names.

Loading script libraries from files

A script can use other scripts as libraries with a uses clause (see Using other scripts for the script-author side). When the compiler reaches a name in a uses clause, it tries to resolve it in this order:

  1. A registered Delphi-based library with that name — any library registered with RegisterScripter​Library (for example the imported VCL units such as Classes and Forms). See Using libraries.
  2. A script in the Scripts collection whose UnitName matches the name. Each TatScript object has a UnitName property you can set so the script is treated as a library.
  3. A file whose name matches the library name, when TatCustomScripter.​Lib​Options enables file loading.

The TatCustomScripter.​Lib​Options property controls the file search:

  • SearchPath — a TStrings of paths where scripter looks for the file. It accepts the constants $(CURDIR) (the current directory) and $(APPDIR) (the application path).
  • SourceFileExt — the default extension for source files (for example .psc, so uses Script2 looks for Script2.psc).
  • CompileFileExt — the default extension for compiled files (for example .pcu). Scripter looks for compiled files first, then source files.
  • UseScriptFiles — turns file-based library loading on or off. When False, scripter does not look for files at all.

Debugging scripts

TMS Scripter provides two ways to debug scripts at run time: using the scripter component's own properties and methods, which lets you build your own debug environment; or using the ready-made debug component, which requires only dropping a component and calling a method.

Using methods and properties for debugging

The scripter component exposes the following members for driving execution from Delphi code:

Using the debug component

For VCL applications, the TatScriptDebugDlg component provides high-level debugging. Drop it on a form, assign its Scripter property to an existing scripter component, and call its Execute method: a debug dialog appears showing the script source with a toolbar. The shortcut keys match Delphi's:

  • F4: Run to cursor
  • F5: Toggle breakpoint
  • F7: Step into
  • F8: Step over
  • F9: Run
  • Shift+F9: Pause
  • Ctrl+F2: Reset
  • Shift+F11: Run until return

Form-aware scripters (legacy)

Note

TatPascalFormScripter and TatBasicFormScripter are legacy single-language scripters, kept for backward compatibility, that descend from TatPascalScripter and TatBasicScripter. They automatically register the components owned by the form the scripter belongs to, so a script can access those components without registering them first. New applications should use TatScripter and register the objects they need with TatCustomScripter.​Add​Component.