vscode-textmate icon indicating copy to clipboard operation
vscode-textmate copied to clipboard

Behavior of $base and $self in injection grammars

Open mjbvz opened this issue 6 years ago • 8 comments

As far as I can tell, $base and $self currently do not work as expected in external injection grammars. Both seem to resolve to the injection grammar itself.

Instead, here's how I think they should work:

$base in an injection grammar should always be resolved to root grammar (it should have the same behavior as using $base in a normal grammar file that is included from another grammar)

The expected behavior of $self is less clear. I think it would make most sense for $self to resolve to the grammar being targeted by the injection, although you could argue that it could be resolved to the injection grammar itself

mjbvz avatar Oct 24 '19 23:10 mjbvz

I'm not sure how this should work, we should just align with whatever TextMate does.

alexdima avatar Nov 20 '19 09:11 alexdima

I'm following up because of the same use case as @mjbvz. It appears $self correctly resolves to the injection grammar itself. The metaphor is self in Ruby. $base doesn't seem to do anything at all. It should resolve to the grammar being targeted by the injection. The metaphor is super in Ruby. I can't imagine a use case for targeting the root grammar. In any case the only documentation I'm aware of is:

https://www.apeth.com/nonblog/stories/textmatebundle.html#:~:text=the%20value%20of%20an%20include%20rule%20can%20also,embedded%2E

Relevant code: https://github.com/microsoft/vscode-textmate/blob/a53ae3c12bef5499a7dc548b3058ee64bfcbd222/src/grammar.ts#L122-L125

texastoland avatar Sep 14 '21 14:09 texastoland

@texastoland The usecase for targeting root grammars was for superset languages E.g. Objective C++ includes C++ which includes C. So when C uses $base it re-activates the root (Objective C++) pattern set. The C family and Latex (Tex, Latex, Katex) are the only two I know of that can even attempt to nest that way. But just because thats what it was designed for doesn't mean its good, and one of the first things we did to C++ was rip out all uses of $base because it is terrible. I don't think $base should ever be used.

While $base has special functionality, $self is purely for convenience. Arguably $self should never be used because it would be more clear to actually state the set of patterns that was being reused instead of just saying "$self" and making other devs look up or guess the behavior.

I agree something like $super would be more useful. Not terribly useful because it would need to be a grammar/injection that was unaware of the parent, yet still wanted to include the parent grammar inside itself. If the grammar knows what language it is being injected into, it can simply specify that language by name instead of trying to use something like $super or $base.

jeff-hykin avatar Sep 15 '21 14:09 jeff-hykin

@jeff-hykin Thanks for your explanation of the reasoning! In any case $base has no effect in my current injection grammar.

I follow your logic about explicit scope names. I'd argue very little about TextMate grammars is documented or even consistent. I've been writing regexes for 15 years yet struggling for more than a week to fix a bug I expected to spend a half day on.

There are more bugs I could track here but I'd really prefer some update on https://github.com/microsoft/vscode/issues/216#issuecomment-913872371 (I know you're even more invested in that topic).

texastoland avatar Sep 15 '21 17:09 texastoland

@texastoland I 100% agree.

Matter123 and I spent years on a library (which I finally published just last week) to make it way less painful. The documentation is still sparse, especially for things like $base and $self, but Textmate is easily one of the worst least-documented tools I've ever used. 90% of what I've learned has been through reading other people's textmate grammars and trial-and-error.

jeff-hykin avatar Sep 16 '21 13:09 jeff-hykin

@texastoland

As an example, I went ahead and created a demo of your f# templates syntax using the library. Hopefully that'll be useful

Here's a link to that demo repo: https://github.com/jeff-hykin/fsharp-injections-demo (you can ignore the readme and other stuff, most of it is leftovers from a template/skeleton I use)

jeff-hykin avatar Sep 16 '21 15:09 jeff-hykin

@jeff-hykin Thanks that was fast! That's the syntax I'm currently rewriting. As I mentioned there are a few tricks to do it much more succinctly than either JSON or Ruby with plain YAML. Understandablly you're working at a bigger scale with C and Bash. But I've been stopped by weird behavior (or just lack of documentation) and a few annoying bugs in this repo. I only reported this 1 because $base literally does nothing in my grammar.

texastoland avatar Sep 16 '21 19:09 texastoland

@texastoland I'll continue the topic over here since this is off topic from the original issue

https://github.com/jeff-hykin/fsharp-injections-demo/issues/1

jeff-hykin avatar Sep 16 '21 21:09 jeff-hykin