Merge pull request #1550 from atom/ks-no-more-text-mate-package

Remove TextMatePackage
This commit is contained in:
Kevin Sawicki
2014-02-17 15:06:42 -08:00
16 changed files with 396 additions and 519 deletions

View File

@@ -90,7 +90,7 @@
"metrics": "0.26.0",
"package-generator": "0.26.0",
"release-notes": "0.20.0",
"settings-view": "0.72.0",
"settings-view": "0.73.0",
"snippets": "0.27.0",
"spell-check": "0.25.0",
"status-bar": "0.32.0",
@@ -106,39 +106,39 @@
"welcome": "0.4.0",
"whitespace": "0.13.0",
"wrap-guide": "0.14.0",
"language-c": "0.4.0",
"language-clojure": "0.1.0",
"language-coffee-script": "0.7.0",
"language-css": "0.3.0",
"language-gfm": "0.16.0",
"language-git": "0.4.0",
"language-go": "0.3.0",
"language-html": "0.3.0",
"language-hyperlink": "0.3.0",
"language-java": "0.3.0",
"language-javascript": "0.6.0",
"language-json": "0.3.0",
"language-less": "0.2.0",
"language-make": "0.2.0",
"language-mustache": "0.2.0",
"language-objective-c": "0.3.0",
"language-pegjs": "0.2.0",
"language-perl": "0.3.0",
"language-php": "0.4.0",
"language-property-list": "0.3.0",
"language-puppet": "0.3.0",
"language-python": "0.3.0",
"language-ruby": "0.9.0",
"language-ruby-on-rails": "0.5.0",
"language-sass": "0.4.0",
"language-shellscript": "0.3.0",
"language-source": "0.3.0",
"language-sql": "0.3.0",
"language-text": "0.3.0",
"language-todo": "0.3.0",
"language-toml": "0.8.0",
"language-xml": "0.3.0",
"language-yaml": "0.2.0"
"language-c": "0.8.0",
"language-clojure": "0.2.0",
"language-coffee-script": "0.9.0",
"language-css": "0.7.0",
"language-gfm": "0.17.0",
"language-git": "0.6.0",
"language-go": "0.4.0",
"language-html": "0.5.0",
"language-hyperlink": "0.5.0",
"language-java": "0.5.0",
"language-javascript": "0.8.0",
"language-json": "0.5.0",
"language-less": "0.4.0",
"language-make": "0.4.0",
"language-mustache": "0.3.0",
"language-objective-c": "0.5.0",
"language-pegjs": "0.3.0",
"language-perl": "0.5.0",
"language-php": "0.6.0",
"language-property-list": "0.5.0",
"language-puppet": "0.5.0",
"language-python": "0.5.0",
"language-ruby": "0.11.0",
"language-ruby-on-rails": "0.6.0",
"language-sass": "0.6.0",
"language-shellscript": "0.5.0",
"language-source": "0.5.0",
"language-sql": "0.5.0",
"language-text": "0.4.0",
"language-todo": "0.4.0",
"language-toml": "0.9.0",
"language-xml": "0.5.0",
"language-yaml": "0.4.0"
},
"private": true,
"scripts": {

View File

@@ -1,7 +1,7 @@
{$, $$, fs, WorkspaceView} = require 'atom'
Exec = require('child_process').exec
path = require 'path'
AtomPackage = require '../src/atom-package'
Package = require '../src/package'
ThemeManager = require '../src/theme-manager'
describe "the `atom` global", ->
@@ -50,7 +50,7 @@ describe "the `atom` global", ->
describe "atom packages", ->
describe "when called multiple times", ->
it "it only calls activate on the package once", ->
spyOn(AtomPackage.prototype, 'activateNow').andCallThrough()
spyOn(Package.prototype, 'activateNow').andCallThrough()
atom.packages.activatePackage('package-with-index')
atom.packages.activatePackage('package-with-index')
@@ -58,7 +58,7 @@ describe "the `atom` global", ->
atom.packages.activatePackage('package-with-index')
runs ->
expect(AtomPackage.prototype.activateNow.callCount).toBe 1
expect(Package.prototype.activateNow.callCount).toBe 1
describe "when the package has a main module", ->
describe "when the metadata specifies a main module path˜", ->
@@ -87,9 +87,13 @@ describe "the `atom` global", ->
it "assigns config defaults from the module", ->
expect(atom.config.get('package-with-config-defaults.numbers.one')).toBeUndefined()
atom.packages.activatePackage('package-with-config-defaults')
expect(atom.config.get('package-with-config-defaults.numbers.one')).toBe 1
expect(atom.config.get('package-with-config-defaults.numbers.two')).toBe 2
waitsForPromise ->
atom.packages.activatePackage('package-with-config-defaults')
runs ->
expect(atom.config.get('package-with-config-defaults.numbers.one')).toBe 1
expect(atom.config.get('package-with-config-defaults.numbers.two')).toBe 2
describe "when the package metadata includes activation events", ->
[mainModule, promise] = []
@@ -97,8 +101,7 @@ describe "the `atom` global", ->
beforeEach ->
mainModule = require './fixtures/packages/package-with-activation-events/index'
spyOn(mainModule, 'activate').andCallThrough()
AtomPackage = require '../src/atom-package'
spyOn(AtomPackage.prototype, 'requireMainModule').andCallThrough()
spyOn(Package.prototype, 'requireMainModule').andCallThrough()
promise = atom.packages.activatePackage('package-with-activation-events')
@@ -259,9 +262,12 @@ describe "the `atom` global", ->
describe "grammar loading", ->
it "loads the package's grammars", ->
atom.packages.activatePackage('package-with-grammars')
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Alot'
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Alittle'
waitsForPromise ->
atom.packages.activatePackage('package-with-grammars')
runs ->
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Alot'
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Alittle'
describe "scoped-property loading", ->
it "loads the scoped properties", ->
@@ -271,7 +277,7 @@ describe "the `atom` global", ->
runs ->
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
describe "textmate packages", ->
describe "converted textmate packages", ->
it "loads the package's grammars", ->
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
@@ -281,7 +287,7 @@ describe "the `atom` global", ->
runs ->
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
it "translates the package's scoped properties to Atom terms", ->
it "loads the translated scoped properties", ->
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
waitsForPromise ->
@@ -290,17 +296,6 @@ describe "the `atom` global", ->
runs ->
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBe '# '
describe "when the package has no grammars but does have preferences", ->
it "loads the package's preferences as scoped properties", ->
jasmine.unspy(window, 'setTimeout')
spyOn(atom.syntax, 'addProperties').andCallThrough()
waitsForPromise ->
atom.packages.activatePackage('package-with-preferences-tmbundle')
runs ->
expect(atom.syntax.getProperty(['.source.pref'], 'editor.increaseIndentPattern')).toBe '^abc$'
describe ".deactivatePackage(id)", ->
describe "atom packages", ->
it "calls `deactivate` on the package's main module if activate was successful", ->

View File

@@ -2782,12 +2782,13 @@ describe "Editor", ->
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
waitsForPromise ->
atom.packages.activatePackage('package-with-injection-selector')
atom.packages.activatePackage('package-with-injection-selector')
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
runs ->
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
waitsForPromise ->
atom.packages.activatePackage('language-sql')

View File

@@ -1 +0,0 @@
I am hidden so I shouldn't be loaded

View File

@@ -1 +0,0 @@
I am not a valid plist but that shouldn't cause a crisis

View File

@@ -1,7 +0,0 @@
{
"name": "my preferences",
"scope": "source.pref",
"settings": {
"increaseIndentPattern": "^abc$"
}
}

View File

@@ -1,8 +1,8 @@
{$} = require 'atom'
path = require 'path'
Package = require '../src/package'
ThemePackage = require '../src/theme-package'
describe "AtomPackage", ->
describe "Package", ->
describe "theme", ->
theme = null
@@ -16,14 +16,14 @@ describe "AtomPackage", ->
it "loads and applies css", ->
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
themePath = atom.project.resolve('packages/theme-with-index-css')
theme = Package.load(themePath)
theme = new ThemePackage(themePath)
theme.activate()
expect($(".editor").css("padding-top")).toBe "1234px"
it "parses, loads and applies less", ->
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
themePath = atom.project.resolve('packages/theme-with-index-less')
theme = Package.load(themePath)
theme = new ThemePackage(themePath)
theme.activate()
expect($(".editor").css("padding-top")).toBe "4321px"
@@ -34,7 +34,7 @@ describe "AtomPackage", ->
expect($(".editor").css("padding-bottom")).not.toBe("103px")
themePath = atom.project.resolve('packages/theme-with-package-file')
theme = Package.load(themePath)
theme = new ThemePackage(themePath)
theme.activate()
expect($(".editor").css("padding-top")).toBe("101px")
expect($(".editor").css("padding-right")).toBe("102px")
@@ -47,7 +47,7 @@ describe "AtomPackage", ->
expect($(".editor").css("padding-bottom")).not.toBe "30px"
themePath = atom.project.resolve('packages/theme-without-package-file')
theme = Package.load(themePath)
theme = new ThemePackage(themePath)
theme.activate()
expect($(".editor").css("padding-top")).toBe "10px"
expect($(".editor").css("padding-right")).toBe "20px"
@@ -56,7 +56,7 @@ describe "AtomPackage", ->
describe "reloading a theme", ->
beforeEach ->
themePath = atom.project.resolve('packages/theme-with-package-file')
theme = Package.load(themePath)
theme = new ThemePackage(themePath)
theme.activate()
it "reloads without readding to the stylesheets list", ->
@@ -67,7 +67,7 @@ describe "AtomPackage", ->
describe "events", ->
beforeEach ->
themePath = atom.project.resolve('packages/theme-with-package-file')
theme = Package.load(themePath)
theme = new ThemePackage(themePath)
theme.activate()
it "deactivated event fires on .deactivate()", ->

View File

@@ -4,7 +4,7 @@ path = require 'path'
temp = require 'temp'
ThemeManager = require '../src/theme-manager'
AtomPackage = require '../src/atom-package'
Package = require '../src/package'
describe "ThemeManager", ->
themeManager = null

View File

@@ -1,254 +0,0 @@
Package = require './package'
fs = require 'fs-plus'
path = require 'path'
_ = require 'underscore-plus'
Q = require 'q'
{$} = require './space-pen-extensions'
CSON = require 'season'
{Emitter} = require 'emissary'
# Loads and activates a package's main module and resources such as
# stylesheets, keymaps, grammar, editor properties, and menus.
module.exports =
class AtomPackage extends Package
Emitter.includeInto(this)
@stylesheetsDir: 'stylesheets'
metadata: null
keymaps: null
menus: null
stylesheets: null
grammars: null
scopedProperties: null
mainModulePath: null
resolvedMainModulePath: false
mainModule: null
constructor: (path, {@metadata}) ->
super(path)
@reset()
getType: -> 'atom'
getStylesheetType: -> 'bundled'
load: ->
@measure 'loadTime', =>
try
@metadata ?= Package.loadMetadata(@path)
@loadKeymaps()
@loadMenus()
@loadStylesheets()
@loadGrammars()
@loadScopedProperties()
@requireMainModule() unless @metadata.activationEvents?
catch e
console.warn "Failed to load package named '#{@name}'", e.stack ? e
this
reset: ->
@stylesheets = []
@keymaps = []
@menus = []
@grammars = []
@scopedProperties = []
activate: ->
return @activationDeferred.promise if @activationDeferred?
@activationDeferred = Q.defer()
@measure 'activateTime', =>
@activateResources()
if @metadata.activationEvents?
@subscribeToActivationEvents()
else
@activateNow()
@activationDeferred.promise
activateNow: ->
try
@activateConfig()
@activateStylesheets()
if @requireMainModule()
@mainModule.activate(atom.packages.getPackageState(@name) ? {})
@mainActivated = true
catch e
console.warn "Failed to activate package named '#{@name}'", e.stack
@activationDeferred.resolve()
activateConfig: ->
return if @configActivated
@requireMainModule()
if @mainModule?
atom.config.setDefaults(@name, @mainModule.configDefaults)
@mainModule.activateConfig?()
@configActivated = true
activateStylesheets: ->
return if @stylesheetsActivated
type = @getStylesheetType()
for [stylesheetPath, content] in @stylesheets
atom.themes.applyStylesheet(stylesheetPath, content, type)
@stylesheetsActivated = true
activateResources: ->
atom.keymap.add(keymapPath, map) for [keymapPath, map] in @keymaps
atom.contextMenu.add(menuPath, map['context-menu']) for [menuPath, map] in @menus
atom.menu.add(map.menu) for [menuPath, map] in @menus when map.menu
grammar.activate() for grammar in @grammars
for [scopedPropertiesPath, selector, properties] in @scopedProperties
atom.syntax.addProperties(scopedPropertiesPath, selector, properties)
loadKeymaps: ->
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath)]
loadMenus: ->
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath)]
getKeymapPaths: ->
keymapsDirPath = path.join(@path, 'keymaps')
if @metadata.keymaps
@metadata.keymaps.map (name) -> fs.resolve(keymapsDirPath, name, ['json', 'cson', ''])
else
fs.listSync(keymapsDirPath, ['cson', 'json'])
getMenuPaths: ->
menusDirPath = path.join(@path, 'menus')
if @metadata.menus
@metadata.menus.map (name) -> fs.resolve(menusDirPath, name, ['json', 'cson', ''])
else
fs.listSync(menusDirPath, ['cson', 'json'])
loadStylesheets: ->
@stylesheets = @getStylesheetPaths().map (stylesheetPath) ->
[stylesheetPath, atom.themes.loadStylesheet(stylesheetPath)]
getStylesheetsPath: ->
path.join(@path, @constructor.stylesheetsDir)
getStylesheetPaths: ->
stylesheetDirPath = @getStylesheetsPath()
if @metadata.stylesheetMain
[fs.resolve(@path, @metadata.stylesheetMain)]
else if @metadata.stylesheets
@metadata.stylesheets.map (name) -> fs.resolve(stylesheetDirPath, name, ['css', 'less', ''])
else if indexStylesheet = fs.resolve(@path, 'index', ['css', 'less'])
[indexStylesheet]
else
fs.listSync(stylesheetDirPath, ['css', 'less'])
loadGrammars: ->
@grammars = []
grammarsDirPath = path.join(@path, 'grammars')
for grammarPath in fs.listSync(grammarsDirPath, ['.json', '.cson'])
@grammars.push(atom.syntax.readGrammarSync(grammarPath))
loadScopedProperties: ->
@scopedProperties = []
scopedPropertiessDirPath = path.join(@path, 'scoped-properties')
for scopedPropertiesPath in fs.listSync(scopedPropertiessDirPath, ['.json', '.cson'])
for selector, properties of fs.readObjectSync(scopedPropertiesPath)
@scopedProperties.push([scopedPropertiesPath, selector, properties])
serialize: ->
if @mainActivated
try
@mainModule?.serialize?()
catch e
console.error "Error serializing package '#{@name}'", e.stack
deactivate: ->
@activationDeferred?.reject()
@activationDeferred = null
@unsubscribeFromActivationEvents()
@deactivateResources()
@deactivateConfig()
@mainModule?.deactivate?() if @mainActivated
@emit('deactivated')
deactivateConfig: ->
@mainModule?.deactivateConfig?()
@configActivated = false
deactivateResources: ->
grammar.deactivate() for grammar in @grammars
atom.syntax.removeProperties(scopedPropertiesPath) for [scopedPropertiesPath] in @scopedProperties
atom.keymap.remove(keymapPath) for [keymapPath] in @keymaps
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
@stylesheetsActivated = false
reloadStylesheets: ->
oldSheets = _.clone(@stylesheets)
@loadStylesheets()
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
@reloadStylesheet(stylesheetPath, content) for [stylesheetPath, content] in @stylesheets
reloadStylesheet: (stylesheetPath, content) ->
atom.themes.applyStylesheet(stylesheetPath, content, @getStylesheetType())
requireMainModule: ->
return @mainModule if @mainModule?
mainModulePath = @getMainModulePath()
@mainModule = require(mainModulePath) if fs.isFileSync(mainModulePath)
getMainModulePath: ->
return @mainModulePath if @resolvedMainModulePath
@resolvedMainModulePath = true
mainModulePath =
if @metadata.main
path.join(@path, @metadata.main)
else
path.join(@path, 'index')
@mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...])
subscribeToActivationEvents: ->
return unless @metadata.activationEvents?
if _.isArray(@metadata.activationEvents)
atom.workspaceView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
else if _.isString(@metadata.activationEvents)
atom.workspaceView.command(@metadata.activationEvents, @handleActivationEvent)
else
atom.workspaceView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
handleActivationEvent: (event) =>
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
@activateNow()
$(event.target).trigger(event)
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
@unsubscribeFromActivationEvents()
unsubscribeFromActivationEvents: ->
return unless atom.workspaceView?
if _.isArray(@metadata.activationEvents)
atom.workspaceView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
else if _.isString(@metadata.activationEvents)
atom.workspaceView.off(@metadata.activationEvents, @handleActivationEvent)
else
atom.workspaceView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
disableEventHandlersOnBubblePath: (event) ->
bubblePathEventHandlers = []
disabledHandler = ->
element = $(event.target)
while element.length
if eventHandlers = element.handlers()?[event.type]
for eventHandler in eventHandlers
eventHandler.disabledHandler = eventHandler.handler
eventHandler.handler = disabledHandler
bubblePathEventHandlers.push(eventHandler)
element = element.parent()
bubblePathEventHandlers
restoreEventHandlersOnBubblePath: (eventHandlers) ->
for eventHandler in eventHandlers
eventHandler.handler = eventHandler.disabledHandler
delete eventHandler.disabledHandler

