Getting Started with Handlers (Part 3 of 3)

This month’s column serves as the last in a series of columns covering handler usage in AppleScript.

Part 1 of this series introduced handlers and discussed the benefits of writing and using subroutine handlers. It also looked at writing and calling subroutine handlers, as well as proper usage of handler parameters. You can read part 1 here.

Part 2 of this series discussed the scope of variables with regard to handlers, explained how to return values from handlers, and demonstrated how to call handlers from within application tell statements. You can read part 2 here.

So far, our handler discussions have been focused primarily around subroutine handlers, i.e. custom handlers that you write yourself and call throughout your script. In this month’s column, we will discuss another type of hander: command handlers.

What is a Command Handler?

A command handler is a handler that is predefined by an application, scripting addition, or by the operating system. Just like a subroutine handler, a command handler may be called manually within a script, causing it to execute. A command handler can also be called and executed by an event sent by an application or the operating system.

Script-Specific Command Handlers

An AppleScript itself actually has the ability to call certain command handlers when certain events take place. The manner by which a script is saved and executed affects which command handlers will be called.

Run Handler

By default, every AppleScript possesses an implied run handler, which contains any code at the top level of the script. For example:

display dialog "Hello!"

Optionally, the run handler of a script may be explicitly defined by manually wrapping all code at the top level of the script as follows:

on run
	display dialog "Hello!"
end run

Within a script, a run handler may be either implied or explicitly defined, but not both. Attempting to do so will result in a syntax error when compiling the script. For example:

display dialog "Hello!"

on run
	display dialog "Hello!"
end run
--> Syntax Error - The run handler is specified more than once, or there were top-level commands in addition to the run handler.

When a script that has been saved as an application is launched, a run command is sent to the script, and any code within the run handler is executed. Likewise, running a script from within the Script Editor, from the Script Menu, and so forth, will also cause a run command to be sent to the script. If you run the first examples above, you will find the result to be the same.

Open Handler

AppleScripts that are saved as applications also have the ability to execute some other command handlers in response to certain events. One such event is an open event.

When a user drags and drops files and folders onto an AppleScript application, an open command is sent to the script, along with a list of the items that were dropped. If the script contains only a run handler, then it will not respond to the event and nothing will happen. However, if the script contains an open handler, then that handler will be executed, and any items dropped onto the script will be passed to it via a parameter, to be processed.

The following is an example of an open handler, which, in this case, will simply loop through any dropped items, and display their paths in a dialog.

on open theDroppedItems
	repeat with aDroppedItem in theDroppedItems
		display dialog aDroppedItem as string
	end repeat
end open

The open handler requires a single direct parameter, whose value will be a list of any dropped items. In the example above, I have named this parameter theDroppedItems. You may use any name you desire for this parameter, as long as it adheres to variable naming standards.

When you save an AppleScript application containing an open handler, you will notice that the application�s icon changes slightly from a typical script application icon. Its icon will now include a small downward arrow, indicating that items may be dropped onto the script to be processed.

Idle Handler

When a script is saved as an application, you have the option to save it as a stay opened application. If you do this, then the script will have the ability to make use of an idle handler, which will trigger whenever the script becomes idle.

The following is an example of the proper use of an idle handler.

on idle
	display dialog "The script is now idle."
end idle

When launched, a stay opened script application will become idle after the code within its run handler has been executed. At that time, any code within the idle handler will be executed. From that point forward, the idle handler will continue to execute every 30 seconds, by default, until the script is quit.

Optionally, you may choose to change the frequency by which the idle handler is called. To do this, you may return from the idle handler the desired number of seconds you’d like the script to delay before the next idle period. For example, the following code would cause the idle handler to execute every 5 seconds.

on idle
	display dialog "The script is now idle."
	return 5
end idle

Quit Handler

AppleScripts that are saved as applications also have the ability to execute code within a quit handler when the script is quit, although the functionality of this command handler differs slightly depending on whether the script is saved as a stay opened application.

The following is an example of a quit handler, which would be executed when a script quits.

on quit
	display dialog "Goodbye!"
end quit

In a normal AppleScript application, the script would quit once this handler has finished executing. However, when implemented in a stay opened script application, the script would not quit. To allow it to quit, you must make use of a continue quit statement. For example:

on quit
	display dialog "Are you sure you want to quit." buttons {"Yes", "No"} default button "No"
	if button returned of result = "Yes" then continue quit
end quit

When using the code above in a stay opened script, once the script is quit, it would display a dialog asking if the user really wants to quit. If the user chooses Yes, then the continue quit statement would be executed and the script would quit. If the user chooses No, then the script would remain running.

Application-Specific Command Handlers

