Merge pull request #881 from atom/ks-globalization

Clean up globals
This commit is contained in:
Kevin Sawicki 2013-10-02 13:45:36 -07:00
commit 46762327c6
16 changed files with 621 additions and 505 deletions

View File

@ -1,4 +1,5 @@
require '../src/atom'
Atom = require '../src/atom'
window.atom = new Atom()
{runSpecSuite} = require '../spec/jasmine-helper'
atom.openDevTools()

View File

@ -6,29 +6,6 @@ describe "the `atom` global", ->
beforeEach ->
window.rootView = new RootView
describe "base stylesheet loading", ->
beforeEach ->
rootView.append $$ -> @div class: 'editor'
rootView.attachToDom()
atom.themes.load()
atom.watchThemes()
afterEach ->
atom.themes.unload()
config.set('core.themes', [])
atom.reloadBaseStylesheets()
it "loads the correct values from the theme's ui-variables file", ->
config.set('core.themes', ['theme-with-ui-variables'])
# an override loaded in the base css
expect(rootView.css("background-color")).toBe "rgb(0, 0, 255)"
# from within the theme itself
expect($(".editor").css("padding-top")).toBe "150px"
expect($(".editor").css("padding-right")).toBe "150px"
expect($(".editor").css("padding-bottom")).toBe "150px"
describe "package lifecycle methods", ->
describe ".loadPackage(name)", ->
describe "when the package has deferred deserializers", ->
@ -205,15 +182,15 @@ describe "the `atom` global", ->
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
expect(stylesheetElementForId(one)).not.toExist()
expect(stylesheetElementForId(two)).not.toExist()
expect(stylesheetElementForId(three)).not.toExist()
expect(atom.themes.stylesheetElementForId(one)).not.toExist()
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
atom.activatePackage("package-with-stylesheets-manifest")
expect(stylesheetElementForId(one)).toExist()
expect(stylesheetElementForId(two)).toExist()
expect(stylesheetElementForId(three)).not.toExist()
expect(atom.themes.stylesheetElementForId(one)).toExist()
expect(atom.themes.stylesheetElementForId(two)).toExist()
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
expect($('#jasmine-content').css('font-size')).toBe '1px'
describe "when the metadata does not contain a 'stylesheets' manifest", ->
@ -221,14 +198,14 @@ describe "the `atom` global", ->
one = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/3.css")
expect(stylesheetElementForId(one)).not.toExist()
expect(stylesheetElementForId(two)).not.toExist()
expect(stylesheetElementForId(three)).not.toExist()
expect(atom.themes.stylesheetElementForId(one)).not.toExist()
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
atom.activatePackage("package-with-stylesheets")
expect(stylesheetElementForId(one)).toExist()
expect(stylesheetElementForId(two)).toExist()
expect(stylesheetElementForId(three)).toExist()
expect(atom.themes.stylesheetElementForId(one)).toExist()
expect(atom.themes.stylesheetElementForId(two)).toExist()
expect(atom.themes.stylesheetElementForId(three)).toExist()
expect($('#jasmine-content').css('font-size')).toBe '3px'
describe "grammar loading", ->
@ -298,8 +275,8 @@ describe "the `atom` global", ->
atom.activatePackage('package-with-serialize-error', immediate: true)
atom.activatePackage('package-with-serialization', immediate: true)
atom.deactivatePackages()
expect(atom.packageStates['package-with-serialize-error']).toBeUndefined()
expect(atom.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
it "removes the package's grammars", ->
@ -320,9 +297,9 @@ describe "the `atom` global", ->
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
expect(stylesheetElementForId(one)).not.toExist()
expect(stylesheetElementForId(two)).not.toExist()
expect(stylesheetElementForId(three)).not.toExist()
expect(atom.themes.stylesheetElementForId(one)).not.toExist()
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
it "removes the package's scoped-properties", ->
atom.activatePackage("package-with-scoped-properties")

View File

@ -0,0 +1,33 @@
DeserializerManager = require '../src/deserializer-manager'
describe ".deserialize(state)", ->
deserializer = null
class Foo
@deserialize: ({name}) -> new Foo(name)
constructor: (@name) ->
beforeEach ->
deserializer = new DeserializerManager()
deserializer.registerDeserializer(Foo)
it "calls deserialize on the deserializer for the given state object, or returns undefined if one can't be found", ->
spyOn(console, 'warn')
object = deserializer.deserialize({ deserializer: 'Foo', name: 'Bar' })
expect(object.name).toBe 'Bar'
expect(deserializer.deserialize({ deserializer: 'Bogus' })).toBeUndefined()
describe "when the deserializer has a version", ->
beforeEach ->
Foo.version = 2
describe "when the deserialized state has a matching version", ->
it "attempts to deserialize the state", ->
object = deserializer.deserialize({ deserializer: 'Foo', version: 2, name: 'Bar' })
expect(object.name).toBe 'Bar'
describe "when the deserialized state has a non-matching version", ->
it "returns undefined", ->
expect(deserializer.deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined()
expect(deserializer.deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined()
expect(deserializer.deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined()

View File

@ -1,7 +1,8 @@
try
require '../src/atom'
require '../src/window'
atom.show()
Atom = require '../src/atom'
window.atom = new Atom()
window.atom.show()
{runSpecSuite} = require './jasmine-helper'
document.title = "Spec Suite"

View File

@ -14,12 +14,11 @@ TokenizedBuffer = require '../src/tokenized-buffer'
pathwatcher = require 'pathwatcher'
clipboard = require 'clipboard'
atom.loadBaseStylesheets()
requireStylesheet '../static/jasmine'
atom.themes.loadBaseStylesheets()
atom.themes.requireStylesheet '../static/jasmine'
fixturePackagesPath = path.resolve(__dirname, './fixtures/packages')
config.packageDirPaths.unshift(fixturePackagesPath)
keymap.loadBundledKeymaps()
atom.keymap.loadBundledKeymaps()
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
$(window).on 'core:close', -> window.close()
@ -36,20 +35,22 @@ specProjectPath = path.join(specDirectory, 'fixtures')
beforeEach ->
$.fx.off = true
window.project = new Project(specProjectPath)
atom.project = new Project(specProjectPath)
window.project = atom.project
window.resetTimeouts()
atom.packageStates = {}
atom.packages.packageStates = {}
spyOn(atom, 'saveWindowState')
syntax.clearGrammarOverrides()
syntax.clearProperties()
atom.syntax.clearGrammarOverrides()
atom.syntax.clearProperties()
# used to reset keymap after each spec
bindingSetsToRestore = _.clone(keymap.bindingSets)
bindingSetsByFirstKeystrokeToRestore = _.clone(keymap.bindingSetsByFirstKeystroke)
# reset config before each spec; don't load or save from/to `config.json`
window.config = new Config()
config = new Config()
config.packageDirPaths.unshift(fixturePackagesPath)
spyOn(config, 'load')
spyOn(config, 'save')
config.set "editor.fontFamily", "Courier"
@ -57,6 +58,8 @@ beforeEach ->
config.set "editor.autoIndent", false
config.set "core.disabledPackages", ["package-that-throws-an-exception"]
config.save.reset()
atom.config = config
window.config = config
# make editor display updates synchronous
spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()

View File

@ -1,4 +1,5 @@
{$} = require 'atom'
path = require 'path'
{$, $$, fs, RootView} = require 'atom'
ThemeManager = require '../src/theme-manager'
AtomPackage = require '../src/atom-package'
@ -73,3 +74,81 @@ describe "ThemeManager", ->
expect(loadHandler).toHaveBeenCalled()
expect(loadHandler.mostRecentCall.args[0]).toBeInstanceOf AtomPackage
describe "requireStylesheet(path)", ->
it "synchronously loads css at the given path and installs a style tag for it in the head", ->
cssPath = project.resolve('css.css')
lengthBefore = $('head style').length
themeManager.requireStylesheet(cssPath)
expect($('head style').length).toBe lengthBefore + 1
element = $('head style[id*="css.css"]')
expect(element.attr('id')).toBe cssPath
expect(element.text()).toBe fs.read(cssPath)
# doesn't append twice
themeManager.requireStylesheet(cssPath)
expect($('head style').length).toBe lengthBefore + 1
$('head style[id*="css.css"]').remove()
it "synchronously loads and parses less files at the given path and installs a style tag for it in the head", ->
lessPath = project.resolve('sample.less')
lengthBefore = $('head style').length
themeManager.requireStylesheet(lessPath)
expect($('head style').length).toBe lengthBefore + 1
element = $('head style[id*="sample.less"]')
expect(element.attr('id')).toBe lessPath
expect(element.text()).toBe """
#header {
color: #4d926f;
}
h2 {
color: #4d926f;
}
"""
# doesn't append twice
themeManager.requireStylesheet(lessPath)
expect($('head style').length).toBe lengthBefore + 1
$('head style[id*="sample.less"]').remove()
it "supports requiring css and less stylesheets without an explicit extension", ->
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'css')
expect($('head style[id*="css.css"]').attr('id')).toBe project.resolve('css.css')
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
expect($('head style[id*="sample.less"]').attr('id')).toBe project.resolve('sample.less')
$('head style[id*="css.css"]').remove()
$('head style[id*="sample.less"]').remove()
describe ".removeStylesheet(path)", ->
it "removes styling applied by given stylesheet path", ->
cssPath = require.resolve('./fixtures/css.css')
expect($(document.body).css('font-weight')).not.toBe("bold")
themeManager.requireStylesheet(cssPath)
expect($(document.body).css('font-weight')).toBe("bold")
themeManager.removeStylesheet(cssPath)
expect($(document.body).css('font-weight')).not.toBe("bold")
describe "base stylesheet loading", ->
beforeEach ->
window.rootView = new RootView
rootView.append $$ -> @div class: 'editor'
rootView.attachToDom()
themeManager.load()
it "loads the correct values from the theme's ui-variables file", ->
config.set('core.themes', ['theme-with-ui-variables'])
# an override loaded in the base css
expect(rootView.css("background-color")).toBe "rgb(0, 0, 255)"
# from within the theme itself
expect($(".editor").css("padding-top")).toBe "150px"
expect($(".editor").css("padding-right")).toBe "150px"
expect($(".editor").css("padding-bottom")).toBe "150px"

View File

@ -75,66 +75,6 @@ describe "Window", ->
expect(window.onbeforeunload(new Event('beforeunload'))).toBeFalsy()
expect(atom.confirmSync).toHaveBeenCalled()
describe "requireStylesheet(path)", ->
it "synchronously loads css at the given path and installs a style tag for it in the head", ->
cssPath = project.resolve('css.css')
lengthBefore = $('head style').length
requireStylesheet(cssPath)
expect($('head style').length).toBe lengthBefore + 1
element = $('head style[id*="css.css"]')
expect(element.attr('id')).toBe cssPath
expect(element.text()).toBe fs.read(cssPath)
# doesn't append twice
requireStylesheet(cssPath)
expect($('head style').length).toBe lengthBefore + 1
$('head style[id*="css.css"]').remove()
it "synchronously loads and parses less files at the given path and installs a style tag for it in the head", ->
lessPath = project.resolve('sample.less')
lengthBefore = $('head style').length
requireStylesheet(lessPath)
expect($('head style').length).toBe lengthBefore + 1
element = $('head style[id*="sample.less"]')
expect(element.attr('id')).toBe lessPath
expect(element.text()).toBe """
#header {
color: #4d926f;
}
h2 {
color: #4d926f;
}
"""
# doesn't append twice
requireStylesheet(lessPath)
expect($('head style').length).toBe lengthBefore + 1
$('head style[id*="sample.less"]').remove()
it "supports requiring css and less stylesheets without an explicit extension", ->
requireStylesheet path.join(__dirname, 'fixtures', 'css')
expect($('head style[id*="css.css"]').attr('id')).toBe project.resolve('css.css')
requireStylesheet path.join(__dirname, 'fixtures', 'sample')
expect($('head style[id*="sample.less"]').attr('id')).toBe project.resolve('sample.less')
$('head style[id*="css.css"]').remove()
$('head style[id*="sample.less"]').remove()
describe ".removeStylesheet(path)", ->
it "removes styling applied by given stylesheet path", ->
cssPath = require.resolve('./fixtures/css.css')
expect($(document.body).css('font-weight')).not.toBe("bold")
requireStylesheet(cssPath)
expect($(document.body).css('font-weight')).toBe("bold")
removeStylesheet(cssPath)
expect($(document.body).css('font-weight')).not.toBe("bold")
describe ".unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", ->
rootViewState = rootView.serialize()
@ -156,38 +96,6 @@ describe "Window", ->
expect(buffer.subscriptionCount()).toBe 0
describe ".deserialize(state)", ->
class Foo
@deserialize: ({name}) -> new Foo(name)
constructor: (@name) ->
beforeEach ->
registerDeserializer(Foo)
afterEach ->
unregisterDeserializer(Foo)
it "calls deserialize on the deserializer for the given state object, or returns undefined if one can't be found", ->
spyOn(console, 'warn')
object = deserialize({ deserializer: 'Foo', name: 'Bar' })
expect(object.name).toBe 'Bar'
expect(deserialize({ deserializer: 'Bogus' })).toBeUndefined()
describe "when the deserializer has a version", ->
beforeEach ->
Foo.version = 2
describe "when the deserialized state has a matching version", ->
it "attempts to deserialize the state", ->
object = deserialize({ deserializer: 'Foo', version: 2, name: 'Bar' })
expect(object.name).toBe 'Bar'
describe "when the deserialized state has a non-matching version", ->
it "returns undefined", ->
expect(deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined()
expect(deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined()
expect(deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined()
describe "drag and drop", ->
buildDragEvent = (type, files) ->
dataTransfer =
@ -206,7 +114,7 @@ describe "Window", ->
it "opens it", ->
spyOn(atom, "open")
event = buildDragEvent("drop", [ {path: "/fake1"}, {path: "/fake2"} ])
window.onDrop(event)
$(document).trigger(event)
expect(atom.open.callCount).toBe 1
expect(atom.open.argsForCall[0][0]).toEqual pathsToOpen: ['/fake1', '/fake2']
@ -214,7 +122,7 @@ describe "Window", ->
it "does nothing", ->
spyOn(atom, "open")
event = buildDragEvent("drop", [])
window.onDrop(event)
$(document).trigger(event)
expect(atom.open).not.toHaveBeenCalled()
describe "when a link is clicked", ->

View File

@ -83,7 +83,8 @@ class AtomPackage extends Package
activateStylesheets: ->
type = if @metadata.theme then 'theme' else 'bundled'
applyStylesheet(stylesheetPath, content, type) for [stylesheetPath, content] in @stylesheets
for [stylesheetPath, content] in @stylesheets
atom.themes.applyStylesheet(stylesheetPath, content, type)
activateResources: ->
keymap.add(keymapPath, map) for [keymapPath, map] in @keymaps
@ -113,7 +114,8 @@ class AtomPackage extends Package
fsUtils.listSync(menusDirPath, ['cson', 'json'])
loadStylesheets: ->
@stylesheets = @getStylesheetPaths().map (stylesheetPath) -> [stylesheetPath, loadStylesheet(stylesheetPath)]
@stylesheets = @getStylesheetPaths().map (stylesheetPath) ->
[stylesheetPath, atom.themes.loadStylesheet(stylesheetPath)]
getStylesheetsPath: ->
path.join(@path, @constructor.stylesheetsDir)
@ -165,17 +167,17 @@ class AtomPackage extends Package
syntax.removeGrammar(grammar) for grammar in @grammars
syntax.removeProperties(scopedPropertiesPath) for [scopedPropertiesPath] in @scopedProperties
keymap.remove(keymapPath) for [keymapPath] in @keymaps
removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
reloadStylesheets: ->
oldSheets = _.clone(@stylesheets)
@loadStylesheets()
removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
@reloadStylesheet(stylesheetPath, content) for [stylesheetPath, content] in @stylesheets
reloadStylesheet: (stylesheetPath, content) ->
type = if @metadata.theme then 'theme' else 'bundled'
window.applyStylesheet(stylesheetPath, content, type)
atom.themes.applyStylesheet(stylesheetPath, content, type)
requireMainModule: ->
return @mainModule if @mainModule?

View File

@ -10,155 +10,140 @@ path = require 'path'
dialog = remote.require 'dialog'
app = remote.require 'app'
{Document} = require 'telepath'
ThemeManager = require './theme-manager'
ContextMenuManager = require './context-menu-manager'
DeserializerManager = require './deserializer-manager'
Subscriber = require './subscriber'
window.atom =
loadedPackages: {}
activePackages: {}
packageStates: {}
themes: new ThemeManager()
contextMenu: new ContextMenuManager(remote.getCurrentWindow().loadSettings.devMode)
# Public: Atom global for dealing with packages, themes, menus, and the window.
#
# An instance of this class is always available as the `atom` global.
module.exports =
class Atom
_.extend @prototype, Subscriber
getLoadSettings: ->
@getCurrentWindow().loadSettings
constructor: ->
@rootViewParentSelector = 'body'
@deserializers = new DeserializerManager()
initialize: ->
@unsubscribe()
Config = require './config'
Keymap = require './keymap'
PackageManager = require './package-manager'
Pasteboard = require './pasteboard'
Syntax = require './syntax'
ThemeManager = require './theme-manager'
ContextMenuManager = require './context-menu-manager'
@packages = new PackageManager()
#TODO Remove once packages have been updated to not touch atom.packageStates directly
@__defineGetter__ 'packageStates', => @packages.packageStates
@__defineSetter__ 'packageStates', (packageStates) => @packages.packageStates = packageStates
@subscribe @packages, 'loaded', => @watchThemes()
@themes = new ThemeManager()
@contextMenu = new ContextMenuManager(@getLoadSettings().devMode)
@config = new Config()
@pasteboard = new Pasteboard()
@keymap = new Keymap()
@syntax = deserialize(@getWindowState('syntax')) ? new Syntax()
getCurrentWindow: ->
remote.getCurrentWindow()
getPackageState: (name) ->
@packageStates[name]
# Public: Get the dimensions of this window.
#
# Returns an object with x, y, width, and height keys.
getDimensions: ->
browserWindow = @getCurrentWindow()
[x, y] = browserWindow.getPosition()
[width, height] = browserWindow.getSize()
{x, y, width, height}
setPackageState: (name, state) ->
@packageStates[name] = state
activatePackages: ->
@activatePackage(pack.name) for pack in @getLoadedPackages()
activatePackage: (name, options) ->
if pack = @loadPackage(name, options)
@activePackages[pack.name] = pack
pack.activate(options)
pack
deactivatePackages: ->
@deactivatePackage(pack.name) for pack in @getActivePackages()
deactivatePackage: (name) ->
if pack = @getActivePackage(name)
@setPackageState(pack.name, state) if state = pack.serialize?()
pack.deactivate()
delete @activePackages[pack.name]
# Public: Set the dimensions of the window.
#
# The window will be centered if either the x or y coordinate is not set
# in the dimensions parameter.
#
# * dimensions:
# + x:
# The new x coordinate.
# + y:
# The new y coordinate.
# + width:
# The new width.
# + height:
# The new height.
setDimensions: ({x, y, width, height}) ->
browserWindow = @getCurrentWindow()
browserWindow.setSize(width, height)
if x? and y?
browserWindow.setPosition(x, y)
else
throw new Error("No active package for name '#{name}'")
browserWindow.center()
getActivePackage: (name) ->
@activePackages[name]
restoreDimensions: (defaultDimensions={width: 800, height: 600})->
dimensions = @getWindowState().getObject('dimensions')
dimensions = defaultDimensions unless dimensions?.width and dimensions?.height
@setDimensions(dimensions)
isPackageActive: (name) ->
@getActivePackage(name)?
getLoadSettings: ->
@getCurrentWindow().loadSettings
getActivePackages: ->
_.values(@activePackages)
deserializeProject: ->
Project = require './project'
state = @getWindowState()
@project = deserialize(state.get('project'))
unless @project?
@project = new Project(@getLoadSettings().initialPath)
state.set('project', @project.getState())
loadPackages: ->
# Ensure atom exports is already in the require cache so the load time
# of the first package isn't skewed by being the first to require atom
require '../exports/atom'
deserializeRootView: ->
RootView = require './root-view'
state = @getWindowState()
@rootView = deserialize(state.get('rootView'))
unless @rootView?
@rootView = new RootView()
state.set('rootView', @rootView.getState())
$(@rootViewParentSelector).append(@rootView)
@loadPackage(name) for name in @getAvailablePackageNames() when not @isPackageDisabled(name)
@watchThemes()
deserializePackageStates: ->
state = @getWindowState()
@packages.packageStates = state.getObject('packageStates') ? {}
state.remove('packageStates')
loadPackage: (name, options) ->
if @isPackageDisabled(name)
return console.warn("Tried to load disabled package '#{name}'")
if packagePath = @resolvePackagePath(name)
return pack if pack = @getLoadedPackage(name)
pack = Package.load(packagePath, options)
if pack.metadata.theme
@themes.register(pack)
else
@loadedPackages[pack.name] = pack
pack
else
throw new Error("Could not resolve '#{name}' to a package path")
unloadPackage: (name) ->
if @isPackageActive(name)
throw new Error("Tried to unload active package '#{name}'")
if pack = @getLoadedPackage(name)
delete @loadedPackages[pack.name]
else
throw new Error("No loaded package for name '#{name}'")
resolvePackagePath: (name) ->
return name if fsUtils.isDirectorySync(name)
packagePath = fsUtils.resolve(config.packageDirPaths..., name)
return packagePath if fsUtils.isDirectorySync(packagePath)
packagePath = path.join(window.resourcePath, 'node_modules', name)
return packagePath if @isInternalPackage(packagePath)
isInternalPackage: (packagePath) ->
{engines} = Package.loadMetadata(packagePath, true)
engines?.atom?
getLoadedPackage: (name) ->
@loadedPackages[name]
isPackageLoaded: (name) ->
@getLoadedPackage(name)?
getLoadedPackages: ->
_.values(@loadedPackages)
isPackageDisabled: (name) ->
_.include(config.get('core.disabledPackages') ? [], name)
getAvailablePackagePaths: ->
packagePaths = []
for packageDirPath in config.packageDirPaths
for packagePath in fsUtils.listSync(packageDirPath)
packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath)
for packagePath in fsUtils.listSync(path.join(window.resourcePath, 'node_modules'))
packagePaths.push(packagePath) if @isInternalPackage(packagePath)
_.uniq(packagePaths)
getAvailablePackageNames: ->
_.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
getAvailablePackageMetadata: ->
packages = []
for packagePath in atom.getAvailablePackagePaths()
name = path.basename(packagePath)
metadata = atom.getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true)
packages.push(metadata)
packages
#TODO Remove theses once packages have been migrated
getPackageState: (args...) -> @packages.getPackageState(args...)
setPackageState: (args...) -> @packages.setPackageState(args...)
activatePackages: (args...) -> @packages.activatePackages(args...)
activatePackage: (args...) -> @packages.activatePackage(args...)
deactivatePackages: (args...) -> @packages.deactivatePackages(args...)
deactivatePackage: (args...) -> @packages.deactivatePackage(args...)
getActivePackage: (args...) -> @packages.getActivePackage(args...)
isPackageActive: (args...) -> @packages.isPackageActive(args...)
getActivePackages: (args...) -> @packages.getActivePackages(args...)
loadPackages: (args...) -> @packages.loadPackages(args...)
loadPackage: (args...) -> @packages.loadPackage(args...)
unloadPackage: (args...) -> @packages.unloadPackage(args...)
resolvePackagePath: (args...) -> @packages.resolvePackagePath(args...)
isInternalPackage: (args...) -> @packages.isInternalPackage(args...)
getLoadedPackage: (args...) -> @packages.getLoadedPackage(args...)
isPackageLoaded: (args...) -> @packages.isPackageLoaded(args...)
getLoadedPackages: (args...) -> @packages.getLoadedPackages(args...)
isPackageDisabled: (args...) -> @packages.isPackageDisabled(args...)
getAvailablePackagePaths: (args...) -> @packages.getAvailablePackagePaths(args...)
getAvailablePackageNames: (args...) -> @packages.getAvailablePackageNames(args...)
getAvailablePackageMetadata: (args...)-> @packages.getAvailablePackageMetadata(args...)
loadThemes: ->
@themes.load()
watchThemes: ->
@themes.on 'reloaded', =>
@reloadBaseStylesheets()
pack.reloadStylesheets?() for name, pack of @loadedPackages
pack.reloadStylesheets?() for name, pack of @getLoadedPackages()
null
loadBaseStylesheets: ->
requireStylesheet('bootstrap/less/bootstrap')
@reloadBaseStylesheets()
reloadBaseStylesheets: ->
requireStylesheet('../static/atom')
if nativeStylesheetPath = fsUtils.resolveOnLoadPath(process.platform, ['css', 'less'])
requireStylesheet(nativeStylesheetPath)
open: (options) ->
ipc.sendChannel('open', options)
@ -210,8 +195,7 @@ window.atom =
close: ->
@getCurrentWindow().close()
exit: (status) ->
app.exit(status)
exit: (status) -> app.exit(status)
toggleFullScreen: ->
@setFullScreen(!@isFullScreen())
@ -236,7 +220,7 @@ window.atom =
filename = "editor-#{sha1}"
if filename
path.join(config.userStoragePath, filename)
path.join(@config.userStoragePath, filename)
else
null
@ -289,8 +273,22 @@ window.atom =
shell.beep()
requireUserInitScript: ->
userInitScriptPath = path.join(config.configDirPath, "user.coffee")
userInitScriptPath = path.join(@config.configDirPath, "user.coffee")
try
require userInitScriptPath if fsUtils.isFileSync(userInitScriptPath)
catch error
console.error "Failed to load `#{userInitScriptPath}`", error.stack, error
requireWithGlobals: (id, globals={}) ->
existingGlobals = {}
for key, value of globals
existingGlobals[key] = window[key]
window[key] = value
require(id)
for key, value of existingGlobals
if value is undefined
delete window[key]
else
window[key] = value

View File

@ -8,12 +8,6 @@ async = require 'async'
pathWatcher = require 'pathwatcher'
configDirPath = fsUtils.absolute("~/.atom")
nodeModulesDirPath = path.join(resourcePath, "node_modules")
bundledKeymapsDirPath = path.join(resourcePath, "keymaps")
userPackagesDirPath = path.join(configDirPath, "packages")
userPackageDirPaths = [userPackagesDirPath]
userPackageDirPaths.unshift(path.join(configDirPath, "dev", "packages")) if atom.getLoadSettings().devMode
userStoragePath = path.join(configDirPath, "storage")
# Public: Used to access all of Atom's configuration details.
#
@ -36,23 +30,26 @@ module.exports =
class Config
_.extend @prototype, EventEmitter
configDirPath: configDirPath
bundledPackageDirPaths: [nodeModulesDirPath]
bundledKeymapsDirPath: bundledKeymapsDirPath
nodeModulesDirPath: nodeModulesDirPath
packageDirPaths: _.clone(userPackageDirPaths)
userPackageDirPaths: userPackageDirPaths
userStoragePath: userStoragePath
lessSearchPaths: [
path.join(resourcePath, 'static', 'variables')
path.join(resourcePath, 'static')
]
defaultSettings: null
settings: null
configFileHasErrors: null
# Private: Created during initialization, available as `global.config`
constructor: ->
@configDirPath = configDirPath
@bundledKeymapsDirPath = path.join(resourcePath, "keymaps")
@nodeModulesDirPath = path.join(resourcePath, "node_modules")
@bundledPackageDirPaths = [@nodeModulesDirPath]
@lessSearchPaths = [
path.join(resourcePath, 'static', 'variables')
path.join(resourcePath, 'static')
]
@packageDirPaths = [path.join(configDirPath, "packages")]
if atom.getLoadSettings().devMode
@packageDirPaths.unshift(path.join(configDirPath, "dev", "packages"))
@userPackageDirPaths = _.clone(@packageDirPaths)
@userStoragePath = path.join(configDirPath, "storage")
@defaultSettings =
core: _.clone(require('./root-view').configDefaults)
editor: _.clone(require('./editor').configDefaults)

View File

@ -0,0 +1,38 @@
{Document} = require 'telepath'
module.exports =
class DeserializerManager
constructor: ->
@deserializers = {}
@deferredDeserializers = {}
registerDeserializer: (klasses...) ->
@deserializers[klass.name] = klass for klass in klasses
registerDeferredDeserializer: (name, fn) ->
@deferredDeserializers[name] = fn
unregisterDeserializer: (klasses...) ->
delete @deserializers[klass.name] for klass in klasses
deserialize: (state, params) ->
return unless state?
if deserializer = @getDeserializer(state)
stateVersion = state.get?('version') ? state.version
return if deserializer.version? and deserializer.version isnt stateVersion
if (state instanceof Document) and not deserializer.acceptsDocuments
state = state.toObject()
deserializer.deserialize(state, params)
else
console.warn "No deserializer found for", state
getDeserializer: (state) ->
return unless state?
name = state.get?('deserializer') ? state.deserializer
if @deferredDeserializers[name]
@deferredDeserializers[name]()
delete @deferredDeserializers[name]
@deserializers[name]

129
src/package-manager.coffee Normal file
View File

@ -0,0 +1,129 @@
EventEmitter = require './event-emitter'
fsUtils = require './fs-utils'
_ = require './underscore-extensions'
Package = require './package'
path = require 'path'
module.exports =
class PackageManager
_.extend @prototype, EventEmitter
constructor: ->
@loadedPackages = {}
@activePackages = {}
@packageStates = {}
getPackageState: (name) ->
@packageStates[name]
setPackageState: (name, state) ->
@packageStates[name] = state
activatePackages: ->
@activatePackage(pack.name) for pack in @getLoadedPackages()
activatePackage: (name, options) ->
if pack = @loadPackage(name, options)
@activePackages[pack.name] = pack
pack.activate(options)
pack
deactivatePackages: ->
@deactivatePackage(pack.name) for pack in @getActivePackages()
deactivatePackage: (name) ->
if pack = @getActivePackage(name)
@setPackageState(pack.name, state) if state = pack.serialize?()
pack.deactivate()
delete @activePackages[pack.name]
else
throw new Error("No active package for name '#{name}'")
getActivePackage: (name) ->
@activePackages[name]
isPackageActive: (name) ->
@getActivePackage(name)?
getActivePackages: ->
_.values(@activePackages)
loadPackages: ->
# Ensure atom exports is already in the require cache so the load time
# of the first package isn't skewed by being the first to require atom
require '../exports/atom'
@loadPackage(name) for name in @getAvailablePackageNames() when not @isPackageDisabled(name)
@trigger 'loaded'
loadPackage: (name, options) ->
if @isPackageDisabled(name)
return console.warn("Tried to load disabled package '#{name}'")
if packagePath = @resolvePackagePath(name)
return pack if pack = @getLoadedPackage(name)
pack = Package.load(packagePath, options)
if pack.metadata.theme
atom.themes.register(pack)
else
@loadedPackages[pack.name] = pack
pack
else
throw new Error("Could not resolve '#{name}' to a package path")
unloadPackage: (name) ->
if @isPackageActive(name)
throw new Error("Tried to unload active package '#{name}'")
if pack = @getLoadedPackage(name)
delete @loadedPackages[pack.name]
else
throw new Error("No loaded package for name '#{name}'")
resolvePackagePath: (name) ->
return name if fsUtils.isDirectorySync(name)
packagePath = fsUtils.resolve(config.packageDirPaths..., name)
return packagePath if fsUtils.isDirectorySync(packagePath)
packagePath = path.join(window.resourcePath, 'node_modules', name)
return packagePath if @isInternalPackage(packagePath)
isInternalPackage: (packagePath) ->
{engines} = Package.loadMetadata(packagePath, true)
engines?.atom?
getLoadedPackage: (name) ->
@loadedPackages[name]
isPackageLoaded: (name) ->
@getLoadedPackage(name)?
getLoadedPackages: ->
_.values(@loadedPackages)
isPackageDisabled: (name) ->
_.include(config.get('core.disabledPackages') ? [], name)
getAvailablePackagePaths: ->
packagePaths = []
for packageDirPath in config.packageDirPaths
for packagePath in fsUtils.listSync(packageDirPath)
packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath)
for packagePath in fsUtils.listSync(path.join(window.resourcePath, 'node_modules'))
packagePaths.push(packagePath) if @isInternalPackage(packagePath)
_.uniq(packagePaths)
getAvailablePackageNames: ->
_.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
getAvailablePackageMetadata: ->
packages = []
for packagePath in atom.getAvailablePackagePaths()
name = path.basename(packagePath)
metadata = atom.getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true)
packages.push(metadata)
packages

View File

@ -4,7 +4,7 @@ Package = require './package'
AtomPackage = require './atom-package'
_ = require './underscore-extensions'
$ = require './jquery-extensions'
fsUtils = require './fs-utils'
# Private: Handles discovering and loading available themes.
@ -15,6 +15,7 @@ class ThemeManager
constructor: ->
@loadedThemes = []
@activeThemes = []
@lessCache = null
# Internal-only:
register: (theme) ->
@ -33,9 +34,85 @@ class ThemeManager
getLoadedThemes: ->
_.clone(@loadedThemes)
# Internal-only:
loadBaseStylesheets: ->
@requireStylesheet('bootstrap/less/bootstrap')
@reloadBaseStylesheets()
# Internal-only:
reloadBaseStylesheets: ->
@requireStylesheet('../static/atom')
if nativeStylesheetPath = fsUtils.resolveOnLoadPath(process.platform, ['css', 'less'])
@requireStylesheet(nativeStylesheetPath)
# Internal-only:
stylesheetElementForId: (id) ->
$("""head style[id="#{id}"]""")
# Internal-only:
resolveStylesheet: (stylesheetPath) ->
if path.extname(stylesheetPath).length > 0
fsUtils.resolveOnLoadPath(stylesheetPath)
else
fsUtils.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
# Public: resolves and applies the stylesheet specified by the path.
#
# * stylesheetPath: String. Can be an absolute path or the name of a CSS or
# LESS file in the stylesheets path.
#
# Returns the absolute path to the stylesheet
requireStylesheet: (stylesheetPath) ->
if fullPath = @resolveStylesheet(stylesheetPath)
content = @loadStylesheet(fullPath)
@applyStylesheet(fullPath, content)
else
throw new Error("Could not find a file at path '#{stylesheetPath}'")
fullPath
# Internal-only:
loadStylesheet: (stylesheetPath) ->
if path.extname(stylesheetPath) is '.less'
@loadLessStylesheet(stylesheetPath)
else
fsUtils.read(stylesheetPath)
# Internal-only:
loadLessStylesheet: (lessStylesheetPath) ->
unless lessCache?
LessCompileCache = require './less-compile-cache'
@lessCache = new LessCompileCache()
try
@lessCache.read(lessStylesheetPath)
catch e
console.error """
Error compiling less stylesheet: #{lessStylesheetPath}
Line number: #{e.line}
#{e.message}
"""
# Internal-only:
removeStylesheet: (stylesheetPath) ->
unless fullPath = @resolveStylesheet(stylesheetPath)
throw new Error("Could not find a file at path '#{stylesheetPath}'")
@stylesheetElementForId(fullPath).remove()
# Internal-only:
applyStylesheet: (id, text, ttype = 'bundled') ->
styleElement = @stylesheetElementForId(id)
if styleElement.length
styleElement.text(text)
else
if $("head style.#{ttype}").length
$("head style.#{ttype}:last").after "<style class='#{ttype}' id='#{id}'>#{text}</style>"
else
$("head").append "<style class='#{ttype}' id='#{id}'>#{text}</style>"
# Internal-only:
unload: ->
removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
@removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
theme.deactivate() while theme = @activeThemes.pop()
# Internal-only:
@ -50,7 +127,7 @@ class ThemeManager
@activateTheme(themeName) for themeName in themeNames
@loadUserStylesheet()
@reloadBaseStylesheets()
@trigger('reloaded')
# Private:
@ -118,5 +195,5 @@ class ThemeManager
loadUserStylesheet: ->
if userStylesheetPath = @getUserStylesheetPath()
@userStylesheetPath = userStylesheetPath
userStylesheetContents = loadStylesheet(userStylesheetPath)
applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
userStylesheetContents = @loadStylesheet(userStylesheetPath)
@applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')

View File

@ -1,9 +1,10 @@
# Like sands through the hourglass, so are the days of our lives.
startTime = new Date().getTime()
require './atom'
require './window'
Atom = require './atom'
window.atom = new Atom()
window.setUpEnvironment('editor')
window.startEditorWindow()
console.log "Window load time: #{new Date().getTime() - startTime}ms"

View File

@ -1,7 +1,7 @@
$ = require './jquery-extensions'
_ = require './underscore-extensions'
ipc = require 'ipc'
remote = require 'remote'
shell = require 'shell'
Subscriber = require './subscriber'
fsUtils = require './fs-utils'
@ -20,27 +20,43 @@ class WindowEventHandler
$(atom.contextMenu.activeElement).trigger(command, args...)
@subscribe $(window), 'focus', -> $("body").removeClass('is-blurred')
@subscribe $(window), 'blur', -> $("body").addClass('is-blurred')
@subscribe $(window), 'window:open-path', (event, {pathToOpen, initialLine}) ->
rootView?.open(pathToOpen, {initialLine}) unless fsUtils.isDirectorySync(pathToOpen)
atom.rootView?.open(pathToOpen, {initialLine}) unless fsUtils.isDirectorySync(pathToOpen)
@subscribe $(window), 'beforeunload', =>
confirmed = rootView?.confirmClose()
atom.hide() if confirmed and not @reloadRequested and remote.getCurrentWindow().isWebViewFocused()
confirmed = atom.rootView?.confirmClose()
atom.hide() if confirmed and not @reloadRequested and atom.getCurrentWindow().isWebViewFocused()
@reloadRequested = false
confirmed
@subscribe $(window), 'unload', ->
atom.getWindowState().set('dimensions', atom.getDimensions())
@subscribeToCommand $(window), 'window:toggle-full-screen', => atom.toggleFullScreen()
@subscribeToCommand $(window), 'window:close', => atom.close()
@subscribeToCommand $(window), 'window:reload', =>
@reloadRequested = true
atom.reload()
@subscribeToCommand $(window), 'window:toggle-dev-tools', => atom.toggleDevTools()
@subscribeToCommand $(document), 'core:focus-next', @focusNext
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
@subscribe $(document), 'keydown', keymap.handleKeyEvent
@subscribe $(document), 'keydown', atom.keymap.handleKeyEvent
@subscribe $(document), 'drop', (e) ->
e.preventDefault()
e.stopPropagation()
pathsToOpen = _.pluck(e.originalEvent.dataTransfer.files, 'path')
atom.open({pathsToOpen}) if pathsToOpen.length > 0
@subscribe $(document), 'drop', onDrop
@subscribe $(document), 'dragover', (e) ->
e.preventDefault()
e.stopPropagation()
@ -54,7 +70,7 @@ class WindowEventHandler
openLink: (event) =>
location = $(event.target).attr('href')
if location and location[0] isnt '#' and /^https?:\/\//.test(location)
require('shell').openExternal(location)
shell.openExternal(location)
false
eachTabIndexedElement: (callback) ->

View File

@ -1,17 +1,9 @@
fsUtils = require './fs-utils'
path = require 'path'
telepath = require 'telepath'
$ = require './jquery-extensions'
_ = require './underscore-extensions'
remote = require 'remote'
ipc = require 'ipc'
WindowEventHandler = require './window-event-handler'
deserializers = {}
deferredDeserializers = {}
defaultWindowDimensions = {width: 800, height: 600}
lessCache = null
### Internal ###
windowEventHandler = null
@ -28,19 +20,13 @@ displayWindow = ->
# This method is called in any window needing a general environment, including specs
window.setUpEnvironment = (windowMode) ->
atom.windowMode = windowMode
window.resourcePath = remote.getCurrentWindow().loadSettings.resourcePath
Config = require './config'
Syntax = require './syntax'
Pasteboard = require './pasteboard'
Keymap = require './keymap'
window.rootViewParentSelector = 'body'
window.config = new Config
window.syntax = deserialize(atom.getWindowState('syntax')) ? new Syntax
window.pasteboard = new Pasteboard
window.keymap = new Keymap()
window.resourcePath = atom.getLoadSettings().resourcePath
atom.initialize()
#TODO remove once all packages use the atom global
window.config = atom.config
window.syntax = atom.syntax
window.pasteboard = atom.pasteboard
window.keymap = atom.keymap
# Set up the default event handlers and menus for a non-editor windows.
#
@ -50,8 +36,8 @@ window.setUpEnvironment = (windowMode) ->
# This should only be called after setUpEnvironment() has been called.
window.setUpDefaultEvents = ->
windowEventHandler = new WindowEventHandler
keymap.loadBundledKeymaps()
ipc.sendChannel 'update-application-menu', keymap.keystrokesByCommandForSelector('body')
atom.keymap.loadBundledKeymaps()
ipc.sendChannel 'update-application-menu', atom.keymap.keystrokesByCommandForSelector('body')
# This method is only called when opening a real application window
window.startEditorWindow = ->
@ -60,16 +46,16 @@ window.startEditorWindow = ->
windowEventHandler = new WindowEventHandler
restoreDimensions()
config.load()
keymap.loadBundledKeymaps()
atom.loadBaseStylesheets()
atom.loadPackages()
atom.loadThemes()
atom.config.load()
atom.keymap.loadBundledKeymaps()
atom.themes.loadBaseStylesheets()
atom.packages.loadPackages()
atom.themes.load()
deserializeEditorWindow()
atom.activatePackages()
keymap.loadUserKeymaps()
atom.packages.activatePackages()
atom.keymap.loadUserKeymaps()
atom.requireUserInitScript()
ipc.sendChannel 'update-application-menu', keymap.keystrokesByCommandForSelector('body')
ipc.sendChannel 'update-application-menu', atom.keymap.keystrokesByCommandForSelector('body')
$(window).on 'unload', ->
$(document.body).hide()
unloadEditorWindow()
@ -78,188 +64,58 @@ window.startEditorWindow = ->
displayWindow()
window.unloadEditorWindow = ->
return if not project and not rootView
return if not atom.project and not atom.rootView
windowState = atom.getWindowState()
windowState.set('project', project.serialize())
windowState.set('syntax', syntax.serialize())
windowState.set('rootView', rootView.serialize())
atom.deactivatePackages()
windowState.set('packageStates', atom.packageStates)
windowState.set('project', atom.project.serialize())
windowState.set('syntax', atom.syntax.serialize())
windowState.set('rootView', atom.rootView.serialize())
atom.packages.deactivatePackages()
windowState.set('packageStates', atom.packages.packageStates)
atom.saveWindowState()
rootView.remove()
project.destroy()
atom.rootView.remove()
atom.project.destroy()
windowEventHandler?.unsubscribe()
lessCache?.destroy()
window.rootView = null
window.project = null
window.installAtomCommand = (callback) ->
installAtomCommand = (callback) ->
commandPath = path.join(window.resourcePath, 'atom.sh')
require('./command-installer').install(commandPath, callback)
window.installApmCommand = (callback) ->
installApmCommand = (callback) ->
commandPath = path.join(window.resourcePath, 'node_modules', '.bin', 'apm')
require('./command-installer').install(commandPath, callback)
window.onDrop = (e) ->
e.preventDefault()
e.stopPropagation()
pathsToOpen = _.pluck(e.originalEvent.dataTransfer.files, 'path')
atom.open({pathsToOpen}) if pathsToOpen.length > 0
window.deserializeEditorWindow = ->
RootView = require './root-view'
Project = require './project'
atom.deserializePackageStates()
atom.deserializeProject()
window.project = atom.project
atom.deserializeRootView()
window.rootView = atom.rootView
windowState = atom.getWindowState()
window.getDimensions = -> atom.getDimensions()
atom.packageStates = windowState.getObject('packageStates') ? {}
windowState.remove('packageStates')
window.setDimensions = (args...) -> atom.setDimensions(args...)
window.project = deserialize(windowState.get('project'))
unless window.project?
window.project = new Project(atom.getLoadSettings().initialPath)
windowState.set('project', window.project.getState())
window.rootView = deserialize(windowState.get('rootView'))
unless window.rootView?
window.rootView = new RootView()
windowState.set('rootView', window.rootView.getState())
$(rootViewParentSelector).append(rootView)
project.on 'path-changed', ->
projectPath = project.getPath()
atom.getLoadSettings().initialPath = projectPath
window.stylesheetElementForId = (id) ->
$("""head style[id="#{id}"]""")
window.resolveStylesheet = (stylesheetPath) ->
if path.extname(stylesheetPath).length > 0
fsUtils.resolveOnLoadPath(stylesheetPath)
else
fsUtils.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
# Public: resolves and applies the stylesheet specified by the path.
#
# * stylesheetPath: String. Can be an absolute path or the name of a CSS or
# LESS file in the stylesheets path.
#
# Returns the absolute path to the stylesheet
window.requireStylesheet = (stylesheetPath) ->
if fullPath = window.resolveStylesheet(stylesheetPath)
content = window.loadStylesheet(fullPath)
window.applyStylesheet(fullPath, content)
else
throw new Error("Could not find a file at path '#{stylesheetPath}'")
fullPath
window.loadStylesheet = (stylesheetPath) ->
if path.extname(stylesheetPath) is '.less'
loadLessStylesheet(stylesheetPath)
else
fsUtils.read(stylesheetPath)
window.loadLessStylesheet = (lessStylesheetPath) ->
unless lessCache?
LessCompileCache = require './less-compile-cache'
lessCache = new LessCompileCache()
try
lessCache.read(lessStylesheetPath)
catch e
console.error """
Error compiling less stylesheet: #{lessStylesheetPath}
Line number: #{e.line}
#{e.message}
"""
window.removeStylesheet = (stylesheetPath) ->
unless fullPath = window.resolveStylesheet(stylesheetPath)
throw new Error("Could not find a file at path '#{stylesheetPath}'")
window.stylesheetElementForId(fullPath).remove()
window.applyStylesheet = (id, text, ttype = 'bundled') ->
styleElement = window.stylesheetElementForId(id)
if styleElement.length
styleElement.text(text)
else
if $("head style.#{ttype}").length
$("head style.#{ttype}:last").after "<style class='#{ttype}' id='#{id}'>#{text}</style>"
else
$("head").append "<style class='#{ttype}' id='#{id}'>#{text}</style>"
window.getDimensions = ->
browserWindow = remote.getCurrentWindow()
[x, y] = browserWindow.getPosition()
[width, height] = browserWindow.getSize()
{x, y, width, height}
window.setDimensions = ({x, y, width, height}) ->
browserWindow = remote.getCurrentWindow()
browserWindow.setSize(width, height)
if x? and y?
browserWindow.setPosition(x, y)
else
browserWindow.center()
window.restoreDimensions = ->
dimensions = atom.getWindowState().getObject('dimensions')
dimensions = defaultWindowDimensions unless dimensions?.width and dimensions?.height
window.setDimensions(dimensions)
$(window).on 'unload', -> atom.getWindowState().set('dimensions', window.getDimensions())
window.restoreDimensions = (args...) -> atom.restoreDimensions(args...)
window.onerror = ->
atom.openDevTools()
window.registerDeserializers = (args...) ->
registerDeserializer(arg) for arg in args
window.registerDeserializer = (klass) ->
deserializers[klass.name] = klass
window.registerDeferredDeserializer = (name, fn) ->
deferredDeserializers[name] = fn
window.unregisterDeserializer = (klass) ->
delete deserializers[klass.name]
window.deserialize = (state, params) ->
return unless state?
if deserializer = getDeserializer(state)
stateVersion = state.get?('version') ? state.version
return if deserializer.version? and deserializer.version isnt stateVersion
if (state instanceof telepath.Document) and not deserializer.acceptsDocuments
state = state.toObject()
deserializer.deserialize(state, params)
else
console.warn "No deserializer found for", state
window.getDeserializer = (state) ->
return unless state?
name = state.get?('deserializer') ? state.deserializer
if deferredDeserializers[name]
deferredDeserializers[name]()
delete deferredDeserializers[name]
deserializers[name]
window.requireWithGlobals = (id, globals={}) ->
existingGlobals = {}
for key, value of globals
existingGlobals[key] = window[key]
window[key] = value
require(id)
for key, value of existingGlobals
if value is undefined
delete window[key]
else
window[key] = value
atom.deserializers.registerDeserializer(args...)
window.registerDeserializer = (args...) ->
atom.deserializers.registerDeserializer(args...)
window.registerDeferredDeserializer = (args...) ->
atom.deserializers.registerDeferredDeserializer(args...)
window.unregisterDeserializer = (args...) ->
atom.deserializers.unregisterDeserializer(args...)
window.deserialize = (args...) ->
atom.deserializers.deserialize(args...)
window.getDeserializer = (args...) ->
atom.deserializer.getDeserializer(args...)
window.requireWithGlobals = (args...) ->
atom.requireWithGlobals(args...)
window.measure = (description, fn) ->
start = new Date().getTime()