Files
atom/src/text-mate-package.coffee
2013-11-11 08:53:52 -08:00

171 lines
5.7 KiB
CoffeeScript

Package = require './package'
path = require 'path'
_ = require 'underscore-plus'
fs = require 'fs-plus'
TextMateGrammar = require './text-mate-grammar'
async = require 'async'
### Internal ###
module.exports =
class TextMatePackage extends Package
@testName: (packageName) ->
packageName = path.basename(packageName)
/(^language-.+)|((\.|_|-)tmbundle$)/.test(packageName)
@getLoadQueue: ->
return @loadQueue if @loadQueue
@loadQueue = async.queue (pack, done) ->
pack.loadGrammars ->
pack.loadScopedProperties(done)
@loadQueue
constructor: ->
super
@grammars = []
@scopedProperties = []
@metadata = {@name}
getType: -> 'textmate'
load: ({sync}={}) ->
@measure 'loadTime', =>
@metadata = Package.loadMetadata(@path, true)
if sync
@loadGrammarsSync()
@loadScopedPropertiesSync()
else
TextMatePackage.getLoadQueue().push(this)
activate: ->
@measure 'activateTime', =>
atom.syntax.addGrammar(grammar) for grammar in @grammars
for { selector, properties } in @scopedProperties
atom.syntax.addProperties(@path, selector, properties)
activateConfig: -> # noop
deactivate: ->
atom.syntax.removeGrammar(grammar) for grammar in @grammars
atom.syntax.removeProperties(@path)
legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage', 'json', 'cson']
loadGrammars: (done) ->
fs.isDirectory @getSyntaxesPath(), (isDirectory) =>
if isDirectory
fs.list @getSyntaxesPath(), @legalGrammarExtensions, (error, paths) =>
if error?
console.log("Error loading grammars of TextMate package '#{@path}':", error.stack, error)
done()
else
async.eachSeries(paths, @loadGrammarAtPath, done)
else
done()
loadGrammarAtPath: (grammarPath, done) =>
TextMateGrammar.load grammarPath, (err, grammar) =>
return console.log("Error loading grammar at path '#{grammarPath}':", err.stack ? err) if err
@addGrammar(grammar)
done()
loadGrammarsSync: ->
for grammarPath in fs.listSync(@getSyntaxesPath(), @legalGrammarExtensions)
@addGrammar(TextMateGrammar.loadSync(grammarPath))
addGrammar: (grammar) ->
@grammars.push(grammar)
atom.syntax.addGrammar(grammar) if @isActive()
getGrammars: -> @grammars
getSyntaxesPath: ->
syntaxesPath = path.join(@path, "syntaxes")
if fs.isDirectorySync(syntaxesPath)
syntaxesPath
else
path.join(@path, "Syntaxes")
getPreferencesPath: ->
preferencesPath = path.join(@path, "preferences")
if fs.isDirectorySync(preferencesPath)
preferencesPath
else
path.join(@path, "Preferences")
loadScopedPropertiesSync: ->
for grammar in @getGrammars()
if properties = @propertiesFromTextMateSettings(grammar)
selector = atom.syntax.cssSelectorFromScopeSelector(grammar.scopeName)
@scopedProperties.push({selector, properties})
for preferencePath in fs.listSync(@getPreferencesPath())
{scope, settings} = fs.readObjectSync(preferencePath)
if properties = @propertiesFromTextMateSettings(settings)
selector = atom.syntax.cssSelectorFromScopeSelector(scope) if scope?
@scopedProperties.push({selector, properties})
if @isActive()
for {selector, properties} in @scopedProperties
atom.syntax.addProperties(@path, selector, properties)
loadScopedProperties: (callback) ->
scopedProperties = []
for grammar in @getGrammars()
if properties = @propertiesFromTextMateSettings(grammar)
selector = atom.syntax.cssSelectorFromScopeSelector(grammar.scopeName)
scopedProperties.push({selector, properties})
preferenceObjects = []
done = =>
for {scope, settings} in preferenceObjects
if properties = @propertiesFromTextMateSettings(settings)
selector = atom.syntax.cssSelectorFromScopeSelector(scope) if scope?
scopedProperties.push({selector, properties})
@scopedProperties = scopedProperties
if @isActive()
for {selector, properties} in @scopedProperties
atom.syntax.addProperties(@path, selector, properties)
callback?()
@loadTextMatePreferenceObjects(preferenceObjects, done)
loadTextMatePreferenceObjects: (preferenceObjects, done) ->
fs.isDirectory @getPreferencesPath(), (isDirectory) =>
return done() unless isDirectory
fs.list @getPreferencesPath(), (error, paths) =>
if error?
console.log("Error loading preferences of TextMate package '#{@path}':", error.stack, error)
done()
return
loadPreferencesAtPath = (preferencePath, done) ->
fs.readObject preferencePath, (error, preferences) =>
if error?
console.warn("Failed to parse preference at path '#{preferencePath}'", error.stack, error)
else
preferenceObjects.push(preferences)
done()
async.eachSeries paths, loadPreferencesAtPath, done
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
completions: textMateSettings.completions
)
{ editor: editorProperties } if _.size(editorProperties) > 0