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
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
Calling a script or handler as a function works the same way: just use the script or handler name as a function. 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
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 commandsand 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.
The run command can be used 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 accrueInterest 30, 4.125 to account
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 send 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.
Syntax:
run scriptName {,} {parameters}
run scriptName 's handlerName {parameters}
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
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}
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
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
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
Tech Talk
The messages that are sent to the target include:
command messages from "generic" commands of the form:
commandName {parameter1 {, parameter2}…}
and function messages that don't have an explicit target:
functionName ( {parameter1 {, parameter2}…} ) {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 example to 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:
sendmessage {to object}
sendmessage parameters {to object}
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
Example:
send"Hello"tonewObject
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.
sendaccrueInterest30, 4.625toaccount
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:
thetarget
target()
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
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
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
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
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
get doAppleScript(expression)
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
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]
Syntax definitions for language elements follow these formatting guidelines:
- boldface: Indicates words and characters that must be typed exactly
- italic: Indicates expressions or other variable elements
- {} (curly braces): Indicate optional elements.
- [] (square brackets) separated by | (vertical pipes): Indicate alternative options where one or the other can be used, but not both.
Example syntax:
In this example, "open file" is required and must be typed exactly. "fileName" is a variable element; it is the path to and name of the file being opened. The following expression is optional and indicates why the file is being opened. If this expression is added, "for" is required and must be typed exactly. One of the following must be included, but only one, and they also must be typed exactly: "reading", "writing", "readwrite", "appending", or "updating".
Example:
[currentLoan computeInterest:10,9,5000]
Example:
answer "The result is: " & [calculator getResult]