mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
The requiring of a package's main module is now decoupled from package activation. Non-deferred packages will always be required before the panes are deserialized. This allows the package to register any deserializers for objects displayed in the panes. Deferred packages can contain a 'deferredDeserializers' array in their package.cson. If we attempt to deserialize an object with a deserializer in the list, the package's main module will be required first so it has a chance to register the deserializer. But the package still won't be activated until an activation event occurs. We may want to add an additional optional hook called 'load' which is called at require time. We would not guarantee that the rootView global would exist, but we could give the package a chance to register deserializers etc. For now, registering deserializers is a side-effect of requiring the package.
119 lines
3.7 KiB
CoffeeScript
119 lines
3.7 KiB
CoffeeScript
Package = require 'package'
|
|
fs = require 'fs'
|
|
plist = require 'plist'
|
|
_ = require 'underscore'
|
|
TextMateGrammar = require 'text-mate-grammar'
|
|
|
|
module.exports =
|
|
class TextMatePackage extends Package
|
|
@testName: (packageName) ->
|
|
/(\.|_|-)tmbundle$/.test(packageName)
|
|
|
|
@cssSelectorFromScopeSelector: (scopeSelector) ->
|
|
scopeSelector.split(', ').map((commaFragment) ->
|
|
commaFragment.split(' ').map((spaceFragment) ->
|
|
spaceFragment.split('.').map((dotFragment) ->
|
|
'.' + dotFragment.replace(/\+/g, '\\+')
|
|
).join('')
|
|
).join(' ')
|
|
).join(', ')
|
|
|
|
constructor: ->
|
|
super
|
|
@preferencesPath = fs.join(@path, "Preferences")
|
|
@syntaxesPath = fs.join(@path, "Syntaxes")
|
|
@grammars = []
|
|
|
|
load: ->
|
|
try
|
|
@loadGrammars()
|
|
catch e
|
|
console.warn "Failed to load package at '#{@path}'", e.stack
|
|
this
|
|
|
|
activate: -> # no-op
|
|
|
|
getGrammars: -> @grammars
|
|
|
|
readGrammars: ->
|
|
grammars = []
|
|
for grammarPath in fs.list(@syntaxesPath)
|
|
try
|
|
grammars.push(TextMateGrammar.readFromPath(grammarPath))
|
|
catch e
|
|
console.warn "Failed to load grammar at path '#{grammarPath}'", e.stack
|
|
grammars
|
|
|
|
addGrammar: (rawGrammar) ->
|
|
grammar = new TextMateGrammar(rawGrammar)
|
|
@grammars.push(grammar)
|
|
syntax.addGrammar(grammar)
|
|
|
|
loadGrammars: (rawGrammars) ->
|
|
rawGrammars = @readGrammars() unless rawGrammars?
|
|
|
|
@grammars = []
|
|
@addGrammar(rawGrammar) for rawGrammar in rawGrammars
|
|
@loadScopedProperties()
|
|
|
|
loadScopedProperties: ->
|
|
for { selector, properties } in @getScopedProperties()
|
|
syntax.addProperties(selector, properties)
|
|
|
|
getScopedProperties: ->
|
|
scopedProperties = []
|
|
|
|
for grammar in @getGrammars()
|
|
if properties = @propertiesFromTextMateSettings(grammar)
|
|
selector = @cssSelectorFromScopeSelector(grammar.scopeName)
|
|
scopedProperties.push({selector, properties})
|
|
|
|
for {scope, settings} in @getTextMatePreferenceObjects()
|
|
if properties = @propertiesFromTextMateSettings(settings)
|
|
selector = @cssSelectorFromScopeSelector(scope) if scope?
|
|
scopedProperties.push({selector, properties})
|
|
|
|
scopedProperties
|
|
|
|
readObjectFromPath: (path, callback) ->
|
|
object = null
|
|
error = null
|
|
if fs.isObjectPath(path)
|
|
object = fs.readObject(path)
|
|
else
|
|
plist.parseString fs.read(path), (e, data) ->
|
|
error = e
|
|
object = data[0]
|
|
error = throw new Error("Failed to load object at path `#{path}`") unless object
|
|
callback(error, object)
|
|
|
|
getTextMatePreferenceObjects: ->
|
|
preferenceObjects = []
|
|
if fs.exists(@preferencesPath)
|
|
for preferencePath in fs.list(@preferencesPath)
|
|
@readObjectFromPath preferencePath, (e, object) =>
|
|
if e
|
|
console.warn "Failed to parse preference at path '#{preferencePath}'", e.stack
|
|
else
|
|
preferenceObjects.push(object)
|
|
preferenceObjects
|
|
|
|
propertiesFromTextMateSettings: (textMateSettings) ->
|
|
if textMateSettings.shellVariables
|
|
shellVariables = {}
|
|
for {name, value} in textMateSettings.shellVariables
|
|
shellVariables[name] = value
|
|
textMateSettings.shellVariables = shellVariables
|
|
|
|
editorProperties = _.compactObject(
|
|
commentStart: _.valueForKeyPath(textMateSettings, 'shellVariables.TM_COMMENT_START')
|
|
commentEnd: _.valueForKeyPath(textMateSettings, 'shellVariables.TM_COMMENT_END')
|
|
increaseIndentPattern: textMateSettings.increaseIndentPattern
|
|
decreaseIndentPattern: textMateSettings.decreaseIndentPattern
|
|
foldEndPattern: textMateSettings.foldingStopMarker
|
|
)
|
|
{ editor: editorProperties } if _.size(editorProperties) > 0
|
|
|
|
cssSelectorFromScopeSelector: (scopeSelector) ->
|
|
@constructor.cssSelectorFromScopeSelector(scopeSelector)
|