[TxMt] Re: Grammar injection. Main grammar taking priority?

Allan Odgaard mailinglist at textmate.org
Mon May 30 20:06:09 UTC 2016

On 16 May 2016, at 17:29, Daniel Rodríguez Troitiño wrote:

> A simple version of my grammar looks like this:
> […]
> 'source.swift.gyb - (meta.embedded.block.gyb)' = {

The injection scope selector should use L:(…) so your injected rules 
go before Swift’s (as you also write yourself).

> { begin = '(^|\s*)(?=%\{(?![^\}]*\}%))';

This seems to be the problem, this rule doesn’t actually match 
anything as it’s a “begin of line” assertion and then a “look 
ahead” assertion.

So while the rule “matches” when you have `%{` at the beginning of a 
line, no characters are consumed, so we descend into the rule’s 
patterns, but here we also have the Swift rules, and the L:(…) only 
affects the priority of the root rules injected (not their children), so 
the Swift rule will consume the `%` character because it was not 
consumed by the parent rule’s begin pattern.

A minimal version of your grammar that works would be this:

     {   injections = {
             'L:(source.swift.gyb - meta.embedded.block.gyb)' = {
                 patterns = (
                     {   name = 'meta.embedded.block.gyb';
                         begin = '%\{';
                         end = '\}%';
                         contentName = 'source.python';
                         patterns = ( { include = 'source.python'; } );
         patterns = ( { include = 'source.swift'; } );

I understand you wanted to scope the leading/trailing whitespace and 
then re-use the actual matching of %{ and %}, but I don’t think this 
is possible, though I think it will be simpler to add optional matches 
like this:

     begin = '(^\s*)?%\{';
     end = '\}%(\s*$)?';

Then name these captures for 

More information about the textmate mailing list