Search code examples
regexvisual-studio-codevscode-extensionssyntax-highlightingtextmate

Embedding YAML language in SQL document with VS Code with TextMate


I am having trouble embedding a YAML snippet into VS Code with TextMate.

For our internal software, we use a Context system based on SQL which works like this:

-- MyContext.sql
/* @Context@
<some_metadata_in_yaml_format
*/

-- some sql query

Basically we prefix our files with a block comment, identified with a @Context@ string as discriminator, and put some metadata in it as a YAML snippet.

I made an extension for text highlighting using Textmate JSON for vscode. This is the syntax:

{
    "scopeName": "contextMetadata.injection",
    "injectionSelector": "L:source.sql",
    "patterns": [
        {
            "include": "#contextMeta"
        }
    ],
    "repository": {
        "contextMeta": {
            "name": "lctx.context.metadata",
            "begin": "/\\*[* \\t]*(@Context@)",
            "beginCaptures": {
                "0": {
                    "name": "comment.block entity.other.document.begin.yaml"
                },
                "1": {
                    "name": "support.function lctx.context.metadata.declaration"
                }
            },
            "end": "(?=\\*\/)",
            "endCaptures": {
                "0": {
                    "name": "entity.other.document.end.yaml"
                }
            },
            "contentName": "meta.embedded.block.yaml",
            "patterns": [
                {
                    "include": "source.yaml"
                }
            ]
        }
    }
}

It's very simple, and although textmate/vscode workings are not yet entirely clear to me, it worked up until v1.92.0. After updating, it seems the terminating '*/' is caught into the yaml syntax, and the whole file ends up being highlighted as YAML, which is obviously not what i want. I included an image for reference.

Anyone has a hunch at what's happening here, and can demistify it for me? Thank you!

I tried using various matchers for the end matcher. The look-ahead solution is the one posted in the snippet above, but i also tried this matcher: "end": "([*][/])",, as well as a few other.

They all work fine prior to 1.92, but can't seem to work anymore.

I except the embedded YAML section to end at the block comment.


Solution

  • you should use begin/while instead of end
    while is a lot more concrete when working with line based embeddings
    as unlike end, embedded patterns are not allowed to push the ending out
    (which is what is happening to you)

    it sort of works in the opposite way to end
    in the sense that it needs to validate against each line to continue
    rather than validating against the end text

    so you would need something like this: "while": "^(?!\\s*\\*/)"
    it checks if each line does not contain the ending text */

    https://github.com/RedCMD/TmLanguage-Syntax-Highlighter/blob/main/documentation/rules.md#while

    EDIT: maybe something like this? begin,while,end