You can currently extend Espresso in two ways:
Themes are normal CSS files, and mainly allow you to change the color and background color of text in the editor.
Sugars are the plugins that add support for new languages, actions, and CodeSense. Although a Sugar looks and acts like a special file in the Finder, it is actually just a folder with specially named XML files inside. You can examine the contents of any Sugar by right clicking it in the Finder and choosing Show Package Contents. This can be a great way to learn by example.
Espresso’s internal logic
Regardless of what you want to do with a custom Sugar, you need to know how Espresso interprets documents:
The text in a document is broken down into syntax zones based on regular expressions that are defined in a Sugar. Using those syntax zones, Espresso separates the document into logical chunks called Itemizers and colors the syntax zones using the active CSS theme. Itemizers are used to tell what code should be foldable and show up in the Navigator. As you edit the document, different actions and CodeSense will be available depending on the syntax zone the cursor is inside.
Many aspects of both Sugars and themes rely on CSS-like Selectors that leverage the syntax zones that define the basic parts of the document.
Although all of these things are defined in Sugars (except the CSS theme), they break down into several basic systems depending on how you want to extend Espresso:
- SyntaxThemes that define the coloring for all languages based on their syntax zones
- LanguageSugars that define the syntax zones and Itemizers for any given language
- CodeSense which provides context-sensitive auto-completions
In general, here is what Sugars can do:
- Syntaxes: syntaxes define a coding language using regular expressions, and a Sugar can do one or more of the following:
- define a new language
- add new definitions or replace existing definitions in a language defined in another Sugar
- include syntax definitions from another language (for instance, CSS inside <style> tags in HTML)
- CodeSense: CodeSense is what Espresso calls auto-complete, and a Sugar can do the following:
- create CodeSense definitions for a new language
- add new CodeSense definitions to an existing language
- define in what context certain completions should be used (based on the syntax definition of the language)
- Itemizers: itemizers build on the syntax definition to allow code folding and the Navigator to work
- Text Actions: a Text Action lives in the Actions menu, and is used to modify the contents of the active document
- File Actions: a File Action lives in the File→Actions menu, and is used to act on a folder or file
Espresso’s Sugar API is quite powerful, but there are some limitations to keep in mind while you’re imagining the possibilities:
- Text or file actions must be invoked by the user, either through a menu item, a keyboard shortcut, or an automatic completion. This means that your action cannot execute on its own based on something happening in Espresso (for instance, it’s not possible to do something to a file as a result of it being saved unless the user intentionally invokes your action after saving the file).
- Although text actions have quite a lot of power when it comes to modifying the contents of the active document, there is not currently any way to ask Espresso to execute tasks outside the file. For instance, there is no API for opening up a preview window and populating it with a URL.
- Creating custom interface elements is certainly possible if you code your actions in Objective-C, but adding or modifying interface within existing Espresso windows is not supported (aside from attaching custom sheets to the active window).
There may be other limitations within the API, but these are the ones that most often trip people up when they’re trying to figure out what they can accomplish. We’re always working to improve the Sugar API, as well, so some of these limitations may cease to exist down the road.
Since most of the files in an Espresso Sugar are XML, you must remember to properly escape the illegal characters &, <, and > either using character entities, or by wrapping the entire element’s contents in a CDATA block. For example:
<!-- This will prevent this file from loading! -->
<myelement>Remember that < & > are illegal characters</myelement>
<!--Either of these two options will work properly-->
<myelement>Escaping with character entities like &</myelement>
<myelement><![CDATA[Wrapping in a CDATA block: < & >]]></myelement>
If your Sugar is mysteriously failing to work, remember to check for illegal characters! It also might be worth running your XML files through an XML validator if they are not loading, because XML formatting is a lot more strict than HTML, and thus easier to mess up if you forget a closing tag or similar.
Also, remember that any changes you make to your Sugar’s XML will require you to restart Espresso to see the changes.