Javascripting your Mac

OS X 10.10 Yosemite brought a lot of stuff under the hood. One of the rarely mentioned surprises is that, after years of death speculations, Apple suddenly breathed a lot of life into scripting the OS again. Applescript has been around since forever, a natural-looking and powerful yet surprisingly clunky-to-write way of stringing applications and tasks together into repeatable workflows. Automator - an app providing a sort of IDE for creating scripts in a more visual way - was pretty much the last update to the OS X automation story.

Automator was released in 2005.

With no updates on one hand, and on the other app store guidlines, sandboxing and limits on inter-application communication, many of us feared scripting was on the way out. Then Apple dropped all scripting support in one of the larger updates to Iwork, and the demise seemed all but certain.

But then Apple brought back Iwork scripting in a big way. And now we have Javascript as a first-class OS scripting language, with the official label of "Javascript for automation". For years, people have been wishing for a "pro" dialect of Applescript. Javascript, for all its flaws, fits that bill perfectly. I took the one Applescript I have created and actually use regularly, ported it to Javascript in no time at all and added features to it almost without noticing. The script editor is still almost desolately spartan as far as development environments go, but the familiar language and the added capabilities it brings makes scripting feel both a whole lot more modern and especially a whole lot more accessible.

One weird trick to invoke methods

Scripting dictionaries hold all the keys you are looking for, and you find them in the file menu. Open the dictionary for an application and you will find a concise list of everything it can do. The UI is complete with a switch to go between Applescript and Javascript. The parameters for all methods are clearly listed and described, but it took me a few minutes to dig up how to actually invoke them.

First, I thought you would simply list the parameters in order, like in any old function call. But that was not it, although it seemed to work for a single parameter. Then I noticed the parameters had names and thought perhaps you simply wrapped them all in an object where the parameter name was the key and the value the … well, value. The truth, surprisingly, was just inbetween. Turns out methods can have one direct parameter and then optional named ones. The direct parameter goes straight in, while the named ones are wrapped in an object. Pretty reasonable once you know about it.

And one to get interaction

Oh, a second trick. To get some interaction - dialogs, notifications or input - you need an application to latch on to. The magic is this:

var app = Application.currentApplication(); app.includeStandardAdditions = true;

Then, you are free to do things like this:

app.displayDialog('Paste markdown title list', {defaultAnswer: ''})

You find these methods described in the "StandardAdditions" dictionary, by the way.

The direct parameter of the displayDialog method is the dialog text. defaultAnswer is one of the optionals, and it makes the dialog have an input text field. The contents of the field are available in the returnedText property of the object returned by displayDialog once the dialog is dismissed.

Finding more

Apart from the dictionaries, the only document from Apple I have found is the release notes. While brief, they have managed to answer my questions so far.

(But I sure hope more is coming.)

A few more starting points I have found: