Coda 2 modes, scopes, and you

Hidden in the massive list of awesome that Panic shipped with Coda 2 was an entirely new way to highlight files: color themes, or Syntax Style Sheets. And they are awesome.

Essentially, they separated syntax parsing (syntax .mode bundles) from highlighting (the new syntax stylesheets). Unfortunately, to make any progress, you’ve gotta break a few things. In this case, Coda 1 syntax modes don’t quite work with the new color themes.

So what’s all this about scopes?

The difference between syntax modes for Coda 1 and Coda 2 largely boils down to an attribute called scope. These scope attributes are how Coda 2 decides which bits are what colors.

This isn’t the perfect analogy, but bear with me

If you think about a syntax mode and a color theme as XML and CSS, it makes a lot of sense.

The syntax mode is a set of rules for parsing a file and generating a document. Let’s pretend it’s generating an XML document. So this:

<?php
    echo "foo";
?>

Might look something like this in our imaginary XML representation:

<delimiter>&lt;?php</delimiter> 
    <keyword>echo</keyword> <string>"foo"</string>;
<delimiter>?&gt;</delimiter>

Now to make this pretty, you’d use CSS like this:

delimiter { color: grey; } 
keyword   { color: blue; } 
string    { color: red;  }

Make sense?

Now, if we wanted our imaginary XML output to be more specific, we could add classes:

<string class="double-quote">"foo"</string> .
<string class="single-quote">'bar'</string>;

Now we can style it like this:

string.double-quote { color: red;    } 
string.single-quote { color: orange; }

By using a more specific selector, we can have a general color as a base style, or a more specific color when needed. Note that the examples above aren’t actually what the default syntax modes use, they’re simplified so they’re easier to grok.

Like I said, this isn’t the perfect analogy, but it’s close enough to get the idea.

When you have a “state” or a “keyword” in your syntax mode, you can assign it a “scope” which is something like a CSS class. This scope is then used by color themes to actually make your mode be colors.

Because color themes (and the preferences dialog) style generic versions of things, you want to use the same basic scope names as the default themes. For example:

constant                  // general case for any constant 
constant.numeric          // like an int or a float 
constant.numeric.keyword  // this might be True or False or Nil or something 

keyword                   // general keyword 
keyword.control           // depends on the language 
keyword.type              // typehints, typecasting, etc

Your actual scopes can be more specific than this. You could use scope="keyword.type.cast.java" as the scope for typecasting in a Java syntax mode, for example, and it would be highlighted using the most specific style available, in this case keyword.type.

To see all of the generic scopes available

Open Coda 2 preferences and export your current color scheme. Edit it (don’t double click, or it will import) and check out all the style rules.

By using generic scopes (markup.comment, language.variable, etc) Panic made it so any color scheme could work with any syntax mode, provided the syntax mode uses the same basic scope names. This is 100% awesomer than before. If you want to see the difference, download any color scheme from this page and look at the source of the old-school .seestyle vs the new .sss of the exact same color scheme.

With the old way, any time a any new syntax mode came along, we would have to update the theme and add a couple hundred lines of XML to color things correctly. That’s the equivalent to using <font> tags to style text all over your website. It doesn’t scale, and it’s not future-proof. So Panic replaced it with a syntax style sheet (at least that’s what I assume .sss stands for).

The new way is a ton better, eh?

Cool story, bro.

But how do I update a Coda 1 syntax mode to work with Coda 2?

Simple: add scopes.

You can see the update applied to Mustache.mode here. You’ll need to do something similar to your syntax mode.

It’s probably easiest to open one of the default syntax modes and work from that. For each of the states and keywords in your syntax mode, find an analogous state from the default mode. Choose the same scope, or make up one that has the same base but is more “specific”.

It’s important to pick scopes based on semantic meaning, rather than desired color. This maintains consistency between languages: If you pick blue as your language.variable color, it’ll be blue in language.variable.php, language.variable.less or language.variable.string.here-doc.perl.