On 25 Mar 2015, at 22:12, Jacob Carlborg wrote:
I'm trying to match the following code in the D
language grammar:
static if (true) {}
void foo ()
{
static if (true) {}
}
The first static-if is correctly recognized as
"keyword.control.conditional.d". But the static-if inside "foo" is
recognized as a method "meta.definition.method.d". I managed to get
the top level static-if correctly recognized by moving the pattern for
the static-if before the pattern for a method. But I don't understand
why that doesn't work inside "foo".
This is because of the indent. The rule for
‘meta.definition.method.d’ will match from the start of the line
(eating leading whitespace), so while the static keyword rule has
precedence, this rule cannot match at the beginning of the line (where
there is just whitespace), so TextMate will instead pick the rule that
can match.
You could prefix the keyword.control.conditional.d pattern with (^\s+)
so that this rule will also be a candidate when at the beginning of the
line, though in general having rules match leading whitespace makes the
grammar more difficult to work with (as you’ll get these unexpected
issues).
Another thing I noticed is the "static if"
on the top level seems to
be recognized as a single word. When I use the hot keys for moving the
cursor a word it jumps from the start of "static" to the end of "if",
instead of to the end of "static".
This is because the whitespace between the two keywords are scoped as a
keyword, so TextMate consider the entire thing a single unit for
character movement (and word selection, etc.).
One way to fix this is by using captures for the non-whitespace and only
assigning a scope name to the captures, e.g.:
{ match =
'\b(?:(?<keyword>static)\s+)?(?<keyword>if|else|switch)\b';
captures = {
keyword = { name = 'keyword.control.conditional.d'; };
};
},
For more info about character classes (which is used for word movement)
see this blog post:
http://blog.macromates.com/2012/clever-completion/