<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">

    <title type="text">Espresso Wiki</title>
    <subtitle type="text">Espresso Wiki</subtitle>
    <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/" />
    <link rel="self" type="application/atom+xml" href="http://wiki.macrabbit.com/index/Special:Recentchanges_Atom" />
    <updated>2010-08-04T22:19:17Z</updated>
    <rights>Copyright (c) 2008, info@macrabbit.com</rights>
    <generator uri="http://expressionengine.com/" version="1.6.5">ExpressionEngine</generator>
    <id>tag:wiki.macrabbit.com,2010:08:04:wiki</id>


    <entry>
      <title>Syntaxes</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/Syntaxes/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:Syntaxes/5.152</id>
      <published>2010-08-04T22:19:17Z</published>
      <updated>2010-08-04T22:19:17Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>Syntax definitions (&#8220;syntaxes&#8221; henceforth) add structural information to text. Formats like <span class="caps">HTML</span>, <span class="caps">CSS</span>, <span class="caps">XML</span>, JavaScript, etc. are merely text until something tells Espresso that certain keywords, constructs and pieces of text have special meaning. Syntaxes define that extra information using flexible syntax rules.</p>

	<h2>Big Picture</h2>

	<p>Before going into details about how to make a syntax, it&#8217;s important to realize how Espresso loads and uses syntaxes.</p>

	<p>(sugar collection) &gt; (detected xml syntaxes) + (detected xml syntax injections) &gt; syntax compiling and injecting &gt; (pool with syntaxes)</p>

	<ol>
		<li>First, Espresso collects all the sugars (see <a href="http://wiki.macrabbit.com/index/SugarBasics/" title="SugarBasics">SugarBasics</a>) it can find.</li>
		<li>Syntaxes and syntax injections (more info on injections later) are collected from the sugars. Each syntax has a root identifier, which is used to reference it for <a href="http://wiki.macrabbit.com/index/Languages/" title="Languages">Languages</a>, to include it in other syntaxes, etc.</li>
		<li>Once all syntaxes and injections have been detected, the compiling and injecting process starts. This involves a few steps: syntax injections are prepared by cross-injecting them with other injections &#8211; syntaxes are compiled for internal usage &#8211; all prepared injections are injected into compiled syntaxes.</li>
		<li>Espresso now has one pool of syntaxes ready to go.</li>
	</ol>

	<h2>Compatibility</h2>

	<p>Espresso syntaxes are similar to TextMate language definitions, so anyone with previous experience there should feel right at home. To convert a .tmLanguage to the Espresso <span class="caps">XML</span> format, you can use the <a href="http://macrabbit.com/espresso/EspressoSyntaxTool.zip">Espresso Syntax Tool</a>.</p>

	<h2>Composition of a Syntax</h2>

	<p>Espresso syntaxes are defined using <span class="caps">XML</span> files. The basic structure looks as follows:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?xml&nbsp;version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0"</span><span style="color: #0000BB">?&gt;<br /></span><span style="color: #007700">&lt;</span><span style="color: #0000BB">syntax&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"root.type.identifier"</span><span style="color: #007700">&gt;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">Syntax&nbsp;zones&nbsp;go&nbsp;into&nbsp;the&nbsp;</span><span style="color: #007700">&lt;</span><span style="color: #0000BB">zones</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">tag&nbsp;</span><span style="color: #007700">--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">zones</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">zones</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">optional</span><span style="color: #007700">)&nbsp;&lt;</span><span style="color: #0000BB">library</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">tag&nbsp;contains&nbsp;collections&nbsp;of&nbsp;reusable&nbsp;zones&nbsp;</span><span style="color: #007700">--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">library</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">library</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&lt;/</span><span style="color: #0000BB">syntax</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>The key piece in this <span class="caps">XML</span> is the name of the syntax. This identifier should be unique for each syntax in Espresso, so it&#8217;s a good idea to prefix it with your domain name or something similar. Syntaxes shipping with Espresso reserve the prefix <strong>espresso.default</strong>.</p>

	<p>In the following sections, we&#8217;ll have a look at what the &lt;zones&gt; and &lt;library&gt; tags should contain.</p>

	<h2>Syntax Zones and Rules</h2>

	<p>Espresso has a syntax core based on regular expressions (&#8220;regexes&#8221; henceforth). When all syntax rules have been evaluated for the entire text, the result is a hierarchical structure that contains syntax zones mapping to parts of the text. Each of those zones has a type identifier that describes what it is, and can contain more syntax zones within.</p>

	<p>To understand how the core builds this tree, let&#8217;s start with the notion of a syntax context. This context maintains a list of all the currently active syntax rules: the rules that can be evaluated to find a new piece of structure. The initial context consists of the rules defined in the root of a grammar, which comes down to all the rules in the &lt;zones&gt; tag.</p>

	<p>There are 4 rule types that can be defined: start/end, match, include and cut-off. Each has a specific purpose and <span class="caps">XML</span> syntax. For performance reasons, the syntax core has one limitation that you must absolutely remember: <strong>syntax regular expressions only search in a single line of the text</strong>.</p>

	<h4>Start/End Rules</h4>

	<p>This rule produces a syntax zone which begins with a piece of text matching the regex from the starts-with tag and ends with a piece of text matching the ends-with regex. When this rule becomes active (when a start match is found), the new syntax context comprises the syntax rules defined in the &lt;subzones&gt; tag. Once the end expression is encountered, the old syntax context is restored again.</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">zone&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"zone.identifier"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">starts</span><span style="color: #007700">-</span><span style="color: #0000BB">with</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">regular&nbsp;expression&nbsp;here</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">starts</span><span style="color: #007700">-</span><span style="color: #0000BB">with</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">ends</span><span style="color: #007700">-</span><span style="color: #0000BB">with</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">regular&nbsp;expression&nbsp;here</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">ends</span><span style="color: #007700">-</span><span style="color: #0000BB">with</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">subzones</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">subzones</span><span style="color: #007700">&gt;<br />&lt;/</span><span style="color: #0000BB">zone</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<h4>Match Rules</h4>

	<p>For simple structures like keywords, it&#8217;s sufficient to match a single piece of text. The syntax looks as follows:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">zone&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"zone.identifier"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">regular&nbsp;expression&nbsp;here</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;<br />&lt;/</span><span style="color: #0000BB">zone</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<h4>Include Rules</h4>

	<p>For more complex syntaxes, it can be handy to use the rules of other syntaxes (for <span class="caps">CSS</span> embedded in <span class="caps">HTML</span>, for example) or to reuse sets of rules. Include rules address both, and come in 3 forms:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;include&nbsp;</span><span style="color: #0000BB">syntax</span><span style="color: #007700">=</span><span style="color: #DD0000">"syntax.identifier"</span><span style="color: #007700">/&gt;<br />&lt;include&nbsp;</span><span style="color: #0000BB">syntax</span><span style="color: #007700">=</span><span style="color: #DD0000">"self"</span><span style="color: #007700">/&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>This rule collects all the root rules (inside the &lt;zones&gt; tag) of the syntax named syntax.identifier, and inserts them in place of the include rule. To recursively include the current syntax&#8217;s root rules (useful for languages like <span class="caps">XML</span>), use &#8220;self&#8221; as the attribute value.</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;include&nbsp;</span><span style="color: #0000BB">collection</span><span style="color: #007700">=</span><span style="color: #DD0000">"collection.identifier"</span><span style="color: #007700">/&gt;<br />&lt;include&nbsp;</span><span style="color: #0000BB">syntax</span><span style="color: #007700">=</span><span style="color: #DD0000">"syntax.identifier"&nbsp;</span><span style="color: #0000BB">collection</span><span style="color: #007700">=</span><span style="color: #DD0000">"collection.identifier"</span><span style="color: #007700">/&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>In this form, the rule collects all zones from the collection named collection.identifier. Without a &#8220;syntax&#8221; attribute, the collection is assumed to be in the syntax of the include rule.</p>

	<h4>Cut-off Rules</h4>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">cut</span><span style="color: #007700">-</span><span style="color: #0000BB">off</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">regular&nbsp;expression&nbsp;here</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;<br />&lt;/</span><span style="color: #0000BB">cut</span><span style="color: #007700">-</span><span style="color: #0000BB">off</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>This rule is a processing instruction, rather than a true syntax rule, since it never generates a syntax zone. Normally, the regexes in the various rules are searched in the rest of the current line. Some situations may arise where a search expression could become unwieldy trying to define the cut-off point for the search.</p>

	<p>Even though it&#8217;s often possible to use regex lookahead for these cases, much more convenient is the ability to say &#8220;no search expressions for rules in the current context can go beyond this point&#8221;. When the cut-off expression is found in the text, expressions for all real rules cannot go beyond the location of the cut-off.</p>

	<p>The usefulness of cut-offs becomes apparent with large syntaxes and the use of syntax injections (see further). For example, the <span class="caps">HTML</span> syntax uses cut-offs to make sure embedded <span class="caps">CSS</span> doesn&#8217;t go beyond its closing &lt;/style&gt; tag. Instead making the <span class="caps">CSS</span> syntax explicitly aware of this by modifying the rule regexes, a simple external cut-off has the same result. Because the <span class="caps">CSS</span> syntax should require no knowledge about languages it&#8217;s embedded in, this is clearly a preferable solution to a pure regex-based approach.</p>

	<p><strong>Important</strong>: a cut-off rule only has an effect on the rules in the same context, not in higher or deeper contexts.</p>

	<h4>Order and Precedence</h4>

	<p>When looking for a new syntax zone, the syntax core evaluates all rules in the order they&#8217;re written in the syntax definition. The rule that has the earliest occurrence in the text is then used to create a new syntax zone.</p>

	<p>Start or match expressions have no precedence over others in the same context; they are simply evaluated in their source order. However, in case an <strong>end</strong> expression starts at the same point as a begin or match expression, the <strong>end</strong> expression takes precedence. Do note that this is only the case for occurrences at the exact same position. A match expression of rule A that begins before the end expression of rule B will always be chosen over the end of B, even if A&#8217;s match extends far past B&#8217;s end.</p>

	<h4>Rule Captures</h4>

	<p>Now that we discussed the basic workings of syntax rules, let&#8217;s look at some details. Because expressions for syntax rules are often composed of several semantic parts (for example, a <span class="caps">HTML</span> &lt;tag&gt; has at least angle brackets and the actual tag name), &lt;expression&gt; tags inside &lt;zone&gt; tags can be combined with &lt;capture&gt; tags to easily define subzones based on captures in the regex. An example:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">zone&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"a.surrounded"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;(+)(</span><span style="color: #0000BB">a</span><span style="color: #007700">*)(+)&lt;/</span><span style="color: #0000BB">expression</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">capture&nbsp;number</span><span style="color: #007700">=</span><span style="color: #DD0000">"1"&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">=</span><span style="color: #DD0000">"plus"</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">capture&nbsp;number</span><span style="color: #007700">=</span><span style="color: #DD0000">"2"&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">=</span><span style="color: #DD0000">"multiple.a"</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">capture&nbsp;number</span><span style="color: #007700">=</span><span style="color: #DD0000">"3"&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">=</span><span style="color: #DD0000">"plus"</span><span style="color: #007700">/&gt;<br />&lt;/</span><span style="color: #0000BB">zone</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>Instead of simply generating a syntax zone with identifier &#8220;a.surrounded&#8221;, the capture definitions insert subzones for &#8220;plus&#8221;, &#8220;multiple.a&#8221; and &#8220;plus&#8221; inside the &#8220;a.surrounded&#8221; zone.</p>

	<h2>Syntax Rule Libraries</h2>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">library</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">collection&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"collection.identifier"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">collection</span><span style="color: #007700">&gt;<br />&lt;/</span><span style="color: #0000BB">library</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>The optional zone library in a syntax can define several zone collections, which can then be referenced using include rules. Each collection needs to specify a name, and can contain the same elements as the &lt;zones&gt; tag.</p>

	<h2>Syntax Injections</h2>

	<p>To avoid unnecessary dependencies between syntaxes and to prevent duplication, Espresso offers syntax injections. Injections are best compared to rule collections, except that they&#8217;re included automatically by the syntax core. The basic structure of a syntax injection looks as follows:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?xml&nbsp;version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0"&nbsp;</span><span style="color: #0000BB">encoding</span><span style="color: #007700">=</span><span style="color: #DD0000">"UTF-8"</span><span style="color: #0000BB">?&gt;<br /></span><span style="color: #007700">&lt;</span><span style="color: #0000BB">injections</span><span style="color: #007700">&gt;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">injection&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"injection.identifier"&nbsp;</span><span style="color: #0000BB">selector</span><span style="color: #007700">=</span><span style="color: #DD0000">"..."&nbsp;</span><span style="color: #0000BB">action</span><span style="color: #007700">=</span><span style="color: #DD0000">"..."</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">injection</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&lt;/</span><span style="color: #0000BB">injections</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>Each &lt;injection&gt; element contains a list of rules that need to be injected. The allowed elements are the same for collections, so they won&#8217;t be repeated here. Each syntax injection must have a unique name (once again, the espresso.default prefix is reserved).</p>

	<p>The selector attribute specifies which syntax rules have to be targeted for this particular injection. Note that the selector is interpreted against syntax rules in the syntax definitions, not against the resulting syntax zones. Additionally, collections can not be targeted (they serve mainly as syntactic sugar to improve the organization in the <span class="caps">XML</span>).</p>

	<p>For all targeted rules, an action is performed with the rules in the injection body. The value can be any of these:</p>

	<ul>
		<li>replace-target: replace the target rule with the injection rules</li>
		<li>replace-children: replace the target&#8217;s subzone rules with the injection rules</li>
		<li>attach-before-target: insert the injection rules before the target rule, so inside the parent rule</li>
		<li>attach-after-target: same as before, but after the target rule</li>
		<li>insert-before-children: insert the injection rules into the target rule, before the first subzone rule</li>
		<li>insert-after-children: same as before, but after the last subzone rule</li>
	</ul>

	<p>Syntax injections have no enforced relative order, but any replace-target action will neutralize any subzone-related actions for the same target rule.</p>
      ]]></content>
    </entry>

    <entry>
      <title>Types of Custom Actions</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/Types_of_Custom_Actions/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:Types of Custom Actions/28.151</id>
      <published>2010-07-22T22:35:50Z</published>
      <updated>2010-07-22T22:35:50Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>Thanks to the flexibility of Espresso&#8217;s sugar system, there are several types of custom actions:</p>

	<h2>Objective-C actions</h2>

	<p>This is the most direct way to do things, and preferable if you are comfortable with Objective-C. You&#8217;ll code custom Objective-C classes (that use the right methods so Espresso can interact with them), and then tell Espresso which class to link to which menu item using <span class="caps">XML</span>. To get started see the <a href="http://wiki.macrabbit.com/index/Intro_to_Cocoa_Sugars/" title="Intro_to_Cocoa_Sugars">Intro to Cocoa Sugars</a>.</p>

	<p>The remaining types of custom actions all use pre-defined Objective-C classes that allow you to interact with the Espresso <span class="caps">API</span> using other languages.</p>

	<h2>Javascript actions</h2>

	<p><a href="http://onecrayon.com/spice/">Spice.sugar</a> provides full access to the Objective-C <span class="caps">API</span> using <a href="http://inexdo.com/JSCocoa"><span class="caps">JSC</span>ocoa</a> (a Javascript to Objective-C bridge). The main benefits to going this route are:</p>

	<ol>
		<li>No need to relaunch Espresso to test changes (just save the Javascript file and run the action again)</li>
		<li>If you aren&#8217;t comfortable with converting Objective-C objects and methods into Javascript via <span class="caps">JSC</span>ocoa, Spice offers a reasonably robust collection of native Javascript classes that allow you to interact with Espresso without worrying about how the <span class="caps">JSC</span>ocoa bridge works. This is essentially just trading one <span class="caps">API</span> for another, but can simplify the code for most text actions quite a bit (and additionally doesn&#8217;t require understanding how to translate Objective-C objects and methods into Javascript, although learning that is straight-forward if you need it).</li>
	</ol>

	<p>The main downside is that the users of your Sugar will need to install Spice.sugar before your actions will work.</p>

	<p>For more information about developing Espresso actions using Spice, see the <a href="http://onecrayon.com/spice/docs/">Spice documentation</a>.</p>

	<h2>Python actions</h2>

	<p><span class="caps">TEA</span> for Espresso is a Sugar that is bundled with Espresso.  <span class="caps">TEA</span> leverages the <a href="http://pyobjc.sourceforge.net/">PyObjC</a> bridge to allow you to work directly with the Objective-C <span class="caps">API</span> using Python. This has the same trade-offs as working with Javascript, mostly, with some differences:</p>

	<ol>
		<li><span class="caps">TEA</span> offers no utility classes, so figuring out the basics of the <span class="caps">API</span> and how the PyObjC bridge works is required (although there&#8217;s a good set of utility functions for common tasks).</li>
		<li>You have to relaunch Espresso to see your changes in an action (although you do miss the step of needing to compile them from plain Objective-C actions)</li>
		<li>The first <span class="caps">TEA</span> action to be invoked will take a couple seconds while the Python interpreter fires up.</li>
	</ol>

	<p>The main benefit is that <span class="caps">TEA</span> has been bundled with Espresso since version 1.0, so your Sugar will work for anyone with an up-to-date copy of Espresso.  You can find more information about Python actions in the <a href="http://onecrayon.com/tea/docs/"><span class="caps">TEA</span> documentation</a>.</p>

	<h2>Shell script languages</h2>

	<p>Any language you can execute on the command-line (<span class="caps">PHP</span>, Ruby, etc.) can be used for a custom action. This is very similar to Textmate bundle actions. You&#8217;ll get the contents of the document (or the line, or word, or whatever else you specify) in standard input along with numerous environment variables containing info about the document and so forth. What you send to standard output gets inserted into the document.</p>

	<p>This is often the quickest way to get an action up and running (fewest new things to learn; just the environment variables and <span class="caps">XML</span> action definitions), but has the downside of not having any way to do more than text input/output. Additionally, standard input has a memory limit to it, so if you are trying to process a large document you may not actually get all of the text. Of course, if all you need is to invoke a shell action for the document&#8217;s path or whatever, this is <span class="caps">WAY</span> easier than learning another language or <span class="caps">API</span>.  Running shell scripts is also possible thanks to <span class="caps">TEA</span> for Espresso: <a href="http://onecrayon.com/tea/docs/shell-scripts/">shell scripts in the <span class="caps">TEA</span> documentation</a>.</p>
      ]]></content>
    </entry>

    <entry>
      <title>CocoaSugars</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/CocoaSugars/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:CocoaSugars/9.150</id>
      <published>2010-07-22T22:18:42Z</published>
      <updated>2010-07-22T22:18:42Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>While Espresso&#8217;s language system can easily be extended using only <span class="caps">XML</span> (<a href="http://wiki.macrabbit.com/index/SugarBasics/" title="SugarBasics">SugarBasics</a>), sugars can also contain compiled Cocoa code. This gives you a rich <span class="caps">API</span> with extensive access to Espresso&#8217;s syntax metadata model. Currently, you can create the following Cocoa extensions:</p>

	<ul>
		<li>Custom &#8220;items&#8221;, used in the <a href="http://wiki.macrabbit.com/index/Itemizers/" title="Itemizers">Itemizers</a>. Together with the <span class="caps">XML</span> itemizer definitions, this allows you to create Navigator listings that work perfectly with a specific language.</li>
		<li><a href="http://wiki.macrabbit.com/index/TextActions/" title="TextActions">TextActions</a>. Get access to a document&#8217;s text along with its syntax and itemizer metadata and create awesome transformations and functionality.</li>
		<li><a href="http://wiki.macrabbit.com/index/FileActions/" title="FileActions">FileActions</a>. Create custom actions for local and remote file listings.</li>
	</ul>

	<p>If you are not familiar or comfortable with Cocoa bundles yet, you may find the <a href="http://wiki.macrabbit.com/index/Intro_to_Cocoa_Sugars/" title="Intro_to_Cocoa_Sugars">Intro to Cocoa Sugars</a> and <a href="http://wiki.macrabbit.com/index/Espresso_Cocoa_API/" title="Espresso_Cocoa_API">Espresso Cocoa <span class="caps">API</span></a> useful places to start.  If you are interested in coding Espresso actions but disinclined to work in Objective-C, see <a href="http://wiki.macrabbit.com/index/Types_of_Custom_Actions/" title="Types_of_Custom_Actions">Types of Custom Actions</a>.  Otherwise, the resources below should give you a place to start.</p>

	<h2>Headers</h2>

	<p>The Espresso <span class="caps">API</span>&#8217;s headers come with every build of Espresso, and are located in Espresso.app/Contents/Headers. The best way to learn about the possibilities is to look at these documented headers.</p>

	<h2>Example Sugar</h2>

	<p>Right now, the easiest way to dig in and learn more about the Cocoa Sugar <span class="caps">API</span> is to download the example. You need Apple&#8217;s Xcode Tools installed to compile.</p>

	<p>1. Download the <a href="http://macrabbit.com/espresso/ExampleCocoaSugar.zip">Example Cocoa Sugar</a>.<br />
