Skip to main content

Running Other Scripts and Handlers

Writing other scripts and handlers outside of the main script for your test allows you to create reusable chunks of code, effectively modularizing your test. But, how do you call those scripts and handlers once they're written? This page explains how, and then provides some related commands and functions.

Calling a Local Handler or Script

Calling a Handler or Script as a Command

Syntax:
scriptOrHandlerName {parameters}

To call another handler within your script, simply use the handler name as a command, along with any needed parameters. For example, consider this command:

recordScores 2017, rawScores

If there is a "to" (or "on") handler in the local script for the recordScores message, this command will run that handler, passing it two parameters.

If there is no local handler for the recordScores command, but there is a script by that name, that script (meaning, the script's initial handler) will be run, passing it the two parameters. So in either case, to call a handler in the local script, or another script in the same directory, all that is needed is to use that handler or script name as a command.

Calling a Handler or Script as a Function

Syntax:
scriptOrFunctionName ( {parameters} )

Calling a script or handler as a function works the same way: just use the script or handler name as a function name within an expression context (not at the beginning of a line, which would be a command call). For example, consider this function call:

put consolidatedSales("Ohio") into ohioSales

In this case if there is a "to" (or "function") handler in the local script for the consolidatedSales message, this function call will run that handler, passing it the single parameter value "Ohio". The return value from that handler will be stored in the variable ohioSales.

If there is no local handler for the consolidatedSales function, but there is a script by that name, that script (meaning the script's initial handler) will be run, passing it the value "Ohio", and the return value from that script will be stored into ohioSales.

For the vast majority of cases, this simple approach to calling another script or handler is all that's needed. The command or function call will send a message to the current script which will be handled by a local handler. If there is no local handler for the message, it will be passed to a local script with the same name as the message.

Calling a Handler Within Another Script

Command Syntax:
scriptName . handlerName {parameters}
scriptName 's handlerName {parameters}

Function Syntax:
scriptName . handlerName ( {parameters} )
scriptName 's handlerName ( {parameters} )

Occasionally, you may want to call a handler (other than the initial handler) in another script. To do this, the dot or apostrophe-s notation can be used. For example, to call the to recordScores handler in a script called "FileUtility" as a command, you could use this command:

FileUtility.recordScores 2017, rawScores

Similarly, to call the consolidatedSales handler in a "BusinessCenter" script as a function, you could do it like this:

put BusinessCenter's consolidatedSales("Ohio") into ohioSales

Other Flow Control Commands and Functions

These lesser used commands and functions allow you to control the execution flow of your test.

Run Command

Behavior: Calls the scriptName script, or the handlerName handler of that script, as a command. HandlerName is usually just the simple name of a handler without quotes, but may also be given as a quoted literal, or as an expression in parentheses to construct the handler name at run time.

Syntax:
run scriptName {,} {parameters}
run scriptName 's handlerName {parameters}

The run command is only needed to run a specified script when a simple command as shown above won't work, such as when a full pathname is needed or the script's name contains spaces or other special characters, or when the name of the script to be run is in a variable. The following command will run the script’s initial handler:

run "/tmp/testScript.st"

Parameters may be passed:

run "common/startup" 1200,true,"salvador"

A specific handler other than the script’s initial handler may be called, using 's:

run "common/finance" 's amortize 143000,6.75,360

The run command may be used with any object, not just a script file:

run account's accrueInterest 30, 4.125

The preceding example is equivalent to:

Tell account to accrueInterest 30, 4.125

Although the run command provides similar functionality to that of the tell command, it offers an alternative syntax for running a script, and also gives you the ability to run the initial handler of a script, which the tell command does not provide. In addition, the run command runs the script’s initial handler directly, without calling front scripts, back scripts, or helpers.

The run command also supports calling a handler whose name is dynamic, or comes from a variable or an expression:

run scriptName.(commandName) playerType,loopLocation

In this case, scriptName and commandName are both treated as variables that hold the names of the script and handler to be called. This example sends a "command"-type message that can be handled by either a "to" or "on" handler.

Run Function

Behavior: Calls the initial handler of a script or other object explicitly as a function. This also allows calling a script whose name is generated dynamically at runtime. The run function needs to be called in a way that sends the run message to the target object, such as using dot notation.

Syntax:
object .run( parameters )
{the} run of object {with parameters}

Example:

set doubler to (script:"return 2*param(1)")
put doubler.run(12) -- 24
get ("test" & testNumber).run(value1, value2)
-- call script dynamically

Tell Command

Behavior: This flow control command changes the message target for any command or function. Ordinarily, when a generic command or function is called, it sends a message to the object whose script is running (the target of the message). If that object has a handler for that message, that handler is executed, otherwise the message is passed along The Message Path. Tell changes the target for any generic messages sent by the statement or StatementList (see Syntax below), so those messages are sent to the defined object instead. If the object doesn't have a handler for the message, the message is passed along the subsequent message path as usual.

Syntax:
tell object [ to {:} | : ] statement

tell object {to} {:}
    statementList
end tell

Tech Talk

The messages that are sent to the target include:

  • command messages from "generic" commands of the form:
       commandName {parameters}
  • function messages that don't have an explicit target:
       functionName ( {parameters} )
       {the} functionName of parameter

Examples:

The main use of the Tell flow control command is as an alternative mechanism for calling handlers in specific objects or scripts. For example, to call the recordScores handler in a script called "FileUtility" as a command, then instead of using this command...

FileUtility.recordScores 2017, rawScores

... you could use Tell instead, like this:

Tell FileUtility to recordScores 2017, rawScores

Similarly, to call the consolidatedSales handler in a "BusinessCenter" script as a function, then instead of doing it like this:

put BusinessCenter's consolidatedSales("Ohio") into ohioSales

you could use Tell instead, like this:

Tell BusinessCenter to put consolidatedSales("Ohio") into ohioSales

Those examples may not add much other than clarifying the intent of the code and making it more readable. The real utility of Tell comes when using the block form of Tell to target a number of commands and functions to a specific object, or in cases where the object isn't a script, but is stored in a variable.

Example:

Here is an example that uses the block form of Tell.

Tell BusinessCenter
put consolidatedSales("Ohio") into ohioSales
put consolidatedSales("Pennsylvania") into pennsylvaniaSales
put consolidatedSales("California") into californiaSales
End Tell

Example:

Here is an example involving a deckofCards object that is created from a "StandardDeck" script.

set deckOfCards to a new StandardDeck with {jokers:No} -- Set up the test with a standard deck and no jokers

// Use Tell to shuffle a deck of cards and deal two Poker hands:
tell deckOfCards -- Directs the following commands and functions to the deckOfCards object
shuffle -- Shuffle command is sent to DeckOfCards object
put dealCards(5) into pokerHand1 -- Sends the dealCards function message, with a parameter of 5, to the deckOfCards object and stores the output in pokerHand1
put dealCards(5) into pokerHand2 -- Repeats the same as the prior command but stores the output in pokerHand2
end tell

// Print the output to the run window:
put "Hand 1: " & pokerHand1
put "Hand 2: " & pokerHand2

Send Command

Behavior: Sends a message to another object. Message is an expression which is evaluated as text. The message sent may include parameters, either within the message string (as in the calculateLoan example) or separately (as in the accrueInterest example). If an object is not specified, the message is sent to the object me (that is, the object containing the script).

Syntax:
send message {to object}
send message parameters {to object}

Example:

send "Hello" to newObject

Example:

In this example, parameters are included within the message string.

send "calculateLoan 10,9,5000" to "Loan"

Example:

In this example, parameters are passed separately from the message string.

send accrueInterest 30, 4.625 to account

Target Function

Behavior: Returns the long ID of the object to which the current message was sent. Useful in a handler farther down the message passing path when you need to know what the original target of the message was.

Syntax:
the target
target()

As of SenseTalk version 1.1, using the syntax the target accesses the target object directly. The target() syntax calls a function which (if not overridden by another script in the message path) will return the long ID of the target object. This will function equivalently for most purposes, although it may be slightly less efficient in some cases.

Example:

if the target is not me then ...

Do Command

Behavior: The do command evaluates expression as one or more SenseTalk statements and executes those statements as though they were part of the current handler. This means that the statements contained in expression can refer to, use, and modify any local variables of the handler (unless the evaluationContext global property is set to Global or Universal, in which case undeclared variables will be treated as global or universal rather than local variables).

Using the do command to execute some code is slower than including the same statements directly in your script, because the SenseTalk compiler is called to compile the code each time before it is executed. The impact on performance is especially significant if the do command will be executed many times, such as inside a repeat loop.

Syntax:
do expression

Example:

do "put total into quarter" & currentQtrNumber

Example:

do customCleanupCode

Do AppleScript Command, DoAppleScript Function

Behavior: Executes one or more statements written in the AppleScript scripting language that are contained in a variable or generated by your script at runtime. Any final value or error will be available in the result.

Syntax:
do AppleScript expression
do expression as AppleScript

As a function:
doAppleScript( expression )

Examples

do acquireDataScript as AppleScript
put "eggPlant" into app
-- name of the app we want to leave showing
do AppleScript merge of {{
tell application "Finder"
activate
set visible of every process whose name is not "[[app]]" to false
end tell
}}
put doAppleScript(merge("get [[A]] + [[B]]")) into sumDoneTheHardWay
Tech Talk

The do AppleScript command evaluates expression as AppleScript statements and executes those statements by calling the AppleScript interpreter. Values can be passed in at any point within the AppleScript code by enclosing local SenseTalk variable names and expressions in double square brackets [[ ]] within the code and using the merge function to insert their values before running the AppleScript.

When run using the doAppleScript function, the final value of the AppleScript expression will be the value returned by the function. Any errors will be returned as an exception object in the result. When do AppleScript is run as a command, the result will contain either an exception object or the final value of the expression.

The AppleScript code is run on the local machine. To send messages to another machine using this mechanism, the other machine will need to have remote events turned on in the Sharing panel of the System Preferences, and your AppleScript code will need to send commands to that machine using a tell statement looking something like this:

tell application "AppName" of machine "eppc://userName:password@xxx.xxx.xxx.xxx"

Consult an AppleScript reference for more details.

[ ] (Square Bracket Messaging)

Behavior: Use square brackets to send a function-type message to a specific object. The square bracket syntax can be used by itself as a statement, or like a function call as part of an expression. In both cases, however, the message it sends is a function message, so it must be handled by a to or function handler (not an on handler).

Syntax:
[ object functionMessage ]
[ object functionMessage : parameters ]

Example:

[currentLoan computeInterest:10,9,5000]

Example:

answer "The result is: " & [calculator getResult]