View File

@@ -1,9 +1,12 @@
path = require 'path'
_ = require 'underscore-plus'
{Emitter} = require 'emissary'
fs = require 'fs-plus'
_ = require 'underscore-plus'
Q = require 'q'
Package = require './package'
path = require 'path'
ThemePackage = require './theme-package'
# Public: Package manager for coordinating the lifecycle of Atom packages.
#
@@ -144,9 +147,18 @@ class PackageManager
name = path.basename(nameOrPath)
return pack if pack = @getLoadedPackage(name)
pack = Package.load(packagePath)
@loadedPackages[pack.name] = pack if pack?
pack
try
metadata = Package.loadMetadata(packagePath) ? {}
if metadata.theme
pack = new ThemePackage(packagePath, metadata)
else
pack = new Package(packagePath, metadata)
pack.load()
@loadedPackages[pack.name] = pack
pack
catch error
console.warn "Failed to load package.json '#{path.basename(packagePath)}'", error.stack ? error
else
throw new Error("Could not resolve '#{nameOrPath}' to a package path")

View File

@@ -1,53 +1,52 @@
CSON = require 'season'
{basename, join} = require 'path'
path = require 'path'
_ = require 'underscore-plus'
async = require 'async'
CSON = require 'season'
fs = require 'fs-plus'
{Emitter} = require 'emissary'
Q = require 'q'
{$} = require './space-pen-extensions'
ScopedProperties = require './scoped-properties'
# Loads and activates a package's main module and resources such as
# stylesheets, keymaps, grammar, editor properties, and menus.
module.exports =
class Package
@build: (path) ->
TextMatePackage = require './text-mate-package'
AtomPackage = require './atom-package'
ThemePackage = require './theme-package'
Emitter.includeInto(this)
if TextMatePackage.testName(path)
pack = new TextMatePackage(path)
else
try
metadata = @loadMetadata(path)
if metadata.theme
pack = new ThemePackage(path, {metadata})
else
pack = new AtomPackage(path, {metadata})
catch e
console.warn "Failed to load package.json '#{basename(path)}'", e.stack ? e
@stylesheetsDir: 'stylesheets'
pack
@load: (path) ->
pack = @build(path)
pack?.load()
pack
@loadMetadata: (path, ignoreErrors=false) ->
if metadataPath = CSON.resolve(join(path, 'package'))
@loadMetadata: (packagePath, ignoreErrors=false) ->
if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
try
metadata = CSON.readFileSync(metadataPath)
catch e
throw e unless ignoreErrors
catch error
throw error unless ignoreErrors
metadata ?= {}
metadata.name = basename(path)
metadata.name = path.basename(packagePath)
metadata
name: null
path: null
keymaps: null
menus: null
stylesheets: null
grammars: null
scopedProperties: null
mainModulePath: null
resolvedMainModulePath: false
mainModule: null
constructor: (@path) ->
@name = basename(@path)
constructor: (@path, @metadata) ->
@metadata ?= Package.loadMetadata(@path)
@name = @metadata?.name ? path.basename(@path)
@reset()
enable: ->
atom.config.removeAtKeyPath('core.disabledPackages', @metadata.name)
atom.config.removeAtKeyPath('core.disabledPackages', @name)
disable: ->
atom.config.pushAtKeyPath('core.disabledPackages', @metadata.name)
atom.config.pushAtKeyPath('core.disabledPackages', @name)
isTheme: ->
@metadata?.theme?
@@ -57,3 +56,252 @@ class Package
value = fn()
@[key] = Date.now() - startTime
value
getType: -> 'atom'
getStylesheetType: -> 'bundled'
load: ->
@measure 'loadTime', =>
try
@loadKeymaps()
@loadMenus()
@loadStylesheets()
@grammarsPromise = @loadGrammars()
@scopedPropertiesPromise = @loadScopedProperties()
@requireMainModule() unless @metadata.activationEvents?
catch error
console.warn "Failed to load package named '#{@name}'", error.stack ? error
this
reset: ->
@stylesheets = []
@keymaps = []
@menus = []
@grammars = []
@scopedProperties = []
activate: ->
unless @activationDeferred?
@activationDeferred = Q.defer()
@measure 'activateTime', =>
@activateResources()
if @metadata.activationEvents?
@subscribeToActivationEvents()
else
@activateNow()
Q.all([@grammarsPromise, @scopedPropertiesPromise, @activationDeferred.promise])
activateNow: ->
try
@activateConfig()
@activateStylesheets()
if @requireMainModule()
@mainModule.activate(atom.packages.getPackageState(@name) ? {})
@mainActivated = true
catch e
console.warn "Failed to activate package named '#{@name}'", e.stack
@activationDeferred.resolve()
activateConfig: ->
return if @configActivated
@requireMainModule()
if @mainModule?
atom.config.setDefaults(@name, @mainModule.configDefaults)
@mainModule.activateConfig?()
@configActivated = true
activateStylesheets: ->
return if @stylesheetsActivated
type = @getStylesheetType()
for [stylesheetPath, content] in @stylesheets
atom.themes.applyStylesheet(stylesheetPath, content, type)
@stylesheetsActivated = true
activateResources: ->
atom.keymap.add(keymapPath, map) for [keymapPath, map] in @keymaps
atom.contextMenu.add(menuPath, map['context-menu']) for [menuPath, map] in @menus
atom.menu.add(map.menu) for [menuPath, map] in @menus when map.menu
grammar.activate() for grammar in @grammars
@grammarsActivated = true
scopedProperties.activate() for scopedProperties in @scopedProperties
@scopedPropertiesActivated = true
loadKeymaps: ->
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath)]
loadMenus: ->
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath)]
getKeymapPaths: ->
keymapsDirPath = path.join(@path, 'keymaps')
if @metadata.keymaps
@metadata.keymaps.map (name) -> fs.resolve(keymapsDirPath, name, ['json', 'cson', ''])
else
fs.listSync(keymapsDirPath, ['cson', 'json'])
getMenuPaths: ->
menusDirPath = path.join(@path, 'menus')
if @metadata.menus
@metadata.menus.map (name) -> fs.resolve(menusDirPath, name, ['json', 'cson', ''])
else
fs.listSync(menusDirPath, ['cson', 'json'])
loadStylesheets: ->
@stylesheets = @getStylesheetPaths().map (stylesheetPath) ->
[stylesheetPath, atom.themes.loadStylesheet(stylesheetPath)]
getStylesheetsPath: ->
path.join(@path, @constructor.stylesheetsDir)
getStylesheetPaths: ->
stylesheetDirPath = @getStylesheetsPath()
if @metadata.stylesheetMain
[fs.resolve(@path, @metadata.stylesheetMain)]
else if @metadata.stylesheets
@metadata.stylesheets.map (name) -> fs.resolve(stylesheetDirPath, name, ['css', 'less', ''])
else if indexStylesheet = fs.resolve(@path, 'index', ['css', 'less'])
[indexStylesheet]
else
fs.listSync(stylesheetDirPath, ['css', 'less'])
loadGrammars: ->
@grammars = []
loadGrammar = (grammarPath, callback) =>
atom.syntax.readGrammar grammarPath, (error, grammar) =>
if error?
console.warn("Failed to load grammar: #{grammarPath}", error.stack ? error)
else
@grammars.push(grammar)
grammar.activate() if @grammarsActivated
callback()
deferred = Q.defer()
grammarsDirPath = path.join(@path, 'grammars')
fs.list grammarsDirPath, ['json', 'cson'], (error, grammarPaths=[]) ->
async.each grammarPaths, loadGrammar, -> deferred.resolve()
deferred.promise
loadScopedProperties: ->
@scopedProperties = []
loadScopedPropertiesFile = (scopedPropertiesPath, callback) =>
ScopedProperties.load scopedPropertiesPath, (error, scopedProperties) =>
if error?
console.warn("Failed to load scoped properties: #{scopedPropertiesPath}", error.stack ? error)
else
@scopedProperties.push(scopedProperties)
scopedProperties.activate() if @scopedPropertiesActivated
callback()
deferred = Q.defer()
scopedPropertiesDirPath = path.join(@path, 'scoped-properties')
fs.list scopedPropertiesDirPath, ['json', 'cson'], (error, scopedPropertiesPaths=[]) ->
async.each scopedPropertiesPaths, loadScopedPropertiesFile, -> deferred.resolve()
deferred.promise
serialize: ->
if @mainActivated
try
@mainModule?.serialize?()
catch e
console.error "Error serializing package '#{@name}'", e.stack
deactivate: ->
@activationDeferred?.reject()
@activationDeferred = null
@unsubscribeFromActivationEvents()
@deactivateResources()
@deactivateConfig()
@mainModule?.deactivate?() if @mainActivated
@emit('deactivated')
deactivateConfig: ->
@mainModule?.deactivateConfig?()
@configActivated = false
deactivateResources: ->
grammar.deactivate() for grammar in @grammars
scopedProperties.deactivate() for scopedProperties in @scopedProperties
atom.keymap.remove(keymapPath) for [keymapPath] in @keymaps
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
@stylesheetsActivated = false
@grammarsActivated = false
@scopedPropertiesActivated = false
reloadStylesheets: ->
oldSheets = _.clone(@stylesheets)
@loadStylesheets()
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
@reloadStylesheet(stylesheetPath, content) for [stylesheetPath, content] in @stylesheets
reloadStylesheet: (stylesheetPath, content) ->
atom.themes.applyStylesheet(stylesheetPath, content, @getStylesheetType())
requireMainModule: ->
return @mainModule if @mainModule?
mainModulePath = @getMainModulePath()
@mainModule = require(mainModulePath) if fs.isFileSync(mainModulePath)
getMainModulePath: ->
return @mainModulePath if @resolvedMainModulePath
@resolvedMainModulePath = true
mainModulePath =
if @metadata.main
path.join(@path, @metadata.main)
else
path.join(@path, 'index')
@mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...])
subscribeToActivationEvents: ->
return unless @metadata.activationEvents?
if _.isArray(@metadata.activationEvents)
atom.workspaceView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
else if _.isString(@metadata.activationEvents)
atom.workspaceView.command(@metadata.activationEvents, @handleActivationEvent)
else
atom.workspaceView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
handleActivationEvent: (event) =>
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
@activateNow()
$(event.target).trigger(event)
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
@unsubscribeFromActivationEvents()
unsubscribeFromActivationEvents: ->
return unless atom.workspaceView?
if _.isArray(@metadata.activationEvents)
atom.workspaceView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
else if _.isString(@metadata.activationEvents)
atom.workspaceView.off(@metadata.activationEvents, @handleActivationEvent)
else
atom.workspaceView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
disableEventHandlersOnBubblePath: (event) ->
bubblePathEventHandlers = []
disabledHandler = ->
element = $(event.target)
while element.length
if eventHandlers = element.handlers()?[event.type]
for eventHandler in eventHandlers
eventHandler.disabledHandler = eventHandler.handler
eventHandler.handler = disabledHandler
bubblePathEventHandlers.push(eventHandler)
element = element.parent()
bubblePathEventHandlers
restoreEventHandlersOnBubblePath: (eventHandlers) ->
for eventHandler in eventHandlers
eventHandler.handler = eventHandler.disabledHandler
delete eventHandler.disabledHandler

