Development software

Using Tiger: Learning AppleScript

Ihnatko Tiger book cover
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.

Automator truly is one of the most salivationary features of Tiger and proof positive that God loves us (if you believe in God) or we’re doing just fine without a Supreme Being around calling the shots, thank you very much (if you don’t believe in God).

Still, Automator has limitations. It’s marvelously well-suited for automating processes that are linear… ones that can be easily broken down into a list of predictable steps. The point where Automator falls down is when you throw it a problem that requires it to do some actual thinking . “If the file is smaller than 500K, I want you to e-mail it to my editor; if it’s larger, then upload it to my personal FTP server and send him an e-mail with instructions on how to download it.” You just can’t do that with Automator.

You also can’t do anything that requires the use of variables. Anyone who’s taken an introductory programming course knows what a variable is. Imagine that I’ve got an Automator workflow that’s 20 or 30 steps long. There are plenty of workflows in which it’d be helpful to say “OK: you remember 20 steps ago, way back in Step Three, when I told you to get a list of all of the pictures on the Astronomy Picture of the Day Web site? Here’s something else I want you to do with that same list:” But that’s way beyond Automator’s puny intellect. You can work around that limitation sometimes; in the preceding example, I could just tell Automator to go visit the Web site and build that list all over again.

But there are times when only a “real” programming language will do. And AppleScript is indeed a real language. It’s a really simple language, that’s really easy to learn and really tolerant of little mistakes. But it’s also one that has nearly every feature that a developer would wish for, short of the sort of tools you’d need to write a new challenger to Microsoft Office.

The bottom-line advice is to use Automator until you find yourself spending more time working around its limitations than taking advantage of its features. And that’s when you should start learning AppleScript.

Creating your own scripts