2. Open Example Sugar.xcodeproj.<br />
3. Open the project inspector and set the <span class="caps">ESPRESSO</span>_PATH variable to wherever Espresso is installed. (Do this by choosing Project &gt; Edit Project Settings in Xcode, then going to the Build tab and finding the <span class="caps">ESPRESSO</span>_PATH setting all the way down the list).<br />
4. Optionally change the sugar&#8217;s product name to something of your own.<br />
5. Compile!<br />
6. Install into ~/Library/Application Support/Espresso/Sugars<br />
7. Relaunch Espresso to test</p>

	<h2>Example Sugar (Python flavor)</h2>

	<p>If for whatever reason you&#8217;re interested in coding in Python rather than Objective-C, it&#8217;s possible to code Sugars without ever touching Xcode.  Here&#8217;s the steps:</p>

	<ol>
		<li>Download the <a href="http://onecrayon.com/downloads/PyExampleSugar.zip">PyExampleSugar</a> (a direct port of the Cocoa Example Sugar above into Python)</li>
		<li>Open up Terminal, navigate to the PyExampleSugar directory and run <code>python setup.py py2app</code> (see the setup.py file for how to create a development version you can edit without recompiling)</li>
		<li>Move the newly created ExampleSugar.sugar out of the ./dist directory and into ~/Library/Application Support/Espresso/Sugars</li>
		<li>Relaunch Espresso to test</li>
	</ol>

	<p>For more detailed information, see <a href="http://wiki.macrabbit.com/index/CocoaSugars_in_Python/" title="CocoaSugars_in_Python">CocoaSugars in Python</a>.</p>
      ]]></content>
    </entry>

    <entry>
      <title>SugarBasics</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/SugarBasics/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:SugarBasics/6.149</id>
      <published>2010-07-22T22:16:25Z</published>
      <updated>2010-07-22T22:16:25Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<h2>What&#8217;s possible</h2>

	<p>Although Espresso is a powerful editor, you may come across areas that you think could improve. Perhaps it doesn&#8217;t support your favorite coding language, you wish there was a way to delete the current line with a single keystroke, or you need the auto-complete to offer completions for a <span class="caps">PHP</span> framework that you use all the time.  If you want to extend the capabilities of editor for something like this, then you will be creating a Sugar. Sugars are plugins that Espresso loads when it launches that extend its capabilities.</p>

	<p>In general, here is what Sugars can do:</p>

	<ul>
		<li><strong>Syntaxes</strong>: syntaxes define a coding language using regular expressions, and a Sugar can do one or more of the following:
	<ul>
		<li>define a new language</li>
		<li>add new definitions or replace existing definitions in a language defined in another Sugar</li>
		<li>include syntax definitions from another language (for instance, <span class="caps">CSS</span> inside &lt;script&gt; tags in <span class="caps">HTML</span>)</li>
	</ul></li>
		<li><strong>CodeSense</strong>: CodeSense is what Espresso calls auto-complete, and a sugar can do the following:
	<ul>
		<li>create CodeSense definitions for a new language</li>
		<li>add new CodeSense definitions to an existing language</li>
		<li>define in what context certain completions should be used (based on the syntax definition of the language)</li>
	</ul></li>
		<li><strong>Itemizers</strong>: itemizers build on the syntax definition to allow code folding and the Navigator to work</li>
		<li><strong>Text Actions</strong>: a Text Action lives in the Actions menu, and is used to modify the contents of the active document</li>
		<li><strong>File Actions</strong>: a File Action lives in the File&rarr;Actions menu, and is used to do something with a folder or file</li>
	</ul>

	<p>Unless you need advanced itemizers, text actions, or file actions, your Sugar will be entirely authored in <span class="caps">XML</span>. See below for links to documentation for each feature.</p>

	<h2>Limitations</h2>

	<p>Espresso&#8217;s Sugar <span class="caps">API</span> is quite powerful, but there are some limitations to keep in mind while you&#8217;re imagining the possibilities:</p>

	<ul>
		<li>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&#8217;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).</li>
		<li>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 <span class="caps">API</span> currently for opening up a preview window and populating it with a <span class="caps">URL</span> or file.</li>
		<li>Creating custom interface elements is certainly possible, but adding or modifying interface within existing Espresso windows is not supported (aside from custom sheets).</li>
	</ul>

	<p>There may be other limitations within the <span class="caps">API</span>, but these are the ones that most often trip people up when they&#8217;re trying to imagine what they can accomplish. We&#8217;re always working to improve the Sugar <span class="caps">API</span>, as well, so some of these limitations may cease to exist eventually.</p>

	<h2>Specific layout</h2>

	<p>A Sugar is a folder with a .sugar extension, and the following structure:</p>

	<ul>
		<li>CodeSenseLibraries/</li>
		<li>CodeSenseProviders/</li>
		<li>Contents/
	<ul>
		<li>Info.plist</li>
	</ul></li>
		<li>FileActions/</li>
		<li>Itemizers/</li>
		<li>Languages.xml</li>
		<li>PlaceholderThemes/</li>
		<li>Syntaxes/</li>
		<li>SyntaxInjections/</li>
		<li>TextActions/</li>
	</ul>

	<p>Each of these is optional, depending on what features you want your Sugar to provide. To test a Sugar in Espresso, move it to ~/Library/Application Support/Espresso/Sugars/ and <strong>restart Espresso</strong> for the changes to take effect.</p>

	<h3>A quick overview</h3>

	<p>Although not all Sugars will use all of the files and folders above, a useful way to get a handle on what the files do is to think about a sugar that is describing a completely new syntax (rather than expanding on an existing syntax).  For such a Sugar that&#8217;s building a syntax from the ground up, here&#8217;s how the files interact with one another:</p>

	<p><strong>Languages.xml</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/Languages/" title="Languages">Languages</a><br />
