JavaScript as an alternative to AppleScript on OS X Yosemite
developer.apple.com
developer.apple.com
In the same cycle that they release a brand new language, they begin the deprecation process for their (only?) other proprietary programming language in favor of an existing language. Pretty cool.
The most underrated thing to me that made it all worthwhile, though, was Remote Scripting. I think the full potential of it has yet to be realized, and hopefully JavaScript will allow some impressive future developments.
Looking at the sample code in this page:
Mail.outgoingMessages.whose({subject:'JavaScript'})
is doesn't look much better.Edit: found a stack overflow question/answer [1]. It's doing a little additional work beyond searching for mails with a particular subject, but even just the searching functionality is much larger and more convoluted that the single line of js you referenced.
<https://developer.apple.com/library/mac/documentation/apples...
doWhatImThinking();
Since the javascript code looks isomorphic to
outgoing messages whose subject is "JavaScript"
I'd think that the issue is not mitigated by a different syntax. tell application "Mail"
set msgs to every outgoing message whose subject is 'JavsScript'
end tell
So, yes :).It also didn't help that Apple provided very little support for implementing the language's rich query model, which led to many applications only implementing one or two ways to access objects, often with bugs. That was the source of most of the annoyances with AppleScript.
edit: Back in 1998/99, I even wrote a web server entirely in AppleScript - it was a platform for our research lab to share, debate and record ideas.
Some apps have them (Pixelmator comes to mind), but for the most part it doesn't have the support that AppleScript used to. It's a bit sad that we now have easier automation (via IFTT) in a huge pile of webapps than many native programs where it hasn't improved in the last 10-20 years.
[1] http://www.macosxautomation.com/automator/features/virtual-u...
Actually, even an 'evolution' isn't necessary, since AppleScript can directly work with Objective-C frameworks, instantiating objects, calling methods, etc. So this gluing between the desktop world and the networked world already exists.
http://www.astronomy.pomona.edu/archeo/WebSTAR%20Doc.pdf
http://infomotions.com/musings/tricks/manuscript/0800-machtt...
http://tidbits.com/article/6292
It had an AppleScript / OSA API that let you write handlers for responding to web hits in other languages that supported AppleScript.
I used it to integrate ScriptX with the web:
http://www.art.net/~hopkins/Don/lang/scriptx/scriptx-www.htm...
The coolest thing somebody did with WebStar was to integrate it with HyperCard so you could actually publish live INTERACTIVE HyperCard stacks on the web, that you could see as images you could click on to follow links, and followed by html form elements corresponding to the text fields, radio buttons, checkboxes, drop down menus, scrolling lists, etc in the HyperCard stack that you could use in the browser to interactive with live HyperCard pages!
That was the earliest easiest way that non-programmers and even kids could both not just create graphical web pages, but publish live interactive apps on the web!
Using HyperCard as a CGI application
http://aaa-proteins.uni-graz.at/HyperCGI.html
http://pfhyper.com/hcfaq/hcfaq4.html
http://www.drdobbs.com/web-development/cgi-and-applescript/1...
The following is taken from the LiveCard web site
(http://www.royalsoftware.com):
"LiveCard is a HyperCard add-on that enables remote users to browse
and interact with HyperCard files, called "stacks", on your web
server. Once installed, you'll be able to serve any HyperCard stack
without extensive preparation - often with no preparation at all.
This means you have all the advantages of HyperCard as part of your
server solution, plus you can now serve those stacks to anyone on
the Web, regardless of whether they're using a text- or
graphics-based browser and regardless of their platform: Macintosh,
Windows, UNIX, whatever."
"LiveCard implements a CGI (Common Gateway Interface) between
Macintosh servers, such as WebStar, and HyperCard. It makes the
HyperCard interface available as high-resolution, compressed
image-maps and HTML form elements, and transforms user gestures in a
web browser to a format HyperCard can understand. LiveCard
translates between HTML, HTTP, and HyperCard "on the fly," requiring
little or no preparation of the HyperCard stack. LiveCard generates
HTML dynamically - as stack content and functionality changes, these
changes are reflected live in the remote users browser."
What does this mean for you? Well, if you have access to a Macintosh
web server running WebStar, MacHTTP, or similar server software that
is cgi-aware, you can serve your stacks using LiveCard. LiveCard can
generate an HTML forms page using the text fields on the card, an
image map with stack graphics and buttons that responds to user
clicks (although the buttons can't highlight), or a combination of
the two. In addition, each generated page has a header and footer
that can be set by scripting...and is HTML aware. This gives an
incredible amount of flexibility.
Note that LiveCard requires a Macintosh web server (not really a
criticism... I love Mac servers...but you do have to have access to
the server, and it *has* to be a Mac, since LiveCard is
HyperCard-based). And to fully realize the potential of LiveCard,
you need to learn some new commands...but there aren't too many, and
they make sense. Plus, the examples provided are very helpful. At
this point in time LiveCard has a limited ability to work with
QuickTime...you can kludge your way around the limitations, but if
your stack relies on a lot of QuickTime, you have to do some serious
modifications. Rumor has it that future versions will have more
QuickTime functionality. But for static graphics (color spoken
here!), there are no modifications.
Where LiveCard really shines is in the area of forms and databases.
I created a stack to be used for a course I was teaching...very
simple, with about 5 text fields for the students name, college,
major, and a topic they were interested in. I then just dragged this
stack into my server folder where LiveCard resides. That was it. I
called up my page on a browser (remember, any browser, any
platform), went to the LiveCard page, clicked on the link to my
stack (automatically created by LiveCard), and there was a
forms-based page with all of the fields...including their labels. I
filled the page out and hit submit. Voila...the data appeared on the
stack residing on my server. Now that is cool.
Pros: Can serve your stack mostly without modification. Can use
externals in the stack. Browser is *completely* platform independent
since a plug-in is not required. Data can be easily transferred
between web page and stack. Leverages existing HyperCard stacks,
especially databases and order processing.
Cons: Requires a Macintosh web server. Limited ability to work with
QuickTime. Can be a tad slow. Lose button highlights and card
transitions.
3. Convert your stack to a SuperCard project. Allegiant (makers of
SuperCard - http://www.allegiant.com) has recently released
Roadster, which is a plug-in for Netscape navigator. Roadster is in
public beta at this time (December '96), and is available for both
Mac *AND* Windows 95. Can anyone say cross-platform? Before you get
too excited, remember that you first have to convert your HyperCard
stack into a SuperCard project. This is fairly painless
however...unless you use externals. Externals present two problems
for the SuperCard/Roadster approach...they don't always convert, and
more importantly, at this time Roadster does not support *any*
XCMD's. This is due to security concerns (you could do some nasty
damage to a client computer...kinda like a java applet gone bad). A
future intranet version of Roadster may show up that supports
externals. Another potential problem is that Roadster only supports
a single window. Now this might not be a problem for HyperCarders,
since one window is the norm. But for dedicated SuperCard people
that have grown used to multiple windows in projects, some tinkering
has to be done.
Since Roadster is a plug-in, you get some more good news and bad
news. The bad news is that people have to download the plug-in and
install it into their Netscape Plug-ins folder before they can view
your project. The good news is the plug-in is free, and your project
runs in the browser exactly as it does on the desktop...buttons
highlight, transitions work, etc... And perhaps even more
importantly, Roadster is available for Windows, so you can finally
get your stack into the hands of the unfortunate Intel-laden masses.
Pros: Project looks and runs just like on the desktop.
Cross-platform. Ability to transfer information via forms commands.
Ability to cache and preload graphics. Very good with external media
such as QuickTime, audio, etc.
Cons: Have to convert your stack. Browser requires plug-in. Lose all
functionality of externals.For instance most of the Adobe product don't care about OSA and offer a Lua extension mechanism instead (even there, I feel they only cared avout filters and publishing modules). Or even iPhoto had severe limitations on what could be done through the scripting interface.
The Finder has perhaps the most useful interface, but anything done there can also be done in the shell IMO. There must be other apps exposing very useful functionalities to OSA, but I haven't see many.
Switching to JavaScript will do exactly zero to fix that. However, there appears to be new functionality inherent in the implementation, including better integration of native code (oddly, the examples are in ObjC instead of Swift), and I assume this will be faster than AppleScript. If this increases the popularity of writing scripts, then perhaps app-writers will improve their dictionaries.
The functionality exposed by OSX apps via AppleScript is often incredible, but the language itself is annoying.
The question is whether or not applications will support it. With the emphasis shifting away from OSX desktop applications to cross-platform and cloud apps, will OSX app developers still take the time to expose scripting functionality?
2) Vendors get a lot of benefits by NOT providing a standard implementation (lock-in, for one).
3) It's not like everybody runs around implementing every new standard that comes out. Vendors have their own timelines and priorities. Heck, we've waited how many years for CSS3 to be implemented? (and it's still missing full support...).
About all I'd change is placing the column names after the table/object names - "FROM table1 SELECT col1, col2" instead of "SELECT col1, col2 FROM table" because it makes code assist features easier. (Microsoft did this with LINQ)
SQL is more like math than natural language. That it is declarative doesn't make it like Applescript.
Yup :-) AppleScript has an interesting history, it used to support multiple "natural languages" (such as French, ...) in addition to English: http://www.cs.utexas.edu/~wcook/Drafts/2006/ashopl.pdf
(This is probably why many AppleScript Guides still say "English Dialect" on the first page, e.g. http://download.info.apple.com/Apple_Support_Area/Manuals/se... )
Here's a Dijkstra rant from '77 against natural language programming: http://www.cs.utexas.edu/~EWD/transcriptions/EWD06xx/EWD667....
In deference to the expressive flexibility demanded by humans, it does provide a few alias terms (“=“, “equals”, “is equal to”) and a few places where something can be written either left-to-right or right-to-left (“name of document” vs. “document’s name”), but even that is common in other languages. e.g., document.name vs. name(document), foo(bar.baz()) vs. bar.baz().foo(), and C’s support for both ”! && ||” and “not and or” operators.
Obviously, tastes vary, and I’m not trying to convince anyone that they should like something they don’t, but often people who complain that AppleScript is unlike languages they are more familiar with have only taken a cursory look at examples of AppleScript and are unaware that it has a syntax that is in fact similar to other languages. The primary differences are that it is very light on punctuation and prefers using descriptive words over abbreviations, because its goal is to be approachable for first-time and casual programmers. Even for AppleScript experts, this often helps make understanding or maintaining code easier.
Personally, I’d like to see AppleScript support some more “compact” syntax, like square brackets for array references, but I do not think it’s reasonable for AppleScript’s target audience to have to learn the meaning of “a ? b : c” before they can read simple conditional statements like “if a then b else c”.
Python, OTOH, strikes a decent balance (assuming de-punctuating is your goal), avoiding punctuation by using keywords for 'and' and 'or' and 'not' , without making the grammar incomprehensible.
AppleScript and HyperTalk are aesthetically very similar but every time I have to write something in AppleScript I get oddball parse errors that I can never decipher and I need to randomly try things until an approach succeeds (for reasons I don't understand) or I give up.
Where HyperTalk was friendly and forgiving, AppleTalk is punishing.
A. Almost any English sentence was grammatically valid.
B. Almost none of those sentences did what you expected.
I find AppleScript a more regular language overall. I think the biggest difference is that HyperTalk was built in to the HyperCard environment, and therefore most of the “language” was in fact just HyperCard-supplied functionality, whereas AppleScript has very little built-in functionality, and sometimes this surprises people when they discover that it’s up to some other application to decide what the behavior of the script is.
tell application "foo"
every bar whose third baz is frob
end tell
whatever you write in that tell phrase gets executed by application "foo" (the logic runs in the process, and has to be written by the implementers writing the "foo" application). Implementing that flexibility is lots of work and hard because Apple did not supply much support libraries (1). Because of that, all implementations were incomplete (and differently so) and buggy. That "and differently so" was the main reason one cannot get comfortable writing AppleScript. Even if the above worked, there was no guarantee that, for example tell application "foo"
the third baz of every bar
end tell
worked.The essence of AppleScript goes very far:
- The editor imports syntax from "foo" the moment it sees that tell application "foo" block.
- When compiled, it converts that into a standardised binary format (an Apple Event)
- When run, AppleScript sends that event to "foo", and "foo" parses and executes it.
In essence, it turns application "foo" into a service that shows its internal state in its GUI (in 1993).
(1) in their defence, I don't think they could have written good support libraries in the language of the day. A few C++ 'interfaces' in header files might have helped, though.
(I expect to have the ability to introspect and manipulate Swift objects in the near future as well, and have a talk on preliminary research of low-level Swift object runtime metadata at #AltConf a couple days ago. The console will also support some of Swift's syntax, such as the named-argument-style method calls.)
Will Cycript work on 10.10 or are you just saying that you'll have two JS choices now (Cycript and JS Automation)?
I use Substrate all the time, I really need to look into Cycript! =)
Why aren't there saner alternatives to Javascript in browsers? We have so many languages at our disposal, why choose Javascript? Why don't people realize that web programming is not great because of Javascript but despite Javascript?
We are bound to Javascript on the web because browsers, for whatever reason, don't support anything else. But we don't have to make matters worse by dragging this weirdo language unto the rest of the programming world.
But who am I kidding, AppleScript may be one of the few languages actually worse than Javascript.
Honestly, I find web programming to be generally terrible. JavaScript is actually one of the better parts of it.
Most of the time I work in C++ these days though.
But let me give you a few recent examples I stumbled over: - Javascript can not format numbers with leading zeros. - Handling binary data is increadibly painful. - Object oriented programming is really convoluted. - Lack of classes and modules makes code structuring hard.
True, it could be worse. But Lua, Ruby, Python, Perl, Scheme, Clojure, and many others are much better languages with very similar feature sets. And then there's a whole host of languages with different features. I just don't see why you would Javascript in an environment where all these other alternatives are available.
Which language would be preferable? Perhaps Lua? Not much else with comparable simplicity comes to mind.
It is better to be lucky than smart."
- Douglas Crockford, 2008
Google, Mozilla, Microsoft, and Opera (and obviously Apple) haven't exactly been jumping at the opportunity to deprecate Javascript in or out of the web. I mean hell, now we have technologies like Node and asm.js that make Javascript the fastest dynamic language in existence! People are even using it in embedded hardware now! So it can't be nearly as bad as people say.
Yup, we're getting trolled...
TL;DR shell scripting for the GUI, not a way to build Mac applications (which you can already do with JS).
Edit: video link
Double edit: Looks like I'm slightly wrong about using JS to build apps this way. You can bundle scripts as applications, and OSA can create windows and controls, so you could hypothetically build whole apps this way. But I'm not sure I would want to.
Given Apple's well-known antipathy to the idea of browser engines other than WebKit and scripting languages other than JavaScript on iOS (yes, yes, I know you can find Python/Lua/Lisp/whatever apps on iOS; I mean as a general rule and for inter-app automation), could this be a prelude to allowing some sort of sandboxed-app automation interface on iOS? That is, allow a JavaScript implementation running on iOS to "drive" apps via this object model?
(Genuine question here. I have no idea whether I'm blowing smoke or whether this is a plausible long-term direction for Apple to take iOS.)
JavaScript is just another interface to Apple's "Open Scripting Architecture (OSA)." Previously, AppleScript was the only way to use it. The fact that they added another language indicates nothing about whether OSA will ever come to iOS. My guess is it won't; the new extensions APIs will likely handle any inter-app communication Apple wants to allow, because they are designed with iOS's sandbox model in mind already.
Put another way, Javascript is to AppleScript with respect to OS X automation, as Scala is to Java on the JVM. The existence of Scala does not indicate that the JVM will be ported to the Haiku OS. (There may be a better analogy but that's what I came up with.)
Additional refs:
- https://developer.apple.com/library/mac/documentation/Darwin...
- http://www.macosxautomation.com/applescript/features/scripti...
- https://developer.apple.com/library/mac/documentation/Darwin...
In the general case, for published apps, I'm not seeing it happen. Apple seems to be super focused on sandboxing and separating components on iOS. Even with the new iOS8 extensions, everything needs to be user triggered and even then, extensions live on separate islands.
It's doubtful they'll change that model since it would defeat the "you can't break your idevice even if you tried" feeling for end users and the app store.
You actually can use Javascript to automate iOS apps running in Instruments (one of Apple's developer tools). This is used for automated UI testing in the iOS simulator or while your iOS device is tethered to a Mac. This has been around for a couple years and there's no indication that it will ever be permitted in released applications. There's actually no reason to enable it – it's only useful for snooping on apps (good for developers, bad for users).
That entire thread is around how Javascript is a bad paradigm for desktop. But, this entire thread is how amazing javascript is going to be for OSX.
Let me add that the JS programming model of Gnome is what powers http://extensions.gnome.org - and I have my own extensions in there. Also (and correct me if I'm wrong) the "GObject Introspection" mechanism is fairly analogous to OSA.
So, is there a underlying technical or implementation issue that makes it good on OSX and bad on Gnome ? use case? technology ? OSA ?
Applescript is used for automation of already existing applications which will still be written in C++ or Objective C. Applescript, a proprietary language with no other uses, is just being replaced by a much more common language in Javascript so people won't need to learn a new one to automate apps. People don't generally write applications using Applescript and they probably won't be using Javascript, so there's little overlap.
In GNOME Javascript is being used to write the applications in the first place. There is total overlap between Javascript and C/C++.
People see the GNOME choice as both redundant and reducing performance of desktop apps while people see the Apple choice as simply using a common language instead of a proprietary one for scripting.
If you think of automation, there have been attempts at bringing flow based programming to the Gnome-JS engine (think of it as Quartz Composer integrated into the desktop) [3] - plus the fact that http://extensions.gnome.org is about as automatic as you can get to customize the desktop.
Is it a difference in positioning ? Because honestly I'm a little befuddled on why all the developers on HN get supremely excited about JS on OSX... and not something like NoFlo.js integrated into Gnome.
[1] https://github.com/GNOME/vala [2] http://lethalman.hostei.com/maja/index.html [3] http://bergie.iki.fi/blog/noflo-and-gnome/
Still, it's a bit weird and it makes me think that the poor folks working on this didn't know what the swift folks were doing because if they had, i suspect that the cocoa-bridged syntax would feel even more natively javascripty than it does right now rather than what's here. For comparison
// in swift
var color = UIColor(red: 0.61, green: .71, blue: .23, alpha: .8)
// in js for automation
var color = $.UIColor.colorWithRedGreenBlueAlpha(.61, .71, .23, .8);
// but why not use objs for named args?
var color = $.UIColor({red: 0.61, green: .71, blue: .23, alpha: .8})
Of the two, the swift feels the most js-native to me because you can easily hallucinate the {}s from the third example. But even if you're creating a js bridge and you're apple, why even force people to deal with alloc/init anymore? Even the registerSubclass syntax feels like a concessionDon't get me wrong, I think it's great that we're getting better applescript support via js, but it's definitely an area where the implementation feels like a step back from cocoascript and jstalk, at least with both of those the syntax highlighted when you were engaging in nonidiomatic behavior but at least both tried their best to paper over it.
What should have been a lightweight approach actually feels more heavyweight than writing equivalent code in swift instead, which makes me sad because i like js and i would have really liked for this to have been more approachable.
Because then there is no way of conveying the order of the parameters. In this case, it's ambiguous whether the method we are calling is colorWithRedGreenBlueAlpha, colorWithGreenBlueRedAlpha, etc.
on change_case(this_text, this_case) if this_case is 0 then set the comparison_string to "ABCDEFGHIJKLMNOPQRSTUVWXYZ" set the source_string to "abcdefghijklmnopqrstuvwxyz" else set the comparison_string to "abcdefghijklmnopqrstuvwxyz" set the source_string to "ABCDEFGHIJKLMNOPQRSTUVWXYZ" end if set the new_text to "" repeat with this_char in this_text set x to the offset of this_char in the comparison_string if x is not 0 then set the new_text to (the new_text & character x of the source_string) as string else set the new_text to (the new_text & this_char) as string end if end repeat return the new_text end change_case
I'm assuming that this will be easier using JavaScript... :)
AppleScript’s primary target audience is first-time and casual programmers. (Of course, there are professional programmers writing applications and utilities in AppleScript, too.)
While you're correct that JS can now be used to write Mac applications without an Obj-C wrapper, that's not really the point of this.
Anyway, you can already write Mac applications in JavaScript. And iOS applications! This has been true since iOS 7 and Mavericks. http://strongloop.com/strongblog/apples-ios7-native-javascri...
You can build double-clickable "applets" in AppleScript and JavaScript, but the OSA interface isn't really made for app development, just automation.
However, they do expose all Cocoa and Obj-C APIs to JavaScript, so anything is possible! They even do a demo of a standalone temperature converter at the end of the WWDC session.
I'm pretty familiar with ObjC-Javascript integration and have been working with it for a while. This change offers a nice direct system interface for automation, and one that has access to all of Cocoa.
I also didn't intend to put Javascript down at all - its more that the more complex part of building a MacOS app is working with Cocoa, and Javascript will make that more complex, rather than simpler, just because of the impedance mismatch.
I'm not sure there's a compelling use case for building such apps, but it's still pretty cool!
It actually kind of cool. And the Temperature Converter example showed a lot of the dynamic nature of the objective C runtime. This one presentation actually piqued my interest in looking at os x scripting.
I've been using it for a couple of months now, and it's been glorious! So being able to do more things in JS makes me very excited.
As to AppleScript's deficiencies, in the past I've used py-appscript[2], though apparently it's no longer developed.
1. https://developer.apple.com/library/mac/documentation/apples...
app.say('This is exciting')
I used work for a living in AppleScript nearly 20 years ago. Heavy drinking helps block out the memories.
Yes, I know that Open Scripting Architecture is also quite old, but having now JavaScript bindings and the types of demos they made, just reminded me of it.
To me it makes more sense to either go completely native with Swift and Cocoa / Cocoa Touch or use hybrid model where HTML 5 content is embedded with the new WKWebView API (aka WebKit 2).
WebKit 2 framework will become public in iOS 8 and OS X 10.10 which means hybrid HTML5/Native apps will be able to run with full speed thanks to JIT, split process model and other optimisations.
One time I had to fill out a few thousand pdf files and print only select pages from them (like pages 2-4 and 14-22) for a client. I used applescripting because it was easy to write (took about half an hour) and worked consistently. Are there any other ways to do GUI scripting in OSX?
I wonder if this will imply (significantly) better debugging tools? Like a way to debug a javascript-script in Safari, sorta like iOS webviews?
You don't write applications in AppleScript; you use AppleScript to control other applications in an automated way.
You can write AppleScripts with simple dialog boxes and such, just as you can write interactive bash scripts. And while you could theoretically implement an application entirely as a shell script or batch file or AppleScript, it'd be a bit like mowing your lawn with a pair of scissors.
On another side note, while Yosemite is the first time Apple has supplied or supported JavaScript as an OSA language, third parties have integrated the Mozilla JavaScript engine into OSA in the past in what I believe is an abandoned project (Google "JavaScript OSA").
I kind've wish they'd used $ for what Application() is, though, to keep an analogous similarity with jQuery and the like.
Easy fix!
"The primary access points for the Objective-C bridge are the global properties ObjC and $."
$ = Application;
var $ = Application;(Although, I suppose, you could use another var for jQuery, such as, uh, 'jQuery' ...)
...unless one of them exposes a HTML DOM to the scripting layer, now that I think of it.
tell document to write "hello world"I'll be interested once I see some succinct JS to show me most played songs in last week, or recent photos imported from iCloud.
https://news.ycombinator.com/submitted?id=bpierre
Edit: Didn't mean to sound critical with "is this normal" comment. Just pointing out.
On one hand, it's really exciting that Apple is taking these huge steps in making our lives as programmers easier. And yeah, I wish they had done this when JSTalk came out, but better late than never.
On the other hand, it really sucks that JavaScript is the new universal scripting language. Swift and JavaScript are now the two blessed languages on Apple platforms. I mean, I get why, but man, JS is just so awful.