Nearly every app supports at least four basic AppleScript commands:

  • Run. Launches the app.
  • Open. Opens an item, typically a document file.
  • Print. Prints an item, again, typically a document.
  • Quit. Fold. Pack it in. Give up hope. Take your ball and go home. You know…Quit.
  • Anything above and beyond that is up to the ambition and commitment of the developer. It’s a crapshoot of delight and disappointment. It’s the good apps that keep you committed to AppleScript. Some apps are so script-happy that it almost seems like a waste to work with the user interface at all.

    Script Editor

    The Script Editor, with a simple script up on the lift so we can finally do something about those brake pads.

    Script Editor is the app you use to record scripts, edit existing ones, write brand-new scripts of your own, and crack open your applications to see just how scriptable they are. You find it inside your AppleScript folder, which awaits you inside Applications. The figure on the right shows you a typical script-editing window. This is Script Editor’s entire interface, or near enough. Apart from Saves, Opens, and Prints, you never touch the menu bar at all. Here, give it a shot:

  • Create a new script by pressing Command-N. Alternatively, you can click File: New.
  • Type the following code into the editing window:
    say "Greetings, Professor Falken."
    delay 1
    say "How about a nice game of chess?"
  • Click the Run button.
  • There you go; you’re now a programmer. I bet your skin’s half a shade paler already.

    If you were watching the window carefully when you clicked Run, you noticed that the Stop button enabled itself while your script was running. Clicking that sucker terminates the script in mid-run—a very useful feature when the script that you thought you told to automatically assemble a report on the status of the network actually winds up taking a folder full of boudoir photos that you posed for at the mall and e-mails them to everyone in your 1,100-person Address Book.

    As you start to work with longer and more complicated scripts, you’ll probably start making regular use of the Compile button. Essentially, it double-checks your spelling and grammar. If something you’ve typed doesn’t make sense as AppleScript, it flags it for you and does its best to explain what the problem is. If everything’s flawless, it reformats the script with fancy nested indents and type styles to make it more readable.

    Underneath the code section of the window exists a little pane of information. It can display three different things, depending on which of those three tabs underneath it has been clicked:

  • Description. It’s a good idea to describe your script and what it does. You’re going to start writing a lot of scripts (No, really, I’ve paid a large man $30 to come over to your house and beat the snot out of you if you don’t. So, I mean, time’s a-wasting), and without attaching notes to these things, it becomes really easy to forget why you bothered to write this particular script in the first place.
  • Result. That’s a debugging tool. When a script runs to the very end, the results of the last operation it performed are displayed in the Result tab.
  • Event Log. An even more sophisticated debugging resource. At the root of a gas engine is combustion. At the root of national-level politics are unresolved childhood inadequacy issues. And at the root of all Mac software are events. These are the molecules of what goes on behind the scenes—the actual activities that software has to carry out to make things happen. Script Editor can maintain an Event Log that keeps track of everything your script did during execution and what the immediate result was, step by step by step.
  • There’s a second set of resources for examining results and events: the Result Log and Event Log windows, which you can open from Script Editor’s Windows menu. They’re both frightfully useful; when a script fails to work the way you thought it did, they can act like the “black box” that gets pulled from the wreckage of a crashed airplane. They give you a detailed history of everything that your script did and what those intermediate results were, step by step along the way. By examining these logs, it’s easy to discover precisely which line of code caused One plus One to equal Twelve, and then make the necessary fixes.

    Ah, yes, we seem to have overlooked the Record button. Well, let’s just clear that out of the way so we can move on.

    Recording scripts

    Like I said earlier, recording scripts can be a hit-or-miss proposition. There’s no way to tell whether or not an app is recordable—or exactly how useful its recording features are—until you give it a whirl. Let’s toss in a ringer for our example: the Finder. It’s eminently recordable and, as an environment for mind-numbing, repetitious behavior, it gives secondary education a real run for its money. I often organize my windows in a specific way that lets me reorganize my hard drive’s clutter quickly. Regardez-vous the screenshot below.

    AppleScript and the Finder

    It’s a master column view of the whole hard drive up top, and three windows of subfolders arranged on the bottom. But it’s a pain to create and arrange these windows manually, so, on the next page, I’m going to record a script that does it for me.

    Ihnatko Tiger book cover
    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.

  • Create a new script file in Script Editor by pressing Command-N.
    Alternatively, you can click File: New.
  • Click the Record button.
    The Stop button activates.
  • Click over to the Finder.
    Create those four windows, click in them until they’re displaying the folders I want to examine, and change their views to the styles I want (one set to Columns and the rest set to Lists).
  • Click back into Script Editor when the windows are just the way I like them.
    Notice that the script window is now jam-freakin’-packed with script.
  • Click the Stop button.
    The final result is what you see below.
  • AppleScript recording

    Woo-hoo! Just imagine having to type all that in yourself! Recording scripts rules!!!

    Not so fast, Skeezix. Why don’t you try something even simpler, like recording all the steps of using the Finder to connect to an FTP server? Go ahead. I’ll wait here.

    Uh-huh. You wound up with something like the screenshot below, didn’t you?

    Unsuccessful applescript recording

    The only thing it actually recorded was that thing at the very end, when you finished logging in to the FTP server and you changed the window’s view from Icon to List. See what I mean? Spotty and unpredictable. Recording scripts isn’t totally useless, but once you pick up some scripting skills, you practically never use it.

    Well, the Finder window thing went well at any rate. I might want to actually use that script later. Which dovetails us nicely into…

    Saving scripts

    Saving a script has a couple of quirks, compared to saving document files in other applications. No big surprise…in a sense, you’re building software here, so you have to decide how this new software is going to be deployed, you know? The screenshot below shows Script Editor’s standard Save dialog.

    Script Editor’s Save options

    The file format options are as follows:

  • Application. The most useful form for your finished script. It’ll run whether or not Script Editor is present, and it can run as a drag-and-drop utility if you’ve scripted it properly.
  • Script. If you’re still working on your script—or if you’re co-authoring it with another scripter — you might want to save it as a Script file instead. It’s slower and not quite as versatile as an application, but it’s a little easier for a scripter to work with.
  • Script and Application Bundles. You don’t want to know.*
  • Text. It’s a file containing nothing but words. No formatting, no other data at all. Useful for publishing purposes and when you need to read your script on an OS that doesn’t support AppleScript (like a PDA or a Windows notebook).
  • * No, really… I want to know about Bundles : I’ll give you the simplest possible explanation of what a Bundles is—it’s a scheme that the Mac OS uses to ensure that a price of executable software and its resources are always lumped together and treated like a single entity. Imagine that I’ve written an AppleScript that takes a generic, prefabbed sales agreement (which exists as a TextEdit document) and, after asking the user some questions, prints out a binding contract that even Judge Judy would approve of. It’s so useful that I want to give it away to people. If I save the script as a bundle, I can stick the template file right in the same package as the script. My script will always be able to find it, and there’s no chance that someone will receive this script without this Really Important File. Bottom line is that Bundles are things you’ll deal with as you become an advanced scripter. Don’t worry about ’em for now. These aren’t the droids you’re looking for. Move along.

    You also have three options available to you:

  • Run Only. Normally, a saved script, even one that winds up as an Application, can be opened in Script Editor and modified. If you want to protect your code from tampering or theft, click this option.
  • Startup Screen. Sure, you know what this script does and know how to use it. But will everybody else? Clicking this option takes the text you wrote in the Description tab of the script window and packages it as a startup screen that appears whenever the script is run.
  • Stay Open. Scripts normally run once and then quit. Checking this box causes the script to stay open and active. There’s a special kind of AppleScript code called an idle handler that takes advantage of this. If it’s incredibly important that iTunes is always up and running (it has to be available to serve music to all the other Macs in your house, let’s say), you can write a script that checks every 10 minutes to relaunch it if it doesn’t appear to be in the list of running apps.
  • Give the script a name, click Save, and you’re golden.

    Ihnatko Tiger book cover
    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.

    AppleScript dictionaries

    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.

    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.

    Editing tools

    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

  • Script Assistant. Script Editor can take a wild guess at what you want to type next. If you’re about to type the name of a container that you’ve used before, but you’re not entirely sure how you spelled it, just type the first few letters and wait a moment. An ellipses (…) will appear. If you press the F5 key on your keyboard, Script Editor will pop up a list of suggestions (shown to the right).
    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.
  • Contextual Menu Scripts. Dang. You know the AppleScript code presenting the user with a one-button dialog box, but you’ve forgotten. Or maybe you remember, but you’re just too lazy to type it all out. No problem. Just control-click in your script’s editing window, optimally in the place where this new bit of script needs to go. You’ll see a contextual menu pop up, a la the screenshot below.
    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.

    Scriptus annotatus

    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

    end tell

    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:

  • Tell… end Tell: Reflect upon the fact that there are anywhere from dozens to hundreds of apps installed on your Mac. If you have something to say to just one of them, you can’t just stand on your chair and shout “Hey, you!” So when you have something to say, you surround it with a tell block so that it doesn’t get intercepted by the wrong app.
    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.
  • set… to is how you load up a container (
    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 dialog: Generates a standard Macintosh dialog with the contents you specify. For simplicity’s sake, we’re using the plain-vanilla, ready-to-wear dialog. It has text, plus OK and Cancel buttons. AppleScript lets you customize these pretty thoroughly. Because the dialog is just giving us some information, there’s really no need for a Cancel button, for example. Go to the Scripts menu and look at the dialog samples under the Script Editor Scripts menu.
    display dialog
    generates its own results, too. If I made the line
    set someContainerName to display dialog (etc.)
    ,
    someContainerName
    would 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. ]

    Subscribe to the Create Newsletter

    Comments