This is the entry point for Sugars that define new languages.  The Languages.xml file describes all the languages that your Sugar is defining and tells Espresso how to detect those languages (for instance, which file extensions should trigger this Sugar).</p>

	<p><strong>Contents</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/CocoaSugars/" title="CocoaSugars">CocoaSugars</a><br />
This is a folder that gets automatically generated when the Sugar contains compiled code.</p>

	<p>Every Sugar (Cocoa or otherwise) must have an <strong>Info.plist</strong> in the Contents folder. This file defines a unique identifier, version and optional update information for your Sugar. At some point in the future, we will no longer load Sugars without this file present.</p>

	<p><strong>Syntaxes</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/Syntaxes/" title="Syntaxes">Syntaxes</a><br />
In this folder, you define the zones that make up your <a href="http://wiki.macrabbit.com/index/Syntaxes/" title="Syntaxes">syntax</a> using regular expressions.  You can have multiple <span class="caps">XML</span> files for different languages (see the <span class="caps">XML</span>+HTML Sugar for a great example); a standard usage is to have one <span class="caps">XML</span> file for each language in Languages.xml.  The syntax definition is incredibly important, because it&#8217;s the basis of both CodeSense and itemizers.</p>

	<p><strong>SyntaxInjections</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/Syntaxes/" title="Syntaxes">Syntaxes</a><br />
