diff --git a/package.json b/package.json index cbf421ef5..3b4e03880 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,10 @@ "git-utils": "^1.1.1", "guid": "0.0.10", "jasmine-tagged": ">=1.1.1 <2.0", - "mkdirp": "0.3.5", "keytar": "1.x", "less-cache": "0.12.0", "mixto": "1.x", + "mkdirp": "0.3.5", "nslog": "0.5.0", "oniguruma": "^1.0.4", "optimist": "0.4.0", @@ -41,6 +41,7 @@ "random-words": "0.0.1", "runas": "0.5.x", "scandal": "0.15.0", + "scoped-property-store": "^0.3.0", "scrollbar-style": "^0.1.0", "season": ">=1.0.2 <2.0", "semver": "1.1.4", @@ -49,7 +50,7 @@ "temp": "0.5.0", "text-buffer": "^1.4.4", "theorist": "1.x", - "underscore-plus": ">=1.0.5 <2.0", + "underscore-plus": "^1.1.0", "vm-compatibility-layer": "0.1.0" }, "packageDependencies": { diff --git a/src/syntax.coffee b/src/syntax.coffee index 881d5fa2a..793d070b2 100644 --- a/src/syntax.coffee +++ b/src/syntax.coffee @@ -2,6 +2,7 @@ _ = require 'underscore-plus' {specificity} = require 'clear-cut' {Subscriber} = require 'emissary' {GrammarRegistry, ScopeSelector} = require 'first-mate' +ScopedPropertyStore = require 'scoped-property-store' {$, $$} = require './space-pen-extensions' Token = require './token' @@ -24,9 +25,7 @@ class Syntax extends GrammarRegistry constructor: -> super - - @scopedPropertiesIndex = 0 - @scopedProperties = [] + @scopedProperties = new ScopedPropertyStore serialize: -> {deserializer: @constructor.name, @grammarOverridesByPath} @@ -36,22 +35,15 @@ class Syntax extends GrammarRegistry addProperties: (args...) -> name = args.shift() if args.length > 2 [selector, properties] = args - - @scopedProperties.unshift( - name: name - selector: selector, - properties: properties, - specificity: specificity(selector), - index: @scopedPropertiesIndex++ - ) + propertiesBySelector = {} + propertiesBySelector[selector] = properties + @scopedProperties.addProperties(name, propertiesBySelector) removeProperties: (name) -> - for properties in @scopedProperties.filter((properties) -> properties.name is name) - _.remove(@scopedProperties, properties) + @scopedProperties.removeProperties(name) clearProperties: -> - @scopedProperties = [] - @scopedPropertiesIndex = 0 + @scopedProperties = new ScopedPropertyStore # Public: Get a property for the given scope and key path. # @@ -66,48 +58,21 @@ class Syntax extends GrammarRegistry # # Returns a {String} property value or undefined. getProperty: (scope, keyPath) -> - for object in @propertiesForScope(scope, keyPath) - value = _.valueForKeyPath(object, keyPath) - return value if value? - undefined + scopeChain = scope + .map (scope) -> + scope = ".#{scope}" unless scope.indexOf('.') is 0 + scope + .join(' ') + @scopedProperties.getPropertyValue(scopeChain, keyPath) propertiesForScope: (scope, keyPath) -> - matchingProperties = [] - candidates = @scopedProperties.filter ({properties}) -> _.valueForKeyPath(properties, keyPath)? - if candidates.length - element = @buildScopeElement(scope) - while element - matchingProperties.push(@matchingPropertiesForElement(element, candidates)...) - element = element.parentNode - matchingProperties + scopeChain = scope + .map (scope) -> + scope = ".#{scope}" unless scope.indexOf('.') is 0 + scope + .join(' ') - matchingPropertiesForElement: (element, candidates) -> - matchingScopedProperties = candidates.filter ({selector}) -> - $.find.matchesSelector(element, selector) - matchingScopedProperties.sort (a, b) -> - if a.specificity == b.specificity - b.index - a.index - else - b.specificity - a.specificity - _.pluck matchingScopedProperties, 'properties' - - buildScopeElement: (scope) -> - scope = scope.slice() - element = $$ -> - elementsForRemainingScopes = => - classString = scope.shift() - classes = classString.replace(/^\./, '').replace(/\./g, ' ') - if scope.length - @div class: classes, elementsForRemainingScopes - else - @div class: classes - elementsForRemainingScopes() - - deepestChild = element.find(":not(:has(*))") - if deepestChild.length - deepestChild[0] - else - element[0] + @scopedProperties.getProperties(scopeChain, keyPath) cssSelectorFromScopeSelector: (scopeSelector) -> new ScopeSelector(scopeSelector).toCssSelector()