JSTalk is how I imagine AppleScript would be done today, if it was written by a Cocoa programmer who was smitten by Cocoa and Objective-C.
JSTalk's goal is not to kill off or replace AppleScript, but to provide a compelling alternative by blending together existing technologies.
JSTalk comes with a command line tool (jstalk), an editor (JSTalk Editor), and a framework that programmers can include in their application to add scripting support with a single line of code.
And finally, JSTalk is open source. So if there is something wrong, or it's not running the way you expect it, you get the chance to peek under the covers and understand what's going on.
Here's the git repository: http://github.com/ccgus/jstalk/tree/master
You can also download JSTalk binaries: http://www.flyingmeat.com/download/latest/JSTalkPreview.zip
Adding AppleScript support to your Cocoa application is a PITA, to put it bluntly. Sure, it's easy to do simple tasks, but once you move away from sample code territory, you are on your own and in many cases, in a world of hurt.
Why not do something more modern? Why not add scripting support the Cocoa way? Here's how to make your app scriptable via JSTalk:
Come up with an object model for your application, using standard Cocoa classes. In many cases this is already done, by virtue of writing a maintainable application.
Expose a "root" object to JSTalk, via Distributed Objects. In most cases, this will just be NSApplication. If you choose to use the JSTalk framework, it's just one line of code: [JSTalk listen];
Document what methods, properties, and objects you support. There's no magic xml files to fill out!
NSString *someContent = @"Hello World!"; NSString *path = @"/tmp/foo.txt"; [[someContent dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES];
And here is how it would normally look in a bridged scripting language:
var someContent = NSString.stringWithString_("Hello World!") var path = "/tmp/foo.txt" someContent.dataUsingEncoding_(NSUTF8StringEncoding).writeToFile_atomically_(path, true)
This is a valid script in JSTalk, but it doesn't look very nice. For instance, there are lots of underscores in the method names, and you don't get the nested message passing like you do in Objective-C. To fix this quandary, JSTalk adds a light preprocessor which will allow you to use Objective-C message syntax like so:
var someContent = @"Hello World!" var path = @"/tmp/foo.txt" [[someContent dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:true]
Here's an AppleScript example, for adding a new rectangle object to a sketch document:
tell application "Sketch" tell document 1 set o to make new box set width of o to 100 set height of o to 100 set stroke thickness of o to 10 end tell end tell
And here's how you do it with JSTalk, using a doctored version of Sketch(6 lines of code, + the JSTalk framework):
var sketch = [JSTalk application:"Sketch"]; var doc = [sketch orderedDocuments] var rectangle = [doc makeNewBox]; [rectangle setWidth:100]; [rectangle setHeight:100]; [rectangle setXPosition:100]; [rectangle setYPosition:100];
If you aren't a fan of the optional bracket syntax, you can also write the script this way:
var sketch = JSTalk.application_("Sketch"); var doc = sketch.orderedDocuments() var rectangle = doc.makeNewBox(); rectangle.setWidth_(100); rectangle.setHeight_(100); rectangle.setXPosition_(100); rectangle.setYPosition_(100);
Applications can also be scripted using Cocoa's Script Bridge class, SBApplication. Here's an example:
[[SBApplication application:"iChat"] setStatusMessage:"Happy (funball)"];
Although this is great to have, it's not the same as an application natively support JSTalk over DO. Anything more than simple tasks using SBApplication tends to be a little more than difficult.
Aka, loadable bundles which add functionality to JSTalk, via helper classes, wrappers, and categories.
JSTalk comes with some standard helper categories (which you can currently find in JSTalkExtras.m), but it will also look in your ~/Library/Application Support/JSTalk/Plug-ins/ folder, and load any .jstplugin bundles it sees. You can turn this off in your application if you don't like that idea, via [JSTalk setShouldLoadJSTPlugins:NO];
There are two examples with JSTalk, one that just adds a category cocoa's string class: - [NSString reversedString]. The other example is "FMDB.jstplugin", which loads the FMDB SQLite classes, for use in JSTalk. This allows you to use sqlite to create, insert, update, etc, sql tables from JSTalk.
Let us know by sending an email to firstname.lastname@example.org
- Developer mailing list: http://groups.google.com/group/jstalk-dev
- Bug reporting: http://jstalk.lighthouseapp.com/projects/26692-jstalk/
A user mailing list will pop up at some point, but we're not there yet.
- No PPC support. The main reason is I don't have a testable PPC box lying around, but in theory it should work.
The preprocessor isn't perfect, and it screws up on some code. For instance:
Doesn't preprocess correctly. To find out if your script is being preprocessed incorrectly, just use the Script->Preprocess menu item to see what it spits out.
$ git clone git://github.com/ccgus/jstalk.git
- Nicer editing features.
- A debugger would be killer.
As said earlier, JSTalk is a blend of existing technologies, and has very little original code in it. Here's what it uses: