Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, Swift, BASIC, and whatever else I happen to feel like hacking at.

AppleScript: The Definitive Guide

Jerry Stratton, August 13, 2005

On his web page, author Matt Neuburg writes that “this is the first really good book on AppleScript--the book I wish I’d had years ago.”

It is definitely better than the other O’Reilly AppleScript book I‘ve got. Despite being filled with text about something that looks like AppleScript, whenever I’ve tried to find an answer in AppleScript in a Nutshell I haven’t been able to find one. This Definitive Guide is much better, and much more useful.

My life with AppleScript

AppleScript was the first scripting language I ever used. Before AppleScript, my programming was with C, PL/I, or batch languages on various computer systems. Because AppleScript was my first taste of scripting, I used it for far too much. When it slowed down on some task, I’d pull out the Metrowerks compiler and write an osax in C.

The epitome of this was when I created a web log analysis script to analyze my nascent web site’s log files in 1995. Analyzing these small log files--the site ran over a 14.4 modem--took about twenty minutes at first, but as the hits increased, the analysis time grew to an hour, a couple of hours, up to about ten hours to complete the daily log analysis.

It was obviously about to reach the point where a day’s analysis was going to take longer than a day to complete. I was about to see which routines could be sped up with a C-written osax, when I realized this would be a good chance to look at this new scripting language called “perl” that a friend of mine had been using. I worked up a short perl script to compare speed, and could not get the thing to work. I’d start up the perl script, and it would immediately quit.

I was about to give up when I noticed that the log analysis web page was dated a few seconds past, and it had stuff in it; sure enough, I opened it in iCab and discovered that what took several hours in AppleScript went by so fast in perl that I thought it wasn’t even working.

Elegance is in the moment

This anecdote, while completely true, is unfair to modern AppleScript for several reasons. The two most obvious are that, first, AppleScript at that time was emulated 68k code on a PowerPC, whereas the perl I was using was native. Nowadays, AppleScript is a lot faster. Since moving to Mac OS X it has gone native. I haven’t even bothered to re-compile the FB Osax that I used to use in OS-9, because it hasn’t been needed.

Second, I was using AppleScript for something it wasn’t designed for, but that perl was designed for: chomping through lines of text.

As you can see from the previous two hacking articles, I’ve come back around to using AppleScript; this time I’m using it for what it was designed for, and for which it is an elegant solution: leveraging the applications I use daily to perform repetitive tasks that those applications are designed to perform.

AppleScript at its simplest can look very user-friendly. If you want to tell Firefox to get a web page, you can

  • tell application "Firefox" to Get URL "http://www.hoboes.com/Mimsy/"

If you want to tell GraphicConverter to trim an image, you can

  • tell application "GraphicConverter" to trim window 1

A well-written application will let you do, with AppleScript, just about anything you can do by hand. This makes it very easy to automate repetitive tasks. For example, if you often receive photographs that need to be rotated 90 degrees and autoleveled, you can make a script that will do this:

[toggle code]

  • on open theImages
    • repeat with theImage in theImages
      • tell application "GraphicConverter"
        • open theImage
        • tell window 1
          • autolevel
          • rotate to angle 90
          • close saving yes
        • end tell
      • end tell
    • end repeat
  • end open

Save this as an application in Script Editor, and any image that gets dropped on it will be rotated and have an autolevel performed on it, then saved.

Anyway, that’s AppleScript.

What about the book?

After a chapter in which the author “complains” about various aspects of AppleScript, points out that despite its English-like-syntax, it is still a programming language with a strict syntax, and then scares everybody by comparing it to scheme, he ends with:

In case you’re beginning to worry that AppleScript is hard, don’t; it isn’t! AppleScript is a straightforward computer language, and can be taught and learned in a straightforward manner; if I didn’t believe that, this book wouldn’t exist. AppleScript is extensible, so this book will tell you how to read a scriptable application’s dictionary, warn of possible pitfalls, and give plenty of examples. AppleScript is English-like, so the book will teach a clean, concise style, and will wave a red flag when an analogy with natural language threatens to mislead. AppleScript values are object-like; this book tells you how to talk to them.... If this book occasionally comments on the odd way AppleScript does certain things, it is not to frighten or frustrate the reader, but rather to gain the reader’s trust. It’s just my way of saying, “Don’t worry if this seems weird; it is weird.”

AppleScript can be very weird, especially to programmers used to scripting languages such as Perl, PHP, and Python, or to programming languages like C and RealBasic. It has a very specific purpose: getting information out of the applications we normally use, about the documents we’ve created. You might ask a document in a word processor, for example, to “get every paragraph where it contains "James"”.

Its “English-likeness” makes AppleScript a very versatile tool for talking to a wide variety of applications about a wide variety of documents. But it does also make for some odd syntax, such as the above “where it”.

