Start on syntax global. Use it to replace scoped config settings.

We'll store all syntax-related global state in the `syntax` global. For
now, this means that all scoped properties will be stored here, as well
as all grammars.
This commit is contained in:
Nathan Sobo
2012-12-23 12:50:58 -07:00
parent aaac5a8659
commit 886995364f
6 changed files with 97 additions and 92 deletions

View File

@@ -34,33 +34,11 @@ class Config
userConfig = JSON.parse(fs.read(configJsonPath))
_.extend(@settings, userConfig)
get: (args...) ->
scopeStack = args.shift() if args.length > 1
keyPath = args.shift()
keys = @keysForKeyPath(keyPath)
settingsToSearch = []
settingsToSearch.push(@settingsForScopeChain(scopeStack)...) if scopeStack
settingsToSearch.push(@settings)
for settings in settingsToSearch
value = settings
for key in keys
value = value[key]
break unless value?
return value if value?
undefined
set: (args...) ->
scope = args.shift() if args.length > 2
keyPath = args.shift()
value = args.shift()
keys = @keysForKeyPath(keyPath)
if scope
keys.unshift(scope)
keys.unshift('scopes')
get: (keyPath) ->
_.valueForKeyPath(@settings, keyPath)
set: (keyPath, value) ->
keys = keyPath.split('.')
hash = @settings
while keys.length > 1
key = keys.shift()
@@ -72,7 +50,7 @@ class Config
value
setDefaults: (keyPath, defaults) ->
keys = @keysForKeyPath(keyPath)
keys = keyPath.split('.')
hash = @settings
for key in keys
hash[key] ?= {}
@@ -102,46 +80,6 @@ class Config
save: ->
fs.write(configJsonPath, JSON.stringify(@settings, undefined, 2) + "\n")
keysForKeyPath: (keyPath) ->
if typeof keyPath is 'string'
keyPath.split(".")
else
new Array(keyPath...)
settingsForScopeChain: (scopeStack) ->
return [] unless @settings.scopes?
matchingScopeSelectors = []
node = @buildDomNodeFromScopeChain(scopeStack)
while node
scopeSelectorsForNode = []
for scopeSelector of @settings.scopes
if jQuery.find.matchesSelector(node, scopeSelector)
scopeSelectorsForNode.push(scopeSelector)
scopeSelectorsForNode.sort (a, b) -> Specificity(b) - Specificity(a)
matchingScopeSelectors.push(scopeSelectorsForNode...)
node = node.parentNode
matchingScopeSelectors.map (scopeSelector) => @settings.scopes[scopeSelector]
buildDomNodeFromScopeChain: (scopeStack) ->
scopeStack = new Array(scopeStack...)
element = $$ ->
elementsForRemainingScopes = =>
classString = scopeStack.shift()
classes = classString.replace(/^\./, '').replace(/\./g, ' ')
if scopeStack.length
@div class: classes, elementsForRemainingScopes
else
@div class: classes
elementsForRemainingScopes()
deepestChild = element.find(":not(:has(*))")
if deepestChild.length
deepestChild[0]
else
element[0]
requireUserInitScript: ->
try
require userInitScriptPath if fs.exists(userInitScriptPath)

59
src/app/syntax.coffee Normal file
View File

@@ -0,0 +1,59 @@
_ = require 'underscore'
jQuery = require 'jquery'
Specificity = require 'specificity'
{$$} = require 'space-pen'
module.exports =
class Syntax
constructor: ->
@globalProperties = {}
@propertiesBySelector = {}
addProperties: (args...) ->
scopeSelector = args.shift() if args.length > 1
properties = args.shift()
if scopeSelector
@propertiesBySelector[scopeSelector] ?= {}
_.extend(@propertiesBySelector[scopeSelector], properties)
else
_.extend(@globalProperties, properties)
getProperty: (scope, keyPath) ->
for object in @propertiesForScope(scope)
value = _.valueForKeyPath(object, keyPath)
return value if value?
undefined
propertiesForScope: (scope) ->
matchingSelectors = []
element = @buildScopeElement(scope)
while element
matchingSelectors.push(@matchingSelectorsForElement(element)...)
element = element.parentNode
properties = matchingSelectors.map (selector) => @propertiesBySelector[selector]
properties.concat([@globalProperties])
matchingSelectorsForElement: (element) ->
matchingSelectors = []
for selector of @propertiesBySelector
matchingSelectors.push(selector) if jQuery.find.matchesSelector(element, selector)
matchingSelectors.sort (a, b) -> Specificity(b) - Specificity(a)
buildScopeElement: (scope) ->
scope = new Array(scope...)
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]

View File

@@ -9,6 +9,7 @@ _ = require 'underscore'
$ = require 'jquery'
{CoffeeScript} = require 'coffee-script'
Config = require 'config'
Syntax = require 'syntax'
RootView = require 'root-view'
Pasteboard = require 'pasteboard'
require 'jquery-extensions'
@@ -25,6 +26,7 @@ windowAdditions =
# in all environments: spec, benchmark, and application
startup: ->
@config = new Config
@syntax = new Syntax
TextMateTheme.loadAll()
@setUpKeymap()
@pasteboard = new Pasteboard

View File

@@ -85,3 +85,10 @@ _.mixin
endsWith: (string, suffix) ->
string.indexOf(suffix, string.length - suffix.length) isnt -1
valueForKeyPath: (object, keyPath) ->
keys = keyPath.split('.')
for key in keys
object = object[key]
return unless object?
object