AppleScript for the rest of us

Of all the programming languages I have learned, there are two that have consistently made me feel stupid.

Prolog and AppleScript.

At least with Prolog, I found I could provide it with enough random facts and it would eventually barf back an answer of ‘yes’ for whether or not my assignment was done. And, of course, Prolog has good jokes (thanks, Ray!):

Q: How many prolog programmers does it take to change a light bulb?
A: No.

AppleScript, on the other hand, continues to baffle me. All those english like sentences just confuse me. I constantly try to write code that is, well, like code and it doesn’t work.

Fortunately, there is appscript, a python module that makes any AppleScriptable application into something I can talk to just like any other Python object. This quite effectively reduces AppleScript programming to a programming exercise that my tiny little mind can effectively metabolize.

Furthermore, I can use appscript from within the command line interpreter (read this first to make sure the command line python interpreter is actually useful).

While grabbing appscript, you might also want to download HTMLDictionary. It dumps an appscript compatible HTML document describing any random application’s scripting dictionary.

After installing appscript, fire up the python interpreter and grab a reference to the iTunes application (yes, start it with pythonw — appscript requires a windowmanager connection):

[albbum:~] bbum% pythonw
Python 2.3.5 (#1, Jan 13 2006, 20:13:11) 
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import appscript
>>> iTunes = appscript.app("iTunes")
>>> print iTunes
app(u'/Applications/iTunes.app')

Great! Now what?

Fortunately, appscript has a built in help() command that will answer exactly that question:

>>> iTunes.help()
================================================================================
Appscript Help (-t)

Reference: app(u'/Applications/iTunes.app') 

-------------------------------------------------------------------------------- 
Description of reference

Terminology for application class

Class: application -- The application program 
    Properties: 
        current_encoder : k.encoder -- the currently selected encoder (MP3, AIFF, WAV, etc.) 
        current_EQ_preset : k.EQ_preset -- the currently selected equalizer preset 
        current_playlist : k.playlist (r/o) -- the playlist containing the currently targeted track 
.....
        visual_size : k.small | k.medium | k.large -- the size of the displayed visual 
    Elements: 
        browser_windows -- index | name | id 
....
        windows -- index | name | id 

================================================================================ 
app(u'/Applications/iTunes.app')

Oddly, help() doesn’t seem to show the commands available on the application reference. Fortunately, HTMLDictionary does.

Now I can can poke around the library a bit:

>>> pl = iTunes.playlists[3]
>>> for p in iTunes.playlists():
...   print p.name()
... 
Library
Party Shuffle
Purchased
90’s Music
My Top Rated
Recently Added
Recently Played
Top 25 Most Played
Videos
burny burny
Podcasts

Including diving all the way down to the tracks:

>>> for t in pl.tracks():
...   print t.name()
... 
Munich
Who Will Love Me Now (Jimmy Gomez Mix)
Cover Me (Trouser Enthusiasts Remix)
Change (Angelic Remix)
....

You get the idea. There are tons of cool things that could be done with this tool in hand. Obviously, combining AppleScript with something like Twisted to build a network enabled gateway to your desktop.

Or you could use PyObjC to build standard Cocoa apps that interact with other apps via AppleScript directly in your app’s code. Of course, this would allow access to any random framework on the system either through the Objective-C APIs directly from Python or by compiling simple wrapper classes in Obj-C around any C or C++ API.

Fun.



8 Responses to “AppleScript for the rest of us”

  1. ssp says:

    I don’t know a bit about Python but all this really sounds interesting.

    I assume it doesn’t really help you to do things which just tend to fail in AppleScript, though. Or is there some higher magic in this than using a different language to send AppleEvents?

  2. Nick Matsakis says:

    I believe the reason that help() is screwed up with iTunes has to do with the way it declares its applescript dictionary. iTunes has a lot of quirks in Applescript that have come over from its OS 9 heritage.

  3. James Eagan says:

    How does appscript compare to gensuitemodule? It’s been a while since I last used that and found that it was pretty darned slow. It took quite a while to read in my iTunes library (only about 5k songs) via applescript. I ended up just slurping the plist instead. I suspect that the slowdown is in the fact that I’m using applescript altogether, but if appscript is any faster, that would certainly be a nice option!

  4. bbum says:

    gensuitemodule is cruft; broken and outdated.

    aete came along and was much better, but has been deprecated in favor of appscript.

    appscript seems pretty speedy and I have yet to really break it. It is still obviously using apple events under the covers, so there is a bit of communication overhead. But I was able to pull a large list of songs out of iTunes without a noticeable pause.

  5. Kevin Marks says:

    You know how regex (and, in some cases, perl) is a write-only language?
    Well AppleScript is a read only language. You can read the scripts and understand whet they are getting at, but not enough to actually edit them and have them still work.

  6. Jacob Rus says:

    Kevin, that’s only about 50% true. While python is certainly a lot nicer than applescript, once you have spent a bit of time with applescript, it’s usually possible to cobble things together to do what you want, especially with some judicious googling. Then again, sometimes it’s just completely baffling.

  7. eike says:

    bbum just talks from my heart.

    (Yes I also only got into it via the pyhton binding,
    and yes prolog always answered NO to me)

    But the concept behind applescript just rocks.

    It’s all about sending complex queries
    just in one turnaround.

    Basically Applescript did Years ago,
    what a good webservice api should do.

    Actually I was quite impressed,
    how flexible python actually is.

    In Python, it looks like a simple object traversal,
    but on the wire it makes for a complex applescript query in the end.

    I believe there’s a lot to be learned for the systems that we build.

    ~eike

  8. bbum’s weblog-o-mat » Blog Archive » Smacbook Pro says:

    […] And, of course, the above demonstrates how trivial it would be to make various physical gestures control other aspects of your machine. Since I don’t actually use multiple desktops, I replaced the notification stuff with a call out to applescript to play the next track in iTunes. […]

Leave a Reply

Line and paragraph breaks automatic.
XHTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>