Sublime Forum

Embedded syntax highlighting in xml

#1

Hi, I’ve been trying to add python syntax highlighting withing certain xml tags to the general xml syntax highlighting. I copied the default tag definition in the main context, and changed it so it matches my target tags and applies the python highlighting:

- match: '(<)(exec|virtual|condition|validate)([^/>\s]*)'
  captures:
    1: punctuation.definition.tag.begin.xml
    2: entity.name.tag.localname.xml
  push:
    - meta_scope: meta.tag.xml
    - include: tag-stuff
    - match: '>'
      scope: punctuation.definition.tag.end.xml

      set: Packages/Python/Python.sublime-syntax
      with_prototype:
        - match: (</)(exec|virtual|condition|validate)
          captures:
            1: punctuation.definition.tag.begin.xml
            2: entity.name.tag.localname.xml
          push:
            - meta_scope: meta.tag.xml
            - include: tag-stuff
            - match: '>'
              scope: punctuation.definition.tag.end.xml
              pop: true
          pop: true

This highlights the python code fine, but I am running in the following problem - when both the opening and closing tags are on the same line, it sometimes fails to pop the python syntax. Here are some example with the the scopes on the closing tag:

<exec> a = 2</exec> <!--pops: text.xml punctuation.definition.tag.begin.xml-->
<exec> a = b </exec> <!--pops: text.xml punctuation.definition.tag.begin.xml-->
<exec> a = b</exec> <!--does not pop with space removed: text.xml source.python meta.qualified-name.python punctuation.definition.tag.begin.xml-->
<exec> import test </exec> <!--does not pop: text.xml source.python meta.statement.import.python punctuation.definition.tag.begin.xml-->

I think this has something to do with the meta scopes since the “meta.tag.xml” is not applied to the closing tag regardless of anything at this point. I don’t really know how to add that, maybe it tries to find it in the python syntax file and that fails? Anyways any help would be appreciated here…

0 Likes

#2

I didn’t actually try the following one. But use embed / escape will make it more easier and maintainable.

- match: '(<)(exec|virtual|condition|validate)([^/>\s]*)'
  captures:
    1: punctuation.definition.tag.begin.xml
    2: entity.name.tag.localname.xml
  push:
    - meta_scope: meta.tag.xml
    - include: tag-stuff
    - match: '>'
      scope: punctuation.definition.tag.end.xml
      embed: Packages/Python/Python.sublime-syntax
      escape: (?=(</)(exec|virtual|condition|validate))
    - match: (</)(exec|virtual|condition|validate)
      captures:
        1: punctuation.definition.tag.begin.xml
        2: entity.name.tag.localname.xml
      push:
        - meta_scope: meta.tag.xml
        - include: tag-stuff
        - match: '>'
          scope: punctuation.definition.tag.end.xml
          pop: true
      pop: true
2 Likes

#3

That works great, thanks! Looks like I missed this key part of the docs
“While similar to push, it pops out of any number of nested contexts as soon as the escape pattern is found.” so now the python syntax can’t mess things up :wink:

0 Likes

#4

… and the embed prevents possible recursions, which with_prototype suffers from.

One additional note: I’d suggest to always include/embed syntaxes by scope name rather than syntax file path.

   embed: scope:source.python
1 Like

#5

I wonder what happens if there are multiple packages creating syntax using scope: source.python as their default scope. Say I have python1.sublime-syntax, python2.sublime-syntax, …etc

0 Likes

#6

I think it will use the last one loaded.

0 Likes