It is also possible for an application to execute a command handler within a script, if the application has been written to support such functionality. Applications of this nature are known to be attachable.

Some attachable applications support the ability to call a command handler when specific application-level events occur. One such application is Mail.

In Mail, a rule may be configured to analyze messages, and then run an AppleScript if certain criteria are met. To make use of this functionality at its basic level, it is only necessary to include code within the run handler of the attached script. In doing so, if the specified criteria are met, then any code within the script’s run handler will be executed.

However, the ability to run an AppleScript from a mail rule may be expanded to provide even greater functionality with the use of a command handler. The Mail suite in Mail’s AppleScript dictionary defines a command handler called perform mail action with messages. If included in a script attached to a mail rule, it will be triggered in lieu of the run handler.

This command handler has a direct parameter, which, when the handler is executed, will contain a list of any messages being processed by the rule. The following example demonstrates the proper usage of this handler. In this example, any messages processed by the rule, passed via the parameter theMessages, would be opened by the code within the handler.

using terms from application "Mail"
	on perform mail action with messages theMessages
		repeat with aMessage in theMessages
			open aMessage
		end repeat
	end perform mail action with messages
end using terms from

In the above example, notice that the command handler has been surrounded by a using terms from statement. This is necessary in order to indicate that the handler belongs to Mail’s AppleScript terminology, to prevent an error at compile time.

Some attachable applications also support the ability to trigger command handlers when users perform certain actions within the application, such as clicking a button, selecting a menu, and so forth. One such application is MultiAd Creator, which will allow AppleScripts to be attached to menus and more within the application’s interface. By doing this, you can actually modify the built-in behavior of the application, and take different courses of action when certain user events occur. For example, you might remap the Save menu so that whenever the user attempts to save a document, a backup of the original is made first. You can find an overview of MultiAd Creator’s AppleScript support here.

Address Book is another application that possesses the ability to trigger command handlers when certain user events occur. Address Book defines a number of command handlers that may be implemented to create plug-in scripts for Address Book. These command handlers can then be triggered when a user moves the mouse over a rollover button, selects a rollover button in a contact entry, and more.

In next month’s column, we will begin to discuss AppleScript Studio, a feature set of the Mac OS X developer tools, which will allow you to construct robust applications, complete with user interfaces that have the same look and feel of any other Mac OS X application. As we proceed, you will find yourself using command handlers quite often, in order to execute AppleScript code when your script is running and when a user interacts with your script’s interface.

Scripting Addition Command Handlers

Before we finish up our discussion of handlers, I want to mention that command handlers can also be defined by scripting additions. In fact, the Standard Additions scripting addition, which is built into Mac OS X, defines several command handlers.

One such handler is handle CGI request, which can be found within the Internet suite in the Standard Additions dictionary. This command handler can be used within a stay opened script application to process CGI (Common Gateway Interface) requests from a web server.

The Folder Actions suite in the Standard Additions scripting addition also defines some command handlers, which may be used to create folder action scripts, something that will probably be of greater use to more users than using the handle cgi request handler. Folder action scripts may be attached to folders in the Finder, to be called when certain actions are performed on those folders, such as when the folders are opened, when their windows are closed or moved, or when items are added to or removed from the folders.

Here is an example of a folder action handler that has been written to display the name of each item that is added into the folder.

on adding folder items to theAttachedFolder after receiving theNewItems
	repeat with aNewItem in theNewItems
		display dialog "New Item Detected: " & return & (name of (info for aNewItem))
	end repeat
end adding folder items to

To test this command handler, you will need to create a folder action script, and attach it to a folder. First create a new script containing the code above and save it as a script file to the /Library/Scripts/Folder Action Scripts/ folder on your machine. Next, make sure that folder actions are enabled on your machine by launching the Folder Actions Setup application, located in the /Applications/AppleScript folder, and then verifying that the Enable Folder Actions checkbox is selected. To attach the script to a folder, click the + button at the bottom left of the Folder Actions Setup window, and navigate to and select the desired folder. You will then be prompted to choose a script to attach to the folder. Select the script you just created and saved. Once you have attached your script to a folder in this manner, you can test the folder action by dropping items into the folder. If all goes well, then a dialog should be displayed for each item dropped into the folder, displaying the name of the item.

In Conclusion

We have been discussing handlers for quite some time now, and hopefully you are beginning to see why they are useful and sometimes necessary in different situations. As I have mentioned before, the reason that I chose to focus on handlers at this time is because my next column will begin a discussion with regard to AppleScript Studio. As we proceed with this discussion, you will find that AppleScript Studio involves heavy use of handlers, in particular, command handlers. Therefore, I felt that an introduction to handlers was a good place to start.

Until next time: just script it!

1 Like