However, I disagree with much of his complaints regarding the “English-like monster” that is AppleScript terminology. The problem isn’t that AppleScript is English-like, but that some developers (including, sometimes, Apple) disregard this. Matt’s favorite example appears to be the “has scripting terminology” property. You end up having to refer to this as “if application file n is has scripting terminology then”. But (as Matt points out) that property should never have been named a verb. AppleScript is very clear that properties are things. If that property were the much simpler “scriptable”, we would be able to refer to it as “if application n is scriptable”, something much more readable and self-commenting.

He also has a very strange recommendation towards the end of the otherwise very useful “AppleScript Experience” chapter. He goes through the creation of a new script from problem to solution, step-by-step. At the end, he summarizes what he’s learned from that experience. One of his “lessons” is: “Don’t try to understand AppleScript’s mysterious error messages: The important thing isn’t what went wrong but where it went wrong.” He then recommends, if you think that the error you don’t understand is unimportant, surround it with an “ignore error” (try) block. That’s such wrong-headed advice I can’t believe I really understand what he means.

It is true that some of AppleScript’s error messages can be “mysterious”. This is mostly because of the English-like nature of AppleScript combined with an attempt by the error message writers to write an easily-understandable, English-like error message. It can sometimes be difficult to parse the oddly non-grammatical sentences that produces.

And the error that he provides as an example is not particularly difficult to parse. He has a block of script that tells FrameMaker to get the file of an inset image in a frame:

[toggle code]

  • set allFrames to get every anchored frame
  • repeat with oneFrame in allFrames
    • set end of allPaths to inset file of inset 1 of oneFrame
  • end repeat

The line “set end of...” produced this error:

FrameMaker 7.0 got an error: Can't get inset file of inset 1 of anchored frame 1 of document "extra:applescriptBook:ch02places.fm".

“inset file of inset 1” is part of his script. This means that “anchored frame 1 of document "extra:applescriptBook:ch02places.fm"” must be the value of oneFrame. That means that the variable oneFrame contains what it should contain. The error message indicates that “anchored frame 1” doesn’t have either an inset or its inset doesn’t have an inset file.

And that’s the conclusion he comes to at the end of the paragraph where he goes over not understanding that error message: that not all frames in FrameMaker have inset files. I don’t even know FrameMaker and the error message was reasonably understandable.

When you receive an error like that while telling an application to do or get something, it helps to look at the error message from the point of view of the application.

Regardless, it is very important not to skip over such errors until you understand them. In any programming language, leaving in errors that you don’t understand is a guaranteed recipe for lost documents, over-written files, and any number of other evils. The error message is there for a reason; ignore an incomprehensible one at your peril.

Basic concepts and reference

While an important quibble, the above is still a minor quibble to an otherwise very useful reference. After diving into the waters of AppleScript with the AppleScript Experience chapter, the author gets down to the basic concepts of AppleScript: Apple events. The section on Apple events is interesting for programmers; while the Experience chapter could be interesting to beginners, I doubt many beginners are going to want to see the inside of an Apple event, or care that they can write “apple scripts” using Javascript--but programmers might.

From this point on, the book is a reference, as expected for a “definitive guide”. As for many definitive guides, I find it interesting to browse but my eyes start to glaze over as soon as I start reading the whole thing through. The true test, for me, of the usefulness of a definitive guide is, how often are my questions answered when I look them up in the guide? The earlier Nutshell book pretty much had a 100% miss rate. The Definitive Guide has been much more useful. I used it several times while working on the iTunes Alarm script, for example, and each time came up with an answer.

The explicit focus of this book is on AppleScript, and how to use it, not on scriptable applications and how to use them. In the course of talking about the former, however, it also covers quite a bit of general ground on the latter. Because of this focus, it goes into more detail on things such as variables and handlers than other books do. This is the first book that really convinced me to stop using function-style handlers and start using prepositional and named parameters.

In various sections, he summarizes the various prepositions, repeat blocks, variable types, string considerations, and data types. The section on references is the best one I’ve seen, explaining in detail how references work and why using them can make applications do things. Finally, he ends with a primer on scripting unscriptable applications, using the Accessibility API, a chapter on using command-line utilities via “do shell script”, and a tutorial on using AppleScript Studio.

If you use AppleScript extensively and wish you had a better reference, I strongly recommend looking at AppleScript: The Definitive Guide. If you are an experienced scripter who doesn’t use AppleScript but think it would be useful, I recommend fooling around with some of the free tutorials on the web, and then getting this book. Otherwise, this is a fairly technical reference written from a technical point of view. Beginners will probably find that it obscures simple topics with--for them--unnecessarily deep explanations. As a reference work for those who already work with AppleScript, however, this is the best book I’ve seen, and a useful one.

  1. <- iTunes Alarm
  2. One-fisted tabs ->