Espresso

Action XML

Actions

Whether you create TextActions or FileActions using JavaScript actions or the Cocoa API, you will need to define the actions in XML. Both TextActions and FileActions use the same XML formatting and file naming rules.

There are three files you may need to edit:

Action definitions

A typical action XML file looks like this:

<?xml version="1.0"?>
<action-recipes>
	<action id="com.mydomain.actionID" category="categoryID/another.categoryID">
		<class>ExampleActionClass</class>
		<title>My Example Action</title>

		<language-context>html, xml</language-context>
		<syntax-context>tag</syntax-context>
		<when-disabled>hide</when-disabled>

		<key-equivalent>command control option shift a</key-equivalent>
		<text-trigger>trigger</text-trigger>

		<setup>
			<custom>Anything here</custom>
			<customArray>
				<array>
					<string>plist syntax is available for arrays and dictionaries</string>
				</array>
			</customArray>
		</setup>
	</action>
</action-recipes>

You can include as many <action> elements as you need. Note that files in TextActions can also contain snippets.

Your action's ID needs to be unique across all plug-ins, so we recommend using reverse domain syntax.

The category attribute allows you to specify where your action will be displayed. Category identifiers often have periods in them (like "actions.text.general"), and you can nest your action within submenus and or nested categories using slashes. If you need to organize your actions within a specific category, you can use a nonexistent category name that ends in a number to sort them on the fly. For instance, a common pattern is appending numerals:

category="actions.text.HTML/tea.zen/1"

<class> is the name of the Objective-C class that is responsible for this action's logic; see the Cocoa API for more info. If you are writing a JavaScript action, then you will use a <script> element instead.

<title> is an optional human-readable name for your action (which will show up in the Actions menu). We recommend using Localizable.strings instead.

<language-context> is an optional element that allows you to only enable your action in specific languages. For instance, in the example above, the action will only be active if the user is editing HTML or XML. You can figure out the string for a given language by looking at their root-level syntax zone. HTML's is "language-root.html" so its language-context is "html". JavaScript's is "language-root.js" so its language-context is "js", and so forth. (You can find bundled plug-in syntax zones here.)

<syntax-context> is an optional element that allows you to specify a selector that the syntax context must match for the action to be enabled. In the example above, the action will not be enabled unless the user's cursor is inside of an HTML or XML "tag" zone.

<when-disabled> is an optional element that can be either "show" or "hide" (defaults to "show"). If <when-disabled> is set to "hide", then the action will not be shown anywhere in the menus if it either does not match the specified language- or syntax-context or its canPerformWithContext method returns false.

<key-equivalent> is an optional element that allows you to specify a shortcut for your action. Shortcuts are specified using one or more modifier keys ("command", "control", "option", or "shift"), and then a letter or symbol (you can also use special keys, such as "enter", "delete", "escape", "arrow-up", and so forth). Note that if you use an upper-case letter, your shortcut will typically require use of the shift key whether or not you specify it explicitly.

<text-trigger> is an optional element that lets you specify a tab-completion for your action. In the example above, if the user typed "trigger" and hit tab, the action would trigger. You can additionally add a key-equivalent attribute to use a different completion key than tab. For instance, this would trigger the action when typing "id=":

<text-trigger key-equivalent="=">id</text-trigger>

<setup> is a special element that allows you to pass arbitrary information from your XML to your action logic. You can either use a custom named element to pass a string, or use plist formatting to pass arrays or dictionaries. Inside arrays and dictionaries, note that you must use a specific syntax:

<setup>
	<arrayName>
		<array>
			<string>A plist string</string>
			<real>1.2</real>
			<integer>5</integer>
			<true/>
		</array>
	</arrayName>
	<dictionaryName>
		<dict>
			<key>keyName</key>
			<string>Regular plist elements go here</string>
		</dict>
	</dictionaryName>
</setup>

Category definitions

Categories define groups and submenus for your plug-in actions in the Actions menu (or File ⟩ Actions menu, for FileActions). Categories are available globally, so if you want to insert your actions into the same menu as another plug-in, use their category IDs.

To define new categories, create a file whose name ends with Categories.xml. The basic contents of the file will look like this:

<?xml version="1.0"?>
<action-categories>
	<!-- All three types of categories -->
	<category id="mycategory.inline" show="inline"></category>
	<category id="mycategory.separated" show="inline separated"></category>
	<category id="mycategory.submenu" show="sub">
		<title>Custom Submenu</title>
	</category>
</action-categories>

The id attribute is used by action definitions to construct their menu location.

The show attribute allows you to specify how the category is displayed:

The <title> attribute specifies the name for submenu categories, and is optional. We recommend using Localizable.strings instead.

Sorting definitions

Sorting definitions allow you to change the order that your custom categories are displayed in (if you want them to display in an order other than alphabetical). Sorting definition files must have filenames that end with Sorting.xml, and their content looks like this:

<?xml version="1.0"?>
<action-sort-instructions>

	<sort-template>
		<selector>mycategory.separated</selector>
		<selector>mycategory.submenu</selector>
		<selector>mycategory.inline</selector>
	</sort-template>

</action-sort-instructions>

Using this sorting definition, actions in the "mycategory.separated" category will be displayed first, followed by the "mycategory.submenu" submenu, and lastly by the inline actions in "mycategory.inline". You can include multiple <sort-template> elements in the file.