Custom syntax in Sublime Text 3

A full discussion of how to create a custom syntax is well outside the bounds of something as simple as a Stack Overflow answer. Also I think you’re making your problem more complicated than it actually is (although creating a syntax is pretty complicated in general).

In order to walk you through the steps that you would take to create a custom syntax, here’s an example.

To start with, create a file with the following contents and save it somewhere as sample.ec, and leave the file open:

// This is a line comment
if (x == 2)
    y = 1
else
    z = 1

You’ll notice that the syntax for this file is set to Plain Text (see the status line in the lower right), which is the default syntax for files that are unknown to Sublime.

Now, select Tools > Developer > New Syntax... from the menu. A buffer with the following will appear. Use File > Save to save the file; the location will default to your User package. The name you give it is not important, but make sure that the extension is sublime-syntax. In my example I’m calling my file Sample.sublime-syntax.

%YAML 1.2
---
# See http://www.sublimetext.com/docs/3/syntax.html
file_extensions:
  - ec
scope: source.example-c
contexts:
  main:
    # Strings begin and end with quotes, and use backslashes as an escape
    # character
    - match: '"'
      scope: punctuation.definition.string.begin.example-c
      push: double_quoted_string

    # Comments begin with a '//' and finish at the end of the line
    - match: '//'
      scope: punctuation.definition.comment.example-c
      push: line_comment

    # Keywords are if, else for and while.
    # Note that blackslashes don't need to be escaped within single quoted
    # strings in YAML. When using single quoted strings, only single quotes
    # need to be escaped: this is done by using two single quotes next to each
    # other.
    - match: '\b(if|else|for|while)\b'
      scope: keyword.control.example-c

    # Numbers
    - match: '\b(-)?[0-9.]+\b'
      scope: constant.numeric.example-c

  double_quoted_string:
    - meta_scope: string.quoted.double.example-c
    - match: '\\.'
      scope: constant.character.escape.example-c
    - match: '"'
      scope: punctuation.definition.string.end.example-c
      pop: true

  line_comment:
    - meta_scope: comment.line.example-c
    - match: $
      pop: true

Now open the Sublime Console with View > Show Console or press the associated key binding. You’ll see that the last line in the console is this:

generating syntax summary

Leaving the console open, click in the syntax file and perform another save operation again without changing anything. The same line appears in the console again.

  1. Are there any compile or refresh steps, or does everything automatically reload?

As seen here, every time you modify the syntax definition, the file is recompiled and the results are cached. So there are no compile steps (other than saving) and nothing you need to do in order to refresh anything.

Now lets turn our attention back to the sample file. It’s still open, and the syntax still says that it’s Plain Text.

Now close the file and re-open it again; a shortcut for this is to use File > Open Recent > Reopen Closed File or it’s associated key binding.

Notice that now that the file is re-opened, there are several changes. Firstly, the syntax name in the bottom right side of the window says Sample (or whatever you named your sublime-syntax file above). For another, the contents of the file are now syntax highlighted.

The colors you see are dependent on the color scheme you use, but an example might look like this:

// This is a line comment
if (x == 2)
    y = 1
else
    z = 1
  1. How do I know that my syntax file, and the scope file it uses, are loaded and applied successfully?

You can see that the syntax file was compiled by the lack of an error message when you save your changes, and you can tell that it’s applied by trying to use the syntax.

Here the syntax is being used automatically, but you’ll find that if you check View > Syntax in the menu or click the current syntax name in the bottom right of the window, your syntax will appear there. Similarly there is now an entry in the command palette named Set Syntax: Sample (or whatever).

That leads us into your last question. If you go back to your sublime-syntax file, you’ll see this at the top:

# See http://www.sublimetext.com/docs/3/syntax.html
file_extensions:
  - ec
scope: source.example-c

The first thing to note is that file_extensions includes ec, and our sample file is called sample.ec; thus this syntax applies to it automatically due to it’s name.

Now switch into the sample.ec file, place the cursor somewhere in the buffer and use Tools > Developer > Show Scope Name or press the associated key.

The content of the popup that appears will vary depending on where in the file the cursor is located, but the common point is that the scope that appears always starts with source.example-c.

  1. In the syntax definition I have to specify a scope (e.g. scope: source.c) but where does that scope file live? Or rather, where do I create my scope file, and how do I name it, so that it loads?

As seen here, there is no such thing as a “scope file”; the sublime-syntax file directly specifies the scope as part of the syntax rules, so it’s the only file that you need to create in order to create a syntax. It may look like a filename, but it is not one.

The scopes that are applied in the syntax matching rules in the syntax need to coincide with the scopes in your color scheme in order to be syntax highlighted; that’s why you should use the scope naming rules to use the common set of scopes that all syntaxes share unless you’re also planning to make a color scheme to go along with your syntax, but unless you use the recommended scopes, your syntax won’t work well with other color schemes and your color scheme won’t work well for other syntaxes.

From this starting point you can modify the sublime-syntax file here in order to make it highlight files the way you want. That would include changing the base scope at the top, applying an appropriate extension, and then including all of the rules that match your language.

As mentioned above, creating the actual rules to match your file is the most complicated part of creating a syntax unless your file format is very simplistic. It’s outside the scope of something that could be conveyed in a Stack Overflow answer, but the official documentation linked above gives you some information on it.

Apart from looking at existing syntax files to see how they’re doing what they do, you can also ask more directed questions on the Sublime forum.

Leave a Comment