Grammar injections and prefixes


#1

So I’ve been looking at the first-mate package, trying to understand exactly how grammars work in Atom. So far, I’ve learnt a fair bit, but I tend to get stuck on the function and purpose of some things.

For example, can someone please explain what injections and prefixes are? I see things like the following

  "injections": {
    "text.html.php - (meta.embedded | meta.tag), L:text.html.php meta.tag, L:source.js.embedded.html": {
      "patterns": [

As far as I can tell, an injection is a specific set of rules that should be applied specifically inside the given scope, even when that grammar is not currently applied to the file (much like injectionSelector applies the main set of rules when the provided scope is found in another grammar).

Writing this out, it seems to make sense. If I could get some confirmation / correction, that would help a lot though.

The prefixes I’m a bit sketchy on though. A commit by @Wliu has a comment saying they represent the position in the rule stack to add them too, but it also says the B prefix has no meaning (or at least no documentation). Any tips with this are appreciated.


Purpose of all grammar & patterns properties
New Grammar seems not recognized
beginCaptures not being applied to grammar
#2

Nice investigation you did there :).

Almost - in order for injections to take effect your grammar must be the active grammar. In PHP’s case, PHP includes text.html.basic by default and then injects the PHP-specific stuff into the HTML grammar that it just included. The reason why it uses text.html.php and not text.html.basic inside its injection is because that’s language-php’s scope name.

Here’s an example to illustrate what L does. Assume you have the following injection:

"source.some.scope": {
  "patterns": [
    {
      "match": "abcd"
      "name": "injection"
    }
  ]
}

Now additionally assume that source.some.scope has a very similar rule:

"match": "abcd"
"name": "not-injection"

Which one gets matched? The answer in this case is not-injection. But if you had used L:source.some.scope instead, then it would be injection. Adding the L: prefix forces the injected scopes to be considered first (usually, the included scopes are considered, then injections).


Weird grammar highlighting behavior with `include`
#3

in order for injections to take effect your grammar must be the active grammar.

OK, so if I’m understanding this right, in a markdown file, let’s say gfm is the active grammar (provided by language-gfm). Then, within a code snippet of the form

```language

```

It will attempt to scope the contents as that language’s grammar (via source.embedded.language. If there exists a grammar package that has an injectionSelectors property that matches the scope, this other grammar will be used inside the contents (as if it were the main grammar all along, except for some quirks with $base). Additionally, any matching scopes in the injections property of the active grammar (gfm) will have their rules applied.

I’m guessing the injection rules will be overriden by any injectionSelector rules, unless prefixes are used.

With prefixes, I think I get it for now.


#4

Yes, I think you have it right.