This folder contains <span class="caps">XML</span> documents for your syntax injections; syntax injections allow you to either inject a different syntax into your Sugar (for example, styling embedded <span class="caps">CSS</span> as <span class="caps">CSS</span> even though it&#8217;s in the larger context of an <span class="caps">HTML</span> syntax), or inject rules of your own into a pre-existing syntax.</p>

	<p><strong>CodeSenseLibraries</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/CodeSense/" title="CodeSense">CodeSense</a><br />
The <span class="caps">XML</span> files in this folder define lists of completions, but do not contain any logic for where those completions should be offered.  For example, in the <span class="caps">XML</span>+HTML Sugar, one of the <span class="caps">XML</span> files in CodeSenseLibraries contains a list of <span class="caps">HTML</span> attributes.</p>

	<p><strong>CodeSenseProviders</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/CodeSense/" title="CodeSense">CodeSense</a><br />
The <span class="caps">XML</span> files in this folder add the contextual logic for defining when a given CodeSenseLibrary should be used using the <a href="http://wiki.macrabbit.com/index/Selectors/" title="Selectors">Selectors</a> from the <a href="http://wiki.macrabbit.com/index/Syntaxes/" title="Syntaxes">Syntaxes</a> files.</p>

	<p><strong>Itemizers</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/Itemizers/" title="Itemizers">Itemizers</a><br />
Using the selectors defined by the syntaxes, the <span class="caps">XML</span> files in Itemizers define the organizational logic for the Sugar.  By defining your itemizers, you enable Espresso to use its code navigator and code folding for your syntax.</p>

	<p><strong>PlaceholderThemes</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/SyntaxThemes/" title="SyntaxThemes">SyntaxThemes</a><br />
This folder contains <span class="caps">CSS</span> theme files that provide default coloring when the Sugar is loaded. User themes can override known placeholder themes to provide custom coloring.</p>

	<p><strong>TextActions</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/TextActions/" title="TextActions">TextActions</a><br />
The <span class="caps">XML</span> files in this folder define actions that can be performed on text, along with the categories they should be grouped in. In order to create text actions, some Cocoa object code must exist to support it. As of writing Espresso doesn&#8217;t come with generic action objects, but this may change.</p>

	<p><strong>FileActions</strong> &#8212; see  <a href="http://wiki.macrabbit.com/index/FileActions/" title="FileActions">FileActions</a><br />
The <span class="caps">XML</span> files in this folder define actions that can be performed on files, and are set up almost exactly like text actions, with that difference that they operate on file contexts instead of text contexts.</p>

	<p>Although we try to keep this wiki up to date with documentation for all portions of Espresso, often the best way to figure out how to do things is to right click on an existing Sugar, choose Show Package Contents, and take a look at what&#8217;s inside its various <span class="caps">XML</span> files.  You can find the Sugars bundled with Espresso by right clicking on the application and navigating to Contents/SharedSupport/Sugars (make sure not to save anything in there, or it will be lost when you update Espresso!).</p>
      ]]></content>
    </entry>

    <entry>
      <title>index</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/index/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:index/1.147</id>
      <published>2010-07-06T20:51:31Z</published>
      <updated>2010-07-06T20:51:31Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>Welcome! This wiki is mainly intended to document Espresso Sugar development, so you can extend it to do new and cool things. To discuss sugar development, <a href="http://wiki.macrabbit.com/forums/">join the forums</a> or <a href="http://wiki.macrabbit.com/index/IRC/" title="IRC">pop into <span class="caps">IRC</span>!</a></p>

	<h2>New to Espresso?</h2>

	<p>Espresso does not currently have any official documentation, but if you have just started working with Espresso, see our <a href="http://wiki.macrabbit.com/index/Intro_to_Espresso/" title="Intro_to_Espresso">Intro to Espresso</a> for useful resources.</p>

	<h2>Sugar Documentation Quick Links</h2>

	<ul>
		<li><a href="http://wiki.macrabbit.com/index/SugarBasics/" title="SugarBasics">SugarBasics</a> &#8212; the starting point for making Sugars</li>
		<li><a href="http://wiki.macrabbit.com/index/SyntaxThemes/" title="SyntaxThemes">SyntaxThemes</a> &#8212; reference for syntax themes (<span class="caps">CSS</span>)</li>
		<li><a href="http://wiki.macrabbit.com/index/Syntaxes/" title="Syntaxes">Syntaxes</a> &#8212; reference for language syntax definitions (<span class="caps">XML</span>)</li>
		<li><a href="http://wiki.macrabbit.com/index/Selectors/" title="Selectors">Selectors</a> &#8212; reference for syntax selectors (used throughout Espresso)</li>
		<li><a href="http://wiki.macrabbit.com/index/CodeSense/" title="CodeSense">CodeSense</a> &#8212; documentation for adding auto-completion to your Sugars (<span class="caps">XML</span>)</li>
		<li><a href="http://wiki.macrabbit.com/index/Itemizers/" title="Itemizers">Itemizers</a> &#8212; reference for itemizer recipes (<span class="caps">XML</span>)</li>
		<li><a href="http://wiki.macrabbit.com/index/Actions/" title="Actions">Actions</a> &#8212; reference for TextAction and FileAction definitions (<span class="caps">XML</span>)</li>
		<li><a href="http://wiki.macrabbit.com/index/Snippets/" title="Snippets">Snippets</a> &#8212; reference for Sugar-defined snippets (<span class="caps">XML</span>)</li>
		<li><a href="http://wiki.macrabbit.com/index/CocoaSugars/" title="CocoaSugars">CocoaSugars</a> &#8212; reference for the Cocoa <span class="caps">API</span> (Objective-C)</li>
	</ul>

	<h2>Introduction to Espresso&#8217;s engine</h2>

	<p>Espresso has a regular-expressions-based syntax core, much like TextMate (in fact, developers of TextMate language plists will be able to convert them). Espresso reads <span class="caps">XML</span>-based syntaxes, then uses those rules to generate a syntax tree for opened text documents. Each syntax zone in that tree has a type identifier (similar to <span class="caps">CSS</span> class names in <span class="caps">HTML</span>) that can be targeted using <span class="caps">CSS</span>-like selectors. This selector targeting is used all over Espresso, for various subsystems like syntax coloring and CodeSense.</p>

	<p>That first layer has been done before, so while Espresso&#8217;s implementation is quite powerful (especially its selectors), the contextual information usually stays very local and somewhat limited. To remedy that, Espresso layers an &#8220;itemizer&#8221; above the syntax core. Itemizer definitions group syntax zones into semantical blocks that behave like an &#8220;item&#8221;, a logical piece of the document.</p>

	<p>Itemizing currently brings along two features: the Navigator and great code folding. <span class="caps">CSSE</span>dit-like structure listings are now possible for any language, as long as someone takes the time to create a good itemizer definition. Any language offering an itemizer also gets code folding support for free.</p>

	<p>This multi-layered design delivers excellent performance while still allowing high-level representations of a document that are actually useful to the user.</p>
      ]]></content>
    </entry>

    <entry>
      <title>IRC</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/IRC/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:IRC/17.145</id>
      <published>2010-07-06T20:49:45Z</published>
      <updated>2010-07-06T20:49:45Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>There is an unofficial <span class="caps">IRC</span> channel that has been established for discussion of Espresso-related topics on the <a href="http://freenode.net/">Freenode</a> <span class="caps">IRC</span> network. Anybody is free to join and chat with us, as well as ask questions or make suggestions.</p>

	<h2><a href="irc://chat.freenode.net/##Espresso">##Espresso</a></h2>

	<p>This channel is available for anybody to use, for general discussion, for requesting help from other Espresso users, or for quick help with Sugars.</p>

	<p>You can either download an <span class="caps">IRC</span> client (see below), or use the following link to open a web chat:</p>

	<p><strong><a href="http://webchat.freenode.net/?channels=##Espresso" target="_blank">http://webchat.freenode.net/?channels=##Espresso</a></strong></p>

	<h2>Clients</h2>

	<p>There are multiple viable <span class="caps">IRC</span> clients for Mac OS X. Here are several very popular ones:</p>

	<ul>
		<li><a href="http://colloquy.info/">Colloquy</a></li>
		<li><a href="http://conceitedsoftware.com/linkinus">Linkinus</a></li>
		<li><a href="http://sourceforge.net/projects/xchataqua/">X-Chat Aqua</a></li>
	</ul>

	<h2>Official Developer Sightings</h2>

	<p>Ian Beck, who does QA and support for MacRabbit, is typically in <span class="caps">IRC</span> during business hours (9-5) Pacific time.</p>

	<p>Jan Van Boghout, the core Espresso developer, occasionally (… very, very ocassionally …) drops his head into the room, as well. If you&#8217;ve got an urgent question that only Jan can answer, or a suggestion/complaint with Espresso, you&#8217;ll probably want to try email first.  He most often drops by <span class="caps">IRC</span> immediately following a new release.</p>
      ]]></content>
    </entry>

    <entry>
      <title>Override default sugars</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/Override_default_sugars/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:Override default sugars/25.144</id>
      <published>2010-06-16T17:11:08Z</published>
      <updated>2010-06-16T17:11:08Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>As of Espresso 1.0.x, it is not currently possible to modify sugars to tweak their bundled actions or the extensions they use to determine which files to parse without editing the sugar itself.  This isn&#8217;t a huge deal, but for sugars bundled with Espresso there&#8217;s a little more work.</p>

	<p>If you need to modify a sugar bundled with Espresso (<span class="caps">HTML</span>, <span class="caps">CSS</span>, and <span class="caps">PHP</span> are the ones people most often want to modify), here&#8217;s how to do so without losing your updates whenever Espresso is updated:</p>

	<p>1) In the Finder, right click on Espresso and choose &#8220;Show Package Contents&#8221;</p>

	<p>2) Navigate to Contents/SharedSupport/Sugars, duplicate whichever sugar you want to override (for instance, <span class="caps">PHP</span>.sugar), and move the new copy here:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">~/</span><span style="color: #0000BB">Library</span><span style="color: #007700">/</span><span style="color: #0000BB">Application&nbsp;Support</span><span style="color: #007700">/</span><span style="color: #0000BB">Espresso</span><span style="color: #007700">/</span><span style="color: #0000BB">Sugars</span><span style="color: #007700">/&nbsp;</span>
