Add TextMateScopeSelector.toCssSelector()

This commit is contained in:
Kevin Sawicki 2013-08-06 14:34:21 -07:00
parent f010e8a888
commit faf02460f5
3 changed files with 81 additions and 46 deletions

View File

@ -1,52 +1,63 @@
TextMateScopeSelector = require 'text-mate-scope-selector'
describe "TextMateScopeSelector", ->
it "matches the asterix", ->
expect(new TextMateScopeSelector('*').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('*').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.d.c'])).toBeFalsy()
describe ".matches(scopes)", ->
it "matches the asterix", ->
expect(new TextMateScopeSelector('*').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('*').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.d.c'])).toBeFalsy()
it "matches prefixes", ->
expect(new TextMateScopeSelector('a').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['a.b'])).toBeTruthy()
expect(new TextMateScopeSelector('a.b').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['abc'])).toBeFalsy()
expect(new TextMateScopeSelector('a.b-c').matches(['a.b-c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.b').matches(['a.b-d'])).toBeFalsy()
it "matches prefixes", ->
expect(new TextMateScopeSelector('a').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['a.b'])).toBeTruthy()
expect(new TextMateScopeSelector('a.b').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['abc'])).toBeFalsy()
expect(new TextMateScopeSelector('a.b-c').matches(['a.b-c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.b').matches(['a.b-d'])).toBeFalsy()
it "matches disjunction", ->
expect(new TextMateScopeSelector('a | b').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['d'])).toBeFalsy()
it "matches disjunction", ->
expect(new TextMateScopeSelector('a | b').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['d'])).toBeFalsy()
it "matches negation", ->
expect(new TextMateScopeSelector('a - c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a-b').matches(['a', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a -b').matches(['a', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a -c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a-c').matches(['a', 'b'])).toBeFalsy()
it "matches negation", ->
expect(new TextMateScopeSelector('a - c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a-b').matches(['a', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a -b').matches(['a', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a -c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a-c').matches(['a', 'b'])).toBeFalsy()
it "matches conjunction", ->
expect(new TextMateScopeSelector('a & b').matches(['b', 'a'])).toBeTruthy()
expect(new TextMateScopeSelector('a&b&c').matches(['c'])).toBeFalsy()
expect(new TextMateScopeSelector('a&b&c').matches(['a', 'b', 'd'])).toBeFalsy()
it "matches conjunction", ->
expect(new TextMateScopeSelector('a & b').matches(['b', 'a'])).toBeTruthy()
expect(new TextMateScopeSelector('a&b&c').matches(['c'])).toBeFalsy()
expect(new TextMateScopeSelector('a&b&c').matches(['a', 'b', 'd'])).toBeFalsy()
it "matches composites", ->
expect(new TextMateScopeSelector('a,b,c').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'e'])).toBeFalsy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'c.e'])).toBeTruthy()
it "matches composites", ->
expect(new TextMateScopeSelector('a,b,c').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'e'])).toBeFalsy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'c.e'])).toBeTruthy()
it "matches groups", ->
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['d'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['e'])).toBeFalsy()
it "matches groups", ->
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['d'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['e'])).toBeFalsy()
it "matches paths", ->
expect(new TextMateScopeSelector('a b').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a b').matches(['b', 'a'])).toBeFalsy()
expect(new TextMateScopeSelector('a c').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
expect(new TextMateScopeSelector('a b e').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
it "matches paths", ->
expect(new TextMateScopeSelector('a b').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a b').matches(['b', 'a'])).toBeFalsy()
expect(new TextMateScopeSelector('a c').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
expect(new TextMateScopeSelector('a b e').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
describe ".toCssSelector()", ->
it "converts the TextMate scope selector to a CSS selector", ->
expect(new TextMateScopeSelector('a b c').toCssSelector()).toBe '.a .b .c'
expect(new TextMateScopeSelector('a.b.c').toCssSelector()).toBe '.a.b.c'
expect(new TextMateScopeSelector('*').toCssSelector()).toBe '*'
expect(new TextMateScopeSelector('a - b').toCssSelector()).toBe '.a :not(.b)'
expect(new TextMateScopeSelector('a & b').toCssSelector()).toBe '.a .b'
expect(new TextMateScopeSelector('a | b').toCssSelector()).toBe '.a .b'
expect(new TextMateScopeSelector('a - (b.c d)').toCssSelector()).toBe '.a :not(.b.c .d)'

View File

@ -6,14 +6,19 @@ class SegmentMatcher
constructor: (segment) ->
@segment = _.flatten(segment).join('')
matches: (scope) ->
scope is @segment
matches: (scope) -> scope is @segment
toCssSelector: ->
@segment.split('.').map((dotFragment) ->
'.' + dotFragment.replace(/\+/g, '\\+')
).join('')
class TrueMatcher
constructor: ->
matches: ->
true
matches: -> true
toCssSelector: -> '*'
class ScopeMatcher
constructor: (first, others) ->
@ -29,6 +34,9 @@ class ScopeMatcher
true
toCssSelector: ->
@segments.map((matcher) -> matcher.toCssSelector()).join('')
class PathMatcher
constructor: (first, others) ->
@matchers = [first]
@ -42,24 +50,36 @@ class PathMatcher
return true unless matcher?
false
toCssSelector: ->
@matchers.map((matcher) -> matcher.toCssSelector()).join(' ')
class OrMatcher
constructor: (@left, @right) ->
matches: (scopes) ->
@left.matches(scopes) or @right.matches(scopes)
toCssSelector: ->
"#{@left.toCssSelector()} #{@right.toCssSelector()}"
class AndMatcher
constructor: (@left, @right) ->
matches: (scopes) ->
@left.matches(scopes) and @right.matches(scopes)
toCssSelector: ->
"#{@left.toCssSelector()} #{@right.toCssSelector()}"
class NegateMatcher
constructor: (@left, @right) ->
matches: (scopes) ->
@left.matches(scopes) and not @right.matches(scopes)
toCssSelector: ->
"#{@left.toCssSelector()} :not(#{@right.toCssSelector()})"
class CompositeMatcher
constructor: (left, operator, right) ->
switch operator
@ -70,6 +90,8 @@ class CompositeMatcher
matches: (scopes) ->
@matcher.matches(scopes)
toCssSelector: -> @matcher.toCssSelector()
module.exports = {
AndMatcher
CompositeMatcher

View File

@ -28,3 +28,5 @@ class TextMateScopeSelector
# Return a {Boolean}.
matches: (scopes) ->
@matcher.matches(scopes)
toCssSelector: -> @matcher.toCssSelector()