In the Help for TextMate, the following are given as examples of legal selectors (with explanations of what they mean / match):
text.html.ruby, text.html source.ruby string string.quoted source.php string text.html source.php source.ruby string source.ruby string - string source string, comment
So, operators here are space, comma-space, and space-minus-space. It appears that space has highest priority, then space-minus-space, then comma. (Or so I would presume.) So far, then, it all seems quite coherent; I grok prefix-matching, descendancy, exclusion, and OR (the comma is apparently an OR operator, even though the help rather confusingly seems to describe it as an AND).
Then, in a blog entry (http://blog.macromates.com/2005/introduction-to-scopes/), additional info is given:
(a | b) & c - d
I find that last one incoherent; I don't get where the pieces are or how the operators here fit, priority-wise, with the previously given operators. For example, which of the selectors given in the first list would be a legal substitute for "b" here? And conversely, for which expressions in the first list of legal selectors, if any, could this expression be substituted?
So, my question is: Can I somewhere get a formal coherent definition of the rules of selector syntax?
m.
On 25 Jun 2008, at 21:07, Matt Neuburg wrote:
In the Help for TextMate, the following are given as examples of legal selectors (with explanations of what they mean / match): [...] Then, in a blog entry (http://blog.macromates.com/2005/introduction-to-scopes/), additional info is given:
(a | b) & c - d
I find that last one incoherent; I don't get where the pieces are or how the operators here fit, priority-wise, with the previously given operators. For example, which of the selectors given in the first list would be a legal substitute for "b" here? And conversely, for which expressions in the first list of legal selectors, if any, could this expression be substituted?
So, my question is: Can I somewhere get a formal coherent definition of the rules of selector syntax?
I’ll see if I can’t add a BNF section to the manual. I won’t be online for an unknown amount of time, so not sure when I will push this.
As for your concrete question, in the last example you quote, a, b, c, and d can all be scope selectors of the form given in the manual section 13.1 or 13.2 (13.1 being a subset of 13.2).
So scopes are matched literally (e.g. “string”). These can form a “descendent selector” (13.2) e.g. “source.ruby string”, and for descendent selectors one can take the union (| or ,), the intersection (&), or the asymmetric difference (-).
As for the exact precedence of these operators, I’ll have to check the grammar in the source, but one can also group with parenthesis. The reason though that both , and | can be used for union is that , was introduced long before the other operators (mimics CSS syntax), so when & was added, I felt that there should be | and | has higher precedence than , it is the operator with lowest precedence, so e.g.:
a - b | c & d, e - f | g & h ⇔ (a - b | c & d), (e - f | g & h)
A bit like | versus || in C.
On 6/26/08 12:26 PM, in article D1A1823C-0A05-4D17-855F-82737CA19FDF@textmate.org, "Allan Odgaard" mailinglist@textmate.org wrote:
As for your concrete question, in the last example you quote, a, b, c,
and d
can all be scope selectors of the form given in the manual
section 13.1 or
13.2 (13.1 being a subset of 13.2).
So scopes are matched literally (e.g.
³string²). These can form a
³descendent selector² (13.2) e.g. ³source.ruby
string², and for
descendent selectors one can take the union (| or ,), the
intersection
(&), or the asymmetric difference (-).
That's a big help, thanks. My last question would then be how all of that fits in with what it says in section 13.5 in the online help about ranking selectors. I see how one can use those rules to rank two selectors whose only operator internally is a space, e.g.
text source string
vs.
source string
But how on earth is one to make sense of the concept "the element deepest down" when a selector is of the form
a - b | c & d, e - f | g & h
?? Even if I can make sense of that, what happens when we get to rule 3, "remove the deepest element"? The deepest element of *what*?
Thx - m.
On 27 Jun 2008, at 00:40, Matt Neuburg wrote:
[...] My last question would then be how all of that fits in with what it says in section 13.5 in the online help about ranking selectors. I see how one can use those rules to rank two selectors [...]
But how on earth is one to make sense of the concept "the element deepest down" when a selector is of the form
a - b | c & d, e - f | g & h
?? [...]
In practice a numeric score is calculated for a scope selector match.
The score will be 1.0 for full overlap between scope and scope selector, 0.0 for no overlap (i.e. empty scope selector), and below zero for “negative overlap” (i.e. the scope selector has elements not part of the scope). The values between 0.0 and 1.0 are calculated corresponding to the rules given in 13.5 (done by effectively converting each fragment of the scope to a fraction and have all those numbers form a harmonic serie and then add the fractions that correspond to fragments matched by the scope selector).
With a numeric score for each scope selector match it is trivial to calculate the score of a compound expression. E.g.: score(a | b) = max(score(a), score(b)).
On 6/29/08 4:06 AM, in article B8C096E6-5D62-4577-81ED-1CB6E863E1FC@textmate.org, "Allan Odgaard" mailinglist@textmate.org wrote:
On 27 Jun 2008, at 00:40, Matt Neuburg wrote:
[...] My last question would then be how all of that fits in with what it says in section 13.5 in the online help about ranking selectors. I see how one can use those rules to rank two selectors [...]
But how on earth is one to make sense of the concept "the element deepest down" when a selector is of the form
a - b | c & d, e - f | g & h
?? [...]
In practice a numeric score is calculated for a scope selector match.
The score will be 1.0 for full overlap between scope and scope selector, 0.0 for no overlap (i.e. empty scope selector), and below zero for ³negative overlap² (i.e. the scope selector has elements not part of the scope). The values between 0.0 and 1.0 are calculated corresponding to the rules given in 13.5 (done by effectively converting each fragment of the scope to a fraction and have all those numbers form a harmonic serie and then add the fractions that correspond to fragments matched by the scope selector).
With a numeric score for each scope selector match it is trivial to calculate the score of a compound expression. E.g.: score(a | b) = max(score(a), score(b)).
And what about score(a & b)? You say "trivial" but it is not at all obvious to me what scoring strategy is right to adopt here.
And I repeat, what about rule 3 in section 13.5? Suppose
score ((a | b) & c) == score ((d & e) | f)
In order to choose between them, we are now to recurse, trying again with a shorter selector expression ("removing the deepest element"). What selector expression am I to shorten? I see how to shorten a simple descendant selector:
string source => string
But I do not see how to shorten
((string source) & ruby)
m.
On 29 Jun 2008, at 18:41, Matt Neuburg wrote:
In practice a numeric score is calculated for a scope selector match.
The score will be 1.0 for full overlap between scope and scope selector, 0.0 for no overlap (i.e. empty scope selector), and below zero for “negative overlap” (i.e. the scope selector has elements not part of the scope). The values between 0.0 and 1.0 are calculated corresponding to the rules given in 13.5 (done by effectively converting each fragment of the scope to a fraction and have all those numbers form a harmonic serie and then add the fractions that correspond to fragments matched by the scope selector).
With a numeric score for each scope selector match it is trivial to calculate the score of a compound expression. E.g.: score(a | b) = max(score(a), score(b)).
And what about score(a & b)? You say "trivial" but it is not at all obvious to me what scoring strategy is right to adopt here.
And I repeat, what about rule 3 in section 13.5? Suppose
Forget about 13.5 and re-read my part about numeric scores. One number is calculated, it is not an iterative algorithm. 13.5 is just describing the effect of how these numbers (ranks) are calculated, but in practice it is done as a simple optimization problem.
[...] But I do not see how to shorten
((string source) & ruby)
This will be: max(score(string source), score(ruby))
Assuming both scores are ≥ 0 (otherwise the result will be -1, i.e. not a match).