View File

@@ -0,0 +1,19 @@
fs = require 'fs-plus'
module.exports =
class ScopedProperties
@load: (scopedPropertiesPath, callback) ->
fs.readObject scopedPropertiesPath, (error, scopedProperties={}) ->
if error?
callback(error)
else
callback(null, new ScopedProperties(scopedPropertiesPath, scopedProperties))
constructor: (@path, @scopedProperties) ->
activate: ->
for selector, properties of @scopedProperties
atom.syntax.addProperties(@path, selector, properties)
deactivate: ->
atom.syntax.removeProperties(@path)

View File

@@ -1,135 +0,0 @@
Package = require './package'
path = require 'path'
_ = require 'underscore-plus'
fs = require 'fs-plus'
Q = require 'q'
module.exports =
class TextMatePackage extends Package
@testName: (packageName) ->
packageName = path.basename(packageName)
/(^language-.+)|((\.|_|-)tmbundle$)/.test(packageName)
@addToActivationPromise = (pack) ->
@activationPromise ?= Q()
@activationPromise = @activationPromise.then =>
pack.loadGrammars()
.then -> pack.loadScopedProperties()
.fail (error) -> console.log pack.name, error.stack ? error
constructor: ->
super
@grammars = []
@scopedProperties = []
@metadata = {@name}
getType: -> 'textmate'
load: ->
@measure 'loadTime', =>
@metadata = Package.loadMetadata(@path, true)
activate: ->
@measure 'activateTime', =>
TextMatePackage.addToActivationPromise(this)
activateConfig: -> # noop
deactivate: ->
grammar.deactivate() for grammar in @grammars
atom.syntax.removeProperties(@path)
loadGrammars: ->
deferred = Q.defer()
fs.isDirectory @getSyntaxesPath(), (isDirectory) =>
return deferred.resolve() unless isDirectory
fs.list @getSyntaxesPath(), ['json', 'cson'], (error, paths) =>
if error?
console.log("Error loading grammars of TextMate package '#{@path}':", error.stack, error)
deferred.resolve()
else
promises = paths.map (path) => @loadGrammarAtPath(path)
Q.all(promises).then -> deferred.resolve()
deferred.promise
loadGrammarAtPath: (grammarPath) ->
deferred = Q.defer()
atom.syntax.readGrammar grammarPath, (error, grammar) =>
if error?
console.log("Error loading grammar at path '#{grammarPath}':", error.stack ? error)
else
@addGrammar(grammar)
deferred.resolve()
deferred.promise
addGrammar: (grammar) ->
@grammars.push(grammar)
grammar.activate()
getGrammars: -> @grammars
getSyntaxesPath: ->
path.join(@path, "syntaxes")
getPreferencesPath: ->
path.join(@path, "preferences")
loadScopedProperties: ->
scopedProperties = []
for grammar in @getGrammars()
if properties = @propertiesFromTextMateSettings(grammar)
selector = atom.syntax.cssSelectorFromScopeSelector(grammar.scopeName)
scopedProperties.push({selector, properties})
@loadTextMatePreferenceObjects().then (preferenceObjects=[]) =>
for {scope, settings} in preferenceObjects
if properties = @propertiesFromTextMateSettings(settings)
selector = atom.syntax.cssSelectorFromScopeSelector(scope) if scope?
scopedProperties.push({selector, properties})
@scopedProperties = scopedProperties
for {selector, properties} in @scopedProperties
atom.syntax.addProperties(@path, selector, properties)
loadTextMatePreferenceObjects: ->
deferred = Q.defer()
fs.isDirectory @getPreferencesPath(), (isDirectory) =>
return deferred.resolve() unless isDirectory
fs.list @getPreferencesPath(), (error, paths) =>
if error?
console.log("Error loading preferences of TextMate package '#{@path}':", error.stack, error)
deferred.resolve()
else
promises = paths.map (path) => @loadPreferencesAtPath(path)
Q.all(promises).then (preferenceObjects) -> deferred.resolve(preferenceObjects)
deferred.promise
loadPreferencesAtPath: (preferencePath) ->
deferred = Q.defer()
fs.readObject preferencePath, (error, preference) ->
if error?
console.warn("Failed to parse preference at path '#{preferencePath}'", error.stack, error)
deferred.resolve(preference)
deferred.promise
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

