Table of Contents

Writing Scripts

This chapter is for the script author — the person who writes the scripts that your application runs. It covers the languages and features available when writing scripts, and how to declare forms and classes directly in script and reuse one script from another.

Two scripting languages are available; the syntax of each is described in its own topic:

Declaring forms in script

A powerful feature of scripter is the ability to declare forms in script and load their resources from DFM files. You declare a form, create an instance of it, and use it much like you would in Delphi.

Take the following scripts as an example:

// Main script
uses
  Classes, Forms, MyFormUnit;
 
var
  MyForm: TMyForm;
begin
  {Create instances of the forms}
  MyForm := TMyForm.Create(Application);
 
  {Initialize all forms calling its Init method}
  MyForm.Init;
 
  {Set a form variable. Each instance has its own variables}
  MyForm.PascalFormGlobalVar := 'my instance';
 
  {Call a form "method". You declare the methods in the form script like procedures}
  MyForm.ChangeButtonCaption('Another click');
 
  {Accessing form properties and components}
  MyForm.Edit1.Text := 'Default text';
 
  MyForm.Show;
end;
// My form script
{$FORM TMyForm, myform.dfm}
 
var
  MyFormGlobalVar: string;
 
procedure Button1Click(Sender: TObject);
begin
  ShowMessage('The text typed in Edit1 is ' + Edit1.Text +
    #13#10 + 'And the value of global var is ' + MyFormGlobalVar);
end;
 
procedure Init;
begin
  MyFormGlobalVar := 'null';
  Button1.OnClick := 'Button1Click';
end;
 
procedure ChangeButtonCaption(ANewCaption: string);
begin
  Button1.Caption := ANewCaption;
end;

The sample scripts above show how to declare a form, create instances, and use its "methods" and variables. The form script is treated as a regular reusable script, so it follows the same loading rules.

The $FORM directive is the key piece of a form script. It tells the compiler to treat the script as a form class that can be instantiated, with all its variables and procedures treated as form properties and methods. The directive has the format {$FORM FormClass, FormFileName}, where FormClass is the name of the form class used to create instances and FormFileName is the DFM file loaded when the form is instantiated. The DFM file is searched the same way as other reusable scripts, using the host's LibOptions.SearchPath (see Loading script libraries from files).

As an alternative to loading a DFM file, you can set the form resource through the TatScript.​Design​Form​Resource string property of the TatScript object that holds the form script. Set it to the DFM content in binary format; when it is not empty, the compiler ignores the DFM file named in the $FORM directive and uses this property instead.

The DFM file must be a regular Delphi DFM file in text format. It cannot contain event handlers, otherwise an error is raised when the DFM is loaded.

All components present in the DFM form must be registered beforehand. For example, if the DFM contains a TEdit and a TButton, register them once in your application before loading the form:

RegisterClasses([TEdit, TButton]);

Otherwise a "class not registered" error is raised when the form is instantiated.

Declaring classes in script (script-based classes)

You can also declare classes in a script, then create instances and reuse them much like Delphi classes.

Declaring the class. Each class is declared in a separate script — one script per class. Turn a script into a "class script" by adding the $CLASS directive at the beginning, followed by the class name:

// Turn this script into a class script for TSomeClass
{$CLASS TSomeClass}

Methods and properties. Each global variable declared in a class script becomes a property of the class, and each procedure/function becomes a method. The main routine of the script runs whenever a new instance is created, so it works as a class initializer where you can set default property values:

// My class script
{$CLASS TMyClass}
uses Dialogs;
 
var
  MyProperty: string;
 
procedure SomeMethod;
begin
  ShowMessage('Hello, world!');
end;
 
// class initializer
begin
  MyProperty := 'Default Value';
end;

Using the class. Use the class from another script by creating an instance of the named class:

uses MyClassScript;
var
  MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  MyClass.MyProperty := 'test';
  MyClass.SomeMethod;
end;

Implementation details. Classes declared in script are "pseudo" classes: no real Delphi class is created. Although the sample calls TMyClass.Create, the name TMyClass only has meaning to the scripting system. All script-based objects are actually instances of TScriptBaseObject. You can change this by setting the scripter's TatCustomScripter.​Script​Base​Object​Class property to a class that descends from TScriptBaseObject.

Memory management. You can call Free on a script-based instance, but you don't have to: all script-based objects are eventually destroyed by the scripter component.

Limitations. Because no real Delphi class is created, inheritance is not supported — all script-based classes are the same underlying Delphi class, so a script class cannot inherit from another.

Using other scripts

A script can "use" another script — to call its procedures and functions, or read and write its global variables. This makes one script act as a library for another.

Take the following two scripts:

// Script1
uses Script2;
 
begin
  Script2GlobalVar := 'Hello world!';
  ShowScript2Var;
end;
// Script2
var
  Script2GlobalVar: string;
 
procedure ShowScript2Var;
begin
  ShowMessage(Script2GlobalVar);
end;

When the first script runs, it "uses" Script2 and can therefore read and write its global variables and call its procedures. Form scripts and class scripts described above are used the same way — by naming them in a uses clause.

The only requirement is that the host application must know where to find the used script. The compiler resolves a name in a uses clause against registered Delphi libraries, scripts in the scripter's Scripts collection, and script files on disk. How the host configures this resolution — including the search path and file extensions — is described in Loading script libraries from files.