Sublime Forum

In a custom syntax, is it possible to make expand selection to scope work if the old scope implicitly ends when the new one starts?

#1

I’m working with a simple language that defines tools. An example of the syntax is:

TOOL <name>
#  tool definition here
END TOOL

I’ve written a custom syntax for this, and it works fine. The part I’m having trouble with is that the “END TOOL” is optional. For example:

TOOL abc
# definition for abc
TOOL def
# definition for def
END TOOL # for def

The idea is that a new “TOOL” declaration implicitly ends the old one. I can certainly write patterns in my custom syntax to match this, and highlighting works as expected. The problem is that in the latter case, “expand selection to scope” doesn’t work. If I have the cursor anywhere in either the abc or def definition, it thinks the enclosing scope is both abc and def. I’m guessing that the reason for this is that the scope for abc doesn’t end until the scope for def starts, so there is no character in the buffer that isn’t in the scope of some tool definition, so it seems that the “scope” includes both of them.

I could make the “TOOL” keyword itself not be part of the tool scope, which would fix this problem (because the old one would end before the new one starts), but I really would rather the scope include the TOOL keyword, too, if that’s possible.

Is there a way to define the syntax such that expanding the selection to the scope does what I want? I would imagine that this is is a general problem. For instance, you don’t know where a python function ends until something else starts (and I’ve noticed that the python syntax doesn’t seem to have a scope for function definitions, so I don’t see anything to pattern-match there).

Thanks.

0 Likes

#2

A Positive Lookahead is probably what you’re looking for. Here are a few links for help.

I would bet this regex will work to identify the end of the block: (^END TOOL\b|\Z|(?=^TOOL\b))

The three alternations are:
^END TOOL\b: general case; \b was added as a basic keyword boundary, your requirements may differ
\Z: end of the file; don’t forget the end of file case if the closing is optional
(?=^TOOL\b): identifies the next tool’s beginning, but still allows the block-start regex to identify correctly

0 Likes

#3

Thanks for your help. I’m actually already using the positive lookahead, exactly as you say (though I wasn’t using \Z and I definitely should be!). My problem isn’t that I can’t identify the end of the tool, it’s that we lose information about where one scope stops and another starts.

For instance,

TOOL abc  # begins scope meta.tool for abc
# definition
TOOL def # pops context/scope for abc, begins scope meta.tool for def
# definition
END TOOL # pops meta.tool for def.

I think the problem is that meta.tool for abc stops at exactly the point in the file that meta.tool for def starts. It seems that “expand selection to scope” sees that as one long scope (abc and def combined) instead of one stopping and another starting at the same point.

Are there any tricks for getting around this?

0 Likes

#4

Only thing I can think of is to exclude the newline char \n from both start & end definitions. If you’ve tried that already then I’m not sure, but I can say that “expand selection to scope” behaves weird at least in Java & bash syntaxes.

0 Likes

#5

Thanks again. I think to do this, you would need to stop at the newline before a new TOOL definition. I don’t see any way to do that, though, because the regex match is a line at a time, so there’s no way to look past the newline to know a new TOOL is coming.

I have thought that I could have two different types of scope, “tool1” and “tool2” and have them ping-pong. I think it would make the expand-selection thing work, but of course, it’s a hack that would complicate everything else (because there would be two different scopes that both mean the same thing).

I have also noticed expand selection to scope behaving weirdly in other syntaxes. I just thought that if there’s a way to do it right, that would be great. Otherwise, I may just need to live with it.

0 Likes