Calling Applescript from Perl

First off, I don’t like Applescript. In fact, I hate it with a passion. You would think the Apple would learn from Cobol that natural language programming languages just suck. But no, Apple created the abomination called Applescript anyway and foisted it upon us and now sometimes you just have to suck it up and use it. Preferably from a distance with gloves on (and maybe a 10 foot pole) so that it doesn’t dirty your soul too much. But I digress.

I needed to call some Applescript from perl and was quite proud of my end result:

sub osascript($) { system 'osascript', map { ('-e', $_) } split(/\n/, $_[0]); }

The usage looks like this:

osascript <<END;
 tell application "Finder"
 display dialog "Hello"
 end tell
END

So basically the Applescript sits right inside your perl program and gets launched without needing any temporary files on the disk.

How does it work?

If the perl line is incomprehensible to you, let me break it down. The inner most expression is:

split(/\n/, $_[0]);

That takes the first argument to the function, breaks it apart at the line endings and puts the parts into a list. If we were to dump the result of the split using the dialog example above it would look like this:

(' tell application "Finder"', ' display dialog "Hello"', ' end tell')

Next, it uses the map function to insert “-” before every item in the list. It does that by using the fact that perl flattens arrays. The dump of the output of the map function conceptually looks like:

(('-e', ' tell application "Finder"'), ('-e', ' display dialog "Hello"'), ('-e', ' end tell'))

but really perl immediately flattens it to:

('-e', ' tell application "Finder"', '-e', ' display dialog "Hello"', '-e', ' end tell')

At that point it calls the system function with “osascript” and that last array as arguments. When system is passed a list instead of a string it runs the command with the arguments directly instead of launching a shell. This way all the arguments are effectively quoted correctly but without ever having to worry about quotes. This is an extremely clean way of launching commands. You really should never pass system (or open) a string: (a) it needlessly launches a shell, and (b) you have to worry about quotes.

In the end, I like that it fits on one line and that it lets the Applescript sit in the program in its native form.

Edit: Also check out my Ruby version.

Last Modified on: Dec 31, 2014 18:59pm