</span>
</code></div></p>

	<p>3) Show package contents on the copied sugar, and open up Contents/Info.plist (I recommend using a dedicated plist editor like <a href="http://www.fatcatsoftware.com/plisteditpro/">Plist Edit Pro</a>, but any text editor will work). You need to update the CFBundleVersion property to something higher than what&#8217;s currently there. For instance, if the current version is 1.0, you could change it to 1.0.1.</p>

	<p>4) Make your desired modifications to the duplicated sugar.  To add a new extension to the <span class="caps">PHP</span>.sugar, for instance, you need to open up Languages.xml and add something like this nested in the <em>&lt;detectors&gt;</em> tag:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">extension&nbsp;casesensitive</span><span style="color: #007700">=</span><span style="color: #DD0000">"false"</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">phtml</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">extension</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>5) Once you&#8217;ve saved your changes, relaunch Espresso. Only the version of the sugar with the highest CFBundleVersion defined will be loaded, and your custom sugar won’t be overwritten when the program is updated. Of course, if the bundled version of the sugar is updated you’ll need to repeat the process, but you would want to do that anyway to get whatever improvements are included with the new version.</p>

	<p>Good luck!  Drop a line in the forums if you&#8217;ve got a specific modification that you aren&#8217;t sure how to achieve.</p>

	<h3>Existing mods</h3>

	<p><a href="http://wiki.macrabbit.com/forums/viewreply/2671/">Modified curly-brace formatting for <span class="caps">CSS</span></a></p>
      ]]></content>
    </entry>

    <entry>
      <title>CodeSense</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/CodeSense/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:CodeSense/14.143</id>
      <published>2010-06-09T22:17:51Z</published>
      <updated>2010-06-09T22:17:51Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>CodeSense is a contextually-aware system for providing auto-completion for your Sugar. Adding CodeSense to your Sugar is easy provided that you have a well-written syntax with descriptive, granular syntax zones.</p>

	<p>There are two components for CodeSense: libraries and providers.</p>

	<h2>CodeSense Libraries</h2>

	<p><span class="caps">XML</span> files within your CodeSenseLibraries folder define the possible completions for your Sugar, grouped into sets. The library contains no logic about when various sets should be shown for auto-completion, but it does offer the ability to specify text snippets for use with specific sets of strings.</p>

	<p>A typical CodeSenseLibraries <span class="caps">XML</span> file looks like this:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?xml&nbsp;version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0"&nbsp;</span><span style="color: #0000BB">encoding</span><span style="color: #007700">=</span><span style="color: #DD0000">"UTF-8"</span><span style="color: #0000BB">?&gt;<br /></span><span style="color: #007700">&lt;</span><span style="color: #0000BB">codesense&nbsp;version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;behavior&nbsp;defined&nbsp;in&nbsp;the&nbsp;root&nbsp;codesense&nbsp;element&nbsp;serves&nbsp;is&nbsp;used&nbsp;</span><span style="color: #007700">for&nbsp;</span><span style="color: #0000BB">all&nbsp;sets</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">unless&nbsp;the&nbsp;set&nbsp;defines&nbsp;its&nbsp;own&nbsp;behavior&nbsp;</span><span style="color: #007700">--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">behavior</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;append</span><span style="color: #007700">-static&nbsp;</span><span style="color: #0000BB">element&nbsp;defines&nbsp;a&nbsp;snippet&nbsp;that&nbsp;gets&nbsp;appended&nbsp;after&nbsp;the<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;completion&nbsp;string</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">append</span><span style="color: #007700">-static&gt;&nbsp;</span><span style="color: #0000BB">is&nbsp;a&nbsp;fruit</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">append</span><span style="color: #007700">-static&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">behavior</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">set&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"com.yourdomain.yoursugar.fruits"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completion&nbsp;string</span><span style="color: #007700">=</span><span style="color: #DD0000">"apple"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completion&nbsp;string</span><span style="color: #007700">=</span><span style="color: #DD0000">"pear"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completion&nbsp;string</span><span style="color: #007700">=</span><span style="color: #DD0000">"orange"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">set</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">set&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"com.yourdomain.yoursugar.vegetables"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">A&nbsp;behavior&nbsp;defined&nbsp;in&nbsp;a&nbsp;set&nbsp;applies&nbsp;only&nbsp;to&nbsp;that&nbsp;set</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">behavior</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">append</span><span style="color: #007700">-static&gt;&nbsp;</span><span style="color: #0000BB">is&nbsp;a&nbsp;vegetable</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">append</span><span style="color: #007700">-static&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">behavior</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completion&nbsp;string</span><span style="color: #007700">=</span><span style="color: #DD0000">"carrot"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completion&nbsp;string</span><span style="color: #007700">=</span><span style="color: #DD0000">"cabbage"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completion&nbsp;string</span><span style="color: #007700">=</span><span style="color: #DD0000">"potato"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">set</span><span style="color: #007700">&gt;<br />&lt;/</span><span style="color: #0000BB">codesense</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>Sets and their completions should be straight-forward; the set has a name (which will be used in the CodeSense Provider to determine when to use these completions), and each completion has a string attribute that is the completion. By convention, the name for each set should be in reverse domain format.</p>

	<p>Behaviors are used to append text snippets after the completion. In the simple example above, when the user uses CodeSense to insert &#8220;apple&#8221; what will actually be inserted is &#8220;apple is a fruit&#8221;.  Behaviors are powerful because they allow you to conditionally insert things based on what comes after the completion, and also use <a href="http://wiki.macrabbit.com/index/Snippets/" title="Snippets">text snippets</a> to create tab stops.</p>

	<p>The above example showcases how to use a static snippet to be appended to the completion string, but for more advanced behaviors, you can use additional settings and a dynamic snippet:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">behavior</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;</span><span style="color: #007700">&lt;</span><span style="color: #0000BB">append</span><span style="color: #007700">-</span><span style="color: #0000BB">dynamic</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">element&nbsp;allows&nbsp;you&nbsp;to&nbsp;dynamically&nbsp;generate&nbsp;a&nbsp;snippet&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;append&nbsp;after&nbsp;the&nbsp;actual&nbsp;completion</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">append</span><span style="color: #007700">-</span><span style="color: #0000BB">dynamic</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;matched&nbsp;suffix&nbsp;allows&nbsp;you&nbsp;to&nbsp;capture&nbsp;information&nbsp;about&nbsp;the&nbsp;text&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after&nbsp;the&nbsp;completion</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">Specify&nbsp;a&nbsp;regular&nbsp;expression&nbsp;here</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">matched</span><span style="color: #007700">-</span><span style="color: #0000BB">suffix</span><span style="color: #007700">&gt;(</span><span style="color: #0000BB">\s</span><span style="color: #007700">+)(</span><span style="color: #0000BB">is&nbsp;a&nbsp;vegetable</span><span style="color: #007700">)?&lt;/</span><span style="color: #0000BB">matched</span><span style="color: #007700">-</span><span style="color: #0000BB">suffix</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;transform</span><span style="color: #007700">-</span><span style="color: #0000BB">into&nbsp;element&nbsp;is&nbsp;a&nbsp;regex&nbsp;replacement&nbsp;expression</span><span style="color: #007700">,&nbsp;and&nbsp;</span><span style="color: #0000BB">can&nbsp;</span><span style="color: #007700">use&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">the&nbsp;captured&nbsp;strings&nbsp;from&nbsp;matched</span><span style="color: #007700">-</span><span style="color: #0000BB">suffix&nbsp;to&nbsp;generate&nbsp;a&nbsp;conditional&nbsp;snippet</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">transform</span><span style="color: #007700">-</span><span style="color: #0000BB">into</span><span style="color: #007700">&gt;(?</span><span style="color: #0000BB">2</span><span style="color: #007700">:</span><span style="color: #0000BB">\1is&nbsp;a&nbsp;vegetable</span><span style="color: #007700">:</span><span style="color: #0000BB">\1is&nbsp;fantastic&nbsp;</span><span style="color: #007700">and&nbsp;)&lt;/</span><span style="color: #0000BB">transform</span><span style="color: #007700">-</span><span style="color: #0000BB">into</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">append</span><span style="color: #007700">-</span><span style="color: #0000BB">dynamic</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;(</span><span style="color: #0000BB">optional</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">The&nbsp;confirm</span><span style="color: #007700">-</span><span style="color: #0000BB">characters&nbsp;element&nbsp;specifies&nbsp;additional&nbsp;characters&nbsp;that&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trigger&nbsp;the&nbsp;confirmation&nbsp;of&nbsp;a&nbsp;completion</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">confirm&nbsp;characters</span><span style="color: #007700">=</span><span style="color: #DD0000">"&nbsp;"&nbsp;</span><span style="color: #007700">/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;(</span><span style="color: #0000BB">optional</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">The&nbsp;confirm</span><span style="color: #007700">-</span><span style="color: #0000BB">partial&nbsp;element&nbsp;specifies&nbsp;characters&nbsp;that&nbsp;are&nbsp;contained&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;within&nbsp;the&nbsp;completion</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">When&nbsp;they</span><span style="color: #007700">'</span><span style="color: #0000BB">re&nbsp;pressed,&nbsp;the&nbsp;completion&nbsp;will&nbsp;confirm&nbsp;up&nbsp;to&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;that&nbsp;character&nbsp;(including&nbsp;the&nbsp;character&nbsp;itself)&nbsp;and&nbsp;continue&nbsp;completing.&nbsp;This&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is&nbsp;useful&nbsp;for&nbsp;things&nbsp;like&nbsp;CSS&nbsp;properties&nbsp;or&nbsp;PHP&nbsp;functions.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;confirm-partial&nbsp;characters="-"&nbsp;/&gt;<br />&lt;/behavior&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>The example above may be confusing at first glance.  The matched-suffix should be comprehensible (it&#8217;s a simple regex that with two capture groups that grabs whitespace immediately after the completion and then looks for the optional string &#8220;is a vegetable&#8221;).  However, the transform-into expression uses a conditional that outputs different contents based on whether the second capture is empty or not.  The syntax for regex conditionals in transform-into elements is:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">(?</span><span style="color: #0000BB">x</span><span style="color: #007700">:</span><span style="color: #0000BB">a</span><span style="color: #007700">:</span><span style="color: #0000BB">b</span><span style="color: #007700">)&nbsp;</span>
