Scriptable Applications

A scriptable application is one that goes beyond the basics of responding to Apple events sent by the Mac OS to make its most important data and operations available to AppleScript scripts or to other applications. To do this, the application must provide both a terminology for scripters to use and the underlying Apple event code to support it. Both Carbon and Cocoa applications can be scriptable, and the Cocoa framework contains built-in support that minimizes the amount of code you have to write.

Specifying Scripting Terminology

Scriptable applications describe the scripting terminology they support by supplying a scripting dictionary. A dictionary specifies the commands and objects an application supports, as well as other information that is used by AppleScript or the application itself, and possibly by other applications or scripts that want to take advantage of the application’s scriptability. For information on designing a scripting terminology, see Technical Note TN2106, Scripting Interface Guidelines.

Users typically examine a dictionary for information on how to control an application in their scripts. You can display the dictionary for a scriptable application or scripting addition with Script Editor, as described in “Displaying Scripting Dictionaries.”

There are currently three dictionary formats:

Determining What to Make Scriptable

In designing a scriptable application, it’s a good idea to provide access to all of the application’s main features, though it may make sense to start with just a key subset. You don’t typically make your application’s user interface directly scriptable. A good design allows users to script your application’s model objects (which represent data and basic behaviors) rather than its user interface (which presents information to the user).

For example, the scripting support for a drawing application might allow a script to rotate an image, but not to perform the user interface operation of clicking a Rotate button. Some applications provide additional capabilities through their scripting interface that aren’t otherwise available.

For design information, see “Learning How to Make an Application Scriptable” in Getting Started with AppleScript and Technical Note TN2106, Scripting Interface Guidelines.

For information on how to support printing in a scriptable application, see The Enhanced Print Apple Event.

Registering to Receive Apple Events

A scriptable application typically responds to a set of common commands, such as get data, set data, delete, and save, as well as to other commands that support operations specific to the application. Commands are represented in Apple events by constants defined in framework or application headers. To support a command, an application registers an event handler routine with the Apple Event Manager to handle Apple events it receives that specify that command. The Apple Event Manager dispatches received events to the handlers registered for them.

For more information on creating and registering event handlers, see “Apple Event Dispatching” and “Responding to Apple Events” in Apple Events Programming Guide.

Resolving Objects in the Application

Apple events often specify items in the application. For example, a get data event might ask for the text of a paragraph in an open document. A distinct item in an application that can be specified in an Apple event is known as an Apple event object. (The term object does not imply that the items must be represented internally as objects in an object-oriented programming language.) All such objects are considered to be contained in other objects, with the application itself serving as the ultimate container. For a given application, the AppleScript object model (also called the Apple event object model) specifies the classes of objects a scripter can work with in scripts, the accessible properties of those objects, and the inheritance and containment relationships for those objects.

The structures within an Apple event that identify objects are referred to as object specifiers. Finding the Apple event objects they specify is known as resolving the object specifiers. To resolve object specifiers, an application must include functions that are able to find objects within their containers. The application registers these functions with the Apple Event Manager, and works with the Apple Event Manager to call them at the appropriate time to obtain the objects they specify.

For Cocoa applications, Cocoa scripting support does much of the work of resolving object specifiers, but a scriptable application must still supply methods that can locate an object within its object model containment hierarchy.

For an example of an AppleScript object model, see “Overview of Cocoa Support for Scriptable Applications”; for information on how Cocoa applications resolve objects, see “Object Specifiers”; both are in Cocoa Scripting Guide.

Recording

A recordable application is one that sends Apple events to itself when a user performs actions with the application. If the user has turned on recording in the Script Editor application (with Script > Record), actions that generate Apple events are recorded into an AppleScript script.

Applications that support recording typically:

The Finder application in OS X is recordable. Starting in OS X version 10.5, the “Automator” application has a separate Record mechanism that lets users record actions into an Automator workflow.

Creating and Sending Apple Events

An application can create and send Apple events directly. This is usually done either to send internal Apple events, as described in “Recording,” to obtain services from a scriptable application, or to communicate directly with another application. The Open Scripting Architecture provides various mechanisms for creating and sending Apple events.

