101: Red Sweaters and AppleScript Fun with Daniel Jalkut

2 Likes

Great episode. My favourite thing that I learned about FastScripts recently is that you can programatically access which scripts are currently running. For example, this will tell you if a script with a particular name is currently running:

on isScriptRunning(scriptName)
	
	tell application "FastScripts"
		repeat with eachTask in (every script task)
			if (name of script item of eachTask) is scriptName then return true
		end repeat
		return false
	end tell
	
end isScriptRunning

This can be useful if you have two scripts that you don’t want running simultaneously (or do want running simultaneously), and so on. Hugely powerful app.

2 Likes

Good show. I’m one of those people described in the episode who just doesn’t get AppleScript. Yet I can’t find a good resource on JavaScript for automation. Am I missing something simple?

@oldblueday: There are some JXA resources if you google around but, I wouldn’t bother. There’s a reason nobody uses it: it’s garbage. AppleScript syntax is awful, but at least it works right and has some community support for when you get stuck.

The key to understanding application scripting in AppleScript is this: It is not OOP. It’s remote procedure calls plus simple first-class queries.

Kinda like SQL, except you’re querying tree-shaped graphs instead of tables. (Or perhaps XQuery over XML-RPC, except that is euwww in any language.)

…

AppleScript’s syntactic sugar is horrible to wade through, but once you learn to see past that it’s a pretty logical system: local procedural Pascal-y language on one side; query-oriented IPC bridge on the other. I wish the original designers hadn’t tried to disguise the join: the impedance mismatch between the two is too great; better to be honest about its true complexity than pretend that it’s simple by hiding that complexity from users, which only confuses and frustrates them and gives the product a bad reputation.

JXA, like ScriptingBridge before it, makes a critical mistake: it failed to learn from the mistakes and successes of its predecessors. JXA and SB lie to their users, pretending app scripting it’s OOP when it’s not. As a result: 1. it breaks some features that work perfectly in AppleScript; and 2. it confuses the hell out of users when it does behave in profoundly non-OOP ways, as observed behaviors contradict their mental model. That’s partly why both of those products crashed and burned.

Also important to note: Apple management eventually noticed these repeated failures too, finally disbanding the Mac Automation team and firing its Product Manager in 2016! The entire AppleScript stack has been in minimal maintenance mode ever since. It’s a walking corpse already.

This is a huge pity and tragic missed opportunity. While the language support is dreadful, the underlying remote-query architecture is actually rather good: a very high-level user-oriented UI/UX that’s a full peer to GUI, only using words instead of click and touch. A modernized Apple event architecture could’ve been ported to iOS by now and hooked into Siri, enabling direct voice control across thousands of apps: simple commands and queries spoken instead of typed. Anyway, that’s Apple.

…

Now, if you do enjoy living dangerously, there are technically competent alternatives to AppleScript: Python appscript and its descendants, SwiftAutomation and nodeautomation. (There is also a 3rd-party fork of Ruby appscript, rb-scpt, but I don’t use that myself.) I know appscript is competent to replace AppleScript because I wrote it for that purpose and have been using it professionally for advanced automation development for more than a decade. (Apple even considered bundling Python and Ruby appscript in 10.5 until some Apple manager spiked that in favor of their own in-house trash.)

The catch is: I will no longer provide (free) training or support, nor any warranty whatsoever. The macOS APIs these bridges depend upon are mostly legacy and some have been deprecated for years. If Apple change something in macOS that breaks it, it breaks. So caveat emptor, E&OE, and don’t invest any more in it than you are willing to lose. Apple’s pram, Apple’s toys; we’re all just visitors in it.

(I currently use these bridges with Adobe CC-based customers wanting to migrate their legacy AppleScript workflows onto modern supported technologies, although only as a temporary stepping stone: I can migrate their AppleScript code to Node.js + nodeautomation now and later, once Adobe finishes UXP, the legacy Apple event stuff can be replaced by shiny new UXP API calls.)

Here’s the old appscript page for reference:

appscript. sourceforge. net

The Tools page has useful links. The only “appscript” which I can say for sure still works is the Python3 version, which is available on PyPI. SwiftAutomation I’ve not used in a while so I can’t vouch for that. If you want to try nodeautomation, which I’ve recently rebuilt, you will need to install from my GitHub:

I should get this new nodeautomation onto npm by end of month (just waiting on the objc author to merge my changes and release). Again: I offer no warranty or support, and there is zero user community left so you’re really on your own if you do choose to use it (although the same is true of JXA). But the documentation is adequate, and the ASDictionary and ASTranslate tools help in translating from familiar AppleScript syntax to Node.js. Personally I’d stick to AppleScript if I were you, but YMMV.

HTH

5 Likes

@Daniel @Rosemary: I agree with Daniel: JXA was a huge mistake and Apple should’ve focused on quickly positioning WebKit’s JavaScript as a modern alternative to Node.js. Remember, this was back around 2012–2013, when Node was just starting to take off.

