mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
Use ScopeSelector class from first-mate
Begin migrating TextMate helpers out of src/ and into the first-mate package.
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
TextMateScopeSelector = require 'text-mate-scope-selector'
|
||||
|
||||
describe "TextMateScopeSelector", ->
|
||||
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()
|
||||
expect(new TextMateScopeSelector('c++').matches(['c++'])).toBeTruthy()
|
||||
expect(new TextMateScopeSelector('c++').matches(['c'])).toBeFalsy()
|
||||
expect(new TextMateScopeSelector('a_b_c').matches(['a_b_c'])).toBeTruthy()
|
||||
expect(new TextMateScopeSelector('a_b_c').matches(['a_b'])).toBeFalsy()
|
||||
|
||||
it "matches filters", ->
|
||||
expect(new TextMateScopeSelector('R:g').matches(['g'])).toBeTruthy()
|
||||
|
||||
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 - c').matches(['a'])).toBeTruthy()
|
||||
expect(new TextMateScopeSelector('-c').matches(['b'])).toBeTruthy()
|
||||
expect(new TextMateScopeSelector('-c').matches(['c', 'b'])).toBeFalsy()
|
||||
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()
|
||||
expect(new TextMateScopeSelector('a & -b').matches(['a', 'b', 'd'])).toBeFalsy()
|
||||
expect(new TextMateScopeSelector('a & -b').matches(['a', 'd'])).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()
|
||||
expect(new TextMateScopeSelector('a,').matches(['a', 'c'])).toBeTruthy()
|
||||
expect(new TextMateScopeSelector('a,').matches(['b', 'c'])).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()
|
||||
|
||||
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:not(.b)'
|
||||
expect(new TextMateScopeSelector('a | b').toCssSelector()).toBe '.a, .b'
|
||||
expect(new TextMateScopeSelector('a - (b.c d)').toCssSelector()).toBe '.a:not(.b.c .d)'
|
||||
expect(new TextMateScopeSelector('a, b').toCssSelector()).toBe '.a, .b'
|
||||
@@ -11,7 +11,7 @@ Selection = require 'selection'
|
||||
EventEmitter = require 'event-emitter'
|
||||
Subscriber = require 'subscriber'
|
||||
Range = require 'range'
|
||||
TextMateScopeSelector = require 'text-mate-scope-selector'
|
||||
TextMateScopeSelector = require('first-mate').ScopeSelector
|
||||
|
||||
# An `EditSession` manages the states between {Editor}s, {Buffer}s, and the project as a whole.
|
||||
module.exports =
|
||||
|
||||
@@ -5,7 +5,7 @@ Specificity = require 'specificity'
|
||||
fsUtils = require 'fs-utils'
|
||||
EventEmitter = require 'event-emitter'
|
||||
NullGrammar = require 'null-grammar'
|
||||
TextMateScopeSelector = require 'text-mate-scope-selector'
|
||||
TextMateScopeSelector = require('first-mate').ScopeSelector
|
||||
|
||||
### Internal ###
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Token = require 'token'
|
||||
{OnigRegExp, OnigScanner} = require 'oniguruma'
|
||||
path = require 'path'
|
||||
EventEmitter = require 'event-emitter'
|
||||
TextMateScopeSelector = require 'text-mate-scope-selector'
|
||||
{ScopeSelector} = require 'first-mate'
|
||||
|
||||
pathSplitRegex = new RegExp("[#{path.sep}.]")
|
||||
|
||||
@@ -40,7 +40,7 @@ class TextMateGrammar
|
||||
@injections = new Injections(this, injections)
|
||||
|
||||
if injectionSelector?
|
||||
@injectionSelector = new TextMateScopeSelector(injectionSelector)
|
||||
@injectionSelector = new ScopeSelector(injectionSelector)
|
||||
|
||||
@firstLineRegex = new OnigRegExp(firstLineMatch) if firstLineMatch
|
||||
@fileTypes ?= []
|
||||
@@ -197,7 +197,7 @@ class Injections
|
||||
patterns.push(pattern.getIncludedPatterns(grammar, patterns)...)
|
||||
@injections.push
|
||||
anchored: anchored
|
||||
selector: new TextMateScopeSelector(selector)
|
||||
selector: new ScopeSelector(selector)
|
||||
patterns: patterns
|
||||
|
||||
getScanner: (injection, firstLine, position, anchorPosition) ->
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
### Internal ###
|
||||
|
||||
class SegmentMatcher
|
||||
constructor: (segment) ->
|
||||
@segment = _.flatten(segment).join('')
|
||||
|
||||
matches: (scope) -> scope is @segment
|
||||
|
||||
toCssSelector: ->
|
||||
@segment.split('.').map((dotFragment) ->
|
||||
'.' + dotFragment.replace(/\+/g, '\\+')
|
||||
).join('')
|
||||
|
||||
class TrueMatcher
|
||||
constructor: ->
|
||||
|
||||
matches: -> true
|
||||
|
||||
toCssSelector: -> '*'
|
||||
|
||||
class ScopeMatcher
|
||||
constructor: (first, others) ->
|
||||
@segments = [first]
|
||||
@segments.push(segment[1]) for segment in others
|
||||
|
||||
matches: (scope) ->
|
||||
scopeSegments = scope.split('.')
|
||||
return false if scopeSegments.length < @segments.length
|
||||
|
||||
for segment, index in @segments
|
||||
return false unless segment.matches(scopeSegments[index])
|
||||
|
||||
true
|
||||
|
||||
toCssSelector: ->
|
||||
@segments.map((matcher) -> matcher.toCssSelector()).join('')
|
||||
|
||||
class PathMatcher
|
||||
constructor: (first, others) ->
|
||||
@matchers = [first]
|
||||
@matchers.push(matcher[1]) for matcher in others
|
||||
|
||||
matches: (scopes) ->
|
||||
index = 0
|
||||
matcher = @matchers[index]
|
||||
for scope in scopes
|
||||
matcher = @matchers[++index] if matcher.matches(scope)
|
||||
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: ->
|
||||
if @right instanceof NegateMatcher
|
||||
"#{@left.toCssSelector()}#{@right.toCssSelector()}"
|
||||
else
|
||||
"#{@left.toCssSelector()} #{@right.toCssSelector()}"
|
||||
|
||||
class NegateMatcher
|
||||
constructor: (@matcher) ->
|
||||
|
||||
matches: (scopes) -> not @matcher.matches(scopes)
|
||||
|
||||
toCssSelector: -> ":not(#{@matcher.toCssSelector()})"
|
||||
|
||||
class CompositeMatcher
|
||||
constructor: (left, operator, right) ->
|
||||
switch operator
|
||||
when '|' then @matcher = new OrMatcher(left, right)
|
||||
when '&' then @matcher = new AndMatcher(left, right)
|
||||
when '-' then @matcher = new AndMatcher(left, new NegateMatcher(right))
|
||||
|
||||
matches: (scopes) -> @matcher.matches(scopes)
|
||||
|
||||
toCssSelector: -> @matcher.toCssSelector()
|
||||
|
||||
module.exports = {
|
||||
AndMatcher
|
||||
CompositeMatcher
|
||||
NegateMatcher
|
||||
OrMatcher
|
||||
PathMatcher
|
||||
ScopeMatcher
|
||||
SegmentMatcher
|
||||
TrueMatcher
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
{
|
||||
var matchers = require('text-mate-scope-selector-matchers');
|
||||
}
|
||||
|
||||
start = _ selector:(selector) _ {
|
||||
return selector;
|
||||
}
|
||||
|
||||
segment
|
||||
= _ segment:([a-zA-Z0-9+_]+[a-zA-Z0-9-+_]*) _ {
|
||||
return new matchers.SegmentMatcher(segment);
|
||||
}
|
||||
|
||||
/ _ scopeName:[\*] _ {
|
||||
return new matchers.TrueMatcher();
|
||||
}
|
||||
|
||||
scope
|
||||
= first:segment others:("." segment)* {
|
||||
return new matchers.ScopeMatcher(first, others);
|
||||
}
|
||||
|
||||
path
|
||||
= first:scope others:(_ scope)* {
|
||||
return new matchers.PathMatcher(first, others);
|
||||
}
|
||||
|
||||
group
|
||||
= "(" _ selector:selector _ ")" {
|
||||
return selector;
|
||||
}
|
||||
|
||||
filter
|
||||
= prefix:([LRB]":") _ group:group {
|
||||
return group;
|
||||
}
|
||||
|
||||
/ prefix:([LRB]":") _ path:path {
|
||||
return path;
|
||||
}
|
||||
|
||||
expression
|
||||
= "-" _ filter:filter _ {
|
||||
return new matchers.NegateMatcher(filter);
|
||||
}
|
||||
|
||||
/ "-" _ group:group _ {
|
||||
return new matchers.NegateMatcher(group);
|
||||
}
|
||||
|
||||
/ "-" _ path:path _ {
|
||||
return new matchers.NegateMatcher(path);
|
||||
}
|
||||
|
||||
/ filter
|
||||
|
||||
/ group
|
||||
|
||||
/ path
|
||||
|
||||
composite
|
||||
= left:expression _ operator:[|&-] _ right:composite {
|
||||
return new matchers.CompositeMatcher(left, operator, right);
|
||||
}
|
||||
|
||||
/ expression
|
||||
|
||||
selector
|
||||
= left:composite _ "," _ right:selector? {
|
||||
if (right)
|
||||
return new matchers.OrMatcher(left, right);
|
||||
else
|
||||
return left;
|
||||
}
|
||||
|
||||
/ composite
|
||||
|
||||
_
|
||||
= [ \t]*
|
||||
@@ -1,32 +0,0 @@
|
||||
PEG = require 'pegjs'
|
||||
fsUtils = require 'fs-utils'
|
||||
|
||||
# Internal: Test a stack of scopes to see if they match a scope selector.
|
||||
module.exports =
|
||||
class TextMateScopeSelector
|
||||
@parser: null
|
||||
|
||||
@createParser: ->
|
||||
unless TextMateScopeSelector.parser?
|
||||
patternPath = require.resolve('text-mate-scope-selector-pattern.pegjs')
|
||||
TextMateScopeSelector.parser = PEG.buildParser(fsUtils.read(patternPath))
|
||||
TextMateScopeSelector.parser
|
||||
|
||||
source: null
|
||||
matcher: null
|
||||
|
||||
# Create a new scope selector.
|
||||
#
|
||||
# source - A {String} to parse as a scope selector.
|
||||
constructor: (@source) ->
|
||||
@matcher = TextMateScopeSelector.createParser().parse(@source)
|
||||
|
||||
# Check if this scope selector matches the scopes.
|
||||
#
|
||||
# scopes - An {Array} of {String}s.
|
||||
#
|
||||
# Return a {Boolean}.
|
||||
matches: (scopes) ->
|
||||
@matcher.matches(scopes)
|
||||
|
||||
toCssSelector: -> @matcher.toCssSelector()
|
||||
@@ -8,8 +8,8 @@ module.exports =
|
||||
return unless token?
|
||||
|
||||
unless @selector?
|
||||
TextMateScopeSelector = require 'text-mate-scope-selector'
|
||||
@selector = new TextMateScopeSelector('markup.underline.link')
|
||||
{ScopeSelector} = require 'first-mate'
|
||||
@selector = new ScopeSelector('markup.underline.link')
|
||||
|
||||
if @selector.matches(token.scopes)
|
||||
require('shell').openExternal token.value
|
||||
|
||||
Reference in New Issue
Block a user