Sublime Forum

Template string syntax highlighting

#1

I’m attempting to make a plugin that will highlight javascript template strings within a file in another syntax. so the segment below would be highlighted as glsl.

const vs = /*glsl*/ `#version 300 es
    precision mediump float;
    in vec4 position;
    void main(){
    }
`;

So far I haven’t been successful, although I find the correct regions with regex, I’m not able to get visible syntax highlighting. I admit I used chatgpt’s suggestion on how to do it so I might have been mislead, but any help is appreciated. the code is below:

import sublime
import sublime_plugin
import re

class TemplateSyntaxHighlighter(sublime_plugin.ViewEventListener):
    @classmethod
    def is_applicable(cls, settings):
        syntax = settings.get('syntax')
        return syntax and "Packages/JavaScript" in syntax

    def on_modified_async(self):
        self.highlight_template_strings()

    def on_activated_async(self):
        self.highlight_template_strings()

    def highlight_template_strings(self):
        content = self.view.substr(sublime.Region(0, self.view.size()))
        pattern = re.compile(r"/\*\s*glsl\s*\*/\s*`([\s\S]*?)`")
        regions = []

        for match in pattern.finditer(content):
            if match.group(1):
                start = match.start(1)
                end = match.end(1)
                regions.append(sublime.Region(start, end))

        self.view.set_status("glsl_highlight_info", f"GLSL strings: {len(regions)}")
        if regions:  
            self.view.add_regions(
                "glsl_highlight",
                regions,
                "source.glsl",  
                "",
                flags=sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE  
            )
        else:
            self.view.erase_regions("glsl_highlight")
0 Likes

#2

There’s more to it than just rolling dice to string words together.

The provided solution couldn’t be less correct.

A possible solution was to create a custom JavaScript syntax definition (e.g.: Packages/User/JavaScript (GLSL).sublime-syntax ), extending ST’s default one, with following content

%YAML 1.2
---
name: JavaScript (GLSL)
scope: source.js.glsl
version: 2

extends: Packages/JavaScript/JavaScript.sublime-syntax

contexts:
  block-comments:
   - meta_prepend: true
   - match: ((/\*)\s*glsl\s*(\*/))\s*((\`){{trailing_wspace}}?)
     captures:
       1: comment.block.js
       2: punctuation.definition.comment.begin.js
       3: punctuation.definition.comment.end.js
       4: meta.string.template.js string.quoted.other.js
       5: punctuation.definition.string.begin.js
     embed: scope:source.glsl
     embed_scope: meta.string.template.js source.glsl.embedded.js
     escape: '{{leading_wspace}}?(\`)'
     escape_captures:
       0: meta.string.template.js string.quoted.other.js
       1: punctuation.definition.string.end.js

The snippet embeds syntaxes with source.glsl scope, provided by https://packagecontrol.io/packages/OpenGL%20Shading%20Language%20(GLSL)

0 Likes

#3

Yes I’ve seen that can be done. Your snippet works after adding two variables that were missing. I’m interested in making a plugin because I have this use case in multiple languages and the only plugin for that purpose js-custom is no longer working.

I want to ask more specifically, if the code I have is highlighting the correct regions by flag, just not syntax highlighting why do you think it couldn’t be any less correct? Maybe View.assign_syntax is a better approach, do you have any input on the plugin?

0 Likes

#4

Your snippet works after adding two variables

Snippet was made with ST4183 which ships JavaScript with those variables pre-defined.

I want to ask more specifically, if the code I have is highlighting the correct regions by flag, just not syntax highlighting why do you think it couldn’t be any less correct?

Not sure I understand the question correct, but view.add_region() is not designed to inject custom syntax definitions. It just adds a region with given scope to document. Proper use cases is highlighting spelling errors or linter errors.

LSP uses add_region() to hack semantic highlighting by applying semantic scopes. But too many regions are hard to maintain properly and can cause significant performance issues in large documents.

view.assign_syntax() assigns a syntax definitnion (sublime-syntax file) to the whole view.

0 Likes