From 077cb9ddb763934d109f9fe00f3b4db9d8018d07 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 17 Oct 2013 15:15:57 -0700 Subject: [PATCH 01/48] Add an enableTheme() function to ThemeManager And use it in the activatePackage() function in PackageManager --- spec/atom-spec.coffee | 9 ++++++++- src/package-manager.coffee | 9 ++++++--- src/theme-manager.coffee | 5 +++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 65eda00c0..9166aacd0 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -192,7 +192,6 @@ describe "the `atom` global", -> expect(atom.contextMenu.definitionsForElement(element)[1].label).toBe "Menu item 1" expect(atom.contextMenu.definitionsForElement(element)[2]).toBeUndefined() - describe "stylesheet loading", -> describe "when the metadata contains a 'stylesheets' manifest", -> it "loads stylesheets from the stylesheets directory as specified by the manifest", -> @@ -225,6 +224,14 @@ describe "the `atom` global", -> expect(atom.themes.stylesheetElementForId(three)).toExist() expect($('#jasmine-content').css('font-size')).toBe '3px' + describe "theme loading", -> + it "properly sets the config.themes to activate the theme when a theme is activated", -> + themeName = "theme-with-package-file" + expect(config.get('core.themes')).not.toContain themeName + atom.activatePackage(themeName) + expect(config.get('core.themes')).toContain themeName + expect(atom.themes.getAvailableNames()).toContain themeName + describe "grammar loading", -> it "loads the package's grammars", -> atom.activatePackage('package-with-grammars') diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 66f06d2ef..a734ac448 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -28,9 +28,12 @@ class PackageManager activatePackage: (name, options) -> if pack = @loadPackage(name, options) - @activePackages[pack.name] = pack - pack.activate(options) - pack + if pack.isTheme() + atom.themes.enableTheme(pack.name) + else + @activePackages[pack.name] = pack + pack.activate(options) + pack deactivatePackages: -> @deactivatePackage(pack.name) for pack in @getActivePackages() diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index c3e097581..9cab3cac8 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -171,6 +171,11 @@ class ThemeManager catch error console.warn("Failed to load theme #{name}", error.stack ? error) + # Public: + enableTheme: (name) -> + themes = config.get('core.themes') + config.set('core.themes', _.uniq(themes.concat([name]))) + # Public: getUserStylesheetPath: -> stylesheetPath = fsUtils.resolve(path.join(config.configDirPath, 'user'), ['css', 'less']) From 56832b11fc15127e916d555c4f6ace5be5d36c5d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 18 Oct 2013 15:24:39 -0700 Subject: [PATCH 02/48] Refactor pkg and themeManager -- all themes stored in the pkg manager --- spec/theme-manager-spec.coffee | 39 ++++---- src/atom-package.coffee | 38 ++++--- src/atom.coffee | 2 +- src/package-manager.coffee | 77 ++++++++++----- src/package.coffee | 7 +- src/theme-manager.coffee | 175 ++++++++++++++------------------- src/theme-package.coffee | 25 +++++ 7 files changed, 198 insertions(+), 165 deletions(-) create mode 100644 src/theme-package.coffee diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index d5d5cc1b3..59ab435ee 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -8,10 +8,25 @@ describe "ThemeManager", -> themeManager = null beforeEach -> - themeManager = new ThemeManager() + themeManager = new ThemeManager(atom.packages) afterEach -> - themeManager.unload() + themeManager.deactivateThemes() + + describe "theme getters and setters", -> + beforeEach -> + atom.packages.loadPackages() + + it 'getLoadedThemes get all the loaded themes', -> + themes = themeManager.getLoadedThemes() + expect(themes).toHaveLength(13) + + it 'getActiveThemes get all the active themes', -> + themeManager.activateThemes() + names = atom.config.get('core.themes') + expect(names.length).toBeGreaterThan(0) + themes = themeManager.getActiveThemes() + expect(themes).toHaveLength(names.length) describe "getImportPaths()", -> it "returns the theme directories before the themes are loaded", -> @@ -32,7 +47,7 @@ describe "ThemeManager", -> it "add/removes stylesheets to reflect the new config value", -> themeManager.on 'reloaded', reloadHandler = jasmine.createSpy() spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null - themeManager.load() + themeManager.activateThemes() config.set('core.themes', []) expect($('style.theme').length).toBe 0 @@ -59,21 +74,7 @@ describe "ThemeManager", -> describe "when a theme fails to load", -> it "logs a warning", -> spyOn(console, 'warn') - themeManager.activateTheme('a-theme-that-will-not-be-found') - expect(console.warn).toHaveBeenCalled() - - describe "theme-loaded event", -> - beforeEach -> - spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null - themeManager.load() - - it "fires when a new theme has been added", -> - themeManager.on 'theme-activated', loadHandler = jasmine.createSpy() - - config.set('core.themes', ['atom-dark-syntax']) - - expect(loadHandler).toHaveBeenCalled() - expect(loadHandler.mostRecentCall.args[0]).toBeInstanceOf AtomPackage + expect(-> themeManager.activateTheme('a-theme-that-will-not-be-found')).toThrow() describe "requireStylesheet(path)", -> it "synchronously loads css at the given path and installs a style tag for it in the head", -> @@ -140,7 +141,7 @@ describe "ThemeManager", -> window.rootView = new RootView rootView.append $$ -> @div class: 'editor' rootView.attachToDom() - themeManager.load() + themeManager.activateThemes() it "loads the correct values from the theme's ui-variables file", -> config.set('core.themes', ['theme-with-ui-variables']) diff --git a/src/atom-package.coffee b/src/atom-package.coffee index 62f7cdc70..f36e06b9e 100644 --- a/src/atom-package.coffee +++ b/src/atom-package.coffee @@ -25,20 +25,18 @@ class AtomPackage extends Package resolvedMainModulePath: false mainModule: null + constructor: (path, {@metadata}) -> + super(path) + @reset() + getType: -> 'atom' - load: -> - @metadata = {} - @stylesheets = [] - @keymaps = [] - @menus = [] - @grammars = [] - @scopedProperties = [] + getStylesheetType: -> 'bundled' + load: -> @measure 'loadTime', => try - @metadata = Package.loadMetadata(@path) - return if @isTheme() + @metadata = Package.loadMetadata(@path) unless @metadata @loadKeymaps() @loadMenus() @@ -55,9 +53,22 @@ class AtomPackage extends Package console.warn "Failed to load package named '#{@name}'", e.stack ? e this + enable: -> + atom.config.removeAtKeyPath('core.disabledPackages', @metadata.name) + + disable: -> + atom.config.pushAtKeyPath('core.disabledPackages', @metadata.name) + + reset: -> + @stylesheets = [] + @keymaps = [] + @menus = [] + @grammars = [] + @scopedProperties = [] + activate: ({immediate}={}) -> @measure 'activateTime', => - @loadStylesheets() if @isTheme() + @loadStylesheets() @activateResources() if @metadata.activationEvents? and not immediate @subscribeToActivationEvents() @@ -69,7 +80,7 @@ class AtomPackage extends Package @activateConfig() @activateStylesheets() if @requireMainModule() - @mainModule.activate(atom.getPackageState(@name) ? {}) + @mainModule.activate(atom.packages.getPackageState(@name) ? {}) @mainActivated = true catch e console.warn "Failed to activate package named '#{@name}'", e.stack @@ -86,7 +97,7 @@ class AtomPackage extends Package activateStylesheets: -> return if @stylesheetsActivated - type = if @metadata.theme then 'theme' else 'bundled' + type = @getStylesheetType() for [stylesheetPath, content] in @stylesheets atom.themes.applyStylesheet(stylesheetPath, content, type) @stylesheetsActivated = true @@ -183,8 +194,7 @@ class AtomPackage extends Package @reloadStylesheet(stylesheetPath, content) for [stylesheetPath, content] in @stylesheets reloadStylesheet: (stylesheetPath, content) -> - type = if @metadata.theme then 'theme' else 'bundled' - atom.themes.applyStylesheet(stylesheetPath, content, type) + atom.themes.applyStylesheet(stylesheetPath, content, @getStylesheetType()) requireMainModule: -> return @mainModule if @mainModule? diff --git a/src/atom.coffee b/src/atom.coffee index 8aadbbe5b..32e634d88 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -55,7 +55,7 @@ class Atom @__defineSetter__ 'packageStates', (packageStates) => @packages.packageStates = packageStates @subscribe @packages, 'loaded', => @watchThemes() - @themes = new ThemeManager() + @themes = new ThemeManager(@packages) @contextMenu = new ContextMenuManager(devMode) @menu = new MenuManager() @pasteboard = new Pasteboard() diff --git a/src/package-manager.coffee b/src/package-manager.coffee index a734ac448..4e499f45d 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -4,6 +4,21 @@ _ = require 'underscore-plus' Package = require './package' path = require 'path' +### +Packages have a lifecycle + +* The paths to all non-disabled packages and themes are found on disk (these are available packages) +* Every package (except those in core.disabledPackages) is 'loaded', meaning + `Package` objects are created, and their metadata loaded. This includes themes, + as themes are packages +* Each non-theme package is 'activated', meaning its resources are loaded into the +* Packages and themes can be enabled and disabled, and + +TODO: +* test that it doesnt activate all the theme packages +* originally disabled packages can be enabled, and loaded without reloading +* config.observe the core.disabledPackages +### module.exports = class PackageManager Emitter.includeInto(this) @@ -23,17 +38,25 @@ class PackageManager setPackageState: (name, state) -> @packageStates[name] = state + enablePackage: (name) -> + pack = @loadPackage(name) + pack?.enable() + + disablePackage: (name) -> + pack = @loadPackage(name) + pack?.disable() + activatePackages: -> - @activatePackage(pack.name) for pack in @getLoadedPackages() + # ThemeManager handles themes. Only activate non theme packages + # This is the only part I dislike + @activatePackage(pack.name) for pack in @getLoadedPackages() when not pack.isTheme() activatePackage: (name, options) -> + return if @getActivePackage(name) if pack = @loadPackage(name, options) - if pack.isTheme() - atom.themes.enableTheme(pack.name) - else - @activePackages[pack.name] = pack - pack.activate(options) - pack + @activePackages[pack.name] = pack + pack.activate(options) + pack deactivatePackages: -> @deactivatePackage(pack.name) for pack in @getActivePackages() @@ -46,15 +69,15 @@ class PackageManager else throw new Error("No active package for name '#{name}'") + getActivePackages: -> + _.values(@activePackages) + getActivePackage: (name) -> @activePackages[name] isPackageActive: (name) -> @getActivePackage(name)? - getActivePackages: -> - _.values(@activePackages) - loadPackages: -> # Ensure atom exports is already in the require cache so the load time # of the first package isn't skewed by being the first to require atom @@ -67,14 +90,14 @@ class PackageManager if @isPackageDisabled(name) return console.warn("Tried to load disabled package '#{name}'") + pack = @getLoadedPackage(name) + return pack if pack + if packagePath = @resolvePackagePath(name) return pack if pack = @getLoadedPackage(name) pack = Package.load(packagePath, options) - if pack.metadata?.theme - atom.themes.register(pack) - else - @loadedPackages[pack.name] = pack + @loadedPackages[pack.name] = pack pack else throw new Error("Could not resolve '#{name}' to a package path") @@ -88,19 +111,6 @@ class PackageManager else throw new Error("No loaded package for name '#{name}'") - resolvePackagePath: (name) -> - return name if fsUtils.isDirectorySync(name) - - packagePath = fsUtils.resolve(@packageDirPaths..., name) - return packagePath if fsUtils.isDirectorySync(packagePath) - - packagePath = path.join(@resourcePath, 'node_modules', name) - return packagePath if @isInternalPackage(packagePath) - - isInternalPackage: (packagePath) -> - {engines} = Package.loadMetadata(packagePath, true) - engines?.atom? - getLoadedPackage: (name) -> @loadedPackages[name] @@ -110,9 +120,22 @@ class PackageManager getLoadedPackages: -> _.values(@loadedPackages) + resolvePackagePath: (name) -> + return name if fsUtils.isDirectorySync(name) + + packagePath = fsUtils.resolve(@packageDirPaths..., name) + return packagePath if fsUtils.isDirectorySync(packagePath) + + packagePath = path.join(@resourcePath, 'node_modules', name) + return packagePath if @isInternalPackage(packagePath) + isPackageDisabled: (name) -> _.include(config.get('core.disabledPackages') ? [], name) + isInternalPackage: (packagePath) -> + {engines} = Package.loadMetadata(packagePath, true) + engines?.atom? + getAvailablePackagePaths: -> packagePaths = [] diff --git a/src/package.coffee b/src/package.coffee index 4a1a2571f..a1b7e4648 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -7,11 +7,16 @@ class Package @build: (path) -> TextMatePackage = require './text-mate-package' AtomPackage = require './atom-package' + ThemePackage = require './theme-package' if TextMatePackage.testName(path) new TextMatePackage(path) else - new AtomPackage(path) + metadata = @loadMetadata(path) + if metadata.theme + new ThemePackage(path, {metadata}) + else + new AtomPackage(path, {metadata}) @load: (path, options) -> pack = @build(path) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 9cab3cac8..c941976f6 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -8,31 +8,93 @@ _ = require 'underscore-plus' fsUtils = require './fs-utils' # Private: Handles discovering and loading available themes. +### +Themes are a subset of packages +### module.exports = class ThemeManager Emitter.includeInto(this) - constructor: -> - @loadedThemes = [] - @activeThemes = [] + constructor: (@packageManager) -> @lessCache = null # Internal-only: - register: (theme) -> - @loadedThemes.push(theme) - theme + getAvailableNames: -> + # TODO: Maybe should change to list all the available themes out there? + @getLoadedNames() + + getLoadedNames: -> + name for theme.name in @getLoadedThemes() # Internal-only: - getAvailableNames: -> - _.map @loadedThemes, (theme) -> theme.metadata.name + getActiveNames: -> + name for theme.name in @getActiveThemes() # Internal-only: getActiveThemes: -> - _.clone(@activeThemes) + pack for pack in @packageManager.getActivePackages() when pack.isTheme() # Internal-only: getLoadedThemes: -> - _.clone(@loadedThemes) + pack for pack in @packageManager.getLoadedPackages() when pack.isTheme() + + # Internal-only: + activateThemes: -> + # atom.config.observe runs the callback once, then on subsequent changes. + atom.config.observe 'core.themes', (themeNames) => + @deactivateThemes() + themeNames = [themeNames] unless _.isArray(themeNames) + + # Reverse so the first (top) theme is loaded after the others. We want + # the first/top theme to override later themes in the stack. + themeNames = _.clone(themeNames).reverse() + + @activateTheme(themeName) for themeName in themeNames + @loadUserStylesheet() + @reloadBaseStylesheets() + @emit('reloaded') + + # Internal-only: + activateTheme: (themeName) -> + @packageManager.activatePackage(themeName) + + # Internal-only: + deactivateThemes: -> + @removeStylesheet(@userStylesheetPath) if @userStylesheetPath? + @deactivateTheme(pack.name) for pack in @getActiveThemes() + null + + # Internal-only: + deactivateTheme: (themeName) -> + @packageManager.deactivatePackage(themeName) + + # Public: + getImportPaths: -> + activeThemes = @getActiveThemes() + if activeThemes.length > 0 + themePaths = (theme.getStylesheetsPath() for theme in activeThemes when theme) + else + themePaths = [] + for themeName in atom.config.get('core.themes') ? [] + if themePath = @packageManager.resolvePackagePath(themeName) + themePaths.push(path.join(themePath, AtomPackage.stylesheetsDir)) + + themePath for themePath in themePaths when fsUtils.isDirectorySync(themePath) + + # Public: + getUserStylesheetPath: -> + stylesheetPath = fsUtils.resolve(path.join(atom.config.configDirPath, 'user'), ['css', 'less']) + if fsUtils.isFileSync(stylesheetPath) + stylesheetPath + else + null + + # Private: + loadUserStylesheet: -> + if userStylesheetPath = @getUserStylesheetPath() + @userStylesheetPath = userStylesheetPath + userStylesheetContents = @loadStylesheet(userStylesheetPath) + @applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme') # Internal-only: loadBaseStylesheets: -> @@ -109,96 +171,3 @@ class ThemeManager $("head style.#{ttype}:last").after "" else $("head").append "" - - # Internal-only: - unload: -> - @removeStylesheet(@userStylesheetPath) if @userStylesheetPath? - theme.deactivate() while theme = @activeThemes.pop() - - # Internal-only: - load: -> - config.observe 'core.themes', (themeNames) => - @unload() - themeNames = [themeNames] unless _.isArray(themeNames) - - # Reverse so the first (top) theme is loaded after the others. We want - # the first/top theme to override later themes in the stack. - themeNames = _.clone(themeNames).reverse() - - @activateTheme(themeName) for themeName in themeNames - @loadUserStylesheet() - @reloadBaseStylesheets() - @emit('reloaded') - - # Private: - loadTheme: (name, options) -> - if themePath = @resolveThemePath(name) - return theme if theme = @getLoadedTheme(name) - pack = Package.load(themePath, options) - if pack.isTheme() - @register(pack) - else - throw new Error("Attempted to load a non-theme package '#{name}' as a theme") - else - throw new Error("Could not resolve '#{name}' to a theme path") - - # Private: - getLoadedTheme: (name) -> - _.find @loadedThemes, (theme) -> theme.metadata.name is name - - # Private: - resolveThemePath: (name) -> - return name if fsUtils.isDirectorySync(name) - - packagePath = fsUtils.resolve(config.packageDirPaths..., name) - return packagePath if fsUtils.isDirectorySync(packagePath) - - packagePath = path.join(window.resourcePath, 'node_modules', name) - return packagePath if @isThemePath(packagePath) - - # Private: - isThemePath: (packagePath) -> - {engines, theme} = Package.loadMetadata(packagePath, true) - engines?.atom? and theme - - # Private: - activateTheme: (name) -> - try - theme = @loadTheme(name) - theme.activate() - @activeThemes.push(theme) - @emit('theme-activated', theme) - catch error - console.warn("Failed to load theme #{name}", error.stack ? error) - - # Public: - enableTheme: (name) -> - themes = config.get('core.themes') - config.set('core.themes', _.uniq(themes.concat([name]))) - - # Public: - getUserStylesheetPath: -> - stylesheetPath = fsUtils.resolve(path.join(config.configDirPath, 'user'), ['css', 'less']) - if fsUtils.isFileSync(stylesheetPath) - stylesheetPath - else - null - - # Public: - getImportPaths: -> - if @activeThemes.length > 0 - themePaths = (theme.getStylesheetsPath() for theme in @activeThemes when theme) - else - themePaths = [] - for themeName in config.get('core.themes') ? [] - if themePath = @resolveThemePath(themeName) - themePaths.push(path.join(themePath, AtomPackage.stylesheetsDir)) - - themePath for themePath in themePaths when fsUtils.isDirectorySync(themePath) - - # Private: - loadUserStylesheet: -> - if userStylesheetPath = @getUserStylesheetPath() - @userStylesheetPath = userStylesheetPath - userStylesheetContents = @loadStylesheet(userStylesheetPath) - @applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme') diff --git a/src/theme-package.coffee b/src/theme-package.coffee new file mode 100644 index 000000000..aabb9a041 --- /dev/null +++ b/src/theme-package.coffee @@ -0,0 +1,25 @@ +AtomPackage = require './atom-package' +Package = require './package' + +### Internal: Loads and resolves packages. ### + +module.exports = +class ThemePackage extends AtomPackage + + getType: -> 'theme' + + getStylesheetType: -> 'theme' + + enable: -> + atom.config.pushAtKeyPath('core.themes', @metadata.name) + + disable: -> + atom.config.removeAtKeyPath('core.themes', @metadata.name) + + load: -> + @measure 'loadTime', => + try + @metadata = Package.loadMetadata(@path) unless @metadata + catch e + console.warn "Failed to load theme named '#{@name}'", e.stack ? e + this From 4440210d9a841806450efb4676df621a62de21e5 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 18 Oct 2013 17:38:18 -0700 Subject: [PATCH 03/48] Fix tests --- spec/atom-spec.coffee | 46 +++++++++++++++++++++++++++++--------- src/package-manager.coffee | 6 ++++- src/package.coffee | 19 ++++++++++------ src/theme-manager.coffee | 4 ++-- src/window.coffee | 2 +- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 9166aacd0..14d75ccb5 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -20,6 +20,7 @@ describe "the `atom` global", -> expect(pack.activateStylesheets).toHaveBeenCalled() it "continues if the package has an invalid package.json", -> + spyOn(console, 'warn') config.set("core.disabledPackages", []) expect(-> atom.loadPackage("package-with-broken-package-json")).not.toThrow() @@ -224,14 +225,6 @@ describe "the `atom` global", -> expect(atom.themes.stylesheetElementForId(three)).toExist() expect($('#jasmine-content').css('font-size')).toBe '3px' - describe "theme loading", -> - it "properly sets the config.themes to activate the theme when a theme is activated", -> - themeName = "theme-with-package-file" - expect(config.get('core.themes')).not.toContain themeName - atom.activatePackage(themeName) - expect(config.get('core.themes')).toContain themeName - expect(atom.themes.getAvailableNames()).toContain themeName - describe "grammar loading", -> it "loads the package's grammars", -> atom.activatePackage('package-with-grammars') @@ -256,14 +249,17 @@ describe "the `atom` global", -> describe "when the package has no grammars but does have preferences", -> it "loads the package's preferences as scoped properties", -> - jasmine.unspy(window, 'setTimeout') - spyOn(syntax, 'addProperties').andCallThrough() + runs -> + jasmine.unspy(window, 'setTimeout') + spyOn(syntax, 'addProperties').andCallThrough() - atom.activatePackage('package-with-preferences-tmbundle') + console.log atom.packages.loadedPackages + atom.activatePackage('package-with-preferences-tmbundle') waitsFor -> syntax.addProperties.callCount > 0 runs -> + console.log atom.packages.loadedPackages expect(syntax.getProperty(['.source.pref'], 'editor.increaseIndentPattern')).toBe '^abc$' describe ".deactivatePackage(id)", -> @@ -343,3 +339,31 @@ describe "the `atom` global", -> atom.activatePackage('language-ruby', sync: true) atom.deactivatePackage('language-ruby') expect(syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined() + + describe ".activatePackages()", -> + beforeEach -> + spyOn(console, 'warn') + atom.packages.loadPackages() + + afterEach -> + atom.packages.deactivatePackages() + atom.packages.unloadPackages() + + Syntax = require '../src/syntax' + atom.syntax = window.syntax = new Syntax() + + it "activates all the packages, and none of the themes", -> + atom.packages.activatePackages() + loadedPackages = atom.packages.getLoadedPackages() + expect(loadedPackages.length).toBeGreaterThan 0 + hasTheme = false + for pack in loadedPackages + if pack.isTheme() + hasTheme = true + break + + expect(hasTheme).toBeTruthy() + + activatedPackages = atom.packages.getActivePackages() + expect(activatedPackages.length).toBeGreaterThan 0 + expect(pack.isTheme()).toBeFalsy() for pack in activatedPackages diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 4e499f45d..f5bc2207d 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -97,11 +97,15 @@ class PackageManager return pack if pack = @getLoadedPackage(name) pack = Package.load(packagePath, options) - @loadedPackages[pack.name] = pack + @loadedPackages[pack.name] = pack if pack? pack else throw new Error("Could not resolve '#{name}' to a package path") + unloadPackages: -> + for name in _.keys(@loadedPackages) + @unloadPackage(name) + unloadPackage: (name) -> if @isPackageActive(name) throw new Error("Tried to unload active package '#{name}'") diff --git a/src/package.coffee b/src/package.coffee index a1b7e4648..4051ff504 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -10,17 +10,22 @@ class Package ThemePackage = require './theme-package' if TextMatePackage.testName(path) - new TextMatePackage(path) + pack = new TextMatePackage(path) else - metadata = @loadMetadata(path) - if metadata.theme - new ThemePackage(path, {metadata}) - else - new AtomPackage(path, {metadata}) + try + metadata = @loadMetadata(path) + if metadata.theme + pack = new ThemePackage(path, {metadata}) + else + pack = new AtomPackage(path, {metadata}) + catch e + console.warn "Failed to load package.json '#{basename(path)}'", e.stack ? e + + pack @load: (path, options) -> pack = @build(path) - pack.load(options) + pack?.load(options) pack @loadMetadata: (path, ignoreErrors=false) -> diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index c941976f6..7fc5fb163 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -24,11 +24,11 @@ class ThemeManager @getLoadedNames() getLoadedNames: -> - name for theme.name in @getLoadedThemes() + theme.name for theme in @getLoadedThemes() # Internal-only: getActiveNames: -> - name for theme.name in @getActiveThemes() + theme.name for theme in @getActiveThemes() # Internal-only: getActiveThemes: -> diff --git a/src/window.coffee b/src/window.coffee index 9678ca715..3848a43dc 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -51,8 +51,8 @@ window.startEditorWindow = -> atom.keymap.loadBundledKeymaps() atom.themes.loadBaseStylesheets() atom.packages.loadPackages() - atom.themes.load() deserializeEditorWindow() + atom.themes.activateThemes() atom.packages.activatePackages() atom.keymap.loadUserKeymaps() atom.requireUserInitScript() From 9f753cd3b9083799e59f52438a30d4ecb6075a21 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 18 Oct 2013 17:38:55 -0700 Subject: [PATCH 04/48] :lipstick: --- src/package-manager.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index f5bc2207d..c18032b4e 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -103,8 +103,8 @@ class PackageManager throw new Error("Could not resolve '#{name}' to a package path") unloadPackages: -> - for name in _.keys(@loadedPackages) - @unloadPackage(name) + @unloadPackage(name) for name in _.keys(@loadedPackages) + null unloadPackage: (name) -> if @isPackageActive(name) From 0b74dfc67ab40b243d8048008289a8e1d08fc4ae Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 18 Oct 2013 17:41:32 -0700 Subject: [PATCH 05/48] Remove unnecessary lines --- spec/theme-manager-spec.coffee | 4 ++-- src/package-manager.coffee | 3 --- src/theme-manager.coffee | 14 +++----------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index 59ab435ee..b6c0a3f91 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -4,7 +4,7 @@ path = require 'path' ThemeManager = require '../src/theme-manager' AtomPackage = require '../src/atom-package' -describe "ThemeManager", -> +fdescribe "ThemeManager", -> themeManager = null beforeEach -> @@ -74,7 +74,7 @@ describe "ThemeManager", -> describe "when a theme fails to load", -> it "logs a warning", -> spyOn(console, 'warn') - expect(-> themeManager.activateTheme('a-theme-that-will-not-be-found')).toThrow() + expect(-> atom.packages.activatePackage('a-theme-that-will-not-be-found')).toThrow() describe "requireStylesheet(path)", -> it "synchronously loads css at the given path and installs a style tag for it in the head", -> diff --git a/src/package-manager.coffee b/src/package-manager.coffee index c18032b4e..20b45eae8 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -90,9 +90,6 @@ class PackageManager if @isPackageDisabled(name) return console.warn("Tried to load disabled package '#{name}'") - pack = @getLoadedPackage(name) - return pack if pack - if packagePath = @resolvePackagePath(name) return pack if pack = @getLoadedPackage(name) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 7fc5fb163..0730ee8ca 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -42,32 +42,24 @@ class ThemeManager activateThemes: -> # atom.config.observe runs the callback once, then on subsequent changes. atom.config.observe 'core.themes', (themeNames) => - @deactivateThemes() + @packageManager.deactivatePackages() themeNames = [themeNames] unless _.isArray(themeNames) # Reverse so the first (top) theme is loaded after the others. We want # the first/top theme to override later themes in the stack. themeNames = _.clone(themeNames).reverse() - @activateTheme(themeName) for themeName in themeNames + @packageManager.activatePackage(themeName) for themeName in themeNames @loadUserStylesheet() @reloadBaseStylesheets() @emit('reloaded') - # Internal-only: - activateTheme: (themeName) -> - @packageManager.activatePackage(themeName) - # Internal-only: deactivateThemes: -> @removeStylesheet(@userStylesheetPath) if @userStylesheetPath? - @deactivateTheme(pack.name) for pack in @getActiveThemes() + @packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes() null - # Internal-only: - deactivateTheme: (themeName) -> - @packageManager.deactivatePackage(themeName) - # Public: getImportPaths: -> activeThemes = @getActiveThemes() From eaea8753f5a49dbf5cf2f96fb9da6fe78a0dbe42 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 18 Oct 2013 17:42:09 -0700 Subject: [PATCH 06/48] nof --- spec/theme-manager-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index b6c0a3f91..4eb985fdf 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -4,7 +4,7 @@ path = require 'path' ThemeManager = require '../src/theme-manager' AtomPackage = require '../src/atom-package' -fdescribe "ThemeManager", -> +describe "ThemeManager", -> themeManager = null beforeEach -> From abe36765b51364a89197cd6435095893a5af7b59 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 11:37:01 -0700 Subject: [PATCH 07/48] Fix test for both local and janky --- spec/theme-manager-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index 4eb985fdf..250dc2593 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -19,7 +19,7 @@ describe "ThemeManager", -> it 'getLoadedThemes get all the loaded themes', -> themes = themeManager.getLoadedThemes() - expect(themes).toHaveLength(13) + expect(themes.length).toBeGreaterThan(2) it 'getActiveThemes get all the active themes', -> themeManager.activateThemes() From 0788905eb5497f41b442fd874f173852979a941d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 11:50:50 -0700 Subject: [PATCH 08/48] Upgrade to dev-live-reload@0.9.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99455e03f..93f32c4d9 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "collaboration": "0.28.0", "command-logger": "0.6.0", "command-palette": "0.5.0", - "dev-live-reload": "0.8.0", + "dev-live-reload": "0.9.0", "editor-stats": "0.5.0", "exception-reporting": "0.4.0", "find-and-replace": "0.29.0", From 16128b0d90dd08fb6196b1b4ff867ac9a1cfa7c0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 13:19:04 -0700 Subject: [PATCH 09/48] upgrade to settings-view@0.30.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93f32c4d9..e0aadee43 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "metrics": "0.8.0", "package-generator": "0.13.0", "release-notes": "0.8.0", - "settings-view": "0.29.0", + "settings-view": "0.30.0", "snippets": "0.11.0", "spell-check": "0.8.0", "status-bar": "0.15.0", From 81e6150fde5a466a950b9f4e7041dfa06ad56973 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 13:23:10 -0700 Subject: [PATCH 10/48] Return package if its already loaded --- src/package-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 20b45eae8..c1fe0650a 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -52,7 +52,7 @@ class PackageManager @activatePackage(pack.name) for pack in @getLoadedPackages() when not pack.isTheme() activatePackage: (name, options) -> - return if @getActivePackage(name) + return pack if pack = @getActivePackage(name) if pack = @loadPackage(name, options) @activePackages[pack.name] = pack pack.activate(options) From b330ce672237b26b93a5d578d35d007ab0ea515e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 13:48:37 -0700 Subject: [PATCH 11/48] Add atom.inSpecMode() --- src/atom.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/atom.coffee b/src/atom.coffee index 32e634d88..ffe3ba324 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -220,6 +220,9 @@ class Atom inDevMode: -> @getLoadSettings().devMode + inSpecMode: -> + @getLoadSettings().isSpec + toggleFullScreen: -> @setFullScreen(!@isFullScreen()) From d2864f1d0c8815fc73b9b16c49ed5160a46dc145 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 13:49:42 -0700 Subject: [PATCH 12/48] Upgrade to dev-live-reload@0.10.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e0aadee43..59b78e87e 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "collaboration": "0.28.0", "command-logger": "0.6.0", "command-palette": "0.5.0", - "dev-live-reload": "0.9.0", + "dev-live-reload": "0.10.0", "editor-stats": "0.5.0", "exception-reporting": "0.4.0", "find-and-replace": "0.29.0", From d5b07088cd99ea5cc5f68255fd76481083375e9d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 13:55:27 -0700 Subject: [PATCH 13/48] Remove loadStylesheets from non-theme pckage activate() --- src/atom-package.coffee | 1 - src/theme-package.coffee | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/atom-package.coffee b/src/atom-package.coffee index f36e06b9e..34f3f4272 100644 --- a/src/atom-package.coffee +++ b/src/atom-package.coffee @@ -68,7 +68,6 @@ class AtomPackage extends Package activate: ({immediate}={}) -> @measure 'activateTime', => - @loadStylesheets() @activateResources() if @metadata.activationEvents? and not immediate @subscribeToActivationEvents() diff --git a/src/theme-package.coffee b/src/theme-package.coffee index aabb9a041..c8eeab931 100644 --- a/src/theme-package.coffee +++ b/src/theme-package.coffee @@ -23,3 +23,8 @@ class ThemePackage extends AtomPackage catch e console.warn "Failed to load theme named '#{@name}'", e.stack ? e this + + activate: -> + @measure 'activateTime', => + @loadStylesheets() + @activateNow() From 73c1fb23da8e04aba5a82a158804ba4f1a75011f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 14:00:28 -0700 Subject: [PATCH 14/48] Use more concise method for @metadata settings --- src/atom-package.coffee | 2 +- src/theme-package.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/atom-package.coffee b/src/atom-package.coffee index 34f3f4272..579f17085 100644 --- a/src/atom-package.coffee +++ b/src/atom-package.coffee @@ -36,7 +36,7 @@ class AtomPackage extends Package load: -> @measure 'loadTime', => try - @metadata = Package.loadMetadata(@path) unless @metadata + @metadata ?= Package.loadMetadata(@path) @loadKeymaps() @loadMenus() diff --git a/src/theme-package.coffee b/src/theme-package.coffee index c8eeab931..363852cda 100644 --- a/src/theme-package.coffee +++ b/src/theme-package.coffee @@ -19,7 +19,7 @@ class ThemePackage extends AtomPackage load: -> @measure 'loadTime', => try - @metadata = Package.loadMetadata(@path) unless @metadata + @metadata ?= Package.loadMetadata(@path) catch e console.warn "Failed to load theme named '#{@name}'", e.stack ? e this From dd3b20f7de097870cbeab145ab539ff746964245 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 15:46:37 -0700 Subject: [PATCH 15/48] Pass previous value to the callback in config.observe() --- src/config.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config.coffee b/src/config.coffee index 1f38c30c8..98e95ad35 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -207,8 +207,9 @@ class Config updateCallback = => value = @get(keyPath) unless _.isEqual(value, previousValue) + previous = previousValue previousValue = _.clone(value) - callback(value) + callback(value, {previous}) subscription = { cancel: => @off 'updated', updateCallback } @on 'updated', updateCallback From e8b50755cb6fe859968451e19420b80385c29c95 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 15:46:48 -0700 Subject: [PATCH 16/48] Add config.unobserve() --- src/config.coffee | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 98e95ad35..18cbf2692 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -193,7 +193,7 @@ class Config # `callback` is fired whenever the value of the key is changed and will # be fired immediately unless the `callNow` option is `false`. # - # keyPath - The {String} name of the key to watch + # keyPath - The {String} name of the key to observe # options - An optional {Object} containing the `callNow` key. # callback - The {Function} that fires when the. It is given a single argument, `value`, # which is the new value of `keyPath`. @@ -212,10 +212,17 @@ class Config callback(value, {previous}) subscription = { cancel: => @off 'updated', updateCallback } - @on 'updated', updateCallback + @on "updated.#{keyPath.replace(/\./, '-')}", updateCallback callback(value) if options.callNow ? true subscription + + # Public: Unobserve all callbacks on a given key + # + # keyPath - The {String} name of the key to unobserve + unobserve: (keyPath) -> + @off("updated.#{keyPath.replace(/\./, '-')}") + # Private: update: -> return if @configFileHasErrors From 7b1b73e8eba0536ff1416468a0c0eaa3418073f9 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 15:47:15 -0700 Subject: [PATCH 17/48] Watch the core.disabledPackages config option --- spec/atom-spec.coffee | 31 +++++++++++++++++++++++++++++++ src/package-manager.coffee | 30 +++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 14d75ccb5..93c8849e2 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -367,3 +367,34 @@ describe "the `atom` global", -> activatedPackages = atom.packages.getActivePackages() expect(activatedPackages.length).toBeGreaterThan 0 expect(pack.isTheme()).toBeFalsy() for pack in activatedPackages + + describe ".enablePackage()", -> + it "enables a disabled package", -> + packageName = 'package-with-main' + atom.config.pushAtKeyPath('core.disabledPackages', packageName) + + atom.packages.observeDisabledPackages() + + expect(config.get('core.disabledPackages')).toContain packageName + + pack = atom.packages.enablePackage(packageName) + + loadedPackages = atom.packages.getLoadedPackages() + activatedPackages = atom.packages.getActivePackages() + expect(loadedPackages).toContain(pack) + expect(activatedPackages).toContain(pack) + expect(config.get('core.disabledPackages')).not.toContain packageName + + it "enables a disabled theme", -> + packageName = 'theme-with-package-file' + expect(config.get('core.themes')).not.toContain packageName + expect(config.get('core.disabledPackages')).not.toContain packageName + + pack = atom.packages.enablePackage(packageName) + + loadedPackages = atom.packages.getLoadedPackages() + activatedPackages = atom.packages.getLoadedPackages() + expect(loadedPackages).toContain(pack) + expect(activatedPackages).toContain(pack) + expect(config.get('core.themes')).toContain packageName + expect(config.get('core.disabledPackages')).not.toContain packageName diff --git a/src/package-manager.coffee b/src/package-manager.coffee index c1fe0650a..575b5b62f 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -31,6 +31,7 @@ class PackageManager @loadedPackages = {} @activePackages = {} @packageStates = {} + @observingDisabledPackages = false getPackageState: (name) -> @packageStates[name] @@ -41,15 +42,18 @@ class PackageManager enablePackage: (name) -> pack = @loadPackage(name) pack?.enable() + pack disablePackage: (name) -> pack = @loadPackage(name) pack?.disable() + pack activatePackages: -> # ThemeManager handles themes. Only activate non theme packages # This is the only part I dislike @activatePackage(pack.name) for pack in @getLoadedPackages() when not pack.isTheme() + @observeDisabledPackages() activatePackage: (name, options) -> return pack if pack = @getActivePackage(name) @@ -60,6 +64,7 @@ class PackageManager deactivatePackages: -> @deactivatePackage(pack.name) for pack in @getActivePackages() + @unobserveDisabledPackages() deactivatePackage: (name) -> if pack = @getActivePackage(name) @@ -78,6 +83,28 @@ class PackageManager isPackageActive: (name) -> @getActivePackage(name)? + unobserveDisabledPackages: -> + return unless @observingDisabledPackages + config.unobserve('core.disabledPackages') + @observingDisabledPackages = false + + observeDisabledPackages: -> + return if @observingDisabledPackages + + config.observe 'core.disabledPackages', callNow: false, (disabledPackages, {previous}) => + packagesToEnable = _.difference(previous, disabledPackages) + packagesToDisable = _.difference(disabledPackages, previous) + + console.log previous, disabledPackages + console.log packagesToDisable + console.log packagesToEnable + + @deactivatePackage(packageName) for packageName in packagesToDisable when @getActivePackage(packageName) + @activatePackage(packageName) for packageName in packagesToEnable + null + + @observingDisabledPackages = true + loadPackages: -> # Ensure atom exports is already in the require cache so the load time # of the first package isn't skewed by being the first to require atom @@ -87,9 +114,6 @@ class PackageManager @emit 'loaded' loadPackage: (name, options) -> - if @isPackageDisabled(name) - return console.warn("Tried to load disabled package '#{name}'") - if packagePath = @resolvePackagePath(name) return pack if pack = @getLoadedPackage(name) From f2c1ea9b5a57d519415dac9ac0930b02aac0d0bf Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:12:23 -0700 Subject: [PATCH 18/48] Remove log lines --- src/package-manager.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 575b5b62f..39888c7ff 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -95,10 +95,6 @@ class PackageManager packagesToEnable = _.difference(previous, disabledPackages) packagesToDisable = _.difference(disabledPackages, previous) - console.log previous, disabledPackages - console.log packagesToDisable - console.log packagesToEnable - @deactivatePackage(packageName) for packageName in packagesToDisable when @getActivePackage(packageName) @activatePackage(packageName) for packageName in packagesToEnable null From 2624cf6e75563e8a2a7a8cffcbfd260283eda57a Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:12:43 -0700 Subject: [PATCH 19/48] oops, don't deactivate all the packages! --- src/theme-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 0730ee8ca..e91e26e1e 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -42,7 +42,7 @@ class ThemeManager activateThemes: -> # atom.config.observe runs the callback once, then on subsequent changes. atom.config.observe 'core.themes', (themeNames) => - @packageManager.deactivatePackages() + @deactivateThemes() themeNames = [themeNames] unless _.isArray(themeNames) # Reverse so the first (top) theme is loaded after the others. We want From c6145195295e6156977bf7ec71bc73d2411bf4c5 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:13:04 -0700 Subject: [PATCH 20/48] Clean up the tests; add tests for disablePackage() --- spec/atom-spec.coffee | 73 +++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 93c8849e2..8341a15f4 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -1,6 +1,7 @@ {$, $$, fs, RootView} = require 'atom' Exec = require('child_process').exec path = require 'path' +ThemeManager = require '../src/theme-manager' describe "the `atom` global", -> beforeEach -> @@ -368,33 +369,59 @@ describe "the `atom` global", -> expect(activatedPackages.length).toBeGreaterThan 0 expect(pack.isTheme()).toBeFalsy() for pack in activatedPackages - describe ".enablePackage()", -> - it "enables a disabled package", -> - packageName = 'package-with-main' - atom.config.pushAtKeyPath('core.disabledPackages', packageName) + describe ".en/disablePackage()", -> + describe "with packages", -> + it ".enablePackage() enables a disabled package", -> + packageName = 'package-with-main' + atom.config.pushAtKeyPath('core.disabledPackages', packageName) + atom.packages.observeDisabledPackages() + expect(config.get('core.disabledPackages')).toContain packageName - atom.packages.observeDisabledPackages() + pack = atom.packages.enablePackage(packageName) - expect(config.get('core.disabledPackages')).toContain packageName + loadedPackages = atom.packages.getLoadedPackages() + activatedPackages = atom.packages.getActivePackages() + expect(loadedPackages).toContain(pack) + expect(activatedPackages).toContain(pack) + expect(config.get('core.disabledPackages')).not.toContain packageName - pack = atom.packages.enablePackage(packageName) + it ".disablePackage() disables an enabled package", -> + packageName = 'package-with-main' + atom.packages.activatePackage(packageName) + atom.packages.observeDisabledPackages() + expect(config.get('core.disabledPackages')).not.toContain packageName - loadedPackages = atom.packages.getLoadedPackages() - activatedPackages = atom.packages.getActivePackages() - expect(loadedPackages).toContain(pack) - expect(activatedPackages).toContain(pack) - expect(config.get('core.disabledPackages')).not.toContain packageName + pack = atom.packages.disablePackage(packageName) - it "enables a disabled theme", -> - packageName = 'theme-with-package-file' - expect(config.get('core.themes')).not.toContain packageName - expect(config.get('core.disabledPackages')).not.toContain packageName + activatedPackages = atom.packages.getActivePackages() + expect(activatedPackages).not.toContain(pack) + expect(config.get('core.disabledPackages')).toContain packageName - pack = atom.packages.enablePackage(packageName) + describe "with themes", -> + beforeEach -> + atom.themes.activateThemes() - loadedPackages = atom.packages.getLoadedPackages() - activatedPackages = atom.packages.getLoadedPackages() - expect(loadedPackages).toContain(pack) - expect(activatedPackages).toContain(pack) - expect(config.get('core.themes')).toContain packageName - expect(config.get('core.disabledPackages')).not.toContain packageName + afterEach -> + atom.themes.deactivateThemes() + atom.config.unobserve('core.themes') + + it ".enablePackage() and .disablePackage() enables and disables a theme", -> + packageName = 'theme-with-package-file' + + expect(config.get('core.themes')).not.toContain packageName + expect(config.get('core.disabledPackages')).not.toContain packageName + + # enabling of theme + pack = atom.packages.enablePackage(packageName) + activatedPackages = atom.packages.getActivePackages() + expect(activatedPackages).toContain(pack) + expect(config.get('core.themes')).toContain packageName + expect(config.get('core.disabledPackages')).not.toContain packageName + + # disabling of theme + pack = atom.packages.disablePackage(packageName) + activatedPackages = atom.packages.getActivePackages() + expect(activatedPackages).not.toContain(pack) + expect(config.get('core.themes')).not.toContain packageName + expect(config.get('core.themes')).not.toContain packageName + expect(config.get('core.disabledPackages')).not.toContain packageName From 71a24ec49b5756033b93f2fccd373172e9ee5990 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:18:11 -0700 Subject: [PATCH 21/48] Fix config tests --- spec/config-spec.coffee | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 277a8a2d3..f3a3d6e79 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -32,7 +32,7 @@ describe "Config", -> config.set("foo.bar.baz", 42) expect(config.save).toHaveBeenCalled() - expect(observeHandler).toHaveBeenCalledWith 42 + expect(observeHandler).toHaveBeenCalledWith 42, {previous: undefined} describe "when the value equals the default value", -> it "does not store the value", -> @@ -54,7 +54,7 @@ describe "Config", -> expect(config.pushAtKeyPath("foo.bar.baz", "b")).toBe 2 expect(config.get("foo.bar.baz")).toEqual ["a", "b"] - expect(observeHandler).toHaveBeenCalledWith config.get("foo.bar.baz") + expect(observeHandler).toHaveBeenCalledWith config.get("foo.bar.baz"), {previous: ['a']} describe ".removeAtKeyPath(keyPath, value)", -> it "removes the given value from the array at the key path and updates observers", -> @@ -65,7 +65,7 @@ describe "Config", -> expect(config.removeAtKeyPath("foo.bar.baz", "b")).toEqual ["a", "c"] expect(config.get("foo.bar.baz")).toEqual ["a", "c"] - expect(observeHandler).toHaveBeenCalledWith config.get("foo.bar.baz") + expect(observeHandler).toHaveBeenCalledWith config.get("foo.bar.baz"), {previous: ['a', 'b', 'c']} describe ".getPositiveInt(keyPath, defaultValue)", -> it "returns the proper current or default value", -> @@ -142,26 +142,26 @@ describe "Config", -> it "fires the callback every time the observed value changes", -> observeHandler.reset() # clear the initial call config.set('foo.bar.baz', "value 2") - expect(observeHandler).toHaveBeenCalledWith("value 2") + expect(observeHandler).toHaveBeenCalledWith("value 2", {previous: 'value 1'}) observeHandler.reset() config.set('foo.bar.baz', "value 1") - expect(observeHandler).toHaveBeenCalledWith("value 1") + expect(observeHandler).toHaveBeenCalledWith("value 1", {previous: 'value 2'}) it "fires the callback when the observed value is deleted", -> observeHandler.reset() # clear the initial call config.set('foo.bar.baz', undefined) - expect(observeHandler).toHaveBeenCalledWith(undefined) + expect(observeHandler).toHaveBeenCalledWith(undefined, {previous: 'value 1'}) it "fires the callback when the full key path goes into and out of existence", -> observeHandler.reset() # clear the initial call config.set("foo.bar", undefined) - expect(observeHandler).toHaveBeenCalledWith(undefined) + expect(observeHandler).toHaveBeenCalledWith(undefined, {previous: 'value 1'}) observeHandler.reset() config.set("foo.bar.baz", "i'm back") - expect(observeHandler).toHaveBeenCalledWith("i'm back") + expect(observeHandler).toHaveBeenCalledWith("i'm back", {previous: undefined}) describe ".initializeConfigDirectory()", -> beforeEach -> From 8ac84359b121714c2bb575d22700006b6b014157 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:24:29 -0700 Subject: [PATCH 22/48] Fix docs --- src/package-manager.coffee | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 39888c7ff..e6d82f6e0 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -11,13 +11,13 @@ Packages have a lifecycle * Every package (except those in core.disabledPackages) is 'loaded', meaning `Package` objects are created, and their metadata loaded. This includes themes, as themes are packages -* Each non-theme package is 'activated', meaning its resources are loaded into the -* Packages and themes can be enabled and disabled, and - -TODO: -* test that it doesnt activate all the theme packages -* originally disabled packages can be enabled, and loaded without reloading -* config.observe the core.disabledPackages +* The ThemeManager.activateThemes() is called 'activating' all the themes, meaning + their stylesheets are loaded into the window. +* The PackageManager.activatePackages() function is called 'activating' non-theme + package, meaning its resources -- keymaps, classes, etc. -- are loaded, and + the package's activate() method is called. +* Packages and themes can then be enabled and disabled via the public + .enablePackage(name) and .disablePackage(name) functions. ### module.exports = class PackageManager @@ -39,11 +39,13 @@ class PackageManager setPackageState: (name, state) -> @packageStates[name] = state + # Public: enablePackage: (name) -> pack = @loadPackage(name) pack?.enable() pack + # Public: disablePackage: (name) -> pack = @loadPackage(name) pack?.disable() From ecbb7cad230ef1b97fba1071b24ed8f0da547112 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:32:29 -0700 Subject: [PATCH 23/48] fix test from config --- spec/space-pen-extensions-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/space-pen-extensions-spec.coffee b/spec/space-pen-extensions-spec.coffee index 8ae85f814..f121a683f 100644 --- a/spec/space-pen-extensions-spec.coffee +++ b/spec/space-pen-extensions-spec.coffee @@ -25,7 +25,7 @@ describe "SpacePen extensions", -> config.set("foo.bar", "hello") - expect(observeHandler).toHaveBeenCalledWith("hello") + expect(observeHandler).toHaveBeenCalledWith("hello", previous: undefined) observeHandler.reset() view.unobserveConfig() From 2a7908a196997b534fe700633af78b1b96d72aad Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 21 Oct 2013 16:36:40 -0700 Subject: [PATCH 24/48] Upgrade to settings-view@0.31.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59b78e87e..0494378bd 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "metrics": "0.8.0", "package-generator": "0.13.0", "release-notes": "0.8.0", - "settings-view": "0.30.0", + "settings-view": "0.31.0", "snippets": "0.11.0", "spell-check": "0.8.0", "status-bar": "0.15.0", From 967c04fb19206aa2d2d8d26e9f0083a110295953 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 22 Oct 2013 12:57:37 -0700 Subject: [PATCH 25/48] Clean up theme check in PackageManager with PackageActivators You can now call `PackageManager.registerPackageActivator` for specific package types. On `PackageManager.activate` it will call your `PackageActivator.activatePackages(packages)` with the proper packages. --- spec/atom-spec.coffee | 32 ++++++++++++++++++-------------- src/package-manager.coffee | 28 ++++++++++++++++++++++++---- src/theme-manager.coffee | 4 ++++ src/window.coffee | 3 +-- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 8341a15f4..f4f0df935 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -341,33 +341,37 @@ describe "the `atom` global", -> atom.deactivatePackage('language-ruby') expect(syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined() - describe ".activatePackages()", -> + describe ".activate()", -> + packageActivator = null + themeActivator = null + beforeEach -> spyOn(console, 'warn') atom.packages.loadPackages() + loadedPackages = atom.packages.getLoadedPackages() + expect(loadedPackages.length).toBeGreaterThan 0 + + packageActivator = spyOn(atom.packages, 'activatePackages') + themeActivator = spyOn(atom.themes, 'activatePackages') + afterEach -> - atom.packages.deactivatePackages() atom.packages.unloadPackages() Syntax = require '../src/syntax' atom.syntax = window.syntax = new Syntax() it "activates all the packages, and none of the themes", -> - atom.packages.activatePackages() - loadedPackages = atom.packages.getLoadedPackages() - expect(loadedPackages.length).toBeGreaterThan 0 - hasTheme = false - for pack in loadedPackages - if pack.isTheme() - hasTheme = true - break + atom.packages.activate() - expect(hasTheme).toBeTruthy() + expect(packageActivator).toHaveBeenCalled() + expect(themeActivator).toHaveBeenCalled() - activatedPackages = atom.packages.getActivePackages() - expect(activatedPackages.length).toBeGreaterThan 0 - expect(pack.isTheme()).toBeFalsy() for pack in activatedPackages + packages = packageActivator.mostRecentCall.args[0] + expect(['atom', 'textmate']).toContain(pack.getType()) for pack in packages + + themes = themeActivator.mostRecentCall.args[0] + expect(['theme']).toContain(theme.getType()) for theme in themes describe ".en/disablePackage()", -> describe "with packages", -> diff --git a/src/package-manager.coffee b/src/package-manager.coffee index e6d82f6e0..a94153aa9 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -33,6 +33,9 @@ class PackageManager @packageStates = {} @observingDisabledPackages = false + @packageActivators = [] + @registerPackageActivator(this, ['atom', 'textmate']) + getPackageState: (name) -> @packageStates[name] @@ -51,12 +54,23 @@ class PackageManager pack?.disable() pack - activatePackages: -> - # ThemeManager handles themes. Only activate non theme packages - # This is the only part I dislike - @activatePackage(pack.name) for pack in @getLoadedPackages() when not pack.isTheme() + # Internal-only: Activate all the packages that should be activated. + activate: -> + for [activator, types] in @packageActivators + packages = @getLoadedPackagesForTypes(types) + activator.activatePackages(packages) + + # Public: another type of package manager can handle other package types. + # See ThemeManager + registerPackageActivator: (activator, types) -> + @packageActivators.push([activator, types]) + + # Internal-only: + activatePackages: (packages) -> + @activatePackage(pack.name) for pack in packages @observeDisabledPackages() + # Internal-only: Activate a single package by name activatePackage: (name, options) -> return pack if pack = @getActivePackage(name) if pack = @loadPackage(name, options) @@ -143,6 +157,12 @@ class PackageManager getLoadedPackages: -> _.values(@loadedPackages) + # Private: Get packages for a certain package type + # + # * types: an {Array} of {String}s like ['atom', 'textmate'] + getLoadedPackagesForTypes: (types) -> + pack for pack in @getLoadedPackages() when pack.getType() in types + resolvePackagePath: (name) -> return name if fsUtils.isDirectorySync(name) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index e91e26e1e..f40421683 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -17,6 +17,7 @@ class ThemeManager constructor: (@packageManager) -> @lessCache = null + @packageManager.registerPackageActivator(this, ['theme']) # Internal-only: getAvailableNames: -> @@ -38,6 +39,9 @@ class ThemeManager getLoadedThemes: -> pack for pack in @packageManager.getLoadedPackages() when pack.isTheme() + # Internal-only: adhere to the PackageActivator interface + activatePackages: (themePackages) -> @activateThemes() + # Internal-only: activateThemes: -> # atom.config.observe runs the callback once, then on subsequent changes. diff --git a/src/window.coffee b/src/window.coffee index 3848a43dc..4282d2a0b 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -52,8 +52,7 @@ window.startEditorWindow = -> atom.themes.loadBaseStylesheets() atom.packages.loadPackages() deserializeEditorWindow() - atom.themes.activateThemes() - atom.packages.activatePackages() + atom.packages.activate() atom.keymap.loadUserKeymaps() atom.requireUserInitScript() atom.menu.update() From 997891f298273e69809401fc726ed755f56b0523 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 22 Oct 2013 13:02:48 -0700 Subject: [PATCH 26/48] Fixup specs --- spec/atom-spec.coffee | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index f4f0df935..981036868 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -250,17 +250,14 @@ describe "the `atom` global", -> describe "when the package has no grammars but does have preferences", -> it "loads the package's preferences as scoped properties", -> - runs -> - jasmine.unspy(window, 'setTimeout') - spyOn(syntax, 'addProperties').andCallThrough() + jasmine.unspy(window, 'setTimeout') + spyOn(syntax, 'addProperties').andCallThrough() - console.log atom.packages.loadedPackages - atom.activatePackage('package-with-preferences-tmbundle') + atom.activatePackage('package-with-preferences-tmbundle') waitsFor -> syntax.addProperties.callCount > 0 runs -> - console.log atom.packages.loadedPackages expect(syntax.getProperty(['.source.pref'], 'editor.increaseIndentPattern')).toBe '^abc$' describe ".deactivatePackage(id)", -> From b13c633775362050007ad6db4cbd2cec9d14f341 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 22 Oct 2013 15:09:58 -0700 Subject: [PATCH 27/48] Upgrade to dev-live-reload@0.11.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0494378bd..c4d3b41da 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "collaboration": "0.28.0", "command-logger": "0.6.0", "command-palette": "0.5.0", - "dev-live-reload": "0.10.0", + "dev-live-reload": "0.11.0", "editor-stats": "0.5.0", "exception-reporting": "0.4.0", "find-and-replace": "0.29.0", From fd177d71714c3c49930a01e2853c67b7aa2e7a91 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 22 Oct 2013 15:09:09 -0700 Subject: [PATCH 28/48] Look for token in keychain --- tasks/publish-packages.coffee | 72 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/tasks/publish-packages.coffee b/tasks/publish-packages.coffee index 3f274919c..765a927f1 100644 --- a/tasks/publish-packages.coffee +++ b/tasks/publish-packages.coffee @@ -6,6 +6,8 @@ request = require 'request' # This task should be run whenever you want to be sure that atom.io contains # all the packages and versions referenced in Atom's package.json file. module.exports = (grunt) -> + {spawn} = require('./task-helpers')(grunt) + baseUrl = "https://www.atom.io/api/packages" packageExists = (packageName, token, callback) -> @@ -61,38 +63,46 @@ module.exports = (grunt) -> else callback() - grunt.registerTask 'publish-packages', 'Publish all bundled packages', -> - token = process.env.ATOM_ACCESS_TOKEN - unless token - grunt.log.error('Must set ATOM_ACCESS_TOKEN environment variable') - return false + getToken = (callback) -> + if token = process.env.ATOM_ACCESS_TOKEN + callback(null, token) + else + spawn {cmd: 'security', args: ['-q', 'find-generic-password', '-ws', 'GitHub API Token']}, (error, result, code) -> + token = result.toString() unless error? + callback(error, token) - {packageDependencies} = grunt.file.readJSON('package.json') ? {} + grunt.registerTask 'publish-packages', 'Publish all bundled packages', -> done = @async() - tasks = [] - for name, version of packageDependencies - do (name, version) -> - tasks.push (callback) -> - grunt.log.writeln("Publishing #{name}@#{version}") - tag = "v#{version}" - packageExists name, token, (error, exists) -> - if error? - callback(error) - return - - if exists - createPackage name, token, (error) -> - if error? - callback(error) - else - createPackageVersion(name, tag, token, callback) - else - createPackageVersion(name, tag, token, callback) - - async.waterfall tasks, (error) -> - if error? - grunt.log.error(error.message) + getToken (error, token) -> + unless token + grunt.log.error('Token not found in keychain or ATOM_ACCESS_TOKEN environment variable') done(false) - else - done() + + {packageDependencies} = grunt.file.readJSON('package.json') ? {} + tasks = [] + for name, version of packageDependencies + do (name, version) -> + tasks.push (callback) -> + grunt.log.writeln("Publishing #{name}@#{version}") + tag = "v#{version}" + packageExists name, token, (error, exists) -> + if error? + callback(error) + return + + if exists + createPackage name, token, (error) -> + if error? + callback(error) + else + createPackageVersion(name, tag, token, callback) + else + createPackageVersion(name, tag, token, callback) + + async.waterfall tasks, (error) -> + if error? + grunt.log.error(error.message) + done(false) + else + done() From 3eab78bc233a09ab36bd1cdabe9985121e12fd42 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Fri, 18 Oct 2013 13:58:13 -0700 Subject: [PATCH 29/48] Set undo keybinding to meta-y --- keymaps/atom.cson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymaps/atom.cson b/keymaps/atom.cson index a2448e217..37c8b4e01 100644 --- a/keymaps/atom.cson +++ b/keymaps/atom.cson @@ -29,7 +29,7 @@ 'shift-backspace': 'core:backspace' 'delete': 'core:delete' 'meta-z': 'core:undo' - 'meta-Z': 'core:redo' + 'meta-y': 'core:redo' 'meta-x': 'core:cut' 'meta-c': 'core:copy' 'meta-v': 'core:paste' From 74cb91a6a155429f2dc18a70721ffc903a288636 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Fri, 18 Oct 2013 14:42:25 -0700 Subject: [PATCH 30/48] Add Edit > Lines submenu --- menus/base.cson | 13 +++++++++++++ src/menu-manager.coffee | 26 +++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/menus/base.cson b/menus/base.cson index 64a45e615..1c6ab6c89 100644 --- a/menus/base.cson +++ b/menus/base.cson @@ -45,6 +45,19 @@ { label: 'Paste', command: 'core:paste' } { label: 'Select All', command: 'core:select-all' } { type: 'separator' } + { + label: 'Lines', + submenu: [ + { label: 'Indent', command: 'editor:indent-selected-rows' } + { label: 'Outdent', command: 'editor:outdent-selected-rows' } + { label: 'Auto Indent', command: 'editor:auto-indent' } + { label: 'Move Line Up', command: 'editor:move-line-up' } + { label: 'Move Line Down', command: 'editor:move-line-down' } + { label: 'Duplicate Line', command: 'editor:duplicate-line' } + { label: 'Delete Line', command: 'editor:delete-line' } + { label: 'Join Lines', command: 'editor:join-line' } + ] + } ] } diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 7fa1f242a..6e06b6a87 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -30,7 +30,10 @@ class MenuManager # Public: Refreshes the currently visible menu. update: -> - @sendToBrowserProcess(@template, atom.keymap.keystrokesByCommandForSelector('body')) + keystrokesByCommand = atom.keymap.keystrokesByCommandForSelector('body') + _.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor')) + _.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor:not(.mini)')) + @sendToBrowserProcess(@template, keystrokesByCommand) # Private loadCoreItems: -> @@ -49,6 +52,27 @@ class MenuManager else menu.push(item) unless _.find(menu, (i) -> i.label == item.label) + # Private: OSX can't handle displaying accelerators for multiple keystrokes. + # If they are sent across, it will stop processing accelerators for the rest + # of the menu items. + filterMultipleKeystrokes: (keystrokesByCommand) -> + filtered = {} + for key, bindings of keystrokesByCommand + for binding in bindings + continue if binding.indexOf(' ') != -1 + + # Currently being implemented in atom-shell + continue if binding.indexOf('-=') != -1 + continue if binding.indexOf('-up') != -1 + continue if binding.indexOf('-down') != -1 + continue if binding.indexOf('tab') != -1 + + console.log binding if binding.indexOf('alt-meta') !=-1 + filtered[key] ?= [] + filtered[key].push(binding) + filtered + # Private sendToBrowserProcess: (template, keystrokesByCommand) -> + keystrokesByCommand = @filterMultipleKeystrokes(keystrokesByCommand) ipc.sendChannel 'update-application-menu', template, keystrokesByCommand From 161a87b8e17f897de699d1823bbad0d8b5af751a Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Fri, 18 Oct 2013 14:44:36 -0700 Subject: [PATCH 31/48] Change delete-line accelerator to ctrl-K --- keymaps/editor.cson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymaps/editor.cson b/keymaps/editor.cson index c0a328cb0..842b4d7ea 100644 --- a/keymaps/editor.cson +++ b/keymaps/editor.cson @@ -1,5 +1,5 @@ '.editor': - 'meta-d': 'editor:delete-line' + 'ctrl-K': 'editor:delete-line' 'ctrl-W': 'editor:select-word' 'meta-alt-p': 'editor:log-cursor-scope' 'meta-u': 'editor:upper-case' From 1f86c62dc995750f723bf00a4e1bc04e18ecd571 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Fri, 18 Oct 2013 15:19:51 -0700 Subject: [PATCH 32/48] Remove accidental logging --- src/menu-manager.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 6e06b6a87..3d53b6738 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -67,7 +67,6 @@ class MenuManager continue if binding.indexOf('-down') != -1 continue if binding.indexOf('tab') != -1 - console.log binding if binding.indexOf('alt-meta') !=-1 filtered[key] ?= [] filtered[key].push(binding) filtered From fd0bed4248a8499aabee0b9d7c7ab8851e89b153 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Fri, 18 Oct 2013 15:20:02 -0700 Subject: [PATCH 33/48] Fill out the rest of the Edit menu --- menus/base.cson | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/menus/base.cson b/menus/base.cson index 1c6ab6c89..9ed83746d 100644 --- a/menus/base.cson +++ b/menus/base.cson @@ -45,12 +45,14 @@ { label: 'Paste', command: 'core:paste' } { label: 'Select All', command: 'core:select-all' } { type: 'separator' } + { label: 'Toggle Comments', command: 'editor:toggle-line-comments' } { label: 'Lines', submenu: [ { label: 'Indent', command: 'editor:indent-selected-rows' } { label: 'Outdent', command: 'editor:outdent-selected-rows' } { label: 'Auto Indent', command: 'editor:auto-indent' } + { type: 'separator' } { label: 'Move Line Up', command: 'editor:move-line-up' } { label: 'Move Line Down', command: 'editor:move-line-down' } { label: 'Duplicate Line', command: 'editor:duplicate-line' } @@ -58,6 +60,37 @@ { label: 'Join Lines', command: 'editor:join-line' } ] } + { + label: 'Text', + submenu: [ + { label: 'Upper Case', command: 'editor:upper-case' } + { label: 'Lower Case', command: 'editor:lower-case' } + { type: 'separator' } + { label: 'Delete to End of Word', command: 'editor:delete-to-end-of-word' } + { label: 'Delete Line', command: 'editor:delete-line' } + { type: 'separator' } + { label: 'Transpose', command: 'editor:transpose' } + ] + } + { + label: 'Folding', + submenu: [ + { label: 'Fold', command: 'editor:fold-current-row' } + { label: 'Unfold', command: 'editor:unfold-current-row' } + { label: 'Unfold All', command: 'editor:unfold-all' } + { type: 'separator' } + { label: 'Fold All', command: 'editor:fold-all' } + { label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' } + { label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' } + { label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' } + { label: 'Fold Level 4', command: 'editor:fold-at-indent-level-4' } + { label: 'Fold Level 5', command: 'editor:fold-at-indent-level-5' } + { label: 'Fold Level 6', command: 'editor:fold-at-indent-level-6' } + { label: 'Fold Level 7', command: 'editor:fold-at-indent-level-7' } + { label: 'Fold Level 8', command: 'editor:fold-at-indent-level-8' } + { label: 'Fold Level 9', command: 'editor:fold-at-indent-level-9' } + ] + } ] } From 9da395c0aadc0ec3612203a95c136a9a2e3fadc7 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Fri, 18 Oct 2013 15:28:49 -0700 Subject: [PATCH 34/48] Add a Selection menu --- menus/base.cson | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/menus/base.cson b/menus/base.cson index 9ed83746d..9404fcb8b 100644 --- a/menus/base.cson +++ b/menus/base.cson @@ -94,6 +94,25 @@ ] } + { + label: 'Selection' + submenu: [ + { label: 'Add Selection Above', command: 'editor:add-selection-above' } + { label: 'Add Selection Below', command: 'editor:add-selection-below' } + { type: 'separator' } + { label: 'Select to Top', command: 'core:select-to-top' } + { label: 'Select to Bottom', command: 'core:select-to-bottom' } + { type: 'separator' } + { label: 'Select Line', command: 'editor:select-line' } + { label: 'Select Word', command: 'editor:select-word' } + { label: 'Select to Beginning of Word', command: 'editor:select-to-beginning-of-word' } + { label: 'Select to Beginning of Line', command: 'editor:select-to-beginning-of-line' } + { label: 'Select to First Character of Line', command: 'editor:select-to-first-character-of-line' } + { label: 'Select to End of Word', command: 'editor:select-to-end-of-word' } + { label: 'Select to End of Line', command: 'editor:select-to-end-of-line' } + ] + } + { label: 'View' submenu: [ From 5e253378e203f6fec22b43b779487692f0d71219 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 11:23:22 -0700 Subject: [PATCH 35/48] Update restricted key bindings for atom-shell@0.6.3 --- src/menu-manager.coffee | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 3d53b6738..c7b76f9db 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -61,10 +61,8 @@ class MenuManager for binding in bindings continue if binding.indexOf(' ') != -1 - # Currently being implemented in atom-shell - continue if binding.indexOf('-=') != -1 - continue if binding.indexOf('-up') != -1 - continue if binding.indexOf('-down') != -1 + # To be fixed in atom-shell + continue if binding.indexOf('f2') != -1 continue if binding.indexOf('tab') != -1 filtered[key] ?= [] From de69446e1eca0c3553a5f3e8e4fbc112f61f357a Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 11:29:47 -0700 Subject: [PATCH 36/48] Remap join lines to `meta-j` --- keymaps/editor.cson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymaps/editor.cson b/keymaps/editor.cson index 842b4d7ea..5e4d7cf30 100644 --- a/keymaps/editor.cson +++ b/keymaps/editor.cson @@ -38,7 +38,7 @@ 'ctrl-meta-up': 'editor:move-line-up' 'ctrl-meta-down': 'editor:move-line-down' 'meta-D': 'editor:duplicate-line' - 'ctrl-J': 'editor:join-line' + 'meta-j': 'editor:join-line' 'meta-<': 'editor:scroll-to-cursor' '.editor.mini': From e003b478f3df400c75dfcb5b114c908de623c16e Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 11:39:02 -0700 Subject: [PATCH 37/48] Sublime accepts both `meta-Z` and `meta-y` --- keymaps/atom.cson | 1 + 1 file changed, 1 insertion(+) diff --git a/keymaps/atom.cson b/keymaps/atom.cson index 37c8b4e01..2fd92b900 100644 --- a/keymaps/atom.cson +++ b/keymaps/atom.cson @@ -29,6 +29,7 @@ 'shift-backspace': 'core:backspace' 'delete': 'core:delete' 'meta-z': 'core:undo' + 'meta-Z': 'core:redo' 'meta-y': 'core:redo' 'meta-x': 'core:cut' 'meta-c': 'core:copy' From 2ddcfb60cf1d7fe941f746611454a58ac7cb5c71 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Tue, 22 Oct 2013 12:02:17 -0700 Subject: [PATCH 38/48] Allow `f2` and `tab` keybindings This is possible now that we're on atom-shell@0.6.4 --- src/menu-manager.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index c7b76f9db..76d171c60 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -61,10 +61,6 @@ class MenuManager for binding in bindings continue if binding.indexOf(' ') != -1 - # To be fixed in atom-shell - continue if binding.indexOf('f2') != -1 - continue if binding.indexOf('tab') != -1 - filtered[key] ?= [] filtered[key].push(binding) filtered From 59ef210624377ebf95231f102e89d23418bebe12 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 22 Oct 2013 15:26:57 -0700 Subject: [PATCH 39/48] Stub out Find, Collaboration, and Packages in base menu --- menus/base.cson | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/menus/base.cson b/menus/base.cson index 64a45e615..7f455ca01 100644 --- a/menus/base.cson +++ b/menus/base.cson @@ -48,6 +48,11 @@ ] } + { + label: 'Find' + submenu: [] + } + { label: 'View' submenu: [ @@ -67,6 +72,16 @@ ] } + { + label: 'Collaboration' + submenu: [] + } + + { + label: 'Packages' + submenu: [] + } + { label: 'Window' submenu: [ From 141da613017f8bc8d080878341bd6a713ef0e855 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 22 Oct 2013 15:27:27 -0700 Subject: [PATCH 40/48] Commands for moving in buffer more consistent with sublime --- keymaps/apple.cson | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/keymaps/apple.cson b/keymaps/apple.cson index 5087286d8..83b856c82 100644 --- a/keymaps/apple.cson +++ b/keymaps/apple.cson @@ -5,16 +5,24 @@ 'meta-shift-down': 'core:select-to-bottom' '.editor': + 'meta-left': 'editor:move-to-first-character-of-line' 'meta-right': 'editor:move-to-end-of-line' - 'meta-left': 'editor:move-to-beginning-of-line' - 'alt-left': 'editor:move-to-beginning-of-word' - 'alt-right': 'editor:move-to-end-of-word' - 'meta-shift-left': 'editor:select-to-beginning-of-line' + 'meta-shift-left': 'editor:select-to-first-character-of-line' 'meta-shift-right': 'editor:select-to-end-of-line' - 'alt-shift-left': 'editor:select-to-beginning-of-word' - 'alt-shift-right': 'editor:select-to-end-of-word' + + 'home': 'editor:move-to-first-character-of-line' + 'end': 'editor:move-to-end-of-line' + 'shift-home': 'editor:select-to-first-character-of-line' + 'shift-end': 'editor:select-to-end-of-line' + + 'alt-left': 'editor:move-to-previous-word-boundary' + 'alt-right': 'editor:move-to-next-word-boundary' + 'alt-shift-left': 'editor:select-to-previous-word-boundary' + 'alt-shift-right': 'editor:select-to-next-word-boundary' + 'alt-backspace': 'editor:backspace-to-beginning-of-word' 'meta-backspace': 'editor:backspace-to-beginning-of-line' + 'alt-delete': 'editor:delete-to-end-of-word' 'ctrl-t': 'editor:transpose' 'ctrl-A': 'editor:select-to-first-character-of-line' From fa36ab1a5ce265829649554807b6b44ec8aed491 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 22 Oct 2013 15:44:56 -0700 Subject: [PATCH 41/48] Add apm to public API --- exports/atom.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/exports/atom.coffee b/exports/atom.coffee index 2c0bac831..ebc439db6 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -3,6 +3,7 @@ _ = require 'underscore-plus' module.exports = _: _ + apm: require 'atom-package-manager' BufferedNodeProcess: require '../src/buffered-node-process' BufferedProcess: require '../src/buffered-process' Directory: require '../src/directory' From 43dae4e9eb0ebd195c8a9f954953d026500c5e70 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 22 Oct 2013 15:52:04 -0700 Subject: [PATCH 42/48] Add helper to get apm path --- exports/atom.coffee | 1 - src/package-manager.coffee | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/exports/atom.coffee b/exports/atom.coffee index ebc439db6..2c0bac831 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -3,7 +3,6 @@ _ = require 'underscore-plus' module.exports = _: _ - apm: require 'atom-package-manager' BufferedNodeProcess: require '../src/buffered-node-process' BufferedProcess: require '../src/buffered-process' Directory: require '../src/directory' diff --git a/src/package-manager.coffee b/src/package-manager.coffee index a94153aa9..65987ab80 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -36,6 +36,10 @@ class PackageManager @packageActivators = [] @registerPackageActivator(this, ['atom', 'textmate']) + # Public: Get the path to the apm command + getApmPath: -> + @apmPath ?= require.resolve('atom-package-manager/bin/apm') + getPackageState: (name) -> @packageStates[name] From 4a48e1a22872c76213b48bf9f9e3a8a77bc5aeea Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 22 Oct 2013 15:59:49 -0700 Subject: [PATCH 43/48] Upgrade to package-generator@0.14.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a43af2dc0..8461440c6 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "link": "0.7.0", "markdown-preview": "0.11.0", "metrics": "0.8.0", - "package-generator": "0.13.0", + "package-generator": "0.14.0", "release-notes": "0.8.0", "settings-view": "0.31.0", "snippets": "0.11.0", From ba9be0c07ae9896ee29cbeb674735d6b840a2281 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Tue, 22 Oct 2013 16:00:32 -0700 Subject: [PATCH 44/48] Add Movements menu --- menus/base.cson | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/menus/base.cson b/menus/base.cson index 9404fcb8b..ee5bb4c38 100644 --- a/menus/base.cson +++ b/menus/base.cson @@ -113,6 +113,23 @@ ] } + { + label: 'Movement' + submenu: [ + { label: 'Move to Top', command: 'core:move-to-top' } + { label: 'Move to Bottom', command: 'core:move-to-bottom' } + { type: 'separator' } + { label: 'Move to Beginning of Line', command: 'editor:move-to-beginning-of-line' } + { label: 'Move to First Character of Line', command: 'editor:move-to-first-character-of-line' } + { label: 'Move to End of Line', command: 'editor:move-to-end-of-line' } + { type: 'separator' } + { label: 'Move to Beginning of Word', command: 'editor:move-to-beginning-of-word' } + { label: 'Move to End of Word', command: 'editor:move-to-end-of-word' } + { label: 'Move to Next Word', command: 'editor:move-to-next-word-boundary' } + { label: 'Move to Previous Word', command: 'editor:move-to-previous-word-boundary' } + ] + } + { label: 'View' submenu: [ From a37b029ad9132740295562fc56aaa771a2ed1875 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 22 Oct 2013 16:04:55 -0700 Subject: [PATCH 45/48] Prepend newly enabled themes, not append --- src/theme-package.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/theme-package.coffee b/src/theme-package.coffee index 363852cda..73a89e5cf 100644 --- a/src/theme-package.coffee +++ b/src/theme-package.coffee @@ -11,7 +11,9 @@ class ThemePackage extends AtomPackage getStylesheetType: -> 'theme' enable: -> - atom.config.pushAtKeyPath('core.themes', @metadata.name) + themes = atom.config.get('core.themes') + themes = [@metadata.name].concat(themes) + atom.config.set('core.themes', themes) disable: -> atom.config.removeAtKeyPath('core.themes', @metadata.name) From cdebc2306cfdfe123bf70235597f8508a037add8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 22 Oct 2013 16:06:23 -0700 Subject: [PATCH 46/48] Upgrade apm for install version fix --- vendor/apm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/apm b/vendor/apm index 08f26c2ed..0bd38255e 160000 --- a/vendor/apm +++ b/vendor/apm @@ -1 +1 @@ -Subproject commit 08f26c2edb8d041b9cd8374c6e901fb9c026e6ad +Subproject commit 0bd38255ea0aa0fec2a932177b30a388c2d16ded From 48335bd4ac036b8e819824a680c6eb80aed7845d Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Tue, 22 Oct 2013 16:08:05 -0700 Subject: [PATCH 47/48] Upgrade exception-report@0.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8461440c6..a9bd5929c 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "command-palette": "0.5.0", "dev-live-reload": "0.11.0", "editor-stats": "0.5.0", - "exception-reporting": "0.4.0", + "exception-reporting": "0.5.0", "find-and-replace": "0.29.0", "fuzzy-finder": "0.15.0", "gfm": "0.5.0", From e38f7259e5aebaa1134cc66aebda664200a27e37 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Tue, 22 Oct 2013 16:12:15 -0700 Subject: [PATCH 48/48] Upgrade symbols-view@0.13.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9bd5929c..edafcea7d 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "spell-check": "0.8.0", "status-bar": "0.15.0", "styleguide": "0.9.0", - "symbols-view": "0.12.0", + "symbols-view": "0.13.0", "tabs": "0.7.0", "terminal": "0.14.0", "timecop": "0.7.0",