</span>
</code></div></p>

	<p>Which means: if the numbered capture group &#8220;x&#8221; has contents, insert &#8220;a&#8221;. Otherwise, insert &#8220;b&#8221;.</p>

	<p>In the example, if the text &#8220;is a vegetable&#8221; does not fall after the name of the vegetable, then it will be inserted. If it does already exist, then &#8220;is fantastic and&#8221; will be inserted leaving the full completion reading something like &#8220;carrot is fantastic and is a vegetable&#8221;.</p>

	<p>A real-life example is the <span class="caps">CSS</span>.sugar, which when auto-completing property names looks for a colon after the property, and if it isn&#8217;t there inserts it.</p>

	<h2>CodeSense Providers</h2>

	<p>Providers map contexts in a document to possible completions (reference based on the name of the sets you defined in CodeSenseLibraries). Providers should be defined in the CodeSense Providers subfolder of a sugar, as an <span class="caps">XML</span> file with the following structure:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?xml&nbsp;version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0"&nbsp;</span><span style="color: #0000BB">encoding</span><span style="color: #007700">=</span><span style="color: #DD0000">"UTF-8"</span><span style="color: #0000BB">?&gt;<br /></span><span style="color: #007700">&lt;</span><span style="color: #0000BB">codesense</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">provider</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;selector&nbsp;element&nbsp;specifies&nbsp;in&nbsp;what&nbsp;document&nbsp;contexts&nbsp;the&nbsp;provider&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is&nbsp;active</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">The&nbsp;</span><span style="color: #007700">:</span><span style="color: #0000BB">capture&nbsp;pseudo</span><span style="color: #007700">-class&nbsp;</span><span style="color: #0000BB">will&nbsp;save&nbsp;the&nbsp;contents&nbsp;of&nbsp;the&nbsp;zone&nbsp;in&nbsp;a<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;variable</span><span style="color: #007700">.&nbsp;For&nbsp;</span><span style="color: #0000BB">the&nbsp;example&nbsp;below</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">the&nbsp;property</span><span style="color: #007700">-</span><span style="color: #0000BB">name&nbsp;is&nbsp;saved&nbsp;in&nbsp;the&nbsp;</span><span style="color: #DD0000">"name"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">variable</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">selector</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">css&nbsp;</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">property</span><span style="color: #007700">-</span><span style="color: #0000BB">name</span><span style="color: #007700">:</span><span style="color: #0000BB">capture</span><span style="color: #007700">(</span><span style="color: #0000BB">name</span><span style="color: #007700">)&nbsp;+&nbsp;</span><span style="color: #0000BB">property</span><span style="color: #007700">-</span><span style="color: #0000BB">value</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">selector</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;completions&nbsp;element&nbsp;points&nbsp;to&nbsp;the&nbsp;CodeSense&nbsp;Library&nbsp;key&nbsp;that&nbsp;has&nbsp;to&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;be&nbsp;used</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">It&nbsp;can&nbsp;contain&nbsp;placeholders&nbsp;</span><span style="color: #007700">for&nbsp;</span><span style="color: #0000BB">captured&nbsp;pieces&nbsp;of&nbsp;text&nbsp;from&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;selector</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">completions</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">com</span><span style="color: #007700">.</span><span style="color: #0000BB">macrabbit</span><span style="color: #007700">.</span><span style="color: #0000BB">css</span><span style="color: #007700">.</span><span style="color: #0000BB">property</span><span style="color: #007700">.</span><span style="color: #0000BB">$&#123;name&#125;</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">completions</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">The&nbsp;complete</span><span style="color: #007700">-</span><span style="color: #0000BB">match&nbsp;element&nbsp;defines&nbsp;a&nbsp;regular&nbsp;expression&nbsp;</span><span style="color: #007700">for&nbsp;</span><span style="color: #0000BB">the&nbsp;piece&nbsp;of&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text&nbsp;that&nbsp;is&nbsp;completed&nbsp;by&nbsp;this&nbsp;provider</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">It&nbsp;is&nbsp;not&nbsp;necessary&nbsp;to&nbsp;append&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;an&nbsp;end</span><span style="color: #007700">-</span><span style="color: #0000BB">of</span><span style="color: #007700">-</span><span style="color: #0000BB">line&nbsp;symbol</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">this&nbsp;happens&nbsp;automatically</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">Note&nbsp;that&nbsp;even&nbsp;</span><span style="color: #007700">if&nbsp;</span><span style="color: #0000BB">this&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;provider&nbsp;is&nbsp;active&nbsp;in&nbsp;the&nbsp;current&nbsp;context</span><span style="color: #007700">,&nbsp;and&nbsp;</span><span style="color: #0000BB">the&nbsp;expression&nbsp;is&nbsp;matched</span><span style="color: #007700">,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">it&nbsp;may&nbsp;still&nbsp;be&nbsp;ignored&nbsp;</span><span style="color: #007700">for&nbsp;</span><span style="color: #0000BB">a&nbsp;completion&nbsp;</span><span style="color: #007700">if&nbsp;</span><span style="color: #0000BB">other&nbsp;providers&nbsp;match&nbsp;a&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;different&nbsp;piece&nbsp;of&nbsp;the&nbsp;same&nbsp;text</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">complete</span><span style="color: #007700">-</span><span style="color: #0000BB">match</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">&#91;a</span><span style="color: #007700">-</span><span style="color: #0000BB">zA</span><span style="color: #007700">-</span><span style="color: #0000BB">Z0</span><span style="color: #007700">-</span><span style="color: #0000BB">9</span><span style="color: #007700">-</span><span style="color: #0000BB">&#93;</span><span style="color: #007700">*&lt;/</span><span style="color: #0000BB">complete</span><span style="color: #007700">-</span><span style="color: #0000BB">match</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;(</span><span style="color: #0000BB">Optional</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">The&nbsp;</span><span style="color: #007700">require-</span><span style="color: #0000BB">suffix&nbsp;element&nbsp;defines&nbsp;a&nbsp;regular&nbsp;expression&nbsp;which&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;text&nbsp;</span><span style="color: #007700">*</span><span style="color: #0000BB">after</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">the&nbsp;completion&nbsp;has&nbsp;to&nbsp;match</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">It&nbsp;is&nbsp;not&nbsp;necessary&nbsp;to&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prepend&nbsp;a&nbsp;begin</span><span style="color: #007700">-</span><span style="color: #0000BB">of</span><span style="color: #007700">-</span><span style="color: #0000BB">line&nbsp;symbol</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">this&nbsp;happens&nbsp;automatically</span><span style="color: #007700">.&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;require-</span><span style="color: #0000BB">suffix</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">&#91;</span><span style="color: #007700">^:</span><span style="color: #0000BB">&#93;</span><span style="color: #007700">|&lt;/require-</span><span style="color: #0000BB">suffix</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">provider</span><span style="color: #007700">&gt;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;</span><span style="color: #0000BB">Many&nbsp;providers&nbsp;can&nbsp;be&nbsp;defined&nbsp;in&nbsp;the&nbsp;same&nbsp;XML&nbsp;</span><span style="color: #007700">--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">provider</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">provider</span><span style="color: #007700">&gt;<br />&lt;/</span><span style="color: #0000BB">codesense</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>The example above should be largely self-explanatory thanks to its comments, but one thing to keep in mind is that thanks to the :capture(<span class="caps">VARIABLE</span>) pseudo-class you do not have to directly refer to all sets in your CodeSenseLibraries directly. In the example above, both of these sets will be used depending on which <span class="caps">CSS</span> property the user is currently editing:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">set&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"com.maccrabbit.css.property.display"</span><span style="color: #007700">&gt;&nbsp;...&nbsp;&lt;/</span><span style="color: #0000BB">set</span><span style="color: #007700">&gt;<br />&lt;</span><span style="color: #0000BB">set&nbsp;name</span><span style="color: #007700">=</span><span style="color: #DD0000">"com.macrabbit.css.property.float"</span><span style="color: #007700">&gt;&nbsp;...&nbsp;&lt;/</span><span style="color: #0000BB">set</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>
      ]]></content>
    </entry>

    <entry>
      <title>SyntaxThemes</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/SyntaxThemes/" />
      <id>tag:wiki.macrabbit.com,2010:wiki:SyntaxThemes/10.138</id>
      <published>2010-03-10T16:09:03Z</published>
      <updated>2010-03-10T16:09:03Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>Espresso syntax themes are <span class="caps">CSS</span> files with some special comment metadata, and they come in two variants: user themes and placeholder themes.</p>

	<p>Espresso&#8217;s syntax coloring approach is modeled after <span class="caps">HTML</span> and <span class="caps">CSS</span>. In fact, Espresso themes <strong>are</strong> <span class="caps">CSS</span> files. Just like regular style sheets, they contain rules that apply to certain zones in the document. Instead of targeting the web page <span class="caps">DOM</span>, <a href="http://wiki.macrabbit.com/index/Selectors/" title="Selectors">Selectors</a> are now used to target syntax zones in your documents.</p>

	<h2>Placeholder themes</h2>

	<p>Espresso features user themes (loaded from ~/Library/Application Support/Espresso/Themes) and placeholder themes (loaded from the PlaceholderThemes directory in a sugar). Together, they are combined into the final set of rules that define the coloring for documents. A placeholder theme requires a special comment in the <span class="caps">CSS</span> file:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #FF8000">/*<br />&nbsp;&nbsp;&nbsp;&nbsp;@theme&nbsp;XYZ&nbsp;Placeholder<br />&nbsp;&nbsp;&nbsp;&nbsp;@placeholder&nbsp;some.category.here<br />*/&nbsp;</span>
