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 {:} | : ] statementtell object {to} {:}
statementList
end tell
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 AppleScriptAs 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
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]