Using Tiger: Learning AppleScript
This article is excerpted from The Mac OS X Tiger Book from Wiley Publishing (0-7645-7956-6); the book can be ordered from Amazon.com and Barnes & Noble. Copyright ©2005 by Wiley Publishing, Inc. This material is used by permission of John Wiley & Sons, Inc.
The good news about AppleScript is that lots and lots of apps support it ambitiously, and support dozens and dozens of unique AppleScript commands. The bad news becomes apparent when you multiply “lots and lots” by “dozens and dozens.” You wind up with thousands of individual commands, and the sneaking suspicion that you have to know all of them to get anything done with AppleScript.
As I pointed out earlier, the strength or the weakness of an app’s scripting support is up to the developer. Any functions or capabilities that are specific to the app have to be provided by the app. And they also have to provide AppleScript programmers with documentation explaining what these app-specific functions and data types are.
The word documentation has to be used loosely. The developers write up a list of data types the app can recognize and deal with and a list of functions the app can perform, and make this list available to you, eager young space cadet, within the application itself in the form of the app’s built-in Scripting Dictionary. Script Editor can open up these dictionaries and display them in a clearly-organized and easily-searchable fashion.
You can open an app’s dictionary by selecting Open Dictionary from Script Editor’s File menu, and then selecting the app from the resulting list. The screenshot below shows you iTunes’ scripting dictionary.
But who has time to scroll through a list of hundreds of apps, when you’re all hot ’n bothered to start scripting? Script Editor gives you a handy organizational tool in the form of the Library window. You can open it from Script Editor’s Window menu. Behold, the screenshot to the lower right.
The Script Editor’s Library, keeping your favorite scriptable apps handy
It’s sort of like a “Favorites” list for scriptable apps. Note that Apple has pre-loaded the Library window with Tiger’s most popular scriptable apps. You can add your own just by clicking the “plus” button (+) in the window’s toolbar. The Minus sign blasts the item to Hades. Clicking the button that looks like a bunch of books opens a selected app’s scripting dictionary, and the AppleScript icon creates a brand-new script file, all set up to send AppleScript to that app.
Each dictionary contains commands and objects . Commands actually do things. In iTunes, “play” starts or resumes playback, for example. Objects are, well, objects. They’re the things that commands work with. In iTunes’ scripting dictionary, you’ve got tracks, playlists, music sources… and they’re all objects.
You also want to click these objects and see what their properties are. Yes, I’m listening to a track. Very nice, thank you. But what Album is it off of? Who’s the Artist performing it? When was it last played? Each of these is an individual property of the Track object. I can ask iTunes for “the artist of the first track” and get an immediate answer (“They Might Be Giants,” say).
You’ll dive into the scripting dictionary when you need to have a sense of the app’s capabilities. You can either scroll through the dictionary yourself or click in the Dictionary viewer’s Spotlight search box and search for the object of your affection. I want to write an iTunes script that processes my music library on an album-by-album basis. Does its dictionary have an Album object? I type “Album” into the search field… nope, the only thing Spotlight finds for me is that “Album” is a property of “Track.” That is, if I have a Track in my hands, iTunes can tell me what Album it’s from. But I can’t ask it to tell me the name of the first album in a playlist, for instance.
Okay, earlier on, I complained that Script Editor isn’t all that helpful when you’re writing and debugging scripts. It still falls short, when compared to third-party script editors like Script Debugger, from Late Night Software. Still, in addition to the Event and Result Logs that I mentioned earlier, Script Editor does offer some genuine niceties:
Unseen hands speak from beyond the grave and tell you what you probably want to type next
Just use the arrow keys on your keyboard to select the item you want and hit Return to continue editing. It’s a fantastically useful feature. For one, I’m always forgetting that I named something theArtist and not theNameOfTheArtist, for instance, or whether “previous track” is supposed to be one word or two. Script Assistant is another thing that helps me think less. Which isn’t that great a result, come to think of it, but it sure helps with the scripting, I’ll tell you that much. You can activate the Script Assistant through the Script Editor’s Preferences window.
Navigate down to Dialogs, select the kind of dialog you want to use, and presto… the code you need is automatically pasted into your AppleScript-in-progress.
A contextual menu filled with pre-fabbed AppleScript code snippets
Learning AppleScript: Resources
Time and space prevent me from including a full primer on the AppleScript language. (And when I say time and space, I, of course, mean money. This is simple Einsteinian physics, people. Einstein said that time and space were merely vibrational manifestations of matter, and to me, nothing matters more than money. Slip me another three bucks and I’ll be all over this whole Primer thing but otherwise, nothin’ doing). So instead, I’ll steer you toward other resources. The best way to learn AppleScript is to examine a script that (a) already exists, and (b) works. Over time, you’ll wind up working your way through all of the sample scripts Apple left for you in the Scripts menu. Scroll around until you see a script that seems to do something interesting, open the Script file in Script Editor, and play with the code.
No kidding. I’ve written plenty of AppleScripts that use Mail to create and send an e-mail, but the central nugget of that code is always the lines I found in one of Apple’s samples from the Scripts menu. Remember, kids, it’s only thievery if you feel guilty about it later on.
Joking, joking. Apple’s scripts say explicitly that you’re free to recycle these samples as you see fit. Plus, this is exactly what AppleScript’s framers originally intended—learning by example.
You’ll absolutely want to go back to wherever you tossed your Tiger install disc and open the Developer Tools folder to rummage through the information resources to be found therein. I can confirm for you that this disc contains hardcore supergeek resources and references so potent that even now, just reading about them causes calcium deposits to form around my neurons simply as a defensive measure against my getting over-excited. But on this disc lurks a complete set of AppleScript documentation and reference materials that helps explain the basics of writing AppleScript from the basics all the way through the intermediaries.
Some other places to go:
The AppleScript-Users mailing list: This is a public mailing list that’s chock-full of seasoned scripting experts, newbies who’ve yet to write their first tell block, and everyone in between, all asking questions and swapping techniques. AppleScript is full of landmines that require either the sort of lateral thinking that leads to either madness, greatness, or the annual redesign of the federal tax code and only someone Who’s Been There can explain how AppleScript works… and more importantly, why it sometimes doesn’t.
Apple’s Scriptable Applications page: Partly as a user resource and partly to sell people on the power of AppleScript, Apple maintains a Web page lifting all of the built-in Panther apps and iLife apps that support AppleScript, and embroiders each item with some sample scripts complete with explanations. When you want to start learning how to script Safari, this is your starting point.
MacScripter.net: Hands-down the best AppleScript information and education resource outside of Apple. What the hey. Throw Apple in there, too. At this writing, MacScripter contains more than 1,300 sample scripts in every conceivable category for your benefit and edification. It attempts the impossible task of documenting every major Mac app’s level of scriptability. There’s a busy, busy, busy message board where newbie questions are always welcome; MacScripter has succeeded in building a real community.
Doug’s AppleScripts for iTunes: This site does one thing, but it does it with remorseless thoroughness: It’s all about scripting iLife’s music player. It’s actually a fine place to focus your scripting skills as they flower. The downloadable scripts range from simple five-liners to ones whose scale and ambitions demand the use of the term Heroic.
Still and all, I’ll show you a very simple script to start you off. And, because you were one of the first 500 callers to take advantage of this incredible offer, I’ll annotate some of the high points afterward.
For a free word processor, TextEdit is actually pretty slick. On top of all of its built-in features, it’s Microsoft Word-compatible, so it’s actually possible to use it as a serious productivity app. But I can’t use any word processor that doesn’t have a word-count feature. Adding one is easy as pie. Just create a new Script file containing the following code, and save it inside your Scripts folder:
tell application "TextEdit"
set theText to the text of document 1
set theLength to the number of words in theText
display dialog "There are " & theLength & " words in the text."
Running this script returns the number of words in the frontmost TextEdit document. It also gives me three opportunities for blathering on:
In this script, the only thing we need TextEdit for is to get the text of the document (document 1… aka, the document whose window is in front of every other TextEdit window). So that’s the only line you put inside the tell block. That’s not always completely necessary. The rest of the script is part of the core AppleScript language and should work anywhere. But it’s sloppy to put more inside a tell block than you absolutely must. It’s more than sloppy… it can often have unpredictable results. For example, I could have put this line inside the tell block:
set theLength to the number of words in theText of document 1
…and I wouldn’t have needed the line of script that comes after it. It would have run just fine, but it returns an incorrect result. When AppleScript counts the number of words outside of the tell block, everything is both hunky and dory.
theText, in this case) with data. When AppleScript encounters this statement, it evaluates everything that comes after to (be it a mathematical calculation, an operation to retrieve information [like we’re doing here], or the result of another operation). I don’t have to bother declaring theText ahead of time, or telling AppleScript that it’s supposed to contain text. AppleScript figures out that stuff dynamically.
display dialoggenerates its own results, too. If I made the line
set someContainerName to display dialog (etc.),
someContainerNamewould hold the name of the button that the user clicked.
And we’re saving ourselves a step by building the dialog’s text on the fly. The ampersands are your signal to AppleScript that you’d like all those items schmooshed together into one string of text.
[ Andy Ihnatko is one of the best-known Macintosh gurus. He has been writing about the Macintosh since 1988. He has been the monthly back-page opinion columnist for Macworld , and is currently also a columnist for The Chicago Sun-Times . He has also contributed frequently to Playboy , CNN.com , and too many online publications to adequately count. ]