In fact, they did make a start on this, with the JavaScriptCore team announcing a new App-embeddable ObjC API at WWDC13. (I would link to the original session video but looks like Apple has memory-holed it.) That would’ve positioned JavaScript as a modern, developer-friendly alternative to the ancient, painful, and increasingly deprecated OSA. No built-in IPC support, but that could’ve been added later based on XPC Services or other suitable technology (even Apple events!).

It’d also have been trivial to wrap JSCore as a command-line executable so it could be run in Terminal (not doing this for 10.9 was the JSCore team’s key strategic mistake). Add an npm-compatible library management system, and JS on Mac would’ve kicked!

Unfortunately, at some point after WWDC13 JSCore got handed to the Mac Automation team managed by Sal Soghoian. Perhaps some higher up was upset about the WebKit team encroaching on their territory and took the project for their own; whatever. So when JXA was announced at WWDC14 it was a total surprise, having expected embeddable JSCore to begin replacing OSA and AppleScript which, after their renaissance in the mid 2000s†, were already dying again.

Even so, this was an incredible one-time chance to turn Mac Automation into an overnight success with a million sitting JavaScript developers already on Mac OS X.

I also immediately realized just from watching the WWDC demo that JXA was nowhere near finished or fit for purpose. So right after WWDC13 was over I emailed Sal offering my free assistance to help them get it ready and fully tested in time for Mac OS 10.10’s release. He accepted and I hit the ground running: beating the tar out of JXA, identifying numerous omissions and defects, and sending detailed descriptions of those problems and how to fix them directly to Sal so his team could act quickly. I even crash-wrote them a complete JavaScript OSA reference implementation to learn from and/or just steal; that was three weeks of work and, aside from the odd bugs, worked >99% as well as AppleScript. So JXA had every opportunity to stick a respectable landing for 10.10, and really get polished and beautiful in plenty of time for 10.11.

My only conditions to Sal for doing this work were 1. cover my cost of an ADC subscription so I could download the 10.10 developer previews to test it, and 2. don’t waste my time. I gave Sal 6 weeks of free (world-expert) consultancy (≅$25,000) and got ghosted in return. A few minor issues I reported got fixed, a few more got half-assed, and the rest ignored completely. And since I was emailing all this feedback directly, none of it showed up on Radar where it might’ve been flagged for management further up to take action. (My stupid!)

Once JXA shipped in 10.10 half-baked and broken, and it was clear to me that its own project manager did not care, I scrapped my plans to write “Learn JavaScript for Automation” and to do the community building and user support work vital to making JXA a popular success. Ove the next few months the JXA authors patched a couple minor bugs, answered a few user posts requesting assistance, and then gave up. I don’t think Sal even poked his head up once. No improvements, no marketing, no support whatsoever. No way to treat either your product or your users.

Ever since, when someone asks how to do X/Y/Z in JXA, my stock answer is as you’ve learned the hard way yourself: while trivial commands usually mostly work in JXA, sooner or later you will hit its brokenness, and then your only option is to go back to AppleScript. JXA is defective by design—unfixed and unfixable—for no better reason than its developers chose not to listen to what their own users were telling them.

…

So that’s why JXA died, and why JavaScriptCore outside WebKit died too. (Two for the price of one!) Mac Automation followed shortly after: in 2016, the Chrises were reassigned to different departments, Sal fired, and the Mac Automation department eliminated. Node.js climbed unchallenged into the stratosphere, followed by Apple’s new Swift language, and whatever Apple now makes of Siri Automation is the future.

You’re welcome to skim the old appscript site if you’re curious what might’ve been:

http://appscript.sourceforge.net/

And for terrific insight into the original vision and design motivations behind AppleScript and Apple event automation, this is a must-read:

Sadly William Cook passed last year from cancer; Warren Harris a few years earlier. A tragic shame their fantastic vision did not receive the support it deserved. 30 years on and there is still nothing that comes close. That AppleScript has survived this long, as flawed and unloved as it was, is a testament to the power of the ideas that underpin it, chiefly: our machines should work for us, the users; not the other way about.

The past is the past. Let’s hope whatever it is Apple is cooking for WWDC22, it’s a future we can all look forward to.

–

† Thanks largely to Cal Simone and the publishing industry who, back when Jobs was cutting all the OS 9 deadwood, convinced Apple to continue supporting AppleScript (on threat of losing their one profitable Mac market, which Apple then could not afford). If only Cal had been AppleScript Product Manager, Apple Automation would be in a very different state today.

5 Likes

As someone who done alot of web scraping I can add that puppeeter is slightly better for stealth than selenium. You can use selenium in stealth mode too (by changing user agent, etc) but pupeeter is slightly more difficult to detect so its often a better choice.

2 Likes

:wave: Hey everyone —

I enjoyed this episode despite thinking it may be too in-the-weeds for me. Daniel was a great guest.

One thing that came up that I’d heard on other shows previously was the use case of typesetting large amounts of text via scripts. This concept sounds interesting and I’d love to see how this was done.

Does anyone recommend any articles on this?

Thanks!

Awesome! Thanks @redsweater for the quick reply :+1:

1 Like