Creating and using static glues

The SwiftAutomation framework includes a command line aeglue tool for generating static glue files. Glues enable you to control "AppleScriptable" applications using human-readable property and method names derived from their built-in terminology resources.

Generating a glue

For convenience, add the following shortcut to your ~/.bash_profile:

alias aeglue=/Library/Frameworks/SwiftAutomation.framework/Resources/bin/aeglue

To view the aeglue tool's full documentation:

aeglue -h

Glue files follow a standard NAMEGlue.swift naming convention, where NAME is the name of the glue's Application class. The following command generates a TextEditGlue.swift glue file in your current working directory:

aeglue TextEdit

If an identically named file already exists at the same location, aeglue will normally fail with a "path already exists" error. To overwrite the existing file with no warning, add an -r option:

aeglue -r TextEdit

To write the file to a different directory, use the -o option. For example, to create a new iTunesGlue.swift file on your desktop:

aeglue -o ~/Desktop TextEdit

Getting application documentation

In addition to generating the glue file, the aeglue tool also creates a NAMEGlue.swift.sdef file containing the application dictionary (interface documentation), reformatted for use with SwiftAutomation. For example, to view the TextEditGlue.swift terminology in Script Editor:

open -a 'Script Editor' TextEditGlue.swift.sdef

Refer to this documentation when using SwiftAutomation glues in your own code, as it shows element, property, command, etc. names as they appear in the generated glue classes. (Make sure Script Editor's dictionary viewer is set to the "AppleScript" language option for it to display correctly.)

Be aware that only 'keyword' definitions are displayed in Swift syntax; 'type' names are unchanged from their AppleScript representation, as are AppleScript terms and sample code that appear in descriptions. SDEF-based documentation is always written for AppleScript users, so unless the application developer provides external documentation for other programming languages some manual translation is required. Furthermore, most applications' SDEF documentation is far from exhaustive, and frequently lacks both detail and accuracy; for instance, the SDEF format doesn't descript precisely what types and combinations of parameters are/aren't accepted by each command, while the documented 'types' of properties, parameters, and return values may be incomplete or wrong. Supplementary documentation, example code, AppleScript user forums, educated guesswork, and trial-and-error experimentation may also be required.

The bundled command translation tool can also help when the correct AppleScript syntax for the desired command is already known, and all that is needed is some assistance in writing its Swift equivalent.

How glues are structured

Each glue file contains the following classes:

aeglue automatically disambiguates each glue's class names by adding a three-letter PREFIX derived from the application's name (e.g. TextEditTED). Thus the standard TextEditGlue.swift glue defines TextEdit, TEDItem, TEDItems, TEDInsertion, TEDRoot, and TEDSymbol classes, while FinderGlue.swift defines Finder, FINItem, FINItems, and so on. (Different prefixes allow multiple glues to be imported into a program without the need to fully qualify all references to those classes with the full glue name, i.e. TEDItem is easier to write than TextEditGlue.Item.)

Each glue also defines:

Glue files may also include custom typealias, enum, and struct definitions that improve integration between Swift and Apple event type systems. Chapter 10 explains how to add and use these features.

Customizing glues

If the default three-letter prefix is unsuitable for use, use the -p option to specify a custom prefix. The following command creates a new TextEditGlue.swift file that uses the class name prefix TE:

aeglue -p TE TextEdit

For compatibility, aeglue normally sends the application an ascr/gdte event to retrieve its terminology in AETE format. However, some Carbon-based applications (e.g. Finder) may have buggy ascr/gdte event handlers that return Cocoa Scripting's default terminology instead of the application's own. To work around this, add an -S option to retrieve the terminology in SDEF format instead:

aeglue -S Finder

The -S option may be quicker when generating glues for CocoaScripting-based apps which already contain SDEF resources. When using the -S option to work around buggy ascr/gdte event handlers in AETE-based Carbon apps, be aware that macOS's AETE-to-SDEF converter is not 100% reliable. For example, four-char code strings containing non-printing characters fail to appear in the generated SDEF XML, in which case aeglue will warn of their omission and you'll have to correct the glue files manually or use SwiftAutomation's lower-level OSType-based APIs in order to access the affected objects/commands.

Tip: When getting started, a quick way to generate standard glues for all scriptable applications in /Applications, including those in subfolders, is to run the following commands:

mkdir AllGlues && cd AllGlues && aeglue -S /Applications/*.app /Applications/*/*.app

aeglue will log error messages for problematic applications (e.g. those without dictionaries or whose dictionaries contain significant flaws). Any glues that are unsatisfactory or require extra customization can then be manually regenerated one at a time with the appropriate options.

Using a glue

To include the generated glue file in your project:

  1. Right-click in the Project Navigator pane of the Xcode project window, and select Add Files to PROJECT... from the contextual menu.

  2. Select the generated glue file (e.g. TextEditGlue.swift) and click Add.

  3. In the following sheet, check the "Copy items into destination group's folder", and click Add.

Subsequent code examples in this manual assume a standard glue file has already been generated and imported; e.g. TextEdit-based examples use a TextEdit glue with the prefix TED, Finder-based examples use a Finder glue with the prefix FIN, etc.

How keywords are converted

Because scriptable applications' terminology resources supply class, property, command, etc. names in AppleScript keyword format, aeglue must convert these terms to valid Swift identifiers when generating the glue file and accompanying .sdef documentation. For reference, here are the main conversion rules used:

Some rarely encountered corner cases are dealt with by the following conversion rules: