The following notes provide a bare outline of the object-oriented programming (OOP) language known as AppleScript. For further information, see the AppleScript Language Guide (Addison-Wesley 1993), a scholarly although rather tedious tome.
The author originally found this language difficult, perhaps due to his familiarity with calculus and BASIC programming. In some areas, the coercions between different object types (such as text
and date
) seem inconsistent while the setting up of error handling can be very frustrating.
Here’s an embellished script that empties the Trash without leaving the current application, with comments in lines that have a --
prefix:-
set theDlg to display dialog
if button returned of theDlg
with timeout of 1 second
tell application "Finder"
empty
end tell
end timeout
end if
-- A demonstration script
(* Here’s a block of text
The above example includes the following features found in most scripts:-
display dialog
if
, end if
, with timeout
and end timeout
statementstell
and end tell
statementsA simple script, which contains only one section, usually works by what is known as an implied run command. For more complex scripts, which usually incorporate subroutines, an actual run
command must be used to identify the main part of the script, in the form shown below:-
on run
-- put your script here
end run
When a script is used as a droplet it must also have special subroutine called open
to open those items that are dropped onto it. This should be in the form shown below. In this instance the run
routine also calls the open
subroutine, thereby avoid any unnecessary duplication of script.
on open (itemList)
set itemList to itemList
repeat with theItem
-- put your script for
end repeat
end open
on run
-- put your script here
open (theFile)
end run
set itemList to itemList as list
ensures the droplet works normally when only one item is dropped onto it.The script shown below uses an open
subroutine to process items that have already been selected on the desktop or chosen via an Open dialogue. This particular example gives the name of each item.
on open (itemList)
set itemList to itemList
repeat with theItem in itemList
-- put your script for
tell application "Finder"
end repeat
end open
on run
try
tell application "Finder"
activate
set theItems to selection
if count of theItems = 0
repeat
set theItems to choose
tell me to open (theItems)
end repeat
else
tell me to open (theItems)
end if
end tell
end try
end run
Note the the use of a count
instruction that checks how many items have been selected and the repeat
loop around the choose file
line, which allows several items to be selected in turn. Finally, the tell me to open
statements instruct the script to open the chosen items, not the Finder. If you don’t use tell me
the Finder opens the items in the normal way.
In the above example, the open
subroutine includes a parameter in brackets. Other subroutines often involve several parameters, or none at all. Even if you don’t use any parameters you must still use brackets, as in mySubroutine()
.
Under normal circumstances, a failed script produces a special AppleScript error dialogue that contains an error message, sometimes accompanied by an error number, as shown below:-
Usually, clicking on the Edit button causes Script Editor to launch, revealing the error as highlighted text. As you can see, this kind of dialogue is rather ugly and the messages can be confusing, although they’re useful during debugging. They also encourage other people to tinker with your scripts.
Fortunately, AppleScript has a mechanism for using standard dialogues or removing them altogether. This is achieved by wrapping the entire script (or a selected portion of a script) inside try
and end try
statements, as in the following, where * ** ***
is the script that can cause an error:-
try
* ** ***
on error errMsg number errNum
display dialog
end try
In this case errors shown in the resultant dialogues contain both the error message and error number:-
The following example displays the message on its own:-
try
* ** ***
on error errMsg
display dialog
end try
as shown here:-
whilst this version shows a generic message for all errors:-
try
* ** ***
on error
display dialog "An
end try
which looks like this:-
Sometimes, you may want to generate error messages that vary according to what happens, whilst leaving AppleScript free to insert its own messages. Here’s an example:-
try
if * ** ***
error "It went wrong."
end if
on error errMsg
display dialog errMsg
end try
If a script is intended to produce observable effects you can prevent all error messages with a script of the form:-
try
* ** ***
end try
If your try
and end try
statements enclose part of a script you can force it to quit by using something like:-
try
* ** ***
on error
display dialog "An
error number -128
end try
which effectively converts all errors into error number -128
, the user cancelled error. The following is similar, but doesn’t produce a message:-
try
* ** ***
on error errMsg number errNum
if errNum is not -128
error number -128
end try
The nesting of error statements can be useful, as in this example:-
try
* ** *** -- portion of
try
* ** *** -- portion of
on error
error number -128
end try
* ** *** -- portion of
on error errMsg number errNum
display dialog errMsg
end try
However, there’s a problem: the outer error handling produces a ‘user cancelled’ message whenever an inner error occurs. This can be prevented by modifying the last section to something like:-
on error errMsg number errNum
if errNum is not -128 then
end try
In some instances you may want to generate your own error numbers, as in:-
try
* ** *** -- portion of
try
* ** *** -- portion of
on error
error number 560
end try
* ** *** -- portion of
on error errMsg number errNum
display dialog errMsg
end try
or as in:-
try
if theValue = 15
on error number errNum
display dialog
end try
Generally speaking, you can use any value from 500
to 10000
as an error number.
Traditional programming, such as BASIC, uses variables to store numbers and text within a program. AppleScript, in common with other OOP languages, extends this to refer to objects, such as files, disks and computer ports. In AppleScript terminology an object is known as a value, although the author prefers the familiar ‘object’ term.
AppleScript supports 14 types or classes of object, each known as an object type or value class, as listed below:-
Class | Examples |
---|---|
boolean | true, false |
class | string, integer |
constant | Sunday, August |
data | «data ics8…» |
date | date "Sunday, |
integer | 32, 1024 |
list | {"dog", "cat", |
number | 32, 1024, 4, 16.6666 |
real | 32.0, 1024.0, 4.0, |
record | {height:96, width:64} |
reference | file of «script» |
string | "Plain text" |
styled text | "Text with style" |
text | "Plain or styled text" |
Although most applications handle all classes, some prefer to use their own varieties. For example, ClarisWorks requires you to use the plain text
class instead of the string
class in scripts.
Some values can be coerced into other classes. For example:-
gives a result in the form of "Tuesday, February 10, 1998
.
The name of an object mustn’t correspond to any keyword used in AppleScript, or to those used in a scripting addition or application. Most are easily avoided, although some are tricky to spot.
Object names names with capitals inside, such as theDiskSizeInKB
, are often used, although some scripting additions also use these kinds of words. Names such as the_disk_size_in_KB
are usually suitable, although they aren’t easy to read.
Values are usually defined using set
or copy
, as in:-
set theText to ""
set currentFiles to {}
set n to n + 1
copy "this" to theText
copy 3 as text to numText
copy (current date) as
The set
instruction can also be used to ‘initialise’ a value at the start of a script.
A full understanding of the difference between set
and copy
instructions can avoid unnecessary complications. For example, in the following script:-
set listOne to {1,2,3}
set listTwo to listOne
set listOne to {4,5,6}
both listOne
and listTwo
end up containing {4,5,6}
, since the second line has made both values equal. If you don’t want this to happen you should use copy
instead, as shown below:-
set listOne to {1,2,3}
copy listOne to listTwo
set listOne to {4,5,6}
In this case listOne
contains {4,5,6}
and listTwo
contains {1,2,3}
.
The various methods of manipulating values are too numerous to describe in this guide. However a few examples are given below. The following script gets the second word of this text:-
this script obtains the length of a list:-
and this selects the third item in a list:-
Sometimes, it’s necessary to specify the size and position of a window or some other kind of rectangle. The size alone can be given by means of a two-item list such as {200, 100}
, which specifies a rectangle of 200 × 100
pixels. Note that the width of the rectangle along the horizontal axis (the x
value) is always given before the height along its vertical (the y
value).
Defining both the size and position of a rectangle is slightly more difficult, requiring you to use a set of four co-ordinates. Generally speaking, these are measured from a zero point, located at the bottom left-hand corner of the screen or area under consideration. To add to the confusion, the size of a dialogue on a computer screen is normally measured from the top left-hand corner of the screen.
Co-ordinates are often given as a list in the form of {left, top, right, bottom}
, which can be written as {x1, y1, x2, y2}
, although the ordering of the latter isn’t entirely logical when working with co-ordinates that refer to the bottom left-hand corner. Here’s an example:-
which can be specified using co-ordinates of {6, 17, 28, 7}
.
The initial contents of a value can be set using a property statement at the start of a script, such as:-
property fToWatch: " "
property oldFiles: {}
property destFolder: "NULL"
property testFlag: false
Note, however, that the contents of values defined in this way are ‘remembered’ each time the script is used. For example, if you run a script and testFlag
ends up as true this value will again be used when you next run the script. Similarly, the following script tells you how many times it has run:-
property numTimesRun : 0
set numTimesRun to
display dialog "This script has
The common instructions used in AppleScript can be divided into the following groups:-
These let you make decisions in a script, often involving if
, else
and end if
commands, as in:-
if theWord = "dog" then
set n to 2
else
set n to 3
end if
although simple one-line statements can also be used, such as:-
These determine the flow of a script, depending on a result. They often involve the use of tell
, if
, repeat
or try
statements, as well as matching end
statements.
Examples of such statement have already appeared in this document. Here’s another one:-
repeat
-- your script goes here
set n to n + 1
end repeat
This kind of repeat
statement is rather dubious, since there’s a distinct risk of getting stuck in an endless loop. This can be fixed by adding a conditional statement inside the loop, as in:-
repeat
-- your script goes here
set n to n + 1
if n = 64 then exit repeat
end repeat
although it’s far better to to include a conditional value in the top line, as shown in these examples:-
repeat until theValue = 5
repeat while theValue
repeat with theValue
Finally, there’s the most complex form of repeat
statement:-
repeat with loopVar from
-- your script goes here
end repeat
This portion of script performs the same action within different parts of any script, making it easy to create short and well-organised scripts. Each subroutine begins with on
followed by the routine’s name and ending with a matching end
statement. Here’s a routine that converts a list to text:-
on listToTxt(theList,
set delimLength to length
set theText to ""
repeat with theItem in theList
set theText to theText
end repeat
if text 1 thru delimLength
return theText
end listToTxt
where the parameter called theList
is the actual list and theDelim
is the delimiter used in the list. You can ‘call up’ such a routine from within the main part of your script using a line such as:-
set theText to
--> "Computer, Disk Drive,
The following mathematical functions are built into AppleScript:-
Operation | Symbol |
---|---|
Addition | + |
Subtraction | - |
Multiplication | * |
Division • | / |
Brackets can be used to improve the presentation of operations, although you should remember than items within an innermost parenthesis are always calculated first. This example uses a routine to find the impedance of an 10µH inductor with a DC resistance of 0.5 Ω at a frequency of 1000 Hz:-
impInduct(180 * (10 ^ -6),
--> 1.63
on impInduct(L, Rs, f)
set Zl to Rs
return
end impInduct
AppleScript provides little in the way of built-in support for modifying text, although you can create your own routines You can also manipulate text by changing the delimiters used for separating text items, as in this example, which extracts the name of a file from its path:-
set itemPath to
try
set oldDelims to
set text item delimiters
set itemName to last text
set text item delimiters
on error
set text item delimiters
end try
return itemName
--> "My File"
The try
statement around the main part of this script is essential. If you don’t include this and the script fails, AppleScript continues to use the new delimiter in all subsequent scripts. For this reason, it’s better to use something like this:-
pathFileNm("Macintosh HD:
--> "My File"
on pathFileNm(theFile)
set revFilePath to
return (reverse of characters
end pathFileNm
which, although much more complicated, is actually shorter.
Selecting large amount of text within a script can cause memory problems, as in this example:-
where the script has to process the actual text data. To avoid this, you can use:-
which instead works out the length of the text.
AppleScript often can’t perform operations on text over 32 KB, although this is usually possible if left to a scriptable application with sufficient memory. And there shouldn’t be any problem transferring data via the clipboard or other files.
Depending on scriptability, you can send each application a range of instructions. However, if the application name entered in a script doesn’t match the real name or the script can’t locate its file, AppleScript puts up a Where is the file? dialogue, allowing you to find the file manually. Having done this and re-compiled the script you shouldn’t need to do it again.
Any application, even if it isn’t scriptable, can be launched using a script of the form:-
In the case of scriptable applications you can also use a line of the form:-
or:-
tell application "AppleWorks"
run
end tell
Note that the tell
command forces any enclosed operations to be executed from within the application’s memory space, which can cause problems, especially in Mac OS 8.5. And, in all versions of the Classic Mac OS, you can’t normally use a general command, such as display dialog
, inside a tell
statement unless the command is understood by the application.
app
as a shortcut for the word application
.You can quit any application using a command in the form of:-
The launch
command is slightly different, since the application doesn’t show all of the usual start-up displays when it’s launched. The actual line of script is:-
The following variation is only suitable for scriptable applications, although it may cause the application to quit and relaunch if it’s already running:-
tell application "ClarisWorks"
launch
end tell
The following kind of script usually works, but only with a scriptable application:-
tell application "ClarisWorks"
launch
open alias "Macintosh HD:
end tell
At this stage, some people express confusion over the word alias
. However, in this context the term refers to an AppleScript alias, not a standard Mac OS alias. This kind of alias refers to a specific file and keeps track of it, even in the event of it being moved or receiving a new name.
If the above script succeeds, it launches the application and the file’s window appears. Note however, that the application may not come to the front, in which case you'll need to add an extra line containing activate
after the existing one containing launch
. Some applications can open a list of files, as in:-
tell application "ClarisWorks"
launch
open {"Macintosh HD:
end tell
Note that this particular application doesn’t need the word alias
to follow an open
instruction.
activate
instruction and can object to the use an activate
or launch
command.The Finder accepts similar commands to those used by applications. However, an open
command that’s sent to the Finder shouldn’t be confused with the standard AppleScript open
command. The latter opens files that are dropped onto a script in the form of a droplet.
The following example opens a file using Netscape, which is identified by a creator code of MOSS
:-
tell application "Finder"
open alias (choose file)
end tell
whilst this form of script opens a particular file using its default application :-
while this opens a list of files:-
tell application "Finder"
open {alias "****",
end tell
The Finder can perform numerous other tasks. For example, this line of script enters the name of a Mac OS computer’s startup disk into a value called sysDisk
:
whilst this script moves a file identified as theFile
to the path given in theFldr
:
The replacing
instruction indicates that an existing file of the same name must be replaced. A similar script can copy a file:-
The Finder can also create new files from scratch, as in the following:-
tell application "Finder"
make file at alias theFldr
end tell
This example produces a Stickies text file, which is identified by creator code of notz
and file type of TEXT
. The new file’s filename should be contained in the value fileName
.
Recent versions of the Classic Mac OS include a Standard Additions scripting addition, which lives in the Scripting Additions folder, inside the System Folder, replacing the older additions used in earlier versions of the system. Further additions can be added, as required.
The following information refers to the Standard Additions file:-
The most useful feature provided in Standard Additions is a dialogue box. By default, this contains up to 255 characters of text, a Cancel button and an OK button. For example, the line:-
provides the following dialogue:-
If you click the Cancel button the script invariably quits. The limitation of 255 characters can be a problem, with excessively long text becoming harmlessly truncated, as in this example:-
It’s also possible to define up to three individually named buttons, as in:-
which gives this dialogue:-
The default button
can be selected by name or number as in:-
display dialog "Please indicate
or:-
display dialog "Please indicate
both of which give:-
To make the script to continue even though Cancel has been selected you must add a space before and after Cancel
, as in:-
display dialog "Please indicate
the spaces before and after the word ensuring that it aligns centrally in the button.
You can also create a dialogue that accepts entries, such as:-
display dialog "Enter your
which appears as:-
The result produced by such a dialogue can be extracted using:-
set theTxt to text returned of
The entered string will be contained in the value theTxt
.
If you need to know both the string and the name of the button that was clicked you should use something like:-
set theDlg to (display dialog
set theTxt to text returned
set theBtn to button returned
which can be shortened to:-
set theDlg to (display dialog
tell theDlg to set {theTxt,
Similarly, if you want the result as an integer instead of text you could use:-
display dialog "Enter your
set retAge to text returned
In this case, AppleScript’s default value, known as result
, has been used in place of the theDlg
object in the previous example. Although, this is simpler it doesn’t indicate which button was clicked.
Dialogues can also be used to escape from a loop, as in this script:-
repeat
* ** **** -- any portion
display dialog "Do you want
if result is "No" then
end repeat
The appearance of text entries for a dialogue can often be improved by incorporating return
in the text, as in this example:-
display dialog "The current
which gives the dialogue shown below:-
The keyword tab
, although acceptable in text strings, only acts as a space character in dialogues. However, the use of icons in dialogues is highly recommended, as in this an example:-
display dialog "Do you really
which gives:-
You can replace caution
by note
for the ‘speaking man’ icon or by alert
for the ‘warning hand’ icon. Similarly, other icons can be addressed by number, as in this script:-
which appears as:-
The icons provided by Classic Mac OS 9.1 are shown below:-
These icons are stored as ICON
or cicn
resources in modern versions of the System file. You can also call up icons from within an application from within a tell
statement. Applications usually have a standard icon identified by the number 128
.
As well as providing dialogues, Standard Additions can convert values to and from their ASCII equivalents or find offsets within a string. Here’s an example:-
The same addition can also be used to handle files and folders, as in this example that uses the choose file
and list folder
commands to open the files in a chosen folder:-
set theFldr to choose folder
set fldrList to list folder
tell application "Finder"
activate
set theFldr to theFldr
repeat with n from 1 to
try
open alias (theFldr &
end try
end repeat
end tell
There’s also a path to
command, which can give the location of the front application’s file or the script’s applet file, depending on where the current script is running from:-
set thePath to path to
--> "Macintosh HD:
--> "Macintosh HD:
As usual, the as text
instruction coerces the result into a string. In the next example path to
is used to locate the Temporary Items folder in the Classic Mac OS:-
Finally, the say
instruction lets you send instructions to the MacinTalk speech synthesiser, also allowing you to increase or reduce the emphasis of particular words, as in this example:-
©Ray White 2004.