Last Updated: February 25, 2016
·
426
· brendanjcaffrey

Responding to AppleScript Commands in a RubyMotion OS X App

AppleScript is a great way to allow users to interface with your app and automate actions, but there isn't much out there on how to set it up in an Objective C/Cocoa app, let alone one written in RubyMotion. I spent a couple hours figuring it out, so I figured I'd document how to get it up and running here.

First off, create a new RubyMotion app: motion create sample --template=osx. Then, jump in and modify the Rakefile. Under Motion::Project::App.setup do |app|, add the following lines:

app.info_plist['NSAppleScriptEnabled'] = 'YES'
app.info_plist['OSAScriptingDefinition'] = 'scripting.sdef'

Now create a file called scripting.sdef under the resources/ directory, and paste the following into it: (note this is a heavily trimmed down version of a file from here.)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
        <xi:include href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite)"/>
  <suite name="Simple Scripting Verbs" code="SVrb" description="Terminology for the SimpleScriptingVerbs Sample.">
    <command name="do simple command" code="SVrbSimp" description="run a simple command with no parameters">
      <cocoa class="SimpleCommand"/>
      <result type="integer" description="returns the number seven"/>
    </command>
        </suite>
</dictionary>

Once you have that done, create a file under app/ called simple_command.rb. Throw this in there:

class SimpleCommand < NSScriptCommand
  def performDefaultImplementation
    puts 'Responding to simple command'
    NSNumber.numberWithInt(7)
  end
end

Once you have that, build your app with rake, and run this on the command line: osascript -e 'tell application "sample" to do simple command'. You should get the desired output of 7. It doesn't matter if you have the app running or not already. The app will be launched by the system if it's not already.

This is a simple example, but you can allow your users to do extremely powerful things by letting your app be scripted. To see more examples of what can be done, commands with arguments for instance, check out Apple's SimpleScriptingVerbs example.