What is osax?
The OSAX module provides an easy way to call scripting additions (a.k.a. OSAXen) from Ruby. It exports a single public class, ScriptingAddition, and two functions, osax and scripting_additions.
The ScriptingAddition class represents a single scripting addition. It is similar to an appscript application object, except that it defines commands for the specified scripting addition instead of the application's normal commands.
Once you've created a ScriptingAddition instance, you can invoke its commands in exactly the same way as you would call a scriptable application's commands in appscript.
For example:
require "osax"
sa = OSAX::ScriptingAddition.new("StandardAdditions")
sa.say("Hello world", :using=>"Victoria")
The default application commands (run, activate, quit, etc.) are also available; see the appscript manual for details on those.
By default, ScriptingAddition objects are targeted at the current application. You can obtain a ScriptingAddition object targeted at another application by calling one of its by... methods.
OSAX.scripting_additions
The scripting_additions function returns the names of all installed scripting additions:
require "osax"
p OSAX.scripting_additions
# Result: ["Digital Hub Scripting", "StandardAdditions", ...]
OSAX.osax
The osax function provides a convenient shortcut for creating new ScriptingAddition instances.
osax(name=nil, app_name=nil) -- convenience method for
creating a new ScriptingAddition instance
name : String | nil -- scripting addition's name
(nil = "StandardAdditions")
app_name : String | nil -- target application's name/path, or nil
for current application
Result : ScriptingAddition
For example:
require "osax"
sa = OSAX.osax
p sa
# Result: #<OSAX::ScriptingAddition
# name="StandardAdditions"
# target=AEM::Application.current>
In addition, the osax function accepts an application name as an optional second argument, allowing you to specify the application you want to handle the scripting addition's commands, e.g.:
OSAX.osax("StandardAdditions", "System Events")
is shorthand for:
OSAX::ScriptingAddition.new("StandardAdditions").by_name("System Events")
To specify applications by other means (e.g. URL), create a ScriptingAddition object first, then call the appropriate by... method.
For convenience, if both arguments are nil then a ScriptingAddition object for StandardAdditions is created and returned. This object is also cached internally for efficiency and returned as-is in subsequent calls; thus, for example:
sa = osax
sa.some_command
sa.another_command
could also be written as:
osax.some_command
osax.another_command
without the additional overhead of creating a new ScriptingAddition object each time.
OSAX::ScriptingAddition
ScriptingAddition -- represents a single scripting addition and its
target application
Constructors:
ScriptingAddition.new(name, terms=nil) -- make a ScriptingAddition
object for the specified scripting addition, targeted
at the current application
name: string -- a scripting addition's name,
e.g. "StandardAdditions"; basically its filename
minus the '.osax' suffix
terms : module or nil -- an optional terminology glue
module,as exported by Terminology.dump; if
given, ScriptingAddition will use this instead
of retrieving the terminology dynamically
Methods:
# Introspection:
commands -- returns names of all available commands
parameters(command_name) -- returns a command's parameter names
# Specifying a different target application:
# Each of the following methods returns a new ScriptingAddition
# instance targeted at the specified application. The arguments
# are the same as for the by_name, by_creator, etc. methods in
# appscript.
by_name(name) -- name or full path of application, e.g. "Finder"
by_creator(creator) -- four-character creator code, e.g. "ttxt"
by_id(id) -- bundle id, e.g. "com.apple.ical"
by_pid(pid) -- Unix process ID, e.g. 4005
by_url(url) -- eppc URL, e.g. "eppc://jukebox-mac.local/iTunes"
Examples
require "osax"
# Create a new ScriptingAddition object:
sa = OSAX.osax
# List all available commands:
p sa.commands
# Result: ["ASCII_character", "ASCII_number", "activate", ...]
# Call some commands:
sa.beep
p sa.path_to(:scripts_folder)
# Result: MacTypes::Alias.at("/Users/foo/Library/Scripts/")
p sa.display_dialog("Ruby says hello!",
:buttons=>["Hi!", "Howdy!", "Duuuude!"],
:default_button=>3)
# Result: {:button_returned=>"Howdy!"}
Notes
GUI interaction
When using scripting addition commands that require GUI access (e.g. display_dialog) targeted at the command-line Ruby interpreter, the osax module will automatically convert the non-GUI interpreter process into a full GUI process to allow these commands to operate correctly. If you want to avoid this, target these commands at a faceless GUI application such as System Events instead:
sa = OSAX.osax("StandardAdditions", "System Events")
sa.activate # give focus to System Events
p sa.display_dialog("Ruby says hello!",
:buttons=>["Hi!", "Howdy!", "Duuuude!"],
:default_button=>3)
# Result: {:button_returned=>"Duuuude!"}
64-bit limitations
The osax module currently only supports dynamic retrieval of scripting addition terminology when running in 32-bit processes. To use it in 64-bit processes, use the Terminology module's dump method to export a static terminology 'glue' module for the desired scripting addition (running it in a 32-bit process), then import that module and pass it as the second argument to the ScriptingAddition class's initialiser. For example, to export a glue module for Standard Additions:
require 'appscript'
Terminology.dump('/System/Library/ScriptingAdditions/StandardAdditions.osax',
'StandardAdditions', 'standard_additions.rb')
To create a new ScriptingAddition instance using the terminology provided by this glue module:
require 'osax'
require 'standard_additions'
sa = OSAX::ScriptingAddition.new('StandardAdditions', StandardAdditions)
Known problems
When using the osax module within RubyCocoa-based applications, avoid creating ScriptingAddition instances before the main event loop is started as this can result in the application behaving strangely (minimised windows don't expand correctly) due to a bug in OS X's OSAGetAppTerminology function.