Scripting BasicsThe 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:-
set theDlg to display dialog ¬
"Do you really want to empty the Trash?" buttons {"No", "Yes"} ¬
default button "Yes" with icon note -- instruction to scripting addition
if button returned of theDlg = "Yes" then
with timeout of 1 second -- if there’s a problem script gives up after 1 second
tell application "Finder" -- instruction to the Finder
empty -- empties the Trash
end tell -- three lines equivalent to ‘tell application "Finder" to empty’
end timeout
end if
-- A demonstration script for this AppleScript guide
(* Here’s a block of text used as a comment. During debugging you can enclose
unwanted portions of script in the same manner. *)
The above example includes the following features found in most scripts:-
display dialogif, end if, with timeout and end timeout statementstell and end tell statements¬ character to extend instructions over more than one lineA 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
* ** *** -- replace this by the lines of your script
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 as list
repeat with theItem in itemList
* ** *** -- replace by scripting for processing each item
end repeat
end open
on run
* ** *** -- replace this by the lines of your script
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 as list
repeat with theItem in itemList
* ** *** -- script for processing each item
tell application "Finder" to display dialog (name of theItem)
end repeat
end open
on run
try
tell application "Finder"
activate -- brings Finder to the front
set theItems to selection -- gets list of selected items
if count of theItems = 0 then -- no desktop items are selected
repeat
set theItems to choose file with prompt "Choose a file:"
tell me to open (theItems) -- makes script open chosen item
end repeat
else
tell me to open (theItems) -- makes script open selected desktop items
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:-
try
* ** *** -- script that can cause errors
on error errMsg number errNum
display dialog errMsg & return & "Error Number: " & errNum¬
buttons "OK" default button "OK" with icon caution
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
* ** *** -- script that can cause errors
on error errMsg
display dialog errMsg buttons "OK" default button "OK" with icon caution
end try
as shown here:-

whilst this version shows a generic message for all errors:-
try
* ** *** -- script that can cause errors
on error
display dialog "An unexpected error prevented this operation." ¬
buttons "OK" default button "OK" with icon caution
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 * ** *** -- script that can cause errors
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
* ** *** -- script that can cause errors
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
* ** *** -- script that can cause errors
on error
display dialog "An unexpected error prevented this operation." ¬
buttons "OK" default button "OK" with icon caution
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
* ** *** -- script that can cause errors
on error errMsg number errNum
if errNum is not -128 then ** *** -- optional instruction
error number -128
end try
The nesting of error statements can be useful, as in this example:-
try
* ** *** -- portion of script under ‘outer’ error handling
try
* ** *** -- portion of script under ‘inner’ error handling
on error
error number -128
end try
* ** *** -- portion of script under ‘outer’ error handling
on error errMsg number errNum
display dialog errMsg & return & "Error Number: " & errNum ¬
buttons "OK" default button "OK" with icon caution
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 ¬
display dialog errMsg & return & "Error Number: " & errNum ¬
buttons "OK" default button "OK" with icon caution
end try
In some instances you may want to generate your own error numbers, as in:-
try
* ** *** -- portion of script under ‘outer’ error handling
try
* ** *** -- portion of script under ‘inner’ error handling
on error
error number 560
end try
* ** *** -- portion of script under ‘outer’ error handling
on error errMsg number errNum
display dialog errMsg & return & "Error Number: " & errNum ¬
buttons "OK" default button "OK" with icon caution
end try
or as in:-
try
if theValue = 15 then error number 1437
on error number errNum
display dialog "Error Number: " & errNum ¬
buttons "OK" default button "OK" with icon caution
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, March 14, 1999 12:30:52 pm" |
| integer | 32, 1024 |
| list | {"dog", "cat", "mouse"} |
| number | 32, 1024, 4, 16.6666 |
| real | 32.0, 1024.0, 4.0, 16.6666 |
| 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 4:51:49 pm".
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 text to dateNowTxt
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 numTimesRun + 1
display dialog "This script has been used " & numTimesRun & " times."¬
buttons "OK" default button 1 with icon note
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 is less than 5
repeat with theValue in valueList
Finally, there’s the most complex form of repeat statement:-
repeat with loopVar from lowBound to highBound by stepValue
** *** * -- 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, theDelim)
set delimLength to length of theDelim
set theText to ""
repeat with theItem in theList
set theText to theText & theDelim & theItem
end repeat
if text 1 thru delimLength of theText is theDelim then¬
set theText to text (delimLength + 1) thru -1 of theText
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 listToTxt({"Computer", "Disk Drive", "Modem", "Printer"}, ", ")
--> "Computer, Disk Drive, Modem, Printer"
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), 0.5, 1000)
--> 1.63
on impInduct(L, Rs, f) -- values in henrys, ohms and hertz. Rs is the DC resistance
set Zl to Rs + (2 * pi * f * L)
return (round (100 * Zl) ) / 100
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 "Macintosh HD:Documents:My File"
try
set oldDelims to text item delimiters
set text item delimiters to {":"}
set itemName to last text item of itemPath
set text item delimiters to oldDelims
on error
set text item delimiters to oldDelims
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:Documents:My File")
--> "My File"
on pathFileNm(theFile)
set revFilePath to (reverse of characters 1 thru -1 of theFile) as text
return (reverse of characters 1 thru ( (offset of ":" in revFilePath) - 1)¬
of revFilePath) as text
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:Documents:MyTextFile"
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:Documents:MyTextFile", "Macintosh HD:TopFile"}
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) using application file id "MOSS"
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 "****", alias "*****"} -- replace asterisks by file paths
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 with properties ¬
{name:fileName, creator type:"notz", file type:"TEXT"}
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 your gender."¬
buttons {"Male", "Female", "Cancel"} default button "Cancel"
or:-
display dialog "Please indicate your gender."¬
buttons {"Male", "Female", "Cancel"} default button 3
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 your gender."¬
buttons {"Male", "Female", " Cancel "} default button 3
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 retirement age."¬
buttons {"Cancel", "OK"} default answer "60" default button "OK"
which appears as:-

The result produced by such a dialogue can be extracted using:-
set theTxt to text returned of (display dialog "Enter your retirement age."¬
buttons {"Cancel", "OK"} default answer "60" default button "OK")
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 "Enter your retirement age."¬
buttons {"Cancel", "OK"} default answer "60" default button "OK")
set theTxt to text returned of theDlg
set theBtn to button returned of theDlg
which can be shortened to:-
set theDlg to (display dialog "Enter your retirement age."¬
buttons {"Cancel", "OK"} default answer "60" default button "OK")
tell theDlg to set {theTxt, theBtn} to {text returned, button returned}
Similarly, if you want the result as an integer instead of text you could use:-
display dialog "Enter your retirement age."¬
buttons {"Cancel", "OK"} default answer "60" default button "OK"
set retAge to text returned of result as integer
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 of script
display dialog "Do you want to continue?"
if result is "No" then exit repeat
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 date is:" & return & (current date) as string¬
buttons "OK" default button 1
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 want to erase the disk named " & ¬
"“My Whole Life’s Work”?" with icon caution
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 with prompt "Choose a folder to search:" -- Standard Additions instruction
set fldrList to list folder theFldr -- Standard Additions instruction
tell application "Finder"
activate
set theFldr to theFldr as text
repeat with n from 1 to length of fldrList
try
open alias (theFldr & item n of fldrList)
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 me as text
--> "Macintosh HD:Applications (Mac OS 9):Apple Extras:AppleScript:Script Editor"
--> "Macintosh HD:Desktop Folder:Test Script"
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.