Action XML Definitions
All Espresso actions are made up of two parts:
- An action XML definition that tells Espresso the action’s name, menu location, and other information about when it can be used
- The code that performs the action logic
For a typical Sugar, the XML is stored in the Sugar’s TextActions folder (or FileActions if it’s for a file action) and the code is an Objective-C class compiled and bundled with the Sugar. Custom TEA actions, on the other hand, have their action definition stored either in the user’s Support/TextActions folder (see Support folder for more info) or – if included as part of a Sugar – in the standard Sugar TextActions folder.
In either case, TEA actions follow the same basic syntax as their Espresso counterparts but with some special, TEA-specific elements. Which action syntax you use will depend on whether you are using a Python script (including TEA generic actions) or a shell script.
Python action syntax
As per the Espresso documentation on TextActions, TextActions are stored in a file (typically called Actions.xml, although the name doesn’t matter). For a custom user action, the following example code would likely be saved here:
~/Library/Application Support/Espresso/Support/TextActions/Actions.xml
Although this example only contains a single action, you can of course have as many actions per XML file as you want; just nest them all within the <action-recipes>
tag.
<action-recipes>
<action id="com.yourdomain.InsertSnippet.copyright" category="category.id">
<class>TEAforEspresso</class>
<title>Insert Copyright Statement</title>
<text-trigger>copy</text-trigger>
<key-equivalent>cmd option C</key-equivalent>
<setup>
<action>insert_snippet</action>
<options>
<dict>
<key>default</key>
<string><p>&copy; 2009 Your Name</p></string>
</dict>
</options>
<syntax-context>html, html *</syntax-context>
<selection-context>none</selection-context>
</setup>
</action>
</action-recipes>
Standard Espresso elements and attributes
<action>
attributes
- id
- The unique identifier for this action; convention is to use reverse domain name formatting (
com.yourdomain.typeofaction.uniqueIdentifier
). - category
- The category ID that defines where in the Actions menu your action is placed. You can add a slash and another category ID to nest the action, as well. For instance,
category="actions.text.HTML/actions.snippets"
would place the action in Actions → HTML → Snippets (assuming you have the HTMLBundle.sugar installed, which defines the actions.snippets category). You can also usecategory="hidden"
to hide your action from the Actions menu. See the Espresso action documentation for more info about defining categories, sorting, and more.
Standard elements
- class
- This defines what Objective-C class your action should call. For Python actions it will always be
TEAforEspresso
. For shell scripts, you will need to useTEALoader
. - title
- The title is what will be shown in the Actions menu.
- text-trigger
- If you set a text-trigger for your action, then when that text is typed in Espresso your action will be triggered. In the example above, typing
copy
and hitting tab would cause the action to be executed. You may also use the optionalkey-equivalent
attribute to set which key triggers the action. For instance, if you used<text-trigger key-equivalent=".">copy</text-trigger>
then the action would be triggered when you typedcopy.
(hitting tab would not longer be necessary). - key-equivalent
- Not to be confused with the text-trigger attribute of the same name, this element allows you to set a shortcut for accessing your action. In the example above, the action would be triggered by holding down
command-option-shift-C
(shift is not specified because the letter “C” is capitalized; to remove shift, you would lowercase the “C”). Available modifiers include:cmd
(command),control
, andoption
with shift being available based on which character you choose. You can also use keys such asenter
ortab
instead of a character.
TEA-specific elements
- setup
- All of TEA’s elements must be nested within the setup tag. The setup tag allows Espresso to pass arbitrary arguments on to Sugars, and TEA uses a specific set of elements for its contents.
Universally available elements
All TEA actions (including shell scripts) have the following elements available to them.
- syntax-context
- Passing a syntax selector string here will cause the action to only be available when that syntax is active. In the example above, the action would be disabled unless the user was editing in an HTML zone or one of its children. See the Espresso selectors documentation for more details about types of selectors available.
- selection-context
- The selection-context element allows you to specify under which conditions your action is available based on what the user has selected. Valid options include
none
(no selection required),one
(single selection required),one+
(one or more selections required), andmultiple
(multiple selections required).
TEA currently first parses syntax-context (if the element exists) and then selection-context (if it exists). If either of them fails, the action will be disabled. If neither is present, the action will always be available.
TEAforEspresso class elements
- action (required)
- This is the only required element for the TEAforEspresso class, and tells TEA which Python action to use. In the example above, we’re using the insert_snippet action from the generic action API. The name you use should be the name of the Python file containing the action without the extension. So if you have created
my_custom_action.py
your action element will look like this:<action>my_custom_action</action>
. - options
-
The options element must contain a dictionary using Apple’s plist formatting, which is passed on to the Python action as keyword arguments. Different generic actions require and support different elements in the options dictionary, and your custom actions can include any keyword-argument for the options dictionary that you desire.
A plist dictionary contains a root
<dict>
element with nested keys and values. A key is defined with the key element:<key>some_key</key>
followed by a value which can be any valid plist element:<string>
,<integer>
,<true/>
,<false/>
,<dict>
,<array>
, etc.One important thing to note is that you cannot include
<
or&
in XML. You can either go the route of the example above and encode them with HTML entities, or you can use a CDATA block (which is typically easier to read):<string><![CDATA[<p>© 2009 Your Name</p>]]></string>
.