Starting in OS X version 10.5, applications can use “Scripting Bridge” to obtain services from scriptable applications. Scripting Bridge lets you work efficiently in a high-level language (Objective-C) without having to handle the details of sending and receiving Apple events. (See also “Support for Cocoa Applications” for related information.)

When you really do need to send an Apple event directly, see “Building an Apple Event” and “Creating and Sending Apple Events” in Apple Events Programming Guide.

Executing Scripts

To execute scripts, an application establishes a connection with the AppleScript scripting component. It can then:

An application can store and execute scripts regardless of whether it is scriptable or recordable. If an application is scriptable, however, it can execute scripts that control its own behavior, thus acting as both the client application and the server application for the corresponding Apple events. For more information, see Open Scripting Architecture Reference.

In Cocoa, the NSAppleScript class, described in NSAppleScript Class Reference, provides a high-level wrapper for executing AppleScript scripts from applications. For more information, see “Support for Cocoa Applications.”

Summary of Operations in a Scriptable Application

The following list summarizes how scriptable applications interact with the Open Scripting Architecture to make their features available to scripters.

OS X Support for Creating Scriptable Applications

OS X supplies a number of resources that applications can use to work with Apple events and to support scriptability, including the API provided in the following frameworks:

Support for Carbon Applications

Carbon applications have traditionally worked directly with the Apple Event Manager to create, send, receive, and interpret Apple events. These topics are described in detail in Apple Events Programming Guide.

For information on making your Carbon application scriptable, see previous sections in this chapter, as well as the learning paths in Getting Started with AppleScript.

Carbon applications can use functions such as OSACompile and OSAExecute from OpenScripting.framework to compile and execute scripts. Keep in mind, however, that if you are executing a script merely to send a simple command to another application, it is more efficient to create and send an Apple event directly.

If the purpose for executing a script is just to perform a do shell script command, Carbon applications can do so more efficiently using one of the BSD calls system(3), popen(3), or exec(3), which you can read about at their respective man pages.

Support for Cocoa Applications

The Foundation and Application Kit frameworks provide Cocoa applications with automated handling for certain Apple events. This includes events that may be sent by the Mac OS, such as the open application, open documents, print documents, and quit Apple events.

In addition, Cocoa provides substantial support for creating scriptable applications. To take advantage of it, applications provide scriptability information in one of the formats described in “Specifying Scripting Terminology.” They also create KVC-compliant accessors for scriptable properties in their scriptable classes. (Key-value coding, or KVC, is described in Key-Value Coding Programming Guide.) Though creating a fully scriptable application is a non-trivial task, an application can support many standard AppleScript commands, such as those for getting and setting properties of application objects, with a relatively small number of additional steps.

Cocoa applications can also use any of the Open Scripting Architecture APIs available to Carbon applications, and in fact, Cocoa links with the Carbon framework. For example, a Cocoa Application might call an Apple Event Manager function to send an Apple event directly (there currently is no Cocoa API to do that).

Starting in OS X version 10.5, the “Scripting Bridge” technology provides an efficient way for Cocoa applications to interact with scriptable applications at a high level—that is, without having to construct or parse individual Apple events.

Cocoa provides the NSAppleScript class for tasks such as compiling and executing scripts. This gives applications another mechanism to control scriptable applications and take advantage of services they provide. However, you should not use NSAppleScript to execute a script merely to result in sending an Apple event, because it is far more expensive than using Scripting Bridge or creating and sending an Apple event directly. And if the purpose for executing a script is to perform a do shell script command, Cocoa applications can execute shell commands more efficiently using NSTask.

The Cocoa framework also includes classes such as NSAppleEventDescriptor, for working with underlying Apple event data structures, and NSAppleEventManager, for accessing certain Apple Event Manager functions.

Cocoa support for handling Apple events and creating scriptable applications is documented in Cocoa Scripting Guide. For related information, see “Framework and Language Support” in “About Apple Events” in Apple Events Programming Guide. For introductory sample code, see SimpleScripting, SimpleScriptingProperties, SimpleScriptingObjects, and SimpleScriptingVerbs. For a more complex example, see the Sketch sample application.