From 187263173bd70924d1e3e156f9c28de021acc18a Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 26 Mar 2013 14:57:03 -0700 Subject: [PATCH 01/79] Only exit specs on exceptions when `exitWhenDone` is true --- spec/spec-bootstrap.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/spec-bootstrap.coffee b/spec/spec-bootstrap.coffee index 1b0ffcd48..f3a961207 100644 --- a/spec/spec-bootstrap.coffee +++ b/spec/spec-bootstrap.coffee @@ -7,4 +7,4 @@ try runSpecSuite "spec-suite" catch e console.error(e.stack) - atom.exit(1) + atom.exit(1) if window.location.params.exitWhenDone From 7a4f5ad9d179b5e2373745f6eefd33648ef34102 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 18:52:06 -0600 Subject: [PATCH 02/79] Wait until TextMate packages are activated to add grammars/properties My plan is to cache the loading of packages so we don't have to load them from the disk repeatedly in specs. The first step of this is ensuring that load has no side-effects. --- src/app/atom.coffee | 8 +++++++- src/app/text-mate-package.coffee | 21 +++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index 5a784ea5f..bb6e2250b 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -13,6 +13,7 @@ _.extend atom, loadedThemes: [] pendingBrowserProcessCallbacks: {} loadedPackages: [] + activePackages: [] activatedAtomPackages: [] atomPackageStates: {} presentingModal: false @@ -50,7 +51,12 @@ _.extend atom, pack.load() activatePackages: -> - pack.activate() for pack in @loadedPackages + for pack in @loadedPackages + @activePackages.push(pack) + pack.activate() + + isPackageActive: (pack) -> + _.include(@activePackages, pack) getLoadedPackages: -> _.clone(@loadedPackages) diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index 4d2af792f..378f176c9 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -31,6 +31,11 @@ class TextMatePackage extends Package TextMatePackage.getLoadQueue().push(this) @loadScopedProperties() + activate: -> + syntax.addGrammar(grammar) for grammar in @grammars + for { selector, properties } in @scopedProperties + syntax.addProperties(selector, properties) + legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage', 'cson', 'json'] loadGrammars: (done) -> @@ -52,30 +57,22 @@ class TextMatePackage extends Package addGrammar: (grammar) -> @grammars.push(grammar) - syntax.addGrammar(grammar) - - activate: -> # no-op + syntax.addGrammar(grammar) if atom.isPackageActive(this) getGrammars: -> @grammars loadScopedProperties: -> - for { selector, properties } in @getScopedProperties() - syntax.addProperties(selector, properties) - - getScopedProperties: -> - scopedProperties = [] + @scopedProperties = [] for grammar in @getGrammars() if properties = @propertiesFromTextMateSettings(grammar) selector = syntax.cssSelectorFromScopeSelector(grammar.scopeName) - scopedProperties.push({selector, properties}) + @scopedProperties.push({selector, properties}) for {scope, settings} in @getTextMatePreferenceObjects() if properties = @propertiesFromTextMateSettings(settings) selector = syntax.cssSelectorFromScopeSelector(scope) if scope? - scopedProperties.push({selector, properties}) - - scopedProperties + @scopedProperties.push({selector, properties}) getTextMatePreferenceObjects: -> preferenceObjects = [] From af06575aad49ab133ef55f3c18f5a0e299449c67 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 19:03:09 -0600 Subject: [PATCH 03/79] Don't add AtomPackage keymaps until `activate` is called --- src/app/atom-package.coffee | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index f063296ad..1e9639522 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -8,6 +8,7 @@ CSON = require 'cson' module.exports = class AtomPackage extends Package metadata: null + keymaps: null mainModule: null deferActivation: false @@ -32,18 +33,21 @@ class AtomPackage extends Package @metadata ?= {} loadKeymaps: -> + @keymaps = [] + keymapsDirPath = fs.join(@path, 'keymaps') + keymapExtensions = ['cson', 'json', ''] if @metadata.keymaps for path in @metadata.keymaps - keymapPath = fs.resolve(keymapsDirPath, path, ['cson', 'json', '']) - keymap.load(keymapPath) + @keymaps.push(CSON.readObject(fs.resolve(keymapsDirPath, path, keymapExtensions))) else - keymap.loadDirectory(keymapsDirPath) + for path in fs.list(keymapsDirPath, ['cson', 'json', '']) ? [] + @keymaps.push(CSON.readObject(path)) loadStylesheets: -> stylesheetDirPath = fs.join(@path, 'stylesheets') - for stylesheetPath in fs.list(stylesheetDirPath) ? [] + for stylesheetPath in fs.list(stylesheetDirPath, ['css', 'less']) ? [] requireStylesheet(stylesheetPath) loadGrammars: -> @@ -60,15 +64,20 @@ class AtomPackage extends Package syntax.addProperties(selector, properties) activate: -> + keymap.add(map) for map in @keymaps + if @deferActivation @subscribeToActivationEvents() else - try - if @requireMainModule() - config.setDefaults(@name, @mainModule.configDefaults) - atom.activateAtomPackage(this) - catch e - console.warn "Failed to activate package named '#{@name}'", e.stack + @activateNow() + + activateNow: -> + try + if @requireMainModule() + config.setDefaults(@name, @mainModule.configDefaults) + atom.activateAtomPackage(this) + catch e + console.warn "Failed to activate package named '#{@name}'", e.stack requireMainModule: -> return @mainModule if @mainModule @@ -90,7 +99,7 @@ class AtomPackage extends Package activateHandler = (event) => bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event) @deferActivation = false - @activate() + @activateNow() $(event.target).trigger(event) @restoreEventHandlersOnBubblePath(bubblePathEventHandlers) @unsubscribeFromActivationEvents(activateHandler) From bf7e586e6aa194711be9cd499ae199c66ffa957b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 19:15:19 -0600 Subject: [PATCH 04/79] Don't apply stylesheets until `active` is called for atom packages --- src/app/atom-package.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 1e9639522..1ceeb62f0 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -9,6 +9,7 @@ module.exports = class AtomPackage extends Package metadata: null keymaps: null + stylesheets: null mainModule: null deferActivation: false @@ -46,9 +47,10 @@ class AtomPackage extends Package @keymaps.push(CSON.readObject(path)) loadStylesheets: -> + @stylesheets = [] stylesheetDirPath = fs.join(@path, 'stylesheets') for stylesheetPath in fs.list(stylesheetDirPath, ['css', 'less']) ? [] - requireStylesheet(stylesheetPath) + @stylesheets.push([stylesheetPath, loadStylesheet(stylesheetPath)]) loadGrammars: -> grammarsDirPath = fs.join(@path, 'grammars') @@ -65,6 +67,7 @@ class AtomPackage extends Package activate: -> keymap.add(map) for map in @keymaps + applyStylesheet(path, content) for [path, content] in @stylesheets if @deferActivation @subscribeToActivationEvents() From d3099cb682819a7e4b5aed70fb9492cb2c844aaa Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 19:15:42 -0600 Subject: [PATCH 05/79] Don't add grammars for atom packages until `activate` is called --- src/app/atom-package.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 1ceeb62f0..f9a7da0be 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -10,6 +10,7 @@ class AtomPackage extends Package metadata: null keymaps: null stylesheets: null + grammars: null mainModule: null deferActivation: false @@ -53,11 +54,10 @@ class AtomPackage extends Package @stylesheets.push([stylesheetPath, loadStylesheet(stylesheetPath)]) loadGrammars: -> + @grammars = [] grammarsDirPath = fs.join(@path, 'grammars') for grammarPath in fs.list(grammarsDirPath, ['.cson', '.json']) ? [] - grammarContent = fs.readObject(grammarPath) - grammar = new TextMateGrammar(grammarContent) - syntax.addGrammar(grammar) + @grammars.push(TextMateGrammar.loadSync(grammarPath)) loadScopedProperties: -> scopedPropertiessDirPath = fs.join(@path, 'scoped-properties') @@ -68,6 +68,7 @@ class AtomPackage extends Package activate: -> keymap.add(map) for map in @keymaps applyStylesheet(path, content) for [path, content] in @stylesheets + syntax.addGrammar(grammar) for grammar in @grammars if @deferActivation @subscribeToActivationEvents() From c51f1d2c526c9fd72eec4e8caa2a51708001b73a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 20:02:22 -0600 Subject: [PATCH 06/79] :lipstick: --- src/app/atom.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index bb6e2250b..2dfe87bf0 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -37,7 +37,6 @@ _.extend atom, try packageStates[pack.name] = pack.mainModule.serialize?() catch e - console?.error("Exception serializing '#{pack.name}' package's module\n", e.stack) else packageStates[pack.name] = @atomPackageStates[pack.name] packageStates From b64f5b2a85c1479ec1c7b9303b9d997423201f49 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 20:07:03 -0600 Subject: [PATCH 07/79] Add `atom.loadPackage(id)`. Rewrite `loadPackages` in terms of it. --- src/app/atom.coffee | 50 ++++++++++++++++++++++---------- src/app/package.coffee | 5 ++++ src/app/text-mate-package.coffee | 2 +- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index 2dfe87bf0..ec42c3f6d 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -37,40 +37,60 @@ _.extend atom, try packageStates[pack.name] = pack.mainModule.serialize?() catch e + console.error("Exception serializing '#{pack.name}' package's module\n", e.stack) else packageStates[pack.name] = @atomPackageStates[pack.name] packageStates loadPackages: -> - textMatePackages = [] - paths = @getPackagePaths().filter (path) -> fs.base(path) isnt 'text.tmbundle' - for path in paths - pack = Package.build(path) + @loadPackage(path) for path in @getPackagePaths() when not @isPackageDisabled(path) + + loadPackage: (id) -> + if @isPackageDisabled(id) + return console.warn("Tried to load disabled packaged '#{id}'") + + if path = @resolvePackagePath(id) + return pack if pack = @getLoadedPackage(id) + pack = Package.load(path) @loadedPackages.push(pack) - pack.load() + pack + else + throw new Error("Could not resolve '#{id}' to a package path") + + resolvePackagePath: _.memoize (id) -> + return id if fs.isDirectory(id) + path = fs.resolve(config.packageDirPaths..., id) + path if fs.isDirectory(path) + + isPackageDisabled: (id) -> + if path = @resolvePackagePath(id) + _.include(config.get('core.disabledPackages') ? [], fs.base(path)) + + getLoadedPackage: (id) -> + if path = @resolvePackagePath(id) + _.detect @loadedPackages, (pack) -> pack.path is path + + isPackageLoaded: (id) -> + @getLoadedPackage(id)? + + isPackageActive: (id) -> + if path = @resolvePackagePath(id) + _.detect @activePackages, (pack) -> pack.path is path activatePackages: -> for pack in @loadedPackages @activePackages.push(pack) pack.activate() - isPackageActive: (pack) -> - _.include(@activePackages, pack) - getLoadedPackages: -> _.clone(@loadedPackages) getPackagePaths: -> - disabledPackages = config.get("core.disabledPackages") ? [] packagePaths = [] for packageDirPath in config.packageDirPaths for packagePath in fs.list(packageDirPath) - continue if not fs.isDirectory(packagePath) - continue if fs.base(packagePath) in disabledPackages - continue if packagePath in packagePaths - packagePaths.push(packagePath) - - packagePaths + packagePaths.push(packagePath) if fs.isDirectory(packagePath) + _.uniq(packagePaths) loadThemes: -> themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax'] diff --git a/src/app/package.coffee b/src/app/package.coffee index 57c4dc8f5..4b4d47894 100644 --- a/src/app/package.coffee +++ b/src/app/package.coffee @@ -11,6 +11,11 @@ class Package else new AtomPackage(path) + @load: (path) -> + pack = @build(path) + pack.load() + pack + name: null path: null diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index 378f176c9..e9519ba74 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -57,7 +57,7 @@ class TextMatePackage extends Package addGrammar: (grammar) -> @grammars.push(grammar) - syntax.addGrammar(grammar) if atom.isPackageActive(this) + syntax.addGrammar(grammar) if atom.isPackageActive(@path) getGrammars: -> @grammars From ae444d1ea366ca9f9ec7c575cafcd8df1c692b36 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 20:11:57 -0600 Subject: [PATCH 08/79] Add `atom.activatePackage(id)` method It will load the specified package if it hasn't already been loaded. --- src/app/atom.coffee | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index ec42c3f6d..7a87061ff 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -78,13 +78,19 @@ _.extend atom, _.detect @activePackages, (pack) -> pack.path is path activatePackages: -> - for pack in @loadedPackages + @activatePackage(pack.path) for pack in @getLoadedPackages() + + activatePackage: (id) -> + if pack = @loadPackage(id) @activePackages.push(pack) pack.activate() getLoadedPackages: -> _.clone(@loadedPackages) + getActivePackages: -> + _.clone(@activePackages) + getPackagePaths: -> packagePaths = [] for packageDirPath in config.packageDirPaths From 6e238967a43fed68fcd06c60c49cb1b00c74526a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 20:16:00 -0600 Subject: [PATCH 09/79] :lipstick: Rearrange methods --- src/app/atom.coffee | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index 7a87061ff..aa3e032a0 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -42,6 +42,21 @@ _.extend atom, packageStates[pack.name] = @atomPackageStates[pack.name] packageStates + activatePackages: -> + @activatePackage(pack.path) for pack in @getLoadedPackages() + + activatePackage: (id) -> + if pack = @loadPackage(id) + @activePackages.push(pack) + pack.activate() + + isPackageActive: (id) -> + if path = @resolvePackagePath(id) + _.detect @activePackages, (pack) -> pack.path is path + + getActivePackages: -> + _.clone(@activePackages) + loadPackages: -> @loadPackage(path) for path in @getPackagePaths() when not @isPackageDisabled(path) @@ -62,10 +77,6 @@ _.extend atom, path = fs.resolve(config.packageDirPaths..., id) path if fs.isDirectory(path) - isPackageDisabled: (id) -> - if path = @resolvePackagePath(id) - _.include(config.get('core.disabledPackages') ? [], fs.base(path)) - getLoadedPackage: (id) -> if path = @resolvePackagePath(id) _.detect @loadedPackages, (pack) -> pack.path is path @@ -73,23 +84,12 @@ _.extend atom, isPackageLoaded: (id) -> @getLoadedPackage(id)? - isPackageActive: (id) -> - if path = @resolvePackagePath(id) - _.detect @activePackages, (pack) -> pack.path is path - - activatePackages: -> - @activatePackage(pack.path) for pack in @getLoadedPackages() - - activatePackage: (id) -> - if pack = @loadPackage(id) - @activePackages.push(pack) - pack.activate() - getLoadedPackages: -> _.clone(@loadedPackages) - getActivePackages: -> - _.clone(@activePackages) + isPackageDisabled: (id) -> + if path = @resolvePackagePath(id) + _.include(config.get('core.disabledPackages') ? [], fs.base(path)) getPackagePaths: -> packagePaths = [] From 054626a9a24b256298460d8134b123848d2378c7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 20:45:33 -0600 Subject: [PATCH 10/79] Add 'immediate' option to atom.activatePackage to suppress deferral --- src/app/atom-package.coffee | 4 ++-- src/app/atom.coffee | 9 +++++---- src/app/package.coffee | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index f9a7da0be..cf241b6c5 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -65,12 +65,12 @@ class AtomPackage extends Package for selector, properties of fs.readObject(scopedPropertiesPath) syntax.addProperties(selector, properties) - activate: -> + activate: ({immediate}={}) -> keymap.add(map) for map in @keymaps applyStylesheet(path, content) for [path, content] in @stylesheets syntax.addGrammar(grammar) for grammar in @grammars - if @deferActivation + if @deferActivation and not immediate @subscribeToActivationEvents() else @activateNow() diff --git a/src/app/atom.coffee b/src/app/atom.coffee index aa3e032a0..8cda340c2 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -45,10 +45,11 @@ _.extend atom, activatePackages: -> @activatePackage(pack.path) for pack in @getLoadedPackages() - activatePackage: (id) -> - if pack = @loadPackage(id) + activatePackage: (id, options) -> + if pack = @loadPackage(id, options) @activePackages.push(pack) - pack.activate() + pack.activate(options) + pack isPackageActive: (id) -> if path = @resolvePackagePath(id) @@ -60,7 +61,7 @@ _.extend atom, loadPackages: -> @loadPackage(path) for path in @getPackagePaths() when not @isPackageDisabled(path) - loadPackage: (id) -> + loadPackage: (id, options) -> if @isPackageDisabled(id) return console.warn("Tried to load disabled packaged '#{id}'") diff --git a/src/app/package.coffee b/src/app/package.coffee index 4b4d47894..c03e082d5 100644 --- a/src/app/package.coffee +++ b/src/app/package.coffee @@ -11,9 +11,9 @@ class Package else new AtomPackage(path) - @load: (path) -> + @load: (path, options) -> pack = @build(path) - pack.load() + pack.load(options) pack name: null From 58ef6c6582f342a38a32af7f0a01f22bb31411a1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Mar 2013 20:46:32 -0600 Subject: [PATCH 11/79] Use `atom.activatePackage` directly in specs --- spec/app/atom-package-spec.coffee | 6 ++--- spec/app/atom-spec.coffee | 26 ++++++++++--------- spec/app/text-mate-grammar-spec.coffee | 2 +- .../spec/autocomplete-spec.coffee | 4 +-- .../autoflow/spec/autoflow-spec.coffee | 2 +- .../spec/bracket-matcher-spec.coffee | 2 +- .../spec/command-logger-spec.coffee | 2 +- .../spec/command-palette-spec.coffee | 2 +- .../spec/command-panel-spec.coffee | 6 ++--- .../spec/preview-list-spec.coffee | 2 +- .../spec/editor-stats-spec.coffee | 2 +- .../spec/fuzzy-finder-spec.coffee | 2 +- src/packages/gfm/spec/gfm-spec.coffee | 2 +- src/packages/gists/spec/gists-spec.coffee | 2 +- .../spec/markdown-preview-spec.coffee | 2 +- .../spec/package-generator-spec.coffee | 2 +- ...__package-name__-view-spec.coffee.template | 2 +- .../snippets/spec/snippets-spec.coffee | 4 +-- .../spell-check/spec/spell-check-spec.coffee | 2 +- .../strip-trailing-whitespace-spec.coffee | 2 +- .../spec/symbols-view-spec.coffee | 2 +- src/packages/tabs/spec/tabs-spec.coffee | 2 +- src/packages/toml/spec/toml-spec.coffee | 2 +- .../tree-view/spec/tree-view-spec.coffee | 14 +++++----- .../wrap-guide/spec/wrap-guide-spec.coffee | 2 +- 25 files changed, 50 insertions(+), 48 deletions(-) diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee index 1f291b896..03da7ca8d 100644 --- a/spec/app/atom-package-spec.coffee +++ b/spec/app/atom-package-spec.coffee @@ -73,14 +73,14 @@ describe "AtomPackage", -> describe "when a package is activated", -> it "loads config defaults based on the `configDefaults` key", -> expect(config.get('package-with-module.numbers.one')).toBeUndefined() - window.loadPackage("package-with-module") + atom.activatePackage("package-with-module") expect(config.get('package-with-module.numbers.one')).toBe 1 expect(config.get('package-with-module.numbers.two')).toBe 2 describe "when the package has a grammars directory", -> it "loads the grammar and correctly parses a keyword", -> spyOn(syntax, 'addGrammar') - window.loadPackage("package-with-a-cson-grammar") + atom.activatePackage("package-with-a-cson-grammar") expect(syntax.addGrammar).toHaveBeenCalled() grammar = syntax.addGrammar.argsForCall[0][0] expect(grammar.scopeName).toBe "source.alot" @@ -90,7 +90,7 @@ describe "AtomPackage", -> describe "when the package has a scoped properties directory", -> it "loads the scoped properties", -> spyOn(syntax, 'addProperties') - window.loadPackage("package-with-scoped-properties") + atom.activatePackage("package-with-scoped-properties") expect(syntax.addProperties).toHaveBeenCalled() [selector, properties] = syntax.addProperties.argsForCall[0] diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 3b765e1f8..b83b47fc4 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -18,13 +18,13 @@ describe "the `atom` global", -> it "requires and activates the package's main module if it exists", -> spyOn(atom, 'activateAtomPackage').andCallThrough() - window.loadPackage("package-with-module") + atom.activatePackage("package-with-module") expect(atom.activateAtomPackage).toHaveBeenCalled() it "logs warning instead of throwing an exception if a package fails to load", -> config.set("core.disabledPackages", []) spyOn(console, "warn") - expect(-> window.loadPackage("package-that-throws-an-exception")).not.toThrow() + expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow() expect(console.warn).toHaveBeenCalled() describe "keymap loading", -> @@ -38,7 +38,7 @@ describe "the `atom` global", -> expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined() expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - window.loadPackage("package-with-module") + atom.activatePackage("package-with-module") expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1" expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2" @@ -51,7 +51,7 @@ describe "the `atom` global", -> expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() - window.loadPackage("package-with-keymaps-manifest") + atom.activatePackage("package-with-keymaps-manifest") expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1' expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2' @@ -60,25 +60,27 @@ describe "the `atom` global", -> it "loads stylesheets associated with the package", -> stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") expect(stylesheetElementForId(stylesheetPath).length).toBe 0 - window.loadPackage("package-with-module") + atom.activatePackage("package-with-module") expect(stylesheetElementForId(stylesheetPath).length).toBe 1 describe "package lifecycle", -> describe "activation", -> it "calls activate on the package main with its previous state", -> - pack = window.loadPackage('package-with-module') + pack = atom.activatePackage('package-with-module') spyOn(pack.mainModule, 'activate') serializedState = rootView.serialize() rootView.deactivate() + + RootView.deserialize(serializedState) - window.loadPackage('package-with-module') + atom.activatePackage('package-with-module') expect(pack.mainModule.activate).toHaveBeenCalledWith(someNumber: 1) describe "deactivation", -> it "deactivates and removes the package module from the package module map", -> - pack = window.loadPackage('package-with-module') + pack = atom.activatePackage('package-with-module') expect(atom.activatedAtomPackages.length).toBe 1 spyOn(pack.mainModule, "deactivate").andCallThrough() atom.deactivateAtomPackages() @@ -88,8 +90,8 @@ describe "the `atom` global", -> describe "serialization", -> it "uses previous serialization state on packages whose activation has been deferred", -> atom.atomPackageStates['package-with-activation-events'] = {previousData: 'exists'} - unactivatedPackage = window.loadPackage('package-with-activation-events') - activatedPackage = window.loadPackage('package-with-module') + unactivatedPackage = atom.activatePackage('package-with-activation-events') + activatedPackage = atom.activatePackage('package-with-module') expect(atom.serializeAtomPackages()).toEqual 'package-with-module': @@ -108,8 +110,8 @@ describe "the `atom` global", -> it "absorbs exceptions that are thrown by the package module's serialize methods", -> spyOn(console, 'error') - window.loadPackage('package-with-module', activateImmediately: true) - window.loadPackage('package-with-serialize-error', activateImmediately: true) + atom.activatePackage('package-with-module', immediate: true) + atom.activatePackage('package-with-serialize-error', immediate: true) packageStates = atom.serializeAtomPackages() expect(packageStates['package-with-module']).toEqual someNumber: 1 diff --git a/spec/app/text-mate-grammar-spec.coffee b/spec/app/text-mate-grammar-spec.coffee index 80d2a8df1..f524e69e5 100644 --- a/spec/app/text-mate-grammar-spec.coffee +++ b/spec/app/text-mate-grammar-spec.coffee @@ -262,7 +262,7 @@ describe "TextMateGrammar", -> describe "when the grammar can infinitely loop over a line", -> it "aborts tokenization", -> spyOn(console, 'error') - window.loadPackage("package-with-infinite-loop-grammar") + atom.activatePackage("package-with-infinite-loop-grammar") grammar = syntax.selectGrammar("something.package-with-infinite-loop-grammar") {tokens} = grammar.tokenizeLine("abc") expect(tokens[0].value).toBe "a" diff --git a/src/packages/autocomplete/spec/autocomplete-spec.coffee b/src/packages/autocomplete/spec/autocomplete-spec.coffee index c210b2173..b525a8fe7 100644 --- a/src/packages/autocomplete/spec/autocomplete-spec.coffee +++ b/src/packages/autocomplete/spec/autocomplete-spec.coffee @@ -14,7 +14,7 @@ describe "Autocomplete", -> describe "@activate()", -> it "activates autocomplete on all existing and future editors (but not on autocomplete's own mini editor)", -> spyOn(AutocompleteView.prototype, 'initialize').andCallThrough() - autocompletePackage = window.loadPackage("autocomplete") + autocompletePackage = atom.activatePackage("autocomplete") expect(AutocompleteView.prototype.initialize).not.toHaveBeenCalled() leftEditor = rootView.getActiveView() @@ -41,7 +41,7 @@ describe "AutocompleteView", -> beforeEach -> window.rootView = new RootView editor = new Editor(editSession: project.buildEditSession('sample.js')) - window.loadPackage('autocomplete') + atom.activatePackage('autocomplete') autocomplete = new AutocompleteView(editor) miniEditor = autocomplete.miniEditor diff --git a/src/packages/autoflow/spec/autoflow-spec.coffee b/src/packages/autoflow/spec/autoflow-spec.coffee index 190ac238c..c497f6292 100644 --- a/src/packages/autoflow/spec/autoflow-spec.coffee +++ b/src/packages/autoflow/spec/autoflow-spec.coffee @@ -6,7 +6,7 @@ describe "Autoflow package", -> beforeEach -> window.rootView = new RootView rootView.open() - window.loadPackage 'autoflow' + atom.activatePackage('autoflow') editor = rootView.getActiveView() config.set('editor.preferredLineLength', 30) diff --git a/src/packages/bracket-matcher/spec/bracket-matcher-spec.coffee b/src/packages/bracket-matcher/spec/bracket-matcher-spec.coffee index 099be0926..9a44ba3a7 100644 --- a/src/packages/bracket-matcher/spec/bracket-matcher-spec.coffee +++ b/src/packages/bracket-matcher/spec/bracket-matcher-spec.coffee @@ -6,7 +6,7 @@ describe "bracket matching", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - window.loadPackage('bracket-matcher') + atom.activatePackage('bracket-matcher') rootView.attachToDom() editor = rootView.getActiveView() editSession = editor.activeEditSession diff --git a/src/packages/command-logger/spec/command-logger-spec.coffee b/src/packages/command-logger/spec/command-logger-spec.coffee index 8feec78bd..96365b469 100644 --- a/src/packages/command-logger/spec/command-logger-spec.coffee +++ b/src/packages/command-logger/spec/command-logger-spec.coffee @@ -7,7 +7,7 @@ describe "CommandLogger", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - commandLogger = window.loadPackage('command-logger').mainModule + commandLogger = atom.activatePackage('command-logger').mainModule commandLogger.eventLog = {} editor = rootView.getActiveView() diff --git a/src/packages/command-palette/spec/command-palette-spec.coffee b/src/packages/command-palette/spec/command-palette-spec.coffee index 414c53996..1cb533864 100644 --- a/src/packages/command-palette/spec/command-palette-spec.coffee +++ b/src/packages/command-palette/spec/command-palette-spec.coffee @@ -9,7 +9,7 @@ describe "CommandPalette", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - window.loadPackage("command-palette") + atom.activatePackage("command-palette") rootView.attachToDom().focus() rootView.trigger 'command-palette:toggle' palette = rootView.find('.command-palette').view() diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee index c6d9f7997..c1cef3080 100644 --- a/src/packages/command-panel/spec/command-panel-spec.coffee +++ b/src/packages/command-panel/spec/command-panel-spec.coffee @@ -11,7 +11,7 @@ describe "CommandPanel", -> rootView.enableKeymap() editSession = rootView.getActivePaneItem() buffer = editSession.buffer - commandPanelMain = window.loadPackage('command-panel', activateImmediately: true).mainModule + commandPanelMain = atom.activatePackage('command-panel', immediate: true).mainModule commandPanel = commandPanelMain.commandPanelView commandPanel.history = [] commandPanel.historyIndex = 0 @@ -32,7 +32,7 @@ describe "CommandPanel", -> rootView.deactivate() window.rootView = RootView.deserialize(rootViewState) rootView.attachToDom() - window.loadPackage('command-panel') + atom.activatePackage('command-panel') expect(rootView.find('.command-panel')).not.toExist() rootView.trigger 'command-panel:toggle' @@ -58,7 +58,7 @@ describe "CommandPanel", -> rootViewState = rootView.serialize() rootView.deactivate() RootView.deserialize(rootViewState).attachToDom() - window.loadPackage('command-panel') + atom.activatePackage('command-panel') rootView.trigger 'command-panel:toggle' commandPanel = rootView.find('.command-panel').view() diff --git a/src/packages/command-panel/spec/preview-list-spec.coffee b/src/packages/command-panel/spec/preview-list-spec.coffee index 4fecb0f2d..ce91de176 100644 --- a/src/packages/command-panel/spec/preview-list-spec.coffee +++ b/src/packages/command-panel/spec/preview-list-spec.coffee @@ -8,7 +8,7 @@ describe "Preview List", -> beforeEach -> window.rootView = new RootView() rootView.attachToDom() - commandPanelMain = window.loadPackage('command-panel', activateImmediately: true).mainModule + commandPanelMain = atom.activatePackage('command-panel', immediate: true).mainModule commandPanelView = commandPanelMain.commandPanelView previewList = commandPanelView.previewList rootView.trigger 'command-panel:toggle' diff --git a/src/packages/editor-stats/spec/editor-stats-spec.coffee b/src/packages/editor-stats/spec/editor-stats-spec.coffee index 9ce2360a2..582f99cfe 100644 --- a/src/packages/editor-stats/spec/editor-stats-spec.coffee +++ b/src/packages/editor-stats/spec/editor-stats-spec.coffee @@ -17,7 +17,7 @@ describe "EditorStats", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - editorStats = window.loadPackage('editor-stats').mainModule.stats + editorStats = atom.activatePackage('editor-stats').mainModule.stats describe "when a keyup event is triggered", -> beforeEach -> diff --git a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee index 92b91d792..5ae7e20e2 100644 --- a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee +++ b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee @@ -13,7 +13,7 @@ describe 'FuzzyFinder', -> window.rootView = new RootView rootView.open('sample.js') rootView.enableKeymap() - finderView = window.loadPackage("fuzzy-finder").mainModule.createView() + finderView = atom.activatePackage("fuzzy-finder").mainModule.createView() describe "file-finder behavior", -> describe "toggling", -> diff --git a/src/packages/gfm/spec/gfm-spec.coffee b/src/packages/gfm/spec/gfm-spec.coffee index 484835ae9..ea579187e 100644 --- a/src/packages/gfm/spec/gfm-spec.coffee +++ b/src/packages/gfm/spec/gfm-spec.coffee @@ -5,7 +5,7 @@ describe "GitHub Flavored Markdown grammar", -> beforeEach -> spyOn(syntax, "addGrammar").andCallThrough() - window.loadPackage("gfm") + atom.activatePackage("gfm") expect(syntax.addGrammar).toHaveBeenCalled() grammar = syntax.addGrammar.argsForCall[0][0] diff --git a/src/packages/gists/spec/gists-spec.coffee b/src/packages/gists/spec/gists-spec.coffee index 3091f8ed6..58866b892 100644 --- a/src/packages/gists/spec/gists-spec.coffee +++ b/src/packages/gists/spec/gists-spec.coffee @@ -7,7 +7,7 @@ describe "Gists package", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - window.loadPackage('gists') + atom.activatePackage('gists') editor = rootView.getActiveView() spyOn($, 'ajax') diff --git a/src/packages/markdown-preview/spec/markdown-preview-spec.coffee b/src/packages/markdown-preview/spec/markdown-preview-spec.coffee index 9a7ed6e33..1bcf984ad 100644 --- a/src/packages/markdown-preview/spec/markdown-preview-spec.coffee +++ b/src/packages/markdown-preview/spec/markdown-preview-spec.coffee @@ -6,7 +6,7 @@ describe "MarkdownPreview package", -> beforeEach -> project.setPath(project.resolve('markdown')) window.rootView = new RootView - window.loadPackage("markdown-preview", activateImmediately: true) + atom.activatePackage("markdown-preview", immediate: true) spyOn(MarkdownPreviewView.prototype, 'fetchRenderedMarkdown') describe "markdown-preview:show", -> diff --git a/src/packages/package-generator/spec/package-generator-spec.coffee b/src/packages/package-generator/spec/package-generator-spec.coffee index 5df9d71c6..87d57bbdd 100644 --- a/src/packages/package-generator/spec/package-generator-spec.coffee +++ b/src/packages/package-generator/spec/package-generator-spec.coffee @@ -7,7 +7,7 @@ describe 'Package Generator', -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - window.loadPackage("package-generator") + atom.activatePackage("package-generator") describe "when package-generator:generate is triggered", -> it "displays a miniEditor", -> diff --git a/src/packages/package-generator/template/spec/__package-name__-view-spec.coffee.template b/src/packages/package-generator/template/spec/__package-name__-view-spec.coffee.template index a8b62caf7..dc342839d 100644 --- a/src/packages/package-generator/template/spec/__package-name__-view-spec.coffee.template +++ b/src/packages/package-generator/template/spec/__package-name__-view-spec.coffee.template @@ -10,7 +10,7 @@ fdescribe "__PackageName__View", -> beforeEach -> window.rootView = new RootView - __packageName__ = window.loadPackage('__packageName__', activateImmediately: true) + __packageName__ = atom.activatePackage('__packageName__', immediate: true) describe "when the __package-name__:toggle event is triggered", -> it "attaches and then detaches the view", -> diff --git a/src/packages/snippets/spec/snippets-spec.coffee b/src/packages/snippets/spec/snippets-spec.coffee index c02a85f74..fad90f109 100644 --- a/src/packages/snippets/spec/snippets-spec.coffee +++ b/src/packages/snippets/spec/snippets-spec.coffee @@ -12,13 +12,13 @@ describe "Snippets extension", -> window.rootView = new RootView rootView.open('sample.js') - packageWithSnippets = window.loadPackage("package-with-snippets") + packageWithSnippets = atom.loadPackage("package-with-snippets") spyOn(atom, "getLoadedPackages").andCallFake -> textMatePackages = window.textMatePackages.filter (pack) -> /package-with-a-cson-grammar|test|textmate-package|javascript/.test(pack.name) textMatePackages.concat([packageWithSnippets]) spyOn(require("snippets/lib/snippets"), 'loadAll') - window.loadPackage("snippets") + atom.activatePackage("snippets") editor = rootView.getActiveView() editSession = rootView.getActivePaneItem() diff --git a/src/packages/spell-check/spec/spell-check-spec.coffee b/src/packages/spell-check/spec/spell-check-spec.coffee index 6ccf41df5..d6eb88995 100644 --- a/src/packages/spell-check/spec/spell-check-spec.coffee +++ b/src/packages/spell-check/spec/spell-check-spec.coffee @@ -7,7 +7,7 @@ describe "Spell check", -> window.rootView = new RootView rootView.open('sample.js') config.set('spell-check.grammars', []) - window.loadPackage('spell-check', activateImmediately: true) + atom.activatePackage('spell-check', immediate: true) syntax.trigger 'grammars-loaded' rootView.attachToDom() editor = rootView.getActiveView() diff --git a/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee b/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee index 9a405ddd2..e41d2d3ab 100644 --- a/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee +++ b/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee @@ -10,7 +10,7 @@ describe "StripTrailingWhitespace", -> window.rootView = new RootView rootView.open(path) - window.loadPackage('strip-trailing-whitespace') + atom.activatePackage('strip-trailing-whitespace') rootView.focus() editor = rootView.getActiveView() diff --git a/src/packages/symbols-view/spec/symbols-view-spec.coffee b/src/packages/symbols-view/spec/symbols-view-spec.coffee index db8876855..7401a4448 100644 --- a/src/packages/symbols-view/spec/symbols-view-spec.coffee +++ b/src/packages/symbols-view/spec/symbols-view-spec.coffee @@ -8,7 +8,7 @@ describe "SymbolsView", -> beforeEach -> window.rootView = new RootView - window.loadPackage("symbols-view") + atom.activatePackage("symbols-view") rootView.attachToDom() setArraySpy = spyOn(SymbolsView.prototype, 'setArray').andCallThrough() diff --git a/src/packages/tabs/spec/tabs-spec.coffee b/src/packages/tabs/spec/tabs-spec.coffee index 0a31a02b0..820f3f9eb 100644 --- a/src/packages/tabs/spec/tabs-spec.coffee +++ b/src/packages/tabs/spec/tabs-spec.coffee @@ -11,7 +11,7 @@ describe "Tabs package main", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - window.loadPackage("tabs") + atom.activatePackage("tabs") describe ".activate()", -> it "appends a tab bar all existing and new panes", -> diff --git a/src/packages/toml/spec/toml-spec.coffee b/src/packages/toml/spec/toml-spec.coffee index c9d07a4f6..656b99673 100644 --- a/src/packages/toml/spec/toml-spec.coffee +++ b/src/packages/toml/spec/toml-spec.coffee @@ -5,7 +5,7 @@ describe "TOML grammar", -> beforeEach -> spyOn(syntax, "addGrammar") - window.loadPackage("toml") + atom.activatePackage("toml") expect(syntax.addGrammar).toHaveBeenCalled() grammar = syntax.addGrammar.argsForCall[0][0] diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee index dc7645ed2..20b7f4410 100644 --- a/src/packages/tree-view/spec/tree-view-spec.coffee +++ b/src/packages/tree-view/spec/tree-view-spec.coffee @@ -13,7 +13,7 @@ describe "TreeView", -> project.setPath(project.resolve('tree-view')) window.rootView = new RootView - window.loadPackage("tree-view") + atom.activatePackage("tree-view") rootView.trigger 'tree-view:toggle' treeView = rootView.find(".tree-view").view() treeView.root = treeView.find('ol > li:first').view() @@ -50,7 +50,7 @@ describe "TreeView", -> rootView.deactivate() window.rootView = new RootView() rootView.open() - treeView = window.loadPackage("tree-view").mainModule.createView() + treeView = atom.activatePackage("tree-view").mainModule.createView() it "does not attach to the root view or create a root node when initialized", -> expect(treeView.hasParent()).toBeFalsy() @@ -76,13 +76,13 @@ describe "TreeView", -> rootView.deactivate() window.rootView = new RootView rootView.open('tree-view.js') - treeView = window.loadPackage("tree-view").mainModule.createView() + treeView = atom.activatePackage("tree-view").mainModule.createView() expect(treeView.hasParent()).toBeFalsy() expect(treeView.root).toExist() describe "when the root view is opened to a directory", -> it "attaches to the root view", -> - treeView = window.loadPackage("tree-view").mainModule.createView() + treeView = atom.activatePackage("tree-view").mainModule.createView() expect(treeView.hasParent()).toBeTruthy() expect(treeView.root).toExist() @@ -94,7 +94,7 @@ describe "TreeView", -> rootViewState = rootView.serialize() rootView.deactivate() window.rootView = RootView.deserialize(rootViewState) - window.loadPackage("tree-view") + atom.activatePackage("tree-view") treeView = rootView.find(".tree-view").view() expect(treeView).toExist() @@ -111,7 +111,7 @@ describe "TreeView", -> window.rootView = RootView.deserialize(rootViewState) rootView.attachToDom() - window.loadPackage("tree-view") + atom.activatePackage("tree-view") treeView = rootView.find(".tree-view").view() expect(treeView.find(".tree-view")).toMatchSelector ':focus' @@ -612,7 +612,7 @@ describe "TreeView", -> project.setPath(rootDirPath) window.rootView = new RootView(rootDirPath) - window.loadPackage('tree-view') + atom.activatePackage('tree-view') rootView.trigger 'tree-view:toggle' treeView = rootView.find(".tree-view").view() dirView = treeView.root.entries.find('.directory:contains(test-dir)').view() diff --git a/src/packages/wrap-guide/spec/wrap-guide-spec.coffee b/src/packages/wrap-guide/spec/wrap-guide-spec.coffee index ff14f7c27..cd0761881 100644 --- a/src/packages/wrap-guide/spec/wrap-guide-spec.coffee +++ b/src/packages/wrap-guide/spec/wrap-guide-spec.coffee @@ -6,7 +6,7 @@ describe "WrapGuide", -> beforeEach -> window.rootView = new RootView rootView.open('sample.js') - window.loadPackage('wrap-guide') + atom.activatePackage('wrap-guide') rootView.attachToDom() editor = rootView.getActiveView() wrapGuide = rootView.find('.wrap-guide').view() From 4510d31301e3217c12abb56088cd47228ffbab4b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 25 Mar 2013 09:41:03 -0600 Subject: [PATCH 12/79] Pass options through when loading packages --- src/app/atom.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index 8cda340c2..54d3b5991 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -67,7 +67,7 @@ _.extend atom, if path = @resolvePackagePath(id) return pack if pack = @getLoadedPackage(id) - pack = Package.load(path) + pack = Package.load(path, options) @loadedPackages.push(pack) pack else From e3ddc3f29b4947a1dd88e8709f7bc667da8d6a1c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 25 Mar 2013 09:41:23 -0600 Subject: [PATCH 13/79] Kill `window.loadPackage` spec helper. We use built-in methods now. --- spec/spec-helper.coffee | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index b90303d82..ce33c0121 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -92,23 +92,13 @@ afterEach -> syntax.off() waits(0) # yield to ui thread to make screen update more frequently -window.loadPackage = (name, options={}) -> - Package = require 'package' - packagePath = _.find atom.getPackagePaths(), (packagePath) -> fs.base(packagePath) == name - if pack = Package.build(packagePath) - pack.load(options) - atom.loadedPackages.push(pack) - pack.deferActivation = false if options.activateImmediately - pack.activate() - pack - # Specs rely on TextMate bundles (but not atom packages) window.loadTextMatePackages = -> TextMatePackage = require 'text-mate-package' config.packageDirPaths.unshift(fixturePackagesPath) window.textMatePackages = [] for path in atom.getPackagePaths() when TextMatePackage.testName(path) - window.textMatePackages.push window.loadPackage(fs.base(path), sync: true) + window.textMatePackages.push atom.activatePackage(path, sync: true) window.loadTextMatePackages() From f5774972e999b54e25a5dde6a439cfe42dc97b4f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 25 Mar 2013 10:57:58 -0600 Subject: [PATCH 14/79] Add `atom.deactivatePackage(id)` It serializes the package state to the atom.packageStates hash when the package is deactivated, which means we will be able to test package serialization independent of the overall window lifecycle by just deactivating and re-activating the package. --- spec/app/atom-spec.coffee | 150 ++++++++---------- .../packages/package-with-module/index.coffee | 4 +- spec/spec-helper.coffee | 2 +- src/app/atom-package.coffee | 24 ++- src/app/atom.coffee | 41 ++--- src/app/root-view.coffee | 4 +- src/app/text-mate-package.coffee | 3 + .../tree-view/spec/tree-view-spec.coffee | 1 + 8 files changed, 119 insertions(+), 110 deletions(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index b83b47fc4..eec7d718c 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -6,116 +6,100 @@ describe "the `atom` global", -> beforeEach -> window.rootView = new RootView - describe "when a package is built and loaded", -> - [extension, stylesheetPath] = [] + describe "package lifecycle methods", -> + packageModule = null beforeEach -> - extension = require "package-with-module" - stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") + packageModule = require "package-with-module" afterEach -> - removeStylesheet(stylesheetPath) + atom.deactivatePackages() - it "requires and activates the package's main module if it exists", -> - spyOn(atom, 'activateAtomPackage').andCallThrough() - atom.activatePackage("package-with-module") - expect(atom.activateAtomPackage).toHaveBeenCalled() + describe ".activatePackage(id)", -> + stylesheetPath = null - it "logs warning instead of throwing an exception if a package fails to load", -> - config.set("core.disabledPackages", []) - spyOn(console, "warn") - expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow() - expect(console.warn).toHaveBeenCalled() + beforeEach -> + stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") - describe "keymap loading", -> - describe "when package.json does not contain a 'keymaps' manifest", -> - it "loads all the .cson/.json files in the keymaps directory", -> - element1 = $$ -> @div class: 'test-1' - element2 = $$ -> @div class: 'test-2' - element3 = $$ -> @div class: 'test-3' + afterEach -> + removeStylesheet(stylesheetPath) - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() - expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined() - expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() + it "requires and activates the package's main module if it exists", -> + spyOn(packageModule, 'activate').andCallThrough() + atom.activatePackage("package-with-module") + expect(packageModule.activate).toHaveBeenCalledWith({}) - atom.activatePackage("package-with-module") + it "passes the package its previously serialized state if it exists", -> + pack = atom.activatePackage("package-with-module") + expect(pack.mainModule.someNumber).not.toBe 77 + pack.mainModule.someNumber = 77 + atom.deactivatePackage("package-with-module") - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1" - expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2" - expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() + pack.requireMainModule() # deactivating the package nukes its main module, so we require it again to spy on it + spyOn(pack.mainModule, 'activate').andCallThrough() - describe "when package.json contains a 'keymaps' manifest", -> - it "loads only the keymaps specified by the manifest, in the specified order", -> - element1 = $$ -> @div class: 'test-1' - element3 = $$ -> @div class: 'test-3' + atom.activatePackage("package-with-module") + expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77}) - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() + it "logs warning instead of throwing an exception if a package fails to load", -> + config.set("core.disabledPackages", []) + spyOn(console, "warn") + expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow() + expect(console.warn).toHaveBeenCalled() - atom.activatePackage("package-with-keymaps-manifest") + describe "keymap loading", -> + describe "when package.json does not contain a 'keymaps' manifest", -> + it "loads all the .cson/.json files in the keymaps directory", -> + element1 = $$ -> @div class: 'test-1' + element2 = $$ -> @div class: 'test-2' + element3 = $$ -> @div class: 'test-3' - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1' - expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2' - expect(keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined() + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - it "loads stylesheets associated with the package", -> - stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") - expect(stylesheetElementForId(stylesheetPath).length).toBe 0 - atom.activatePackage("package-with-module") - expect(stylesheetElementForId(stylesheetPath).length).toBe 1 + atom.activatePackage("package-with-module") - describe "package lifecycle", -> - describe "activation", -> - it "calls activate on the package main with its previous state", -> - pack = atom.activatePackage('package-with-module') - spyOn(pack.mainModule, 'activate') + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1" + expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2" + expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - serializedState = rootView.serialize() - rootView.deactivate() + describe "when package.json contains a 'keymaps' manifest", -> + it "loads only the keymaps specified by the manifest, in the specified order", -> + element1 = $$ -> @div class: 'test-1' + element3 = $$ -> @div class: 'test-3' + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() - RootView.deserialize(serializedState) - atom.activatePackage('package-with-module') + atom.activatePackage("package-with-keymaps-manifest") - expect(pack.mainModule.activate).toHaveBeenCalledWith(someNumber: 1) + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1' + expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2' + expect(keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined() - describe "deactivation", -> - it "deactivates and removes the package module from the package module map", -> - pack = atom.activatePackage('package-with-module') - expect(atom.activatedAtomPackages.length).toBe 1 - spyOn(pack.mainModule, "deactivate").andCallThrough() - atom.deactivateAtomPackages() + it "loads stylesheets associated with the package", -> + stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") + expect(stylesheetElementForId(stylesheetPath).length).toBe 0 + atom.activatePackage("package-with-module") + expect(stylesheetElementForId(stylesheetPath).length).toBe 1 + + describe ".deactivatePackage(id)", -> + it "calls `deactivate` on the package's main module and deletes the package's module reference and require cache entry", -> + pack = atom.activatePackage("package-with-module") + expect(atom.getActivePackage("package-with-module")).toBe pack + spyOn(pack.mainModule, 'deactivate').andCallThrough() + + atom.deactivatePackage("package-with-module") expect(pack.mainModule.deactivate).toHaveBeenCalled() - expect(atom.activatedAtomPackages.length).toBe 0 - - describe "serialization", -> - it "uses previous serialization state on packages whose activation has been deferred", -> - atom.atomPackageStates['package-with-activation-events'] = {previousData: 'exists'} - unactivatedPackage = atom.activatePackage('package-with-activation-events') - activatedPackage = atom.activatePackage('package-with-module') - - expect(atom.serializeAtomPackages()).toEqual - 'package-with-module': - 'someNumber': 1 - 'package-with-activation-events': - 'previousData': 'exists' - - # ensure serialization occurs when the packageis activated - unactivatedPackage.deferActivation = false - unactivatedPackage.activate() - expect(atom.serializeAtomPackages()).toEqual - 'package-with-module': - 'someNumber': 1 - 'package-with-activation-events': - 'previousData': 'overwritten' + expect(atom.getActivePackage("package-with-module")).toBeUndefined() it "absorbs exceptions that are thrown by the package module's serialize methods", -> spyOn(console, 'error') atom.activatePackage('package-with-module', immediate: true) atom.activatePackage('package-with-serialize-error', immediate: true) - - packageStates = atom.serializeAtomPackages() - expect(packageStates['package-with-module']).toEqual someNumber: 1 - expect(packageStates['package-with-serialize-error']).toBeUndefined() + atom.deactivatePackages() + expect(atom.packageStates['package-with-module']).toEqual someNumber: 1 + expect(atom.packageStates['package-with-serialize-error']).toBeUndefined() expect(console.error).toHaveBeenCalled() describe ".getVersion(callback)", -> diff --git a/spec/fixtures/packages/package-with-module/index.coffee b/spec/fixtures/packages/package-with-module/index.coffee index 84d5c12a1..3872da074 100644 --- a/spec/fixtures/packages/package-with-module/index.coffee +++ b/spec/fixtures/packages/package-with-module/index.coffee @@ -4,8 +4,8 @@ module.exports = someNumber: 0 - activate: -> - @someNumber = 1 + activate: ({@someNumber}) -> + @someNumber ?= 1 deactivate: -> diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index ce33c0121..00afecf1a 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -36,7 +36,7 @@ beforeEach -> window.git = Git.open(window.project.getPath()) window.resetTimeouts() - atom.atomPackageStates = {} + atom.packageStates = {} atom.loadedPackages = [] spyOn(atom, 'saveWindowState') spyOn(atom, 'getSavedWindowState').andReturn(null) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index cf241b6c5..61c9c3879 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -11,6 +11,8 @@ class AtomPackage extends Package keymaps: null stylesheets: null grammars: null + mainModulePath: null + resolvedMainModulePath: false mainModule: null deferActivation: false @@ -79,19 +81,33 @@ class AtomPackage extends Package try if @requireMainModule() config.setDefaults(@name, @mainModule.configDefaults) - atom.activateAtomPackage(this) + @mainModule.activate(atom.getPackageState(@name) ? {}) catch e console.warn "Failed to activate package named '#{@name}'", e.stack + serialize: -> + try + @mainModule?.serialize?() + catch e + console.error "Error serializing package '#{@name}'", e.stack + + deactivate: -> + @mainModule?.deactivate?() + requireMainModule: -> return @mainModule if @mainModule - mainPath = + mainModulePath = @getMainModulePath() + @mainModule = require(mainModulePath) if fs.isFile(mainModulePath) + + getMainModulePath: -> + return @mainModulePath if @resolvedMainModulePath + @resolvedMainModulePath = true + mainModulePath = if @metadata.main fs.join(@path, @metadata.main) else fs.join(@path, 'index') - mainPath = fs.resolveExtension(mainPath, ["", _.keys(require.extensions)...]) - @mainModule = require(mainPath) if fs.isFile(mainPath) + @mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...]) registerDeferredDeserializers: -> for deserializerName in @metadata.deferredDeserializers ? [] diff --git a/src/app/atom.coffee b/src/app/atom.coffee index 54d3b5991..809210d93 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -14,33 +14,23 @@ _.extend atom, pendingBrowserProcessCallbacks: {} loadedPackages: [] activePackages: [] - activatedAtomPackages: [] - atomPackageStates: {} + packageStates: {} presentingModal: false pendingModals: [[]] getPathToOpen: -> @getWindowState('pathToOpen') ? window.location.params.pathToOpen - activateAtomPackage: (pack) -> - @activatedAtomPackages.push(pack) - pack.mainModule.activate(@atomPackageStates[pack.name] ? {}) + getPackageState: (name) -> + @packageStates[name] - deactivateAtomPackages: -> - pack.mainModule.deactivate?() for pack in @activatedAtomPackages - @activatedAtomPackages = [] + setPackageState: (name, state) -> + @packageStates[name] = state serializeAtomPackages: -> - packageStates = {} - for pack in @loadedPackages - if pack in @activatedAtomPackages - try - packageStates[pack.name] = pack.mainModule.serialize?() - catch e - console.error("Exception serializing '#{pack.name}' package's module\n", e.stack) - else - packageStates[pack.name] = @atomPackageStates[pack.name] - packageStates + for pack in @getActivePackages() + @setPackageState(pack.name, state) if state = pack.serialize?() + @packageStates activatePackages: -> @activatePackage(pack.path) for pack in @getLoadedPackages() @@ -51,6 +41,21 @@ _.extend atom, pack.activate(options) pack + deactivatePackages: -> + @deactivatePackage(pack.path) for pack in @getActivePackages() + + deactivatePackage: (id) -> + if pack = @getActivePackage(id) + @setPackageState(pack.name, state) if state = pack.serialize?() + pack.deactivate() + _.remove(@activePackages, pack) + else + throw new Error("No active package for id '#{id}'") + + getActivePackage: (id) -> + if path = @resolvePackagePath(id) + _.detect @activePackages, (pack) -> pack.path is path + isPackageActive: (id) -> if path = @resolvePackagePath(id) _.detect @activePackages, (pack) -> pack.path is path diff --git a/src/app/root-view.coffee b/src/app/root-view.coffee index 5a9f35a3f..aa1f38dac 100644 --- a/src/app/root-view.coffee +++ b/src/app/root-view.coffee @@ -30,7 +30,7 @@ class RootView extends View @subview 'panes', panes ? new PaneContainer @deserialize: ({ panes, packages, projectPath }) -> - atom.atomPackageStates = packages ? {} + atom.packageStates = packages ? {} panes = deserialize(panes) if panes?.deserializer is 'PaneContainer' new RootView({panes}) @@ -95,7 +95,7 @@ class RootView extends View @focus() if onDom deactivate: -> - atom.deactivateAtomPackages() + atom.deactivatePackages() @remove() open: (path, options = {}) -> diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index e9519ba74..36b09cf03 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -36,6 +36,9 @@ class TextMatePackage extends Package for { selector, properties } in @scopedProperties syntax.addProperties(selector, properties) + deactivate: -> + # we should remove grammars and unregister properties, snippets, etc + legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage', 'cson', 'json'] loadGrammars: (done) -> diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee index 20b7f4410..5d0cfe31d 100644 --- a/src/packages/tree-view/spec/tree-view-spec.coffee +++ b/src/packages/tree-view/spec/tree-view-spec.coffee @@ -76,6 +76,7 @@ describe "TreeView", -> rootView.deactivate() window.rootView = new RootView rootView.open('tree-view.js') + atom.packageStates = {} treeView = atom.activatePackage("tree-view").mainModule.createView() expect(treeView.hasParent()).toBeFalsy() expect(treeView.root).toExist() From bb8b3782b9ea218641f3ed4b1769f621278a5307 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 25 Mar 2013 15:37:11 -0600 Subject: [PATCH 15/79] Serialize package states independently of RootView Previously, package specs needed to deactivate the root view to test their package serialization. Now, specs can just deactivate and then reactivate the package, relying on serialization infrastructure that's independent of the lifecycle of the RootView. --- spec/app/root-view-spec.coffee | 6 ++--- spec/spec-helper.coffee | 3 ++- src/app/atom.coffee | 5 ---- src/app/root-view.coffee | 8 +----- src/app/window.coffee | 7 ++++-- .../lib/command-panel-view.coffee | 3 +++ .../spec/command-panel-spec.coffee | 12 +++------ .../spec/fuzzy-finder-spec.coffee | 4 +-- .../lib/markdown-preview.coffee | 2 +- .../status-bar/spec/status-bar-spec.coffee | 2 +- src/packages/tree-view/lib/tree-view.coffee | 7 ++++-- .../tree-view/spec/tree-view-spec.coffee | 25 ++++++------------- 12 files changed, 35 insertions(+), 49 deletions(-) diff --git a/spec/app/root-view-spec.coffee b/spec/app/root-view-spec.coffee index b1f28e9b5..4935dbd1b 100644 --- a/spec/app/root-view-spec.coffee +++ b/spec/app/root-view-spec.coffee @@ -29,7 +29,7 @@ describe "RootView", -> buffer = editor1.getBuffer() editor1.splitRight() viewState = rootView.serialize() - rootView.deactivate() + rootView.remove() window.rootView = deserialize(viewState) rootView.attachToDom() @@ -54,7 +54,7 @@ describe "RootView", -> pane2.focus() viewState = rootView.serialize() - rootView.deactivate() + rootView.remove() window.rootView = deserialize(viewState) rootView.attachToDom() @@ -91,7 +91,7 @@ describe "RootView", -> expect(rootView.getEditors().length).toBe 0 viewState = rootView.serialize() - rootView.deactivate() + rootView.remove() window.rootView = deserialize(viewState) rootView.attachToDom() diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 00afecf1a..b433c4570 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -76,8 +76,9 @@ beforeEach -> afterEach -> keymap.bindingSets = bindingSetsToRestore keymap.bindingSetsByFirstKeystrokeToRestore = bindingSetsByFirstKeystrokeToRestore + atom.deactivatePackages() if rootView? - rootView.deactivate?() + rootView.remove?() window.rootView = null if project? project.destroy() diff --git a/src/app/atom.coffee b/src/app/atom.coffee index 809210d93..70c05a952 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -27,11 +27,6 @@ _.extend atom, setPackageState: (name, state) -> @packageStates[name] = state - serializeAtomPackages: -> - for pack in @getActivePackages() - @setPackageState(pack.name, state) if state = pack.serialize?() - @packageStates - activatePackages: -> @activatePackage(pack.path) for pack in @getLoadedPackages() diff --git a/src/app/root-view.coffee b/src/app/root-view.coffee index aa1f38dac..2c299c92c 100644 --- a/src/app/root-view.coffee +++ b/src/app/root-view.coffee @@ -29,8 +29,7 @@ class RootView extends View @div id: 'vertical', outlet: 'vertical', => @subview 'panes', panes ? new PaneContainer - @deserialize: ({ panes, packages, projectPath }) -> - atom.packageStates = packages ? {} + @deserialize: ({ panes }) -> panes = deserialize(panes) if panes?.deserializer is 'PaneContainer' new RootView({panes}) @@ -73,7 +72,6 @@ class RootView extends View version: RootView.version deserializer: 'RootView' panes: @panes.serialize() - packages: atom.serializeAtomPackages() confirmClose: -> @panes.confirmClose() @@ -94,10 +92,6 @@ class RootView extends View afterAttach: (onDom) -> @focus() if onDom - deactivate: -> - atom.deactivatePackages() - @remove() - open: (path, options = {}) -> changeFocus = options.changeFocus ? true path = project.resolve(path) if path? diff --git a/src/app/window.coffee b/src/app/window.coffee index a2056a672..8ef579f0e 100644 --- a/src/app/window.coffee +++ b/src/app/window.coffee @@ -61,10 +61,12 @@ window.shutdown = -> return if not project and not rootView atom.setWindowState('pathToOpen', project.getPath()) atom.setWindowState('project', project.serialize()) - atom.setWindowState('rootView', rootView.serialize()) atom.setWindowState('syntax', syntax.serialize()) + atom.setWindowState('rootView', rootView.serialize()) + atom.deactivatePackages() + atom.setWindowState('packageStates', atom.packageStates) + rootView.remove() atom.saveWindowState() - rootView.deactivate() project.destroy() git?.destroy() $(window).off('focus blur before') @@ -95,6 +97,7 @@ window.deserializeWindowState = -> windowState = atom.getWindowState() + atom.packageStates = windowState.packageStates ? {} window.project = deserialize(windowState.project) ? new Project(pathToOpen) window.rootView = deserialize(windowState.rootView) ? new RootView diff --git a/src/packages/command-panel/lib/command-panel-view.coffee b/src/packages/command-panel/lib/command-panel-view.coffee index ff574caa6..98004f35b 100644 --- a/src/packages/command-panel/lib/command-panel-view.coffee +++ b/src/packages/command-panel/lib/command-panel-view.coffee @@ -65,6 +65,9 @@ class CommandPanelView extends View destroy: -> @previewList.destroy() + rootView.off "command-panel:toggle-preview command-panel:find-in-file command-panel:find-in-project \ + command-panel:repeat-relative-address command-panel:repeat-relative-address-in-reverse command-panel:set-selection-as-regex-address" + @remove() toggle: -> if @miniEditor.isFocused diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee index c1cef3080..6cfb03bb0 100644 --- a/src/packages/command-panel/spec/command-panel-spec.coffee +++ b/src/packages/command-panel/spec/command-panel-spec.coffee @@ -28,10 +28,7 @@ describe "CommandPanel", -> rootView.trigger 'command-panel:toggle' expect(commandPanel.miniEditor.isFocused).toBeTruthy() - rootViewState = rootView.serialize() - rootView.deactivate() - window.rootView = RootView.deserialize(rootViewState) - rootView.attachToDom() + atom.deactivatePackage('command-panel') atom.activatePackage('command-panel') expect(rootView.find('.command-panel')).not.toExist() @@ -55,13 +52,12 @@ describe "CommandPanel", -> expect(commandPanel.history[2]).toBe('/test3') expect(commandPanel.historyIndex).toBe(3) - rootViewState = rootView.serialize() - rootView.deactivate() - RootView.deserialize(rootViewState).attachToDom() + atom.deactivatePackage('command-panel') atom.activatePackage('command-panel') - rootView.trigger 'command-panel:toggle' + rootView.trigger 'command-panel:toggle' commandPanel = rootView.find('.command-panel').view() + expect(commandPanel.history.length).toBe(2) expect(commandPanel.history[0]).toBe('/test2') expect(commandPanel.history[1]).toBe('/test3') diff --git a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee index 5ae7e20e2..904856ed4 100644 --- a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee +++ b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee @@ -143,8 +143,8 @@ describe 'FuzzyFinder', -> rootView.trigger 'fuzzy-finder:toggle-buffer-finder' rootView.open() - states = rootView.serialize().packages - states = _.map states['fuzzy-finder'], (path, time) -> [ path, time ] + atom.deactivatePackage('fuzzy-finder') + states = _.map atom.getPackageState('fuzzy-finder'), (path, time) -> [ path, time ] states = _.sortBy states, (path, time) -> -time paths = [ 'sample-with-tabs.coffee', 'sample.txt', 'sample.js' ] diff --git a/src/packages/markdown-preview/lib/markdown-preview.coffee b/src/packages/markdown-preview/lib/markdown-preview.coffee index b30bbb621..457984f1e 100644 --- a/src/packages/markdown-preview/lib/markdown-preview.coffee +++ b/src/packages/markdown-preview/lib/markdown-preview.coffee @@ -22,4 +22,4 @@ module.exports = nextPane.showItem(new MarkdownPreviewView(editSession.buffer)) else activePane.splitRight(new MarkdownPreviewView(editSession.buffer)) - activePane.focus() \ No newline at end of file + activePane.focus() diff --git a/src/packages/status-bar/spec/status-bar-spec.coffee b/src/packages/status-bar/spec/status-bar-spec.coffee index 2e03eec13..dd067dbf2 100644 --- a/src/packages/status-bar/spec/status-bar-spec.coffee +++ b/src/packages/status-bar/spec/status-bar-spec.coffee @@ -32,7 +32,7 @@ describe "StatusBar", -> describe "when associated with an unsaved buffer", -> it "displays 'untitled' instead of the buffer's path, but still displays the buffer position", -> - rootView.deactivate() + rootView.remove() window.rootView = new RootView rootView.open() rootView.simulateDomAttachment() diff --git a/src/packages/tree-view/lib/tree-view.coffee b/src/packages/tree-view/lib/tree-view.coffee index e6421679f..18475fa06 100644 --- a/src/packages/tree-view/lib/tree-view.coffee +++ b/src/packages/tree-view/lib/tree-view.coffee @@ -40,8 +40,8 @@ class TreeView extends ScrollView else @selectActiveFile() - rootView.on 'pane:active-item-changed pane:became-active', => @selectActiveFile() - project.on 'path-changed', => @updateRoot() + rootView.on 'pane:active-item-changed.tree-view pane:became-active.tree-view', => @selectActiveFile() + project.on 'path-changed.tree-view', => @updateRoot() @observeConfig 'core.hideGitIgnoredFiles', => @updateRoot() if @root @@ -67,6 +67,9 @@ class TreeView extends ScrollView deactivate: -> @root?.unwatchEntries() + rootView.off('.tree-view') + project.off('.tree-view') + @remove() toggle: -> if @hasFocus() diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee index 5d0cfe31d..f5f01aace 100644 --- a/src/packages/tree-view/spec/tree-view-spec.coffee +++ b/src/packages/tree-view/spec/tree-view-spec.coffee @@ -47,9 +47,7 @@ describe "TreeView", -> describe "when the project has no path", -> beforeEach -> project.setPath(undefined) - rootView.deactivate() - window.rootView = new RootView() - rootView.open() + atom.deactivatePackage("tree-view") treeView = atom.activatePackage("tree-view").mainModule.createView() it "does not attach to the root view or create a root node when initialized", -> @@ -66,6 +64,7 @@ describe "TreeView", -> describe "when the project is assigned a path because a new buffer is saved", -> it "creates a root directory view but does not attach to the root view", -> + rootView.open() rootView.getActivePaneItem().saveAs("/tmp/test.txt") expect(treeView.hasParent()).toBeFalsy() expect(treeView.root.getPath()).toBe '/tmp' @@ -73,10 +72,9 @@ describe "TreeView", -> describe "when the root view is opened to a file path", -> it "does not attach to the root view but does create a root node when initialized", -> - rootView.deactivate() - window.rootView = new RootView - rootView.open('tree-view.js') + atom.deactivatePackage("tree-view") atom.packageStates = {} + rootView.open('tree-view.js') treeView = atom.activatePackage("tree-view").mainModule.createView() expect(treeView.hasParent()).toBeFalsy() expect(treeView.root).toExist() @@ -92,9 +90,7 @@ describe "TreeView", -> treeView.find('.directory:contains(dir1)').click() sampleJs.click() - rootViewState = rootView.serialize() - rootView.deactivate() - window.rootView = RootView.deserialize(rootViewState) + atom.deactivatePackage("tree-view") atom.activatePackage("tree-view") treeView = rootView.find(".tree-view").view() @@ -106,12 +102,7 @@ describe "TreeView", -> rootView.attachToDom() treeView.focus() expect(treeView.find(".tree-view")).toMatchSelector ':focus' - - rootViewState = rootView.serialize() - rootView.deactivate() - window.rootView = RootView.deserialize(rootViewState) - - rootView.attachToDom() + atom.deactivatePackage("tree-view") atom.activatePackage("tree-view") treeView = rootView.find(".tree-view").view() expect(treeView.find(".tree-view")).toMatchSelector ':focus' @@ -600,7 +591,7 @@ describe "TreeView", -> [dirView, fileView, rootDirPath, dirPath, filePath] = [] beforeEach -> - rootView.deactivate() + atom.deactivatePackage('tree-view') rootDirPath = fs.join(fs.absolute("/tmp"), "atom-tests") fs.remove(rootDirPath) if fs.exists(rootDirPath) @@ -612,7 +603,7 @@ describe "TreeView", -> fs.write(filePath, "doesn't matter") project.setPath(rootDirPath) - window.rootView = new RootView(rootDirPath) + atom.activatePackage('tree-view') rootView.trigger 'tree-view:toggle' treeView = rootView.find(".tree-view").view() From a41e3c1ebbac7879f0b43c10948c06a0575ed30a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 25 Mar 2013 15:47:10 -0600 Subject: [PATCH 16/79] Don't clear loaded packages between specs --- spec/spec-helper.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index b433c4570..d66fea65e 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -37,7 +37,6 @@ beforeEach -> window.resetTimeouts() atom.packageStates = {} - atom.loadedPackages = [] spyOn(atom, 'saveWindowState') spyOn(atom, 'getSavedWindowState').andReturn(null) $native.setWindowState('') From 8340a084d3d71775e12f5c7191d89bef2a732118 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Mon, 25 Mar 2013 16:28:34 -0600 Subject: [PATCH 17/79] Kill vestiges of CSON from TextMatePackage --- src/app/text-mate-package.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index 36b09cf03..62114e52a 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -4,7 +4,6 @@ fsUtils = require 'fs-utils' plist = require 'plist' _ = require 'underscore' TextMateGrammar = require 'text-mate-grammar' -CSON = require 'cson' async = require 'async' module.exports = @@ -39,7 +38,7 @@ class TextMatePackage extends Package deactivate: -> # we should remove grammars and unregister properties, snippets, etc - legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage', 'cson', 'json'] + legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage'] loadGrammars: (done) -> fsUtils.isDirectoryAsync @syntaxesPath, (isDirectory) => From 8437f3ff7fd110b829aea401d37f8918521d37de Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Mon, 25 Mar 2013 17:31:01 -0600 Subject: [PATCH 18/79] Only load TextMate packages as needed in specs Also: when a TextMate package is deactivated, remove its grammars --- spec/app/display-buffer-spec.coffee | 1 + spec/app/edit-session-spec.coffee | 6 ++++-- spec/app/editor-spec.coffee | 2 ++ spec/app/grammar-view-spec.coffee | 2 ++ spec/app/language-mode-spec.coffee | 5 ++++- spec/app/syntax-spec.coffee | 16 ++++++++++++++++ spec/app/text-mate-grammar-spec.coffee | 11 +++++++++++ spec/app/tokenized-buffer-spec.coffee | 6 ++++++ spec/spec-helper.coffee | 11 +---------- src/app/syntax.coffee | 13 ++++++++++--- src/app/text-mate-package.coffee | 3 ++- src/packages/snippets/spec/snippets-spec.coffee | 7 ++++--- .../spell-check/spec/spell-check-spec.coffee | 2 ++ .../status-bar/spec/status-bar-spec.coffee | 5 +++++ 14 files changed, 70 insertions(+), 20 deletions(-) diff --git a/spec/app/display-buffer-spec.coffee b/spec/app/display-buffer-spec.coffee index a46f2f63d..8227a94e2 100644 --- a/spec/app/display-buffer-spec.coffee +++ b/spec/app/display-buffer-spec.coffee @@ -6,6 +6,7 @@ describe "DisplayBuffer", -> [editSession, displayBuffer, buffer, changeHandler, tabLength] = [] beforeEach -> tabLength = 2 + atom.activatePackage('javascript.tmbundle', sync: true) editSession = project.buildEditSession('sample.js', { tabLength }) { buffer, displayBuffer } = editSession changeHandler = jasmine.createSpy 'changeHandler' diff --git a/spec/app/edit-session-spec.coffee b/spec/app/edit-session-spec.coffee index 7afe8d888..c6870c7f7 100644 --- a/spec/app/edit-session-spec.coffee +++ b/spec/app/edit-session-spec.coffee @@ -9,6 +9,7 @@ describe "EditSession", -> buffer.setText(buffer.getText().replace(/[ ]{2}/g, "\t")) beforeEach -> + atom.activatePackage('javascript.tmbundle', sync: true) editSession = project.buildEditSession('sample.js', autoIndent: false) buffer = editSession.buffer lineLengths = buffer.getLines().map (line) -> line.length @@ -2048,13 +2049,14 @@ describe "EditSession", -> describe "when the 'grammars-loaded' event is triggered on the syntax global", -> it "reloads the edit session's grammar and re-tokenizes the buffer if it changes", -> editSession.destroy() - grammarToReturn = syntax.grammarByPath('a.txt') + jsGrammar = syntax.selectGrammar('a.js') + grammarToReturn = syntax.nullGrammar spyOn(syntax, 'selectGrammar').andCallFake -> grammarToReturn editSession = project.buildEditSession('sample.js', autoIndent: false) expect(editSession.lineForScreenRow(0).tokens.length).toBe 1 - grammarToReturn = syntax.grammarByPath('a.js') + grammarToReturn = jsGrammar syntax.trigger 'grammars-loaded' expect(editSession.lineForScreenRow(0).tokens.length).toBeGreaterThan 1 diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index a642e3559..ee150eca5 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -12,6 +12,8 @@ describe "Editor", -> [buffer, editor, editSession, cachedLineHeight, cachedCharWidth] = [] beforeEach -> + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) editSession = project.buildEditSession('sample.js') buffer = editSession.buffer editor = new Editor(editSession) diff --git a/spec/app/grammar-view-spec.coffee b/spec/app/grammar-view-spec.coffee index 45157aab0..9928f85ee 100644 --- a/spec/app/grammar-view-spec.coffee +++ b/spec/app/grammar-view-spec.coffee @@ -6,6 +6,8 @@ describe "GrammarView", -> [editor, textGrammar, jsGrammar] = [] beforeEach -> + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) window.rootView = new RootView rootView.open('sample.js') editor = rootView.getActiveView() diff --git a/spec/app/language-mode-spec.coffee b/spec/app/language-mode-spec.coffee index 715296e6b..4244d3c72 100644 --- a/spec/app/language-mode-spec.coffee +++ b/spec/app/language-mode-spec.coffee @@ -10,6 +10,7 @@ describe "LanguageMode", -> describe "common behavior", -> beforeEach -> + atom.activatePackage('javascript.tmbundle', sync: true) editSession = project.buildEditSession('sample.js', autoIndent: false) { buffer, languageMode } = editSession @@ -21,6 +22,7 @@ describe "LanguageMode", -> describe "javascript", -> beforeEach -> + atom.activatePackage('javascript.tmbundle', sync: true) editSession = project.buildEditSession('sample.js', autoIndent: false) { buffer, languageMode } = editSession @@ -60,9 +62,9 @@ describe "LanguageMode", -> expect(languageMode.suggestedIndentForBufferRow(2)).toBe 2 expect(languageMode.suggestedIndentForBufferRow(9)).toBe 1 - describe "coffeescript", -> beforeEach -> + atom.activatePackage('coffee-script-tmbundle', sync: true) editSession = project.buildEditSession('coffee.coffee', autoIndent: false) { buffer, languageMode } = editSession @@ -98,6 +100,7 @@ describe "LanguageMode", -> describe "css", -> beforeEach -> + atom.activatePackage('css.tmbundle', sync: true) editSession = project.buildEditSession('css.css', autoIndent: false) { buffer, languageMode } = editSession diff --git a/spec/app/syntax-spec.coffee b/spec/app/syntax-spec.coffee index 789e44159..01da46baa 100644 --- a/spec/app/syntax-spec.coffee +++ b/spec/app/syntax-spec.coffee @@ -1,6 +1,12 @@ fs = require 'fs-utils' describe "the `syntax` global", -> + beforeEach -> + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) + atom.activatePackage('coffee-script-tmbundle', sync: true) + atom.activatePackage('ruby.tmbundle', sync: true) + describe "serialization", -> it "remembers grammar overrides by path", -> path = '/foo/bar/file.js' @@ -12,6 +18,8 @@ describe "the `syntax` global", -> describe ".selectGrammar(filePath)", -> it "can use the filePath to load the correct grammar based on the grammar's filetype", -> + atom.activatePackage('git.tmbundle', sync: true) + expect(syntax.selectGrammar("file.js").name).toBe "JavaScript" # based on extension (.js) expect(syntax.selectGrammar("/tmp/.git/config").name).toBe "Git Config" # based on end of the path (.git/config) expect(syntax.selectGrammar("Rakefile").name).toBe "Ruby" # based on the file's basename (Rakefile) @@ -23,6 +31,8 @@ describe "the `syntax` global", -> expect(syntax.selectGrammar(filePath).name).toBe "Ruby" it "uses the number of newlines in the first line regex to determine the number of lines to test against", -> + atom.activatePackage('property-list.tmbundle', sync: true) + fileContent = "first-line\n" expect(syntax.selectGrammar("dummy.coffee", fileContent).name).toBe "CoffeeScript" @@ -47,6 +57,12 @@ describe "the `syntax` global", -> syntax.clearGrammarOverrideForPath(path) expect(syntax.selectGrammar(path).name).not.toBe 'Ruby' + describe ".removeGrammar(grammar)", -> + it "removes the grammar, so it won't be returned by selectGrammar", -> + grammar = syntax.selectGrammar('foo.js') + syntax.removeGrammar(grammar) + expect(syntax.selectGrammar('foo.js').name).not.toBe grammar.name + describe ".getProperty(scopeDescriptor)", -> it "returns the property with the most specific scope selector", -> syntax.addProperties(".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42) diff --git a/spec/app/text-mate-grammar-spec.coffee b/spec/app/text-mate-grammar-spec.coffee index f524e69e5..b52f6451a 100644 --- a/spec/app/text-mate-grammar-spec.coffee +++ b/spec/app/text-mate-grammar-spec.coffee @@ -8,6 +8,10 @@ describe "TextMateGrammar", -> grammar = null beforeEach -> + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) + atom.activatePackage('coffee-script-tmbundle', sync: true) + atom.activatePackage('ruby.tmbundle', sync: true) grammar = syntax.selectGrammar("hello.coffee") describe ".tokenizeLine(line, ruleStack)", -> @@ -192,6 +196,9 @@ describe "TextMateGrammar", -> describe "when the pattern includes rules from another grammar", -> it "parses tokens inside the begin/end patterns based on the included grammar's rules", -> + atom.activatePackage('html.tmbundle', sync: true) + atom.activatePackage('ruby-on-rails-tmbundle', sync: true) + grammar = syntax.grammarsByFileType["html.erb"] {tokens} = grammar.tokenizeLine("
<%= User.find(2).full_name %>
") @@ -248,6 +255,9 @@ describe "TextMateGrammar", -> {tokens, ruleStack} = grammar.tokenizeLine(" // second line comment with a single leading space", ruleStack) describe "when inside a C block", -> + beforeEach -> + atom.activatePackage('c.tmbundle', sync: true) + it "correctly parses a method. (regression)", -> grammar = syntax.selectGrammar("hello.c") {tokens, ruleStack} = grammar.tokenizeLine("if(1){m()}") @@ -271,6 +281,7 @@ describe "TextMateGrammar", -> describe "when a grammar has a pattern that has back references in the match value", -> it "does not special handle the back references and instead allows oniguruma to resolve them", -> + atom.activatePackage('sass.tmbundle', sync: true) grammar = syntax.selectGrammar("style.scss") {tokens} = grammar.tokenizeLine("@mixin x() { -moz-selector: whatever; }") expect(tokens[9]).toEqual value: "-moz-selector", scopes: ["source.css.scss", "meta.property-list.scss", "meta.property-name.scss"] diff --git a/spec/app/tokenized-buffer-spec.coffee b/spec/app/tokenized-buffer-spec.coffee index 378534b37..4f7ad41ce 100644 --- a/spec/app/tokenized-buffer-spec.coffee +++ b/spec/app/tokenized-buffer-spec.coffee @@ -8,6 +8,7 @@ describe "TokenizedBuffer", -> [editSession, tokenizedBuffer, buffer, changeHandler] = [] beforeEach -> + atom.activatePackage('javascript.tmbundle', sync: true) # enable async tokenization TokenizedBuffer.prototype.chunkSize = 5 jasmine.unspy(TokenizedBuffer.prototype, 'tokenizeInBackground') @@ -298,6 +299,7 @@ describe "TokenizedBuffer", -> describe "when the buffer contains hard-tabs", -> beforeEach -> + atom.activatePackage('coffee-script-tmbundle', sync: true) tabLength = 2 editSession = project.buildEditSession('sample-with-tabs.coffee', { tabLength }) buffer = editSession.buffer @@ -328,6 +330,7 @@ describe "TokenizedBuffer", -> describe "when a Git commit message file is tokenized", -> beforeEach -> + atom.activatePackage('git.tmbundle', sync: true) editSession = project.buildEditSession('COMMIT_EDITMSG', autoIndent: false) buffer = editSession.buffer tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer @@ -355,6 +358,7 @@ describe "TokenizedBuffer", -> describe "when a C++ source file is tokenized", -> beforeEach -> + atom.activatePackage('c.tmbundle', sync: true) editSession = project.buildEditSession('includes.cc', autoIndent: false) buffer = editSession.buffer tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer @@ -403,6 +407,8 @@ describe "TokenizedBuffer", -> describe "when an Objective-C source file is tokenized", -> beforeEach -> + atom.activatePackage('c.tmbundle', sync: true) + atom.activatePackage('objective-c.tmbundle', sync: true) editSession = project.buildEditSession('function.mm', autoIndent: false) buffer = editSession.buffer tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index d66fea65e..2bef64dc2 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -17,6 +17,7 @@ RootView = require 'root-view' Git = require 'git' requireStylesheet "jasmine" fixturePackagesPath = fs.resolveOnLoadPath('fixtures/packages') +config.packageDirPaths.unshift(fixturePackagesPath) keymap.loadBundledKeymaps() [bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = [] @@ -92,16 +93,6 @@ afterEach -> syntax.off() waits(0) # yield to ui thread to make screen update more frequently -# Specs rely on TextMate bundles (but not atom packages) -window.loadTextMatePackages = -> - TextMatePackage = require 'text-mate-package' - config.packageDirPaths.unshift(fixturePackagesPath) - window.textMatePackages = [] - for path in atom.getPackagePaths() when TextMatePackage.testName(path) - window.textMatePackages.push atom.activatePackage(path, sync: true) - -window.loadTextMatePackages() - ensureNoPathSubscriptions = -> watchedPaths = $native.getWatchedPaths() $native.unwatchAllPaths() diff --git a/src/app/syntax.coffee b/src/app/syntax.coffee index f37949370..fe15047aa 100644 --- a/src/app/syntax.coffee +++ b/src/app/syntax.coffee @@ -32,9 +32,14 @@ class Syntax addGrammar: (grammar) -> @grammars.push(grammar) - for fileType in grammar.fileTypes - @grammarsByFileType[fileType] = grammar - @grammarsByScopeName[grammar.scopeName] = grammar + @grammarsByFileType[fileType] = grammar for fileType in grammar.fileTypes + @grammarsByScopeName[grammar.scopeName] = grammar + + removeGrammar: (grammar) -> + if _.include(@grammars, grammar) + _.remove(@grammars, grammar) + delete @grammarsByFileType[fileType] for fileType in grammar.fileTypes + delete @grammarsByScopeName[grammar.scopeName] setGrammarOverrideForPath: (path, scopeName) -> @grammarOverridesByPath[path] = scopeName @@ -46,7 +51,9 @@ class Syntax @grammarOverridesByPath = {} selectGrammar: (filePath, fileContents) -> + return @grammarsByFileType["txt"] ? @nullGrammar unless filePath + @grammarOverrideForPath(filePath) ? @grammarByFirstLineRegex(filePath, fileContents) ? @grammarByPath(filePath) ? diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index 62114e52a..f9a2dfaea 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -36,7 +36,8 @@ class TextMatePackage extends Package syntax.addProperties(selector, properties) deactivate: -> - # we should remove grammars and unregister properties, snippets, etc + syntax.removeGrammar(grammar) for grammar in @grammars + # we should also unregister properties, snippets, etc legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage'] diff --git a/src/packages/snippets/spec/snippets-spec.coffee b/src/packages/snippets/spec/snippets-spec.coffee index fad90f109..5e2f2c74e 100644 --- a/src/packages/snippets/spec/snippets-spec.coffee +++ b/src/packages/snippets/spec/snippets-spec.coffee @@ -9,13 +9,11 @@ Package = require 'package' describe "Snippets extension", -> [buffer, editor, editSession] = [] beforeEach -> + atom.activatePackage('javascript.tmbundle', sync: true) window.rootView = new RootView rootView.open('sample.js') packageWithSnippets = atom.loadPackage("package-with-snippets") - spyOn(atom, "getLoadedPackages").andCallFake -> - textMatePackages = window.textMatePackages.filter (pack) -> /package-with-a-cson-grammar|test|textmate-package|javascript/.test(pack.name) - textMatePackages.concat([packageWithSnippets]) spyOn(require("snippets/lib/snippets"), 'loadAll') atom.activatePackage("snippets") @@ -238,6 +236,9 @@ describe "Snippets extension", -> describe "snippet loading", -> beforeEach -> + atom.loadPackage('textmate-package.tmbundle', sync: true) + atom.loadPackage('package-with-snippets') + jasmine.unspy(window, "setTimeout") jasmine.unspy(snippets, 'loadAll') spyOn(snippets, 'loadAtomSnippets').andCallFake (path, done) -> done() diff --git a/src/packages/spell-check/spec/spell-check-spec.coffee b/src/packages/spell-check/spec/spell-check-spec.coffee index d6eb88995..5ac927d96 100644 --- a/src/packages/spell-check/spec/spell-check-spec.coffee +++ b/src/packages/spell-check/spec/spell-check-spec.coffee @@ -4,6 +4,8 @@ describe "Spell check", -> [editor] = [] beforeEach -> + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) window.rootView = new RootView rootView.open('sample.js') config.set('spell-check.grammars', []) diff --git a/src/packages/status-bar/spec/status-bar-spec.coffee b/src/packages/status-bar/spec/status-bar-spec.coffee index dd067dbf2..ec4329b6b 100644 --- a/src/packages/status-bar/spec/status-bar-spec.coffee +++ b/src/packages/status-bar/spec/status-bar-spec.coffee @@ -180,6 +180,11 @@ describe "StatusBar", -> expect(statusBar.gitStatusIcon).toHaveText('+1') describe "grammar label", -> + beforeEach -> + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) + syntax.trigger 'grammars-loaded' + it "displays the name of the current grammar", -> expect(statusBar.find('.grammar-name').text()).toBe 'JavaScript' From da016114b61a2e3eaee82c81e466bff5d2505f14 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Mon, 25 Mar 2013 16:55:21 -0700 Subject: [PATCH 19/79] Add specs for activating and deactivating TextMate packages --- spec/app/atom-spec.coffee | 146 +++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 65 deletions(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index eec7d718c..7be81785f 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -16,91 +16,107 @@ describe "the `atom` global", -> atom.deactivatePackages() describe ".activatePackage(id)", -> - stylesheetPath = null + describe "atom packages", -> + stylesheetPath = null - beforeEach -> - stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") + beforeEach -> + stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") - afterEach -> - removeStylesheet(stylesheetPath) + afterEach -> + removeStylesheet(stylesheetPath) - it "requires and activates the package's main module if it exists", -> - spyOn(packageModule, 'activate').andCallThrough() - atom.activatePackage("package-with-module") - expect(packageModule.activate).toHaveBeenCalledWith({}) + it "requires and activates the package's main module if it exists", -> + spyOn(packageModule, 'activate').andCallThrough() + atom.activatePackage("package-with-module") + expect(packageModule.activate).toHaveBeenCalledWith({}) - it "passes the package its previously serialized state if it exists", -> - pack = atom.activatePackage("package-with-module") - expect(pack.mainModule.someNumber).not.toBe 77 - pack.mainModule.someNumber = 77 - atom.deactivatePackage("package-with-module") + it "passes the package its previously serialized state if it exists", -> + pack = atom.activatePackage("package-with-module") + expect(pack.mainModule.someNumber).not.toBe 77 + pack.mainModule.someNumber = 77 + atom.deactivatePackage("package-with-module") - pack.requireMainModule() # deactivating the package nukes its main module, so we require it again to spy on it - spyOn(pack.mainModule, 'activate').andCallThrough() + pack.requireMainModule() # deactivating the package nukes its main module, so we require it again to spy on it + spyOn(pack.mainModule, 'activate').andCallThrough() - atom.activatePackage("package-with-module") - expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77}) + atom.activatePackage("package-with-module") + expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77}) - it "logs warning instead of throwing an exception if a package fails to load", -> - config.set("core.disabledPackages", []) - spyOn(console, "warn") - expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow() - expect(console.warn).toHaveBeenCalled() + it "logs warning instead of throwing an exception if a package fails to load", -> + config.set("core.disabledPackages", []) + spyOn(console, "warn") + expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow() + expect(console.warn).toHaveBeenCalled() - describe "keymap loading", -> - describe "when package.json does not contain a 'keymaps' manifest", -> - it "loads all the .cson/.json files in the keymaps directory", -> - element1 = $$ -> @div class: 'test-1' - element2 = $$ -> @div class: 'test-2' - element3 = $$ -> @div class: 'test-3' + describe "keymap loading", -> + describe "when package.json does not contain a 'keymaps' manifest", -> + it "loads all the .cson/.json files in the keymaps directory", -> + element1 = $$ -> @div class: 'test-1' + element2 = $$ -> @div class: 'test-2' + element3 = $$ -> @div class: 'test-3' - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() - expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined() - expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - atom.activatePackage("package-with-module") + atom.activatePackage("package-with-module") - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1" - expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2" - expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1" + expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2" + expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - describe "when package.json contains a 'keymaps' manifest", -> - it "loads only the keymaps specified by the manifest, in the specified order", -> - element1 = $$ -> @div class: 'test-1' - element3 = $$ -> @div class: 'test-3' + describe "when package.json contains a 'keymaps' manifest", -> + it "loads only the keymaps specified by the manifest, in the specified order", -> + element1 = $$ -> @div class: 'test-1' + element3 = $$ -> @div class: 'test-3' - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined() - atom.activatePackage("package-with-keymaps-manifest") + atom.activatePackage("package-with-keymaps-manifest") - expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1' - expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2' - expect(keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined() + expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1' + expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2' + expect(keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined() - it "loads stylesheets associated with the package", -> - stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") - expect(stylesheetElementForId(stylesheetPath).length).toBe 0 - atom.activatePackage("package-with-module") - expect(stylesheetElementForId(stylesheetPath).length).toBe 1 + it "loads stylesheets associated with the package", -> + stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") + expect(stylesheetElementForId(stylesheetPath).length).toBe 0 + atom.activatePackage("package-with-module") + expect(stylesheetElementForId(stylesheetPath).length).toBe 1 + + describe "textmate packages", -> + it "loads the package's grammars", -> + expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" + atom.activatePackage('ruby.tmbundle', sync: true) + expect(syntax.selectGrammar("file.rb").name).toBe "Ruby" describe ".deactivatePackage(id)", -> - it "calls `deactivate` on the package's main module and deletes the package's module reference and require cache entry", -> - pack = atom.activatePackage("package-with-module") - expect(atom.getActivePackage("package-with-module")).toBe pack - spyOn(pack.mainModule, 'deactivate').andCallThrough() + describe "atom packages", -> + it "calls `deactivate` on the package's main module and deletes the package's module reference and require cache entry", -> + pack = atom.activatePackage("package-with-module") + expect(atom.getActivePackage("package-with-module")).toBe pack + spyOn(pack.mainModule, 'deactivate').andCallThrough() - atom.deactivatePackage("package-with-module") - expect(pack.mainModule.deactivate).toHaveBeenCalled() - expect(atom.getActivePackage("package-with-module")).toBeUndefined() + atom.deactivatePackage("package-with-module") + expect(pack.mainModule.deactivate).toHaveBeenCalled() + expect(atom.getActivePackage("package-with-module")).toBeUndefined() - it "absorbs exceptions that are thrown by the package module's serialize methods", -> - spyOn(console, 'error') - atom.activatePackage('package-with-module', immediate: true) - atom.activatePackage('package-with-serialize-error', immediate: true) - atom.deactivatePackages() - expect(atom.packageStates['package-with-module']).toEqual someNumber: 1 - expect(atom.packageStates['package-with-serialize-error']).toBeUndefined() - expect(console.error).toHaveBeenCalled() + it "absorbs exceptions that are thrown by the package module's serialize methods", -> + spyOn(console, 'error') + atom.activatePackage('package-with-module', immediate: true) + atom.activatePackage('package-with-serialize-error', immediate: true) + atom.deactivatePackages() + expect(atom.packageStates['package-with-module']).toEqual someNumber: 1 + expect(atom.packageStates['package-with-serialize-error']).toBeUndefined() + expect(console.error).toHaveBeenCalled() + + describe "texmate packages", -> + it "removes the package's grammars", -> + expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" + atom.activatePackage('ruby.tmbundle', sync: true) + expect(syntax.selectGrammar("file.rb").name).toBe "Ruby" + atom.deactivatePackage('ruby.tmbundle') + expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" describe ".getVersion(callback)", -> it "calls the callback with the current version number", -> From 643a5c6d0e3b215d07e230bbab2d1e4c2e07a2c1 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Mon, 25 Mar 2013 17:08:07 -0700 Subject: [PATCH 20/79] :lipstick: --- src/app/atom-package.coffee | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 61c9c3879..2d4c68219 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -31,6 +31,24 @@ class AtomPackage extends Package console.warn "Failed to load package named '#{@name}'", e.stack this + activate: ({immediate}={}) -> + keymap.add(map) for map in @keymaps + applyStylesheet(path, content) for [path, content] in @stylesheets + syntax.addGrammar(grammar) for grammar in @grammars + + if @deferActivation and not immediate + @subscribeToActivationEvents() + else + @activateNow() + + activateNow: -> + try + if @requireMainModule() + config.setDefaults(@name, @mainModule.configDefaults) + @mainModule.activate(atom.getPackageState(@name) ? {}) + catch e + console.warn "Failed to activate package named '#{@name}'", e.stack + loadMetadata: -> if metadataPath = fs.resolveExtension(fs.join(@path, 'package'), ['cson', 'json']) @metadata = CSON.readObject(metadataPath) @@ -67,24 +85,6 @@ class AtomPackage extends Package for selector, properties of fs.readObject(scopedPropertiesPath) syntax.addProperties(selector, properties) - activate: ({immediate}={}) -> - keymap.add(map) for map in @keymaps - applyStylesheet(path, content) for [path, content] in @stylesheets - syntax.addGrammar(grammar) for grammar in @grammars - - if @deferActivation and not immediate - @subscribeToActivationEvents() - else - @activateNow() - - activateNow: -> - try - if @requireMainModule() - config.setDefaults(@name, @mainModule.configDefaults) - @mainModule.activate(atom.getPackageState(@name) ? {}) - catch e - console.warn "Failed to activate package named '#{@name}'", e.stack - serialize: -> try @mainModule?.serialize?() From b846a4db985c9b691b27e8f2fe9952edd23264b1 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Mon, 25 Mar 2013 17:57:30 -0700 Subject: [PATCH 21/79] wip: cleanup package lifecycle specs --- spec/app/atom-package-spec.coffee | 21 ----- spec/app/atom-spec.coffee | 79 +++++++++++-------- .../packages/package-with-index/index.coffee | 2 + .../keymaps/keymap-1.cson | 0 .../keymaps/keymap-2.cson | 0 .../keymaps/keymap-3.cjson | 0 .../package-with-main/main-module.coffee | 2 + .../packages/package-with-main/package.cson | 1 + .../stylesheets/styles.css | 0 .../index.coffee | 4 - .../stylesheets/1.css | 3 + .../stylesheets/2.less | 5 ++ .../stylesheets/3.css | 3 + .../package-without-module/package.cson | 1 + 14 files changed, 64 insertions(+), 57 deletions(-) create mode 100644 spec/fixtures/packages/package-with-index/index.coffee rename spec/fixtures/packages/{package-with-module => package-with-keymaps}/keymaps/keymap-1.cson (100%) rename spec/fixtures/packages/{package-with-module => package-with-keymaps}/keymaps/keymap-2.cson (100%) rename spec/fixtures/packages/{package-with-module => package-with-keymaps}/keymaps/keymap-3.cjson (100%) create mode 100644 spec/fixtures/packages/package-with-main/main-module.coffee create mode 100644 spec/fixtures/packages/package-with-main/package.cson delete mode 100644 spec/fixtures/packages/package-with-module/stylesheets/styles.css rename spec/fixtures/packages/{package-with-module => package-with-serialization}/index.coffee (81%) create mode 100644 spec/fixtures/packages/package-with-stylesheets/stylesheets/1.css create mode 100644 spec/fixtures/packages/package-with-stylesheets/stylesheets/2.less create mode 100644 spec/fixtures/packages/package-with-stylesheets/stylesheets/3.css create mode 100644 spec/fixtures/packages/package-without-module/package.cson diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee index 03da7ca8d..9a5c817da 100644 --- a/spec/app/atom-package-spec.coffee +++ b/spec/app/atom-package-spec.coffee @@ -48,27 +48,6 @@ describe "AtomPackage", -> expect(eventHandler.callCount).toBe 2 expect(packageMainModule.activate.callCount).toBe 1 - describe "when the package does not specify a main module", -> - describe "when the package has an index.coffee", -> - it "uses index.coffee as the main module", -> - pack = new AtomPackage(fs.resolve(config.packageDirPaths..., 'package-with-module')) - packageMainModule = require 'fixtures/packages/package-with-module' - spyOn(packageMainModule, 'activate').andCallThrough() - - expect(packageMainModule.activate).not.toHaveBeenCalled() - pack.load() - pack.activate() - expect(packageMainModule.activate).toHaveBeenCalled() - - describe "when the package doesn't have an index.coffee", -> - it "does not throw an exception or log an error", -> - spyOn(console, "error") - spyOn(console, "warn").andCallThrough() - pack = new AtomPackage(fs.resolve(config.packageDirPaths..., 'package-with-keymaps-manifest')) - - expect(-> pack.load()).not.toThrow() - expect(console.error).not.toHaveBeenCalled() - expect(console.warn).not.toHaveBeenCalled() describe "when a package is activated", -> it "loads config defaults based on the `configDefaults` key", -> diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 7be81785f..71287630d 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -1,3 +1,4 @@ +$ = require 'jquery' RootView = require 'root-view' {$$} = require 'space-pen' fs = require 'fs-utils' @@ -7,39 +8,40 @@ describe "the `atom` global", -> window.rootView = new RootView describe "package lifecycle methods", -> - packageModule = null - - beforeEach -> - packageModule = require "package-with-module" - - afterEach -> - atom.deactivatePackages() - describe ".activatePackage(id)", -> describe "atom packages", -> - stylesheetPath = null + describe "when the package has a main module", -> + describe "when the metadata specifies a main module path˜", -> + it "requires the module at the specified path", -> + mainModule = require('package-with-main/main-module') + spyOn(mainModule, 'activate') + pack = atom.activatePackage('package-with-main') + expect(mainModule.activate).toHaveBeenCalled() + expect(pack.mainModule).toBe mainModule - beforeEach -> - stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") + describe "when the metadata does not specify a main module", -> + it "requires index.coffee", -> + indexModule = require('package-with-index/index') + spyOn(indexModule, 'activate') + pack = atom.activatePackage('package-with-index') + expect(indexModule.activate).toHaveBeenCalled() + expect(pack.mainModule).toBe indexModule - afterEach -> - removeStylesheet(stylesheetPath) - - it "requires and activates the package's main module if it exists", -> - spyOn(packageModule, 'activate').andCallThrough() - atom.activatePackage("package-with-module") - expect(packageModule.activate).toHaveBeenCalledWith({}) + describe "when the package has no main module", -> + it "does not throw an exception", -> + spyOn(console, "error") + spyOn(console, "warn").andCallThrough() + expect(-> atom.activatePackage('package-without-module')).not.toThrow() + expect(console.error).not.toHaveBeenCalled() + expect(console.warn).not.toHaveBeenCalled() it "passes the package its previously serialized state if it exists", -> - pack = atom.activatePackage("package-with-module") + pack = atom.activatePackage("package-with-serialization") expect(pack.mainModule.someNumber).not.toBe 77 pack.mainModule.someNumber = 77 - atom.deactivatePackage("package-with-module") - - pack.requireMainModule() # deactivating the package nukes its main module, so we require it again to spy on it + atom.deactivatePackage("package-with-serialization") spyOn(pack.mainModule, 'activate').andCallThrough() - - atom.activatePackage("package-with-module") + atom.activatePackage("package-with-serialization") expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77}) it "logs warning instead of throwing an exception if a package fails to load", -> @@ -49,7 +51,7 @@ describe "the `atom` global", -> expect(console.warn).toHaveBeenCalled() describe "keymap loading", -> - describe "when package.json does not contain a 'keymaps' manifest", -> + describe "when the metadata does not contain a 'keymaps' manifest", -> it "loads all the .cson/.json files in the keymaps directory", -> element1 = $$ -> @div class: 'test-1' element2 = $$ -> @div class: 'test-2' @@ -59,13 +61,13 @@ describe "the `atom` global", -> expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined() expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - atom.activatePackage("package-with-module") + atom.activatePackage("package-with-keymaps") expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1" expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2" expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined() - describe "when package.json contains a 'keymaps' manifest", -> + describe "when the metadata contains a 'keymaps' manifest", -> it "loads only the keymaps specified by the manifest, in the specified order", -> element1 = $$ -> @div class: 'test-1' element3 = $$ -> @div class: 'test-3' @@ -78,11 +80,24 @@ describe "the `atom` global", -> expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2' expect(keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined() - it "loads stylesheets associated with the package", -> - stylesheetPath = fs.resolveOnLoadPath("fixtures/packages/package-with-module/stylesheets/styles.css") - expect(stylesheetElementForId(stylesheetPath).length).toBe 0 - atom.activatePackage("package-with-module") - expect(stylesheetElementForId(stylesheetPath).length).toBe 1 + describe "stylesheet loading", -> + describe "when the metadata contains a 'stylesheets' manifest", -> + # WIP + + describe "when the metadata does not contains a 'stylesheets' manifest", -> + it "loads all stylesheets from the stylesheets directory", -> + one = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/1.css") + two = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/2.less") + three = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/3.css") + expect(stylesheetElementForId(one)).not.toExist() + expect(stylesheetElementForId(two)).not.toExist() + expect(stylesheetElementForId(three)).not.toExist() + + atom.activatePackage("package-with-stylesheets") + expect(stylesheetElementForId(one)).toExist() + expect(stylesheetElementForId(two)).toExist() + expect(stylesheetElementForId(three)).toExist() + expect($('#jasmine-content').css('font-size')).toBe '3px' describe "textmate packages", -> it "loads the package's grammars", -> diff --git a/spec/fixtures/packages/package-with-index/index.coffee b/spec/fixtures/packages/package-with-index/index.coffee new file mode 100644 index 000000000..825eb4055 --- /dev/null +++ b/spec/fixtures/packages/package-with-index/index.coffee @@ -0,0 +1,2 @@ +module.exports = +activate: -> diff --git a/spec/fixtures/packages/package-with-module/keymaps/keymap-1.cson b/spec/fixtures/packages/package-with-keymaps/keymaps/keymap-1.cson similarity index 100% rename from spec/fixtures/packages/package-with-module/keymaps/keymap-1.cson rename to spec/fixtures/packages/package-with-keymaps/keymaps/keymap-1.cson diff --git a/spec/fixtures/packages/package-with-module/keymaps/keymap-2.cson b/spec/fixtures/packages/package-with-keymaps/keymaps/keymap-2.cson similarity index 100% rename from spec/fixtures/packages/package-with-module/keymaps/keymap-2.cson rename to spec/fixtures/packages/package-with-keymaps/keymaps/keymap-2.cson diff --git a/spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson b/spec/fixtures/packages/package-with-keymaps/keymaps/keymap-3.cjson similarity index 100% rename from spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson rename to spec/fixtures/packages/package-with-keymaps/keymaps/keymap-3.cjson diff --git a/spec/fixtures/packages/package-with-main/main-module.coffee b/spec/fixtures/packages/package-with-main/main-module.coffee new file mode 100644 index 000000000..46920ab78 --- /dev/null +++ b/spec/fixtures/packages/package-with-main/main-module.coffee @@ -0,0 +1,2 @@ +module.exports = +activate: -> \ No newline at end of file diff --git a/spec/fixtures/packages/package-with-main/package.cson b/spec/fixtures/packages/package-with-main/package.cson new file mode 100644 index 000000000..a93a109c4 --- /dev/null +++ b/spec/fixtures/packages/package-with-main/package.cson @@ -0,0 +1 @@ +'main': 'main-module.coffee' \ No newline at end of file diff --git a/spec/fixtures/packages/package-with-module/stylesheets/styles.css b/spec/fixtures/packages/package-with-module/stylesheets/styles.css deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/packages/package-with-module/index.coffee b/spec/fixtures/packages/package-with-serialization/index.coffee similarity index 81% rename from spec/fixtures/packages/package-with-module/index.coffee rename to spec/fixtures/packages/package-with-serialization/index.coffee index 3872da074..3756508da 100644 --- a/spec/fixtures/packages/package-with-module/index.coffee +++ b/spec/fixtures/packages/package-with-serialization/index.coffee @@ -2,12 +2,8 @@ module.exports = configDefaults: numbers: { one: 1, two: 2 } - someNumber: 0 - activate: ({@someNumber}) -> @someNumber ?= 1 - deactivate: -> - serialize: -> {@someNumber} diff --git a/spec/fixtures/packages/package-with-stylesheets/stylesheets/1.css b/spec/fixtures/packages/package-with-stylesheets/stylesheets/1.css new file mode 100644 index 000000000..c16849c0e --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets/stylesheets/1.css @@ -0,0 +1,3 @@ +#jasmine-content { + font-size: 1px; +} diff --git a/spec/fixtures/packages/package-with-stylesheets/stylesheets/2.less b/spec/fixtures/packages/package-with-stylesheets/stylesheets/2.less new file mode 100644 index 000000000..c0ffbc897 --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets/stylesheets/2.less @@ -0,0 +1,5 @@ +@size: 2px; + +#jasmine-content { + font-size: @size; +} diff --git a/spec/fixtures/packages/package-with-stylesheets/stylesheets/3.css b/spec/fixtures/packages/package-with-stylesheets/stylesheets/3.css new file mode 100644 index 000000000..f43408c63 --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets/stylesheets/3.css @@ -0,0 +1,3 @@ +#jasmine-content { + font-size: 3px; +} diff --git a/spec/fixtures/packages/package-without-module/package.cson b/spec/fixtures/packages/package-without-module/package.cson new file mode 100644 index 000000000..c6e451934 --- /dev/null +++ b/spec/fixtures/packages/package-without-module/package.cson @@ -0,0 +1 @@ +"name": "perfect" From c8804359c9cf1388c60c8a476172083dd06a4158 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 10:39:07 -0600 Subject: [PATCH 22/79] Rename fs -> fsUtils in atom-package --- src/app/atom-package.coffee | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 2d4c68219..373c440ef 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -1,6 +1,6 @@ TextMateGrammar = require 'text-mate-grammar' Package = require 'package' -fs = require 'fs-utils' +fsUtils = require 'fs-utils' _ = require 'underscore' $ = require 'jquery' CSON = require 'cson' @@ -50,39 +50,39 @@ class AtomPackage extends Package console.warn "Failed to activate package named '#{@name}'", e.stack loadMetadata: -> - if metadataPath = fs.resolveExtension(fs.join(@path, 'package'), ['cson', 'json']) + if metadataPath = fsUtils.resolveExtension(fsUtils.join(@path, 'package'), ['cson', 'json']) @metadata = CSON.readObject(metadataPath) @metadata ?= {} loadKeymaps: -> @keymaps = [] - keymapsDirPath = fs.join(@path, 'keymaps') + keymapsDirPath = fsUtils.join(@path, 'keymaps') keymapExtensions = ['cson', 'json', ''] if @metadata.keymaps for path in @metadata.keymaps - @keymaps.push(CSON.readObject(fs.resolve(keymapsDirPath, path, keymapExtensions))) + @keymaps.push(CSON.readObject(fsUtils.resolve(keymapsDirPath, path, keymapExtensions))) else - for path in fs.list(keymapsDirPath, ['cson', 'json', '']) ? [] + for path in fsUtils.list(keymapsDirPath, ['cson', 'json', '']) ? [] @keymaps.push(CSON.readObject(path)) loadStylesheets: -> @stylesheets = [] - stylesheetDirPath = fs.join(@path, 'stylesheets') - for stylesheetPath in fs.list(stylesheetDirPath, ['css', 'less']) ? [] + stylesheetDirPath = fsUtils.join(@path, 'stylesheets') + for stylesheetPath in fsUtils.list(stylesheetDirPath, ['css', 'less']) ? [] @stylesheets.push([stylesheetPath, loadStylesheet(stylesheetPath)]) loadGrammars: -> @grammars = [] - grammarsDirPath = fs.join(@path, 'grammars') - for grammarPath in fs.list(grammarsDirPath, ['.cson', '.json']) ? [] + grammarsDirPath = fsUtils.join(@path, 'grammars') + for grammarPath in fsUtils.list(grammarsDirPath, ['.cson', '.json']) ? [] @grammars.push(TextMateGrammar.loadSync(grammarPath)) loadScopedProperties: -> - scopedPropertiessDirPath = fs.join(@path, 'scoped-properties') - for scopedPropertiesPath in fs.list(scopedPropertiessDirPath, ['.cson', '.json']) ? [] - for selector, properties of fs.readObject(scopedPropertiesPath) + scopedPropertiessDirPath = fsUtils.join(@path, 'scoped-properties') + for scopedPropertiesPath in fsUtils.list(scopedPropertiessDirPath, ['.cson', '.json']) ? [] + for selector, properties of fsUtils.readObject(scopedPropertiesPath) syntax.addProperties(selector, properties) serialize: -> @@ -97,17 +97,17 @@ class AtomPackage extends Package requireMainModule: -> return @mainModule if @mainModule mainModulePath = @getMainModulePath() - @mainModule = require(mainModulePath) if fs.isFile(mainModulePath) + @mainModule = require(mainModulePath) if fsUtils.isFile(mainModulePath) getMainModulePath: -> return @mainModulePath if @resolvedMainModulePath @resolvedMainModulePath = true mainModulePath = if @metadata.main - fs.join(@path, @metadata.main) + fsUtils.join(@path, @metadata.main) else - fs.join(@path, 'index') - @mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...]) + fsUtils.join(@path, 'index') + @mainModulePath = fsUtils.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...]) registerDeferredDeserializers: -> for deserializerName in @metadata.deferredDeserializers ? [] From 8c1f5658be6005bc1d3d75d512ceb36b925ab88a Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 10:50:40 -0600 Subject: [PATCH 23/79] Allow packages to have stylesheet manifests --- spec/app/atom-spec.coffee | 19 ++++++++++++++++--- .../package.cson | 1 + .../stylesheets/1.css | 3 +++ .../stylesheets/2.less | 5 +++++ .../stylesheets/3.css | 3 +++ src/app/atom-package.coffee | 9 +++++++-- 6 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 spec/fixtures/packages/package-with-stylesheets-manifest/package.cson create mode 100644 spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css create mode 100644 spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less create mode 100644 spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 71287630d..1be3f87b1 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -35,7 +35,7 @@ describe "the `atom` global", -> expect(console.error).not.toHaveBeenCalled() expect(console.warn).not.toHaveBeenCalled() - it "passes the package its previously serialized state if it exists", -> + it "passes the activate method the package's previously serialized state if it exists", -> pack = atom.activatePackage("package-with-serialization") expect(pack.mainModule.someNumber).not.toBe 77 pack.mainModule.someNumber = 77 @@ -44,7 +44,7 @@ describe "the `atom` global", -> atom.activatePackage("package-with-serialization") expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77}) - it "logs warning instead of throwing an exception if a package fails to load", -> + it "logs warning instead of throwing an exception if the package fails to load", -> config.set("core.disabledPackages", []) spyOn(console, "warn") expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow() @@ -82,7 +82,20 @@ describe "the `atom` global", -> describe "stylesheet loading", -> describe "when the metadata contains a 'stylesheets' manifest", -> - # WIP + it "loads stylesheets from the stylesheets directory as specified by the manifest", -> + one = fs.resolveOnLoadPath("package-with-stylesheets-manifest/stylesheets/1.css") + two = fs.resolveOnLoadPath("package-with-stylesheets-manifest/stylesheets/2.less") + three = fs.resolveOnLoadPath("package-with-stylesheets-manifest/stylesheets/3.css") + expect(stylesheetElementForId(one)).not.toExist() + expect(stylesheetElementForId(two)).not.toExist() + expect(stylesheetElementForId(three)).not.toExist() + + atom.activatePackage("package-with-stylesheets-manifest") + + expect(stylesheetElementForId(one)).toExist() + expect(stylesheetElementForId(two)).toExist() + expect(stylesheetElementForId(three)).not.toExist() + expect($('#jasmine-content').css('font-size')).toBe '1px' describe "when the metadata does not contains a 'stylesheets' manifest", -> it "loads all stylesheets from the stylesheets directory", -> diff --git a/spec/fixtures/packages/package-with-stylesheets-manifest/package.cson b/spec/fixtures/packages/package-with-stylesheets-manifest/package.cson new file mode 100644 index 000000000..45ccf32bc --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets-manifest/package.cson @@ -0,0 +1 @@ +stylesheets: ['2', '1'] diff --git a/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css b/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css new file mode 100644 index 000000000..c16849c0e --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css @@ -0,0 +1,3 @@ +#jasmine-content { + font-size: 1px; +} diff --git a/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less b/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less new file mode 100644 index 000000000..c0ffbc897 --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less @@ -0,0 +1,5 @@ +@size: 2px; + +#jasmine-content { + font-size: @size; +} diff --git a/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css b/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css new file mode 100644 index 000000000..f43408c63 --- /dev/null +++ b/spec/fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css @@ -0,0 +1,3 @@ +#jasmine-content { + font-size: 3px; +} diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 373c440ef..75e9f52a6 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -69,9 +69,14 @@ class AtomPackage extends Package loadStylesheets: -> @stylesheets = [] + @stylesheets.push([path, loadStylesheet(path)]) for path in @getStylesheetPaths() + + getStylesheetPaths: -> stylesheetDirPath = fsUtils.join(@path, 'stylesheets') - for stylesheetPath in fsUtils.list(stylesheetDirPath, ['css', 'less']) ? [] - @stylesheets.push([stylesheetPath, loadStylesheet(stylesheetPath)]) + if @metadata.stylesheets + @metadata.stylesheets.map (name) -> fsUtils.resolve(stylesheetDirPath, name, ['css', 'less', '']) + else + fsUtils.list(stylesheetDirPath, ['css', 'less']) ? [] loadGrammars: -> @grammars = [] From de7d9bfcb1e0a217fec9d56d2ff52ae78019fcc0 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 11:00:29 -0600 Subject: [PATCH 24/79] Get deactivatePackage specs passing w/ new fixture data --- spec/app/atom-spec.coffee | 14 +++++++------- .../packages/package-with-deactivate/index.coffee | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 spec/fixtures/packages/package-with-deactivate/index.coffee diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 1be3f87b1..e4ed8f38c 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -120,22 +120,22 @@ describe "the `atom` global", -> describe ".deactivatePackage(id)", -> describe "atom packages", -> - it "calls `deactivate` on the package's main module and deletes the package's module reference and require cache entry", -> - pack = atom.activatePackage("package-with-module") - expect(atom.getActivePackage("package-with-module")).toBe pack + it "calls `deactivate` on the package's main module", -> + pack = atom.activatePackage("package-with-deactivate") + expect(atom.isPackageActive("package-with-deactivate")).toBeTruthy() spyOn(pack.mainModule, 'deactivate').andCallThrough() - atom.deactivatePackage("package-with-module") + atom.deactivatePackage("package-with-deactivate") expect(pack.mainModule.deactivate).toHaveBeenCalled() - expect(atom.getActivePackage("package-with-module")).toBeUndefined() + expect(atom.isPackageActive("package-with-module")).toBeFalsy() it "absorbs exceptions that are thrown by the package module's serialize methods", -> spyOn(console, 'error') - atom.activatePackage('package-with-module', immediate: true) atom.activatePackage('package-with-serialize-error', immediate: true) + atom.activatePackage('package-with-serialization', immediate: true) atom.deactivatePackages() - expect(atom.packageStates['package-with-module']).toEqual someNumber: 1 expect(atom.packageStates['package-with-serialize-error']).toBeUndefined() + expect(atom.packageStates['package-with-serialization']).toEqual someNumber: 1 expect(console.error).toHaveBeenCalled() describe "texmate packages", -> diff --git a/spec/fixtures/packages/package-with-deactivate/index.coffee b/spec/fixtures/packages/package-with-deactivate/index.coffee new file mode 100644 index 000000000..65517bacd --- /dev/null +++ b/spec/fixtures/packages/package-with-deactivate/index.coffee @@ -0,0 +1,3 @@ +module.exports = + activate: -> + deactivate: -> From d37fbd43f1d8730151f711c0988a9ba3b38b9e96 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 11:21:44 -0600 Subject: [PATCH 25/79] Test that atom packages load their grammars --- spec/app/atom-package-spec.coffee | 10 ---------- spec/app/atom-spec.coffee | 6 ++++++ .../package-with-grammars/grammars/alittle.cson | 12 ++++++++++++ .../grammars/alot.cson | 0 4 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 spec/fixtures/packages/package-with-grammars/grammars/alittle.cson rename spec/fixtures/packages/{package-with-a-cson-grammar => package-with-grammars}/grammars/alot.cson (100%) diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee index 9a5c817da..0f17e4b90 100644 --- a/spec/app/atom-package-spec.coffee +++ b/spec/app/atom-package-spec.coffee @@ -56,16 +56,6 @@ describe "AtomPackage", -> expect(config.get('package-with-module.numbers.one')).toBe 1 expect(config.get('package-with-module.numbers.two')).toBe 2 - describe "when the package has a grammars directory", -> - it "loads the grammar and correctly parses a keyword", -> - spyOn(syntax, 'addGrammar') - atom.activatePackage("package-with-a-cson-grammar") - expect(syntax.addGrammar).toHaveBeenCalled() - grammar = syntax.addGrammar.argsForCall[0][0] - expect(grammar.scopeName).toBe "source.alot" - {tokens} = grammar.tokenizeLine("this is alot of code") - expect(tokens[1]).toEqual value: "alot", scopes: ["source.alot", "keyword.alot"] - describe "when the package has a scoped properties directory", -> it "loads the scoped properties", -> spyOn(syntax, 'addProperties') diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index e4ed8f38c..991916d1d 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -112,6 +112,12 @@ describe "the `atom` global", -> expect(stylesheetElementForId(three)).toExist() expect($('#jasmine-content').css('font-size')).toBe '3px' + describe "grammar loading", -> + it "loads the package's grammars", -> + atom.activatePackage('package-with-grammars') + expect(syntax.selectGrammar('a.alot').name).toBe 'Alot' + expect(syntax.selectGrammar('a.alittle').name).toBe 'Alittle' + describe "textmate packages", -> it "loads the package's grammars", -> expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" diff --git a/spec/fixtures/packages/package-with-grammars/grammars/alittle.cson b/spec/fixtures/packages/package-with-grammars/grammars/alittle.cson new file mode 100644 index 000000000..c72bea137 --- /dev/null +++ b/spec/fixtures/packages/package-with-grammars/grammars/alittle.cson @@ -0,0 +1,12 @@ +'fileTypes': ['alittle'] +'name': 'Alittle' +'scopeName': 'source.alittle' + +'patterns': [ + { + 'captures': + '0': + 'name': 'keyword.alittle' + 'match': 'alittle' + } +] diff --git a/spec/fixtures/packages/package-with-a-cson-grammar/grammars/alot.cson b/spec/fixtures/packages/package-with-grammars/grammars/alot.cson similarity index 100% rename from spec/fixtures/packages/package-with-a-cson-grammar/grammars/alot.cson rename to spec/fixtures/packages/package-with-grammars/grammars/alot.cson From c1954d869a05ebdad5b9ae8b974542617a9e4124 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 11:22:00 -0600 Subject: [PATCH 26/79] Add tests for TextMateGrammar@loadSync --- spec/app/text-mate-grammar-spec.coffee | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spec/app/text-mate-grammar-spec.coffee b/spec/app/text-mate-grammar-spec.coffee index b52f6451a..276a96496 100644 --- a/spec/app/text-mate-grammar-spec.coffee +++ b/spec/app/text-mate-grammar-spec.coffee @@ -14,6 +14,19 @@ describe "TextMateGrammar", -> atom.activatePackage('ruby.tmbundle', sync: true) grammar = syntax.selectGrammar("hello.coffee") + describe "@loadSync(path)", -> + it "loads grammars from plists", -> + grammar = TextMateGrammar.loadSync(fs.resolveOnLoadPath('packages/text.tmbundle/Syntaxes/Plain text.plist')) + expect(grammar.scopeName).toBe "text.plain" + {tokens} = grammar.tokenizeLine("this text is so plain. i love it.") + expect(tokens[0]).toEqual value: "this text is so plain. i love it.", scopes: ["text.plain", "meta.paragraph.text"] + + it "loads grammars from cson files", -> + grammar = TextMateGrammar.loadSync(fs.resolveOnLoadPath('package-with-grammars/grammars/alot.cson')) + expect(grammar.scopeName).toBe "source.alot" + {tokens} = grammar.tokenizeLine("this is alot of code") + expect(tokens[1]).toEqual value: "alot", scopes: ["source.alot", "keyword.alot"] + describe ".tokenizeLine(line, ruleStack)", -> describe "when the entire line matches a single pattern with no capture groups", -> it "returns a single token with the correct scope", -> From 772787121c9cc552c3afc2e377eb619f5e5a76af Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 11:25:09 -0600 Subject: [PATCH 27/79] Remove atom package grammars on deactivate --- spec/app/atom-spec.coffee | 6 ++++++ src/app/atom-package.coffee | 1 + 2 files changed, 7 insertions(+) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 991916d1d..c479f58b3 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -144,6 +144,12 @@ describe "the `atom` global", -> expect(atom.packageStates['package-with-serialization']).toEqual someNumber: 1 expect(console.error).toHaveBeenCalled() + it "removes the package's grammars", -> + atom.activatePackage('package-with-grammars') + atom.deactivatePackage('package-with-grammars') + expect(syntax.selectGrammar('a.alot').name).toBe 'Null Grammar' + expect(syntax.selectGrammar('a.alittle').name).toBe 'Null Grammar' + describe "texmate packages", -> it "removes the package's grammars", -> expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 75e9f52a6..dc27d70ac 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -97,6 +97,7 @@ class AtomPackage extends Package console.error "Error serializing package '#{@name}'", e.stack deactivate: -> + syntax.removeGrammar(grammar) for grammar in @grammars @mainModule?.deactivate?() requireMainModule: -> From 5410e9368fef33177a8880a68eaf87450f20eb72 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 11:56:45 -0600 Subject: [PATCH 28/79] Add ability to add/remove keymaps by name --- spec/app/keymap-spec.coffee | 21 ++++++++++++++++++++- src/app/binding-set.coffee | 3 ++- src/app/keymap.coffee | 29 ++++++++++++++++++++++++----- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/spec/app/keymap-spec.coffee b/spec/app/keymap-spec.coffee index b813ad50c..2e6e7a534 100644 --- a/spec/app/keymap-spec.coffee +++ b/spec/app/keymap-spec.coffee @@ -1,5 +1,6 @@ Keymap = require 'keymap' $ = require 'jquery' +{$$} = require 'space-pen' RootView = require 'root-view' describe "Keymap", -> @@ -234,7 +235,7 @@ describe "Keymap", -> it "returns false to prevent the browser from transferring focus", -> expect(keymap.handleKeyEvent(keydownEvent('U+0009', target: fragment[0]))).toBe false - describe ".bindKeys(selector, hash)", -> + describe ".bindKeys(selector, bindings)", -> it "normalizes the key patterns in the hash to put the modifiers in alphabetical order", -> fooHandler = jasmine.createSpy('fooHandler') fragment.on 'foo', fooHandler @@ -249,6 +250,24 @@ describe "Keymap", -> expect(result).toBe(false) expect(fooHandler).toHaveBeenCalled() + describe ".remove(name)", -> + it "removes the binding set with the given selector and bindings", -> + keymap.add 'nature', + '.green': + 'ctrl-c': 'cultivate' + '.brown': + 'ctrl-h': 'harvest' + + expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual { 'ctrl-c': 'cultivate' } + expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual { 'ctrl-h': 'harvest' } + + keymap.remove('nature') + + expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual {} + expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual {} + expect(keymap.bindingSetsByFirstKeystroke['ctrl-c']).toEqual [] + expect(keymap.bindingSetsByFirstKeystroke['ctrl-h']).toEqual [] + describe ".keystrokeStringForEvent(event)", -> describe "when no modifiers are pressed", -> it "returns a string that identifies the key pressed", -> diff --git a/src/app/binding-set.coffee b/src/app/binding-set.coffee index 5621ef9cb..3bf87dab8 100644 --- a/src/app/binding-set.coffee +++ b/src/app/binding-set.coffee @@ -14,8 +14,9 @@ class BindingSet commandsByKeystrokes: null commandForEvent: null parser: null + name: null - constructor: (@selector, commandsByKeystrokes, @index) -> + constructor: (@selector, commandsByKeystrokes, @index, @name) -> BindingSet.parser ?= PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs')) @specificity = Specificity(@selector) @commandsByKeystrokes = @normalizeCommandsByKeystrokes(commandsByKeystrokes) diff --git a/src/app/keymap.coffee b/src/app/keymap.coffee index ec260f417..068ccc606 100644 --- a/src/app/keymap.coffee +++ b/src/app/keymap.coffee @@ -40,20 +40,39 @@ class Keymap @load(filePath) for filePath in fs.list(directoryPath, ['.cson', '.json']) ? [] load: (path) -> - @add(CSON.readObject(path)) + @add(path, CSON.readObject(path)) - add: (keymap) -> + add: (args...) -> + name = args.shift() if args.length > 1 + keymap = args.shift() for selector, bindings of keymap - @bindKeys(selector, bindings) + @bindKeys(name, selector, bindings) - bindKeys: (selector, bindings) -> - bindingSet = new BindingSet(selector, bindings, @bindingSets.length) + remove: (name) -> + for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name) + _.remove(@bindingSets, bindingSet) + for keystrokes of bindingSet.commandsByKeystrokes + keystroke = keystrokes.split(' ')[0] + _.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet) + + bindKeys: (args...) -> + name = args.shift() if args.length > 2 + [selector, bindings] = args + bindingSet = new BindingSet(selector, bindings, @bindingSets.length, name) @bindingSets.unshift(bindingSet) for keystrokes of bindingSet.commandsByKeystrokes keystroke = keystrokes.split(' ')[0] # only index by first keystroke @bindingSetsByFirstKeystroke[keystroke] ?= [] @bindingSetsByFirstKeystroke[keystroke].push(bindingSet) + unbindKeys: (selector, bindings) -> + bindingSet = _.detect @bindingSets, (bindingSet) -> + bindingSet.selector is selector and bindingSet.bindings is bindings + + if bindingSet + console.log "binding set", bindingSet + _.remove(@bindingSets, bindingSet) + bindingsForElement: (element) -> keystrokeMap = {} currentNode = $(element) From 1e51750b6cec8b72dd33f865afc6a5a158feb15d Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:03:48 -0600 Subject: [PATCH 29/79] Remove a package's keymaps when it is deactivated --- spec/app/atom-spec.coffee | 6 ++++++ src/app/atom-package.coffee | 17 +++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index c479f58b3..33485475b 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -150,6 +150,12 @@ describe "the `atom` global", -> expect(syntax.selectGrammar('a.alot').name).toBe 'Null Grammar' expect(syntax.selectGrammar('a.alittle').name).toBe 'Null Grammar' + it "removes the package's keymaps", -> + atom.activatePackage('package-with-keymaps') + atom.deactivatePackage('package-with-keymaps') + expect(keymap.bindingsForElement($$ -> @div class: 'test-1')['ctrl-z']).toBeUndefined() + expect(keymap.bindingsForElement($$ -> @div class: 'test-2')['ctrl-z']).toBeUndefined() + describe "texmate packages", -> it "removes the package's grammars", -> expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index dc27d70ac..e50ec880b 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -32,7 +32,7 @@ class AtomPackage extends Package this activate: ({immediate}={}) -> - keymap.add(map) for map in @keymaps + keymap.add(path, map) for [path, map] in @keymaps applyStylesheet(path, content) for [path, content] in @stylesheets syntax.addGrammar(grammar) for grammar in @grammars @@ -55,21 +55,17 @@ class AtomPackage extends Package @metadata ?= {} loadKeymaps: -> - @keymaps = [] + @keymaps = @getKeymapPaths().map (path) -> [path, CSON.readObject(path)] + getKeymapPaths: -> keymapsDirPath = fsUtils.join(@path, 'keymaps') - keymapExtensions = ['cson', 'json', ''] - if @metadata.keymaps - for path in @metadata.keymaps - @keymaps.push(CSON.readObject(fsUtils.resolve(keymapsDirPath, path, keymapExtensions))) + @metadata.keymaps.map (name) -> fsUtils.resolve(keymapsDirPath, name, ['cson', 'json', '']) else - for path in fsUtils.list(keymapsDirPath, ['cson', 'json', '']) ? [] - @keymaps.push(CSON.readObject(path)) + fsUtils.list(keymapsDirPath, ['cson', 'json']) ? [] loadStylesheets: -> - @stylesheets = [] - @stylesheets.push([path, loadStylesheet(path)]) for path in @getStylesheetPaths() + @stylesheets = @getStylesheetPaths().map (path) -> [path, loadStylesheet(path)] getStylesheetPaths: -> stylesheetDirPath = fsUtils.join(@path, 'stylesheets') @@ -98,6 +94,7 @@ class AtomPackage extends Package deactivate: -> syntax.removeGrammar(grammar) for grammar in @grammars + keymap.remove(path) for [path] in @keymaps @mainModule?.deactivate?() requireMainModule: -> From 5d822b7305a7eb51cf0fa18235cf41ece605dd84 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:07:05 -0600 Subject: [PATCH 30/79] Remove a package's stylesheets when it is deactivated --- spec/app/atom-spec.coffee | 10 ++++++++++ src/app/atom-package.coffee | 1 + 2 files changed, 11 insertions(+) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 33485475b..04a8d6d17 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -156,6 +156,16 @@ describe "the `atom` global", -> expect(keymap.bindingsForElement($$ -> @div class: 'test-1')['ctrl-z']).toBeUndefined() expect(keymap.bindingsForElement($$ -> @div class: 'test-2')['ctrl-z']).toBeUndefined() + it "removes the package's stylesheets", -> + atom.activatePackage('package-with-stylesheets') + atom.deactivatePackage('package-with-stylesheets') + one = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/1.css") + two = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/2.less") + three = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/3.css") + expect(stylesheetElementForId(one)).not.toExist() + expect(stylesheetElementForId(two)).not.toExist() + expect(stylesheetElementForId(three)).not.toExist() + describe "texmate packages", -> it "removes the package's grammars", -> expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index e50ec880b..4820d94a0 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -95,6 +95,7 @@ class AtomPackage extends Package deactivate: -> syntax.removeGrammar(grammar) for grammar in @grammars keymap.remove(path) for [path] in @keymaps + removeStylesheet(path) for [path] in @stylesheets @mainModule?.deactivate?() requireMainModule: -> From c8b9622bf4f1660408ea32391d0615cefb0ebccb Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:12:47 -0600 Subject: [PATCH 31/79] Move specs for loading config defaults to atom-spec --- spec/app/atom-package-spec.coffee | 8 -------- spec/app/atom-spec.coffee | 6 ++++++ .../packages/package-with-config-defaults/index.coffee | 3 +++ .../packages/package-with-serialization/index.coffee | 3 --- 4 files changed, 9 insertions(+), 11 deletions(-) create mode 100644 spec/fixtures/packages/package-with-config-defaults/index.coffee diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee index 0f17e4b90..fdf298f51 100644 --- a/spec/app/atom-package-spec.coffee +++ b/spec/app/atom-package-spec.coffee @@ -48,14 +48,6 @@ describe "AtomPackage", -> expect(eventHandler.callCount).toBe 2 expect(packageMainModule.activate.callCount).toBe 1 - - describe "when a package is activated", -> - it "loads config defaults based on the `configDefaults` key", -> - expect(config.get('package-with-module.numbers.one')).toBeUndefined() - atom.activatePackage("package-with-module") - expect(config.get('package-with-module.numbers.one')).toBe 1 - expect(config.get('package-with-module.numbers.two')).toBe 2 - describe "when the package has a scoped properties directory", -> it "loads the scoped properties", -> spyOn(syntax, 'addProperties') diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 04a8d6d17..40c450a1d 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -27,6 +27,12 @@ describe "the `atom` global", -> expect(indexModule.activate).toHaveBeenCalled() expect(pack.mainModule).toBe indexModule + it "assigns config defaults from the module", -> + expect(config.get('package-with-config-defaults.numbers.one')).toBeUndefined() + atom.activatePackage('package-with-config-defaults') + expect(config.get('package-with-config-defaults.numbers.one')).toBe 1 + expect(config.get('package-with-config-defaults.numbers.two')).toBe 2 + describe "when the package has no main module", -> it "does not throw an exception", -> spyOn(console, "error") diff --git a/spec/fixtures/packages/package-with-config-defaults/index.coffee b/spec/fixtures/packages/package-with-config-defaults/index.coffee new file mode 100644 index 000000000..5e0b1eed6 --- /dev/null +++ b/spec/fixtures/packages/package-with-config-defaults/index.coffee @@ -0,0 +1,3 @@ +module.exports = + configDefaults: + numbers: { one: 1, two: 2 } diff --git a/spec/fixtures/packages/package-with-serialization/index.coffee b/spec/fixtures/packages/package-with-serialization/index.coffee index 3756508da..54949113c 100644 --- a/spec/fixtures/packages/package-with-serialization/index.coffee +++ b/spec/fixtures/packages/package-with-serialization/index.coffee @@ -1,7 +1,4 @@ module.exports = - configDefaults: - numbers: { one: 1, two: 2 } - activate: ({@someNumber}) -> @someNumber ?= 1 From 3c561ef20803b5d4bd7ef9a1a324f5211be430c9 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:12:53 -0600 Subject: [PATCH 32/79] :lipstick: --- spec/app/atom-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 40c450a1d..c87e7a34a 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -103,7 +103,7 @@ describe "the `atom` global", -> expect(stylesheetElementForId(three)).not.toExist() expect($('#jasmine-content').css('font-size')).toBe '1px' - describe "when the metadata does not contains a 'stylesheets' manifest", -> + describe "when the metadata does not contain a 'stylesheets' manifest", -> it "loads all stylesheets from the stylesheets directory", -> one = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/1.css") two = fs.resolveOnLoadPath("package-with-stylesheets/stylesheets/2.less") From 368e10a9f50ded7cf65dab01e95a9b56232612e0 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:17:05 -0600 Subject: [PATCH 33/79] Move spec for scoped property loading to atom-spec --- spec/app/atom-package-spec.coffee | 10 ---------- spec/app/atom-spec.coffee | 5 +++++ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee index fdf298f51..d68359219 100644 --- a/spec/app/atom-package-spec.coffee +++ b/spec/app/atom-package-spec.coffee @@ -47,13 +47,3 @@ describe "AtomPackage", -> expect(packageMainModule.activationEventCallCount).toBe 2 expect(eventHandler.callCount).toBe 2 expect(packageMainModule.activate.callCount).toBe 1 - - describe "when the package has a scoped properties directory", -> - it "loads the scoped properties", -> - spyOn(syntax, 'addProperties') - atom.activatePackage("package-with-scoped-properties") - - expect(syntax.addProperties).toHaveBeenCalled() - [selector, properties] = syntax.addProperties.argsForCall[0] - expect(selector).toBe ".source.omg" - expect(properties).toEqual {editor: increaseIndentPattern: '^a'} diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index c87e7a34a..2bb8af19f 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -124,6 +124,11 @@ describe "the `atom` global", -> expect(syntax.selectGrammar('a.alot').name).toBe 'Alot' expect(syntax.selectGrammar('a.alittle').name).toBe 'Alittle' + describe "scoped-property loading", -> + it "loads the scoped properties", -> + atom.activatePackage("package-with-scoped-properties") + expect(syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a' + describe "textmate packages", -> it "loads the package's grammars", -> expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" From c8ec73d2f03147df51edb8eba67a71b48ee77c7e Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:45:19 -0600 Subject: [PATCH 34/79] Allow scoped-properties to be added/removed by name Also: - remove "global" properties - clear scoped properties between specs --- spec/app/syntax-spec.coffee | 12 ++++++++++-- spec/spec-helper.coffee | 1 + src/app/syntax.coffee | 31 ++++++++++++++++++------------- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/spec/app/syntax-spec.coffee b/spec/app/syntax-spec.coffee index 01da46baa..ad12bee71 100644 --- a/spec/app/syntax-spec.coffee +++ b/spec/app/syntax-spec.coffee @@ -68,12 +68,11 @@ describe "the `syntax` global", -> syntax.addProperties(".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42) syntax.addProperties(".source .string.quoted.double", foo: bar: baz: 22) syntax.addProperties(".source", foo: bar: baz: 11) - syntax.addProperties(foo: bar: baz: 1) expect(syntax.getProperty([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42 expect(syntax.getProperty([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBe 22 expect(syntax.getProperty([".source.js", ".variable.assignment.js"], "foo.bar.baz")).toBe 11 - expect(syntax.getProperty([".text"], "foo.bar.baz")).toBe 1 + expect(syntax.getProperty([".text"], "foo.bar.baz")).toBeUndefined() it "favors the most recently added properties in the event of a specificity tie", -> syntax.addProperties(".source.coffee .string.quoted.single", foo: bar: baz: 42) @@ -81,3 +80,12 @@ describe "the `syntax` global", -> expect(syntax.getProperty([".source.coffee", ".string.quoted.single"], "foo.bar.baz")).toBe 42 expect(syntax.getProperty([".source.coffee", ".string.quoted.single.double"], "foo.bar.baz")).toBe 22 + + describe ".removeProperties(name)", -> + it "allows properties to be removed by name", -> + syntax.addProperties("a", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42) + syntax.addProperties("b", ".source .string.quoted.double", foo: bar: baz: 22) + + syntax.removeProperties("b") + expect(syntax.getProperty([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBeUndefined() + expect(syntax.getProperty([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42 diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 2bef64dc2..65a1b85dd 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -42,6 +42,7 @@ beforeEach -> spyOn(atom, 'getSavedWindowState').andReturn(null) $native.setWindowState('') syntax.clearGrammarOverrides() + syntax.clearProperties() # used to reset keymap after each spec bindingSetsToRestore = _.clone(keymap.bindingSets) diff --git a/src/app/syntax.coffee b/src/app/syntax.coffee index fe15047aa..7ab711a14 100644 --- a/src/app/syntax.coffee +++ b/src/app/syntax.coffee @@ -22,7 +22,6 @@ class Syntax @grammarsByFileType = {} @grammarsByScopeName = {} @grammarOverridesByPath = {} - @globalProperties = {} @scopedPropertiesIndex = 0 @scopedProperties = [] @nullGrammar = new NullGrammar @@ -101,18 +100,24 @@ class Syntax @grammarsByScopeName[scopeName] addProperties: (args...) -> - selector = args.shift() if args.length > 1 - properties = args.shift() + name = args.shift() if args.length > 2 + [selector, properties] = args - if selector - @scopedProperties.unshift( - selector: selector, - properties: properties, - specificity: Specificity(selector), - index: @scopedPropertiesIndex++ - ) - else - _.extend(@globalProperties, properties) + @scopedProperties.unshift( + name: name + selector: selector, + properties: properties, + specificity: Specificity(selector), + index: @scopedPropertiesIndex++ + ) + + removeProperties: (name) -> + for properties in @scopedProperties.filter((properties) -> properties.name is name) + _.remove(@scopedProperties, properties) + + clearProperties: -> + @scopedProperties = [] + @scopedPropertiesIndex = 0 getProperty: (scope, keyPath) -> for object in @propertiesForScope(scope, keyPath) @@ -128,7 +133,7 @@ class Syntax while element matchingProperties.push(@matchingPropertiesForElement(element, candidates)...) element = element.parentNode - matchingProperties.concat([@globalProperties]) + matchingProperties matchingPropertiesForElement: (element, candidates) -> matchingScopedProperties = candidates.filter ({selector}) -> From 81d4b764b8cce340b538e2b6328f6b4e3366de40 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 12:49:48 -0600 Subject: [PATCH 35/79] Remove a package's scoped-properties when it is deactivated Also: don't add the properties until `activate` is called. Previously we were still adding the properties in the `load` method, which was wrong. --- spec/app/atom-spec.coffee | 6 ++++++ src/app/atom-package.coffee | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 2bb8af19f..bc05d7408 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -177,6 +177,12 @@ describe "the `atom` global", -> expect(stylesheetElementForId(two)).not.toExist() expect(stylesheetElementForId(three)).not.toExist() + it "removes the package's scoped-properties", -> + atom.activatePackage("package-with-scoped-properties") + expect(syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a' + atom.deactivatePackage("package-with-scoped-properties") + expect(syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBeUndefined() + describe "texmate packages", -> it "removes the package's grammars", -> expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 4820d94a0..6adf60953 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -11,6 +11,7 @@ class AtomPackage extends Package keymaps: null stylesheets: null grammars: null + scopedProperties: null mainModulePath: null resolvedMainModulePath: false mainModule: null @@ -35,6 +36,7 @@ class AtomPackage extends Package keymap.add(path, map) for [path, map] in @keymaps applyStylesheet(path, content) for [path, content] in @stylesheets syntax.addGrammar(grammar) for grammar in @grammars + syntax.addProperties(path, selector, properties) for [path, selector, properties] in @scopedProperties if @deferActivation and not immediate @subscribeToActivationEvents() @@ -81,10 +83,11 @@ class AtomPackage extends Package @grammars.push(TextMateGrammar.loadSync(grammarPath)) loadScopedProperties: -> + @scopedProperties = [] scopedPropertiessDirPath = fsUtils.join(@path, 'scoped-properties') for scopedPropertiesPath in fsUtils.list(scopedPropertiessDirPath, ['.cson', '.json']) ? [] for selector, properties of fsUtils.readObject(scopedPropertiesPath) - syntax.addProperties(selector, properties) + @scopedProperties.push([scopedPropertiesPath, selector, properties]) serialize: -> try @@ -94,6 +97,7 @@ class AtomPackage extends Package deactivate: -> syntax.removeGrammar(grammar) for grammar in @grammars + syntax.removeProperties(path) for [path] in @scopedProperties keymap.remove(path) for [path] in @keymaps removeStylesheet(path) for [path] in @stylesheets @mainModule?.deactivate?() From 2ac3af193b04471e565ce7cb00ef9a0d2a2c2cff Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 15:42:13 -0600 Subject: [PATCH 36/79] Clean up deferred package activation - Eliminate @deferActivation ivar - Remove activation event listeners when deactivating unactivated packages --- src/app/atom-package.coffee | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 6adf60953..c7f5cfeb3 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -15,7 +15,6 @@ class AtomPackage extends Package mainModulePath: null resolvedMainModulePath: false mainModule: null - deferActivation: false load: -> try @@ -24,7 +23,7 @@ class AtomPackage extends Package @loadStylesheets() @loadGrammars() @loadScopedProperties() - if @deferActivation = @metadata.activationEvents? + if @metadata.activationEvents? @registerDeferredDeserializers() else @requireMainModule() @@ -38,7 +37,7 @@ class AtomPackage extends Package syntax.addGrammar(grammar) for grammar in @grammars syntax.addProperties(path, selector, properties) for [path, selector, properties] in @scopedProperties - if @deferActivation and not immediate + if @metadata.activationEvents? and not immediate @subscribeToActivationEvents() else @activateNow() @@ -96,6 +95,7 @@ class AtomPackage extends Package console.error "Error serializing package '#{@name}'", e.stack deactivate: -> + @unsubscribeFromActivationEvents() syntax.removeGrammar(grammar) for grammar in @grammars syntax.removeProperties(path) for [path] in @scopedProperties keymap.remove(path) for [path] in @keymaps @@ -123,25 +123,23 @@ class AtomPackage extends Package subscribeToActivationEvents: () -> return unless @metadata.activationEvents? - - activateHandler = (event) => - bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event) - @deferActivation = false - @activateNow() - $(event.target).trigger(event) - @restoreEventHandlersOnBubblePath(bubblePathEventHandlers) - @unsubscribeFromActivationEvents(activateHandler) - if _.isArray(@metadata.activationEvents) - rootView.command(event, activateHandler) for event in @metadata.activationEvents + rootView.command(event, @handleActivationEvent) for event in @metadata.activationEvents else - rootView.command(event, selector, activateHandler) for event, selector of @metadata.activationEvents + rootView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents - unsubscribeFromActivationEvents: (activateHandler) -> + handleActivationEvent: (event) => + bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event) + @activateNow() + $(event.target).trigger(event) + @restoreEventHandlersOnBubblePath(bubblePathEventHandlers) + @unsubscribeFromActivationEvents() + + unsubscribeFromActivationEvents: -> if _.isArray(@metadata.activationEvents) - rootView.off(event, activateHandler) for event in @metadata.activationEvents + rootView.off(event, @handleActivationEvent) for event in @metadata.activationEvents else - rootView.off(event, selector, activateHandler) for event, selector of @metadata.activationEvents + rootView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents disableEventHandlersOnBubblePath: (event) -> bubblePathEventHandlers = [] From 2fe057bd9bd498447858a89a441b772e0fb8340a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 15:42:58 -0600 Subject: [PATCH 37/79] Move deferred activation specs to atom-spec --- spec/app/atom-package-spec.coffee | 29 ------------------- spec/app/atom-spec.coffee | 28 ++++++++++++++++++ .../{main.coffee => index.coffee} | 4 +-- .../package.cson | 1 - 4 files changed, 29 insertions(+), 33 deletions(-) rename spec/fixtures/packages/package-with-activation-events/{main.coffee => index.coffee} (86%) diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee index d68359219..2f6c25061 100644 --- a/spec/app/atom-package-spec.coffee +++ b/spec/app/atom-package-spec.coffee @@ -18,32 +18,3 @@ describe "AtomPackage", -> expect(object.data).toBe 'Hello' expect(pack.mainModule).toBeDefined() expect(pack.mainModule.activateCallCount).toBe 0 - - describe ".activate()", -> - beforeEach -> - window.rootView = new RootView - packageMainModule = require 'fixtures/packages/package-with-activation-events/main' - spyOn(packageMainModule, 'activate').andCallThrough() - - describe "when the package metadata includes activation events", -> - beforeEach -> - pack.activate() - - it "defers activating the package until an activation event bubbles to the root view", -> - expect(packageMainModule.activate).not.toHaveBeenCalled() - rootView.trigger 'activation-event' - expect(packageMainModule.activate).toHaveBeenCalled() - - it "triggers the activation event on all handlers registered during activation", -> - rootView.open('sample.js') - editor = rootView.getActiveView() - eventHandler = jasmine.createSpy("activation-event") - editor.command 'activation-event', eventHandler - editor.trigger 'activation-event' - expect(packageMainModule.activate.callCount).toBe 1 - expect(packageMainModule.activationEventCallCount).toBe 1 - expect(eventHandler.callCount).toBe 1 - editor.trigger 'activation-event' - expect(packageMainModule.activationEventCallCount).toBe 2 - expect(eventHandler.callCount).toBe 2 - expect(packageMainModule.activate.callCount).toBe 1 diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index bc05d7408..6680d2631 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -33,6 +33,34 @@ describe "the `atom` global", -> expect(config.get('package-with-config-defaults.numbers.one')).toBe 1 expect(config.get('package-with-config-defaults.numbers.two')).toBe 2 + describe "when the package metadata includes activation events", -> + [mainModule, pack] = [] + + beforeEach -> + mainModule = require 'package-with-activation-events/index' + spyOn(mainModule, 'activate').andCallThrough() + pack = atom.activatePackage('package-with-activation-events') + + it "defers requiring/activating the main module until an activation event bubbles to the root view", -> + expect(pack.mainModule).toBeNull() + expect(mainModule.activate).not.toHaveBeenCalled() + rootView.trigger 'activation-event' + expect(mainModule.activate).toHaveBeenCalled() + + it "triggers the activation event on all handlers registered during activation", -> + rootView.open() + editor = rootView.getActiveView() + eventHandler = jasmine.createSpy("activation-event") + editor.command 'activation-event', eventHandler + editor.trigger 'activation-event' + expect(mainModule.activate.callCount).toBe 1 + expect(mainModule.activationEventCallCount).toBe 1 + expect(eventHandler.callCount).toBe 1 + editor.trigger 'activation-event' + expect(mainModule.activationEventCallCount).toBe 2 + expect(eventHandler.callCount).toBe 2 + expect(mainModule.activate.callCount).toBe 1 + describe "when the package has no main module", -> it "does not throw an exception", -> spyOn(console, "error") diff --git a/spec/fixtures/packages/package-with-activation-events/main.coffee b/spec/fixtures/packages/package-with-activation-events/index.coffee similarity index 86% rename from spec/fixtures/packages/package-with-activation-events/main.coffee rename to spec/fixtures/packages/package-with-activation-events/index.coffee index d57ca7c24..91f2230b1 100644 --- a/spec/fixtures/packages/package-with-activation-events/main.coffee +++ b/spec/fixtures/packages/package-with-activation-events/index.coffee @@ -10,7 +10,5 @@ module.exports = activate: -> @activateCallCount++ rootView.getActiveView()?.command 'activation-event', => + console.log "ACTIVATION EVENT" @activationEventCallCount++ - - serialize: -> - previousData: 'overwritten' diff --git a/spec/fixtures/packages/package-with-activation-events/package.cson b/spec/fixtures/packages/package-with-activation-events/package.cson index 42d3eb78d..45d8dfea1 100644 --- a/spec/fixtures/packages/package-with-activation-events/package.cson +++ b/spec/fixtures/packages/package-with-activation-events/package.cson @@ -1,3 +1,2 @@ 'activationEvents': ['activation-event'] 'deferredDeserializers': ['Foo'] -'main': 'main' From a07cd87c2c540f4dc5f3ca3fb47a5228476ea6a4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 15:46:19 -0600 Subject: [PATCH 38/79] Move testing of deferred deserializers to atom-spec --- spec/app/atom-package-spec.coffee | 20 -------------------- spec/app/atom-spec.coffee | 10 ++++++++++ 2 files changed, 10 insertions(+), 20 deletions(-) delete mode 100644 spec/app/atom-package-spec.coffee diff --git a/spec/app/atom-package-spec.coffee b/spec/app/atom-package-spec.coffee deleted file mode 100644 index 2f6c25061..000000000 --- a/spec/app/atom-package-spec.coffee +++ /dev/null @@ -1,20 +0,0 @@ -RootView = require 'root-view' -AtomPackage = require 'atom-package' -fs = require 'fs-utils' - -describe "AtomPackage", -> - [packageMainModule, pack] = [] - - beforeEach -> - pack = new AtomPackage(fs.resolve(config.packageDirPaths..., 'package-with-activation-events')) - pack.load() - - describe ".load()", -> - describe "if the package's metadata has a `deferredDeserializers` array", -> - it "requires the package's main module attempting to use deserializers named in the array", -> - expect(pack.mainModule).toBeNull() - object = deserialize(deserializer: 'Foo', data: "Hello") - expect(object.constructor.name).toBe 'Foo' - expect(object.data).toBe 'Hello' - expect(pack.mainModule).toBeDefined() - expect(pack.mainModule.activateCallCount).toBe 0 diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 6680d2631..06a0a6dca 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -8,6 +8,16 @@ describe "the `atom` global", -> window.rootView = new RootView describe "package lifecycle methods", -> + describe ".loadPackage(id)", -> + describe "when the package has deferred deserializers", -> + it "requires the package's main module if one of its deferred deserializers is referenced", -> + pack = atom.loadPackage('package-with-activation-events') + expect(pack.mainModule).toBeNull() + object = deserialize({deserializer: 'Foo', data: 5}) + expect(pack.mainModule).toBeDefined() + expect(object.constructor.name).toBe 'Foo' + expect(object.data).toBe 5 + describe ".activatePackage(id)", -> describe "atom packages", -> describe "when the package has a main module", -> From 1f74b5ccb4f1a0aa878e76a13c83a78195d80e4e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 15:52:51 -0600 Subject: [PATCH 39/79] Rename textmate package w/ invalid snippets --- .../Snippets/.hidden-file | 0 .../Snippets/invalid.plist | 0 src/packages/snippets/spec/snippets-spec.coffee | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename spec/fixtures/packages/{textmate-package.tmbundle => package-with-broken-snippets.tmbundle}/Snippets/.hidden-file (100%) rename spec/fixtures/packages/{textmate-package.tmbundle => package-with-broken-snippets.tmbundle}/Snippets/invalid.plist (100%) diff --git a/spec/fixtures/packages/textmate-package.tmbundle/Snippets/.hidden-file b/spec/fixtures/packages/package-with-broken-snippets.tmbundle/Snippets/.hidden-file similarity index 100% rename from spec/fixtures/packages/textmate-package.tmbundle/Snippets/.hidden-file rename to spec/fixtures/packages/package-with-broken-snippets.tmbundle/Snippets/.hidden-file diff --git a/spec/fixtures/packages/textmate-package.tmbundle/Snippets/invalid.plist b/spec/fixtures/packages/package-with-broken-snippets.tmbundle/Snippets/invalid.plist similarity index 100% rename from spec/fixtures/packages/textmate-package.tmbundle/Snippets/invalid.plist rename to spec/fixtures/packages/package-with-broken-snippets.tmbundle/Snippets/invalid.plist diff --git a/src/packages/snippets/spec/snippets-spec.coffee b/src/packages/snippets/spec/snippets-spec.coffee index 5e2f2c74e..2236757e7 100644 --- a/src/packages/snippets/spec/snippets-spec.coffee +++ b/src/packages/snippets/spec/snippets-spec.coffee @@ -236,7 +236,7 @@ describe "Snippets extension", -> describe "snippet loading", -> beforeEach -> - atom.loadPackage('textmate-package.tmbundle', sync: true) + atom.loadPackage('package-with-broken-snippets.tmbundle', sync: true) atom.loadPackage('package-with-snippets') jasmine.unspy(window, "setTimeout") From d8b4beb8bd1a53e3ee9bd640a2f4b1871452a6e0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 16:59:42 -0600 Subject: [PATCH 40/79] Now that we remove binding sets, track binding set indices explicitly Previously we relied on the length of the binding sets, but now that we remove them the length is not a strictly increasing number. This could cause problem when using the index to break specificity ties. --- src/app/keymap.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/keymap.coffee b/src/app/keymap.coffee index 068ccc606..71be30cec 100644 --- a/src/app/keymap.coffee +++ b/src/app/keymap.coffee @@ -8,6 +8,7 @@ BindingSet = require 'binding-set' module.exports = class Keymap bindingSets: null + nextBindingSetIndex: 0 bindingSetsByFirstKeystroke: null queuedKeystrokes: null @@ -58,7 +59,7 @@ class Keymap bindKeys: (args...) -> name = args.shift() if args.length > 2 [selector, bindings] = args - bindingSet = new BindingSet(selector, bindings, @bindingSets.length, name) + bindingSet = new BindingSet(selector, bindings, @nextBindingSetIndex++, name) @bindingSets.unshift(bindingSet) for keystrokes of bindingSet.commandsByKeystrokes keystroke = keystrokes.split(' ')[0] # only index by first keystroke From e32d7b1ff1128c9338fc1813cfef7039d507a6aa Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 17:02:09 -0600 Subject: [PATCH 41/79] Remove unused test.tmbundle --- ...Disable Indention Correction.tmPreferences | 19 ------ .../Preferences/Markup style: Bold.plist | 17 ----- .../Preferences/Markup style: Italic.plist | 17 ----- .../Preferences/Markup style: Underline.plist | 17 ----- .../Preferences/Miscellaneous.plist | 65 ------------------- .../Preferences/Spell checking.plist | 17 ----- .../Style: Numbered List.tmPreferences | 22 ------- .../Preferences/Style: Raw.tmPreferences | 17 ----- .../Style: Unnumbered List.tmPreferences | 22 ------- .../test.tmbundle/Preferences/empty.plist | 0 .../Snippets/010 Copyright.plist | 14 ---- .../Snippets/Conitnue bullet.plist | 17 ----- .../Snippets/Conitnue light bullet.plist | 17 ----- .../Snippets/Conitnue star bullet.plist | 17 ----- .../Snippets/Insert ISO date.plist | 14 ---- .../test.tmbundle/Snippets/Lorem ipsum.plist | 14 ---- .../test.tmbundle/Syntaxes/Empty.plist | 0 .../test.tmbundle/Syntaxes/Test.plist | 35 ---------- 18 files changed, 341 deletions(-) delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Disable Indention Correction.tmPreferences delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Markup style: Bold.plist delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Markup style: Italic.plist delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Markup style: Underline.plist delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Miscellaneous.plist delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Spell checking.plist delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Style: Numbered List.tmPreferences delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Style: Raw.tmPreferences delete mode 100644 spec/fixtures/test.tmbundle/Preferences/Style: Unnumbered List.tmPreferences delete mode 100644 spec/fixtures/test.tmbundle/Preferences/empty.plist delete mode 100644 spec/fixtures/test.tmbundle/Snippets/010 Copyright.plist delete mode 100644 spec/fixtures/test.tmbundle/Snippets/Conitnue bullet.plist delete mode 100644 spec/fixtures/test.tmbundle/Snippets/Conitnue light bullet.plist delete mode 100644 spec/fixtures/test.tmbundle/Snippets/Conitnue star bullet.plist delete mode 100644 spec/fixtures/test.tmbundle/Snippets/Insert ISO date.plist delete mode 100644 spec/fixtures/test.tmbundle/Snippets/Lorem ipsum.plist delete mode 100644 spec/fixtures/test.tmbundle/Syntaxes/Empty.plist delete mode 100644 spec/fixtures/test.tmbundle/Syntaxes/Test.plist diff --git a/spec/fixtures/test.tmbundle/Preferences/Disable Indention Correction.tmPreferences b/spec/fixtures/test.tmbundle/Preferences/Disable Indention Correction.tmPreferences deleted file mode 100644 index 63c91ab3f..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Disable Indention Correction.tmPreferences +++ /dev/null @@ -1,19 +0,0 @@ - - - - - name - Disable Indention Correction - scope - text - text source - settings - - disableIndentCorrections - 1 - indentOnPaste - simple - - uuid - 29B976F9-853F-43FF-AA50-7A6A518EDC81 - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Markup style: Bold.plist b/spec/fixtures/test.tmbundle/Preferences/Markup style: Bold.plist deleted file mode 100644 index 5a63bd8b7..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Markup style: Bold.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - name - Style: Bold - scope - markup.bold - settings - - bold - 1 - - uuid - A088E2CA-03E7-4A8C-855C-AC954E739D6D - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Markup style: Italic.plist b/spec/fixtures/test.tmbundle/Preferences/Markup style: Italic.plist deleted file mode 100644 index 9ea3216d3..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Markup style: Italic.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - name - Style: Italic - scope - markup.italic - settings - - italic - 1 - - uuid - 2EE6D01F-50BC-434B-BE45-54D29CACB3E0 - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Markup style: Underline.plist b/spec/fixtures/test.tmbundle/Preferences/Markup style: Underline.plist deleted file mode 100644 index 11a01ca40..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Markup style: Underline.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - name - Style: Underline - scope - markup.underline - settings - - underline - 1 - - uuid - 4CCD8369-40E4-422A-ABE7-C32F3721AFEF - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Miscellaneous.plist b/spec/fixtures/test.tmbundle/Preferences/Miscellaneous.plist deleted file mode 100644 index 04ffaf9d8..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Miscellaneous.plist +++ /dev/null @@ -1,65 +0,0 @@ - - - - - name - Miscellaneous - settings - - highlightPairs - - - ( - ) - - - { - } - - - [ - ] - - - - - - - - - - - smartTypingPairs - - - " - " - - - ( - ) - - - { - } - - - [ - ] - - - - - - - - - - - unIndentedLinePattern - ^\s*$ - - uuid - 3E8C2307-8175-4A58-BE07-785713D5837A - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Spell checking.plist b/spec/fixtures/test.tmbundle/Preferences/Spell checking.plist deleted file mode 100644 index 3ef7e991a..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Spell checking.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - name - Spell Checking: Disable - scope - markup.underline.link, markup.raw - settings - - spellChecking - 0 - - uuid - 613405D5-67B6-4281-94C9-9148E54C66FB - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Style: Numbered List.tmPreferences b/spec/fixtures/test.tmbundle/Preferences/Style: Numbered List.tmPreferences deleted file mode 100644 index d42f54a77..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Style: Numbered List.tmPreferences +++ /dev/null @@ -1,22 +0,0 @@ - - - - - name - Style: Numbered List - scope - markup.list.numbered - settings - - indentedSoftWrap - - format - ${0/\S/ /g} - match - \A\s*((\d+\.|[-*]|#+)\s+|(?=\w)) - - - uuid - EEDAA012-BFBD-4FE8-9253-4EDC5F7309F1 - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Style: Raw.tmPreferences b/spec/fixtures/test.tmbundle/Preferences/Style: Raw.tmPreferences deleted file mode 100644 index 0cfde4b08..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Style: Raw.tmPreferences +++ /dev/null @@ -1,17 +0,0 @@ - - - - - name - Style: Raw - scope - markup.raw.block - settings - - softWrap - - - uuid - 47A88FB7-A084-48F6-9B54-078E9C888BE6 - - diff --git a/spec/fixtures/test.tmbundle/Preferences/Style: Unnumbered List.tmPreferences b/spec/fixtures/test.tmbundle/Preferences/Style: Unnumbered List.tmPreferences deleted file mode 100644 index 1c92881fd..000000000 --- a/spec/fixtures/test.tmbundle/Preferences/Style: Unnumbered List.tmPreferences +++ /dev/null @@ -1,22 +0,0 @@ - - - - - name - Style: Unnumbered List - scope - markup.list.unnumbered - settings - - indentedSoftWrap - - format - ${0/\S/ /g} - match - \A\s*[-*]\s+ - - - uuid - 93CBCCEB-32BE-41F3-9F00-B975831F33EC - - diff --git a/spec/fixtures/test.tmbundle/Preferences/empty.plist b/spec/fixtures/test.tmbundle/Preferences/empty.plist deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/test.tmbundle/Snippets/010 Copyright.plist b/spec/fixtures/test.tmbundle/Snippets/010 Copyright.plist deleted file mode 100644 index 3d43183c1..000000000 --- a/spec/fixtures/test.tmbundle/Snippets/010 Copyright.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - content - (c) Copyright `date +%Y` $TM_FULLNAME. All Rights Reserved. - name - Copyright Notice - tabTrigger - c) - uuid - BC8B89E4-5F16-11D9-B9C3-000D93589AF6 - - diff --git a/spec/fixtures/test.tmbundle/Snippets/Conitnue bullet.plist b/spec/fixtures/test.tmbundle/Snippets/Conitnue bullet.plist deleted file mode 100644 index 4704f7906..000000000 --- a/spec/fixtures/test.tmbundle/Snippets/Conitnue bullet.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - content - -• - keyEquivalent -  - name - Continue Bullet - scope - meta.bullet-point - uuid - C30BA263-B10E-11D9-9975-000D93589AF6 - - diff --git a/spec/fixtures/test.tmbundle/Snippets/Conitnue light bullet.plist b/spec/fixtures/test.tmbundle/Snippets/Conitnue light bullet.plist deleted file mode 100644 index 2c0cd2a80..000000000 --- a/spec/fixtures/test.tmbundle/Snippets/Conitnue light bullet.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - content - - keyEquivalent -  - name - Continue Light Bullet - scope - meta.bullet-point.light - uuid - EA149DAB-B10E-11D9-9975-000D93589AF6 - - diff --git a/spec/fixtures/test.tmbundle/Snippets/Conitnue star bullet.plist b/spec/fixtures/test.tmbundle/Snippets/Conitnue star bullet.plist deleted file mode 100644 index 81dc40471..000000000 --- a/spec/fixtures/test.tmbundle/Snippets/Conitnue star bullet.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - content - -* - keyEquivalent -  - name - Continue Star Bullet - scope - meta.bullet-point.star - uuid - B5E22191-B151-11D9-85C9-000D93589AF6 - - diff --git a/spec/fixtures/test.tmbundle/Snippets/Insert ISO date.plist b/spec/fixtures/test.tmbundle/Snippets/Insert ISO date.plist deleted file mode 100644 index c2b2f79b8..000000000 --- a/spec/fixtures/test.tmbundle/Snippets/Insert ISO date.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - content - `date +%Y-%m-%d` - name - Current Date — YYYY-MM-DD - tabTrigger - isoD - uuid - C9CAF012-6E50-11D9-AA12-000D93589AF6 - - diff --git a/spec/fixtures/test.tmbundle/Snippets/Lorem ipsum.plist b/spec/fixtures/test.tmbundle/Snippets/Lorem ipsum.plist deleted file mode 100644 index a30cff0d4..000000000 --- a/spec/fixtures/test.tmbundle/Snippets/Lorem ipsum.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - content - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - name - Lorem ipsum - tabTrigger - lorem - uuid - BA9A2B17-DA89-49A5-809B-AC7510C24625 - - diff --git a/spec/fixtures/test.tmbundle/Syntaxes/Empty.plist b/spec/fixtures/test.tmbundle/Syntaxes/Empty.plist deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/test.tmbundle/Syntaxes/Test.plist b/spec/fixtures/test.tmbundle/Syntaxes/Test.plist deleted file mode 100644 index 315d4ce16..000000000 --- a/spec/fixtures/test.tmbundle/Syntaxes/Test.plist +++ /dev/null @@ -1,35 +0,0 @@ - - - - - fileTypes - - .testo - - keyEquivalent - ^~P - name - Test - patterns - - - captures - - 1 - - name - punctuation.definition.item.text - - - match - ^\s*//.*$\n? - name - comment - - - scopeName - text.test - uuid - 313DD4FA-B10E-11D9-9F75-000D93589AF6 - - From eef13e7db80d6aae3007ef1934d2e63e9a92417a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 17:20:16 -0600 Subject: [PATCH 42/79] Test that deferred packages don't require their main module As opposed to asserting that the main module isn't present, which might not be true if a previous spec required it. --- spec/app/atom-spec.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 06a0a6dca..291a71187 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -49,10 +49,12 @@ describe "the `atom` global", -> beforeEach -> mainModule = require 'package-with-activation-events/index' spyOn(mainModule, 'activate').andCallThrough() + AtomPackage = require 'atom-package' + spyOn(AtomPackage.prototype, 'requireMainModule').andCallThrough() pack = atom.activatePackage('package-with-activation-events') it "defers requiring/activating the main module until an activation event bubbles to the root view", -> - expect(pack.mainModule).toBeNull() + expect(pack.requireMainModule).not.toHaveBeenCalled() expect(mainModule.activate).not.toHaveBeenCalled() rootView.trigger 'activation-event' expect(mainModule.activate).toHaveBeenCalled() From 6a5ca3805e467ac344c9f9152cb87e377b577e9a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 17:27:21 -0600 Subject: [PATCH 43/79] Spec loading of scoped properties when activating TextMate packages --- spec/app/atom-spec.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 291a71187..78bddda05 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -175,6 +175,11 @@ describe "the `atom` global", -> atom.activatePackage('ruby.tmbundle', sync: true) expect(syntax.selectGrammar("file.rb").name).toBe "Ruby" + it "translates the package's scoped properties to Atom terms", -> + expect(syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined() + atom.activatePackage('ruby.tmbundle', sync: true) + expect(syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBe '# ' + describe ".deactivatePackage(id)", -> describe "atom packages", -> it "calls `deactivate` on the package's main module", -> From d3fa24be57ad7d2b6f95f9d84a15a11c15685b32 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Mar 2013 17:30:42 -0600 Subject: [PATCH 44/79] Remove scoped-properties when deactivating a TextMate package --- spec/app/atom-spec.coffee | 5 +++++ src/app/text-mate-package.coffee | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index 78bddda05..8b32d3d79 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -236,6 +236,11 @@ describe "the `atom` global", -> atom.deactivatePackage('ruby.tmbundle') expect(syntax.selectGrammar("file.rb").name).toBe "Null Grammar" + it "removes the package's scoped properties", -> + atom.activatePackage('ruby.tmbundle', sync: true) + atom.deactivatePackage('ruby.tmbundle') + expect(syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined() + describe ".getVersion(callback)", -> it "calls the callback with the current version number", -> versionHandler = jasmine.createSpy("versionHandler") diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index f9a2dfaea..dcaddeebc 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -33,11 +33,11 @@ class TextMatePackage extends Package activate: -> syntax.addGrammar(grammar) for grammar in @grammars for { selector, properties } in @scopedProperties - syntax.addProperties(selector, properties) + syntax.addProperties(@path, selector, properties) deactivate: -> syntax.removeGrammar(grammar) for grammar in @grammars - # we should also unregister properties, snippets, etc + syntax.removeProperties(@path) legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage'] From 34f3176259bdc8182a58fe57384bd5c8adea9b4e Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 26 Mar 2013 16:38:54 -0700 Subject: [PATCH 45/79] Add $native.beep I could have created an npm for this. I also could wash my hands every 10 seconds, but I'm not crazy, so I did neither. --- native/v8_extensions/native.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/native/v8_extensions/native.mm b/native/v8_extensions/native.mm index 853d27c5f..e0e2e06a7 100644 --- a/native/v8_extensions/native.mm +++ b/native/v8_extensions/native.mm @@ -25,7 +25,7 @@ namespace v8_extensions { "writeToPasteboard", "readFromPasteboard", "quit", "watchPath", "unwatchPath", "getWatchedPaths", "unwatchAllPaths", "moveToTrash", "reload", "setWindowState", "getWindowState", "isMisspelled", - "getCorrectionsForMisspelling" + "getCorrectionsForMisspelling", "beep" }; CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); @@ -191,6 +191,10 @@ namespace v8_extensions { return true; } + else if (name == "beep") { + NSBeep(); + } + return false; } }; From 2ffb88e936dc33f10db8751a7dd9f954c3a6065e Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 26 Mar 2013 16:39:14 -0700 Subject: [PATCH 46/79] :lipstick: --- src/packages/command-panel/lib/commands/address.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/command-panel/lib/commands/address.coffee b/src/packages/command-panel/lib/commands/address.coffee index 7d0f88214..ffa89f8ff 100644 --- a/src/packages/command-panel/lib/commands/address.coffee +++ b/src/packages/command-panel/lib/commands/address.coffee @@ -6,7 +6,7 @@ module.exports = class Address extends Command compile: (project, buffer, ranges) -> deferred = $.Deferred() - deferred.resolve ranges.map (range) => + operations = ranges.map (range) => newRange = @getRange(buffer, range) new Operation @@ -15,6 +15,7 @@ class Address extends Command bufferRange: newRange errorMessage: @errorMessage + deferred.resolve(operations) deferred.promise() isAddress: -> true From f817e37a015170149010e523fc1fb707d059d134 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 26 Mar 2013 16:43:19 -0700 Subject: [PATCH 47/79] Refactor repeatRelativeAddress/repeatRelativeAddressInReverse --- .../command-panel/lib/command-interpreter.coffee | 10 ++++++---- .../command-panel/lib/command-panel-view.coffee | 9 +++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/packages/command-panel/lib/command-interpreter.coffee b/src/packages/command-panel/lib/command-interpreter.coffee index 8caa07b20..78566c036 100644 --- a/src/packages/command-panel/lib/command-interpreter.coffee +++ b/src/packages/command-panel/lib/command-interpreter.coffee @@ -11,8 +11,10 @@ class CommandInterpreter @lastRelativeAddress = compositeCommand if compositeCommand.isRelativeAddress() compositeCommand.execute(@project, activeEditSession) - repeatRelativeAddress: (activeEditSession) -> - @lastRelativeAddress?.execute(@project, activeEditSession) + repeatRelativeAddress: (activeEditSession, {reverse}={}) -> + return unless @lastRelativeAddress + reverse ?= false + previousSelectionRange = activeEditSession.getSelection().getBufferRange() + address = if reverse then @lastRelativeAddress.reverse() else @lastRelativeAddress - repeatRelativeAddressInReverse: (activeEditSession) -> - @lastRelativeAddress?.reverse().execute(@project, activeEditSession) + address.execute(@project, activeEditSession) \ No newline at end of file diff --git a/src/packages/command-panel/lib/command-panel-view.coffee b/src/packages/command-panel/lib/command-panel-view.coffee index 98004f35b..74806feda 100644 --- a/src/packages/command-panel/lib/command-panel-view.coffee +++ b/src/packages/command-panel/lib/command-panel-view.coffee @@ -44,7 +44,7 @@ class CommandPanelView extends View rootView.command 'command-panel:find-in-file', => @attach('/') rootView.command 'command-panel:find-in-project', => @attach('Xx/') rootView.command 'command-panel:repeat-relative-address', => @repeatRelativeAddress() - rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse() + rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddress(reverse: true) rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress() @on 'click', '.expand', @onExpandAll @@ -157,11 +157,8 @@ class CommandPanelView extends View @historyIndex++ @miniEditor.setText(@history[@historyIndex] or '') - repeatRelativeAddress: -> - @commandInterpreter.repeatRelativeAddress(rootView.getActivePaneItem()) - - repeatRelativeAddressInReverse: -> - @commandInterpreter.repeatRelativeAddressInReverse(rootView.getActivePaneItem()) + repeatRelativeAddress: (options) -> + @commandInterpreter.repeatRelativeAddress(rootView.getActivePaneItem(), options) setSelectionAsLastRelativeAddress: -> selection = rootView.getActiveView().getSelectedText() From 7e405138fcfb1a97d7ab3d5c230aea0bfadb9741 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 26 Mar 2013 16:44:46 -0700 Subject: [PATCH 48/79] Beep when only one matches is found by repeatRelativeAddress Closes #45 --- .../lib/command-interpreter.coffee | 4 +- .../spec/command-panel-spec.coffee | 72 +++++++++++++------ 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/packages/command-panel/lib/command-interpreter.coffee b/src/packages/command-panel/lib/command-interpreter.coffee index 78566c036..07f53672e 100644 --- a/src/packages/command-panel/lib/command-interpreter.coffee +++ b/src/packages/command-panel/lib/command-interpreter.coffee @@ -17,4 +17,6 @@ class CommandInterpreter previousSelectionRange = activeEditSession.getSelection().getBufferRange() address = if reverse then @lastRelativeAddress.reverse() else @lastRelativeAddress - address.execute(@project, activeEditSession) \ No newline at end of file + address.execute(@project, activeEditSession).done -> + currentSelectionRange = activeEditSession.getSelection().getBufferRange() + $native.beep() if previousSelectionRange.isEqual(currentSelectionRange) diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee index 6cfb03bb0..cf86ae0b4 100644 --- a/src/packages/command-panel/spec/command-panel-spec.coffee +++ b/src/packages/command-panel/spec/command-panel-spec.coffee @@ -212,39 +212,69 @@ describe "CommandPanel", -> expect(commandPanel.miniEditor.hiddenInput).not.toMatchSelector ':focus' describe "when command-panel:repeat-relative-address is triggered on the root view", -> - it "repeats the last search command if there is one", -> - rootView.trigger 'command-panel:repeat-relative-address' + describe "when there is more than one match", -> + it "repeats the last search command if there is one", -> + rootView.trigger 'command-panel:repeat-relative-address' - editSession.setCursorScreenPosition([4, 0]) + editSession.setCursorScreenPosition([4, 0]) - commandPanel.execute("/current") - expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]] + commandPanel.execute("/current") + expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]] - rootView.trigger 'command-panel:repeat-relative-address' - expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]] + rootView.trigger 'command-panel:repeat-relative-address' + expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]] - commandPanel.execute('s/r/R/g') + commandPanel.execute('s/r/R/g') - rootView.trigger 'command-panel:repeat-relative-address' - expect(editSession.getSelectedBufferRange()).toEqual [[6,34], [6,41]] + rootView.trigger 'command-panel:repeat-relative-address' + expect(editSession.getSelectedBufferRange()).toEqual [[6,34], [6,41]] - commandPanel.execute('0') - commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated + commandPanel.execute('0') + commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated - rootView.trigger 'command-panel:repeat-relative-address' - expect(editSession.getSelectedBufferRange()).toEqual [[3,31], [3,38]] + rootView.trigger 'command-panel:repeat-relative-address' + expect(editSession.getSelectedBufferRange()).toEqual [[3,31], [3,38]] + + describe "when there is only one match and it is selected", -> + it "maintains the current selection and plays a beep", -> + editSession.setCursorScreenPosition([0, 0]) + waitsForPromise -> + commandPanel.execute("/Array") + runs -> + expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]] + spyOn($native, 'beep') + rootView.trigger 'command-panel:repeat-relative-address' + waitsFor -> + $native.beep.callCount > 0 + runs -> + expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]] describe "when command-panel:repeat-relative-address-in-reverse is triggered on the root view", -> - it "it repeats the last relative address in the reverse direction", -> - rootView.trigger 'command-panel:repeat-relative-address-in-reverse' + describe "when there is more than one match", -> + it "it repeats the last relative address in the reverse direction", -> + rootView.trigger 'command-panel:repeat-relative-address-in-reverse' - editSession.setCursorScreenPosition([6, 0]) + editSession.setCursorScreenPosition([6, 0]) - commandPanel.execute("/current") - expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]] + commandPanel.execute("/current") + expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]] - rootView.trigger 'command-panel:repeat-relative-address-in-reverse' - expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]] + rootView.trigger 'command-panel:repeat-relative-address-in-reverse' + expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]] + + describe "when there is only one match and it is selected", -> + it "maintains the current selection and plays a beep", -> + editSession.setCursorScreenPosition([0, 0]) + waitsForPromise -> + commandPanel.execute("/Array") + runs -> + expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]] + spyOn($native, 'beep') + rootView.trigger 'command-panel:repeat-relative-address-in-reverse' + waitsFor -> + $native.beep.callCount > 0 + runs -> + expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]] describe "when command-panel:set-selection-as-regex-address is triggered on the root view", -> it "sets the @lastRelativeAddress to a RegexAddress of the current selection", -> From a772a9aa7564927d130c13a3a58fb8c4e1cc27cb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 26 Mar 2013 23:32:05 -0400 Subject: [PATCH 49/79] Remove unneeded std:: prefix --- native/v8_extensions/native.mm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/native/v8_extensions/native.mm b/native/v8_extensions/native.mm index e0e2e06a7..8211c7958 100644 --- a/native/v8_extensions/native.mm +++ b/native/v8_extensions/native.mm @@ -79,8 +79,8 @@ namespace v8_extensions { CefV8ValueList args; - args.push_back(CefV8Value::CreateString(std::string([eventType UTF8String], [eventType lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - args.push_back(CefV8Value::CreateString(std::string([path UTF8String], [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); + args.push_back(CefV8Value::CreateString(string([eventType UTF8String], [eventType lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); + args.push_back(CefV8Value::CreateString(string([path UTF8String], [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); function->ExecuteFunction(function, args); context->Exit(); @@ -92,7 +92,7 @@ namespace v8_extensions { retval = CefV8Value::CreateString([watchId UTF8String]); } else { - exception = std::string("Failed to watch path '") + std::string([path UTF8String]) + std::string("' (it may not exist)"); + exception = string("Failed to watch path '") + string([path UTF8String]) + string("' (it may not exist)"); } return true; @@ -138,7 +138,7 @@ namespace v8_extensions { tag:nil]; if (!success) { - std::string exception = "Can not move "; + string exception = "Can not move "; exception += [sourcePath UTF8String]; exception += " to trash."; } @@ -200,7 +200,7 @@ namespace v8_extensions { }; NSString *stringFromCefV8Value(const CefRefPtr& value) { - std::string cc_value = value->GetStringValue().ToString(); + string cc_value = value->GetStringValue().ToString(); return [NSString stringWithUTF8String:cc_value.c_str()]; } @@ -208,7 +208,7 @@ namespace v8_extensions { CefV8ValueList arguments; message = [message stringByAppendingFormat:@"\n%s", exception->GetMessage().ToString().c_str()]; - arguments.push_back(CefV8Value::CreateString(std::string([message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); + arguments.push_back(CefV8Value::CreateString(string([message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); CefRefPtr console = global->GetValue("console"); console->GetValue("error")->ExecuteFunction(console, arguments); From 215cd64c9aecc579e2666b97bf4b44f61aff3b0e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 22 Mar 2013 16:44:17 +0800 Subject: [PATCH 50/79] Use the node binary compiled with V8 used by Chromium. The official node is using a different V8 version with the one used by cefode, which causes incompatibility with cefode on native modules, this special node binary fixes it. The source code of this node binary can be found at: https://github.com/atom/cefode-node/tree/chromium-v8 --- Rakefile | 2 +- script/update-node | 23 ++++++----------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Rakefile b/Rakefile index e75cd8834..873693031 100644 --- a/Rakefile +++ b/Rakefile @@ -28,7 +28,7 @@ end desc "Download node binary" task "update-node" do - `script/update-node` + `script/update-node v0.10.1` end desc "Download debug symbols for CEF" diff --git a/script/update-node b/script/update-node index e3a249707..bbbb6d9e3 100755 --- a/script/update-node +++ b/script/update-node @@ -4,35 +4,24 @@ set -e cd "$(dirname $0)/.." +NODE_VERSION=v0.10.1 +[ -z $1 ] || NODE_VERSION=$1 + # Test whether we need update. -if [ -f "node/node" ]; then +if [ -f "node/node" ] && [[ `node/node --version` == $NODE_VERSION ]] ; then exit 0 fi -if ! DOWNLOAD_PAGE=$(curl -fsSkL http://nodejs.org/download/); then - exit 1; -fi - -NODE_VERSION=$(echo "$DOWNLOAD_PAGE" \ - | awk '/Current version:/ { print }' \ - | awk -F"[<>]" '{ print $5 }') - case $OSTYPE in darwin*) NODE_PLATFORM=darwin ;; linux*) NODE_PLATFORM=linux ;; *) echo "Unsupported platform $OSTYPE" && exit 1 ;; esac -if uname -a | grep 'x86_64' > /dev/null ; then - NODE_ARCH=x64 -else - NODE_ARCH=x86 -fi - -NODE_DIST_NAME="node-$NODE_VERSION-$NODE_PLATFORM-$NODE_ARCH" +NODE_DIST_NAME="node-$NODE_VERSION-$NODE_PLATFORM-x86" # Download node and untar -NODE_TARBALL_URL="http://nodejs.org/dist/$NODE_VERSION/$NODE_DIST_NAME.tar.gz" +NODE_TARBALL_URL="https://gh-contractor-zcbenz.s3.amazonaws.com/node/dist/$NODE_DIST_NAME.tar.gz" TARGET_DIR='node' [ -d "$TARGET_DIR" ] || mkdir "$TARGET_DIR" cd "$TARGET_DIR" From 67c2a1473c3dbcda9b2877d72edc1f3fdf349b61 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 22 Mar 2013 18:07:33 +0800 Subject: [PATCH 51/79] Cefode is using node v0.8.22. --- Rakefile | 2 +- script/bootstrap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 873693031..82b21775a 100644 --- a/Rakefile +++ b/Rakefile @@ -28,7 +28,7 @@ end desc "Download node binary" task "update-node" do - `script/update-node v0.10.1` + `script/update-node v0.8.22` end desc "Download debug symbols for CEF" diff --git a/script/bootstrap b/script/bootstrap index a3ffd75bf..fe49f65df 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -21,7 +21,7 @@ exit_unless_npm_exists npm install npm --silent NODE_DIR="$HOME/.cefode-gyp" -NODE_VERSION="0.8.21" +NODE_VERSION="0.8.22" NODE_URL="https://gh-contractor-zcbenz.s3.amazonaws.com/cefode/dist" if [ ! -d "node_modules/node-gyp" ]; then ./node_modules/.bin/npm install node-gyp --silent From 0d7f64267562ae61aa8ef0b8658b22360ae2add7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 22 Mar 2013 18:43:33 +0800 Subject: [PATCH 52/79] Add ProcessTask. --- src/stdlib/process-task-shell.coffee | 37 +++++++++++++++++ src/stdlib/process-task.coffee | 61 ++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/stdlib/process-task-shell.coffee create mode 100644 src/stdlib/process-task.coffee diff --git a/src/stdlib/process-task-shell.coffee b/src/stdlib/process-task-shell.coffee new file mode 100644 index 000000000..83f36327c --- /dev/null +++ b/src/stdlib/process-task-shell.coffee @@ -0,0 +1,37 @@ +global.window = {} +global.attachEvent = -> +console = + warn: -> callTaskMethod 'warn', arguments... + log: -> callTaskMethod 'log', arguments... + error: -> callTaskMethod 'error', arguments... +global.__defineGetter__ 'console', -> console + +window.document = + createElement: -> + setAttribute: -> + getElementsByTagName: -> [] + appendChild: -> + documentElement: + insertBefore: -> + removeChild: -> + getElementById: -> {} + createComment: -> {} + createDocumentFragment: -> {} +global.document = window.document + +# `callTaskMethod` can be used to invoke method's on the parent `Task` object +# back in the window thread. +global.callTaskMethod = (method, args...) -> + process.send(method: method, args: args) + +# The worker's initial handler replaces itglobal when `start` is invoked +global.handler = + start: ({globals, handlerPath}) -> + for key, value of globals + global[key] = value + window[key] = value + global.handler = require(handlerPath) + callTaskMethod 'started' + +process.on 'message', (data) -> + handler[data.method]?(data.args...) if data.method diff --git a/src/stdlib/process-task.coffee b/src/stdlib/process-task.coffee new file mode 100644 index 000000000..d4a7b0b69 --- /dev/null +++ b/src/stdlib/process-task.coffee @@ -0,0 +1,61 @@ +_ = require 'underscore' +child_process = require 'child_process' +EventEmitter = require 'event-emitter' +fs = require 'fs-utils' + +module.exports = +class ProcessTask + aborted: false + + constructor: (@path) -> + + start: -> + throw new Error("Task already started") if @worker? + + # Equivalent with node --eval "...". + blob = "require('coffee-script'); require('process-task-shell');" + @worker = child_process.fork '--eval', [ blob ], cwd: __dirname + + @worker.on 'message', (data) => + if @aborted + @done() + return + + if data.method and this[data.method] + this[data.method](data.args...) + else + @onMessage(data) + + @startWorker() + + log: -> console.log(arguments...) + warn: -> console.warn(arguments...) + error: -> console.error(arguments...) + + startWorker: -> + @callWorkerMethod 'start', + globals: + navigator: + userAgent: navigator.userAgent + handlerPath: @path + + started: -> + + onMessage: (message) -> + + callWorkerMethod: (method, args...) -> + @postMessage({method, args}) + + postMessage: (data) -> + @worker.send(data) + + abort: -> + @aborted = true + + done: -> + @abort() + @worker?.kill() + @worker = null + @trigger 'task-completed' + +_.extend ProcessTask.prototype, EventEmitter From 142824ec01e7d467437eacaec2e9a1f17c97a4bb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 22 Mar 2013 19:05:10 +0800 Subject: [PATCH 53/79] Add test for ProcessTask. --- spec/stdlib/process-task-shell-spec.coffee | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spec/stdlib/process-task-shell-spec.coffee diff --git a/spec/stdlib/process-task-shell-spec.coffee b/spec/stdlib/process-task-shell-spec.coffee new file mode 100644 index 000000000..124548640 --- /dev/null +++ b/spec/stdlib/process-task-shell-spec.coffee @@ -0,0 +1,23 @@ +Task = require 'process-task' + +describe "ProcessTask shell", -> + describe "populating the window with fake properties", -> + describe "when jQuery is loaded in child process", -> + it "doesn't log to the console", -> + spyOn(console, 'log') + spyOn(console, 'error') + spyOn(console, 'warn') + class JQueryTask extends Task + constructor: -> super('fixtures/jquery-task-handler.coffee') + started: -> @callWorkerMethod('load') + loaded: (@jqueryLoaded) -> + + task = new JQueryTask() + task.start() + waitsFor "child process to start and jquery to be required", 5000, -> + task.jqueryLoaded + runs -> + expect(task.jqueryLoaded).toBeTruthy() + expect(console.log).not.toHaveBeenCalled() + expect(console.error).not.toHaveBeenCalled() + expect(console.warn).not.toHaveBeenCalled() From 3ed35574d48f400cf5bd838604988548266e40bf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 24 Mar 2013 15:45:15 +0800 Subject: [PATCH 54/79] Use node-nsspellchecker to replace $native's spell checker. --- native/v8_extensions/native.mm | 31 +------------------ package.json | 1 + .../spell-check/lib/misspelling-view.coffee | 3 +- .../lib/spell-check-handler.coffee | 4 ++- 4 files changed, 7 insertions(+), 32 deletions(-) diff --git a/native/v8_extensions/native.mm b/native/v8_extensions/native.mm index 8211c7958..03c92eda0 100644 --- a/native/v8_extensions/native.mm +++ b/native/v8_extensions/native.mm @@ -24,8 +24,7 @@ namespace v8_extensions { const char* methodNames[] = { "writeToPasteboard", "readFromPasteboard", "quit", "watchPath", "unwatchPath", "getWatchedPaths", "unwatchAllPaths", "moveToTrash", - "reload", "setWindowState", "getWindowState", "isMisspelled", - "getCorrectionsForMisspelling", "beep" + "reload", "setWindowState", "getWindowState", "beep" }; CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); @@ -163,34 +162,6 @@ namespace v8_extensions { return true; } - else if (name == "isMisspelled") { - NSString *word = stringFromCefV8Value(arguments[0]); - NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker]; - @synchronized(spellChecker) { - NSRange range = [spellChecker checkSpellingOfString:word startingAt:0]; - retval = CefV8Value::CreateBool(range.length > 0); - } - return true; - } - - else if (name == "getCorrectionsForMisspelling") { - NSString *misspelling = stringFromCefV8Value(arguments[0]); - NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker]; - @synchronized(spellChecker) { - NSString *language = [spellChecker language]; - NSRange range; - range.location = 0; - range.length = [misspelling length]; - NSArray *guesses = [spellChecker guessesForWordRange:range inString:misspelling language:language inSpellDocumentWithTag:0]; - CefRefPtr v8Guesses = CefV8Value::CreateArray([guesses count]); - for (int i = 0; i < [guesses count]; i++) { - v8Guesses->SetValue(i, CefV8Value::CreateString([[guesses objectAtIndex:i] UTF8String])); - } - retval = v8Guesses; - } - return true; - } - else if (name == "beep") { NSBeep(); } diff --git a/package.json b/package.json index 8f1d8129a..584bc949d 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "coffee-cache": "0.1.0", "pegjs": "0.7.0", "async": "0.2.6", + "nsspellchecker": "0.1.1", "plist": "git://github.com/nathansobo/node-plist.git" }, diff --git a/src/packages/spell-check/lib/misspelling-view.coffee b/src/packages/spell-check/lib/misspelling-view.coffee index ba57e4164..4f1d898d2 100644 --- a/src/packages/spell-check/lib/misspelling-view.coffee +++ b/src/packages/spell-check/lib/misspelling-view.coffee @@ -1,6 +1,7 @@ {View} = require 'space-pen' Range = require 'range' CorrectionsView = require './corrections-view' +NSSpellChecker = require 'nsspellchecker' module.exports = class MisspellingView extends View @@ -30,7 +31,7 @@ class MisspellingView extends View screenRange = @getScreenRange() misspelling = @editor.getTextInRange(@editor.bufferRangeForScreenRange(screenRange)) - corrections = $native.getCorrectionsForMisspelling(misspelling) + corrections = NSSpellChecker.getCorrectionsForMisspelling(misspelling) @correctionsView?.remove() @correctionsView = new CorrectionsView(@editor, corrections, screenRange) diff --git a/src/packages/spell-check/lib/spell-check-handler.coffee b/src/packages/spell-check/lib/spell-check-handler.coffee index 8040f4991..9dc59ef80 100644 --- a/src/packages/spell-check/lib/spell-check-handler.coffee +++ b/src/packages/spell-check/lib/spell-check-handler.coffee @@ -1,3 +1,5 @@ +NSSpellChecker = require 'nsspellchecker' + module.exports = findMisspellings: (text) -> wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]]|$)/g @@ -6,7 +8,7 @@ module.exports = for line in text.split('\n') while matches = wordRegex.exec(line) word = matches[1] - continue unless $native.isMisspelled(word) + continue unless NSSpellChecker.isMisspelled(word) startColumn = matches.index + matches[0].length - word.length endColumn = startColumn + word.length misspellings.push([[row, startColumn], [row, endColumn]]) From 3c5a79710a8adcbace7c02258a69c9d525e740d1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 24 Mar 2013 19:01:02 +0800 Subject: [PATCH 55/79] Use _.isArray to determine whether a value is Array. When passing arrays between child processes with node's IPC machanism, `instance of Array` will return false for the deserialized array, we should use the reiable way of detecting Array provided by underscore. Read this for more: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ This bug was found when moving spell-check to use ProcessTask, and the wrong Range object was returned for the passed misspelling value. --- src/app/point.coffee | 4 +++- src/app/range.coffee | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/point.coffee b/src/app/point.coffee index e471ad6c6..6dd3eca27 100644 --- a/src/app/point.coffee +++ b/src/app/point.coffee @@ -1,10 +1,12 @@ +_ = require 'underscore' + module.exports = class Point @fromObject: (object) -> if object instanceof Point object else - if object instanceof Array + if _.isArray(object) [row, column] = object else { row, column } = object diff --git a/src/app/range.coffee b/src/app/range.coffee index a3870ea66..d72ef6514 100644 --- a/src/app/range.coffee +++ b/src/app/range.coffee @@ -31,7 +31,7 @@ class Range new Range(@start.copy(), @end.copy()) isEqual: (other) -> - if other instanceof Array and other.length == 2 + if _.isArray(other) and other.length == 2 other = new Range(other...) other.start.isEqual(@start) and other.end.isEqual(@end) From b5be1c378aee4b89b18b0c3bdf93c05945004361 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 24 Mar 2013 19:20:31 +0800 Subject: [PATCH 56/79] Replace Task's implementation with ProcessTask. --- spec/stdlib/process-task-shell-spec.coffee | 23 -------- spec/stdlib/task-shell-spec.coffee | 4 +- src/stdlib/process-task-shell.coffee | 37 ------------- src/stdlib/process-task.coffee | 61 ---------------------- src/stdlib/task-shell.coffee | 29 ++++------ src/stdlib/task.coffee | 18 ++++--- 6 files changed, 24 insertions(+), 148 deletions(-) delete mode 100644 spec/stdlib/process-task-shell-spec.coffee delete mode 100644 src/stdlib/process-task-shell.coffee delete mode 100644 src/stdlib/process-task.coffee diff --git a/spec/stdlib/process-task-shell-spec.coffee b/spec/stdlib/process-task-shell-spec.coffee deleted file mode 100644 index 124548640..000000000 --- a/spec/stdlib/process-task-shell-spec.coffee +++ /dev/null @@ -1,23 +0,0 @@ -Task = require 'process-task' - -describe "ProcessTask shell", -> - describe "populating the window with fake properties", -> - describe "when jQuery is loaded in child process", -> - it "doesn't log to the console", -> - spyOn(console, 'log') - spyOn(console, 'error') - spyOn(console, 'warn') - class JQueryTask extends Task - constructor: -> super('fixtures/jquery-task-handler.coffee') - started: -> @callWorkerMethod('load') - loaded: (@jqueryLoaded) -> - - task = new JQueryTask() - task.start() - waitsFor "child process to start and jquery to be required", 5000, -> - task.jqueryLoaded - runs -> - expect(task.jqueryLoaded).toBeTruthy() - expect(console.log).not.toHaveBeenCalled() - expect(console.error).not.toHaveBeenCalled() - expect(console.warn).not.toHaveBeenCalled() diff --git a/spec/stdlib/task-shell-spec.coffee b/spec/stdlib/task-shell-spec.coffee index d1ccb8fc0..f1a539036 100644 --- a/spec/stdlib/task-shell-spec.coffee +++ b/spec/stdlib/task-shell-spec.coffee @@ -2,7 +2,7 @@ Task = require 'task' describe "Task shell", -> describe "populating the window with fake properties", -> - describe "when jQuery is loaded in a web worker", -> + describe "when jQuery is loaded in a child process", -> it "doesn't log to the console", -> spyOn(console, 'log') spyOn(console, 'error') @@ -14,7 +14,7 @@ describe "Task shell", -> task = new JQueryTask() task.start() - waitsFor "web worker to start and jquery to be required", 5000, -> + waitsFor "child process to start and jquery to be required", 5000, -> task.jqueryLoaded runs -> expect(task.jqueryLoaded).toBeTruthy() diff --git a/src/stdlib/process-task-shell.coffee b/src/stdlib/process-task-shell.coffee deleted file mode 100644 index 83f36327c..000000000 --- a/src/stdlib/process-task-shell.coffee +++ /dev/null @@ -1,37 +0,0 @@ -global.window = {} -global.attachEvent = -> -console = - warn: -> callTaskMethod 'warn', arguments... - log: -> callTaskMethod 'log', arguments... - error: -> callTaskMethod 'error', arguments... -global.__defineGetter__ 'console', -> console - -window.document = - createElement: -> - setAttribute: -> - getElementsByTagName: -> [] - appendChild: -> - documentElement: - insertBefore: -> - removeChild: -> - getElementById: -> {} - createComment: -> {} - createDocumentFragment: -> {} -global.document = window.document - -# `callTaskMethod` can be used to invoke method's on the parent `Task` object -# back in the window thread. -global.callTaskMethod = (method, args...) -> - process.send(method: method, args: args) - -# The worker's initial handler replaces itglobal when `start` is invoked -global.handler = - start: ({globals, handlerPath}) -> - for key, value of globals - global[key] = value - window[key] = value - global.handler = require(handlerPath) - callTaskMethod 'started' - -process.on 'message', (data) -> - handler[data.method]?(data.args...) if data.method diff --git a/src/stdlib/process-task.coffee b/src/stdlib/process-task.coffee deleted file mode 100644 index d4a7b0b69..000000000 --- a/src/stdlib/process-task.coffee +++ /dev/null @@ -1,61 +0,0 @@ -_ = require 'underscore' -child_process = require 'child_process' -EventEmitter = require 'event-emitter' -fs = require 'fs-utils' - -module.exports = -class ProcessTask - aborted: false - - constructor: (@path) -> - - start: -> - throw new Error("Task already started") if @worker? - - # Equivalent with node --eval "...". - blob = "require('coffee-script'); require('process-task-shell');" - @worker = child_process.fork '--eval', [ blob ], cwd: __dirname - - @worker.on 'message', (data) => - if @aborted - @done() - return - - if data.method and this[data.method] - this[data.method](data.args...) - else - @onMessage(data) - - @startWorker() - - log: -> console.log(arguments...) - warn: -> console.warn(arguments...) - error: -> console.error(arguments...) - - startWorker: -> - @callWorkerMethod 'start', - globals: - navigator: - userAgent: navigator.userAgent - handlerPath: @path - - started: -> - - onMessage: (message) -> - - callWorkerMethod: (method, args...) -> - @postMessage({method, args}) - - postMessage: (data) -> - @worker.send(data) - - abort: -> - @aborted = true - - done: -> - @abort() - @worker?.kill() - @worker = null - @trigger 'task-completed' - -_.extend ProcessTask.prototype, EventEmitter diff --git a/src/stdlib/task-shell.coffee b/src/stdlib/task-shell.coffee index bab99dc7c..83f36327c 100644 --- a/src/stdlib/task-shell.coffee +++ b/src/stdlib/task-shell.coffee @@ -1,17 +1,10 @@ -# This file is loaded within Task's worker thread. It will attempt to invoke -# any message with a 'method' and 'args' key on the global `handler` object. The -# initial `handler` object contains the `start` method, which is called by the -# task itself to relay information from the window thread and bootstrap the -# worker's environment. The `start` method then replaces the handler with an -# object required from the given `handlerPath`. - -self.window = {} -self.attachEvent = -> +global.window = {} +global.attachEvent = -> console = warn: -> callTaskMethod 'warn', arguments... log: -> callTaskMethod 'log', arguments... error: -> callTaskMethod 'error', arguments... -self.__defineGetter__ 'console', -> console +global.__defineGetter__ 'console', -> console window.document = createElement: -> @@ -24,21 +17,21 @@ window.document = getElementById: -> {} createComment: -> {} createDocumentFragment: -> {} -self.document = window.document +global.document = window.document # `callTaskMethod` can be used to invoke method's on the parent `Task` object # back in the window thread. -self.callTaskMethod = (method, args...) -> - postMessage(method: method, args: args) +global.callTaskMethod = (method, args...) -> + process.send(method: method, args: args) -# The worker's initial handler replaces itself when `start` is invoked -self.handler = +# The worker's initial handler replaces itglobal when `start` is invoked +global.handler = start: ({globals, handlerPath}) -> for key, value of globals - self[key] = value + global[key] = value window[key] = value - self.handler = require(handlerPath) + global.handler = require(handlerPath) callTaskMethod 'started' -self.addEventListener 'message', ({data}) -> +process.on 'message', (data) -> handler[data.method]?(data.args...) if data.method diff --git a/src/stdlib/task.coffee b/src/stdlib/task.coffee index 636be9e6f..e2f0b4a40 100644 --- a/src/stdlib/task.coffee +++ b/src/stdlib/task.coffee @@ -1,9 +1,10 @@ _ = require 'underscore' +child_process = require 'child_process' EventEmitter = require 'event-emitter' fs = require 'fs-utils' module.exports = -class Task +class ProcessTask aborted: false constructor: (@path) -> @@ -11,9 +12,11 @@ class Task start: -> throw new Error("Task already started") if @worker? - blob = new Blob(["require('coffee-script'); require('task-shell');"], type: 'text/javascript') - @worker = new Worker(URL.createObjectURL(blob)) - @worker.onmessage = ({data}) => + # Equivalent with node --eval "...". + blob = "require('coffee-script'); require('task-shell');" + @worker = child_process.fork '--eval', [ blob ], cwd: __dirname + + @worker.on 'message', (data) => if @aborted @done() return @@ -22,6 +25,7 @@ class Task this[data.method](data.args...) else @onMessage(data) + @startWorker() log: -> console.log(arguments...) @@ -43,15 +47,15 @@ class Task @postMessage({method, args}) postMessage: (data) -> - @worker.postMessage(data) + @worker.send(data) abort: -> @aborted = true done: -> @abort() - @worker?.terminate() + @worker?.kill() @worker = null @trigger 'task-completed' -_.extend Task.prototype, EventEmitter +_.extend ProcessTask.prototype, EventEmitter From 371fdde4f9538801b3455d8638c8cb325875fdef Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 24 Mar 2013 19:39:23 +0800 Subject: [PATCH 57/79] Use atom/cefode. --- Rakefile | 2 +- script/bootstrap | 4 ++-- script/update-cefode | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Rakefile b/Rakefile index 82b21775a..873693031 100644 --- a/Rakefile +++ b/Rakefile @@ -28,7 +28,7 @@ end desc "Download node binary" task "update-node" do - `script/update-node v0.8.22` + `script/update-node v0.10.1` end desc "Download debug symbols for CEF" diff --git a/script/bootstrap b/script/bootstrap index fe49f65df..4db2c1279 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -21,8 +21,8 @@ exit_unless_npm_exists npm install npm --silent NODE_DIR="$HOME/.cefode-gyp" -NODE_VERSION="0.8.22" -NODE_URL="https://gh-contractor-zcbenz.s3.amazonaws.com/cefode/dist" +NODE_VERSION="0.10.1" +NODE_URL="https://gh-contractor-zcbenz.s3.amazonaws.com/cefode2/dist" if [ ! -d "node_modules/node-gyp" ]; then ./node_modules/.bin/npm install node-gyp --silent HOME="$NODE_DIR" ./node_modules/.bin/node-gyp install --target="$NODE_VERSION" --dist-url="$NODE_URL" --arch=ia32 diff --git a/script/update-cefode b/script/update-cefode index 7f582be19..a715242c6 100755 --- a/script/update-cefode +++ b/script/update-cefode @@ -13,7 +13,7 @@ else TARGET=$1 fi -DISTURL="https://gh-contractor-zcbenz.s3.amazonaws.com/cefode/prebuilt-cef" +DISTURL="https://gh-contractor-zcbenz.s3.amazonaws.com/cefode2/prebuilt-cef" CEF_BASENAME="cef_binary_3.1423.1133_macosx" CEF_SYMBOLS_BASENAME="${CEF_BASENAME}_symbols" @@ -29,7 +29,7 @@ fi CURRENT_VERSION=`cat cef/version 2>&1` if [[ $LATEST_VERSION != $CURRENT_VERSION ]]; then - echo "Downloading/extracting cefode u${LATEST_VERSION}..." + echo "Downloading/extracting cefode2 u${LATEST_VERSION}..." curl --progress-bar "${DISTURL}/cef_binary_latest.zip" > "${TEMP_DIR}/cef.zip" unzip -q "${TEMP_DIR}/cef.zip" -d "${TEMP_DIR}" [ -e "${TARGET}" ] && rm -rf "${TARGET}" @@ -41,7 +41,7 @@ if [[ "${SYMBOLS}" != "1" ]]; then exit 0 fi -echo "Downloading/extracting symbols for cefode u${LATEST_VERSION}..." +echo "Downloading/extracting symbols for cefode2 u${LATEST_VERSION}..." curl --progress-bar "${DISTURL}/cef_binary_latest_symbols.zip" > "${TEMP_DIR}/symbols.zip" unzip -q "${TEMP_DIR}/symbols.zip" -d "${TEMP_DIR}" mv "${TEMP_DIR}/${CEF_SYMBOLS_BASENAME}"/* "${TARGET}/Release" From 6ce25d4c71616c6c3a185628eedb24b489610c2a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 24 Mar 2013 22:53:30 +0800 Subject: [PATCH 58/79] Fix the usage of spawn. --- src/app/window.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/window.coffee b/src/app/window.coffee index 8ef579f0e..f6c513c2d 100644 --- a/src/app/window.coffee +++ b/src/app/window.coffee @@ -80,7 +80,7 @@ window.installAtomCommand = (commandPath) -> bundledCommandPath = fs.resolve(window.resourcePath, 'atom.sh') if bundledCommandPath? fs.write(commandPath, fs.read(bundledCommandPath)) - spawn("chmod u+x '#{commandPath}'") + spawn('chmod', ['u+x', commandPath]) window.handleWindowEvents = -> $(window).command 'window:toggle-full-screen', => atom.toggleFullScreen() From 7effc4c4568c06d4dfc47b1b09d77d924cd7c53b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 24 Mar 2013 23:14:08 +0800 Subject: [PATCH 59/79] :lipstick: --- src/stdlib/task-shell.coffee | 7 +++++++ src/stdlib/task.coffee | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/stdlib/task-shell.coffee b/src/stdlib/task-shell.coffee index 83f36327c..6ac2d5f6e 100644 --- a/src/stdlib/task-shell.coffee +++ b/src/stdlib/task-shell.coffee @@ -1,3 +1,10 @@ +# This file is loaded within Task's worker process. It will attempt to invoke +# any message with a 'method' and 'args' key on the global `handler` object. The +# initial `handler` object contains the `start` method, which is called by the +# task itself to relay information from the window thread and bootstrap the +# worker's environment. The `start` method then replaces the handler with an +# object required from the given `handlerPath`. + global.window = {} global.attachEvent = -> console = diff --git a/src/stdlib/task.coffee b/src/stdlib/task.coffee index e2f0b4a40..8216a4f15 100644 --- a/src/stdlib/task.coffee +++ b/src/stdlib/task.coffee @@ -4,7 +4,7 @@ EventEmitter = require 'event-emitter' fs = require 'fs-utils' module.exports = -class ProcessTask +class Task aborted: false constructor: (@path) -> @@ -58,4 +58,4 @@ class ProcessTask @worker = null @trigger 'task-completed' -_.extend ProcessTask.prototype, EventEmitter +_.extend Task.prototype, EventEmitter From 4768ae90080dc4a4396f0c41d26e5310ad5fe259 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 27 Mar 2013 12:24:10 +0800 Subject: [PATCH 60/79] Rename node-nsspellchecker to node-spellchecker. --- package.json | 2 +- src/packages/spell-check/lib/misspelling-view.coffee | 4 ++-- src/packages/spell-check/lib/spell-check-handler.coffee | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 584bc949d..761afa2f7 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "coffee-cache": "0.1.0", "pegjs": "0.7.0", "async": "0.2.6", - "nsspellchecker": "0.1.1", + "spellchecker": "0.2.0", "plist": "git://github.com/nathansobo/node-plist.git" }, diff --git a/src/packages/spell-check/lib/misspelling-view.coffee b/src/packages/spell-check/lib/misspelling-view.coffee index 4f1d898d2..0940ce0f7 100644 --- a/src/packages/spell-check/lib/misspelling-view.coffee +++ b/src/packages/spell-check/lib/misspelling-view.coffee @@ -1,7 +1,7 @@ {View} = require 'space-pen' Range = require 'range' CorrectionsView = require './corrections-view' -NSSpellChecker = require 'nsspellchecker' +SpellChecker = require 'spellchecker' module.exports = class MisspellingView extends View @@ -31,7 +31,7 @@ class MisspellingView extends View screenRange = @getScreenRange() misspelling = @editor.getTextInRange(@editor.bufferRangeForScreenRange(screenRange)) - corrections = NSSpellChecker.getCorrectionsForMisspelling(misspelling) + corrections = SpellChecker.getCorrectionsForMisspelling(misspelling) @correctionsView?.remove() @correctionsView = new CorrectionsView(@editor, corrections, screenRange) diff --git a/src/packages/spell-check/lib/spell-check-handler.coffee b/src/packages/spell-check/lib/spell-check-handler.coffee index 9dc59ef80..0b21f73ab 100644 --- a/src/packages/spell-check/lib/spell-check-handler.coffee +++ b/src/packages/spell-check/lib/spell-check-handler.coffee @@ -1,4 +1,4 @@ -NSSpellChecker = require 'nsspellchecker' +SpellChecker = require 'spellchecker' module.exports = findMisspellings: (text) -> @@ -8,7 +8,7 @@ module.exports = for line in text.split('\n') while matches = wordRegex.exec(line) word = matches[1] - continue unless NSSpellChecker.isMisspelled(word) + continue unless SpellChecker.isMisspelled(word) startColumn = matches.index + matches[0].length - word.length endColumn = startColumn + word.length misspellings.push([[row, startColumn], [row, endColumn]]) From 38924f5bb8aef62adc8dbc9da60e6756a2f27105 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Mar 2013 11:05:58 -0400 Subject: [PATCH 61/79] Upgrade to latest space pen, as an NPM --- package.json | 3 +- src/app/editor.coffee | 2 +- src/app/pane.coffee | 2 +- vendor/space-pen.coffee | 208 ---------------------------------------- 4 files changed, 4 insertions(+), 211 deletions(-) delete mode 100644 vendor/space-pen.coffee diff --git a/package.json b/package.json index 761afa2f7..5d0dfb7ff 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "pegjs": "0.7.0", "async": "0.2.6", "spellchecker": "0.2.0", - "plist": "git://github.com/nathansobo/node-plist.git" + "plist": "git://github.com/nathansobo/node-plist.git", + "space-pen": "git://github.com/nathansobo/space-pen.git" }, "private": true, diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 21eaf143c..c2152f0d3 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -659,7 +659,7 @@ class Editor extends View super rootView?.focus() - afterRemove: -> + beforeRemove: -> @removed = true @activeEditSession?.destroy() $(window).off(".editor-#{@id}") diff --git a/src/app/pane.coffee b/src/app/pane.coffee index 3bd9c9f4c..e9132cc11 100644 --- a/src/app/pane.coffee +++ b/src/app/pane.coffee @@ -324,5 +324,5 @@ class Pane extends View container.adjustPaneDimensions() container.trigger 'pane:removed', [this] - afterRemove: -> + beforeRemove: -> item.destroy?() for item in @getItems() diff --git a/vendor/space-pen.coffee b/vendor/space-pen.coffee deleted file mode 100644 index f734350e0..000000000 --- a/vendor/space-pen.coffee +++ /dev/null @@ -1,208 +0,0 @@ -# Modified from d9b6b4a2fe3fdeca07bb82e14e412718540f89f3 -$ = jQuery = require('jquery') - -elements = - 'a abbr address article aside audio b bdi bdo blockquote body button - canvas caption cite code colgroup datalist dd del details dfn div dl dt em - fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup - html i iframe ins kbd label legend li map mark menu meter nav noscript object - ol optgroup option output p pre progress q rp rt ruby s samp script section - select small span strong style sub summary sup table tbody td textarea tfoot - th thead time title tr u ul video area base br col command embed hr img input - keygen link meta param source track wbrk'.split /\s+/ - -voidElements = - 'area base br col command embed hr img input keygen link meta param - source track wbr'.split /\s+/ - -events = - 'blur change click dblclick error focus input keydown - keypress keyup load mousedown mousemove mouseout mouseover - mouseup resize scroll select submit unload'.split /\s+/ - -idCounter = 0 - -class View extends jQuery - @builderStack: [] - - elements.forEach (tagName) -> - View[tagName] = (args...) -> @currentBuilder.tag(tagName, args...) - - @subview: (name, view) -> - @currentBuilder.subview(name, view) - - @text: (string) -> @currentBuilder.text(string) - - @raw: (string) -> @currentBuilder.raw(string) - - @pushBuilder: -> - builder = new Builder - @builderStack.push(builder) - @currentBuilder = builder - - @popBuilder: -> - @currentBuilder = @builderStack[@builderStack.length - 2] - @builderStack.pop() - - @buildHtml: (fn) -> - @pushBuilder() - fn.call(this) - [html, postProcessingSteps] = @popBuilder().buildHtml() - - @render: (fn) -> - [html, postProcessingSteps] = @buildHtml(fn) - div = document.createElement('div') - div.innerHTML = html - fragment = $(div.childNodes) - step(fragment) for step in postProcessingSteps - fragment - - constructor: (args...) -> - [html, postProcessingSteps] = @constructor.buildHtml -> @content(args...) - jQuery.fn.init.call(this, html) - @constructor = jQuery # sadly, jQuery assumes this.constructor == jQuery in pushStack - throw new Error("View markup must have a single root element") if this.length != 1 - @wireOutlets(this) - @bindEventHandlers(this) - @find('*').andSelf().data('view', this) - @attr('callAttachHooks', true) - step(this) for step in postProcessingSteps - @initialize?(args...) - - buildHtml: (params) -> - @constructor.builder = new Builder - @constructor.content(params) - [html, postProcessingSteps] = @constructor.builder.buildHtml() - @constructor.builder = null - postProcessingSteps - - wireOutlets: (view) -> - @find('[outlet]').each -> - element = $(this) - outlet = element.attr('outlet') - view[outlet] = element - element.attr('outlet', null) - - bindEventHandlers: (view) -> - for eventName in events - selector = "[#{eventName}]" - elements = view.find(selector).add(view.filter(selector)) - elements.each -> - element = $(this) - methodName = element.attr(eventName) - element.on eventName, (event) -> view[methodName](event, element) - -class Builder - constructor: -> - @document = [] - @postProcessingSteps = [] - - buildHtml: -> - [@document.join(''), @postProcessingSteps] - - tag: (name, args...) -> - options = @extractOptions(args) - - @openTag(name, options.attributes) - - if name in voidElements - if (options.text? or options.content?) - throw new Error("Self-closing tag #{name} cannot have text or content") - else - options.content?() - @text(options.text) if options.text - @closeTag(name) - - openTag: (name, attributes) -> - attributePairs = - for attributeName, value of attributes - "#{attributeName}=\"#{value}\"" - - attributesString = - if attributePairs.length - " " + attributePairs.join(" ") - else - "" - - @document.push "<#{name}#{attributesString}>" - - closeTag: (name) -> - @document.push "" - - text: (string) -> - escapedString = string - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>') - - @document.push escapedString - - raw: (string) -> - @document.push string - - subview: (outletName, subview) -> - subviewId = "subview-#{++idCounter}" - @tag 'div', id: subviewId - @postProcessingSteps.push (view) -> - view[outletName] = subview - subview.parentView = view - view.find("div##{subviewId}").replaceWith(subview) - - extractOptions: (args) -> - options = {} - for arg in args - type = typeof(arg) - if type is "function" - options.content = arg - else if type is "string" or type is "number" - options.text = arg.toString() - else - options.attributes = arg - options - -jQuery.fn.view = -> @data('view') -jQuery.fn.views = -> @toArray().map (elt) -> jQuery(elt).view() - -# Trigger attach event when views are added to the DOM -callAttachHook = (element) -> - return unless element - onDom = element.parents?('html').length > 0 - - elementsWithHooks = [] - elementsWithHooks.push(element[0]) if element.attr?('callAttachHooks') - elementsWithHooks = elementsWithHooks.concat(element.find?('[callAttachHooks]').toArray() ? []) if onDom - - parent = element - for element in elementsWithHooks - view = $(element).view() - $(element).view()?.afterAttach?(onDom) - -for methodName in ['append', 'prepend', 'after', 'before'] - do (methodName) -> - originalMethod = $.fn[methodName] - jQuery.fn[methodName] = (args...) -> - flatArgs = [].concat args... - result = originalMethod.apply(this, flatArgs) - callAttachHook arg for arg in flatArgs - result - -for methodName in ['prependTo', 'appendTo', 'insertAfter', 'insertBefore'] - do (methodName) -> - originalMethod = jQuery.fn[methodName] - jQuery.fn[methodName] = (args...) -> - result = originalMethod.apply(this, args) - callAttachHook(this) - result - -originalCleanData = jQuery.cleanData -jQuery.cleanData = (elements) -> - for element in elements - view = $(element).view() - view.afterRemove?() if view and view?[0] == element - originalCleanData(elements) - -(exports ? this).View = View -(exports ? this).$$ = (fn) -> View.render.call(View, fn) -(exports ? this).$$$ = (fn) -> View.buildHtml.call(View, fn)[0] From bc211a2231fb0994ceb4d74fc50d97dcaa2b95df Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 27 Mar 2013 23:05:00 +0800 Subject: [PATCH 62/79] Should erase cef in rake clean. --- Rakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Rakefile b/Rakefile index 873693031..3f3c926eb 100644 --- a/Rakefile +++ b/Rakefile @@ -86,6 +86,7 @@ task :clean do `rm -rf #{BUILD_DIR}` `rm -rf /tmp/atom-compiled-scripts` `rm -rf node_modules` + `rm -rf cef` end desc "Run the specs" From 8d22b6d1b367e03c6cb633fb2670d6acfdc2c0b7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 11:42:55 -0400 Subject: [PATCH 63/79] :lipstick: --- src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee b/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee index 538988957..5b86ec06a 100644 --- a/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee +++ b/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee @@ -162,7 +162,7 @@ class FuzzyFinderView extends SelectList @loadPathsTask.start() populateOpenBufferPaths: -> - editSessions = project.getEditSessions().filter (editSession)-> + editSessions = project.getEditSessions().filter (editSession) -> editSession.getPath()? editSessions = _.sortBy editSessions, (editSession) => From 5a7f2a9ef456714324fb5773abdeb691fc43423c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 11:51:38 -0400 Subject: [PATCH 64/79] Don't show duplicates in open buffer list Closes #378 --- src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee | 2 ++ src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee b/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee index 5b86ec06a..d5a0b3e52 100644 --- a/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee +++ b/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee @@ -164,6 +164,8 @@ class FuzzyFinderView extends SelectList populateOpenBufferPaths: -> editSessions = project.getEditSessions().filter (editSession) -> editSession.getPath()? + editSessions = _.uniq editSessions, (editSession) -> + editSession.getPath() editSessions = _.sortBy editSessions, (editSession) => if editSession is rootView.getActivePaneItem() diff --git a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee index 904856ed4..15c89721e 100644 --- a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee +++ b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee @@ -166,6 +166,13 @@ describe 'FuzzyFinder', -> rootView.trigger 'fuzzy-finder:toggle-buffer-finder' expect(rootView.find('.fuzzy-finder')).not.toExist() + describe "when multiple sessions are opened on the same path", -> + it "does not display duplicates for that path in the list", -> + rootView.open 'sample.js' + rootView.getActivePane().splitRight() + rootView.trigger 'fuzzy-finder:toggle-buffer-finder' + expect(_.pluck(finderView.list.children('li'), 'outerText')).toEqual ['sample.js'] + describe "when a path selection is confirmed", -> [editor1, editor2] = [] From a1b82e9daddb31cad8c8b013873c9e6e2412627a Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 10:13:45 -0700 Subject: [PATCH 65/79] Allow mini-editors to explicitly set their grammars --- spec/app/editor-spec.coffee | 12 ++++++++++++ src/app/edit-session.coffee | 16 +++++++++++----- src/app/editor.coffee | 16 ++++++++++++---- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index ee150eca5..e8c416da7 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -1709,6 +1709,18 @@ describe "Editor", -> miniEditor.setText(" a line with tabs\tand spaces ") expect(miniEditor.renderedLines.find('.line').text()).toBe "#{space}a line with tabs#{tab} and spaces#{space}" + it "lets you set the grammar", -> + miniEditor = new Editor(mini: true) + miniEditor.setText("var something") + previousTokens = miniEditor.lineForScreenRow(0).tokens + miniEditor.setGrammar(syntax.selectGrammar('something.js')) + expect(miniEditor.getGrammar().name).toBe "JavaScript" + expect(previousTokens).not.toEqual miniEditor.lineForScreenRow(0).tokens + + # doesn't allow regular editors to set grammars + expect(-> editor.setGrammar()).toThrow() + + describe "when config.editor.showLineNumbers is false", -> it "doesn't render any line numbers", -> expect(editor.gutter.lineNumbers).toBeVisible() diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 5b66f2c98..f1ddfa232 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -837,12 +837,18 @@ class EditSession getGrammar: -> @languageMode.grammar + setGrammar: (grammar) -> + @languageMode.grammar = grammar + @handleGrammarChange() + reloadGrammar: -> - if @languageMode.reloadGrammar() - @unfoldAll() - @displayBuffer.tokenizedBuffer.resetScreenLines() - @trigger 'grammar-changed' - true + @handleGrammarChange() if @languageMode.reloadGrammar() + + handleGrammarChange: -> + @unfoldAll() + @displayBuffer.tokenizedBuffer.resetScreenLines() + @trigger 'grammar-changed' + true getDebugSnapshot: -> [ diff --git a/src/app/editor.coffee b/src/app/editor.coffee index c2152f0d3..906b5fbd4 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -1143,7 +1143,13 @@ class Editor extends View else @highlightedLine = null - getGrammar: -> @activeEditSession.getGrammar() + getGrammar: -> + @activeEditSession.getGrammar() + + setGrammar: (grammar) -> + throw new Error("Only mini-editors can explicity set their grammar") unless @mini + @activeEditSession.setGrammar(grammar) + @handleGrammarChange() selectGrammar: -> GrammarView = require 'grammar-view' @@ -1151,11 +1157,13 @@ class Editor extends View reloadGrammar: -> grammarChanged = @activeEditSession.reloadGrammar() - if grammarChanged - @clearRenderedLines() - @updateDisplay() + @handleGrammarChange() if grammarChanged grammarChanged + handleGrammarChange: -> + @clearRenderedLines() + @updateDisplay() + bindToKeyedEvent: (key, event, callback) -> binding = {} binding[key] = event From d14ddf6f38c644cad03a91bff0e102cb8d9ce282 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 14:12:41 -0400 Subject: [PATCH 66/79] Remove unused require --- src/app/text-mate-package.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index dcaddeebc..a6ef9b8fd 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -1,5 +1,4 @@ Package = require 'package' -fs = require 'fs' fsUtils = require 'fs-utils' plist = require 'plist' _ = require 'underscore' From 4c9ebc940c02b797dd5d49bd425e2cd119e7f538 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 14:17:36 -0400 Subject: [PATCH 67/79] Remove unneeded initialization of variable from superclass --- src/packages/command-palette/lib/command-palette-view.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/packages/command-palette/lib/command-palette-view.coffee b/src/packages/command-palette/lib/command-palette-view.coffee index 2acb80753..f8371efe7 100644 --- a/src/packages/command-palette/lib/command-palette-view.coffee +++ b/src/packages/command-palette/lib/command-palette-view.coffee @@ -13,7 +13,6 @@ class CommandPaletteView extends SelectList filterKey: 'eventDescription' - previouslyFocusedElement: null keyBindings: null initialize: -> From 7f8adf247e39838e6fdc0293833eab655a707cc0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 14:26:53 -0400 Subject: [PATCH 68/79] Show root view events when no element has focus Closes #327 --- .../lib/command-palette-view.coffee | 10 +++++++--- .../spec/command-palette-spec.coffee | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/packages/command-palette/lib/command-palette-view.coffee b/src/packages/command-palette/lib/command-palette-view.coffee index f8371efe7..34988e751 100644 --- a/src/packages/command-palette/lib/command-palette-view.coffee +++ b/src/packages/command-palette/lib/command-palette-view.coffee @@ -29,10 +29,14 @@ class CommandPaletteView extends SelectList attach: -> super - @keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement)) + if @previouslyFocusedElement[0] + @eventElement = @previouslyFocusedElement + else + @eventElement = rootView + @keyBindings = _.losslessInvert(keymap.bindingsForElement(@eventElement)) events = [] - for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events()) + for eventName, eventDescription of _.extend($(window).events(), @eventElement.events()) events.push({eventName, eventDescription}) if eventDescription events = _.sortBy events, (e) -> e.eventDescription @@ -52,4 +56,4 @@ class CommandPaletteView extends SelectList confirmed: ({eventName}) -> @cancel() - @previouslyFocusedElement.trigger(eventName) + @eventElement.trigger(eventName) diff --git a/src/packages/command-palette/spec/command-palette-spec.coffee b/src/packages/command-palette/spec/command-palette-spec.coffee index 1cb533864..a0de19c61 100644 --- a/src/packages/command-palette/spec/command-palette-spec.coffee +++ b/src/packages/command-palette/spec/command-palette-spec.coffee @@ -81,3 +81,20 @@ describe "CommandPalette", -> expect(activeEditor.isFocused).toBeTruthy() expect(eventHandler).toHaveBeenCalled() expect(palette.hasParent()).toBeFalsy() + + describe "when no element has focus", -> + it "uses the root view as the element to display and trigger events for", -> + rootView.trigger 'command-palette:toggle' + $(':focus').blur() + rootView.trigger 'command-palette:toggle' + keyBindings = _.losslessInvert(keymap.bindingsForElement(rootView.getActiveView())) + for eventName, description of rootView.events() + eventLi = palette.list.children("[data-event-name='#{eventName}']") + if description + expect(eventLi).toExist() + expect(eventLi.find('.label')).toHaveText(description) + expect(eventLi.find('.label').attr('title')).toBe(eventName) + for binding in keyBindings[eventName] ? [] + expect(eventLi.find(".key-binding:contains(#{binding})")).toExist() + else + expect(eventLi).not.toExist() From b6334483c95103ba88726db59ae4f8eecdb9ff72 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 15:41:26 -0400 Subject: [PATCH 69/79] Hide the loading message when eval throws an error --- src/packages/command-panel/lib/command-panel-view.coffee | 1 + src/packages/command-panel/spec/command-panel-spec.coffee | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/packages/command-panel/lib/command-panel-view.coffee b/src/packages/command-panel/lib/command-panel-view.coffee index 74806feda..a0255a6c0 100644 --- a/src/packages/command-panel/lib/command-panel-view.coffee +++ b/src/packages/command-panel/lib/command-panel-view.coffee @@ -141,6 +141,7 @@ class CommandPanelView extends View else @detach() catch error + @loadingMessage.hide() if error.name is "SyntaxError" @flashError() return diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee index cf86ae0b4..782399da3 100644 --- a/src/packages/command-panel/spec/command-panel-spec.coffee +++ b/src/packages/command-panel/spec/command-panel-spec.coffee @@ -345,13 +345,15 @@ describe "CommandPanel", -> # there shouldn't be any dangling operations after this describe "if the command is malformed", -> - it "adds and removes an error class to the command panel and does not close it", -> + it "adds and removes an error class to the command panel and does not close it or display a loading message", -> + rootView.attachToDom() rootView.trigger 'command-panel:toggle' commandPanel.miniEditor.insertText 'garbage-command!!' commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter') expect(commandPanel.parent()).toExist() expect(commandPanel).toHaveClass 'error' + expect(commandPanel.loadingMessage).toBeHidden() advanceClock 400 From 1d842749734c4b4316c072d7abce619a7cf89ef6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 17:56:25 -0400 Subject: [PATCH 70/79] Return existing selections from addSelection() Previously if a selection was added and then merged away the selection-added event would still fire even though the selection was already destroyed. Now the existing selection that intersects with the range is returned when the merge destroys the new selection. Closes #374 --- spec/app/edit-session-spec.coffee | 14 ++++++++++++++ src/app/edit-session.coffee | 10 ++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/spec/app/edit-session-spec.coffee b/spec/app/edit-session-spec.coffee index c6870c7f7..3337d526b 100644 --- a/spec/app/edit-session-spec.coffee +++ b/spec/app/edit-session-spec.coffee @@ -396,6 +396,20 @@ describe "EditSession", -> buffer.insert([8, 0], '...') expect(cursorMovedHandler).not.toHaveBeenCalled() + describe "addCursorAtScreenPosition(screenPosition)", -> + describe "when a cursor already exists at the position", -> + it "returns the existing cursor", -> + cursor1 = editSession.addCursorAtScreenPosition([0,2]) + cursor2 = editSession.addCursorAtScreenPosition([0,2]) + expect(cursor2.marker).toBe cursor1.marker + + describe "addCursorAtBufferPosition(bufferPosition)", -> + describe "when a cursor already exists at the position", -> + it "returns the existing cursor", -> + cursor1 = editSession.addCursorAtBufferPosition([1,4]) + cursor2 = editSession.addCursorAtBufferPosition([1,4]) + expect(cursor2.marker).toBe cursor1.marker + describe "selection", -> selection = null diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index f1ddfa232..e14baa16a 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -584,9 +584,15 @@ class EditSession cursor = @addCursor(marker) selection = new Selection({editSession: this, marker, cursor}) @selections.push(selection) + selectionBufferRange = selection.getBufferRange() @mergeIntersectingSelections() - @trigger 'selection-added', selection - selection + if selection.destroyed + for selection in @getSelections() + if selection.intersectsBufferRange(selectionBufferRange) + return selection + else + @trigger 'selection-added', selection + selection addSelectionForBufferRange: (bufferRange, options={}) -> options = _.defaults({invalidationStrategy: 'never'}, options) From a48a52922b722f2dad7c03b58c49a357e0fb0c22 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 12:02:23 -0700 Subject: [PATCH 71/79] Indent soft-wrap spec correctly --- spec/app/editor-spec.coffee | 169 ++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index e8c416da7..160affc98 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -1050,90 +1050,6 @@ describe "Editor", -> buffer.insert([1,0], "/*") expect(editor.renderedLines.find('.line:eq(2) > span:first > span:first')).toMatchSelector '.comment' - describe "when soft-wrap is enabled", -> - beforeEach -> - setEditorHeightInLines(editor, 20) - setEditorWidthInChars(editor, 50) - editor.setSoftWrap(true) - expect(editor.activeEditSession.softWrapColumn).toBe 50 - - it "wraps lines that are too long to fit within the editor's width, adjusting cursor positioning accordingly", -> - expect(editor.renderedLines.find('.line').length).toBe 16 - expect(editor.renderedLines.find('.line:eq(3)').text()).toBe " var pivot = items.shift(), current, left = [], " - expect(editor.renderedLines.find('.line:eq(4)').text()).toBe "right = [];" - - editor.setCursorBufferPosition([3, 51], wrapAtSoftNewlines: true) - expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(4)').offset()) - - editor.setCursorBufferPosition([4, 0]) - expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(5)').offset()) - - editor.getSelection().setBufferRange(new Range([6, 30], [6, 55])) - [region1, region2] = editor.getSelectionView().regions - expect(region1.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(7)').offset().top) - expect(region2.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(8)').offset().top) - - it "handles changes to wrapped lines correctly", -> - buffer.insert([6, 28], '1234567') - expect(editor.renderedLines.find('.line:eq(7)').text()).toBe ' current < pivot ? left1234567.push(current) ' - expect(editor.renderedLines.find('.line:eq(8)').text()).toBe ': right.push(current);' - expect(editor.renderedLines.find('.line:eq(9)').text()).toBe ' }' - - it "changes the max line length and repositions the cursor when the window size changes", -> - editor.setCursorBufferPosition([3, 60]) - setEditorWidthInChars(editor, 40) - expect(editor.renderedLines.find('.line').length).toBe 19 - expect(editor.renderedLines.find('.line:eq(4)').text()).toBe "left = [], right = [];" - expect(editor.renderedLines.find('.line:eq(5)').text()).toBe " while(items.length > 0) {" - expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60] - - it "does not wrap the lines of any newly assigned buffers", -> - otherEditSession = project.buildEditSession() - otherEditSession.buffer.setText([1..100].join('')) - editor.edit(otherEditSession) - expect(editor.renderedLines.find('.line').length).toBe(1) - - it "unwraps lines and cancels window resize listener when softwrap is disabled", -> - editor.toggleSoftWrap() - expect(editor.renderedLines.find('.line:eq(3)').text()).toBe ' var pivot = items.shift(), current, left = [], right = [];' - - spyOn(editor, 'setSoftWrapColumn') - $(window).trigger 'resize' - expect(editor.setSoftWrapColumn).not.toHaveBeenCalled() - - it "allows the cursor to move down to the last line", -> - _.times editor.getLastScreenRow(), -> editor.moveCursorDown() - expect(editor.getCursorScreenPosition()).toEqual [editor.getLastScreenRow(), 0] - editor.moveCursorDown() - expect(editor.getCursorScreenPosition()).toEqual [editor.getLastScreenRow(), 2] - - it "allows the cursor to move up to a shorter soft wrapped line", -> - editor.setCursorScreenPosition([11, 15]) - editor.moveCursorUp() - expect(editor.getCursorScreenPosition()).toEqual [10, 10] - editor.moveCursorUp() - editor.moveCursorUp() - expect(editor.getCursorScreenPosition()).toEqual [8, 15] - - it "it allows the cursor to wrap when moving horizontally past the beginning / end of a wrapped line", -> - editor.setCursorScreenPosition([11, 0]) - editor.moveCursorLeft() - expect(editor.getCursorScreenPosition()).toEqual [10, 10] - - editor.moveCursorRight() - expect(editor.getCursorScreenPosition()).toEqual [11, 0] - - it "calls .setSoftWrapColumn() when the editor is attached because now its dimensions are available to calculate it", -> - otherEditor = new Editor(editSession: project.buildEditSession('sample.js')) - spyOn(otherEditor, 'setSoftWrapColumn') - - otherEditor.setSoftWrap(true) - expect(otherEditor.setSoftWrapColumn).not.toHaveBeenCalled() - - otherEditor.simulateDomAttachment() - expect(otherEditor.setSoftWrapColumn).toHaveBeenCalled() - otherEditor.remove() - describe "when some lines at the end of the buffer are not visible on screen", -> beforeEach -> editor.attachToDom(heightInLines: 5.5) @@ -1582,6 +1498,91 @@ describe "Editor", -> expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + describe "when soft-wrap is enabled", -> + beforeEach -> + editor.attachToDom() + setEditorHeightInLines(editor, 20) + setEditorWidthInChars(editor, 50) + editor.setSoftWrap(true) + expect(editor.activeEditSession.softWrapColumn).toBe 50 + + it "wraps lines that are too long to fit within the editor's width, adjusting cursor positioning accordingly", -> + expect(editor.renderedLines.find('.line').length).toBe 16 + expect(editor.renderedLines.find('.line:eq(3)').text()).toBe " var pivot = items.shift(), current, left = [], " + expect(editor.renderedLines.find('.line:eq(4)').text()).toBe "right = [];" + + editor.setCursorBufferPosition([3, 51], wrapAtSoftNewlines: true) + expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(4)').offset()) + + editor.setCursorBufferPosition([4, 0]) + expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(5)').offset()) + + editor.getSelection().setBufferRange(new Range([6, 30], [6, 55])) + [region1, region2] = editor.getSelectionView().regions + expect(region1.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(7)').offset().top) + expect(region2.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(8)').offset().top) + + it "handles changes to wrapped lines correctly", -> + buffer.insert([6, 28], '1234567') + expect(editor.renderedLines.find('.line:eq(7)').text()).toBe ' current < pivot ? left1234567.push(current) ' + expect(editor.renderedLines.find('.line:eq(8)').text()).toBe ': right.push(current);' + expect(editor.renderedLines.find('.line:eq(9)').text()).toBe ' }' + + it "changes the max line length and repositions the cursor when the window size changes", -> + editor.setCursorBufferPosition([3, 60]) + setEditorWidthInChars(editor, 40) + expect(editor.renderedLines.find('.line').length).toBe 19 + expect(editor.renderedLines.find('.line:eq(4)').text()).toBe "left = [], right = [];" + expect(editor.renderedLines.find('.line:eq(5)').text()).toBe " while(items.length > 0) {" + expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60] + + it "does not wrap the lines of any newly assigned buffers", -> + otherEditSession = project.buildEditSession() + otherEditSession.buffer.setText([1..100].join('')) + editor.edit(otherEditSession) + expect(editor.renderedLines.find('.line').length).toBe(1) + + it "unwraps lines and cancels window resize listener when softwrap is disabled", -> + editor.toggleSoftWrap() + expect(editor.renderedLines.find('.line:eq(3)').text()).toBe ' var pivot = items.shift(), current, left = [], right = [];' + + spyOn(editor, 'setSoftWrapColumn') + $(window).trigger 'resize' + expect(editor.setSoftWrapColumn).not.toHaveBeenCalled() + + it "allows the cursor to move down to the last line", -> + _.times editor.getLastScreenRow(), -> editor.moveCursorDown() + expect(editor.getCursorScreenPosition()).toEqual [editor.getLastScreenRow(), 0] + editor.moveCursorDown() + expect(editor.getCursorScreenPosition()).toEqual [editor.getLastScreenRow(), 2] + + it "allows the cursor to move up to a shorter soft wrapped line", -> + editor.setCursorScreenPosition([11, 15]) + editor.moveCursorUp() + expect(editor.getCursorScreenPosition()).toEqual [10, 10] + editor.moveCursorUp() + editor.moveCursorUp() + expect(editor.getCursorScreenPosition()).toEqual [8, 15] + + it "it allows the cursor to wrap when moving horizontally past the beginning / end of a wrapped line", -> + editor.setCursorScreenPosition([11, 0]) + editor.moveCursorLeft() + expect(editor.getCursorScreenPosition()).toEqual [10, 10] + + editor.moveCursorRight() + expect(editor.getCursorScreenPosition()).toEqual [11, 0] + + it "calls .setSoftWrapColumn() when the editor is attached because now its dimensions are available to calculate it", -> + otherEditor = new Editor(editSession: project.buildEditSession('sample.js')) + spyOn(otherEditor, 'setSoftWrapColumn') + + otherEditor.setSoftWrap(true) + expect(otherEditor.setSoftWrapColumn).not.toHaveBeenCalled() + + otherEditor.simulateDomAttachment() + expect(otherEditor.setSoftWrapColumn).toHaveBeenCalled() + otherEditor.remove() + describe "gutter rendering", -> beforeEach -> editor.attachToDom(heightInLines: 5.5) From fd7772a653828c7367db636e84564d8ded63f10a Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 15:07:30 -0700 Subject: [PATCH 72/79] Reset scrollLeft when setSoftWrapColumn is called When the scroll view is scrolled and overflow-x is set to 'hidden' the scroll view renders wrong. Setting scrollLeft to 0 fixes this problem. I'm unhappy with this solution, but it was a simple way to get the scroll view to update its layout. Closes #137 --- spec/app/editor-spec.coffee | 9 +++++++++ src/app/editor.coffee | 1 + 2 files changed, 10 insertions(+) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 160affc98..92d8b662b 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -977,6 +977,15 @@ describe "Editor", -> editor.setCursorScreenPosition([2, 5]) expect(editor.scrollView.scrollLeft()).toBe 0 + describe "when editor:toggle-soft-wrap is toggled", -> + describe "when the text exceeds the editor width and the scroll-view is horizontally scrolled", -> + it "wraps the text and renders properly", -> + editor.attachToDom(heightInLines: 30, widthInChars: 30) + editor.setText("Fashion axe umami jean shorts retro hashtag carles mumblecore. Photo booth skateboard Austin gentrify occupy ethical. Food truck gastropub keffiyeh, squid deep v pinterest literally sustainable salvia scenester messenger bag. Neutra messenger bag flexitarian four loko, shoreditch VHS pop-up tumblr seitan synth master cleanse. Marfa selvage ugh, raw denim authentic try-hard mcsweeney's trust fund fashion axe actually polaroid viral sriracha. Banh mi marfa plaid single-origin coffee. Pickled mumblecore lomo ugh bespoke.") + editor.scrollView.scrollLeft(editor.charWidth * 30) + editor.trigger "editor:toggle-soft-wrap" + expect(editor.scrollView.scrollLeft()).toBe 0 + describe "text rendering", -> describe "when all lines in the buffer are visible on screen", -> beforeEach -> diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 906b5fbd4..4ae1a6bd5 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -590,6 +590,7 @@ class Editor extends View @setSoftWrapColumn(softWrapColumn) if @attached if @activeEditSession.getSoftWrap() @addClass 'soft-wrap' + @scrollView.scrollLeft(0) @_setSoftWrapColumn = => @setSoftWrapColumn() $(window).on "resize.editor-#{@id}", @_setSoftWrapColumn else From 8323b0defd7afeb35b98e6ea227487472d4f4608 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 16:30:33 -0700 Subject: [PATCH 73/79] :lipstick: --- src/packages/gists/lib/gists.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/gists/lib/gists.coffee b/src/packages/gists/lib/gists.coffee index 6df96a01d..cada1d582 100644 --- a/src/packages/gists/lib/gists.coffee +++ b/src/packages/gists/lib/gists.coffee @@ -8,7 +8,7 @@ class Gists constructor: -> rootView.command 'gist:create', '.editor', => @createGist() - createGist: (editor) -> + createGist: -> editor = rootView.getActiveView() return unless editor? From 5308e03096e20f8235dc639b2e1c2736951a0def Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 17:02:13 -0700 Subject: [PATCH 74/79] Move GrammarView into GrammarSelector package --- src/app/editor.coffee | 5 -- src/app/keymaps/editor.cson | 1 - .../keymaps/grammar-selector.cson | 3 + .../lib/grammar-selector.coffee | 64 +++++++++++++++++++ src/packages/grammar-selector/package.cson | 2 + .../spec/grammar-selector-spec.coffee | 47 ++++++++++++++ 6 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 src/packages/grammar-selector/keymaps/grammar-selector.cson create mode 100644 src/packages/grammar-selector/lib/grammar-selector.coffee create mode 100644 src/packages/grammar-selector/package.cson create mode 100644 src/packages/grammar-selector/spec/grammar-selector-spec.coffee diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 4ae1a6bd5..f17284bee 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -150,7 +150,6 @@ class Editor extends View 'editor:toggle-line-comments': @toggleLineCommentsInSelection 'editor:log-cursor-scope': @logCursorScope 'editor:checkout-head-revision': @checkoutHead - 'editor:select-grammar': @selectGrammar 'editor:copy-path': @copyPathToPasteboard 'editor:move-line-up': @moveLineUp 'editor:move-line-down': @moveLineDown @@ -1152,10 +1151,6 @@ class Editor extends View @activeEditSession.setGrammar(grammar) @handleGrammarChange() - selectGrammar: -> - GrammarView = require 'grammar-view' - new GrammarView(this) - reloadGrammar: -> grammarChanged = @activeEditSession.reloadGrammar() @handleGrammarChange() if grammarChanged diff --git a/src/app/keymaps/editor.cson b/src/app/keymaps/editor.cson index 8b192fece..f9675e6c1 100644 --- a/src/app/keymaps/editor.cson +++ b/src/app/keymaps/editor.cson @@ -20,7 +20,6 @@ 'meta-U': 'editor:lower-case' 'alt-meta-w': 'editor:close-other-edit-sessions' 'meta-P': 'editor:close-all-edit-sessions' - 'meta-L': 'editor:select-grammar' 'ctrl-C': 'editor:copy-path' 'ctrl-meta-up': 'editor:move-line-up' 'ctrl-meta-down': 'editor:move-line-down' diff --git a/src/packages/grammar-selector/keymaps/grammar-selector.cson b/src/packages/grammar-selector/keymaps/grammar-selector.cson new file mode 100644 index 000000000..07e5050bd --- /dev/null +++ b/src/packages/grammar-selector/keymaps/grammar-selector.cson @@ -0,0 +1,3 @@ +'.editor': + 'meta-L': 'grammar-selector:show' + diff --git a/src/packages/grammar-selector/lib/grammar-selector.coffee b/src/packages/grammar-selector/lib/grammar-selector.coffee new file mode 100644 index 000000000..ca0aa828b --- /dev/null +++ b/src/packages/grammar-selector/lib/grammar-selector.coffee @@ -0,0 +1,64 @@ +SelectList = require 'select-list' +Editor = require 'editor' +{$$} = require 'space-pen' + +module.exports = +class GrammarSelector extends SelectList + @viewClass: -> "#{super} grammar-selector from-top overlay mini" + + @activate: -> + rootView.command 'grammar-selector:show', '.editor', => new GrammarSelector() + + filterKey: 'name' + + initialize: -> + @editor = rootView.getActiveView() + return unless @editor instanceof Editor + @currentGrammar = @editor.getGrammar() + @path = @editor.getPath() + @autoDetect = name: 'Auto Detect' + @command 'grammar-selector:show', => + @cancel() + false + super + + @populate() + @attach() + + itemForElement: (grammar) -> + if grammar is @currentGrammar + grammarClass = 'active-item' + else + grammarClass = 'inactive-item' + + $$ -> + @li grammar.name, class: grammarClass + + populate: -> + grammars = new Array(syntax.grammars...) + grammars.sort (grammarA, grammarB) -> + if grammarA.scopeName is 'text.plain' + -1 + else if grammarB.scopeName is 'text.plain' + 1 + else if grammarA.name < grammarB.name + -1 + else if grammarA.name > grammarB.name + 1 + else + 0 + grammars.unshift(@autoDetect) + @setArray(grammars) + + confirmed: (grammar) -> + @cancel() + if grammar is @autoDetect + syntax.clearGrammarOverrideForPath(@path) + else + syntax.setGrammarOverrideForPath(@path, grammar.scopeName) + @editor.reloadGrammar() + + attach: -> + super + rootView.append(this) + @miniEditor.focus() \ No newline at end of file diff --git a/src/packages/grammar-selector/package.cson b/src/packages/grammar-selector/package.cson new file mode 100644 index 000000000..99390e3bc --- /dev/null +++ b/src/packages/grammar-selector/package.cson @@ -0,0 +1,2 @@ +'main': 'lib/grammar-selector' +'activationEvents': ['grammar-selector:show'] diff --git a/src/packages/grammar-selector/spec/grammar-selector-spec.coffee b/src/packages/grammar-selector/spec/grammar-selector-spec.coffee new file mode 100644 index 000000000..367b74472 --- /dev/null +++ b/src/packages/grammar-selector/spec/grammar-selector-spec.coffee @@ -0,0 +1,47 @@ +GrammarSelector = require '../lib/grammar-selector' +RootView = require 'root-view' +_ = require 'underscore' + +fdescribe "GrammarSelector", -> + [editor, textGrammar, jsGrammar] = [] + + beforeEach -> + window.rootView = new RootView + atom.activatePackage('grammar-selector') + atom.activatePackage('text.tmbundle', sync: true) + atom.activatePackage('javascript.tmbundle', sync: true) + rootView.open('sample.js') + editor = rootView.getActiveView() + textGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'Plain Text' + expect(textGrammar).toBeTruthy() + jsGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'JavaScript' + expect(jsGrammar).toBeTruthy() + expect(editor.getGrammar()).toBe jsGrammar + + describe "when grammar-selector:show is triggered", -> + it "displays a list of all the available grammars", -> + editor.trigger 'grammar-selector:show' + grammarView = rootView.find('.grammar-selector').view() + expect(grammarView).toExist() + grammars = syntax.grammars + expect(grammarView.list.children('li').length).toBe grammars.length + 1 + expect(grammarView.list.children('li:first').text()).toBe 'Auto Detect' + + describe "when a grammar is selected", -> + it "sets the new grammar on the editor", -> + editor.trigger 'grammar-selector:show' + grammarView = rootView.find('.grammar-selector').view() + grammarView.confirmed(textGrammar) + expect(editor.getGrammar()).toBe textGrammar + + describe "when auto-detect is selected", -> + it "restores the auto-detected grammar on the editor", -> + editor.trigger 'grammar-selector:show' + grammarView = rootView.find('.grammar-selector').view() + grammarView.confirmed(textGrammar) + expect(editor.getGrammar()).toBe textGrammar + + editor.trigger 'grammar-selector:show' + grammarView = rootView.find('.grammar-selector').view() + grammarView.confirmed(grammarView.array[0]) + expect(editor.getGrammar()).toBe jsGrammar From 70010bad56043acf11a3136c155e72a0801e2a89 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 20:30:22 -0400 Subject: [PATCH 75/79] Un-f grammar-selector specs --- src/packages/grammar-selector/spec/grammar-selector-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/grammar-selector/spec/grammar-selector-spec.coffee b/src/packages/grammar-selector/spec/grammar-selector-spec.coffee index 367b74472..db4fa262c 100644 --- a/src/packages/grammar-selector/spec/grammar-selector-spec.coffee +++ b/src/packages/grammar-selector/spec/grammar-selector-spec.coffee @@ -2,7 +2,7 @@ GrammarSelector = require '../lib/grammar-selector' RootView = require 'root-view' _ = require 'underscore' -fdescribe "GrammarSelector", -> +describe "GrammarSelector", -> [editor, textGrammar, jsGrammar] = [] beforeEach -> From 72f57ad993546334e297c3b34664ae8cc055dbc5 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 17:30:49 -0700 Subject: [PATCH 76/79] Remove old grammar view files --- spec/app/grammar-view-spec.coffee | 46 ------------------------ src/app/grammar-view.coffee | 60 ------------------------------- 2 files changed, 106 deletions(-) delete mode 100644 spec/app/grammar-view-spec.coffee delete mode 100644 src/app/grammar-view.coffee diff --git a/spec/app/grammar-view-spec.coffee b/spec/app/grammar-view-spec.coffee deleted file mode 100644 index 9928f85ee..000000000 --- a/spec/app/grammar-view-spec.coffee +++ /dev/null @@ -1,46 +0,0 @@ -RootView = require 'root-view' -GrammarView = require 'grammar-view' -_ = require 'underscore' - -describe "GrammarView", -> - [editor, textGrammar, jsGrammar] = [] - - beforeEach -> - atom.activatePackage('text.tmbundle', sync: true) - atom.activatePackage('javascript.tmbundle', sync: true) - window.rootView = new RootView - rootView.open('sample.js') - editor = rootView.getActiveView() - textGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'Plain Text' - expect(textGrammar).toBeTruthy() - jsGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'JavaScript' - expect(jsGrammar).toBeTruthy() - expect(editor.getGrammar()).toBe jsGrammar - - describe "when editor:select-grammar is toggled", -> - it "displays a list of all the available grammars", -> - editor.trigger 'editor:select-grammar' - grammarView = rootView.find('.grammar-view').view() - expect(grammarView).toExist() - grammars = syntax.grammars - expect(grammarView.list.children('li').length).toBe grammars.length + 1 - expect(grammarView.list.children('li:first').text()).toBe 'Auto Detect' - - describe "when a grammar is selected", -> - it "sets the new grammar on the editor", -> - editor.trigger 'editor:select-grammar' - grammarView = rootView.find('.grammar-view').view() - grammarView.confirmed(textGrammar) - expect(editor.getGrammar()).toBe textGrammar - - describe "when auto-detect is selected", -> - it "restores the auto-detected grammar on the editor", -> - editor.trigger 'editor:select-grammar' - grammarView = rootView.find('.grammar-view').view() - grammarView.confirmed(textGrammar) - expect(editor.getGrammar()).toBe textGrammar - - editor.trigger 'editor:select-grammar' - grammarView = rootView.find('.grammar-view').view() - grammarView.confirmed(grammarView.array[0]) - expect(editor.getGrammar()).toBe jsGrammar diff --git a/src/app/grammar-view.coffee b/src/app/grammar-view.coffee deleted file mode 100644 index 5c1638057..000000000 --- a/src/app/grammar-view.coffee +++ /dev/null @@ -1,60 +0,0 @@ -SelectList = require 'select-list' -{$$} = require 'space-pen' - -module.exports = -class GrammarView extends SelectList - - @viewClass: -> "#{super} grammar-view from-top overlay mini" - - filterKey: 'name' - - initialize: (@editor) -> - @currentGrammar = @editor.getGrammar() - @path = @editor.getPath() - @autoDetect = name: 'Auto Detect' - @command 'editor:select-grammar', => - @cancel() - false - super - - @populate() - @attach() - - itemForElement: (grammar) -> - if grammar is @currentGrammar - grammarClass = 'active-item' - else - grammarClass = 'inactive-item' - - $$ -> - @li grammar.name, class: grammarClass - - populate: -> - grammars = new Array(syntax.grammars...) - grammars.sort (grammarA, grammarB) -> - if grammarA.scopeName is 'text.plain' - -1 - else if grammarB.scopeName is 'text.plain' - 1 - else if grammarA.name < grammarB.name - -1 - else if grammarA.name > grammarB.name - 1 - else - 0 - grammars.unshift(@autoDetect) - @setArray(grammars) - - confirmed: (grammar) -> - @cancel() - if grammar is @autoDetect - syntax.clearGrammarOverrideForPath(@path) - else - syntax.setGrammarOverrideForPath(@path, grammar.scopeName) - @editor.reloadGrammar() - - attach: -> - super - - rootView.append(this) - @miniEditor.focus() From 0fe93bef9128a50966f1221841a45d503fb07dd1 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 27 Mar 2013 17:32:15 -0700 Subject: [PATCH 77/79] StatusBar now triggers `grammar-selector:show` --- src/packages/status-bar/lib/status-bar-view.coffee | 2 +- src/packages/status-bar/spec/status-bar-spec.coffee | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/status-bar/lib/status-bar-view.coffee b/src/packages/status-bar/lib/status-bar-view.coffee index 152136a0d..ecae8af28 100644 --- a/src/packages/status-bar/lib/status-bar-view.coffee +++ b/src/packages/status-bar/lib/status-bar-view.coffee @@ -34,7 +34,7 @@ class StatusBarView extends View @updateCursorPositionText() @subscribe @editor, 'cursor:moved', => @updateCursorPositionText() - @subscribe @grammarName, 'click', => @editor.trigger 'editor:select-grammar' + @subscribe @grammarName, 'click', => @editor.trigger 'grammar-selector:show' @subscribe @editor, 'editor:grammar-changed', => @updateGrammarText() if git? @subscribe git, 'status-changed', (path, status) => diff --git a/src/packages/status-bar/spec/status-bar-spec.coffee b/src/packages/status-bar/spec/status-bar-spec.coffee index ec4329b6b..497a4143d 100644 --- a/src/packages/status-bar/spec/status-bar-spec.coffee +++ b/src/packages/status-bar/spec/status-bar-spec.coffee @@ -205,8 +205,8 @@ describe "StatusBar", -> expect(statusBar.find('.grammar-name').text()).toBe 'Plain Text' describe "when clicked", -> - it "toggles the editor:select-grammar event", -> + it "toggles the grammar-selector:show event", -> eventHandler = jasmine.createSpy('eventHandler') - editor.on 'editor:select-grammar', eventHandler + editor.on 'grammar-selector:show', eventHandler statusBar.find('.grammar-name').click() expect(eventHandler).toHaveBeenCalled() From a3483d0ffeb16ad47e15980fc58377d5fc1e125f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 20:51:01 -0400 Subject: [PATCH 78/79] Remove native injection from web worker contexts Tasks are now processed based and so web workers no longer need access to the native extension. --- native/atom_cef_render_process_handler.h | 12 ------------ native/atom_cef_render_process_handler.mm | 21 --------------------- 2 files changed, 33 deletions(-) diff --git a/native/atom_cef_render_process_handler.h b/native/atom_cef_render_process_handler.h index 973086245..96fe15a5c 100644 --- a/native/atom_cef_render_process_handler.h +++ b/native/atom_cef_render_process_handler.h @@ -16,17 +16,6 @@ class AtomCefRenderProcessHandler : public CefRenderProcessHandler { virtual bool OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) OVERRIDE; - virtual void OnWorkerContextCreated(int worker_id, - const CefString& url, - CefRefPtr context) OVERRIDE; - virtual void OnWorkerContextReleased(int worker_id, - const CefString& url, - CefRefPtr context) OVERRIDE; - virtual void OnWorkerUncaughtException(int worker_id, - const CefString& url, - CefRefPtr context, - CefRefPtr exception, - CefRefPtr stackTrace) OVERRIDE; void Reload(CefRefPtr browser); void Shutdown(CefRefPtr browser); @@ -37,4 +26,3 @@ class AtomCefRenderProcessHandler : public CefRenderProcessHandler { }; #endif // ATOM_CEF_RENDER_PROCESS_HANDLER_H_ - diff --git a/native/atom_cef_render_process_handler.mm b/native/atom_cef_render_process_handler.mm index fd0a60a58..b3147478c 100644 --- a/native/atom_cef_render_process_handler.mm +++ b/native/atom_cef_render_process_handler.mm @@ -21,27 +21,6 @@ void AtomCefRenderProcessHandler::OnContextReleased(CefRefPtr browse [PathWatcher removePathWatcherForContext:context]; } -void AtomCefRenderProcessHandler::OnWorkerContextCreated(int worker_id, - const CefString& url, - CefRefPtr context) { - InjectExtensionsIntoV8Context(context); -} - -void AtomCefRenderProcessHandler::OnWorkerContextReleased(int worker_id, - const CefString& url, - CefRefPtr context) { -} - -void AtomCefRenderProcessHandler::OnWorkerUncaughtException(int worker_id, - const CefString& url, - CefRefPtr context, - CefRefPtr exception, - CefRefPtr stackTrace) { - - std::string message = exception->GetMessage().ToString(); - NSLog(@"Exception throw in worker thread %s", message.c_str()); -} - bool AtomCefRenderProcessHandler::OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) { From d54f2e6eabd5f8e39605bc7e02ede1c9bd731c4f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 27 Mar 2013 20:56:24 -0400 Subject: [PATCH 79/79] Only track selections that start with a left-click Closes #396 --- spec/app/editor-spec.coffee | 14 ++++++++++++++ src/app/editor.coffee | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 92d8b662b..885981485 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -558,6 +558,20 @@ describe "Editor", -> expect(editor.scrollTop()).toBe 0 + it "ignores non left-click and drags", -> + editor.attachToDom() + editor.css(position: 'absolute', top: 10, left: 10) + + event = mousedownEvent(editor: editor, point: [4, 10]) + event.originalEvent.which = 2 + editor.renderedLines.trigger(event) + $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) + $(document).trigger 'mouseup' + + range = editor.getSelection().getScreenRange() + expect(range.start).toEqual({row: 4, column: 10}) + expect(range.end).toEqual({row: 4, column: 10}) + describe "double-click and drag", -> it "selects the word under the cursor, then continues to select by word in either direction as the mouse is dragged", -> expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index f17284bee..9377de760 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -373,7 +373,7 @@ class Editor extends View else if clickCount == 3 @activeEditSession.selectLine() unless e.shiftKey - @selectOnMousemoveUntilMouseup() + @selectOnMousemoveUntilMouseup() unless e.originalEvent.which > 1 @renderedLines.on 'mousedown', onMouseDown