View File

@@ -6,7 +6,7 @@ fs = require 'fs-plus'
Q = require 'q'
{$} = require './space-pen-extensions'
AtomPackage = require './atom-package'
Package = require './package'
File = require './file'
# Public: Handles loading and activating available themes.
@@ -93,7 +93,7 @@ class ThemeManager
themePaths = []
for themeName in @getEnabledThemeNames()
if themePath = @packageManager.resolvePackagePath(themeName)
themePaths.push(path.join(themePath, AtomPackage.stylesheetsDir))
themePaths.push(path.join(themePath, Package.stylesheetsDir))
themePaths.filter (themePath) -> fs.isDirectorySync(themePath)

View File

@@ -1,24 +1,24 @@
Q = require 'q'
AtomPackage = require './atom-package'
Package = require './package'
module.exports =
class ThemePackage extends AtomPackage
class ThemePackage extends Package
getType: -> 'theme'
getStylesheetType: -> 'theme'
enable: ->
atom.config.unshiftAtKeyPath('core.themes', @metadata.name)
atom.config.unshiftAtKeyPath('core.themes', @name)
disable: ->
atom.config.removeAtKeyPath('core.themes', @metadata.name)
atom.config.removeAtKeyPath('core.themes', @name)
load: ->
@measure 'loadTime', =>
try
@metadata ?= Package.loadMetadata(@path)
catch e
console.warn "Failed to load theme named '#{@name}'", e.stack ? e
catch error
console.warn "Failed to load theme named '#{@name}'", error.stack ? error
this
activate: ->

2
vendor/apm vendored

Submodule vendor/apm updated: af40a0ed55...be0c1fb771