</span>
</code></div></p>

	<p>The value for @placeholder is a type identifier and can be freely chosen, but must be descriptive about the rules your placeholder theme contains. It&#8217;s a good idea to make a single placeholder theme (and identifier) per language instead of grouping several unrelated languages into one.</p>

	<p><strong>Example</strong>: currently, the <span class="caps">CSS</span> built-in sugar is the only one defining a placeholder theme.</p>

	<h2>User themes</h2>

	<p>One user theme can be active at a time. It must contain a comment like this:<br />
<div class="codeblock"><code><span style="color: #000000">
<span style="color: #FF8000">/*<br />&nbsp;&nbsp;&nbsp;&nbsp;@theme&nbsp;My&nbsp;Theme&nbsp;Name<br />&nbsp;&nbsp;&nbsp;&nbsp;@override-placeholders&nbsp;identifier,&nbsp;some.other.category<br />*/&nbsp;</span>
</span>
</code></div></p>

	<p>When it&#8217;s active, the user theme will be combined with all placeholder themes that do <strong>not</strong> have an identifier matched by the selector in @override-placeholders. Note that an override like &#8220;text&#8221; matches &#8220;text.html&#8221;, &#8220;something.text&#8221;, etc.</p>

	<h2>Possible values</h2>

	<p>Since themes are simple <span class="caps">CSS</span> files, you can use a range of color definitions: hex colors, rgb() notation and even composited rgba() for blended alpha colors. Each rule can contain any of the following properties: color, background-color, font-weight, font-style and spell-check.</p>

	<h2>Changing background, default text color, and more</h2>

	<p>To adjust global colors, you need to specify a special rule with &#8220;@base&#8221; in place of the selector. It&#8217;s recommended to add this to any theme you make.</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">@</span><span style="color: #0000BB">base&nbsp;&#123;<br />&nbsp;&nbsp;&nbsp;&nbsp;color</span><span style="color: #007700">:&nbsp;</span><span style="color: #FF8000">#000000;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">background</span><span style="color: #007700">-</span><span style="color: #0000BB">color</span><span style="color: #007700">:&nbsp;</span><span style="color: #FF8000">#FFFFFF;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">insertion</span><span style="color: #007700">-</span><span style="color: #0000BB">point</span><span style="color: #007700">-</span><span style="color: #0000BB">color</span><span style="color: #007700">:&nbsp;</span><span style="color: #FF8000">#000000;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">selection</span><span style="color: #007700">-</span><span style="color: #0000BB">background</span><span style="color: #007700">-</span><span style="color: #0000BB">color</span><span style="color: #007700">:&nbsp;default;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">current</span><span style="color: #007700">-</span><span style="color: #0000BB">line</span><span style="color: #007700">-</span><span style="color: #0000BB">background</span><span style="color: #007700">-</span><span style="color: #0000BB">color</span><span style="color: #007700">:&nbsp;</span><span style="color: #FF8000">#fff8dd;<br /></span><span style="color: #0000BB">&#125;&nbsp;</span>
</span>
</code></div></p>

	<p>You can also specify whether a zone should have spell-checking disabled by default:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">tag</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">source</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">sourcecode&nbsp;&#123;<br />&nbsp;&nbsp;&nbsp;&nbsp;spell</span><span style="color: #007700">-</span><span style="color: #0000BB">check</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">disabled</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">&#125;&nbsp;</span>
</span>
</code></div></p>

	<h2>Editing Themes</h2>

	<p>Themes can be directly edited within Espresso by choosing &#8220;Preferences&#8221; (command + ,) from the &#8220;Espresso&#8221; contextual menu, clicking on &#8220;Colors&#8221; within the Preferences window, then clicking &#8220;Edit Theme&#8230;&#8221;.</p>

	<p>Alternately, if you&#8217;d like to edit the Syntax theme with another application (For instance the wonderful <span class="caps">CSSE</span>dit), while in the &#8220;Colors&#8221; section within the Preferences window, click &#8220;Reveal in Finder&#8221;. In Finder you can right (or control) click on the theme you&#8217;d like to edit, go to &#8220;Open With&#8221;, and select the application of your choice.  </p>

	<p>A new window will open with the syntax colors written in hex. If you are unfamiliar with hex colors see: <a href="http://en.wikipedia.org/wiki/Web_colors#Hex_triplet">Wikipedia</a> , and be sure to pick up the indispensable and free <a href="http://wafflesoftware.net/hexpicker/">HexColorPicker</a> for the OS X Color Panel.</p>

	<p>If you are editing the currently active theme, changes will be updated live in all open windows.</p>
      ]]></content>
    </entry>

    <entry>
      <title>Snippets</title>
      <link rel="alternate" type="text/html" href="http://wiki.macrabbit.com/index/Snippets/" />
      <id>tag:wiki.macrabbit.com,2009:wiki:Snippets/20.136</id>
      <published>2009-12-26T22:59:46Z</published>
      <updated>2009-12-26T22:59:46Z</updated>
      <author>
            <name>Ian Beck</name>
            <email></email>
      </author>
      <content type="html"><![CDATA[
        	<p>Snippets provide shortcuts for frequently used pieces of code. You can define standard snippets that are included in your sugar.</p>

	<h2>Defining Snippets</h2>

	<p>Snippets are defined in an <span class="caps">XML</span> file in the <i>TextActions</i> subdirectory of your sugar. For example, this snippet will expand into a C for loop when the user types &#8220;for[tab]&#8221;</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?xml&nbsp;version</span><span style="color: #007700">=</span><span style="color: #DD0000">"1.0"&nbsp;</span><span style="color: #0000BB">encoding</span><span style="color: #007700">=</span><span style="color: #DD0000">"UTF-8"</span><span style="color: #0000BB">?&gt;<br /></span><span style="color: #007700">&lt;</span><span style="color: #0000BB">action</span><span style="color: #007700">-</span><span style="color: #0000BB">recipes</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">snippet&nbsp;id</span><span style="color: #007700">=</span><span style="color: #DD0000">"com.example.snippets.for"&nbsp;</span><span style="color: #0000BB">category</span><span style="color: #007700">=</span><span style="color: #DD0000">"tools.Snippets"</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">title</span><span style="color: #007700">&gt;for&nbsp;</span><span style="color: #0000BB">loop</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">title</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">text</span><span style="color: #007700">&gt;&lt;!</span><span style="color: #0000BB">&#91;CDATA&#91;int&nbsp;$&#123;1</span><span style="color: #007700">:</span><span style="color: #0000BB">i&#125;</span><span style="color: #007700">;<br />for&nbsp;($</span><span style="color: #0000BB">1&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;$</span><span style="color: #0000BB">1&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$&#123;2</span><span style="color: #007700">:</span><span style="color: #0000BB">N&#125;</span><span style="color: #007700">;&nbsp;$</span><span style="color: #0000BB">1</span><span style="color: #007700">++)<br /></span><span style="color: #0000BB">&#123;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">$</span><span style="color: #0000BB">0<br />&#125;&#93;&#93;</span><span style="color: #007700">&gt;&lt;/</span><span style="color: #0000BB">text</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">syntax</span><span style="color: #007700">-</span><span style="color: #0000BB">context</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">c</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">c&nbsp;</span><span style="color: #007700">*&lt;/</span><span style="color: #0000BB">syntax</span><span style="color: #007700">-</span><span style="color: #0000BB">context</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">text</span><span style="color: #007700">-</span><span style="color: #0000BB">trigger</span><span style="color: #007700">&gt;for&lt;/</span><span style="color: #0000BB">text</span><span style="color: #007700">-</span><span style="color: #0000BB">trigger</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color: #0000BB">key</span><span style="color: #007700">-</span><span style="color: #0000BB">equivalent</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">control&nbsp;option&nbsp;shift&nbsp;f</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">key</span><span style="color: #007700">-</span><span style="color: #0000BB">equivalent</span><span style="color: #007700">&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color: #0000BB">snippet</span><span style="color: #007700">&gt;<br /><br />&lt;/</span><span style="color: #0000BB">action</span><span style="color: #007700">-</span><span style="color: #0000BB">recipes</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>The <strong>&lt;title&gt;</strong> element defines the name shown in the snippets viewer.<br />
The <strong>&lt;text&gt;</strong> element defines the contents of the snippet (as per the <a href="http://manual.macromates.com/en/snippets#snippets">TextMate syntax</a>).<br />
The <strong>&lt;snippet-context&gt;</strong> element defines where the snippet will be available.<br />
The optional <strong>&lt;text-trigger&gt;</strong> element defines a tab-trigger. Adding a key-equivalent=&#8221;&#8230;&#8221; allows a custom trigger key to be set instead of [tab].<br />
The optional <strong>&lt;key-equivalent&gt;</strong> element defines a keyboard shortcut for the snippet composed of any number of modifiers (command, control, option, and/or shift) and a character (&#8220;tab&#8221;, &#8220;enter&#8221;, &#8220;space&#8221;, etc. may also be used for some special keys).  Although this isn&#8217;t always 100% accurate, you can sometimes leave off the &#8220;shift&#8221; modifier if you use a capitalized character (or other character that can only be typed by holding down shift).  Note, also, that if you use capital letters this may add a shift modifier even if you don&#8217;t want one.</p>

	<h2>Snippet placeholders</h2>

	<p>Version 1.1 of Espresso introduces several placeholders for snippets, allowing you to do things like include selected text in a snippet.  Available placeholders include:</p>

	<ul>
		<li><strong><span class="caps">EDITOR</span>_SELECTION</strong>: the selected text, if any, when the snippet is invoked</li>
		<li><strong><span class="caps">EDITOR</span>_SELECTION_LINE</strong>: the contents of the first line of the selection when the snippet is invoked</li>
		<li><strong><span class="caps">EDITOR</span>_SELECTION_LINENUMBER</strong>: the number of the first selected line in the document when the snippet is invoked</li>
		<li><strong><span class="caps">EDITOR</span>_URL</strong>: the <span class="caps">URL</span> of the current file &#40;e.g. file://localhost/Users/myaccount/myproject/myfile.html&#41;</li>
		<li><strong><span class="caps">EDITOR</span>_PATH</strong>: the absolute path to the file &#40;e.g. /Users/myaccount/myproject/myfile.html&#41;</li>
		<li><strong><span class="caps">EDITOR</span>_DIRECTORY_PATH</strong>: the absolute path to the file&#8217;s parent directory (e.g. /Users/myaccount/myproject)</li>
		<li><strong><span class="caps">EDITOR</span>_PROJECT_PATH</strong>: the absolute path to the project root directory (e.g. /Users/myaccount)</li>
	</ul>

	<p>To use a placeholder in a snippet, simply prepend a dollar sign to the variable name:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">p</span><span style="color: #007700">&gt;</span><span style="color: #0000BB">This&nbsp;is&nbsp;the&nbsp;selected&nbsp;text</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$EDITOR_SELECTION</span><span style="color: #007700">&lt;/</span><span style="color: #0000BB">p</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>

	<p>Just like in Textmate, you can also specify an alternative in case the variable is empty:</p>

	<p><div class="codeblock"><code><span style="color: #000000">
<span style="color: #0000BB">$&#123;EDITOR_SELECTION</span><span style="color: #007700">:</span><span style="color: #0000BB">Sorry</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">no&nbsp;selection</span><span style="color: #007700">!</span><span style="color: #0000BB">&#125;&nbsp;</span>
</span>
</code></div></p>

	<h2>Hiding Snippets</h2>

	<p>Snippets can also be <i>hidden</i>. Hidden snippets aren&#8217;t exposed in the tools pane but can be accessed by their key equivalents or tab triggers. To hide a snippet, change its category to &#8220;hidden&#8221;.<br />
For example:<br />
<div class="codeblock"><code><span style="color: #000000">
<span style="color: #007700">&lt;</span><span style="color: #0000BB">snippet&nbsp;id</span><span style="color: #007700">=</span><span style="color: #DD0000">"com.example.snippets.closetag"&nbsp;</span><span style="color: #0000BB">category</span><span style="color: #007700">=</span><span style="color: #DD0000">"hidden"</span><span style="color: #007700">&gt;&nbsp;</span>
</span>
</code></div></p>
      ]]></content>
    </entry>


</feed>