Sublime Forum

Swapping between syntax stacks?


I’m learning how to write syntax definitions. I’m creating a syntax definition for a language that has two filetypes: source code (.wbs), and HTML with sourcecode embedded (.wbt). I’ve written the syntax for the source code and it works pretty well; now I’m trying to figure out the syntax definition for HTML with source embedded.

Here is my issue:

My sourcecode syntax does some fancy stack work to detect matched and unmatched keywords. For example, “else” will be identified as keyword.control.conditional if it’s within an “if” statement, but is otherwise identified as invalid.unmatched.

With my template syntax, I push the source syntax at <% and pop it off at %>, but this means the source’s stack is deleted and starts over at every embedded statement. This leads to keywords incorrectly being identified as invalid.unmatched, since the stack was not preserved. I need to preserve the source’s stack between these embedded statements – sort of like juggling two distinct stacks (HTML and my source). Is this possible? How would you approach this problem?



If it’s useful, here’s the super simple syntax definition I have:

%YAML 1.2

name: shfsource Template
  - wbt
scope: source.shfsource

    - match: ""
      push: "Packages/HTML/HTML.sublime-syntax"
        - match: <%
          push: Packages/User/shfsource.sublime-syntax
            - match: (?=%>)
              pop: true


I don’t think it’s possible in ST currently.

Make those keywords like if, else, end-if not context-aware. For example, in the PHP Source syntax definition file (which is similar to your case), from the highlighter’s perspective, there is no rule that makes else can only be used after if or something.



It might be worth logging a feature request for it at - I also wanted to do the same with ASP etc. And in some cases it is more useful than “just” detecting stray end keywords or brackets (which some people argue is better handled by a linter) - embedding PHP inside JS for example where there are lots of context switches is currently problematic. There’s also a need for extra features to handle FIFO heredocs etc



Thanks Cherng and Keith! I’ll probably create a simplified syntax that doesn’t care about context for the template pages.

And in some cases it is more useful than “just” detecting stray end keywords or brackets (which some people argue is better handled by a linter)

True, and I actually have some cases for that too! This is one of those “natural-language” programming languages, where simple keywords like “to” can be used in a variety of contexts and should be highlighted differently. For example,

for a to b
  move a to c

I’d label that first to as keyword.control.conditional.for.shfsource, and the other as variable.function.move.shfsource. Little overlaps like that are common, and the language is very loose about whitespace, so I can’t guarantee they’ll always be next to each other in a template.

I’ll consider making a feature request for it – I haven’t done one before but this would be handy to have!



I’ve created an enhancement request:

1 Like