Espresso

JavaScript Actions

Actions

Espresso provides a JavaScript API that allows you to easily script text actions to make Espresso even more useful for your particular workflow.

Basic layout

JavaScript actions are made up of up to three parts:

  1. The XML definition that tells Espresso how to present the action to the user
  2. The JavaScript action file, which lives in the Scripts folder
  3. Optional additional JavaScript files to share logic between multiple actions using ScriptLibraries

Most of the things you can do with the Cocoa API are possible with JavaScript; notable exceptions are any actions that require custom GUI and FileActions. You can find an API reference here.

XML action definitions

JavaScript actions use the same XML syntax as all other actions, but instead of associating a <class> with the action, they have a <script> element:

<action id="com.macrabbit.tea-for-two.text-actions.move-line-up" category="menu.ids">
	<script>move_line.js</script>
	<key-equivalent>command control arrow-up</key-equivalent>
	<setup>
		<direction>up</direction>
	</setup>
</action>

The file referenced in the <script> element must be saved in the Scripts folder in your plug-in. Note that there are several elements you can use that are not shown in this example; see the Actions.xml documentation for details.

The contents of the <setup> element can be arbitrarily named elements that are strings, or other data formats using plist formatting.

JavaScript action syntax

Within your JavaScript action you will be provided with a root-level action object that you can use to create the logic for your action. The most basic actions will include a single function:

action.performWithContext = function(context, outError) {
	// Action logic here
	// Return true or false
};

The context parameter will be a TextActionContext object provided by Espresso for the current document. The outError parameter is currently a placeholder, but will likely be used by the system in future updates.

To access the contents of your action's <setup> element, you will use the action.setup object. For instance, the JavaScript for the above XML example might do something like this:

if (action.setup.direction == 'up') {
	// Move line up
}

The action.setup object is read-only.

In addition to performing your action with a given context, you can also specify custom logic to determine if your action applies to a particular context, or to give it a different title in different contexts. To do so, you will add two additional functions to your action object:

action.titleWithContext = function(context, outError) {
	// Return string representing new title, or null to use default
};

action.canPerformWithContext = function(context, outError) {
	// Return true or false
};

If you are using titleWithContext, you can additionally return a string formatted like @key to use the title associated with "key" in Localizable.strings. For instance, for the action above returning "@multiple" from the titleWithContext would use the *.title.multiple key:

"com.macrabbit.tea-for-two.text-actions.move-line-up.title" = "Move Line Up";
"com.macrabbit.tea-for-two.text-actions.move-line-up.title.multiple" = "Move Lines Up";

JavaScript Libraries

If you are coding more than one JavaScript action that shares similar logic, you can gather it all into a JavaScript library. To do so, create a new JS file in the top-level ScriptLibraries folder:

MyPlugIn.espressoplugin/ScriptLibraries/my_library.js

Inside of your library, you can create whatever functions and variables that you need, and then assign the functions you need access to the global library object:

var myFunction = function(text) {
	// Do stuff to text
	return text;
};

library.myFunction = myFunction;

Then in your JavaScript action code, load in your library and use it like so:

var extras = loadLibrary('my_library');

action.performWithContext = function(context, outError) {
	var selection = context.selectedRanges[0];
	var text = context.string.substringWithRange(selection);
	text = extras.myFunction(text);
	// Insert the modified text or similar
};