I agree with this wholeheartedly. Or maybe even make a clean break and scrap OSA and introduce a new system.

I’ve been talking up the benefits of scripting apps on the Mac since the 1990′s. The sad fact of it is that Apple has never really supported scripting to the level that it deserves. It’s even more important now in the days of a UNIX based MacOS. I have a bunch of scripts that I rely on daily to help me get things done more efficiently. I’d write more of them, but two things hold me back. AppleScript is really a funky language. I’ve partially solved that by switching to using Python (via appscript) to do the scripting, but that’s only half the problem. The other half of the problem is that the API exposed via OSA is also pretty funky. If Apple cleaned all that up, in say, 10.6, I’d be happy to rework my existing body of scripts.

Even if that happened, the big problem is that developer’s don’t really support scripting that well, so a good scripting system overhaul needs to look at making it easy for developers to expose application functionality to scripts. Unless that part happens, improvements in the scripting language, and OSA’s API’s will not be enough to push scripting to the level where it belongs.

12 Responses to “OS X Scripting”

Thank you for bringing this topic up, as there seems to be considerable confusion as to what the overloaded term “scripting” means in Mac OS X.

Mac OS X supports a wide variety of scripting languages, from Shell to Python to Ruby to AppleScript, etc., and a variety of implementation methods. Generally when the term “scripting” is used, many think of AppleScript, probably because of its popularity and 15-year history on the Mac. But AppleScript is not the only scripting language in the OS.

The most common method of “scripting” applications is through Apple events, a messaging architecture integrated in the OS, that allows applications to be queried and controlled through the use of Apple event messages. Application Apple event APIs are referred to as an application’s “scripting dictionary” and they contain information about the application’s classes and properties exposed to Apple event calls.

In Mac OS X Leopard, the Scripting Bridge was introduced, and it enables languages other than AppleScript to also query and control applications with Apple event interfaces. So with Leopard, you can use Python, Ruby, and other languages to “script” applications as you want. Examples and documentation for the Scripting Bridge are on the AppleScript website (www.apple.com/applescript) and the developer website (deeveloper.apple.com). The Scripting Bridge is efficient and will make it much easier for those developers who write in scripting languages to add application control to their repertoire.

As pointed out in the blog, the depth and quality of an application’s “scriptability” depends entirely on the application’s author. While it takes time to think-through and design a good scripting dictionary, there are many tools available in the OS to make it easy for the developer to expose application and class properties, and to add commands. These are well documented in tech note 2106.

Unfortunately, not all developers take the time to read this document or to review the sample code on the website. This is unfortunate. Adding Apple event support to your application is a fantastic way to provide dependable, low-cost regression testing, in addition to gaining customer loyalty by providing your customers with the tools they need to make your application part of their essential workflows.

But enough of the “marketing-speak” (even though it is true). My goal is to point out that there are tools, resources, and documentation available in Leopard to aid scripters and developers alike.

One more thing… if you’re in SF next week attending the WWDC conference, come by the Cocoa Development with Scripting session at 5 PM on Wednesday to get an overview of this issue. And who knows, you may learn something new

“The other half of the problem is that the API exposed via OSA is also pretty funky.”

Hi Ted, I assume you’re talking about the ability to attach scripts to applications, yes? (Mail rules, folder actions, etc.) Yeah, the OSA API is a bit of a bear at the best of times, and a right pain to integrate with interpreters such as Python and Ruby that are simpler and safer to run out of process than those specifically designed for in-process use (AppleScript, JavaScript).

Personally I’m with Gruber in thinking the OSA component architecture needs ditched and replaced with something more suitable to OS X and the sorts of languages that are popular today, but I doubt this’ll happen any time soon.

In the meantime though, if you’ve a burning desire for a fully OSA-aware Python or Ruby and want to discuss, drop us a note sometime and we can chat about it some more. While I’ve decided not to pursue the current PyOSA codebase beyond its current ‘developer preview’ status, it has given me ideas for a new design that, time permitting, I’d like to try later in the year.

I’ve been using AppleScript since day 1 (15 years?!) and for me, at this point, it just seems to flow naturally. Sure there are peculiarities in how developers implement their dictionaries and it takes a bit of probing to figure that out but once you do, the ability to string complex workflows together using best of breed apps makes the Mac an incredibly powerful platform. Note to developers: if you make your app scriptable (and you should), offer loads of example scripts to show users how to actually utilize your app via scripting.

At first, like everyone I guess, i struggled with AppleScript too. At some point, though, it just clicked (though I enjoy solving puzzles which is a very handy trait if you are going to get into AppleScripting at all).

For quickly prototyping new applications, I often test my logic in AppleScript before porting to something else (JavaScript, Objective-C, etc.). I test in AppleScript because the authoring tools are so accessible but I port to other languages because, and this is my one major complaint, AppleScript is so painfully slow. OSA is a great idea, it just needs to be orders of magnitude faster.

I gotta say, I really disagree with Gruber here, which is unusual. I am proof positive that Applescript is in fact something between natural language and real scripting/programming. He complains that you can’t simply write English sentences in Applescripts; of course not! But you can think of what you want to do in English, and do some Google searches, and generally you’ll find otu how to write what you want to do. In Perl or Python or PHP or Ruby or what have you, I don’t even know where to start thinking about things. They are much less approachable. Applescript’s in-between position has allowed me to do things with my Mac that I never could with Windows or with other UNIX scripts: an iCal alarm clock; picture uploads from a web form with folder actions; even make a whole application for network iTunes control, with Applescript Studio.

But fine – maybe I’m in a very small minority, and should be ignored. More importantly, many applications are written with Applescript support built-in. This, plus the OSA, means that you can easily control GUI applications on the Mac from any kind of script you desire. It’s a great bridge.

Is it inefficient? Sure. Is the syntax weird? Sure. But it works great when it works, and it’s honestly not that hard to learn. If you’re complaining about it not reflecting natural English, then you probably haven’t actually sat down and learned the syntax like you would with a normal scripting language. If Gruber wasn’t trying to take shortcuts, he might find it’s not that hard to get a handle on it.

Plus, getting rid of it would just mean introducing some other new, arbitrary thing to replace it, and it would be a whole new thing to learn. For what?

If you want to only use those other scripting languages, than you might as well use a Linux box. One of that great strengths of OS X is that it’s UNIX+. Scripts+Applescript(+Automator); Terminal+GUI; etc. Abandoning Applescript would diminish that strength.

I don’t think that Gruber is advocating doing away with the ability to script the GUI apps. I know that I am not. All I want is a better way to be able to do that. My Python scripts take data out of GUI apps, jam them through UNIX programs and then jam that data into other GUI apps, which then do actions on the data. All I want is for it to be easier to do that in languages that lots of people know, and for there to be more apps that expose more of their internals to be scripted that way. The comment above about Numbers (which has no scripting dictionary at all) suggests that it’s too much trouble for even Apple to bother implementing.

Ted: “or even basic weirdness in dictionaries – itâ€™s way more complicated than it needs to be.”

That’s the fault of the Apple Event Object Model, with is the clever-but-heinously-difficult-to-implement-reliably RPC+query mechanism used for identifying and manipulating application objects via Apple events. It’s a wonderful idea in principle, but after nearly a decade of dealing with the problems it causes in practice I’m pretty much of the conclusion that ditching it for a really simple and stupid, but reliable and easy-to-understand, object-oriented replacement a-la COM or DO, would ultimately be the best way forward for application developers, application scripters and Apple itself.

Let’s face it: Apple have been trying to get Cocoa Scripting working properly for five years now and it still blows a variety of chunks, most of their own scriptable applications have chronic design and/or implementation problems, and looking at Scripting Bridge I get the impression that the AppleScript team themselves wishes the whole fancy-schmancy weird-as-heck RPC+query thing would kindly bog off now. Even William Cook, one of the original designers, pretty much acknowledges it was the wrong way to go for desktop IPC; it’s just that System 7′s atrocious multitasking performance made it a simple, fine-grained messaging system impractical – hence the heroics in creating AEOM.

Ted: “I hope that you wonâ€™t give up on PyOSA.”

I think the current PyOSA implementation is a bit of an evolutionary dead-end, given the problems of running a Python interpreter in-process without any control over what users throw at it. This certainly doesn’t mean I’m giving up on OSA component development, however, and I do have plans for its successor. As with my first attempt, MacPythonOSA, I’ll be happy to write off PyOSA as a learning experience if it means the third time’s the charm. As with most OSS ventures, mostly it’s just a question of finding the time and motivation to make it all happen. But hey, fingers crossed.

So much for the original idea behind OSA and AppleEvents, which was to expose the *human centric* application objects (not the programming objects) to control by a scripting language or other non-graphical user inteface. That virtually no-one recalls that this was meant as a bridge to natural, universal application voice control is shameful, to say the least.

I have done a heck of a lot of Applescript, osascript, and appscript, and as a result I agree it could be much better. On the other hand Apple is stubborn, and still uses Objective C, which only recently obtained garbage collection. It probably won’t happen any time soon if at all.

AEOM and full scripting support was always hard to add in a Carbon-based app. Designing it in from the beginning was was the ideal solution of course. And factoring out the command/object structure, in a manner that things were useful and functional was a bit of a bear as well. I hope that at least part of it has gotten easier in Cocoa (well, I know it has) but haven’t had the need to work in that area of an app for awhile.

My point is simply: don’t dis’ the developers for not implementing the full AEOM in their apps; and don’t believe the Apple evangelist guys who’ll tell you how easy it is.

Its certainly valuable to have an application do this, but its doesn’t come cheap.
the architecture of a fully-scriptable application is probably cleaner (due to separation of UI from command processing), and certainly more testable (since you’ve now exposed a command interface below the UI.)

One thing to think of: instead of having a UI guide the user, and prevent them from doing things in an “unexpected” way, a command script is likely to blow up your app and really expose those inner edges more easily. It adds another serious round of testing and fixing. A valuable thing to be sure, but one more task to worry about in a busy development schedule.