From 2600115ebe81ac7f17a8a17dc9cb85e9402da038 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 25 Sep 2015 15:15:11 -0600 Subject: [PATCH 001/316] Start moving toward a customizable test runner --- spec/jasmine-helper.coffee | 59 ----------------------- spec/jasmine-test-runner.coffee | 85 +++++++++++++++++++++++++++++++++ spec/spec-bootstrap.coffee | 14 ++++-- spec/spec-suite.coffee | 55 --------------------- 4 files changed, 94 insertions(+), 119 deletions(-) delete mode 100644 spec/jasmine-helper.coffee create mode 100644 spec/jasmine-test-runner.coffee delete mode 100644 spec/spec-suite.coffee diff --git a/spec/jasmine-helper.coffee b/spec/jasmine-helper.coffee deleted file mode 100644 index 74e4a0384..000000000 --- a/spec/jasmine-helper.coffee +++ /dev/null @@ -1,59 +0,0 @@ -fs = require 'fs' - -module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) -> - window[key] = value for key, value of require '../vendor/jasmine' - - {TerminalReporter} = require 'jasmine-tagged' - - disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI - - TimeReporter = require './time-reporter' - timeReporter = new TimeReporter() - - logStream = fs.openSync(logFile, 'w') if logFile? - log = (str) -> - if logStream? - fs.writeSync(logStream, str) - else - process.stderr.write(str) - - if atom.getLoadSettings().exitWhenDone - reporter = new TerminalReporter - print: (str) -> - log(str) - onComplete: (runner) -> - fs.closeSync(logStream) if logStream? - if process.env.JANKY_SHA1 or process.env.CI - grim = require 'grim' - - if grim.getDeprecationsLength() > 0 - grim.logDeprecations() - return atom.exit(1) - - if runner.results().failedCount > 0 - atom.exit(1) - else - atom.exit(0) - else - AtomReporter = require './atom-reporter' - reporter = new AtomReporter() - - require specSuite - - jasmineEnv = jasmine.getEnv() - jasmineEnv.addReporter(reporter) - jasmineEnv.addReporter(timeReporter) - jasmineEnv.setIncludedTags([process.platform]) - - jasmineContent = document.createElement('div') - jasmineContent.setAttribute('id', 'jasmine-content') - document.body.appendChild(jasmineContent) - - jasmineEnv.execute() - -disableFocusMethods = -> - ['fdescribe', 'ffdescribe', 'fffdescribe', 'fit', 'ffit', 'fffit'].forEach (methodName) -> - focusMethod = window[methodName] - window[methodName] = (description) -> - error = new Error('Focused spec is running on CI') - focusMethod description, -> throw error diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee new file mode 100644 index 000000000..a85e3a8a2 --- /dev/null +++ b/spec/jasmine-test-runner.coffee @@ -0,0 +1,85 @@ +fs = require 'fs' +_ = require 'underscore-plus' +fs = require 'fs-plus' +path = require 'path' + +module.exports = ({logFile, exitWhenDone, testPaths}) -> + window[key] = value for key, value of require '../vendor/jasmine' + require 'jasmine-tagged' + + require './spec-helper' + disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI + requireSpecs(testPath) for testPath in testPaths + + setSpecType('user') + + jasmineEnv = jasmine.getEnv() + jasmineEnv.addReporter(buildReporter({logFile, exitWhenDone})) + TimeReporter = require './time-reporter' + jasmineEnv.addReporter(new TimeReporter()) + jasmineEnv.setIncludedTags([process.platform]) + + jasmineContent = document.createElement('div') + jasmineContent.setAttribute('id', 'jasmine-content') + document.body.appendChild(jasmineContent) + + jasmineEnv.execute() + +disableFocusMethods = -> + ['fdescribe', 'ffdescribe', 'fffdescribe', 'fit', 'ffit', 'fffit'].forEach (methodName) -> + focusMethod = window[methodName] + window[methodName] = (description) -> + error = new Error('Focused spec is running on CI') + focusMethod description, -> throw error + +requireSpecs = (specDirectory, specType) -> + for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.(coffee|js)$/.test specFilePath + require specFilePath + # Set spec directory on spec for setting up the project in spec-helper + setSpecDirectory(specDirectory) + +setSpecField = (name, value) -> + specs = jasmine.getEnv().currentRunner().specs() + return if specs.length is 0 + for index in [specs.length-1..0] + break if specs[index][name]? + specs[index][name] = value + +setSpecType = (specType) -> + setSpecField('specType', specType) + +setSpecDirectory = (specDirectory) -> + setSpecField('specDirectory', specDirectory) + +buildReporter = ({logFile, exitWhenDone}) -> + if exitWhenDone + buildTerminalReporter(logFile) + else + AtomReporter = require './atom-reporter' + reporter = new AtomReporter() + +buildTerminalReporter = (logFile) -> + logStream = fs.openSync(logFile, 'w') if logFile? + log = (str) -> + if logStream? + fs.writeSync(logStream, str) + else + process.stderr.write(str) + + {TerminalReporter} = require 'jasmine-tagged' + new TerminalReporter + print: (str) -> + log(str) + onComplete: (runner) -> + fs.closeSync(logStream) if logStream? + if process.env.JANKY_SHA1 + grim = require 'grim' + + if grim.getDeprecationsLength() > 0 + grim.logDeprecations() + return atom.exit(1) + + if runner.results().failedCount > 0 + atom.exit(1) + else + atom.exit(0) diff --git a/spec/spec-bootstrap.coffee b/spec/spec-bootstrap.coffee index 5158c9bee..7cf972484 100644 --- a/spec/spec-bootstrap.coffee +++ b/spec/spec-bootstrap.coffee @@ -12,16 +12,20 @@ try # that are focused in the very first spec run. atom.getCurrentWindow().show() unless atom.getLoadSettings().exitWhenDone - {runSpecSuite} = require './jasmine-helper' - # Add 'exports' to module search path. exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports') require('module').globalPaths.push(exportsPath) - # Still set NODE_PATH since tasks may need it. - process.env.NODE_PATH = exportsPath + process.env.NODE_PATH = exportsPath # Set NODE_PATH env variable since tasks may need it. document.title = "Spec Suite" - runSpecSuite './spec-suite', atom.getLoadSettings().logFile + + testRunner = require('./jasmine-test-runner') + testRunner({ + logFile: atom.getLoadSettings().logFile + exitWhenDone: atom.getLoadSettings().exitWhenDone + testPaths: [atom.getLoadSettings().specDirectory] + }) + catch error if atom?.getLoadSettings().exitWhenDone console.error(error.stack ? error) diff --git a/spec/spec-suite.coffee b/spec/spec-suite.coffee deleted file mode 100644 index 817de7986..000000000 --- a/spec/spec-suite.coffee +++ /dev/null @@ -1,55 +0,0 @@ -_ = require 'underscore-plus' -fs = require 'fs-plus' -path = require 'path' -require './spec-helper' - -requireSpecs = (specDirectory, specType) -> - for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.(coffee|js)$/.test specFilePath - require specFilePath - - # Set spec directory on spec for setting up the project in spec-helper - setSpecDirectory(specDirectory) - -setSpecField = (name, value) -> - specs = jasmine.getEnv().currentRunner().specs() - return if specs.length is 0 - for index in [specs.length-1..0] - break if specs[index][name]? - specs[index][name] = value - -setSpecType = (specType) -> - setSpecField('specType', specType) - -setSpecDirectory = (specDirectory) -> - setSpecField('specDirectory', specDirectory) - -runAllSpecs = -> - {resourcePath} = atom.getLoadSettings() - - requireSpecs(path.join(resourcePath, 'spec')) - setSpecType('core') - - fixturesPackagesPath = path.join(__dirname, 'fixtures', 'packages') - packagePaths = atom.packages.getAvailablePackageNames().map (packageName) -> - atom.packages.resolvePackagePath(packageName) - packagePaths = _.groupBy packagePaths, (packagePath) -> - if packagePath.indexOf("#{fixturesPackagesPath}#{path.sep}") is 0 - 'fixtures' - else if packagePath.indexOf("#{resourcePath}#{path.sep}") is 0 - 'bundled' - else - 'user' - - # Run bundled package specs - requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.bundled ? [] - setSpecType('bundled') - - # Run user package specs - requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.user ? [] - setSpecType('user') - -if specDirectory = atom.getLoadSettings().specDirectory - requireSpecs(specDirectory) - setSpecType('user') -else - runAllSpecs() From 8e988e874e29dfd598c84cd572c0a9ce1c1ce00b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 25 Sep 2015 15:49:57 -0600 Subject: [PATCH 002/316] Rename exitWhenDone to headless --- spec/jasmine-test-runner.coffee | 8 ++++---- spec/spec-bootstrap.coffee | 6 +++--- src/browser/atom-application.coffee | 12 ++++++------ src/browser/atom-window.coffee | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index a85e3a8a2..2c2d8553d 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -3,7 +3,7 @@ _ = require 'underscore-plus' fs = require 'fs-plus' path = require 'path' -module.exports = ({logFile, exitWhenDone, testPaths}) -> +module.exports = ({logFile, headless, testPaths}) -> window[key] = value for key, value of require '../vendor/jasmine' require 'jasmine-tagged' @@ -14,7 +14,7 @@ module.exports = ({logFile, exitWhenDone, testPaths}) -> setSpecType('user') jasmineEnv = jasmine.getEnv() - jasmineEnv.addReporter(buildReporter({logFile, exitWhenDone})) + jasmineEnv.addReporter(buildReporter({logFile, headless})) TimeReporter = require './time-reporter' jasmineEnv.addReporter(new TimeReporter()) jasmineEnv.setIncludedTags([process.platform]) @@ -51,8 +51,8 @@ setSpecType = (specType) -> setSpecDirectory = (specDirectory) -> setSpecField('specDirectory', specDirectory) -buildReporter = ({logFile, exitWhenDone}) -> - if exitWhenDone +buildReporter = ({logFile, headless}) -> + if headless buildTerminalReporter(logFile) else AtomReporter = require './atom-reporter' diff --git a/spec/spec-bootstrap.coffee b/spec/spec-bootstrap.coffee index 7cf972484..0bf691d05 100644 --- a/spec/spec-bootstrap.coffee +++ b/spec/spec-bootstrap.coffee @@ -10,7 +10,7 @@ try # Show window synchronously so a focusout doesn't fire on input elements # that are focused in the very first spec run. - atom.getCurrentWindow().show() unless atom.getLoadSettings().exitWhenDone + atom.getCurrentWindow().show() unless atom.getLoadSettings().headless # Add 'exports' to module search path. exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports') @@ -22,12 +22,12 @@ try testRunner = require('./jasmine-test-runner') testRunner({ logFile: atom.getLoadSettings().logFile - exitWhenDone: atom.getLoadSettings().exitWhenDone + headless: atom.getLoadSettings().headless testPaths: [atom.getLoadSettings().specDirectory] }) catch error - if atom?.getLoadSettings().exitWhenDone + if atom?.getLoadSettings().headless console.error(error.stack ? error) atom.exit(1) else diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 0be160b5d..6e587e8f1 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -87,7 +87,7 @@ class AtomApplication openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, profileStartup}) -> if test - @runSpecs({exitWhenDone: true, @resourcePath, specDirectory, logFile}) + @runSpecs({headless: true, @resourcePath, specDirectory, logFile}) else if pathsToOpen.length > 0 @openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup}) else if urlsToOpen.length > 0 @@ -160,7 +160,7 @@ class AtomApplication devMode: @focusedWindow()?.devMode safeMode: @focusedWindow()?.safeMode - @on 'application:run-all-specs', -> @runSpecs(exitWhenDone: false, resourcePath: @devResourcePath, safeMode: @focusedWindow()?.safeMode) + @on 'application:run-all-specs', -> @runSpecs(headless: false, resourcePath: @devResourcePath, safeMode: @focusedWindow()?.safeMode) @on 'application:quit', -> app.quit() @on 'application:new-window', -> @openPath(_.extend(windowDimensions: @focusedWindow()?.getDimensions(), getLoadSettings())) @on 'application:new-file', -> (@focusedWindow() ? this).openPath() @@ -251,7 +251,7 @@ class AtomApplication @applicationMenu.update(win, template, keystrokesByCommand) ipc.on 'run-package-specs', (event, specDirectory) => - @runSpecs({resourcePath: @devResourcePath, specDirectory: specDirectory, exitWhenDone: false}) + @runSpecs({resourcePath: @devResourcePath, specDirectory: specDirectory, headless: false}) ipc.on 'command', (event, command) => @emit(command) @@ -483,13 +483,13 @@ class AtomApplication # Opens up a new {AtomWindow} to run specs within. # # options - - # :exitWhenDone - A Boolean that, if true, will close the window upon + # :headless - A Boolean that, if true, will close the window upon # completion. # :resourcePath - The path to include specs from. # :specPath - The directory to load specs from. # :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages # and ~/.atom/dev/packages, defaults to false. - runSpecs: ({exitWhenDone, resourcePath, specDirectory, logFile, safeMode}) -> + runSpecs: ({headless, resourcePath, specDirectory, logFile, safeMode}) -> if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath @@ -501,7 +501,7 @@ class AtomApplication isSpec = true devMode = true safeMode ?= false - new AtomWindow({bootstrapScript, resourcePath, exitWhenDone, isSpec, devMode, specDirectory, logFile, safeMode}) + new AtomWindow({bootstrapScript, resourcePath, headless, isSpec, devMode, specDirectory, logFile, safeMode}) locationForPathToOpen: (pathToOpen, executedFrom='') -> return {pathToOpen} unless pathToOpen diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 99b28444f..12d7ccd98 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -19,7 +19,7 @@ class AtomWindow isSpec: null constructor: (settings={}) -> - {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @exitWhenDone, @safeMode, @devMode} = settings + {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode} = settings locationsToOpen ?= [{pathToOpen}] if pathToOpen locationsToOpen ?= [] @@ -131,7 +131,7 @@ class AtomWindow @browserWindow.destroy() if chosen is 0 @browserWindow.webContents.on 'crashed', => - global.atomApplication.exit(100) if @exitWhenDone + global.atomApplication.exit(100) if @headless chosen = dialog.showMessageBox @browserWindow, type: 'warning' From e886d8b25336f6420124ef3285f08fa374bbab94 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 25 Sep 2015 16:04:10 -0600 Subject: [PATCH 003/316] =?UTF-8?q?Rename=20=E2=80=9Cbootstrap=E2=80=9D=20?= =?UTF-8?q?scripts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They’re just window initialization scripts, and this new naming makes that a lot clearer. --- src/browser/atom-application.coffee | 16 ++++++++-------- ...ffee => initialize-application-window.coffee} | 0 .../initialize-test-window.coffee | 2 +- static/index.js | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) rename src/{window-bootstrap.coffee => initialize-application-window.coffee} (100%) rename spec/spec-bootstrap.coffee => src/initialize-test-window.coffee (95%) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 6e587e8f1..ce2355aa6 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -392,12 +392,12 @@ class AtomApplication else if devMode try - bootstrapScript = require.resolve(path.join(@devResourcePath, 'src', 'window-bootstrap')) + windowInitializationScript = require.resolve(path.join(@devResourcePath, 'src', 'initialize-application-window')) resourcePath = @devResourcePath - bootstrapScript ?= require.resolve('../window-bootstrap') + windowInitializationScript ?= require.resolve('../initialize-application-window') resourcePath ?= @resourcePath - openedWindow = new AtomWindow({locationsToOpen, bootstrapScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup}) + openedWindow = new AtomWindow({locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup}) if pidToKillWhenClosed? @pidsToOpenWindows[pidToKillWhenClosed] = openedWindow @@ -472,9 +472,9 @@ class AtomApplication if pack? if pack.urlMain packagePath = @packages.resolvePackagePath(packageName) - bootstrapScript = path.resolve(packagePath, pack.urlMain) + windowInitializationScript = path.resolve(packagePath, pack.urlMain) windowDimensions = @focusedWindow()?.getDimensions() - new AtomWindow({bootstrapScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions}) + new AtomWindow({windowInitializationScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions}) else console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}" else @@ -494,14 +494,14 @@ class AtomApplication resourcePath = @resourcePath try - bootstrapScript = require.resolve(path.resolve(@devResourcePath, 'spec', 'spec-bootstrap')) + windowInitializationScript = require.resolve(path.resolve(@devResourcePath, 'src', 'initialize-test-window')) catch error - bootstrapScript = require.resolve(path.resolve(__dirname, '..', '..', 'spec', 'spec-bootstrap')) + windowInitializationScript = require.resolve(path.resolve(__dirname, '..', '..', 'src', 'initialize-test-window')) isSpec = true devMode = true safeMode ?= false - new AtomWindow({bootstrapScript, resourcePath, headless, isSpec, devMode, specDirectory, logFile, safeMode}) + new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, specDirectory, logFile, safeMode}) locationForPathToOpen: (pathToOpen, executedFrom='') -> return {pathToOpen} unless pathToOpen diff --git a/src/window-bootstrap.coffee b/src/initialize-application-window.coffee similarity index 100% rename from src/window-bootstrap.coffee rename to src/initialize-application-window.coffee diff --git a/spec/spec-bootstrap.coffee b/src/initialize-test-window.coffee similarity index 95% rename from spec/spec-bootstrap.coffee rename to src/initialize-test-window.coffee index 0bf691d05..77461667c 100644 --- a/spec/spec-bootstrap.coffee +++ b/src/initialize-test-window.coffee @@ -19,7 +19,7 @@ try document.title = "Spec Suite" - testRunner = require('./jasmine-test-runner') + testRunner = require('../spec/jasmine-test-runner') testRunner({ logFile: atom.getLoadSettings().logFile headless: atom.getLoadSettings().headless diff --git a/static/index.js b/static/index.js index 11527e963..5f90591f0 100644 --- a/static/index.js +++ b/static/index.js @@ -76,7 +76,7 @@ setupVmCompatibility() setupCsonCache(CompileCache.getCacheDirectory()) - require(loadSettings.bootstrapScript) + require(loadSettings.windowInitializationScript) require('ipc').sendChannel('window-command', 'window:loaded') } From e4d64309b71bd6a1c23a4a71fc7578351ad3ec0d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 27 Sep 2015 20:53:41 -0600 Subject: [PATCH 004/316] Allow multiple test paths to be specified as command line arguments --- src/browser/atom-application.coffee | 16 +++++++++++----- src/initialize-test-window.coffee | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index ce2355aa6..9ac5ea8b9 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -87,7 +87,7 @@ class AtomApplication openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, profileStartup}) -> if test - @runSpecs({headless: true, @resourcePath, specDirectory, logFile}) + @runTests({headless: true, @resourcePath, executedFrom, specDirectory, pathsToOpen, logFile}) else if pathsToOpen.length > 0 @openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup}) else if urlsToOpen.length > 0 @@ -160,7 +160,7 @@ class AtomApplication devMode: @focusedWindow()?.devMode safeMode: @focusedWindow()?.safeMode - @on 'application:run-all-specs', -> @runSpecs(headless: false, resourcePath: @devResourcePath, safeMode: @focusedWindow()?.safeMode) + @on 'application:run-all-specs', -> @runTests(headless: false, resourcePath: @devResourcePath, safeMode: @focusedWindow()?.safeMode) @on 'application:quit', -> app.quit() @on 'application:new-window', -> @openPath(_.extend(windowDimensions: @focusedWindow()?.getDimensions(), getLoadSettings())) @on 'application:new-file', -> (@focusedWindow() ? this).openPath() @@ -251,7 +251,7 @@ class AtomApplication @applicationMenu.update(win, template, keystrokesByCommand) ipc.on 'run-package-specs', (event, specDirectory) => - @runSpecs({resourcePath: @devResourcePath, specDirectory: specDirectory, headless: false}) + @runTests({resourcePath: @devResourcePath, specDirectory: specDirectory, headless: false}) ipc.on 'command', (event, command) => @emit(command) @@ -489,7 +489,7 @@ class AtomApplication # :specPath - The directory to load specs from. # :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages # and ~/.atom/dev/packages, defaults to false. - runSpecs: ({headless, resourcePath, specDirectory, logFile, safeMode}) -> + runTests: ({headless, resourcePath, executedFrom, specDirectory, pathsToOpen, logFile, safeMode}) -> if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath @@ -498,10 +498,16 @@ class AtomApplication catch error windowInitializationScript = require.resolve(path.resolve(__dirname, '..', '..', 'src', 'initialize-test-window')) + testPaths = [] + testPaths.push(specDirectory) if specDirectory? + if pathsToOpen? + for pathToOpen in pathsToOpen + testPaths.push(path.resolve(executedFrom, fs.normalize(pathToOpen))) + isSpec = true devMode = true safeMode ?= false - new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, specDirectory, logFile, safeMode}) + new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testPaths, logFile, safeMode}) locationForPathToOpen: (pathToOpen, executedFrom='') -> return {pathToOpen} unless pathToOpen diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 77461667c..aa8e7f5d6 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -23,7 +23,7 @@ try testRunner({ logFile: atom.getLoadSettings().logFile headless: atom.getLoadSettings().headless - testPaths: [atom.getLoadSettings().specDirectory] + testPaths: atom.getLoadSettings().testPaths }) catch error From 7a77ffde433679c0bce9485476f62d3659af3dd6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 27 Sep 2015 21:00:21 -0600 Subject: [PATCH 005/316] Log to stdout from terminal runner via ipc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason, logging to stderr/stdout from the render process only works when Atom is run via child_process.spawn, which is how `apm test` invokes it. I’m trying to make a convenient interface for running tests directly via the `atom` command, and this is the only way I could find to long to stdout from the render process. I’m also choosing stdout rather than stderr because in this case, you’re intentionally running the tests and want to see feedback. --- spec/jasmine-test-runner.coffee | 3 ++- src/browser/atom-application.coffee | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 2c2d8553d..8a42033b9 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -2,6 +2,7 @@ fs = require 'fs' _ = require 'underscore-plus' fs = require 'fs-plus' path = require 'path' +ipc = require 'ipc' module.exports = ({logFile, headless, testPaths}) -> window[key] = value for key, value of require '../vendor/jasmine' @@ -64,7 +65,7 @@ buildTerminalReporter = (logFile) -> if logStream? fs.writeSync(logStream, str) else - process.stderr.write(str) + ipc.send 'write-to-stdout', str {TerminalReporter} = require 'jasmine-tagged' new TerminalReporter diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 9ac5ea8b9..6c0b0bff4 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -275,6 +275,9 @@ class AtomApplication ipc.on 'write-text-to-selection-clipboard', (event, selectedText) -> clipboard.writeText(selectedText, 'selection') + ipc.on 'write-to-stdout', (event, output) -> + process.stdout.write(output) + # Public: Executes the given command. # # If it isn't handled globally, delegate to the currently focused window. From 2e54ae1e570e66c9467d30986317b8f6e326a548 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 27 Sep 2015 21:53:09 -0600 Subject: [PATCH 006/316] Allow a custom test runner path to be specified in package.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the nearest containing package.json of a test path has an atomTestRunner field, we’ll require the specified file as a test runner rather than the default jasmine runner. --- package.json | 2 ++ src/browser/atom-application.coffee | 24 +++++++++++++++++++++++- src/initialize-test-window.coffee | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5e4271b17..221004c12 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "coffee-script": "1.8.0", "color": "^0.7.3", "event-kit": "^1.3.0", + "find-parent-dir": "^0.3.0", "first-mate": "^5.0.0", "fs-plus": "^2.8.0", "fstream": "0.1.24", @@ -40,6 +41,7 @@ "pathwatcher": "^6.2", "property-accessors": "^1.1.3", "random-words": "0.0.1", + "resolve": "^1.1.6", "runas": "^3.1", "scandal": "^2.2", "scoped-property-store": "^0.17.0", diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 6c0b0bff4..72e371cf8 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -16,6 +16,8 @@ net = require 'net' url = require 'url' {EventEmitter} = require 'events' _ = require 'underscore-plus' +FindParentDir = null +Resolve = null LocationSuffixRegExp = /(:\d+)(:\d+)?$/ @@ -507,10 +509,30 @@ class AtomApplication for pathToOpen in pathsToOpen testPaths.push(path.resolve(executedFrom, fs.normalize(pathToOpen))) + if testPaths.length is 0 + process.stderr.write 'Error: Specify at least one test path\n\n' + process.exit(1) + + testRunnerPath = @resolveTestRunnerPath(testPaths[0]) isSpec = true devMode = true safeMode ?= false - new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testPaths, logFile, safeMode}) + new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, testPaths, logFile, safeMode}) + + resolveTestRunnerPath: (testPath) -> + FindParentDir ?= require 'find-parent-dir' + + if packageRoot = FindParentDir.sync(testPath, 'package.json') + packageMetadata = require(path.join(packageRoot, 'package.json')) + if packageMetadata.atomTestRunner + Resolve ?= require('resolve') + if testRunnerPath = Resolve.sync(packageMetadata.atomTestRunner, basedir: packageRoot, extensions: Object.keys(require.extensions)) + return testRunnerPath + else + process.stderr.write "Error: Could not resolve test runner path '#{packageMetadata.atomTestRunner}'" + process.exit(1) + + require.resolve('../../spec/jasmine-test-runner') locationForPathToOpen: (pathToOpen, executedFrom='') -> return {pathToOpen} unless pathToOpen diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index aa8e7f5d6..79a1d9c2c 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -19,7 +19,7 @@ try document.title = "Spec Suite" - testRunner = require('../spec/jasmine-test-runner') + testRunner = require(atom.getLoadSettings().testRunnerPath) testRunner({ logFile: atom.getLoadSettings().logFile headless: atom.getLoadSettings().headless From b32d49fab11cff98c3611bf927746a397589d60b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 10:50:59 -0600 Subject: [PATCH 007/316] Allow running of individual test paths in legacy jasmine runner --- spec/jasmine-test-runner.coffee | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 8a42033b9..03e67bea3 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -33,11 +33,15 @@ disableFocusMethods = -> error = new Error('Focused spec is running on CI') focusMethod description, -> throw error -requireSpecs = (specDirectory, specType) -> - for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.(coffee|js)$/.test specFilePath - require specFilePath - # Set spec directory on spec for setting up the project in spec-helper - setSpecDirectory(specDirectory) +requireSpecs = (testPath, specType) -> + if fs.isDirectorySync(testPath) + for testFilePath in fs.listTreeSync(testPath) when /-spec\.(coffee|js)$/.test testFilePath + require(testFilePath) + # Set spec directory on spec for setting up the project in spec-helper + setSpecDirectory(testPath) + else + require(testPath) + setSpecDirectory(path.dirname(testPath)) setSpecField = (name, value) -> specs = jasmine.getEnv().currentRunner().specs() From 009dae171788f319388e59c5de4c7496811baca7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 11:43:17 -0600 Subject: [PATCH 008/316] =?UTF-8?q?Default=20to=20using=20the=20jasmine-te?= =?UTF-8?q?st-runner=20in=20Atom=E2=80=99s=20dev=20resource=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/browser/atom-application.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 72e371cf8..8aaa237dc 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -532,7 +532,10 @@ class AtomApplication process.stderr.write "Error: Could not resolve test runner path '#{packageMetadata.atomTestRunner}'" process.exit(1) - require.resolve('../../spec/jasmine-test-runner') + try + require.resolve(path.resolve(@devResourcePath, 'spec', 'jasmine-test-runner')) + catch error + require.resolve(path.resolve(__dirname, '..', '..', 'spec', 'jasmine-test-runner')) locationForPathToOpen: (pathToOpen, executedFrom='') -> return {pathToOpen} unless pathToOpen From 43c959fdebaa68d542bfe48a727041592d8ed247 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 11:51:31 -0600 Subject: [PATCH 009/316] Assign notifications in Atom environment constructor --- src/atom.coffee | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 59d7765ac..d5bcd952e 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -151,13 +151,18 @@ class Atom extends Model # Call .loadOrCreate instead constructor: (@state) -> + {@mode} = @state + @emitter = new Emitter @disposables = new CompositeDisposable - {@mode} = @state + DeserializerManager = require './deserializer-manager' @deserializers = new DeserializerManager() @deserializeTimings = {} + NotificationManager = require './notification-manager' + @notifications = new NotificationManager + # Sets up the basic services that should be available in all modes # (both spec and application). # @@ -196,7 +201,6 @@ class Atom extends Model ViewRegistry = require './view-registry' CommandRegistry = require './command-registry' TooltipManager = require './tooltip-manager' - NotificationManager = require './notification-manager' PackageManager = require './package-manager' Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' @@ -220,7 +224,6 @@ class Atom extends Model @keymaps = new KeymapManager({configDirPath, resourcePath}) @keymaps.subscribeToFileReadFailure() @tooltips = new TooltipManager - @notifications = new NotificationManager @commands = new CommandRegistry @views = new ViewRegistry @registerViewProviders() From 88d80b1c9766c855aabc7e9fcf3f1ad1c9906d6f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 13:21:50 -0600 Subject: [PATCH 010/316] Assign config in Atom environment constructor --- spec/spec-helper.coffee | 25 ++++++++++++------------- src/atom.coffee | 10 ++++++++-- src/config.coffee | 12 +++++++----- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 085db7835..0d538b7a3 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -10,7 +10,6 @@ fs = require 'fs-plus' Grim = require 'grim' KeymapManager = require '../src/keymap-extensions' -Config = require '../src/config' {Point} = require 'text-buffer' Project = require '../src/project' Workspace = require '../src/workspace' @@ -124,22 +123,20 @@ beforeEach -> spyOn(atom.menu, 'sendToBrowserProcess') # reset config before each spec; don't load or save from/to `config.json` - spyOn(Config::, 'load') - spyOn(Config::, 'save') - config = new Config({resourcePath, configDirPath: atom.getConfigDirPath()}) - atom.config = config + spyOn(atom.config, 'load') + spyOn(atom.config, 'save') atom.loadConfig() - config.set "core.destroyEmptyPanes", false - config.set "editor.fontFamily", "Courier" - config.set "editor.fontSize", 16 - config.set "editor.autoIndent", false - config.set "core.disabledPackages", ["package-that-throws-an-exception", + atom.config.set "core.destroyEmptyPanes", false + atom.config.set "editor.fontFamily", "Courier" + atom.config.set "editor.fontSize", 16 + atom.config.set "editor.autoIndent", false + atom.config.set "core.disabledPackages", ["package-that-throws-an-exception", "package-with-broken-package-json", "package-with-broken-keymap"] - config.set "editor.useShadowDOM", true + atom.config.set "editor.useShadowDOM", true advanceClock(1000) window.setTimeout.reset() - config.load.reset() - config.save.reset() + atom.config.load.reset() + atom.config.save.reset() # make editor display updates synchronous TextEditorElement::setUpdatedSynchronously(true) @@ -159,6 +156,8 @@ beforeEach -> addCustomMatchers(this) afterEach -> + atom.reset() + atom.packages.deactivatePackages() atom.menu.template = [] atom.contextMenu.clear() diff --git a/src/atom.coffee b/src/atom.coffee index d5bcd952e..7202824b1 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -152,6 +152,8 @@ class Atom extends Model # Call .loadOrCreate instead constructor: (@state) -> {@mode} = @state + {resourcePath} = @getLoadSettings() + configDirPath = @getConfigDirPath() @emitter = new Emitter @disposables = new CompositeDisposable @@ -163,6 +165,12 @@ class Atom extends Model NotificationManager = require './notification-manager' @notifications = new NotificationManager + Config = require './config' + @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) + + reset: -> + @config.reset() + # Sets up the basic services that should be available in all modes # (both spec and application). # @@ -196,7 +204,6 @@ class Atom extends Model @loadTime = null - Config = require './config' KeymapManager = require './keymap-extensions' ViewRegistry = require './view-registry' CommandRegistry = require './command-registry' @@ -220,7 +227,6 @@ class Atom extends Model # Make react.js faster process.env.NODE_ENV ?= 'production' unless devMode - @config = new Config({configDirPath, resourcePath}) @keymaps = new KeymapManager({configDirPath, resourcePath}) @keymaps.subscribeToFileReadFailure() @tooltips = new TooltipManager diff --git a/src/config.coffee b/src/config.coffee index 176390869..f914be820 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -331,7 +331,12 @@ class Config value # Created during initialization, available as `atom.config` - constructor: ({@configDirPath, @resourcePath}={}) -> + constructor: ({@configDirPath, @resourcePath, @notificationManager}={}) -> + @configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson']) + @configFilePath ?= path.join(@configDirPath, 'config.cson') + @reset() + + reset: -> @emitter = new Emitter @schema = type: 'object' @@ -340,11 +345,8 @@ class Config @settings = {} @scopedSettingsStore = new ScopedPropertyStore @configFileHasErrors = false - @configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson']) - @configFilePath ?= path.join(@configDirPath, 'config.cson') @transactDepth = 0 @savePending = false - @requestLoad = _.debounce(@loadUserConfig, 100) @requestSave = => @savePending = true @@ -779,7 +781,7 @@ class Config @watchSubscription = null notifyFailure: (errorMessage, detail) -> - atom.notifications.addError(errorMessage, {detail, dismissable: true}) + @notificationManager.addError(errorMessage, {detail, dismissable: true}) save: -> allSettings = {'*': @settings} From 68b9512da0f9536bd147548681de1d889b1c60c7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 13:26:10 -0600 Subject: [PATCH 011/316] Assign keymaps in Atom environment constructor --- src/atom.coffee | 6 ++++-- src/keymap-extensions.coffee | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 7202824b1..12dc52516 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -168,6 +168,10 @@ class Atom extends Model Config = require './config' @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) + KeymapManager = require './keymap-extensions' + @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) + + reset: -> @config.reset() @@ -204,7 +208,6 @@ class Atom extends Model @loadTime = null - KeymapManager = require './keymap-extensions' ViewRegistry = require './view-registry' CommandRegistry = require './command-registry' TooltipManager = require './tooltip-manager' @@ -227,7 +230,6 @@ class Atom extends Model # Make react.js faster process.env.NODE_ENV ?= 'production' unless devMode - @keymaps = new KeymapManager({configDirPath, resourcePath}) @keymaps.subscribeToFileReadFailure() @tooltips = new TooltipManager @commands = new CommandRegistry diff --git a/src/keymap-extensions.coffee b/src/keymap-extensions.coffee index da77f0156..61ce1a315 100644 --- a/src/keymap-extensions.coffee +++ b/src/keymap-extensions.coffee @@ -41,11 +41,11 @@ KeymapManager::loadUserKeymap = -> [this document][watches] for more info. [watches]:https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#typeerror-unable-to-watch-path """ - atom.notifications.addError(message, {dismissable: true}) + @notificationManager.addError(message, {dismissable: true}) else detail = error.path stack = error.stack - atom.notifications.addFatalError(error.message, {detail, stack, dismissable: true}) + @notificationManager.addFatalError(error.message, {detail, stack, dismissable: true}) KeymapManager::subscribeToFileReadFailure = -> @onDidFailToReadFile (error) => @@ -57,6 +57,6 @@ KeymapManager::subscribeToFileReadFailure = -> else error.message - atom.notifications.addError(message, {detail, dismissable: true}) + @notificationManager.addError(message, {detail, dismissable: true}) module.exports = KeymapManager From 54ab5980fa6feedf0c170a4193715b7a05b2aef0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 13:42:34 -0600 Subject: [PATCH 012/316] Assign tooltips in Atom environment constructor --- src/atom.coffee | 4 ++-- src/tooltip-manager.coffee | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 12dc52516..10cb868d6 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -171,6 +171,8 @@ class Atom extends Model KeymapManager = require './keymap-extensions' @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) + TooltipManager = require './tooltip-manager' + @tooltips = new TooltipManager(keymapManager: @keymaps) reset: -> @config.reset() @@ -210,7 +212,6 @@ class Atom extends Model ViewRegistry = require './view-registry' CommandRegistry = require './command-registry' - TooltipManager = require './tooltip-manager' PackageManager = require './package-manager' Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' @@ -231,7 +232,6 @@ class Atom extends Model process.env.NODE_ENV ?= 'production' unless devMode @keymaps.subscribeToFileReadFailure() - @tooltips = new TooltipManager @commands = new CommandRegistry @views = new ViewRegistry @registerViewProviders() diff --git a/src/tooltip-manager.coffee b/src/tooltip-manager.coffee index 21b8b07c6..247437535 100644 --- a/src/tooltip-manager.coffee +++ b/src/tooltip-manager.coffee @@ -54,6 +54,8 @@ class TooltipManager placement: 'auto top' viewportPadding: 2 + constructor: ({@keymapManager}) -> + # Essential: Add a tooltip to the given element. # # * `target` An `HTMLElement` @@ -81,7 +83,7 @@ class TooltipManager {keyBindingCommand, keyBindingTarget} = options if keyBindingCommand? - bindings = atom.keymaps.findKeyBindings(command: keyBindingCommand, target: keyBindingTarget) + bindings = @keymapManager.findKeyBindings(command: keyBindingCommand, target: keyBindingTarget) keystroke = getKeystroke(bindings) if options.title? and keystroke? options.title += " " + getKeystroke(bindings) From 2c440dada83b9af8deea5dff6de0ab8876f7972e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 13:43:18 -0600 Subject: [PATCH 013/316] Assign commands in Atom environment constructor --- src/atom.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 10cb868d6..3c7e49d91 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -174,6 +174,9 @@ class Atom extends Model TooltipManager = require './tooltip-manager' @tooltips = new TooltipManager(keymapManager: @keymaps) + CommandRegistry = require './command-registry' + @commands = new CommandRegistry + reset: -> @config.reset() @@ -211,7 +214,6 @@ class Atom extends Model @loadTime = null ViewRegistry = require './view-registry' - CommandRegistry = require './command-registry' PackageManager = require './package-manager' Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' @@ -232,7 +234,7 @@ class Atom extends Model process.env.NODE_ENV ?= 'production' unless devMode @keymaps.subscribeToFileReadFailure() - @commands = new CommandRegistry + @views = new ViewRegistry @registerViewProviders() @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode}) From 5d919c89a106fafe4f0e3d629ef06554f07c6bcb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 15:21:52 -0600 Subject: [PATCH 014/316] Fix tooltip manager specs --- spec/tooltip-manager-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/tooltip-manager-spec.coffee b/spec/tooltip-manager-spec.coffee index ec30ef2e3..bf0462ebf 100644 --- a/spec/tooltip-manager-spec.coffee +++ b/spec/tooltip-manager-spec.coffee @@ -8,7 +8,7 @@ describe "TooltipManager", -> ctrlY = _.humanizeKeystroke("ctrl-y") beforeEach -> - manager = new TooltipManager + manager = new TooltipManager(keymapManager: atom.keymaps) element = document.createElement('div') element.classList.add('foo') jasmine.attachToDOM(element) From 33e7af611e0377933b2fccd97f8609d2dde5e6a3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 15:26:01 -0600 Subject: [PATCH 015/316] Build views in Atom environment constructor --- src/atom.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 3c7e49d91..6154a33ef 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -177,6 +177,9 @@ class Atom extends Model CommandRegistry = require './command-registry' @commands = new CommandRegistry + ViewRegistry = require './view-registry' + @views = new ViewRegistry + reset: -> @config.reset() @@ -213,7 +216,6 @@ class Atom extends Model @loadTime = null - ViewRegistry = require './view-registry' PackageManager = require './package-manager' Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' @@ -235,7 +237,6 @@ class Atom extends Model @keymaps.subscribeToFileReadFailure() - @views = new ViewRegistry @registerViewProviders() @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode}) @styles = new StyleManager From c4bbd2bbf273cadb321bff1ba1486ec5e7e53a05 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 15:30:06 -0600 Subject: [PATCH 016/316] Build StyleManager in Atom environment constructor --- spec/style-manager-spec.coffee | 2 +- src/atom.coffee | 12 +++++++----- src/package-manager.coffee | 12 ++++++------ src/style-manager.coffee | 6 +++--- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/spec/style-manager-spec.coffee b/spec/style-manager-spec.coffee index 7e601bcc1..d0a1cfe13 100644 --- a/spec/style-manager-spec.coffee +++ b/spec/style-manager-spec.coffee @@ -4,7 +4,7 @@ describe "StyleManager", -> [manager, addEvents, removeEvents, updateEvents] = [] beforeEach -> - manager = new StyleManager + manager = new StyleManager(configDirPath: atom.getConfigDirPath()) addEvents = [] removeEvents = [] updateEvents = [] diff --git a/src/atom.coffee b/src/atom.coffee index 6154a33ef..e7b35b3b2 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -152,7 +152,7 @@ class Atom extends Model # Call .loadOrCreate instead constructor: (@state) -> {@mode} = @state - {resourcePath} = @getLoadSettings() + {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @emitter = new Emitter @@ -180,6 +180,12 @@ class Atom extends Model ViewRegistry = require './view-registry' @views = new ViewRegistry + PackageManager = require './package-manager' + @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config}) + + StyleManager = require './style-manager' + @styles = new StyleManager({configDirPath}) + reset: -> @config.reset() @@ -216,11 +222,9 @@ class Atom extends Model @loadTime = null - PackageManager = require './package-manager' Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' ThemeManager = require './theme-manager' - StyleManager = require './style-manager' ContextMenuManager = require './context-menu-manager' MenuManager = require './menu-manager' {devMode, safeMode, resourcePath} = @getLoadSettings() @@ -238,8 +242,6 @@ class Atom extends Model @keymaps.subscribeToFileReadFailure() @registerViewProviders() - @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode}) - @styles = new StyleManager document.head.appendChild(new StylesElement) @themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode}) @contextMenu = new ContextMenuManager({resourcePath, devMode}) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 7e4a19470..f36a0c389 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -26,7 +26,7 @@ ThemePackage = require './theme-package' # settings and also by calling `enablePackage()/disablePackage()`. module.exports = class PackageManager - constructor: ({configDirPath, @devMode, safeMode, @resourcePath}) -> + constructor: ({configDirPath, @devMode, safeMode, @resourcePath, @config}) -> @emitter = new Emitter @activationHookEmitter = new Emitter @packageDirPaths = [] @@ -185,7 +185,7 @@ class PackageManager # # Returns a {Boolean}. isPackageDisabled: (name) -> - _.include(atom.config.get('core.disabledPackages') ? [], name) + _.include(@config.get('core.disabledPackages') ? [], name) ### Section: Accessing active packages @@ -300,7 +300,7 @@ class PackageManager @disabledPackagesSubscription = null observeDisabledPackages: -> - @disabledPackagesSubscription ?= atom.config.onDidChange 'core.disabledPackages', ({newValue, oldValue}) => + @disabledPackagesSubscription ?= @config.onDidChange 'core.disabledPackages', ({newValue, oldValue}) => packagesToEnable = _.difference(oldValue, newValue) packagesToDisable = _.difference(newValue, oldValue) @@ -313,7 +313,7 @@ class PackageManager @packagesWithKeymapsDisabledSubscription = null observePackagesWithKeymapsDisabled: -> - @packagesWithKeymapsDisabledSubscription ?= atom.config.onDidChange 'core.packagesWithKeymapsDisabled', ({newValue, oldValue}) => + @packagesWithKeymapsDisabledSubscription ?= @config.onDidChange 'core.packagesWithKeymapsDisabled', ({newValue, oldValue}) => keymapsToEnable = _.difference(oldValue, newValue) keymapsToDisable = _.difference(newValue, oldValue) @@ -392,7 +392,7 @@ class PackageManager activatePackages: (packages) -> promises = [] - atom.config.transact => + @config.transact => for pack in packages promise = @activatePackage(pack.name) promises.push(promise) unless pack.hasActivationCommands() @@ -423,7 +423,7 @@ class PackageManager # Deactivate all packages deactivatePackages: -> - atom.config.transact => + @config.transact => @deactivatePackage(pack.name) for pack in @getLoadedPackages() return @unobserveDisabledPackages() diff --git a/src/style-manager.coffee b/src/style-manager.coffee index cfe86b3fe..11dc4b97f 100644 --- a/src/style-manager.coffee +++ b/src/style-manager.coffee @@ -9,7 +9,7 @@ path = require 'path' # which clone and attach style elements in different contexts. module.exports = class StyleManager - constructor: -> + constructor: ({@configDirPath}) -> @emitter = new Emitter @styleElements = [] @styleElementsBySourcePath = {} @@ -162,8 +162,8 @@ class StyleManager # # Returns a {String}. getUserStyleSheetPath: -> - stylesheetPath = fs.resolve(path.join(atom.getConfigDirPath(), 'styles'), ['css', 'less']) + stylesheetPath = fs.resolve(path.join(@configDirPath, 'styles'), ['css', 'less']) if fs.isFileSync(stylesheetPath) stylesheetPath else - path.join(atom.getConfigDirPath(), 'styles.less') + path.join(@configDirPath, 'styles.less') From 943f6cf5132a347378373b3ddbf6c725ab49bbb4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 15:58:50 -0600 Subject: [PATCH 017/316] Build ThemeManager in Atom environment constructor --- spec/spec-helper.coffee | 2 ++ src/atom.coffee | 10 ++++++++-- src/theme-manager.coffee | 33 ++++++++++++++++++--------------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 0d538b7a3..fd02e6fac 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -93,6 +93,7 @@ beforeEach -> atom.packages.serviceHub = new ServiceHub atom.project = new Project(paths: [projectPath]) atom.workspace = new Workspace() + atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) atom.commands.restoreSnapshot(commandsToRestore) atom.styles.restoreSnapshot(styleElementsToRestore) @@ -165,6 +166,7 @@ afterEach -> atom.workspace?.destroy() atom.workspace = null + atom.themes.workspace = null delete atom.state.workspace atom.project?.destroy() diff --git a/src/atom.coffee b/src/atom.coffee index e7b35b3b2..ee0efda62 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -186,6 +186,12 @@ class Atom extends Model StyleManager = require './style-manager' @styles = new StyleManager({configDirPath}) + ThemeManager = require './theme-manager' + @themes = new ThemeManager({ + packageManager: @packages, configDirPath, resourcePath, safeMode, @config, + styleManager: @styles, notificationManager: @notifications, viewRegistry: @views + }) + reset: -> @config.reset() @@ -224,7 +230,6 @@ class Atom extends Model Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' - ThemeManager = require './theme-manager' ContextMenuManager = require './context-menu-manager' MenuManager = require './menu-manager' {devMode, safeMode, resourcePath} = @getLoadSettings() @@ -243,7 +248,6 @@ class Atom extends Model @registerViewProviders() document.head.appendChild(new StylesElement) - @themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode}) @contextMenu = new ContextMenuManager({resourcePath, devMode}) @menu = new MenuManager({resourcePath}) @clipboard = new Clipboard() @@ -632,6 +636,7 @@ class Atom extends Model @workspace?.destroy() @workspace = null + @themes.workspace = null @project?.destroy() @project = null @@ -734,6 +739,7 @@ class Atom extends Model startTime = Date.now() @workspace = Workspace.deserialize(@state.workspace) ? new Workspace + @themes.workspace = @workspace @deserializeTimings.workspace = Date.now() - startTime workspaceElement = @views.getView(@workspace) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 0d329cea7..ad5fe96d4 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -9,7 +9,10 @@ fs = require 'fs-plus' # An instance of this class is always available as the `atom.themes` global. module.exports = class ThemeManager - constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode}) -> + constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode, @config, @styleManager, @notificationManager, @viewRegistry}) -> + unless @packageManager + debugger + @emitter = new Emitter @styleSheetDisposablesBySourcePath = {} @lessCache = null @@ -66,21 +69,21 @@ class ThemeManager ### warnForNonExistentThemes: -> - themeNames = atom.config.get('core.themes') ? [] + themeNames = @config.get('core.themes') ? [] themeNames = [themeNames] unless _.isArray(themeNames) for themeName in themeNames - unless themeName and typeof themeName is 'string' and atom.packages.resolvePackagePath(themeName) + unless themeName and typeof themeName is 'string' and @packageManager.resolvePackagePath(themeName) console.warn("Enabled theme '#{themeName}' is not installed.") # Public: Get the enabled theme names from the config. # # Returns an array of theme names in the order that they should be activated. getEnabledThemeNames: -> - themeNames = atom.config.get('core.themes') ? [] + themeNames = @config.get('core.themes') ? [] themeNames = [themeNames] unless _.isArray(themeNames) - themeNames = themeNames.filter (themeName) -> + themeNames = themeNames.filter (themeName) => if themeName and typeof themeName is 'string' - return true if atom.packages.resolvePackagePath(themeName) + return true if @packageManager.resolvePackagePath(themeName) false # Use a built-in syntax and UI theme any time the configured themes are not @@ -139,7 +142,7 @@ class ThemeManager loadUserStylesheet: -> @unwatchUserStylesheet() - userStylesheetPath = atom.styles.getUserStyleSheetPath() + userStylesheetPath = @styleManager.getUserStyleSheetPath() return unless fs.isFileSync(userStylesheetPath) try @@ -158,14 +161,14 @@ class ThemeManager [this document][watches] for more info. [watches]:https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#typeerror-unable-to-watch-path """ - atom.notifications.addError(message, dismissable: true) + @notificationManager.addError(message, dismissable: true) try userStylesheetContents = @loadStylesheet(userStylesheetPath, true) catch return - @userStyleSheetDisposable = atom.styles.addStyleSheet(userStylesheetContents, sourcePath: userStylesheetPath, priority: 2) + @userStyleSheetDisposable = @styleManager.addStyleSheet(userStylesheetContents, sourcePath: userStylesheetPath, priority: 2) loadBaseStylesheets: -> @requireStylesheet('../static/bootstrap') @@ -221,22 +224,22 @@ class ThemeManager message = "Error loading Less stylesheet: `#{lessStylesheetPath}`" detail = error.message - atom.notifications.addError(message, {detail, dismissable: true}) + @notificationManager.addError(message, {detail, dismissable: true}) throw error removeStylesheet: (stylesheetPath) -> @styleSheetDisposablesBySourcePath[stylesheetPath]?.dispose() applyStylesheet: (path, text) -> - @styleSheetDisposablesBySourcePath[path] = atom.styles.addStyleSheet(text, sourcePath: path) + @styleSheetDisposablesBySourcePath[path] = @styleManager.addStyleSheet(text, sourcePath: path) stringToId: (string) -> string.replace(/\\/g, '/') activateThemes: -> new Promise (resolve) => - # atom.config.observe runs the callback once, then on subsequent changes. - atom.config.observe 'core.themes', => + # @config.observe runs the callback once, then on subsequent changes. + @config.observe 'core.themes', => @deactivateThemes() @warnForNonExistentThemes() @@ -268,13 +271,13 @@ class ThemeManager isInitialLoadComplete: -> @initialLoadComplete addActiveThemeClasses: -> - if workspaceElement = atom.views.getView(atom.workspace) + if workspaceElement = @viewRegistry.getView(@workspace) for pack in @getActiveThemes() workspaceElement.classList.add("theme-#{pack.name}") return removeActiveThemeClasses: -> - workspaceElement = atom.views.getView(atom.workspace) + workspaceElement = @viewRegistry.getView(@workspace) for pack in @getActiveThemes() workspaceElement.classList.remove("theme-#{pack.name}") return From 6de0da792b4706276f18dec91088612425c82303 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 16:44:49 -0600 Subject: [PATCH 018/316] Build ContextMenuManager in Atom environment constructor --- spec/context-menu-manager-spec.coffee | 2 +- src/atom.coffee | 5 +++-- src/context-menu-manager.coffee | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/context-menu-manager-spec.coffee b/spec/context-menu-manager-spec.coffee index 4cf33acc6..ddced8452 100644 --- a/spec/context-menu-manager-spec.coffee +++ b/spec/context-menu-manager-spec.coffee @@ -5,7 +5,7 @@ describe "ContextMenuManager", -> beforeEach -> {resourcePath} = atom.getLoadSettings() - contextMenu = new ContextMenuManager({resourcePath}) + contextMenu = new ContextMenuManager({resourcePath, keymapManager: atom.keymaps}) parent = document.createElement("div") child = document.createElement("div") diff --git a/src/atom.coffee b/src/atom.coffee index ee0efda62..2b6fcbc99 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -192,6 +192,9 @@ class Atom extends Model styleManager: @styles, notificationManager: @notifications, viewRegistry: @views }) + ContextMenuManager = require './context-menu-manager' + @contextMenu = new ContextMenuManager({resourcePath, devMode, keymapManager: @keymaps}) + reset: -> @config.reset() @@ -230,7 +233,6 @@ class Atom extends Model Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' - ContextMenuManager = require './context-menu-manager' MenuManager = require './menu-manager' {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @@ -248,7 +250,6 @@ class Atom extends Model @registerViewProviders() document.head.appendChild(new StylesElement) - @contextMenu = new ContextMenuManager({resourcePath, devMode}) @menu = new MenuManager({resourcePath}) @clipboard = new Clipboard() @grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry() diff --git a/src/context-menu-manager.coffee b/src/context-menu-manager.coffee index 0ca005d8a..869076beb 100644 --- a/src/context-menu-manager.coffee +++ b/src/context-menu-manager.coffee @@ -4,6 +4,7 @@ CSON = require 'season' fs = require 'fs-plus' {calculateSpecificity, validateSelector} = require 'clear-cut' {Disposable} = require 'event-kit' +remote = require 'remote' MenuHelpers = require './menu-helpers' platformContextMenu = require('../package.json')?._atomMenu?['context-menu'] @@ -40,11 +41,11 @@ platformContextMenu = require('../package.json')?._atomMenu?['context-menu'] # {::add} for more information. module.exports = class ContextMenuManager - constructor: ({@resourcePath, @devMode}) -> + constructor: ({@resourcePath, @devMode, @keymapManager}) -> @definitions = {'.overlayer': []} # TODO: Remove once color picker package stops touching private data @clear() - atom.keymaps.onDidLoadBundledKeymaps => @loadPlatformItems() + @keymapManager.onDidLoadBundledKeymaps => @loadPlatformItems() loadPlatformItems: -> if platformContextMenu? @@ -175,7 +176,7 @@ class ContextMenuManager menuTemplate = @templateForEvent(event) return unless menuTemplate?.length > 0 - atom.getCurrentWindow().emit('context-menu', menuTemplate) + remote.getCurrentWindow().emit('context-menu', menuTemplate) return clear: -> From 35c2ccd5087e5158e13a72f50b18201e1169baf3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 16:57:46 -0600 Subject: [PATCH 019/316] Build MenuManager in Atom environment constructor --- spec/menu-manager-spec.coffee | 6 +++++- src/atom.coffee | 5 +++-- src/menu-manager.coffee | 10 +++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/spec/menu-manager-spec.coffee b/spec/menu-manager-spec.coffee index c047bbcfc..5fcb2fee1 100644 --- a/spec/menu-manager-spec.coffee +++ b/spec/menu-manager-spec.coffee @@ -5,7 +5,11 @@ describe "MenuManager", -> menu = null beforeEach -> - menu = new MenuManager(resourcePath: atom.getLoadSettings().resourcePath) + menu = new MenuManager( + resourcePath: atom.getLoadSettings().resourcePath + keymapManager: atom.keymaps + packageManager: atom.packages + ) describe "::add(items)", -> it "can add new menus that can be removed with the returned disposable", -> diff --git a/src/atom.coffee b/src/atom.coffee index 2b6fcbc99..5b81e1e56 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -192,6 +192,9 @@ class Atom extends Model styleManager: @styles, notificationManager: @notifications, viewRegistry: @views }) + MenuManager = require './menu-manager' + @menu = new MenuManager({resourcePath, keymapManager: @keymaps, packageManager: @packages}) + ContextMenuManager = require './context-menu-manager' @contextMenu = new ContextMenuManager({resourcePath, devMode, keymapManager: @keymaps}) @@ -233,7 +236,6 @@ class Atom extends Model Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' - MenuManager = require './menu-manager' {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @@ -250,7 +252,6 @@ class Atom extends Model @registerViewProviders() document.head.appendChild(new StylesElement) - @menu = new MenuManager({resourcePath}) @clipboard = new Clipboard() @grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry() @disposables.add @packages.onDidActivateInitialPackages => @watchThemes() diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index b138f2da2..0de08cfa7 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -59,12 +59,12 @@ platformMenu = require('../package.json')?._atomMenu?.menu # See {::add} for more info about adding menu's directly. module.exports = class MenuManager - constructor: ({@resourcePath}) -> + constructor: ({@resourcePath, @keymapManager, @packageManager}) -> @pendingUpdateOperation = null @template = [] - atom.keymaps.onDidLoadBundledKeymaps => @loadPlatformItems() - atom.keymaps.onDidReloadKeymap => @update() - atom.packages.onDidActivateInitialPackages => @sortPackagesMenu() + @keymapManager.onDidLoadBundledKeymaps => @loadPlatformItems() + @keymapManager.onDidReloadKeymap => @update() + @packageManager.onDidActivateInitialPackages => @sortPackagesMenu() # Public: Adds the given items to the application menu. # @@ -143,7 +143,7 @@ class MenuManager includedBindings = [] unsetKeystrokes = new Set - for binding in atom.keymaps.getKeyBindings() when @includeSelector(binding.selector) + for binding in @keymapManager.getKeyBindings() when @includeSelector(binding.selector) includedBindings.push(binding) if binding.command is 'unset!' unsetKeystrokes.add(binding.keystrokes) From c1f5d6b8bf221629b3e2222ba9e66cbe391ec4d3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 18:51:56 -0600 Subject: [PATCH 020/316] Build Clipboard in Atom environment constructor --- src/atom.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 5b81e1e56..3a4f89893 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -198,6 +198,9 @@ class Atom extends Model ContextMenuManager = require './context-menu-manager' @contextMenu = new ContextMenuManager({resourcePath, devMode, keymapManager: @keymaps}) + Clipboard = require './clipboard' + @clipboard = new Clipboard() + reset: -> @config.reset() @@ -234,7 +237,6 @@ class Atom extends Model @loadTime = null - Clipboard = require './clipboard' GrammarRegistry = require './grammar-registry' {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @@ -252,7 +254,6 @@ class Atom extends Model @registerViewProviders() document.head.appendChild(new StylesElement) - @clipboard = new Clipboard() @grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry() @disposables.add @packages.onDidActivateInitialPackages => @watchThemes() From 27762866c0fafa9cc8d554e06755a0de6818c1af Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 19:05:35 -0600 Subject: [PATCH 021/316] Build GrammarRegistry in Atom environment constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As part of this, we no longer serialize/deserialize the grammar registry instance, but instead just restore the grammarOverridesByPath state. Ultimately I’d like to store these overrides on the editor instead. --- spec/atom-spec.coffee | 4 ++-- spec/grammars-spec.coffee | 11 +---------- spec/package-manager-spec.coffee | 2 +- src/atom.coffee | 11 ++++++++--- src/grammar-registry.coffee | 14 ++------------ 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 31265c9a6..85d9dd4b9 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -226,13 +226,13 @@ describe "the `atom` global", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> workspaceState = atom.workspace.serialize() - syntaxState = atom.grammars.serialize() + grammarsState = {grammarOverridesByPath: atom.grammars.grammarOverridesByPath} projectState = atom.project.serialize() atom.unloadEditorWindow() expect(atom.state.workspace).toEqual workspaceState - expect(atom.state.grammars).toEqual syntaxState + expect(atom.state.grammars).toEqual grammarsState expect(atom.state.project).toEqual projectState expect(atom.saveSync).toHaveBeenCalled() diff --git a/spec/grammars-spec.coffee b/spec/grammars-spec.coffee index 960ce7d52..82a29892a 100644 --- a/spec/grammars-spec.coffee +++ b/spec/grammars-spec.coffee @@ -24,18 +24,9 @@ describe "the `grammars` global", -> atom.packages.deactivatePackages() atom.packages.unloadPackages() - describe "serialization", -> - it "remembers grammar overrides by path", -> - filePath = '/foo/bar/file.js' - expect(atom.grammars.selectGrammar(filePath).name).not.toBe 'Ruby' - atom.grammars.setGrammarOverrideForPath(filePath, 'source.ruby') - grammars2 = atom.deserializers.deserialize(atom.grammars.serialize()) - grammars2.addGrammar(grammar) for grammar in atom.grammars.grammars when grammar isnt atom.grammars.nullGrammar - expect(grammars2.selectGrammar(filePath).name).toBe 'Ruby' - describe ".selectGrammar(filePath)", -> it "always returns a grammar", -> - registry = new GrammarRegistry() + registry = new GrammarRegistry(config: atom.config) expect(registry.selectGrammar().scopeName).toBe 'text.plain.null-grammar' it "selects the text.plain grammar over the null grammar", -> diff --git a/spec/package-manager-spec.coffee b/spec/package-manager-spec.coffee index d1afd6ade..3121ad5e9 100644 --- a/spec/package-manager-spec.coffee +++ b/spec/package-manager-spec.coffee @@ -771,7 +771,7 @@ describe "PackageManager", -> atom.packages.unloadPackages() GrammarRegistry = require '../src/grammar-registry' - atom.grammars = window.syntax = new GrammarRegistry() + atom.grammars = window.syntax = new GrammarRegistry(config: atom.config) jasmine.restoreDeprecationsSnapshot() it "activates all the packages, and none of the themes", -> diff --git a/src/atom.coffee b/src/atom.coffee index 3a4f89893..53a76d440 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -201,6 +201,9 @@ class Atom extends Model Clipboard = require './clipboard' @clipboard = new Clipboard() + GrammarRegistry = require './grammar-registry' + @grammars = new GrammarRegistry({@config}) + reset: -> @config.reset() @@ -237,7 +240,6 @@ class Atom extends Model @loadTime = null - GrammarRegistry = require './grammar-registry' {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @@ -254,7 +256,10 @@ class Atom extends Model @registerViewProviders() document.head.appendChild(new StylesElement) - @grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry() + + if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath + @grammars.grammarOverridesByPath = grammarOverridesByPath + @disposables.add @packages.onDidActivateInitialPackages => @watchThemes() Project = require './project' @@ -626,7 +631,7 @@ class Atom extends Model return if not @project @storeWindowBackground() - @state.grammars = @grammars.serialize() + @state.grammars = {grammarOverridesByPath: @grammars.grammarOverridesByPath} @state.project = @project.serialize() @state.workspace = @workspace.serialize() @packages.deactivatePackages() diff --git a/src/grammar-registry.coffee b/src/grammar-registry.coffee index 109e719fc..65d6b1731 100644 --- a/src/grammar-registry.coffee +++ b/src/grammar-registry.coffee @@ -14,19 +14,9 @@ PathSplitRegex = new RegExp("[/.]") # language-specific comment regexes. See {::getProperty} for more details. module.exports = class GrammarRegistry extends FirstMate.GrammarRegistry - @deserialize: ({grammarOverridesByPath}) -> - grammarRegistry = new GrammarRegistry() - grammarRegistry.grammarOverridesByPath = grammarOverridesByPath - grammarRegistry - - atom.deserializers.add(this) - - constructor: -> + constructor: ({@config}={}) -> super(maxTokensPerLine: 100) - serialize: -> - {deserializer: @constructor.name, @grammarOverridesByPath} - createToken: (value, scopes) -> new Token({value, scopes}) # Extended: Select a grammar for the given file path and file contents. @@ -70,7 +60,7 @@ class GrammarRegistry extends FirstMate.GrammarRegistry pathScore = -1 fileTypes = grammar.fileTypes - if customFileTypes = atom.config.get('core.customFileTypes')?[grammar.scopeName] + if customFileTypes = @config.get('core.customFileTypes')?[grammar.scopeName] fileTypes = fileTypes.concat(customFileTypes) for fileType, i in fileTypes From e0d426b817d26b78b5e32175baccec8dc385dcb8 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 28 Sep 2015 21:26:34 -0600 Subject: [PATCH 022/316] Register deserializers, view providers, and commands in Atom constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, these registrations were scattered all over the codebase and required that `global.atom` be defined, which creating weird ordering issues. Registering them all from the global makes the relationships clearer and means we don’t have to assign a global to set up a fully- functional environment. --- src/atom.coffee | 72 ++++----- src/pane-axis.coffee | 2 - src/pane-container.coffee | 2 - src/pane-element.coffee | 26 ---- src/pane.coffee | 2 - src/project.coffee | 2 - src/register-default-commands.coffee | 210 +++++++++++++++++++++++++++ src/text-editor-element.coffee | 137 ----------------- src/text-editor.coffee | 2 - src/workspace-element.coffee | 49 ------- src/workspace.coffee | 2 - 11 files changed, 249 insertions(+), 257 deletions(-) create mode 100644 src/register-default-commands.coffee diff --git a/src/atom.coffee b/src/atom.coffee index 53a76d440..8f01d2122 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -204,6 +204,45 @@ class Atom extends Model GrammarRegistry = require './grammar-registry' @grammars = new GrammarRegistry({@config}) + @registerDeserializersAndViewProviders() + + registerDefaultCommands = require './register-default-commands' + registerDefaultCommands(@commands) + + registerDeserializersAndViewProviders: -> + Workspace = require './workspace' + PaneContainer = require './pane-container' + PaneAxis = require './pane-axis' + Pane = require './pane' + Project = require './project' + TextEditor = require './text-editor' + TextBuffer = require 'text-buffer' + + @deserializers.add(Workspace) + @deserializers.add(PaneContainer) + @deserializers.add(PaneAxis) + @deserializers.add(Pane) + @deserializers.add(Project) + @deserializers.add(TextEditor) + @deserializers.add(TextBuffer) + + Gutter = require './gutter' + PaneElement = require './pane-element' + PaneContainerElement = require './pane-container-element' + PaneAxisElement = require './pane-axis-element' + TextEditorElement = require './text-editor-element' + {createGutterView} = require './gutter-component-helpers' + + @views.addViewProvider PaneContainer, (model) -> + new PaneContainerElement().initialize(model) + @views.addViewProvider PaneAxis, (model) -> + new PaneAxisElement().initialize(model) + @views.addViewProvider Pane, (model) -> + new PaneElement().initialize(model) + @views.addViewProvider TextEditor, (model) -> + new TextEditorElement().initialize(model) + @views.addViewProvider(Gutter, createGutterView) + reset: -> @config.reset() @@ -254,47 +293,14 @@ class Atom extends Model @keymaps.subscribeToFileReadFailure() - @registerViewProviders() document.head.appendChild(new StylesElement) if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath @grammars.grammarOverridesByPath = grammarOverridesByPath @disposables.add @packages.onDidActivateInitialPackages => @watchThemes() - - Project = require './project' - TextBuffer = require 'text-buffer' - @deserializers.add(TextBuffer) - TokenizedBuffer = require './tokenized-buffer' - DisplayBuffer = require './display-buffer' - TextEditor = require './text-editor' - @windowEventHandler = new WindowEventHandler - # Register the core views as early as possible in case they are needed for - # package deserialization. - registerViewProviders: -> - Gutter = require './gutter' - Pane = require './pane' - PaneElement = require './pane-element' - PaneContainer = require './pane-container' - PaneContainerElement = require './pane-container-element' - PaneAxis = require './pane-axis' - PaneAxisElement = require './pane-axis-element' - TextEditor = require './text-editor' - TextEditorElement = require './text-editor-element' - {createGutterView} = require './gutter-component-helpers' - - atom.views.addViewProvider PaneContainer, (model) -> - new PaneContainerElement().initialize(model) - atom.views.addViewProvider PaneAxis, (model) -> - new PaneAxisElement().initialize(model) - atom.views.addViewProvider Pane, (model) -> - new PaneElement().initialize(model) - atom.views.addViewProvider TextEditor, (model) -> - new TextEditorElement().initialize(model) - atom.views.addViewProvider(Gutter, createGutterView) - ### Section: Event Subscription ### diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 57d07d8a9..3bb4e285e 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -4,8 +4,6 @@ Model = require './model' module.exports = class PaneAxis extends Model - atom.deserializers.add(this) - parent: null container: null orientation: null diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 786c4b84f..18f6166c0 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -7,8 +7,6 @@ ItemRegistry = require './item-registry' module.exports = class PaneContainer extends Model - atom.deserializers.add(this) - @version: 1 root: null diff --git a/src/pane-element.coffee b/src/pane-element.coffee index c6ded79c4..41f110ddb 100644 --- a/src/pane-element.coffee +++ b/src/pane-element.coffee @@ -123,30 +123,4 @@ class PaneElement extends HTMLElement hasFocus: -> this is document.activeElement or @contains(document.activeElement) -atom.commands.add 'atom-workspace', - 'pane:show-next-item': -> @getModel().getActivePane().activateNextItem() - 'pane:show-previous-item': -> @getModel().getActivePane().activatePreviousItem() - 'pane:show-item-1': -> @getModel().getActivePane().activateItemAtIndex(0) - 'pane:show-item-2': -> @getModel().getActivePane().activateItemAtIndex(1) - 'pane:show-item-3': -> @getModel().getActivePane().activateItemAtIndex(2) - 'pane:show-item-4': -> @getModel().getActivePane().activateItemAtIndex(3) - 'pane:show-item-5': -> @getModel().getActivePane().activateItemAtIndex(4) - 'pane:show-item-6': -> @getModel().getActivePane().activateItemAtIndex(5) - 'pane:show-item-7': -> @getModel().getActivePane().activateItemAtIndex(6) - 'pane:show-item-8': -> @getModel().getActivePane().activateItemAtIndex(7) - 'pane:show-item-9': -> @getModel().getActivePane().activateItemAtIndex(8) - 'pane:move-item-right': -> @getModel().getActivePane().moveItemRight() - 'pane:move-item-left': -> @getModel().getActivePane().moveItemLeft() - -atom.commands.add 'atom-pane', - 'pane:save-items': -> @getModel().saveItems() - 'pane:split-left': -> @getModel().splitLeft(copyActiveItem: true) - 'pane:split-right': -> @getModel().splitRight(copyActiveItem: true) - 'pane:split-up': -> @getModel().splitUp(copyActiveItem: true) - 'pane:split-down': -> @getModel().splitDown(copyActiveItem: true) - 'pane:close': -> @getModel().close() - 'pane:close-other-items': -> @getModel().destroyInactiveItems() - 'pane:increase-size': -> @getModel().increaseSize() - 'pane:decrease-size': -> @getModel().decreaseSize() - module.exports = PaneElement = document.registerElement 'atom-pane', prototype: PaneElement.prototype diff --git a/src/pane.coffee b/src/pane.coffee index a146b66fc..45577dab7 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -10,8 +10,6 @@ TextEditor = require './text-editor' # the default configuration, tabs are also displayed for each item. module.exports = class Pane extends Model - atom.deserializers.add(this) - container: undefined activeItem: undefined focused: false diff --git a/src/project.coffee b/src/project.coffee index b3f05a942..faead038e 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -17,8 +17,6 @@ GitRepositoryProvider = require './git-repository-provider' # An instance of this class is always available as the `atom.project` global. module.exports = class Project extends Model - atom.deserializers.add(this) - ### Section: Construction and Destruction ### diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee new file mode 100644 index 000000000..c43fd5bb7 --- /dev/null +++ b/src/register-default-commands.coffee @@ -0,0 +1,210 @@ +module.exports = (commandRegistry) -> + commandRegistry.add 'atom-workspace', + 'pane:show-next-item': -> @getModel().getActivePane().activateNextItem() + 'pane:show-previous-item': -> @getModel().getActivePane().activatePreviousItem() + 'pane:show-item-1': -> @getModel().getActivePane().activateItemAtIndex(0) + 'pane:show-item-2': -> @getModel().getActivePane().activateItemAtIndex(1) + 'pane:show-item-3': -> @getModel().getActivePane().activateItemAtIndex(2) + 'pane:show-item-4': -> @getModel().getActivePane().activateItemAtIndex(3) + 'pane:show-item-5': -> @getModel().getActivePane().activateItemAtIndex(4) + 'pane:show-item-6': -> @getModel().getActivePane().activateItemAtIndex(5) + 'pane:show-item-7': -> @getModel().getActivePane().activateItemAtIndex(6) + 'pane:show-item-8': -> @getModel().getActivePane().activateItemAtIndex(7) + 'pane:show-item-9': -> @getModel().getActivePane().activateItemAtIndex(8) + 'pane:move-item-right': -> @getModel().getActivePane().moveItemRight() + 'pane:move-item-left': -> @getModel().getActivePane().moveItemLeft() + 'window:increase-font-size': -> @getModel().increaseFontSize() + 'window:decrease-font-size': -> @getModel().decreaseFontSize() + 'window:reset-font-size': -> @getModel().resetFontSize() + 'application:about': -> ipc.send('command', 'application:about') + 'application:run-all-specs': -> ipc.send('command', 'application:run-all-specs') + 'application:show-preferences': -> ipc.send('command', 'application:show-settings') + 'application:show-settings': -> ipc.send('command', 'application:show-settings') + 'application:quit': -> ipc.send('command', 'application:quit') + 'application:hide': -> ipc.send('command', 'application:hide') + 'application:hide-other-applications': -> ipc.send('command', 'application:hide-other-applications') + 'application:install-update': -> ipc.send('command', 'application:install-update') + 'application:unhide-all-applications': -> ipc.send('command', 'application:unhide-all-applications') + 'application:new-window': -> ipc.send('command', 'application:new-window') + 'application:new-file': -> ipc.send('command', 'application:new-file') + 'application:open': -> ipc.send('command', 'application:open') + 'application:open-file': -> ipc.send('command', 'application:open-file') + 'application:open-folder': -> ipc.send('command', 'application:open-folder') + 'application:open-dev': -> ipc.send('command', 'application:open-dev') + 'application:open-safe': -> ipc.send('command', 'application:open-safe') + 'application:add-project-folder': -> atom.addProjectFolder() + 'application:minimize': -> ipc.send('command', 'application:minimize') + 'application:zoom': -> ipc.send('command', 'application:zoom') + 'application:bring-all-windows-to-front': -> ipc.send('command', 'application:bring-all-windows-to-front') + 'application:open-your-config': -> ipc.send('command', 'application:open-your-config') + 'application:open-your-init-script': -> ipc.send('command', 'application:open-your-init-script') + 'application:open-your-keymap': -> ipc.send('command', 'application:open-your-keymap') + 'application:open-your-snippets': -> ipc.send('command', 'application:open-your-snippets') + 'application:open-your-stylesheet': -> ipc.send('command', 'application:open-your-stylesheet') + 'application:open-license': -> @getModel().openLicense() + 'window:run-package-specs': -> @runPackageSpecs() + 'window:focus-next-pane': -> @getModel().activateNextPane() + 'window:focus-previous-pane': -> @getModel().activatePreviousPane() + 'window:focus-pane-above': -> @focusPaneViewAbove() + 'window:focus-pane-below': -> @focusPaneViewBelow() + 'window:focus-pane-on-left': -> @focusPaneViewOnLeft() + 'window:focus-pane-on-right': -> @focusPaneViewOnRight() + 'window:save-all': -> @getModel().saveAll() + 'window:toggle-invisibles': -> atom.config.set("editor.showInvisibles", not atom.config.get("editor.showInvisibles")) + 'window:log-deprecation-warnings': -> Grim.logDeprecations() + 'window:toggle-auto-indent': -> atom.config.set("editor.autoIndent", not atom.config.get("editor.autoIndent")) + 'pane:reopen-closed-item': -> @getModel().reopenItem() + 'core:close': -> @getModel().destroyActivePaneItemOrEmptyPane() + 'core:save': -> @getModel().saveActivePaneItem() + 'core:save-as': -> @getModel().saveActivePaneItemAs() + + if process.platform is 'darwin' + commandRegistry.add 'atom-workspace', 'window:install-shell-commands', -> @getModel().installShellCommands() + + commandRegistry.add 'atom-pane', + 'pane:save-items': -> @getModel().saveItems() + 'pane:split-left': -> @getModel().splitLeft(copyActiveItem: true) + 'pane:split-right': -> @getModel().splitRight(copyActiveItem: true) + 'pane:split-up': -> @getModel().splitUp(copyActiveItem: true) + 'pane:split-down': -> @getModel().splitDown(copyActiveItem: true) + 'pane:close': -> @getModel().close() + 'pane:close-other-items': -> @getModel().destroyInactiveItems() + 'pane:increase-size': -> @getModel().increaseSize() + 'pane:decrease-size': -> @getModel().decreaseSize() + + commandRegistry.add 'atom-text-editor', stopEventPropagation( + 'core:undo': -> @undo() + 'core:redo': -> @redo() + 'core:move-left': -> @moveLeft() + 'core:move-right': -> @moveRight() + 'core:select-left': -> @selectLeft() + 'core:select-right': -> @selectRight() + 'core:select-up': -> @selectUp() + 'core:select-down': -> @selectDown() + 'core:select-all': -> @selectAll() + 'editor:select-word': -> @selectWordsContainingCursors() + 'editor:consolidate-selections': (event) -> event.abortKeyBinding() unless @consolidateSelections() + 'editor:move-to-beginning-of-next-paragraph': -> @moveToBeginningOfNextParagraph() + 'editor:move-to-beginning-of-previous-paragraph': -> @moveToBeginningOfPreviousParagraph() + 'editor:move-to-beginning-of-screen-line': -> @moveToBeginningOfScreenLine() + 'editor:move-to-beginning-of-line': -> @moveToBeginningOfLine() + 'editor:move-to-end-of-screen-line': -> @moveToEndOfScreenLine() + 'editor:move-to-end-of-line': -> @moveToEndOfLine() + 'editor:move-to-first-character-of-line': -> @moveToFirstCharacterOfLine() + 'editor:move-to-beginning-of-word': -> @moveToBeginningOfWord() + 'editor:move-to-end-of-word': -> @moveToEndOfWord() + 'editor:move-to-beginning-of-next-word': -> @moveToBeginningOfNextWord() + 'editor:move-to-previous-word-boundary': -> @moveToPreviousWordBoundary() + 'editor:move-to-next-word-boundary': -> @moveToNextWordBoundary() + 'editor:move-to-previous-subword-boundary': -> @moveToPreviousSubwordBoundary() + 'editor:move-to-next-subword-boundary': -> @moveToNextSubwordBoundary() + 'editor:select-to-beginning-of-next-paragraph': -> @selectToBeginningOfNextParagraph() + 'editor:select-to-beginning-of-previous-paragraph': -> @selectToBeginningOfPreviousParagraph() + 'editor:select-to-end-of-line': -> @selectToEndOfLine() + 'editor:select-to-beginning-of-line': -> @selectToBeginningOfLine() + 'editor:select-to-end-of-word': -> @selectToEndOfWord() + 'editor:select-to-beginning-of-word': -> @selectToBeginningOfWord() + 'editor:select-to-beginning-of-next-word': -> @selectToBeginningOfNextWord() + 'editor:select-to-next-word-boundary': -> @selectToNextWordBoundary() + 'editor:select-to-previous-word-boundary': -> @selectToPreviousWordBoundary() + 'editor:select-to-next-subword-boundary': -> @selectToNextSubwordBoundary() + 'editor:select-to-previous-subword-boundary': -> @selectToPreviousSubwordBoundary() + 'editor:select-to-first-character-of-line': -> @selectToFirstCharacterOfLine() + 'editor:select-line': -> @selectLinesContainingCursors() + ) + + commandRegistry.add 'atom-text-editor', stopEventPropagationAndGroupUndo( + 'core:backspace': -> @backspace() + 'core:delete': -> @delete() + 'core:cut': -> @cutSelectedText() + 'core:copy': -> @copySelectedText() + 'core:paste': -> @pasteText() + 'editor:delete-to-previous-word-boundary': -> @deleteToPreviousWordBoundary() + 'editor:delete-to-next-word-boundary': -> @deleteToNextWordBoundary() + 'editor:delete-to-beginning-of-word': -> @deleteToBeginningOfWord() + 'editor:delete-to-beginning-of-line': -> @deleteToBeginningOfLine() + 'editor:delete-to-end-of-line': -> @deleteToEndOfLine() + 'editor:delete-to-end-of-word': -> @deleteToEndOfWord() + 'editor:delete-to-beginning-of-subword': -> @deleteToBeginningOfSubword() + 'editor:delete-to-end-of-subword': -> @deleteToEndOfSubword() + 'editor:delete-line': -> @deleteLine() + 'editor:cut-to-end-of-line': -> @cutToEndOfLine() + 'editor:cut-to-end-of-buffer-line': -> @cutToEndOfBufferLine() + 'editor:transpose': -> @transpose() + 'editor:upper-case': -> @upperCase() + 'editor:lower-case': -> @lowerCase() + 'editor:copy-selection': -> @copyOnlySelectedText() + ) + + commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagation( + 'core:move-up': -> @moveUp() + 'core:move-down': -> @moveDown() + 'core:move-to-top': -> @moveToTop() + 'core:move-to-bottom': -> @moveToBottom() + 'core:page-up': -> @pageUp() + 'core:page-down': -> @pageDown() + 'core:select-to-top': -> @selectToTop() + 'core:select-to-bottom': -> @selectToBottom() + 'core:select-page-up': -> @selectPageUp() + 'core:select-page-down': -> @selectPageDown() + 'editor:add-selection-below': -> @addSelectionBelow() + 'editor:add-selection-above': -> @addSelectionAbove() + 'editor:split-selections-into-lines': -> @splitSelectionsIntoLines() + 'editor:toggle-soft-tabs': -> @toggleSoftTabs() + 'editor:toggle-soft-wrap': -> @toggleSoftWrapped() + 'editor:fold-all': -> @foldAll() + 'editor:unfold-all': -> @unfoldAll() + 'editor:fold-current-row': -> @foldCurrentRow() + 'editor:unfold-current-row': -> @unfoldCurrentRow() + 'editor:fold-selection': -> @foldSelectedLines() + 'editor:fold-at-indent-level-1': -> @foldAllAtIndentLevel(0) + 'editor:fold-at-indent-level-2': -> @foldAllAtIndentLevel(1) + 'editor:fold-at-indent-level-3': -> @foldAllAtIndentLevel(2) + 'editor:fold-at-indent-level-4': -> @foldAllAtIndentLevel(3) + 'editor:fold-at-indent-level-5': -> @foldAllAtIndentLevel(4) + 'editor:fold-at-indent-level-6': -> @foldAllAtIndentLevel(5) + 'editor:fold-at-indent-level-7': -> @foldAllAtIndentLevel(6) + 'editor:fold-at-indent-level-8': -> @foldAllAtIndentLevel(7) + 'editor:fold-at-indent-level-9': -> @foldAllAtIndentLevel(8) + 'editor:log-cursor-scope': -> @logCursorScope() + 'editor:copy-path': -> @copyPathToClipboard() + 'editor:toggle-indent-guide': -> atom.config.set('editor.showIndentGuide', not atom.config.get('editor.showIndentGuide')) + 'editor:toggle-line-numbers': -> atom.config.set('editor.showLineNumbers', not atom.config.get('editor.showLineNumbers')) + 'editor:scroll-to-cursor': -> @scrollToCursorPosition() + ) + + commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo( + 'editor:indent': -> @indent() + 'editor:auto-indent': -> @autoIndentSelectedRows() + 'editor:indent-selected-rows': -> @indentSelectedRows() + 'editor:outdent-selected-rows': -> @outdentSelectedRows() + 'editor:newline': -> @insertNewline() + 'editor:newline-below': -> @insertNewlineBelow() + 'editor:newline-above': -> @insertNewlineAbove() + 'editor:toggle-line-comments': -> @toggleLineCommentsInSelection() + 'editor:checkout-head-revision': -> @checkoutHeadRevision() + 'editor:move-line-up': -> @moveLineUp() + 'editor:move-line-down': -> @moveLineDown() + 'editor:duplicate-lines': -> @duplicateLines() + 'editor:join-lines': -> @joinLines() + ) + +stopEventPropagation = (commandListeners) -> + newCommandListeners = {} + for commandName, commandListener of commandListeners + do (commandListener) -> + newCommandListeners[commandName] = (event) -> + event.stopPropagation() + commandListener.call(@getModel(), event) + newCommandListeners + +stopEventPropagationAndGroupUndo = (commandListeners) -> + newCommandListeners = {} + for commandName, commandListener of commandListeners + do (commandListener) -> + newCommandListeners[commandName] = (event) -> + event.stopPropagation() + model = @getModel() + model.transact atom.config.get('editor.undoGroupingInterval'), -> + commandListener.call(model, event) + newCommandListeners diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 405cf30e4..5f87bb6ff 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -313,141 +313,4 @@ class TextEditorElement extends HTMLElement getHeight: -> @offsetHeight -stopEventPropagation = (commandListeners) -> - newCommandListeners = {} - for commandName, commandListener of commandListeners - do (commandListener) -> - newCommandListeners[commandName] = (event) -> - event.stopPropagation() - commandListener.call(@getModel(), event) - newCommandListeners - -stopEventPropagationAndGroupUndo = (commandListeners) -> - newCommandListeners = {} - for commandName, commandListener of commandListeners - do (commandListener) -> - newCommandListeners[commandName] = (event) -> - event.stopPropagation() - model = @getModel() - model.transact atom.config.get('editor.undoGroupingInterval'), -> - commandListener.call(model, event) - newCommandListeners - -atom.commands.add 'atom-text-editor', stopEventPropagation( - 'core:undo': -> @undo() - 'core:redo': -> @redo() - 'core:move-left': -> @moveLeft() - 'core:move-right': -> @moveRight() - 'core:select-left': -> @selectLeft() - 'core:select-right': -> @selectRight() - 'core:select-up': -> @selectUp() - 'core:select-down': -> @selectDown() - 'core:select-all': -> @selectAll() - 'editor:select-word': -> @selectWordsContainingCursors() - 'editor:consolidate-selections': (event) -> event.abortKeyBinding() unless @consolidateSelections() - 'editor:move-to-beginning-of-next-paragraph': -> @moveToBeginningOfNextParagraph() - 'editor:move-to-beginning-of-previous-paragraph': -> @moveToBeginningOfPreviousParagraph() - 'editor:move-to-beginning-of-screen-line': -> @moveToBeginningOfScreenLine() - 'editor:move-to-beginning-of-line': -> @moveToBeginningOfLine() - 'editor:move-to-end-of-screen-line': -> @moveToEndOfScreenLine() - 'editor:move-to-end-of-line': -> @moveToEndOfLine() - 'editor:move-to-first-character-of-line': -> @moveToFirstCharacterOfLine() - 'editor:move-to-beginning-of-word': -> @moveToBeginningOfWord() - 'editor:move-to-end-of-word': -> @moveToEndOfWord() - 'editor:move-to-beginning-of-next-word': -> @moveToBeginningOfNextWord() - 'editor:move-to-previous-word-boundary': -> @moveToPreviousWordBoundary() - 'editor:move-to-next-word-boundary': -> @moveToNextWordBoundary() - 'editor:move-to-previous-subword-boundary': -> @moveToPreviousSubwordBoundary() - 'editor:move-to-next-subword-boundary': -> @moveToNextSubwordBoundary() - 'editor:select-to-beginning-of-next-paragraph': -> @selectToBeginningOfNextParagraph() - 'editor:select-to-beginning-of-previous-paragraph': -> @selectToBeginningOfPreviousParagraph() - 'editor:select-to-end-of-line': -> @selectToEndOfLine() - 'editor:select-to-beginning-of-line': -> @selectToBeginningOfLine() - 'editor:select-to-end-of-word': -> @selectToEndOfWord() - 'editor:select-to-beginning-of-word': -> @selectToBeginningOfWord() - 'editor:select-to-beginning-of-next-word': -> @selectToBeginningOfNextWord() - 'editor:select-to-next-word-boundary': -> @selectToNextWordBoundary() - 'editor:select-to-previous-word-boundary': -> @selectToPreviousWordBoundary() - 'editor:select-to-next-subword-boundary': -> @selectToNextSubwordBoundary() - 'editor:select-to-previous-subword-boundary': -> @selectToPreviousSubwordBoundary() - 'editor:select-to-first-character-of-line': -> @selectToFirstCharacterOfLine() - 'editor:select-line': -> @selectLinesContainingCursors() -) - -atom.commands.add 'atom-text-editor', stopEventPropagationAndGroupUndo( - 'core:backspace': -> @backspace() - 'core:delete': -> @delete() - 'core:cut': -> @cutSelectedText() - 'core:copy': -> @copySelectedText() - 'core:paste': -> @pasteText() - 'editor:delete-to-previous-word-boundary': -> @deleteToPreviousWordBoundary() - 'editor:delete-to-next-word-boundary': -> @deleteToNextWordBoundary() - 'editor:delete-to-beginning-of-word': -> @deleteToBeginningOfWord() - 'editor:delete-to-beginning-of-line': -> @deleteToBeginningOfLine() - 'editor:delete-to-end-of-line': -> @deleteToEndOfLine() - 'editor:delete-to-end-of-word': -> @deleteToEndOfWord() - 'editor:delete-to-beginning-of-subword': -> @deleteToBeginningOfSubword() - 'editor:delete-to-end-of-subword': -> @deleteToEndOfSubword() - 'editor:delete-line': -> @deleteLine() - 'editor:cut-to-end-of-line': -> @cutToEndOfLine() - 'editor:cut-to-end-of-buffer-line': -> @cutToEndOfBufferLine() - 'editor:transpose': -> @transpose() - 'editor:upper-case': -> @upperCase() - 'editor:lower-case': -> @lowerCase() - 'editor:copy-selection': -> @copyOnlySelectedText() -) - -atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagation( - 'core:move-up': -> @moveUp() - 'core:move-down': -> @moveDown() - 'core:move-to-top': -> @moveToTop() - 'core:move-to-bottom': -> @moveToBottom() - 'core:page-up': -> @pageUp() - 'core:page-down': -> @pageDown() - 'core:select-to-top': -> @selectToTop() - 'core:select-to-bottom': -> @selectToBottom() - 'core:select-page-up': -> @selectPageUp() - 'core:select-page-down': -> @selectPageDown() - 'editor:add-selection-below': -> @addSelectionBelow() - 'editor:add-selection-above': -> @addSelectionAbove() - 'editor:split-selections-into-lines': -> @splitSelectionsIntoLines() - 'editor:toggle-soft-tabs': -> @toggleSoftTabs() - 'editor:toggle-soft-wrap': -> @toggleSoftWrapped() - 'editor:fold-all': -> @foldAll() - 'editor:unfold-all': -> @unfoldAll() - 'editor:fold-current-row': -> @foldCurrentRow() - 'editor:unfold-current-row': -> @unfoldCurrentRow() - 'editor:fold-selection': -> @foldSelectedLines() - 'editor:fold-at-indent-level-1': -> @foldAllAtIndentLevel(0) - 'editor:fold-at-indent-level-2': -> @foldAllAtIndentLevel(1) - 'editor:fold-at-indent-level-3': -> @foldAllAtIndentLevel(2) - 'editor:fold-at-indent-level-4': -> @foldAllAtIndentLevel(3) - 'editor:fold-at-indent-level-5': -> @foldAllAtIndentLevel(4) - 'editor:fold-at-indent-level-6': -> @foldAllAtIndentLevel(5) - 'editor:fold-at-indent-level-7': -> @foldAllAtIndentLevel(6) - 'editor:fold-at-indent-level-8': -> @foldAllAtIndentLevel(7) - 'editor:fold-at-indent-level-9': -> @foldAllAtIndentLevel(8) - 'editor:log-cursor-scope': -> @logCursorScope() - 'editor:copy-path': -> @copyPathToClipboard() - 'editor:toggle-indent-guide': -> atom.config.set('editor.showIndentGuide', not atom.config.get('editor.showIndentGuide')) - 'editor:toggle-line-numbers': -> atom.config.set('editor.showLineNumbers', not atom.config.get('editor.showLineNumbers')) - 'editor:scroll-to-cursor': -> @scrollToCursorPosition() -) - -atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo( - 'editor:indent': -> @indent() - 'editor:auto-indent': -> @autoIndentSelectedRows() - 'editor:indent-selected-rows': -> @indentSelectedRows() - 'editor:outdent-selected-rows': -> @outdentSelectedRows() - 'editor:newline': -> @insertNewline() - 'editor:newline-below': -> @insertNewlineBelow() - 'editor:newline-above': -> @insertNewlineAbove() - 'editor:toggle-line-comments': -> @toggleLineCommentsInSelection() - 'editor:checkout-head-revision': -> @checkoutHeadRevision() - 'editor:move-line-up': -> @moveLineUp() - 'editor:move-line-down': -> @moveLineDown() - 'editor:duplicate-lines': -> @duplicateLines() - 'editor:join-lines': -> @joinLines() -) - module.exports = TextEditorElement = document.registerElement 'atom-text-editor', prototype: TextEditorElement.prototype diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 1e9b6d993..e6719565c 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -54,8 +54,6 @@ GutterContainer = require './gutter-container' # soft wraps and folds to ensure your code interacts with them correctly. module.exports = class TextEditor extends Model - atom.deserializers.add(this) - callDisplayBufferCreatedHook: false registerEditor: false buffer: null diff --git a/src/workspace-element.coffee b/src/workspace-element.coffee index 378969481..c8ad1fe0d 100644 --- a/src/workspace-element.coffee +++ b/src/workspace-element.coffee @@ -102,53 +102,4 @@ class WorkspaceElement extends HTMLElement [projectPath] = atom.project.getPaths() ipc.send('run-package-specs', path.join(projectPath, 'spec')) if projectPath -atom.commands.add 'atom-workspace', - 'window:increase-font-size': -> @getModel().increaseFontSize() - 'window:decrease-font-size': -> @getModel().decreaseFontSize() - 'window:reset-font-size': -> @getModel().resetFontSize() - 'application:about': -> ipc.send('command', 'application:about') - 'application:run-all-specs': -> ipc.send('command', 'application:run-all-specs') - 'application:show-preferences': -> ipc.send('command', 'application:show-settings') - 'application:show-settings': -> ipc.send('command', 'application:show-settings') - 'application:quit': -> ipc.send('command', 'application:quit') - 'application:hide': -> ipc.send('command', 'application:hide') - 'application:hide-other-applications': -> ipc.send('command', 'application:hide-other-applications') - 'application:install-update': -> ipc.send('command', 'application:install-update') - 'application:unhide-all-applications': -> ipc.send('command', 'application:unhide-all-applications') - 'application:new-window': -> ipc.send('command', 'application:new-window') - 'application:new-file': -> ipc.send('command', 'application:new-file') - 'application:open': -> ipc.send('command', 'application:open') - 'application:open-file': -> ipc.send('command', 'application:open-file') - 'application:open-folder': -> ipc.send('command', 'application:open-folder') - 'application:open-dev': -> ipc.send('command', 'application:open-dev') - 'application:open-safe': -> ipc.send('command', 'application:open-safe') - 'application:add-project-folder': -> atom.addProjectFolder() - 'application:minimize': -> ipc.send('command', 'application:minimize') - 'application:zoom': -> ipc.send('command', 'application:zoom') - 'application:bring-all-windows-to-front': -> ipc.send('command', 'application:bring-all-windows-to-front') - 'application:open-your-config': -> ipc.send('command', 'application:open-your-config') - 'application:open-your-init-script': -> ipc.send('command', 'application:open-your-init-script') - 'application:open-your-keymap': -> ipc.send('command', 'application:open-your-keymap') - 'application:open-your-snippets': -> ipc.send('command', 'application:open-your-snippets') - 'application:open-your-stylesheet': -> ipc.send('command', 'application:open-your-stylesheet') - 'application:open-license': -> @getModel().openLicense() - 'window:run-package-specs': -> @runPackageSpecs() - 'window:focus-next-pane': -> @getModel().activateNextPane() - 'window:focus-previous-pane': -> @getModel().activatePreviousPane() - 'window:focus-pane-above': -> @focusPaneViewAbove() - 'window:focus-pane-below': -> @focusPaneViewBelow() - 'window:focus-pane-on-left': -> @focusPaneViewOnLeft() - 'window:focus-pane-on-right': -> @focusPaneViewOnRight() - 'window:save-all': -> @getModel().saveAll() - 'window:toggle-invisibles': -> atom.config.set("editor.showInvisibles", not atom.config.get("editor.showInvisibles")) - 'window:log-deprecation-warnings': -> Grim.logDeprecations() - 'window:toggle-auto-indent': -> atom.config.set("editor.autoIndent", not atom.config.get("editor.autoIndent")) - 'pane:reopen-closed-item': -> @getModel().reopenItem() - 'core:close': -> @getModel().destroyActivePaneItemOrEmptyPane() - 'core:save': -> @getModel().saveActivePaneItem() - 'core:save-as': -> @getModel().saveActivePaneItemAs() - -if process.platform is 'darwin' - atom.commands.add 'atom-workspace', 'window:install-shell-commands', -> @getModel().installShellCommands() - module.exports = WorkspaceElement = document.registerElement 'atom-workspace', prototype: WorkspaceElement.prototype diff --git a/src/workspace.coffee b/src/workspace.coffee index bda6e9b45..c8bbdc0c8 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -26,8 +26,6 @@ Task = require './task' # module.exports = class Workspace extends Model - atom.deserializers.add(this) - @deserialize: (state) -> return unless state? From 085b945015b75ff7975e1dfce445ae5498fed6fc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 10:48:17 -0600 Subject: [PATCH 023/316] Don't mess with disposables in initialize --- src/atom.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 8f01d2122..6bd34a102 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -270,9 +270,6 @@ class Atom extends Model @emitter.emit 'did-throw-error', {message, url, line, column, originalError} - @disposables?.dispose() - @disposables = new CompositeDisposable - @displayWindow() unless @inSpecMode() @setBodyPlatformClass() From bcabd0b8a9a7ccf528b47be5ec7e09158abab51c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 13:04:33 -0600 Subject: [PATCH 024/316] :arrow_up: donna to fix docs generation errors --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index ad483c75f..da11dc97a 100644 --- a/build/package.json +++ b/build/package.json @@ -8,7 +8,7 @@ "dependencies": { "asar": "^0.8.0", "async": "~0.2.9", - "donna": "1.0.10", + "donna": "^1.0.12", "formidable": "~1.0.14", "fs-plus": "2.x", "github-releases": "~0.3.0", From eead10a9c540b77baf5db66efe05d3ce75b90bf7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 19:59:03 -0600 Subject: [PATCH 025/316] Initialize loadTime to null in Atom environment constructor --- src/atom.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 6bd34a102..65ab141a9 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -152,6 +152,7 @@ class Atom extends Model # Call .loadOrCreate instead constructor: (@state) -> {@mode} = @state + @loadTime = null {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @@ -274,8 +275,6 @@ class Atom extends Model @setBodyPlatformClass() - @loadTime = null - {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() From 23d1151ca3a30e427338f96352b13c9379814679 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 20:05:44 -0600 Subject: [PATCH 026/316] Initialize KeymapManager on Atom environment construction --- src/atom.coffee | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 65ab141a9..9769a06da 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -171,6 +171,8 @@ class Atom extends Model KeymapManager = require './keymap-extensions' @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) + @keymaps.subscribeToFileReadFailure() + @keymaps.loadBundledKeymaps() TooltipManager = require './tooltip-manager' @tooltips = new TooltipManager(keymapManager: @keymaps) @@ -287,8 +289,6 @@ class Atom extends Model # Make react.js faster process.env.NODE_ENV ?= 'production' unless devMode - @keymaps.subscribeToFileReadFailure() - document.head.appendChild(new StylesElement) if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath @@ -611,7 +611,6 @@ class Atom extends Model console.warn error.message if error? @loadConfig() - @keymaps.loadBundledKeymaps() @themes.loadBaseStylesheets() @packages.loadPackages() @deserializeEditorWindow() From a2563a1b4f79990e5f7a6c1d43a7440a9a4ee6a4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 20:12:38 -0600 Subject: [PATCH 027/316] Require ipc for use in default commands --- src/register-default-commands.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index c43fd5bb7..44c8e287c 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -1,3 +1,5 @@ +ipc = require 'ipc' + module.exports = (commandRegistry) -> commandRegistry.add 'atom-workspace', 'pane:show-next-item': -> @getModel().getActivePane().activateNextItem() From a573e1f381824c227713f1084eb714d1ef61b291 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 20:16:22 -0600 Subject: [PATCH 028/316] Watch for theme changes in ThemeManager instead of Atom environment --- src/atom.coffee | 7 ------- src/package-manager.coffee | 5 +++++ src/theme-manager.coffee | 2 ++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 9769a06da..c302bbdc0 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -294,7 +294,6 @@ class Atom extends Model if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath @grammars.grammarOverridesByPath = grammarOverridesByPath - @disposables.add @packages.onDidActivateInitialPackages => @watchThemes() @windowEventHandler = new WindowEventHandler ### @@ -771,12 +770,6 @@ class Atom extends Model loadThemes: -> @themes.load() - watchThemes: -> - @themes.onDidChangeActiveThemes => - # Only reload stylesheets from non-theme packages - for pack in @packages.getActivePackages() when pack.getType() isnt 'theme' - pack.reloadStylesheets?() - return # Notify the browser project of the window's current project path watchProjectPath: -> diff --git a/src/package-manager.coffee b/src/package-manager.coffee index f36a0c389..b6d708d3a 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -456,3 +456,8 @@ class PackageManager [isSymLink, isDir] = values if not isSymLink and isDir fs.remove directory, -> + + reloadActivePackageStyleSheets: -> + for pack in @getActivePackages() when pack.getType() isnt 'theme' + pack.reloadStylesheets?() + return diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index ad5fe96d4..7484ef96f 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -18,6 +18,8 @@ class ThemeManager @lessCache = null @initialLoadComplete = false @packageManager.registerPackageActivator(this, ['theme']) + @packageManager.onDidActivateInitialPackages => + @onDidChangeActiveThemes => @packageManager.reloadActivePackageStyleSheets() ### Section: Event Subscription From 7d014581cf761e28aee149acdd03e4783cf61002 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Sep 2015 20:23:51 -0600 Subject: [PATCH 029/316] Move installation of uncaught error handler to startEditorWindow --- spec/atom-spec.coffee | 4 ++++ src/atom.coffee | 45 +++++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 85d9dd4b9..f0219d164 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -61,6 +61,10 @@ describe "the `atom` global", -> beforeEach -> spyOn atom, 'openDevTools' spyOn atom, 'executeJavaScriptInDevTools' + atom.installUncaughtErrorHandler() + + afterEach: -> + atom.uninstallUncaughtErrorHandler() it "will open the dev tools when an error is triggered", -> try diff --git a/src/atom.coffee b/src/atom.coffee index c302bbdc0..720f2c455 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -254,25 +254,6 @@ class Atom extends Model # # Call after this instance has been assigned to the `atom` global. initialize: -> - window.onerror = => - @lastUncaughtError = Array::slice.call(arguments) - [message, url, line, column, originalError] = @lastUncaughtError - - {line, column} = mapSourcePosition({source: url, line, column}) - - eventObject = {message, url, line, column, originalError} - - openDevTools = true - eventObject.preventDefault = -> openDevTools = false - - @emitter.emit 'will-throw-error', eventObject - - if openDevTools - @openDevTools() - @executeJavaScriptInDevTools('DevToolsAPI.showConsole()') - - @emitter.emit 'did-throw-error', {message, url, line, column, originalError} - @displayWindow() unless @inSpecMode() @setBodyPlatformClass() @@ -599,6 +580,8 @@ class Atom extends Model # Call this method when establishing a real application window. startEditorWindow: -> + @installUncaughtErrorHandler() + {safeMode} = @getLoadSettings() CommandInstaller = require './command-installer' @@ -655,6 +638,30 @@ class Atom extends Model if @getLoadSettings().initialPaths?.length is 0 and @workspace.getPaneItems().length is 0 @workspace.open(null) + installUncaughtErrorHandler: -> + @previousWindowErrorHandler = window.onerror + window.onerror = => + @lastUncaughtError = Array::slice.call(arguments) + [message, url, line, column, originalError] = @lastUncaughtError + + {line, column} = mapSourcePosition({source: url, line, column}) + + eventObject = {message, url, line, column, originalError} + + openDevTools = true + eventObject.preventDefault = -> openDevTools = false + + @emitter.emit 'will-throw-error', eventObject + + if openDevTools + @openDevTools() + @executeJavaScriptInDevTools('DevToolsAPI.showConsole()') + + @emitter.emit 'did-throw-error', {message, url, line, column, originalError} + + uninstallUncaughtErrorHandler: -> + window.onerror = @previousWindowErrorHandler + ### Section: Messaging the User ### From dba2a77e1fb0f4ee5d2893a07324ccf73d0b78f7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 11:33:40 -0600 Subject: [PATCH 030/316] Assign env vars in initialize-application-window Also, add a get-window-load-settings helper. --- src/atom.coffee | 19 ++----------------- src/get-window-load-settings.coffee | 16 ++++++++++++++++ src/initialize-application-window.coffee | 13 +++++++++++++ 3 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 src/get-window-load-settings.coffee diff --git a/src/atom.coffee b/src/atom.coffee index 720f2c455..4c0807dc4 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -14,6 +14,7 @@ Model = require './model' WindowEventHandler = require './window-event-handler' StylesElement = require './styles-element' StorageFolder = require './storage-folder' +getWindowLoadSettings = require './get-window-load-settings' # Essential: Atom global for dealing with packages, themes, menus, and the window. # @@ -72,15 +73,7 @@ class Atom extends Model @storageFolder ?= new StorageFolder(@getConfigDirPath()) # Returns the load settings hash associated with the current window. - @getLoadSettings: -> - @loadSettings ?= JSON.parse(decodeURIComponent(location.hash.substr(1))) - cloned = _.deepClone(@loadSettings) - # The loadSettings.windowState could be large, request it only when needed. - cloned.__defineGetter__ 'windowState', => - @getCurrentWindow().loadSettings.windowState - cloned.__defineSetter__ 'windowState', (value) => - @getCurrentWindow().loadSettings.windowState = value - cloned + @getLoadSettings: -> getWindowLoadSettings() @updateLoadSetting: (key, value) -> @getLoadSettings() @@ -261,14 +254,6 @@ class Atom extends Model {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() - # Add 'exports' to module search path. - exportsPath = path.join(resourcePath, 'exports') - require('module').globalPaths.push(exportsPath) - # Still set NODE_PATH since tasks may need it. - process.env.NODE_PATH = exportsPath - - # Make react.js faster - process.env.NODE_ENV ?= 'production' unless devMode document.head.appendChild(new StylesElement) diff --git a/src/get-window-load-settings.coffee b/src/get-window-load-settings.coffee new file mode 100644 index 000000000..7f41ad05f --- /dev/null +++ b/src/get-window-load-settings.coffee @@ -0,0 +1,16 @@ +remote = require 'remote' +_ = require 'underscore-plus' + +windowLoadSettings = null + +module.exports = -> + windowLoadSettings ?= JSON.parse(window.decodeURIComponent(window.location.hash.substr(1))) + clone = _.deepClone(windowLoadSettings) + + # The windowLoadSettings.windowState could be large, request it only when needed. + clone.__defineGetter__ 'windowState', => + remote.getCurrentWindow().loadSettings.windowState + clone.__defineSetter__ 'windowState', (value) => + remote.getCurrentWindow().loadSettings.windowState = value + + clone diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 886ba26dc..69c7e6582 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -1,5 +1,18 @@ # Like sands through the hourglass, so are the days of our lives. + +path = require 'path' require './window' +getWindowLoadSettings = require './get-window-load-settings' + +{devMode, resourcePath} = getWindowLoadSettings() + +# Add application-specific exports to module search path. +exportsPath = path.join(resourcePath, 'exports') +require('module').globalPaths.push(exportsPath) +process.env.NODE_PATH = exportsPath + +# Make React faster +process.env.NODE_ENV ?= 'production' unless devMode Atom = require './atom' window.atom = Atom.loadOrCreate('editor') From 2737e05561a11cf1afd66f369eb4b0571057c501 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 12:04:17 -0600 Subject: [PATCH 031/316] Display window in initialize-application-window script --- src/atom.coffee | 3 --- src/initialize-application-window.coffee | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 4c0807dc4..06c8e4bd2 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -247,8 +247,6 @@ class Atom extends Model # # Call after this instance has been assigned to the `atom` global. initialize: -> - @displayWindow() unless @inSpecMode() - @setBodyPlatformClass() {devMode, safeMode, resourcePath} = @getLoadSettings() @@ -762,7 +760,6 @@ class Atom extends Model loadThemes: -> @themes.load() - # Notify the browser project of the window's current project path watchProjectPath: -> @disposables.add @project.onDidChangePaths => diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 69c7e6582..3e4b435e2 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -4,7 +4,7 @@ path = require 'path' require './window' getWindowLoadSettings = require './get-window-load-settings' -{devMode, resourcePath} = getWindowLoadSettings() +{resourcePath, isSpec, devMode} = getWindowLoadSettings() # Add application-specific exports to module search path. exportsPath = path.join(resourcePath, 'exports') @@ -16,6 +16,8 @@ process.env.NODE_ENV ?= 'production' unless devMode Atom = require './atom' window.atom = Atom.loadOrCreate('editor') + +atom.displayWindow() unless isSpec atom.initialize() atom.startEditorWindow() From ee270db7accc1252a6c50eb0f8204f1699331316 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 13:37:24 -0600 Subject: [PATCH 032/316] Move document mutation to startEditorWindow --- spec/jasmine-test-runner.coffee | 2 ++ src/atom.coffee | 11 +++-------- src/menu-manager.coffee | 5 ++++- src/package.coffee | 3 --- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 03e67bea3..ab7e9aae1 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -3,6 +3,7 @@ _ = require 'underscore-plus' fs = require 'fs-plus' path = require 'path' ipc = require 'ipc' +StylesElement = require '../src/styles-element' module.exports = ({logFile, headless, testPaths}) -> window[key] = value for key, value of require '../vendor/jasmine' @@ -22,6 +23,7 @@ module.exports = ({logFile, headless, testPaths}) -> jasmineContent = document.createElement('div') jasmineContent.setAttribute('id', 'jasmine-content') + document.head.appendChild(new StylesElement) document.body.appendChild(jasmineContent) jasmineEnv.execute() diff --git a/src/atom.coffee b/src/atom.coffee index 06c8e4bd2..8b4e7b4f6 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -247,14 +247,6 @@ class Atom extends Model # # Call after this instance has been assigned to the `atom` global. initialize: -> - @setBodyPlatformClass() - - {devMode, safeMode, resourcePath} = @getLoadSettings() - configDirPath = @getConfigDirPath() - - - document.head.appendChild(new StylesElement) - if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath @grammars.grammarOverridesByPath = grammarOverridesByPath @@ -577,6 +569,9 @@ class Atom extends Model @loadConfig() @themes.loadBaseStylesheets() + + @setBodyPlatformClass() + document.head.appendChild(new StylesElement) @packages.loadPackages() @deserializeEditorWindow() diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 0de08cfa7..c8096441a 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -191,7 +191,10 @@ class MenuManager # Get an {Array} of {String} classes for the given element. classesForElement: (element) -> - element?.classList.toString().split(' ') ? [] + if classList = element?.classList + Array::slice.apply(classList) + else + [] sortPackagesMenu: -> packagesMenu = _.find @template, ({label}) -> MenuHelpers.normalizeLabel(label) is 'Packages' diff --git a/src/package.coffee b/src/package.coffee index 0163f8bcd..dcb188584 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -132,7 +132,6 @@ class Package @activationPromise ?= new Promise (resolve, reject) => @resolveActivationPromise = resolve - @rejectActivationPromise = reject @measure 'activateTime', => try @activateResources() @@ -370,10 +369,8 @@ class Package console.error "Error serializing package '#{@name}'", e.stack deactivate: -> - @rejectActivationPromise?() @activationPromise = null @resolveActivationPromise = null - @rejectActivationPromise = null @activationCommandSubscriptions?.dispose() @deactivateResources() @deactivateConfig() From 4ca09ef7d3cd88d00cb951727967f3a3a45ecc63 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 13:44:17 -0600 Subject: [PATCH 033/316] Assign to cached load settings correctly --- src/atom.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 8b4e7b4f6..98f7682e4 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -76,8 +76,7 @@ class Atom extends Model @getLoadSettings: -> getWindowLoadSettings() @updateLoadSetting: (key, value) -> - @getLoadSettings() - @loadSettings[key] = value + @getLoadSettings()[key] = value location.hash = encodeURIComponent(JSON.stringify(@loadSettings)) @getCurrentWindow: -> From 0f5483a2ede0a02b5d06d35ced8e552b00fa800d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 14:04:09 -0600 Subject: [PATCH 034/316] Assign config schema on Atom environment construction --- spec/atom-spec.coffee | 2 +- spec/spec-helper.coffee | 4 +--- src/atom.coffee | 12 +++++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index f0219d164..4d3021bef 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -52,7 +52,7 @@ describe "the `atom` global", -> expect(releaseVersion).toBe 'version' describe "loading default config", -> - it 'loads the default core config', -> + it 'loads the default core config schema', -> expect(atom.config.get('core.excludeVcsIgnoredPaths')).toBe true expect(atom.config.get('core.followSymlinks')).toBe true expect(atom.config.get('editor.showInvisibles')).toBe false diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index fd02e6fac..d0350dc62 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -126,7 +126,6 @@ beforeEach -> # reset config before each spec; don't load or save from/to `config.json` spyOn(atom.config, 'load') spyOn(atom.config, 'save') - atom.loadConfig() atom.config.set "core.destroyEmptyPanes", false atom.config.set "editor.fontFamily", "Courier" atom.config.set "editor.fontSize", 16 @@ -157,8 +156,6 @@ beforeEach -> addCustomMatchers(this) afterEach -> - atom.reset() - atom.packages.deactivatePackages() atom.menu.template = [] atom.contextMenu.clear() @@ -175,6 +172,7 @@ afterEach -> atom.themes.removeStylesheet('global-editor-styles') delete atom.state.packageStates + atom.reset() document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent diff --git a/src/atom.coffee b/src/atom.coffee index 98f7682e4..a150fef2c 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -160,6 +160,7 @@ class Atom extends Model Config = require './config' @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) + @setConfigSchema() KeymapManager = require './keymap-extensions' @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) @@ -204,6 +205,9 @@ class Atom extends Model registerDefaultCommands = require './register-default-commands' registerDefaultCommands(@commands) + setConfigSchema: -> + @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} + registerDeserializersAndViewProviders: -> Workspace = require './workspace' PaneContainer = require './pane-container' @@ -240,6 +244,7 @@ class Atom extends Model reset: -> @config.reset() + @setConfigSchema() # Sets up the basic services that should be available in all modes # (both spec and application). @@ -566,7 +571,8 @@ class Atom extends Model commandInstaller.installApmCommand false, (error) -> console.warn error.message if error? - @loadConfig() + @config.load() + @themes.loadBaseStylesheets() @setBodyPlatformClass() @@ -747,10 +753,6 @@ class Atom extends Model @deserializeProject() @deserializeWorkspace() - loadConfig: -> - @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} - @config.load() - loadThemes: -> @themes.load() From 716807f6197529bf2b7e51a9bed846fc937acd3d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 14:06:30 -0600 Subject: [PATCH 035/316] Remove stray debugger --- src/theme-manager.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 7484ef96f..649478841 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -10,9 +10,6 @@ fs = require 'fs-plus' module.exports = class ThemeManager constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode, @config, @styleManager, @notificationManager, @viewRegistry}) -> - unless @packageManager - debugger - @emitter = new Emitter @styleSheetDisposablesBySourcePath = {} @lessCache = null From dd4b9346bbe9b4374963fc37805a83a076c1b3d0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 14:57:50 -0600 Subject: [PATCH 036/316] Deserialize grammar on editor window start --- src/atom.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index a150fef2c..31fa6a923 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -251,9 +251,6 @@ class Atom extends Model # # Call after this instance has been assigned to the `atom` global. initialize: -> - if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath - @grammars.grammarOverridesByPath = grammarOverridesByPath - @windowEventHandler = new WindowEventHandler ### @@ -749,6 +746,9 @@ class Atom extends Model delete @state.packageStates deserializeEditorWindow: -> + if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath + @grammars.grammarOverridesByPath = grammarOverridesByPath + @deserializePackageStates() @deserializeProject() @deserializeWorkspace() From e838863bc7e9b733ed04a5cdaad8f7b40af98ea2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 15:21:19 -0600 Subject: [PATCH 037/316] Handle window/document events in startEditorWindow and remove initialize --- spec/atom-spec.coffee | 20 ------ spec/spec-helper.coffee | 1 - spec/window-event-handler-spec.coffee | 25 ++++++- src/atom.coffee | 9 +-- src/initialize-application-window.coffee | 1 - src/window-event-handler.coffee | 86 ++++++++++++------------ 6 files changed, 67 insertions(+), 75 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 4d3021bef..9bcb985ee 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -31,26 +31,6 @@ describe "the `atom` global", -> version = '36b5518' expect(atom.isReleasedVersion()).toBe false - describe "when an update becomes available", -> - subscription = null - - afterEach -> - subscription?.dispose() - - it "invokes onUpdateAvailable listeners", -> - updateAvailableHandler = jasmine.createSpy("update-available-handler") - subscription = atom.onUpdateAvailable updateAvailableHandler - - autoUpdater = require('remote').require('auto-updater') - autoUpdater.emit 'update-downloaded', null, "notes", "version" - - waitsFor -> - updateAvailableHandler.callCount > 0 - - runs -> - {releaseVersion} = updateAvailableHandler.mostRecentCall.args[0] - expect(releaseVersion).toBe 'version' - describe "loading default config", -> it 'loads the default core config schema', -> expect(atom.config.get('core.excludeVcsIgnoredPaths')).toBe true diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index d0350dc62..508c8c1fa 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -1,5 +1,4 @@ require '../src/window' -atom.initialize() atom.restoreWindowDimensions() require 'jasmine-json' diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 345c0fd8c..07bcae5a3 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -5,7 +5,7 @@ temp = require 'temp' TextEditor = require '../src/text-editor' WindowEventHandler = require '../src/window-event-handler' -describe "Window", -> +describe "WindowEventHandler", -> [projectPath, windowEventHandler] = [] beforeEach -> @@ -16,8 +16,7 @@ describe "Window", -> loadSettings.initialPath = initialPath loadSettings atom.project.destroy() - atom.windowEventHandler.unsubscribe() - windowEventHandler = new WindowEventHandler + windowEventHandler = new WindowEventHandler(atom) projectPath = atom.project.getPaths()[0] afterEach -> @@ -293,3 +292,23 @@ describe "Window", -> expect(dispatchedCommands.length).toBe 1 expect(dispatchedCommands[0].type).toBe 'foo-command' + + describe "when an update becomes available", -> + subscription = null + + afterEach -> + subscription?.dispose() + + it "invokes onUpdateAvailable listeners", -> + updateAvailableHandler = jasmine.createSpy("update-available-handler") + subscription = atom.onUpdateAvailable updateAvailableHandler + + autoUpdater = require('remote').require('auto-updater') + autoUpdater.emit 'update-downloaded', null, "notes", "version" + + waitsFor -> + updateAvailableHandler.callCount > 0 + + runs -> + {releaseVersion} = updateAvailableHandler.mostRecentCall.args[0] + expect(releaseVersion).toBe 'version' diff --git a/src/atom.coffee b/src/atom.coffee index 31fa6a923..cb2d8f899 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -246,13 +246,6 @@ class Atom extends Model @config.reset() @setConfigSchema() - # Sets up the basic services that should be available in all modes - # (both spec and application). - # - # Call after this instance has been assigned to the `atom` global. - initialize: -> - @windowEventHandler = new WindowEventHandler - ### Section: Event Subscription ### @@ -574,6 +567,8 @@ class Atom extends Model @setBodyPlatformClass() document.head.appendChild(new StylesElement) + @windowEventHandler = new WindowEventHandler(this) + @packages.loadPackages() @deserializeEditorWindow() diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 3e4b435e2..246633179 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -18,7 +18,6 @@ Atom = require './atom' window.atom = Atom.loadOrCreate('editor') atom.displayWindow() unless isSpec -atom.initialize() atom.startEditorWindow() # Workaround for focus getting cleared upon window creation diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 270650b2f..ceb9c126e 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -8,7 +8,7 @@ listen = require './delegated-listener' # Handles low-level events related to the window. module.exports = class WindowEventHandler - constructor: -> + constructor: (@atomEnv) -> @reloadRequested = false @subscriptions = new CompositeDisposable @@ -28,17 +28,17 @@ class WindowEventHandler @subscriptions.add listen(document, 'click', 'a', @handleLinkClick) @subscriptions.add listen(document, 'submit', 'form', @handleFormSubmit) - @subscriptions.add atom.commands.add window, + @subscriptions.add @atomEnv.commands.add window, 'window:toggle-full-screen': @handleWindowToggleFullScreen 'window:close': @handleWindowClose 'window:reload': @handleWindowReload 'window:toggle-dev-tools': @handleWindowToggleDevTools if process.platform in ['win32', 'linux'] - @subscriptions.add atom.commands.add window, + @subscriptions.add @atomEnv.commands.add window, 'window:toggle-menu-bar': @handleWindowToggleMenuBar - @subscriptions.add atom.commands.add document, + @subscriptions.add @atomEnv.commands.add document, 'core:focus-next': @handleFocusNext 'core:focus-previous': @handleFocusPrevious @@ -48,9 +48,9 @@ class WindowEventHandler # `.native-key-bindings` class. handleNativeKeybindings: -> bindCommandToAction = (command, action) => - @addEventListener document, command, (event) -> + @addEventListener document, command, (event) => if event.target.webkitMatchesSelector('.native-key-bindings') - atom.getCurrentWindow().webContents[action]() + @atomEnv.getCurrentWindow().webContents[action]() bindCommandToAction('core:copy', 'copy') bindCommandToAction('core:paste', 'paste') @@ -72,8 +72,8 @@ class WindowEventHandler target.addEventListener(eventName, handler) @subscriptions.add(new Disposable(-> target.removeEventListener(eventName, handler))) - handleDocumentKeydown: (event) -> - atom.keymaps.handleKeyboardEvent(event) + handleDocumentKeydown: (event) => + @atomEnv.keymaps.handleKeyboardEvent(event) event.stopImmediatePropagation() handleDrop: (event) -> @@ -134,80 +134,80 @@ class WindowEventHandler else if highestElement? highestElement.focus() - handleIPCMessage: (message, detail) -> + handleIPCMessage: (message, detail) => switch message when 'open-locations' - needsProjectPaths = atom.project?.getPaths().length is 0 + needsProjectPaths = @atomEnv.project?.getPaths().length is 0 for {pathToOpen, initialLine, initialColumn} in detail if pathToOpen? and needsProjectPaths if fs.existsSync(pathToOpen) - atom.project.addPath(pathToOpen) + @atomEnv.project.addPath(pathToOpen) else if fs.existsSync(path.dirname(pathToOpen)) - atom.project.addPath(path.dirname(pathToOpen)) + @atomEnv.project.addPath(path.dirname(pathToOpen)) else - atom.project.addPath(pathToOpen) + @atomEnv.project.addPath(pathToOpen) unless fs.isDirectorySync(pathToOpen) - atom.workspace?.open(pathToOpen, {initialLine, initialColumn}) + @atomEnv.workspace?.open(pathToOpen, {initialLine, initialColumn}) return when 'update-available' - atom.updateAvailable(detail) + @atomEnv.updateAvailable(detail) - handleIPCCommand: (command, args...) -> + handleIPCCommand: (command, args...) => activeElement = document.activeElement # Use the workspace element view if body has focus - if activeElement is document.body and workspaceElement = atom.views.getView(atom.workspace) + if activeElement is document.body and workspaceElement = @atomEnv.views.getView(@atomEnv.workspace) activeElement = workspaceElement - atom.commands.dispatch(activeElement, command, args[0]) + @atomEnv.commands.dispatch(activeElement, command, args[0]) - handleIPCContextCommand: (command, args...) -> - atom.commands.dispatch(atom.contextMenu.activeElement, command, args) + handleIPCContextCommand: (command, args...) => + @atomEnv.commands.dispatch(@atomEnv.contextMenu.activeElement, command, args) handleWindowFocus: -> document.body.classList.remove('is-blurred') - handleWindowBlur: -> + handleWindowBlur: => document.body.classList.add('is-blurred') - atom.storeDefaultWindowDimensions() + @atomEnv.storeDefaultWindowDimensions() handleWindowBeforeunload: => - confirmed = atom.workspace?.confirmClose(windowCloseRequested: true) - atom.hide() if confirmed and not @reloadRequested and atom.getCurrentWindow().isWebViewFocused() + confirmed = @atomEnv.workspace?.confirmClose(windowCloseRequested: true) + @atomEnv.hide() if confirmed and not @reloadRequested and @atomEnv.getCurrentWindow().isWebViewFocused() @reloadRequested = false - atom.storeDefaultWindowDimensions() - atom.storeWindowDimensions() + @atomEnv.storeDefaultWindowDimensions() + @atomEnv.storeWindowDimensions() if confirmed - atom.unloadEditorWindow() + @atomEnv.unloadEditorWindow() else ipc.send('cancel-window-close') confirmed - handleWindowUnload: -> - atom.removeEditorWindow() + handleWindowUnload: => + @atomEnv.removeEditorWindow() - handleWindowToggleFullScreen: -> - atom.toggleFullScreen() + handleWindowToggleFullScreen: => + @atomEnv.toggleFullScreen() - handleWindowClose: -> - atom.close() + handleWindowClose: => + @atomEnv.close() - handleWindowReload: -> + handleWindowReload: => @reloadRequested = true - atom.reload() + @atomEnv.reload() - handleWindowToggleDevTools: -> - atom.toggleDevTools() + handleWindowToggleDevTools: => + @atomEnv.toggleDevTools() - handleWindowToggleMenuBar: -> - atom.config.set('core.autoHideMenuBar', not atom.config.get('core.autoHideMenuBar')) + handleWindowToggleMenuBar: => + @atomEnv.config.set('core.autoHideMenuBar', not @atomEnv.config.get('core.autoHideMenuBar')) - if atom.config.get('core.autoHideMenuBar') + if @atomEnv.config.get('core.autoHideMenuBar') detail = "To toggle, press the Alt key or execute the window:toggle-menu-bar command" - atom.notifications.addInfo('Menu bar hidden', {detail}) + @atomEnv.notifications.addInfo('Menu bar hidden', {detail}) handleLinkClick: (event) -> event.preventDefault() @@ -219,6 +219,6 @@ class WindowEventHandler # Prevent form submits from changing the current window's URL event.preventDefault() - handleDocumentContextmenu: (event) -> + handleDocumentContextmenu: (event) => event.preventDefault() - atom.contextMenu.showForEvent(event) + @atomEnv.contextMenu.showForEvent(event) From 57bae5745f2b83c3a5aafef6034d49855c003d28 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 15:26:23 -0600 Subject: [PATCH 038/316] Check deprecations on travis --- spec/jasmine-test-runner.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index ab7e9aae1..0f795af0a 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -79,7 +79,7 @@ buildTerminalReporter = (logFile) -> log(str) onComplete: (runner) -> fs.closeSync(logStream) if logStream? - if process.env.JANKY_SHA1 + if process.env.JANKY_SHA1 or process.env.CI grim = require 'grim' if grim.getDeprecationsLength() > 0 From b240ffc16148b0478b326e183e3868c98e690c3b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 15:31:29 -0600 Subject: [PATCH 039/316] :art: --- src/atom.coffee | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index cb2d8f899..6622da39f 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -16,6 +16,20 @@ StylesElement = require './styles-element' StorageFolder = require './storage-folder' getWindowLoadSettings = require './get-window-load-settings' +Workspace = require './workspace' +PaneContainer = require './pane-container' +PaneAxis = require './pane-axis' +Pane = require './pane' +Project = require './project' +TextEditor = require './text-editor' +TextBuffer = require 'text-buffer' +Gutter = require './gutter' +PaneElement = require './pane-element' +PaneContainerElement = require './pane-container-element' +PaneAxisElement = require './pane-axis-element' +TextEditorElement = require './text-editor-element' +{createGutterView} = require './gutter-component-helpers' + # Essential: Atom global for dealing with packages, themes, menus, and the window. # # An instance of this class is always available as the `atom` global. @@ -154,6 +168,11 @@ class Atom extends Model DeserializerManager = require './deserializer-manager' @deserializers = new DeserializerManager() @deserializeTimings = {} + @registerDeserializers() + + ViewRegistry = require './view-registry' + @views = new ViewRegistry + @registerViewProviders() NotificationManager = require './notification-manager' @notifications = new NotificationManager @@ -172,9 +191,8 @@ class Atom extends Model CommandRegistry = require './command-registry' @commands = new CommandRegistry - - ViewRegistry = require './view-registry' - @views = new ViewRegistry + registerDefaultCommands = require './register-default-commands' + registerDefaultCommands(@commands) PackageManager = require './package-manager' @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config}) @@ -200,23 +218,10 @@ class Atom extends Model GrammarRegistry = require './grammar-registry' @grammars = new GrammarRegistry({@config}) - @registerDeserializersAndViewProviders() - - registerDefaultCommands = require './register-default-commands' - registerDefaultCommands(@commands) - setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} - registerDeserializersAndViewProviders: -> - Workspace = require './workspace' - PaneContainer = require './pane-container' - PaneAxis = require './pane-axis' - Pane = require './pane' - Project = require './project' - TextEditor = require './text-editor' - TextBuffer = require 'text-buffer' - + registerDeserializers: -> @deserializers.add(Workspace) @deserializers.add(PaneContainer) @deserializers.add(PaneAxis) @@ -225,13 +230,7 @@ class Atom extends Model @deserializers.add(TextEditor) @deserializers.add(TextBuffer) - Gutter = require './gutter' - PaneElement = require './pane-element' - PaneContainerElement = require './pane-container-element' - PaneAxisElement = require './pane-axis-element' - TextEditorElement = require './text-editor-element' - {createGutterView} = require './gutter-component-helpers' - + registerViewProviders: -> @views.addViewProvider PaneContainer, (model) -> new PaneContainerElement().initialize(model) @views.addViewProvider PaneAxis, (model) -> From 727d6f60f73f9ff0c14e54279b084c88ab585570 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 19:22:49 -0600 Subject: [PATCH 040/316] :art: --- src/atom.coffee | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 6622da39f..5887881ee 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -550,10 +550,7 @@ class Atom extends Model startEditorWindow: -> @installUncaughtErrorHandler() - {safeMode} = @getLoadSettings() - CommandInstaller = require './command-installer' - commandInstaller = new CommandInstaller(@getVersion()) commandInstaller.installAtomCommand false, (error) -> console.warn error.message if error? @@ -561,7 +558,6 @@ class Atom extends Model console.warn error.message if error? @config.load() - @themes.loadBaseStylesheets() @setBodyPlatformClass() @@ -575,7 +571,7 @@ class Atom extends Model @packages.activate() @keymaps.loadUserKeymap() - @requireUserInitScript() unless safeMode + @requireUserInitScript() unless @getLoadSettings().safeMode @menu.update() @disposables.add @config.onDidChange 'core.autoHideMenuBar', ({newValue}) => From b649cb48efe449c39a132671fd6872570d9f9660 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 19:42:37 -0600 Subject: [PATCH 041/316] Move static Package methods to PackageManager instance --- spec/package-spec.coffee | 32 +++++++++++----------- src/package-manager.coffee | 45 +++++++++++++++++++++++++++---- src/package.coffee | 55 +++++++------------------------------- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index bf059e0b5..c106689f2 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -13,29 +13,29 @@ describe "Package", -> it "does not activate it", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - pack = new Package(packagePath) + pack = new Package(path: packagePath, packageManager: atom.packages) expect(pack.isCompatible()).toBe false expect(pack.incompatibleModules[0].name).toBe 'native-module' expect(pack.incompatibleModules[0].path).toBe path.join(packagePath, 'node_modules', 'native-module') it "utilizes _atomModuleCache if present to determine the package's native dependencies", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-ignored-incompatible-native-module') - pack = new Package(packagePath) + pack = new Package(path: packagePath, packageManager: atom.packages) expect(pack.getNativeModuleDependencyPaths().length).toBe(1) # doesn't see the incompatible module expect(pack.isCompatible()).toBe true packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-cached-incompatible-native-module') - pack = new Package(packagePath) + pack = new Package(path: packagePath, packageManager: atom.packages) expect(pack.isCompatible()).toBe false it "caches the incompatible native modules in local storage", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - expect(new Package(packagePath).isCompatible()).toBe false + expect(new Package(path: packagePath, packageManager: atom.packages).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 1 expect(global.localStorage.setItem.callCount).toBe 1 - expect(new Package(packagePath).isCompatible()).toBe false + expect(new Package(path: packagePath, packageManager: atom.packages).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 2 expect(global.localStorage.setItem.callCount).toBe 1 @@ -49,7 +49,7 @@ describe "Package", -> it "returns a promise resolving to the results of `apm rebuild`", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index') - pack = new Package(packagePath) + pack = new Package(path: packagePath, packageManager: atom.packages) rebuildCallbacks = [] spyOn(pack, 'runRebuildProcess').andCallFake ((callback) -> rebuildCallbacks.push(callback)) @@ -63,7 +63,7 @@ describe "Package", -> it "persists build failures in local storage", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index') - pack = new Package(packagePath) + pack = new Package(path: packagePath, packageManager: atom.packages) expect(pack.isCompatible()).toBe true expect(pack.getBuildFailureOutput()).toBeNull() @@ -79,7 +79,7 @@ describe "Package", -> expect(pack.isCompatible()).toBe false # A different package instance has the same failure output (simulates reload) - pack2 = new Package(packagePath) + pack2 = new Package(path: packagePath, packageManager: atom.packages) expect(pack2.getBuildFailureOutput()).toBe 'It is broken' expect(pack2.isCompatible()).toBe false @@ -92,7 +92,7 @@ describe "Package", -> it "sets cached incompatible modules to an empty array when the rebuild completes (there may be a build error, but rebuilding *deletes* native modules)", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - pack = new Package(packagePath) + pack = new Package(path: packagePath, packageManager: atom.packages) expect(pack.getIncompatibleNativeModules().length).toBeGreaterThan(0) @@ -118,14 +118,14 @@ describe "Package", -> it "loads and applies css", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "1234px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-index-css') - theme = new ThemePackage(themePath) + theme = new ThemePackage(path: themePath, packageManager: atom.packages) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "1234px" it "parses, loads and applies less", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "1234px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-index-less') - theme = new ThemePackage(themePath) + theme = new ThemePackage(path: themePath, packageManager: atom.packages) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "4321px" @@ -136,7 +136,7 @@ describe "Package", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe("103px") themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(themePath) + theme = new ThemePackage(path: themePath, packageManager: atom.packages) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe("101px") expect(getComputedStyle(editorElement).paddingRight).toBe("102px") @@ -149,7 +149,7 @@ describe "Package", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "30px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-without-package-file') - theme = new ThemePackage(themePath) + theme = new ThemePackage(path: themePath, packageManager: atom.packages) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "10px" expect(getComputedStyle(editorElement).paddingRight).toBe "20px" @@ -158,7 +158,7 @@ describe "Package", -> describe "reloading a theme", -> beforeEach -> themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(themePath) + theme = new ThemePackage(path: themePath, packageManager: atom.packages) theme.activate() it "reloads without readding to the stylesheets list", -> @@ -169,7 +169,7 @@ describe "Package", -> describe "events", -> beforeEach -> themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(themePath) + theme = new ThemePackage(path: themePath, packageManager: atom.packages) theme.activate() it "deactivated event fires on .deactivate()", -> @@ -182,7 +182,7 @@ describe "Package", -> beforeEach -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-different-directory-name') - metadata = Package.loadMetadata(packagePath, true) + metadata = atom.packages.loadPackageMetadata(packagePath, true) it "uses the package name defined in package.json", -> expect(metadata.name).toBe 'package-with-a-totally-different-name' diff --git a/src/package-manager.coffee b/src/package-manager.coffee index b6d708d3a..c75268339 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -1,8 +1,10 @@ path = require 'path' +normalizePackageData = null _ = require 'underscore-plus' {Emitter} = require 'event-kit' fs = require 'fs-plus' +CSON = require 'season' ServiceHub = require 'service-hub' Package = require './package' @@ -35,6 +37,7 @@ class PackageManager @packageDirPaths.push(path.join(configDirPath, "dev", "packages")) @packageDirPaths.push(path.join(configDirPath, "packages")) + @packagesCache = require('../package.json')?._atomPackages ? {} @loadedPackages = {} @activePackages = {} @packageStates = {} @@ -269,7 +272,7 @@ class PackageManager packages = [] for packagePath in @getAvailablePackagePaths() name = path.basename(packagePath) - metadata = @getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true) + metadata = @getLoadedPackage(name)?.metadata ? @loadPackageMetadata(packagePath, true) packages.push(metadata) packages @@ -292,7 +295,7 @@ class PackageManager @packageDependencies hasAtomEngine: (packagePath) -> - metadata = Package.loadMetadata(packagePath, true) + metadata = @loadPackageMetadata(packagePath, true) metadata?.engines?.atom? unobserveDisabledPackages: -> @@ -340,7 +343,7 @@ class PackageManager return pack if pack = @getLoadedPackage(name) try - metadata = Package.loadMetadata(packagePath) ? {} + metadata = @loadPackageMetadata(packagePath) ? {} catch error @handleMetadataError(error, packagePath) return null @@ -351,9 +354,9 @@ class PackageManager return null if metadata.theme - pack = new ThemePackage(packagePath, metadata) + pack = new ThemePackage({path: packagePath, metadata, packageManager: this}) else - pack = new Package(packagePath, metadata) + pack = new Package({path: packagePath, metadata, packageManager: this}) pack.load() @loadedPackages[pack.name] = pack @emitter.emit 'did-load-package', pack @@ -461,3 +464,35 @@ class PackageManager for pack in @getActivePackages() when pack.getType() isnt 'theme' pack.reloadStylesheets?() return + + isBundledPackagePath: (packagePath) -> + if @devMode + return false unless @resourcePath.startsWith("#{process.resourcesPath}#{path.sep}") + + @resourcePathWithTrailingSlash ?= "#{@resourcePath}#{path.sep}" + packagePath?.startsWith(@resourcePathWithTrailingSlash) + + loadPackageMetadata: (packagePath, ignoreErrors=false) -> + packageName = path.basename(packagePath) + if @isBundledPackagePath(packagePath) + metadata = packagesCache[packageName]?.metadata + unless metadata? + if metadataPath = CSON.resolve(path.join(packagePath, 'package')) + try + metadata = CSON.readFileSync(metadataPath) + @normalizePackageMetadata(metadata) + catch error + throw error unless ignoreErrors + + metadata ?= {} + unless typeof metadata.name is 'string' and metadata.name.length > 0 + metadata.name = packageName + + metadata + + normalizePackageMetadata: (metadata) -> + unless metadata?._id + normalizePackageData ?= require 'normalize-package-data' + normalizePackageData(metadata) + if metadata.repository?.type is 'git' and typeof metadata.repository.url is 'string' + metadata.repository.url = metadata.repository.url.replace(/^git\+/, '') diff --git a/src/package.coffee b/src/package.coffee index dcb188584..584000b57 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -1,5 +1,4 @@ path = require 'path' -normalizePackageData = null _ = require 'underscore-plus' async = require 'async' @@ -11,44 +10,10 @@ ModuleCache = require './module-cache' ScopedProperties = require './scoped-properties' BufferedProcess = require './buffered-process' -packagesCache = require('../package.json')?._atomPackages ? {} - # Extended: Loads and activates a package's main module and resources such as # stylesheets, keymaps, grammar, editor properties, and menus. module.exports = class Package - @isBundledPackagePath: (packagePath) -> - if atom.packages.devMode - return false unless atom.packages.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}") - - @resourcePathWithTrailingSlash ?= "#{atom.packages.resourcePath}#{path.sep}" - packagePath?.startsWith(@resourcePathWithTrailingSlash) - - @normalizeMetadata: (metadata) -> - unless metadata?._id - normalizePackageData ?= require 'normalize-package-data' - normalizePackageData(metadata) - if metadata.repository?.type is 'git' and typeof metadata.repository.url is 'string' - metadata.repository.url = metadata.repository.url.replace(/^git\+/, '') - - @loadMetadata: (packagePath, ignoreErrors=false) -> - packageName = path.basename(packagePath) - if @isBundledPackagePath(packagePath) - metadata = packagesCache[packageName]?.metadata - unless metadata? - if metadataPath = CSON.resolve(path.join(packagePath, 'package')) - try - metadata = CSON.readFileSync(metadataPath) - @normalizeMetadata(metadata) - catch error - throw error unless ignoreErrors - - metadata ?= {} - unless typeof metadata.name is 'string' and metadata.name.length > 0 - metadata.name = packageName - - metadata - keymaps: null menus: null stylesheets: null @@ -64,10 +29,10 @@ class Package Section: Construction ### - constructor: (@path, @metadata) -> + constructor: ({@path, @metadata, @packageManager}) -> @emitter = new Emitter - @metadata ?= Package.loadMetadata(@path) - @bundledPackage = Package.isBundledPackagePath(@path) + @metadata ?= @packageManager.loadPackageMetadata(@path) + @bundledPackage = @packageManager.isBundledPackagePath(@path) @name = @metadata?.name ? path.basename(@path) ModuleCache.add(@path, @metadata) @reset() @@ -251,15 +216,15 @@ class Package return loadKeymaps: -> - if @bundledPackage and packagesCache[@name]? - @keymaps = (["#{atom.packages.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of packagesCache[@name].keymaps) + if @bundledPackage and @packageManager.packagesCache[@name]? + @keymaps = (["#{atom.packages.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps) else @keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath) ? {}] return loadMenus: -> - if @bundledPackage and packagesCache[@name]? - @menus = (["#{atom.packages.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of packagesCache[@name].menus) + if @bundledPackage and @packageManager.packagesCache[@name]? + @menus = (["#{atom.packages.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of @packageManager.packagesCache[@name].menus) else @menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath) ? {}] return @@ -427,9 +392,9 @@ class Package return @mainModulePath if @resolvedMainModulePath @resolvedMainModulePath = true - if @bundledPackage and packagesCache[@name]? - if packagesCache[@name].main - @mainModulePath = "#{atom.packages.resourcePath}#{path.sep}#{packagesCache[@name].main}" + if @bundledPackage and @packageManager.packagesCache[@name]? + if @packageManager.packagesCache[@name].main + @mainModulePath = "#{atom.packages.resourcePath}#{path.sep}#{@packageManager.packagesCache[@name].main}" else @mainModulePath = null else From 677d7d69755e376a3bf93003a4c9bb86c6146ee4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Sep 2015 19:43:06 -0600 Subject: [PATCH 042/316] Load base stylesheets on ThemeManager construction --- spec/spec-helper.coffee | 1 - src/atom.coffee | 2 -- src/theme-manager.coffee | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 508c8c1fa..fb326caf8 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -20,7 +20,6 @@ TextEditorComponent = require '../src/text-editor-component' pathwatcher = require 'pathwatcher' clipboard = require '../src/safe-clipboard' -atom.themes.loadBaseStylesheets() atom.themes.requireStylesheet '../static/jasmine' atom.themes.initialLoadComplete = true diff --git a/src/atom.coffee b/src/atom.coffee index 5887881ee..6ae31c767 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -558,8 +558,6 @@ class Atom extends Model console.warn error.message if error? @config.load() - @themes.loadBaseStylesheets() - @setBodyPlatformClass() document.head.appendChild(new StylesElement) @windowEventHandler = new WindowEventHandler(this) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 649478841..4ccee0a4c 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -17,6 +17,7 @@ class ThemeManager @packageManager.registerPackageActivator(this, ['theme']) @packageManager.onDidActivateInitialPackages => @onDidChangeActiveThemes => @packageManager.reloadActivePackageStyleSheets() + @loadBaseStylesheets() ### Section: Event Subscription From d08180ceb0c640c1d69e0a7ca735b5aa31f18799 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 1 Oct 2015 16:43:16 -0600 Subject: [PATCH 043/316] Remove mode parameter from atom environment --- spec/atom-spec.coffee | 5 ++--- src/atom.coffee | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 9bcb985ee..7fb26f102 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -151,16 +151,15 @@ describe "the `atom` global", -> spyOn(Atom, 'getLoadSettings').andCallFake -> loadSettings spyOn(Atom.getStorageFolder(), 'getPath').andReturn(temp.mkdirSync("storage-dir-")) - atom.mode = "editor" atom.state.stuff = "cool" atom.project.setPaths([dir1, dir2]) atom.saveSync.originalValue.call(atom) - atom1 = Atom.loadOrCreate("editor") + atom1 = Atom.loadOrCreate() expect(atom1.state.stuff).toBeUndefined() loadSettings.initialPaths = [dir2, dir1] - atom2 = Atom.loadOrCreate("editor") + atom2 = Atom.loadOrCreate() expect(atom2.state.stuff).toBe("cool") describe "openInitialEmptyEditorIfNecessary", -> diff --git a/src/atom.coffee b/src/atom.coffee index 6ae31c767..090ce4ee3 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -43,9 +43,9 @@ class Atom extends Model # kind of environment you want to build. # # Returns an Atom instance, fully initialized - @loadOrCreate: (mode) -> + @loadOrCreate: -> startTime = Date.now() - atom = @deserialize(@loadState(mode)) ? new this({mode, @version}) + atom = @deserialize(@loadState()) ? new this({@version}) atom.deserializeTimings.atom = Date.now() - startTime atom @@ -55,8 +55,8 @@ class Atom extends Model # Loads and returns the serialized state corresponding to this window # if it exists; otherwise returns undefined. - @loadState: (mode) -> - if stateKey = @getStateKey(@getLoadSettings().initialPaths, mode) + @loadState: -> + if stateKey = @getStateKey(@getLoadSettings().initialPaths) if state = @getStorageFolder().load(stateKey) return state @@ -68,10 +68,8 @@ class Atom extends Model # Returns the path where the state for the current window will be # located if it exists. - @getStateKey: (paths, mode) -> - if mode is 'spec' - 'spec' - else if mode is 'editor' and paths?.length > 0 + @getStateKey: (paths) -> + if paths?.length > 0 sha1 = crypto.createHash('sha1').update(paths.slice().sort().join("\n")).digest('hex') "editor-#{sha1}" else @@ -156,8 +154,9 @@ class Atom extends Model ### # Call .loadOrCreate instead - constructor: (@state) -> - {@mode} = @state + constructor: (@state={}) -> + @state.version ?= @constructor.version + @loadTime = null {devMode, safeMode, resourcePath} = @getLoadSettings() configDirPath = @getConfigDirPath() @@ -779,7 +778,7 @@ class Atom extends Model dialog.showSaveDialog currentWindow, options saveSync: -> - if storageKey = @constructor.getStateKey(@project?.getPaths(), @mode) + if storageKey = @constructor.getStateKey(@project?.getPaths()) @constructor.getStorageFolder().store(storageKey, @state) else @getCurrentWindow().loadSettings.windowState = JSON.stringify(@state) From a87605164bfe0c5221beafd62b8f4db5beffc96f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 1 Oct 2015 16:52:20 -0600 Subject: [PATCH 044/316] Restore test window position after testing setPosition --- spec/atom-spec.coffee | 7 +++++++ spec/spec-helper.coffee | 4 ---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 7fb26f102..b73095805 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -8,6 +8,13 @@ temp = require "temp" describe "the `atom` global", -> describe 'window sizing methods', -> describe '::getPosition and ::setPosition', -> + originalPosition = null + beforeEach -> + originalPosition = atom.getPosition() + + afterEach -> + atom.setPosition(originalPosition.x, originalPosition.y) + it 'sets the position of the window, and can retrieve the position just set', -> atom.setPosition(22, 45) expect(atom.getPosition()).toEqual x: 22, y: 45 diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index fb326caf8..36b4e2a40 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -1,5 +1,4 @@ require '../src/window' -atom.restoreWindowDimensions() require 'jasmine-json' require '../vendor/jasmine-jquery' @@ -31,9 +30,6 @@ commandsToRestore = atom.commands.getSnapshot() styleElementsToRestore = atom.styles.getSnapshot() window.addEventListener 'core:close', -> window.close() -window.addEventListener 'beforeunload', -> - atom.storeWindowDimensions() - atom.saveSync() document.querySelector('html').style.overflow = 'auto' document.body.style.overflow = 'auto' From 6c67f42eab8d76ade80e44dfb2c3387696d89b37 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 11:28:50 -0600 Subject: [PATCH 045/316] Move state loading for Atom environment to an instance method --- spec/atom-spec.coffee | 26 ++++--- spec/spec-helper.coffee | 3 +- src/atom.coffee | 94 +++++++++--------------- src/initialize-application-window.coffee | 5 +- src/initialize-test-window.coffee | 7 +- 5 files changed, 59 insertions(+), 76 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index b73095805..c138e83eb 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -145,29 +145,31 @@ describe "the `atom` global", -> expect(errors).toEqual [] describe "saving and loading", -> - afterEach -> atom.mode = "spec" - it "selects the state based on the current project paths", -> - Atom = atom.constructor + jasmine.unspy(atom, 'saveStateSync') + # jasmine.unspy(atom, 'loadStateSync') + [dir1, dir2] = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")] - loadSettings = _.extend Atom.getLoadSettings(), + loadSettings = _.extend atom.constructor.getLoadSettings(), initialPaths: [dir1] windowState: null - spyOn(Atom, 'getLoadSettings').andCallFake -> loadSettings - spyOn(Atom.getStorageFolder(), 'getPath').andReturn(temp.mkdirSync("storage-dir-")) + spyOn(atom, 'getLoadSettings').andCallFake -> loadSettings + spyOn(atom.getStorageFolder(), 'getPath').andReturn(temp.mkdirSync("storage-dir-")) atom.state.stuff = "cool" atom.project.setPaths([dir1, dir2]) - atom.saveSync.originalValue.call(atom) + atom.saveStateSync() - atom1 = Atom.loadOrCreate() - expect(atom1.state.stuff).toBeUndefined() + atom.state = {} + atom.loadStateSync() + expect(atom.state.stuff).toBeUndefined() loadSettings.initialPaths = [dir2, dir1] - atom2 = Atom.loadOrCreate() - expect(atom2.state.stuff).toBe("cool") + atom.state = {} + atom.loadStateSync() + expect(atom.state.stuff).toBe("cool") describe "openInitialEmptyEditorIfNecessary", -> describe "when there are no paths set", -> @@ -224,7 +226,7 @@ describe "the `atom` global", -> expect(atom.state.workspace).toEqual workspaceState expect(atom.state.grammars).toEqual grammarsState expect(atom.state.project).toEqual projectState - expect(atom.saveSync).toHaveBeenCalled() + expect(atom.saveStateSync).toHaveBeenCalled() describe "::removeEditorWindow()", -> it "unsubscribes from all buffers", -> diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 36b4e2a40..ec06b9087 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -104,7 +104,7 @@ beforeEach -> serializedWindowState = null - spyOn(atom, 'saveSync') + spyOn(atom, 'saveStateSync') atom.grammars.clearGrammarOverrides() spy = spyOn(atom.packages, 'resolvePackagePath').andCallFake (packageName) -> @@ -170,7 +170,6 @@ afterEach -> document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent - jasmine.unspy(atom, 'saveSync') ensureNoPathSubscriptions() waits(0) # yield to ui thread to make screen update more frequently diff --git a/src/atom.coffee b/src/atom.coffee index 090ce4ee3..815063407 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -37,53 +37,6 @@ module.exports = class Atom extends Model @version: 1 # Increment this when the serialization format changes - # Load or create the Atom environment in the given mode. - # - # * `mode` A {String} mode that is either 'editor' or 'spec' depending on the - # kind of environment you want to build. - # - # Returns an Atom instance, fully initialized - @loadOrCreate: -> - startTime = Date.now() - atom = @deserialize(@loadState()) ? new this({@version}) - atom.deserializeTimings.atom = Date.now() - startTime - atom - - # Deserializes the Atom environment from a state object - @deserialize: (state) -> - new this(state) if state?.version is @version - - # Loads and returns the serialized state corresponding to this window - # if it exists; otherwise returns undefined. - @loadState: -> - if stateKey = @getStateKey(@getLoadSettings().initialPaths) - if state = @getStorageFolder().load(stateKey) - return state - - if windowState = @getLoadSettings().windowState - try - JSON.parse(@getLoadSettings().windowState) - catch error - console.warn "Error parsing window state: #{statePath} #{error.stack}", error - - # Returns the path where the state for the current window will be - # located if it exists. - @getStateKey: (paths) -> - if paths?.length > 0 - sha1 = crypto.createHash('sha1').update(paths.slice().sort().join("\n")).digest('hex') - "editor-#{sha1}" - else - null - - # Get the directory path to Atom's configuration area. - # - # Returns the absolute path to ~/.atom - @getConfigDirPath: -> - @configDirPath ?= process.env.ATOM_HOME - - @getStorageFolder: -> - @storageFolder ?= new StorageFolder(@getConfigDirPath()) - # Returns the load settings hash associated with the current window. @getLoadSettings: -> getWindowLoadSettings() @@ -154,8 +107,8 @@ class Atom extends Model ### # Call .loadOrCreate instead - constructor: (@state={}) -> - @state.version ?= @constructor.version + constructor: -> + @state = {version: @constructor.version} @loadTime = null {devMode, safeMode, resourcePath} = @getLoadSettings() @@ -318,12 +271,6 @@ class Atom extends Model isReleasedVersion: -> not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix - # Public: Get the directory path to Atom's configuration area. - # - # Returns the absolute path to `~/.atom`. - getConfigDirPath: -> - @constructor.getConfigDirPath() - # Public: Get the time taken to completely load the current window. # # This time include things like loading and activating packages, creating @@ -586,7 +533,7 @@ class Atom extends Model @state.workspace = @workspace.serialize() @packages.deactivatePackages() @state.packageStates = @packages.packageStates - @saveSync() + @saveStateSync() @windowState = null removeEditorWindow: -> @@ -777,12 +724,41 @@ class Atom extends Model options.defaultPath ?= @project?.getPaths()[0] dialog.showSaveDialog currentWindow, options - saveSync: -> - if storageKey = @constructor.getStateKey(@project?.getPaths()) - @constructor.getStorageFolder().store(storageKey, @state) + saveStateSync: -> + if storageKey = @getStateKey(@project?.getPaths()) + @getStorageFolder().store(storageKey, @state) else @getCurrentWindow().loadSettings.windowState = JSON.stringify(@state) + loadStateSync: -> + startTime = Date.now() + + if stateKey = @getStateKey(@getLoadSettings().initialPaths) + if state = @getStorageFolder().load(stateKey) + @state = state + + if not @state? and windowState = @getLoadSettings().windowState + try + if state = JSON.parse(@getLoadSettings().windowState) + @state = state + catch error + console.warn "Error parsing window state: #{statePath} #{error.stack}", error + + @deserializeTimings.atom = Date.now() - startTime + + getStateKey: (paths) -> + if paths?.length > 0 + sha1 = crypto.createHash('sha1').update(paths.slice().sort().join("\n")).digest('hex') + "editor-#{sha1}" + else + null + + getConfigDirPath: -> + @configDirPath ?= process.env.ATOM_HOME + + getStorageFolder: -> + @storageFolder ?= new StorageFolder(@getConfigDirPath()) + crashMainProcess: -> remote.process.crash() diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 246633179..1646c17a8 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -15,9 +15,10 @@ process.env.NODE_PATH = exportsPath process.env.NODE_ENV ?= 'production' unless devMode Atom = require './atom' -window.atom = Atom.loadOrCreate('editor') +window.atom = new Atom -atom.displayWindow() unless isSpec +atom.displayWindow() +atom.loadStateSync() atom.startEditorWindow() # Workaround for focus getting cleared upon window creation diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 79a1d9c2c..90aa075e6 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -3,10 +3,15 @@ require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') path = require 'path' + +ipc = require 'ipc' +ipc.send('call-window-method', 'openDevTools') + + try require '../src/window' Atom = require '../src/atom' - window.atom = Atom.loadOrCreate('spec') + window.atom = new Atom # Show window synchronously so a focusout doesn't fire on input elements # that are focused in the very first spec run. From 6348d8f07870752c52ee0582c9c51e30fe11e971 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 11:47:00 -0600 Subject: [PATCH 046/316] Remove last Atom static methods --- spec/atom-spec.coffee | 2 +- src/atom.coffee | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index c138e83eb..1d8942e9d 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -151,7 +151,7 @@ describe "the `atom` global", -> [dir1, dir2] = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")] - loadSettings = _.extend atom.constructor.getLoadSettings(), + loadSettings = _.extend atom.getLoadSettings(), initialPaths: [dir1] windowState: null diff --git a/src/atom.coffee b/src/atom.coffee index 815063407..91d9f6e77 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -37,16 +37,6 @@ module.exports = class Atom extends Model @version: 1 # Increment this when the serialization format changes - # Returns the load settings hash associated with the current window. - @getLoadSettings: -> getWindowLoadSettings() - - @updateLoadSetting: (key, value) -> - @getLoadSettings()[key] = value - location.hash = encodeURIComponent(JSON.stringify(@loadSettings)) - - @getCurrentWindow: -> - remote.getCurrentWindow() - workspaceParentSelectorctor: 'body' lastUncaughtError: null @@ -285,7 +275,11 @@ class Atom extends Model # # Returns an {Object} containing all the load setting key/value pairs. getLoadSettings: -> - @constructor.getLoadSettings() + getWindowLoadSettings() + + updateLoadSetting: (key, value) -> + @getLoadSettings()[key] = value + location.hash = encodeURIComponent(JSON.stringify(@loadSettings)) ### Section: Managing The Atom Window @@ -354,7 +348,7 @@ class Atom extends Model # Extended: Get the current window getCurrentWindow: -> - @constructor.getCurrentWindow() + remote.getCurrentWindow() # Extended: Move current window to the center of the screen. center: -> @@ -693,7 +687,7 @@ class Atom extends Model # Notify the browser project of the window's current project path watchProjectPath: -> @disposables.add @project.onDidChangePaths => - @constructor.updateLoadSetting('initialPaths', @project.getPaths()) + @updateLoadSetting('initialPaths', @project.getPaths()) exit: (status) -> app = remote.require('app') From 26f0ef5424ba3e7e45dcb5a9a56f47348119678d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:12:16 -0600 Subject: [PATCH 047/316] Move Project.deserialize to instance method So we can instantiate atom.project during Atom environment construction. Signed-off-by: Max Brunsfeld --- spec/git-spec.coffee | 3 ++- spec/project-spec.coffee | 13 +++++++++---- spec/spec-helper.coffee | 3 ++- spec/workspace-spec.coffee | 4 +++- src/atom.coffee | 4 ++-- src/project.coffee | 40 ++++++++++++++++++-------------------- 6 files changed, 37 insertions(+), 30 deletions(-) diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index a72cd47cd..e627ec520 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -277,7 +277,8 @@ describe "GitRepository", -> atom.workspace.open('file.txt') runs -> - project2 = Project.deserialize(atom.project.serialize()) + project2 = new Project() + project2.deserialize(atom.project.serialize(), atom.deserializers) buffer = project2.getBuffers()[0] waitsFor -> diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 13dd3e70c..3de55a02d 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -66,7 +66,9 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 - deserializedProject = Project.deserialize(atom.project.serialize()) + + deserializedProject = new Project() + deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 0 it "listens for destroyed events on deserialized buffers and removes them when they are destroyed", -> @@ -75,7 +77,8 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 - deserializedProject = Project.deserialize(atom.project.serialize()) + deserializedProject = new Project + deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 1 deserializedProject.getBuffers()[0].destroy() @@ -91,7 +94,8 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 fs.mkdirSync(pathToOpen) - deserializedProject = Project.deserialize(atom.project.serialize()) + deserializedProject = new Project + deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 0 it "does not deserialize buffers when their path is inaccessible", -> @@ -104,7 +108,8 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 fs.chmodSync(pathToOpen, '000') - deserializedProject = Project.deserialize(atom.project.serialize()) + deserializedProject = new Project() + deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 0 describe "when an editor is saved and the project has no path", -> diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index ec06b9087..8764c5eb0 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -85,7 +85,8 @@ beforeEach -> documentTitle = null projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures') atom.packages.serviceHub = new ServiceHub - atom.project = new Project(paths: [projectPath]) + atom.project = new Project + atom.project.setPaths([projectPath]) atom.workspace = new Workspace() atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index c60508640..0dacf7468 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -1,6 +1,7 @@ path = require 'path' temp = require 'temp' Workspace = require '../src/workspace' +Project = require '../src/project' Pane = require '../src/pane' platform = require './spec-helper-platform' _ = require 'underscore-plus' @@ -21,7 +22,8 @@ describe "Workspace", -> projectState = atom.project.serialize() atom.workspace.destroy() atom.project.destroy() - atom.project = atom.deserializers.deserialize(projectState) + atom.project = new Project() + atom.project.deserialize(projectState, atom.deserializers) atom.workspace = Workspace.deserialize(workspaceState) describe "when the workspace contains text editors", -> diff --git a/src/atom.coffee b/src/atom.coffee index 91d9f6e77..2a3831de2 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -652,9 +652,9 @@ class Atom extends Model deserializeProject: -> Project = require './project' - startTime = Date.now() - @project ?= @deserializers.deserialize(@state.project) ? new Project() + @project = new Project() + @project.deserialize(@state.project, @deserializers) if @state.project? @deserializeTimings.project = Date.now() - startTime deserializeWorkspace: -> diff --git a/src/project.coffee b/src/project.coffee index faead038e..45a62c799 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -21,23 +21,10 @@ class Project extends Model Section: Construction and Destruction ### - @deserialize: (state) -> - state.buffers = _.compact state.buffers.map (bufferState) -> - # Check that buffer's file path is accessible - return if fs.isDirectorySync(bufferState.filePath) - if bufferState.filePath - try - fs.closeSync(fs.openSync(bufferState.filePath, 'r')) - catch error - return unless error.code is 'ENOENT' - - atom.deserializers.deserialize(bufferState) - - new this(state) - - constructor: ({path, paths, @buffers}={}) -> + constructor: -> @emitter = new Emitter - @buffers ?= [] + @buffers = [] + @paths = [] @rootDirectories = [] @repositories = [] @@ -68,11 +55,6 @@ class Project extends Model @setPaths(@getPaths()) ) - @subscribeToBuffer(buffer) for buffer in @buffers - - paths ?= _.compact([path]) - @setPaths(paths) - destroyed: -> buffer.destroy() for buffer in @getBuffers() @setPaths([]) @@ -85,6 +67,22 @@ class Project extends Model Section: Serialization ### + deserialize: (state, deserializerManager) -> + states.paths = [state.path] if state.path? # backward compatibility + + @buffers = _.compact state.buffers.map (bufferState) -> + # Check that buffer's file path is accessible + return if fs.isDirectorySync(bufferState.filePath) + if bufferState.filePath + try + fs.closeSync(fs.openSync(bufferState.filePath, 'r')) + catch error + return unless error.code is 'ENOENT' + deserializerManager.deserialize(bufferState) + + @subscribeToBuffer(buffer) for buffer in @buffers + @setPaths(state.paths) + serialize: -> deserializer: 'Project' paths: @getPaths() From d2e6cb0097b7a60273e015d92b301864b035d4ba Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:32:57 -0600 Subject: [PATCH 048/316] Fix updating of load settings Signed-off-by: Max Brunsfeld --- src/atom.coffee | 7 ++++--- src/initialize-application-window.coffee | 2 +- ...settings.coffee => window-load-settings-helpers.coffee} | 6 +++++- 3 files changed, 10 insertions(+), 5 deletions(-) rename src/{get-window-load-settings.coffee => window-load-settings-helpers.coffee} (74%) diff --git a/src/atom.coffee b/src/atom.coffee index 2a3831de2..a68136d02 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -14,7 +14,7 @@ Model = require './model' WindowEventHandler = require './window-event-handler' StylesElement = require './styles-element' StorageFolder = require './storage-folder' -getWindowLoadSettings = require './get-window-load-settings' +{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' Workspace = require './workspace' PaneContainer = require './pane-container' @@ -278,8 +278,9 @@ class Atom extends Model getWindowLoadSettings() updateLoadSetting: (key, value) -> - @getLoadSettings()[key] = value - location.hash = encodeURIComponent(JSON.stringify(@loadSettings)) + loadSettings = @getLoadSettings() + loadSettings[key] = value + setWindowLoadSettings(loadSettings) ### Section: Managing The Atom Window diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 1646c17a8..a10cc9dba 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -2,7 +2,7 @@ path = require 'path' require './window' -getWindowLoadSettings = require './get-window-load-settings' +{getWindowLoadSettings} = require './window-load-settings-helpers' {resourcePath, isSpec, devMode} = getWindowLoadSettings() diff --git a/src/get-window-load-settings.coffee b/src/window-load-settings-helpers.coffee similarity index 74% rename from src/get-window-load-settings.coffee rename to src/window-load-settings-helpers.coffee index 7f41ad05f..1ae76c442 100644 --- a/src/get-window-load-settings.coffee +++ b/src/window-load-settings-helpers.coffee @@ -3,7 +3,7 @@ _ = require 'underscore-plus' windowLoadSettings = null -module.exports = -> +exports.getWindowLoadSettings = -> windowLoadSettings ?= JSON.parse(window.decodeURIComponent(window.location.hash.substr(1))) clone = _.deepClone(windowLoadSettings) @@ -14,3 +14,7 @@ module.exports = -> remote.getCurrentWindow().loadSettings.windowState = value clone + +exports.setWindowLoadSettings = (settings) -> + windowLoadSettings = settings + location.hash = encodeURIComponent(JSON.stringify(settings)) From 3491fa36503890df43f434ebd38398dd2ff0addc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:39:18 -0600 Subject: [PATCH 049/316] Construct Project during Atom environment construction Signed-off-by: Max Brunsfeld --- spec/git-spec.coffee | 2 +- spec/project-spec.coffee | 8 ++++---- spec/spec-helper.coffee | 2 +- spec/workspace-spec.coffee | 2 +- src/atom.coffee | 15 +++++++-------- src/project.coffee | 10 +++++----- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index e627ec520..9359499bc 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -277,7 +277,7 @@ describe "GitRepository", -> atom.workspace.open('file.txt') runs -> - project2 = new Project() + project2 = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) project2.deserialize(atom.project.serialize(), atom.deserializers) buffer = project2.getBuffers()[0] diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 3de55a02d..ce93a791e 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -67,7 +67,7 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 - deserializedProject = new Project() + deserializedProject = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 0 @@ -77,7 +77,7 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 - deserializedProject = new Project + deserializedProject = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 1 @@ -94,7 +94,7 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 fs.mkdirSync(pathToOpen) - deserializedProject = new Project + deserializedProject = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 0 @@ -108,7 +108,7 @@ describe "Project", -> runs -> expect(atom.project.getBuffers().length).toBe 1 fs.chmodSync(pathToOpen, '000') - deserializedProject = new Project() + deserializedProject = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) deserializedProject.deserialize(atom.project.serialize(), atom.deserializers) expect(deserializedProject.getBuffers().length).toBe 0 diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 8764c5eb0..f239d546a 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -85,7 +85,7 @@ beforeEach -> documentTitle = null projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures') atom.packages.serviceHub = new ServiceHub - atom.project = new Project + atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) atom.project.setPaths([projectPath]) atom.workspace = new Workspace() atom.themes.workspace = atom.workspace diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 0dacf7468..3c650554c 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -22,7 +22,7 @@ describe "Workspace", -> projectState = atom.project.serialize() atom.workspace.destroy() atom.project.destroy() - atom.project = new Project() + atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) atom.project.deserialize(projectState, atom.deserializers) atom.workspace = Workspace.deserialize(workspaceState) diff --git a/src/atom.coffee b/src/atom.coffee index a68136d02..e6f92eee8 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -160,6 +160,9 @@ class Atom extends Model GrammarRegistry = require './grammar-registry' @grammars = new GrammarRegistry({@config}) + Project = require './project' + @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm}) + setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -651,13 +654,6 @@ class Atom extends Model false - deserializeProject: -> - Project = require './project' - startTime = Date.now() - @project = new Project() - @project.deserialize(@state.project, @deserializers) if @state.project? - @deserializeTimings.project = Date.now() - startTime - deserializeWorkspace: -> Workspace = require './workspace' @@ -679,7 +675,6 @@ class Atom extends Model @grammars.grammarOverridesByPath = grammarOverridesByPath @deserializePackageStates() - @deserializeProject() @deserializeWorkspace() loadThemes: -> @@ -741,6 +736,10 @@ class Atom extends Model @deserializeTimings.atom = Date.now() - startTime + startTime = Date.now() + @project.deserialize(@state.project, @deserializers) if @state.project? + @deserializeTimings.project = Date.now() - startTime + getStateKey: (paths) -> if paths?.length > 0 sha1 = crypto.createHash('sha1').update(paths.slice().sort().join("\n")).digest('hex') diff --git a/src/project.coffee b/src/project.coffee index 45a62c799..2a60ff7d5 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -21,7 +21,7 @@ class Project extends Model Section: Construction and Destruction ### - constructor: -> + constructor: ({@confirm, @notificationManager, packageManager}) -> @emitter = new Emitter @buffers = [] @paths = [] @@ -30,7 +30,7 @@ class Project extends Model @directoryProviders = [] @defaultDirectoryProvider = new DefaultDirectoryProvider() - atom.packages.serviceHub.consume( + packageManager.serviceHub.consume( 'atom.directory-provider', '^0.1.0', (provider) => @directoryProviders.unshift(provider)) @@ -42,7 +42,7 @@ class Project extends Model @repositoryPromisesByPath = new Map() @repositoryProviders = [new GitRepositoryProvider(this)] - atom.packages.serviceHub.consume( + packageManager.serviceHub.consume( 'atom.repository-provider', '^0.1.0', (provider) => @@ -417,9 +417,9 @@ class Project extends Model subscribeToBuffer: (buffer) -> buffer.onDidDestroy => @removeBuffer(buffer) - buffer.onWillThrowWatchError ({error, handle}) -> + buffer.onWillThrowWatchError ({error, handle}) => handle() - atom.notifications.addWarning """ + @notificationManager.addWarning """ Unable to read file after file `#{error.eventType}` event. Make sure you have permission to access `#{buffer.getPath()}`. """, From a3e1b34e954c2379c1bc0078f18c68451a85fa49 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:53:06 -0600 Subject: [PATCH 050/316] Add reload and toggle dev tools key bindings to test window Signed-off-by: Max Brunsfeld --- src/initialize-test-window.coffee | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 90aa075e6..5fa3dca3c 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -1,14 +1,10 @@ # Start the crash reporter before anything else. require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') -path = require 'path' - - -ipc = require 'ipc' -ipc.send('call-window-method', 'openDevTools') - - try + path = require 'path' + ipc = require 'ipc' + require '../src/window' Atom = require '../src/atom' window.atom = new Atom @@ -17,6 +13,15 @@ try # that are focused in the very first spec run. atom.getCurrentWindow().show() unless atom.getLoadSettings().headless + window.addEventListener 'keydown', (event) -> + # Reload: cmd-r / ctrl-r + if (event.metaKey or event.ctrlKey) and event.keyCode is 82 + ipc.send('call-window-method', 'restart') + + # Toggle Dev Tools: cmd-alt-i / ctrl-alt-i + if (event.metaKey or event.ctrlKey) and event.altKey and event.keyCode is 73 + ipc.send('call-window-method', 'toggleDevTools') + # Add 'exports' to module search path. exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports') require('module').globalPaths.push(exportsPath) From d0e1505a0f477cc59218bdd84dc0eb0f9cafdcb4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:53:23 -0600 Subject: [PATCH 051/316] Inline deserializePackageStates into loadStateSync Signed-off-by: Max Brunsfeld --- src/atom.coffee | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index e6f92eee8..a6624c5bb 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -666,15 +666,10 @@ class Atom extends Model @keymaps.defaultTarget = workspaceElement document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) - deserializePackageStates: -> - @packages.packageStates = @state.packageStates ? {} - delete @state.packageStates - deserializeEditorWindow: -> if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath @grammars.grammarOverridesByPath = grammarOverridesByPath - @deserializePackageStates() @deserializeWorkspace() loadThemes: -> @@ -736,6 +731,8 @@ class Atom extends Model @deserializeTimings.atom = Date.now() - startTime + @packages.packageStates = @state.packageStates ? {} + startTime = Date.now() @project.deserialize(@state.project, @deserializers) if @state.project? @deserializeTimings.project = Date.now() - startTime From 3d5f6c858d3d6ceb84946f41933bac325392942d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:54:23 -0600 Subject: [PATCH 052/316] Move grammar override assignment into loadStateSync Signed-off-by: Max Brunsfeld --- src/atom.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index a6624c5bb..f494e6114 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -667,9 +667,6 @@ class Atom extends Model document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) deserializeEditorWindow: -> - if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath - @grammars.grammarOverridesByPath = grammarOverridesByPath - @deserializeWorkspace() loadThemes: -> @@ -731,6 +728,9 @@ class Atom extends Model @deserializeTimings.atom = Date.now() - startTime + if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath + @grammars.grammarOverridesByPath = grammarOverridesByPath + @packages.packageStates = @state.packageStates ? {} startTime = Date.now() From 4a00d6ba35b30c514aed21997f338288c494cdeb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 12:56:15 -0600 Subject: [PATCH 053/316] Bind cmd/ctrl-w to close window in tests Signed-off-by: Max Brunsfeld --- src/initialize-test-window.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 5fa3dca3c..ad854d89a 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -22,6 +22,10 @@ try if (event.metaKey or event.ctrlKey) and event.altKey and event.keyCode is 73 ipc.send('call-window-method', 'toggleDevTools') + # Reload: cmd-w / ctrl-w + if (event.metaKey or event.ctrlKey) and event.keyCode is 87 + ipc.send('call-window-method', 'close') + # Add 'exports' to module search path. exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports') require('module').globalPaths.push(exportsPath) From fd7fbbfea524b56b785e693b7804a9262ecd7158 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 13:42:36 -0600 Subject: [PATCH 054/316] Move PaneContainer.deserialize to an instance method Signed-off-by: Max Brunsfeld --- spec/pane-container-element-spec.coffee | 14 ++++---- spec/pane-container-spec.coffee | 44 +++++++++++++++---------- spec/pane-element-spec.coffee | 4 +-- spec/pane-spec.coffee | 21 +++++++----- src/pane-container.coffee | 31 +++++++---------- src/workspace.coffee | 6 ++-- 6 files changed, 63 insertions(+), 57 deletions(-) diff --git a/spec/pane-container-element-spec.coffee b/spec/pane-container-element-spec.coffee index 890baec38..46a8fbdbb 100644 --- a/spec/pane-container-element-spec.coffee +++ b/spec/pane-container-element-spec.coffee @@ -42,7 +42,7 @@ describe "PaneContainerElement", -> ] it "transfers focus to the next pane if a focused pane is removed", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) containerElement = atom.views.getView(container) leftPane = container.getActivePane() leftPaneElement = atom.views.getView(leftPane) @@ -58,10 +58,10 @@ describe "PaneContainerElement", -> describe "when a pane is split", -> it "builds appropriately-oriented atom-pane-axis elements", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) containerElement = atom.views.getView(container) - pane1 = container.getRoot() + pane1 = container.getActivePane() pane2 = pane1.splitRight() pane3 = pane2.splitDown() @@ -84,7 +84,7 @@ describe "PaneContainerElement", -> [container, containerElement] = [] beforeEach -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) containerElement = atom.views.getView(container) document.querySelector('#jasmine-content').appendChild(containerElement) @@ -201,7 +201,7 @@ describe "PaneContainerElement", -> [leftPane, rightPane] = [] beforeEach -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) leftPane = container.getActivePane() rightPane = leftPane.splitRight() @@ -252,8 +252,8 @@ describe "PaneContainerElement", -> element.tabIndex = -1 element - container = new PaneContainer - pane1 = container.getRoot() + container = new PaneContainer(config: atom.config) + pane1 = container.getActivePane() pane1.activateItem(buildElement('1')) pane4 = pane1.splitDown(items: [buildElement('4')]) pane7 = pane4.splitDown(items: [buildElement('7')]) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 58e159279..f577c3ba2 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -12,8 +12,9 @@ describe "PaneContainer", -> @deserialize: -> new this serialize: -> deserializer: 'Item' - pane1A = new Pane(items: [new Item]) - containerA = new PaneContainer(root: pane1A) + containerA = new PaneContainer(config: atom.config) + pane1A = containerA.getActivePane() + pane1A.addItem(new Item) pane2A = pane1A.splitRight(items: [new Item]) pane3A = pane2A.splitDown(items: [new Item]) pane3A.focus() @@ -21,7 +22,8 @@ describe "PaneContainer", -> it "preserves the focused pane across serialization", -> expect(pane3A.focused).toBe true - containerB = PaneContainer.deserialize(containerA.serialize()) + containerB = new PaneContainer(config: atom.config) + containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(pane3B.focused).toBe true @@ -29,7 +31,8 @@ describe "PaneContainer", -> pane3A.activate() expect(containerA.getActivePane()).toBe pane3A - containerB = PaneContainer.deserialize(containerA.serialize()) + containerB = new PaneContainer(config: atom.config) + containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(containerB.getActivePane()).toBe pane3B @@ -37,7 +40,8 @@ describe "PaneContainer", -> pane3A.activate() state = containerA.serialize() state.activePaneId = -22 - containerB = atom.deserializers.deserialize(state) + containerB = new PaneContainer(config: atom.config) + containerB.deserialize(state, atom.deserializers) expect(containerB.getActivePane()).toBe containerB.getPanes()[0] describe "if there are empty panes after deserialization", -> @@ -47,7 +51,8 @@ describe "PaneContainer", -> describe "if the 'core.destroyEmptyPanes' config option is false (the default)", -> it "leaves the empty panes intact", -> state = containerA.serialize() - containerB = atom.deserializers.deserialize(state) + containerB = new PaneContainer(config: atom.config) + containerB.deserialize(state, atom.deserializers) [leftPane, column] = containerB.getRoot().getChildren() [topPane, bottomPane] = column.getChildren() @@ -60,14 +65,15 @@ describe "PaneContainer", -> atom.config.set('core.destroyEmptyPanes', true) state = containerA.serialize() - containerB = atom.deserializers.deserialize(state) + containerB = new PaneContainer(config: atom.config) + containerB.deserialize(state, atom.deserializers) [leftPane, rightPane] = containerB.getRoot().getChildren() expect(leftPane.getItems().length).toBe 1 expect(rightPane.getItems().length).toBe 1 it "does not allow the root pane to be destroyed", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) container.getRoot().destroy() expect(container.getRoot()).toBeDefined() expect(container.getRoot().isDestroyed()).toBe false @@ -76,7 +82,7 @@ describe "PaneContainer", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) pane1 = container.getRoot() it "returns the first pane if no pane has been made active", -> @@ -105,7 +111,8 @@ describe "PaneContainer", -> [container, pane1, pane2, observed] = [] beforeEach -> - container = new PaneContainer(root: new Pane(items: [new Object, new Object])) + container = new PaneContainer(config: atom.config) + container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object, new Object]) [pane1, pane2] = container.getPanes() @@ -124,7 +131,7 @@ describe "PaneContainer", -> describe "::observePanes()", -> it "invokes observers with all current and future panes", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() @@ -138,7 +145,8 @@ describe "PaneContainer", -> describe "::observePaneItems()", -> it "invokes observers with all current and future pane items", -> - container = new PaneContainer(root: new Pane(items: [new Object, new Object])) + container = new PaneContainer(config: atom.config) + container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object]) [pane1, pane2] = container.getPanes() observed = [] @@ -157,7 +165,7 @@ describe "PaneContainer", -> shouldPromptToSave: -> true getURI: -> 'test' - container = new PaneContainer + container = new PaneContainer(config: atom.config) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() pane1.addItem(new TestItem) @@ -177,7 +185,7 @@ describe "PaneContainer", -> describe "::onDidAddPane(callback)", -> it "invokes the given callback when panes are added", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) events = [] container.onDidAddPane (event) -> events.push(event) @@ -194,7 +202,7 @@ describe "PaneContainer", -> destroy: -> @_isDestroyed = true isDestroyed: -> @_isDestroyed - container = new PaneContainer + container = new PaneContainer(config: atom.config) events = [] container.onWillDestroyPane (event) -> itemsDestroyed = (item.isDestroyed() for item in event.pane.getItems()) @@ -210,7 +218,7 @@ describe "PaneContainer", -> describe "::onDidDestroyPane(callback)", -> it "invokes the given callback when panes are destroyed", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) events = [] container.onDidDestroyPane (event) -> events.push(event) @@ -225,7 +233,7 @@ describe "PaneContainer", -> describe "::onWillDestroyPaneItem() and ::onDidDestroyPaneItem", -> it "invokes the given callbacks when an item will be destroyed on any pane", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) pane1 = container.getRoot() item1 = new Object item2 = new Object @@ -252,7 +260,7 @@ describe "PaneContainer", -> describe "::saveAll()", -> it "saves all open pane items", -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) pane1 = container.getRoot() pane2 = pane1.splitRight() diff --git a/spec/pane-element-spec.coffee b/spec/pane-element-spec.coffee index 40712ce90..e20068bfc 100644 --- a/spec/pane-element-spec.coffee +++ b/spec/pane-element-spec.coffee @@ -4,8 +4,8 @@ describe "PaneElement", -> [paneElement, container, pane] = [] beforeEach -> - container = new PaneContainer - pane = container.getRoot() + container = new PaneContainer(config: atom.config) + pane = container.getActivePane() paneElement = atom.views.getView(pane) describe "when the pane's active status changes", -> diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index d293a6d2c..8f18b6199 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -38,8 +38,8 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(root: new Pane) - container.getRoot().splitRight() + container = new PaneContainer(config: atom.config) + container.getActivePane().splitRight() [pane1, pane2] = container.getPanes() it "changes the active pane on the container", -> @@ -107,8 +107,9 @@ describe "Pane", -> it "throws an exception if the item is already present on a pane", -> item = new Item("A") - pane1 = new Pane(items: [item]) - container = new PaneContainer(root: pane1) + container = new PaneContainer(config: atom.config) + pane1 = container.getActivePane() + pane1.addItem(item) pane2 = pane1.splitRight() expect(-> pane2.addItem(item)).toThrow() @@ -501,8 +502,9 @@ describe "Pane", -> [item1, item2, item3, item4, item5] = [] beforeEach -> - pane1 = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - container = new PaneContainer(root: pane1) + container = new PaneContainer(config: atom.config) + pane1 = container.getActivePane() + pane1.addItems([new Item("A"), new Item("B"), new Item("C")]) pane2 = pane1.splitRight(items: [new Item("D"), new Item("E")]) [item1, item2, item3] = pane1.getItems() [item4, item5] = pane2.getItems() @@ -553,8 +555,9 @@ describe "Pane", -> [pane1, container] = [] beforeEach -> - pane1 = new Pane(items: [new Item("A")]) - container = new PaneContainer(root: pane1) + container = new PaneContainer(config: atom.config) + pane1 = container.getActivePane() + pane1.addItem(new Item("A")) describe "::splitLeft(params)", -> describe "when the parent is the container root", -> @@ -685,7 +688,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer + container = new PaneContainer(config: atom.config) pane1 = container.root pane1.addItems([new Item("A"), new Item("B")]) pane2 = pane1.splitRight() diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 18f6166c0..60537424d 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -7,42 +7,35 @@ ItemRegistry = require './item-registry' module.exports = class PaneContainer extends Model - @version: 1 - + serializationVersion: 1 root: null - @deserialize: (state) -> - container = Object.create(@prototype) # allows us to pass a self reference to our child before invoking constructor - state.root = atom.deserializers.deserialize(state.root, {container}) - state.destroyEmptyPanes = atom.config.get('core.destroyEmptyPanes') - state.activePane = find state.root.getPanes(), (pane) -> pane.id is state.activePaneId - @call(container, state) # run constructor - container - constructor: (params) -> super - @activePane = params?.activePane - + @config = params.config @emitter = new Emitter @subscriptions = new CompositeDisposable - @itemRegistry = new ItemRegistry - @setRoot(params?.root ? new Pane) - @setActivePane(@getPanes()[0]) unless @getActivePane() - - @destroyEmptyPanes() if params?.destroyEmptyPanes - + @setRoot(new Pane(container: this)) + @setActivePane(@getRoot()) @monitorActivePaneItem() @monitorPaneItems() serialize: (params) -> deserializer: 'PaneContainer' - version: @constructor.version + version: @serializationVersion root: @root?.serialize() activePaneId: @activePane.id + deserialize: (state, deserializerManager) -> + return unless state.version is @serializationVersion + @setRoot(deserializerManager.deserialize(state.root, {container: this})) + activePane = find @getRoot().getPanes(), (pane) -> pane.id is state.activePaneId + @setActivePane(activePane ? @getPanes()[0]) + @destroyEmptyPanes() if @config.get('core.destroyEmptyPanes') + onDidChangeRoot: (fn) -> @emitter.on 'did-change-root', fn diff --git a/src/workspace.coffee b/src/workspace.coffee index c8bbdc0c8..ef684f54e 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -32,7 +32,9 @@ class Workspace extends Model for packageName in state.packagesWithActiveGrammars ? [] atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync() - state.paneContainer = PaneContainer.deserialize(state.paneContainer) + paneContainer = new PaneContainer(config: atom.config) + paneContainer.deserialize(state.paneContainer, atom.deserializers) + state.paneContainer = paneContainer new this(state) constructor: (params) -> @@ -45,7 +47,7 @@ class Workspace extends Model @emitter = new Emitter @openers = [] - @paneContainer ?= new PaneContainer() + @paneContainer ?= new PaneContainer(config: atom.config) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @directorySearchers = [] From 156cdfaf31d86af26a5c3502ae1dd1be2f653a2d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 16:18:51 -0600 Subject: [PATCH 055/316] Move Workspace.deserialize to an instance method Signed-off-by: Max Brunsfeld --- spec/spec-helper.coffee | 7 ++- spec/workspace-spec.coffee | 43 +++++++++---- src/atom.coffee | 39 +++++++++++- src/workspace.coffee | 120 ++++++++++++++----------------------- 4 files changed, 122 insertions(+), 87 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index f239d546a..97bcbf04b 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -87,7 +87,12 @@ beforeEach -> atom.packages.serviceHub = new ServiceHub atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) atom.project.setPaths([projectPath]) - atom.workspace = new Workspace() + atom.workspace = new Workspace({ + config: atom.config, project: atom.project, packageManager: atom.packages, + grammarRegistry: atom.grammars, notificationManager: atom.notifications, + setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), + setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion() + }) atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) atom.commands.restoreSnapshot(commandsToRestore) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 3c650554c..b0b32e33b 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -9,11 +9,17 @@ fstream = require 'fstream' fs = require 'fs-plus' describe "Workspace", -> - workspace = null + [workspace, setDocumentEdited] = [] beforeEach -> + setDocumentEdited = jasmine.createSpy('setDocumentEdited') atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) - atom.workspace = workspace = new Workspace + atom.workspace = workspace = new Workspace({ + config: atom.config, project: atom.project, packageManager: atom.packages, + grammarRegistry: atom.grammars, notificationManager: atom.notifications, + setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + }) waits(1) describe "serialization", -> @@ -24,7 +30,13 @@ describe "Workspace", -> atom.project.destroy() atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) atom.project.deserialize(projectState, atom.deserializers) - atom.workspace = Workspace.deserialize(workspaceState) + atom.workspace = new Workspace({ + config: atom.config, project: atom.project, packageManager: atom.packages, + grammarRegistry: atom.grammars, notificationManager: atom.notifications, + setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + }) + atom.workspace.deserialize(workspaceState, atom.deserializers) describe "when the workspace contains text editors", -> it "constructs the view with the same panes", -> @@ -616,7 +628,13 @@ describe "Workspace", -> spyOn(jsPackage, 'loadGrammarsSync') spyOn(coffeePackage, 'loadGrammarsSync') - workspace2 = Workspace.deserialize(state) + workspace2 = new Workspace({ + config: atom.config, project: atom.project, packageManager: atom.packages, + grammarRegistry: atom.grammars, notificationManager: atom.notifications, + setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + }) + workspace2.deserialize(state, atom.deserializers) expect(jsPackage.loadGrammarsSync.callCount).toBe 1 expect(coffeePackage.loadGrammarsSync.callCount).toBe 1 @@ -668,7 +686,13 @@ describe "Workspace", -> it "updates the title to contain the project's path", -> document.title = null - workspace2 = Workspace.deserialize(atom.workspace.serialize()) + workspace2 = new Workspace({ + config: atom.config, project: atom.project, packageManager: atom.packages, + grammarRegistry: atom.grammars, notificationManager: atom.notifications, + setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + }) + workspace2.deserialize(atom.workspace.serialize(), atom.deserializers) item = atom.workspace.getActivePaneItem() expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPaths()[0]} - Atom" workspace2.destroy() @@ -681,15 +705,14 @@ describe "Workspace", -> waitsForPromise -> atom.workspace.open('b') runs -> [item1, item2] = atom.workspace.getPaneItems() - spyOn(atom, 'setDocumentEdited') - it "calls atom.setDocumentEdited when the active item changes", -> + it "calls setDocumentEdited when the active item changes", -> expect(atom.workspace.getActivePaneItem()).toBe item2 item1.insertText('a') expect(item1.isModified()).toBe true atom.workspace.getActivePane().activateNextItem() - expect(atom.setDocumentEdited).toHaveBeenCalledWith(true) + expect(setDocumentEdited).toHaveBeenCalledWith(true) it "calls atom.setDocumentEdited when the active item's modified status changes", -> expect(atom.workspace.getActivePaneItem()).toBe item2 @@ -697,13 +720,13 @@ describe "Workspace", -> advanceClock(item2.getBuffer().getStoppedChangingDelay()) expect(item2.isModified()).toBe true - expect(atom.setDocumentEdited).toHaveBeenCalledWith(true) + expect(setDocumentEdited).toHaveBeenCalledWith(true) item2.undo() advanceClock(item2.getBuffer().getStoppedChangingDelay()) expect(item2.isModified()).toBe false - expect(atom.setDocumentEdited).toHaveBeenCalledWith(false) + expect(setDocumentEdited).toHaveBeenCalledWith(false) describe "adding panels", -> class TestItem diff --git a/src/atom.coffee b/src/atom.coffee index f494e6114..2a52cc317 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -17,6 +17,8 @@ StorageFolder = require './storage-folder' {getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' Workspace = require './workspace' +PanelContainer = require './panel-container' +Panel = require './panel' PaneContainer = require './pane-container' PaneAxis = require './pane-axis' Pane = require './pane' @@ -24,9 +26,13 @@ Project = require './project' TextEditor = require './text-editor' TextBuffer = require 'text-buffer' Gutter = require './gutter' -PaneElement = require './pane-element' + +WorkspaceElement = require './workspace-element' +PanelContainerElement = require './panel-container-element' +PanelElement = require './panel-element' PaneContainerElement = require './pane-container-element' PaneAxisElement = require './pane-axis-element' +PaneElement = require './pane-element' TextEditorElement = require './text-editor-element' {createGutterView} = require './gutter-component-helpers' @@ -163,6 +169,14 @@ class Atom extends Model Project = require './project' @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm}) + @workspace = new Workspace({ + @config, @project, packageManager: @packages, grammarRegistry: @grammars, + notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), + setDocumentEdited: @setDocumentEdited.bind(this), atomVersion: @getVersion() + }) + + @registerDefaultOpeners() + setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -176,6 +190,12 @@ class Atom extends Model @deserializers.add(TextBuffer) registerViewProviders: -> + @views.addViewProvider Workspace, (model) -> + new WorkspaceElement().initialize(model) + @views.addViewProvider PanelContainer, (model) -> + new PanelContainerElement().initialize(model) + @views.addViewProvider Panel, (model) -> + new PanelElement().initialize(model) @views.addViewProvider PaneContainer, (model) -> new PaneContainerElement().initialize(model) @views.addViewProvider PaneAxis, (model) -> @@ -186,6 +206,18 @@ class Atom extends Model new TextEditorElement().initialize(model) @views.addViewProvider(Gutter, createGutterView) + registerDefaultOpeners: -> + @workspace.addOpener (filePath) -> + switch filePath + when 'atom://.atom/stylesheet' + @project.open(@styles.getUserStyleSheetPath()) + when 'atom://.atom/keymap' + @project.open(@keymaps.getUserKeymapPath()) + when 'atom://.atom/config' + @project.open(@config.getUserConfigPath()) + when 'atom://.atom/init-script' + @project.open(@getUserInitScriptPath()) + reset: -> @config.reset() @setConfigSchema() @@ -531,6 +563,7 @@ class Atom extends Model @state.workspace = @workspace.serialize() @packages.deactivatePackages() @state.packageStates = @packages.packageStates + @state.fullScreen = @isFullScreen() @saveStateSync() @windowState = null @@ -658,7 +691,7 @@ class Atom extends Model Workspace = require './workspace' startTime = Date.now() - @workspace = Workspace.deserialize(@state.workspace) ? new Workspace + @workspace.deserialize(@state.workspace, @deserializers) @themes.workspace = @workspace @deserializeTimings.workspace = Date.now() - startTime @@ -731,6 +764,8 @@ class Atom extends Model if grammarOverridesByPath = @state.grammars?.grammarOverridesByPath @grammars.grammarOverridesByPath = grammarOverridesByPath + @setFullScreen(@state.fullScreen) + @packages.packageStates = @state.packageStates ? {} startTime = Date.now() diff --git a/src/workspace.coffee b/src/workspace.coffee index ef684f54e..76af92119 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -9,10 +9,7 @@ TextEditor = require './text-editor' PaneContainer = require './pane-container' Pane = require './pane' Panel = require './panel' -PanelElement = require './panel-element' PanelContainer = require './panel-container' -PanelContainerElement = require './panel-container-element' -WorkspaceElement = require './workspace-element' Task = require './task' # Essential: Represents the state of the user interface for the entire window. @@ -26,33 +23,22 @@ Task = require './task' # module.exports = class Workspace extends Model - @deserialize: (state) -> - return unless state? - - for packageName in state.packagesWithActiveGrammars ? [] - atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync() - - paneContainer = new PaneContainer(config: atom.config) - paneContainer.deserialize(state.paneContainer, atom.deserializers) - state.paneContainer = paneContainer - new this(state) - constructor: (params) -> super - @paneContainer = params?.paneContainer - @fullScreen = params?.fullScreen ? false - @destroyedItemURIs = params?.destroyedItemURIs ? [] + {@packageManager, @config, @project, @grammarRegistry, @notificationManager} = params + {@setRepresentedFilename, @setDocumentEdited, @atomVersion} = params @emitter = new Emitter @openers = [] + @destroyedItemURIs = [] - @paneContainer ?= new PaneContainer(config: atom.config) + @paneContainer = new PaneContainer(config: @config) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @directorySearchers = [] @defaultDirectorySearcher = new DefaultDirectorySearcher() - atom.packages.serviceHub.consume( + @packageManager.serviceHub.consume( 'atom.directory-searcher', '^0.1.0', (provider) => @directorySearchers.unshift(provider)) @@ -65,53 +51,39 @@ class Workspace extends Model modal: new PanelContainer({location: 'modal'}) @subscribeToActiveItem() - - @addOpener (filePath) -> - switch filePath - when 'atom://.atom/stylesheet' - atom.project.open(atom.styles.getUserStyleSheetPath()) - when 'atom://.atom/keymap' - atom.project.open(atom.keymaps.getUserKeymapPath()) - when 'atom://.atom/config' - atom.project.open(atom.config.getUserConfigPath()) - when 'atom://.atom/init-script' - atom.project.open(atom.getUserInitScriptPath()) - - atom.views.addViewProvider Workspace, (model) -> - new WorkspaceElement().initialize(model) - - atom.views.addViewProvider PanelContainer, (model) -> - new PanelContainerElement().initialize(model) - - atom.views.addViewProvider Panel, (model) -> - new PanelElement().initialize(model) - @subscribeToFontSize() # Called by the Serializable mixin during serialization. serialize: -> deserializer: 'Workspace' paneContainer: @paneContainer.serialize() - fullScreen: atom.isFullScreen() packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars() + destroyedItemURIs: @destroyedItemURIs.slice() + + deserialize: (state, deserializerManager) -> + for packageName in state.packagesWithActiveGrammars ? [] + @packageManager.getLoadedPackage(packageName)?.loadGrammarsSync() + if state.destroyedItemURIs? + @destroyedItemURIs = state.destroyedItemURIs + @paneContainer.deserialize(state.paneContainer, deserializerManager) getPackageNamesWithActiveGrammars: -> packageNames = [] - addGrammar = ({includedGrammarScopes, packageName}={}) -> + addGrammar = ({includedGrammarScopes, packageName}={}) => return unless packageName # Prevent cycles return if packageNames.indexOf(packageName) isnt -1 packageNames.push(packageName) for scopeName in includedGrammarScopes ? [] - addGrammar(atom.grammars.grammarForScopeName(scopeName)) + addGrammar(@grammarRegistry.grammarForScopeName(scopeName)) return editors = @getTextEditors() addGrammar(editor.getGrammar()) for editor in editors if editors.length > 0 - for grammar in atom.grammars.getGrammars() when grammar.injectionSelector + for grammar in @grammarRegistry.getGrammars() when grammar.injectionSelector addGrammar(grammar) _.uniq(packageNames) @@ -120,13 +92,13 @@ class Workspace extends Model installShellCommands: -> CommandInstaller = require('./command-installer') - commandInstaller = new CommandInstaller(atom.getVersion()) + commandInstaller = new CommandInstaller(@atomVersion) commandInstaller.installShellCommandsInteractively() subscribeToActiveItem: -> @updateWindowTitle() @updateDocumentEdited() - atom.project.onDidChangePaths @updateWindowTitle + @project.onDidChangePaths @updateWindowTitle @observeActivePaneItem (item) => @updateWindowTitle() @@ -156,7 +128,7 @@ class Workspace extends Model # open. updateWindowTitle: => appName = 'Atom' - projectPaths = atom.project?.getPaths() ? [] + projectPaths = @project.getPaths() ? [] if item = @getActivePaneItem() itemPath = item.getPath?() itemTitle = item.getTitle?() @@ -167,19 +139,19 @@ class Workspace extends Model if item? and projectPath? document.title = "#{itemTitle} - #{projectPath} - #{appName}" - atom.setRepresentedFilename(itemPath ? projectPath) + @setRepresentedFilename(itemPath ? projectPath) else if projectPath? document.title = "#{projectPath} - #{appName}" - atom.setRepresentedFilename(projectPath) + @setRepresentedFilename(projectPath) else document.title = "#{itemTitle} - #{appName}" - atom.setRepresentedFilename("") + @setRepresentedFilename("") # On OS X, fades the application window's proxy icon when the current file # has been modified. updateDocumentEdited: => modified = @getActivePaneItem()?.isModified?() ? false - atom.setDocumentEdited(modified) + @setDocumentEdited(modified) ### Section: Event Subscription @@ -377,7 +349,7 @@ class Workspace extends Model open: (uri, options={}) -> searchAllPanes = options.searchAllPanes split = options.split - uri = atom.project.resolvePath(uri) + uri = @project.resolvePath(uri) pane = @paneContainer.paneForURI(uri) if searchAllPanes pane ?= switch split @@ -410,11 +382,11 @@ class Workspace extends Model {initialLine, initialColumn} = options activatePane = options.activatePane ? true - uri = atom.project.resolvePath(uri) + uri = @project.resolvePath(uri) item = @getActivePane().itemForURI(uri) if uri item ?= opener(uri, options) for opener in @getOpeners() when not item - item ?= atom.project.openSync(uri, {initialLine, initialColumn}) + item ?= @project.openSync(uri, {initialLine, initialColumn}) @getActivePane().activateItem(item) @itemOpened(item) @@ -429,16 +401,16 @@ class Workspace extends Model item ?= opener(uri, options) for opener in @getOpeners() when not item try - item ?= atom.project.open(uri, options) + item ?= @project.open(uri, options) catch error switch error.code when 'CANCELLED' return Promise.resolve() when 'EACCES' - atom.notifications.addWarning("Permission denied '#{error.path}'") + @notificationManager.addWarning("Permission denied '#{error.path}'") return Promise.resolve() when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL' - atom.notifications.addWarning("Unable to open '#{error.path ? uri}'", detail: error.message) + @notificationManager.addWarning("Unable to open '#{error.path ? uri}'", detail: error.message) return Promise.resolve() else throw error @@ -617,20 +589,20 @@ class Workspace extends Model # Increase the editor font size by 1px. increaseFontSize: -> - atom.config.set("editor.fontSize", atom.config.get("editor.fontSize") + 1) + @config.set("editor.fontSize", @config.get("editor.fontSize") + 1) # Decrease the editor font size by 1px. decreaseFontSize: -> - fontSize = atom.config.get("editor.fontSize") - atom.config.set("editor.fontSize", fontSize - 1) if fontSize > 1 + fontSize = @config.get("editor.fontSize") + @config.set("editor.fontSize", fontSize - 1) if fontSize > 1 # Restore to the window's original editor font size. resetFontSize: -> if @originalFontSize - atom.config.set("editor.fontSize", @originalFontSize) + @config.set("editor.fontSize", @originalFontSize) subscribeToFontSize: -> - atom.config.onDidChange 'editor.fontSize', ({oldValue}) => + @config.onDidChange 'editor.fontSize', ({oldValue}) => @originalFontSize ?= oldValue # Removes the item's uri from the list of potential items to reopen. @@ -807,7 +779,7 @@ class Workspace extends Model # Find a searcher for every Directory in the project. Each searcher that is matched # will be associated with an Array of Directory objects in the Map. directoriesForSearcher = new Map() - for directory in atom.project.getDirectories() + for directory in @project.getDirectories() searcher = @defaultDirectorySearcher for directorySearcher in @directorySearchers if directorySearcher.canSearchDirectory(directory) @@ -838,15 +810,15 @@ class Workspace extends Model # Kick off all of the searches and unify them into one Promise. allSearches = [] - directoriesForSearcher.forEach (directories, searcher) -> + directoriesForSearcher.forEach (directories, searcher) => searchOptions = inclusions: options.paths or [] includeHidden: true - excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths') - exclusions: atom.config.get('core.ignoredNames') - follow: atom.config.get('core.followSymlinks') - didMatch: (result) -> - iterator(result) unless atom.project.isPathModified(result.filePath) + excludeVcsIgnores: @config.get('core.excludeVcsIgnoredPaths') + exclusions: @config.get('core.ignoredNames') + follow: @config.get('core.followSymlinks') + didMatch: (result) => + iterator(result) unless @project.isPathModified(result.filePath) didError: (error) -> iterator(null, error) didSearchPaths: (count) -> onPathsSearched(searcher, count) @@ -854,9 +826,9 @@ class Workspace extends Model allSearches.push(directorySearcher) searchPromise = Promise.all(allSearches) - for buffer in atom.project.getBuffers() when buffer.isModified() + for buffer in @project.getBuffers() when buffer.isModified() filePath = buffer.getPath() - continue unless atom.project.contains(filePath) + continue unless @project.contains(filePath) matches = [] buffer.scan regex, (match) -> matches.push match iterator {filePath, matches} if matches.length > 0 @@ -902,8 +874,8 @@ class Workspace extends Model # # Returns a `Promise`. replace: (regex, replacementText, filePaths, iterator) -> - new Promise (resolve, reject) -> - openPaths = (buffer.getPath() for buffer in atom.project.getBuffers()) + new Promise (resolve, reject) => + openPaths = (buffer.getPath() for buffer in @project.getBuffers()) outOfProcessPaths = _.difference(filePaths, openPaths) inProcessFinished = not openPaths.length @@ -922,7 +894,7 @@ class Workspace extends Model task.on 'replace:path-replaced', iterator task.on 'replace:file-error', (error) -> iterator(null, error) - for buffer in atom.project.getBuffers() + for buffer in @project.getBuffers() continue unless buffer.getPath() in filePaths replacements = buffer.replace(regex, replacementText, iterator) iterator({filePath: buffer.getPath(), replacements}) if replacements From 8436715b02f2c4d6f22c217f2e9b21991ed152bb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 16:25:59 -0600 Subject: [PATCH 056/316] Deserialize Workspace in atom.loadStateSync --- src/atom.coffee | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 2a52cc317..dc1f857e6 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -174,6 +174,7 @@ class Atom extends Model notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), setDocumentEdited: @setDocumentEdited.bind(this), atomVersion: @getVersion() }) + @themes.workspace = @workspace @registerDefaultOpeners() @@ -539,7 +540,10 @@ class Atom extends Model @windowEventHandler = new WindowEventHandler(this) @packages.loadPackages() - @deserializeEditorWindow() + + workspaceElement = @views.getView(@workspace) + @keymaps.defaultTarget = workspaceElement + document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) @watchProjectPath() @@ -688,19 +692,7 @@ class Atom extends Model false deserializeWorkspace: -> - Workspace = require './workspace' - startTime = Date.now() - @workspace.deserialize(@state.workspace, @deserializers) - @themes.workspace = @workspace - @deserializeTimings.workspace = Date.now() - startTime - - workspaceElement = @views.getView(@workspace) - @keymaps.defaultTarget = workspaceElement - document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) - - deserializeEditorWindow: -> - @deserializeWorkspace() loadThemes: -> @themes.load() @@ -772,6 +764,10 @@ class Atom extends Model @project.deserialize(@state.project, @deserializers) if @state.project? @deserializeTimings.project = Date.now() - startTime + startTime = Date.now() + @workspace.deserialize(@state.workspace, @deserializers) if @state.workspace? + @deserializeTimings.workspace = Date.now() - startTime + getStateKey: (paths) -> if paths?.length > 0 sha1 = crypto.createHash('sha1').update(paths.slice().sort().join("\n")).digest('hex') @@ -800,7 +796,7 @@ class Atom extends Model try require(userInitScriptPath) if fs.isFileSync(userInitScriptPath) catch error - atom.notifications.addError "Failed to load `#{userInitScriptPath}`", + @notifications.addError "Failed to load `#{userInitScriptPath}`", detail: error.message dismissable: true From eb68c9135e6a5fd16066d4b741c2010bc03b1de9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 2 Oct 2015 15:45:01 -0700 Subject: [PATCH 057/316] Don't use atom global in default commands Signed-off-by: Nathan Sobo --- spec/command-installer-spec.coffee | 3 ++- src/atom.coffee | 13 +++++++------ src/command-installer.coffee | 6 +++--- src/register-default-commands.coffee | 17 +++++++++-------- src/workspace.coffee | 7 +------ 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/spec/command-installer-spec.coffee b/spec/command-installer-spec.coffee index 972494ec3..584dc193e 100644 --- a/spec/command-installer-spec.coffee +++ b/spec/command-installer-spec.coffee @@ -22,7 +22,8 @@ describe "CommandInstaller on #darwin", -> describe "when using a stable version of atom", -> beforeEach -> - installer = new CommandInstaller("2.0.2") + confirm = -> + installer = new CommandInstaller("2.0.2", confirm) it "symlinks the atom command as 'atom'", -> installedAtomPath = path.join(installationPath, 'atom') diff --git a/src/atom.coffee b/src/atom.coffee index dc1f857e6..242cb4960 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -140,7 +140,7 @@ class Atom extends Model CommandRegistry = require './command-registry' @commands = new CommandRegistry registerDefaultCommands = require './register-default-commands' - registerDefaultCommands(@commands) + registerDefaultCommands(this) PackageManager = require './package-manager' @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config}) @@ -169,10 +169,13 @@ class Atom extends Model Project = require './project' @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm}) + CommandInstaller = require './command-installer' + @commandInstaller = new CommandInstaller(@getVersion(), @confirm.bind(this)) + @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), - setDocumentEdited: @setDocumentEdited.bind(this), atomVersion: @getVersion() + setDocumentEdited: @setDocumentEdited.bind(this) }) @themes.workspace = @workspace @@ -527,11 +530,9 @@ class Atom extends Model startEditorWindow: -> @installUncaughtErrorHandler() - CommandInstaller = require './command-installer' - commandInstaller = new CommandInstaller(@getVersion()) - commandInstaller.installAtomCommand false, (error) -> + @commandInstaller.installAtomCommand false, (error) -> console.warn error.message if error? - commandInstaller.installApmCommand false, (error) -> + @commandInstaller.installApmCommand false, (error) -> console.warn error.message if error? @config.load() diff --git a/src/command-installer.coffee b/src/command-installer.coffee index 729aef84c..b224d531f 100644 --- a/src/command-installer.coffee +++ b/src/command-installer.coffee @@ -26,7 +26,7 @@ symlinkCommandWithPrivilegeSync = (sourcePath, destinationPath) -> module.exports = class CommandInstaller - constructor: (@appVersion) -> + constructor: (@appVersion, @confirm) -> getInstallDirectory: -> "/usr/local/bin" @@ -36,7 +36,7 @@ class CommandInstaller installShellCommandsInteractively: -> showErrorDialog = (error) -> - atom.confirm + @confirm message: "Failed to install shell commands" detailedMessage: error.message @@ -48,7 +48,7 @@ class CommandInstaller if error? showErrorDialog(error) else - atom.confirm + @confirm message: "Commands installed." detailedMessage: "The shell commands `atom` and `apm` are installed." diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index 44c8e287c..df633b8a5 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -1,7 +1,7 @@ ipc = require 'ipc' -module.exports = (commandRegistry) -> - commandRegistry.add 'atom-workspace', +module.exports = (atom) -> + atom.commands.add 'atom-workspace', 'pane:show-next-item': -> @getModel().getActivePane().activateNextItem() 'pane:show-previous-item': -> @getModel().getActivePane().activatePreviousItem() 'pane:show-item-1': -> @getModel().getActivePane().activateItemAtIndex(0) @@ -61,9 +61,10 @@ module.exports = (commandRegistry) -> 'core:save-as': -> @getModel().saveActivePaneItemAs() if process.platform is 'darwin' - commandRegistry.add 'atom-workspace', 'window:install-shell-commands', -> @getModel().installShellCommands() + atom.commands.add 'atom-workspace', 'window:install-shell-commands', -> + atom.commandInstaller.installShellCommandsInteractively() - commandRegistry.add 'atom-pane', + atom.commands.add 'atom-pane', 'pane:save-items': -> @getModel().saveItems() 'pane:split-left': -> @getModel().splitLeft(copyActiveItem: true) 'pane:split-right': -> @getModel().splitRight(copyActiveItem: true) @@ -74,7 +75,7 @@ module.exports = (commandRegistry) -> 'pane:increase-size': -> @getModel().increaseSize() 'pane:decrease-size': -> @getModel().decreaseSize() - commandRegistry.add 'atom-text-editor', stopEventPropagation( + atom.commands.add 'atom-text-editor', stopEventPropagation( 'core:undo': -> @undo() 'core:redo': -> @redo() 'core:move-left': -> @moveLeft() @@ -115,7 +116,7 @@ module.exports = (commandRegistry) -> 'editor:select-line': -> @selectLinesContainingCursors() ) - commandRegistry.add 'atom-text-editor', stopEventPropagationAndGroupUndo( + atom.commands.add 'atom-text-editor', stopEventPropagationAndGroupUndo( 'core:backspace': -> @backspace() 'core:delete': -> @delete() 'core:cut': -> @cutSelectedText() @@ -138,7 +139,7 @@ module.exports = (commandRegistry) -> 'editor:copy-selection': -> @copyOnlySelectedText() ) - commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagation( + atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagation( 'core:move-up': -> @moveUp() 'core:move-down': -> @moveDown() 'core:move-to-top': -> @moveToTop() @@ -175,7 +176,7 @@ module.exports = (commandRegistry) -> 'editor:scroll-to-cursor': -> @scrollToCursorPosition() ) - commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo( + atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo( 'editor:indent': -> @indent() 'editor:auto-indent': -> @autoIndentSelectedRows() 'editor:indent-selected-rows': -> @indentSelectedRows() diff --git a/src/workspace.coffee b/src/workspace.coffee index 76af92119..b7c46f0d4 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -27,7 +27,7 @@ class Workspace extends Model super {@packageManager, @config, @project, @grammarRegistry, @notificationManager} = params - {@setRepresentedFilename, @setDocumentEdited, @atomVersion} = params + {@setRepresentedFilename, @setDocumentEdited} = params @emitter = new Emitter @openers = [] @@ -90,11 +90,6 @@ class Workspace extends Model editorAdded: (editor) -> - installShellCommands: -> - CommandInstaller = require('./command-installer') - commandInstaller = new CommandInstaller(@atomVersion) - commandInstaller.installShellCommandsInteractively() - subscribeToActiveItem: -> @updateWindowTitle() @updateDocumentEdited() From ed735c115b2165ce4b1fcda141ef74297aeaf6e7 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 2 Oct 2015 15:54:10 -0700 Subject: [PATCH 058/316] Fix typo in package manager Signed-off-by: Nathan Sobo --- 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 c75268339..9b382d093 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -475,7 +475,7 @@ class PackageManager loadPackageMetadata: (packagePath, ignoreErrors=false) -> packageName = path.basename(packagePath) if @isBundledPackagePath(packagePath) - metadata = packagesCache[packageName]?.metadata + metadata = @packagesCache[packageName]?.metadata unless metadata? if metadataPath = CSON.resolve(path.join(packagePath, 'package')) try From 77825e9d415a2bae7310e0f1bf8c5fe785171a55 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 2 Oct 2015 16:38:25 -0700 Subject: [PATCH 059/316] Wait for async service consumption in workspace spec Signed-off-by: Nathan Sobo --- spec/workspace-spec.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index b0b32e33b..6b93e1eea 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -1095,6 +1095,9 @@ describe "Workspace", -> search: (directory, regex, options) -> fakeSearch = new FakeSearch(options) }) + waitsFor -> + atom.workspace.directorySearchers.length > 0 + it "can override the DefaultDirectorySearcher on a per-directory basis", -> foreignFilePath = 'ssh://foreign-directory:8080/hello.txt' numPathsSearchedInDir2 = 1 From eb2ace37b4ed05fd8d24a35fdfac18423340dcd7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 21:13:42 -0600 Subject: [PATCH 060/316] Move TextEditor construction to Workspace Signed-off-by: Max Brunsfeld --- spec/project-spec.coffee | 22 +++++++-------- spec/text-editor-component-spec.coffee | 4 +-- spec/text-editor-spec.coffee | 27 ++++++++++-------- spec/tokenized-buffer-spec.coffee | 8 +++--- spec/tokenized-line-spec.coffee | 2 +- spec/workspace-spec.coffee | 10 +++---- src/atom.coffee | 12 ++++---- src/project.coffee | 39 -------------------------- src/workspace.coffee | 31 +++++++++++++++++++- 9 files changed, 74 insertions(+), 81 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index ce93a791e..7e7925904 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -73,7 +73,7 @@ describe "Project", -> it "listens for destroyed events on deserialized buffers and removes them when they are destroyed", -> waitsForPromise -> - atom.project.open('a') + atom.workspace.open('a') runs -> expect(atom.project.getBuffers().length).toBe 1 @@ -89,7 +89,7 @@ describe "Project", -> pathToOpen = path.join(temp.mkdirSync(), 'file.txt') waitsForPromise -> - atom.project.open(pathToOpen) + atom.workspace.open(pathToOpen) runs -> expect(atom.project.getBuffers().length).toBe 1 @@ -103,7 +103,7 @@ describe "Project", -> fs.writeFileSync(pathToOpen, '') waitsForPromise -> - atom.project.open(pathToOpen) + atom.workspace.open(pathToOpen) runs -> expect(atom.project.getBuffers().length).toBe 1 @@ -120,7 +120,7 @@ describe "Project", -> editor = null waitsForPromise -> - atom.project.open().then (o) -> editor = o + atom.workspace.open().then (o) -> editor = o runs -> editor.saveAs(tempFile) @@ -130,7 +130,7 @@ describe "Project", -> editor = null beforeEach -> waitsForPromise -> - atom.project.open(require.resolve('./fixtures/dir/a')).then (o) -> editor = o + atom.workspace.open(require.resolve('./fixtures/dir/a')).then (o) -> editor = o it "creates a warning notification", -> atom.notifications.onDidAddNotification noteSpy = jasmine.createSpy() @@ -161,7 +161,7 @@ describe "Project", -> it "returns a new edit session for the given path and emits 'buffer-created'", -> editor = null waitsForPromise -> - atom.project.open(absolutePath).then (o) -> editor = o + atom.workspace.open(absolutePath).then (o) -> editor = o runs -> expect(editor.buffer.getPath()).toBe absolutePath @@ -171,7 +171,7 @@ describe "Project", -> it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created'", -> editor = null waitsForPromise -> - atom.project.open(absolutePath).then (o) -> editor = o + atom.workspace.open(absolutePath).then (o) -> editor = o runs -> expect(editor.buffer.getPath()).toBe absolutePath @@ -182,17 +182,17 @@ describe "Project", -> editor = null waitsForPromise -> - atom.project.open(absolutePath).then (o) -> editor = o + atom.workspace.open(absolutePath).then (o) -> editor = o runs -> newBufferHandler.reset() waitsForPromise -> - atom.project.open(absolutePath).then ({buffer}) -> + atom.workspace.open(absolutePath).then ({buffer}) -> expect(buffer).toBe editor.buffer waitsForPromise -> - atom.project.open('a').then ({buffer}) -> + atom.workspace.open('a').then ({buffer}) -> expect(buffer).toBe editor.buffer expect(newBufferHandler).not.toHaveBeenCalled() @@ -200,7 +200,7 @@ describe "Project", -> it "returns a new edit session and emits 'buffer-created'", -> editor = null waitsForPromise -> - atom.project.open().then (o) -> editor = o + atom.workspace.open().then (o) -> editor = o runs -> expect(editor.buffer.getPath()).toBeUndefined() diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 27e9864aa..836516759 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -27,7 +27,7 @@ describe "TextEditorComponent", -> fn() waitsForPromise -> - atom.project.open('sample.js').then (o) -> editor = o + atom.workspace.open('sample.js').then (o) -> editor = o runs -> contentNode = document.querySelector('#jasmine-content') @@ -3194,7 +3194,7 @@ describe "TextEditorComponent", -> waitsForPromise -> atom.packages.activatePackage('language-coffee-script') waitsForPromise -> - atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o + atom.workspace.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o afterEach: -> atom.packages.deactivatePackages() diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index e95818900..6d29073e1 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -12,7 +12,7 @@ describe "TextEditor", -> beforeEach -> waitsForPromise -> - atom.project.open('sample.js', autoIndent: false).then (o) -> editor = o + atom.workspace.open('sample.js', autoIndent: false).then (o) -> editor = o runs -> buffer = editor.buffer @@ -27,7 +27,7 @@ describe "TextEditor", -> editor1 = null waitsForPromise -> - atom.project.open(pathToOpen).then (o) -> editor1 = o + atom.workspace.open(pathToOpen).then (o) -> editor1 = o runs -> fs.mkdirSync(pathToOpen) @@ -71,7 +71,7 @@ describe "TextEditor", -> editor = null waitsForPromise -> - atom.workspace.open('sample.js', largeFileMode: true).then (o) -> editor = o + atom.workspace.openTextFile('sample.js', largeFileMode: true).then (o) -> editor = o runs -> buffer = editor.getBuffer() @@ -1331,7 +1331,7 @@ describe "TextEditor", -> waitsForPromise -> atom.packages.activatePackage('language-coffee-script') waitsForPromise -> - atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o + atom.workspace.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o it 'selects the correct surrounding word for the given scoped setting', -> coffeeEditor.setCursorBufferPosition [0, 9] # in the middle of quicksort @@ -1533,7 +1533,7 @@ describe "TextEditor", -> it "takes atomic tokens into account", -> waitsForPromise -> - atom.project.open('sample-with-tabs-and-leading-comment.coffee', autoIndent: false).then (o) -> editor = o + atom.workspace.open('sample-with-tabs-and-leading-comment.coffee', autoIndent: false).then (o) -> editor = o runs -> editor.setSelectedBufferRange([[2, 1], [2, 3]]) @@ -1644,7 +1644,7 @@ describe "TextEditor", -> it "takes atomic tokens into account", -> waitsForPromise -> - atom.project.open('sample-with-tabs-and-leading-comment.coffee', autoIndent: false).then (o) -> editor = o + atom.workspace.open('sample-with-tabs-and-leading-comment.coffee', autoIndent: false).then (o) -> editor = o runs -> editor.setSelectedBufferRange([[3, 1], [3, 2]]) @@ -1769,9 +1769,11 @@ describe "TextEditor", -> it "does not share selections between different edit sessions for the same buffer", -> editor2 = null waitsForPromise -> - atom.project.open('sample.js').then (o) -> editor2 = o + atom.workspace.getActivePane().splitRight() + atom.workspace.open(editor.getPath()).then (o) => editor2 = o runs -> + expect(editor2.getText()).toBe(editor.getText()) editor.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) editor2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]]) expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges() @@ -3673,7 +3675,7 @@ describe "TextEditor", -> editor.destroy() waitsForPromise -> - atom.project.open('sample-with-tabs-and-leading-comment.coffee').then (o) -> editor = o + atom.workspace.open('sample-with-tabs-and-leading-comment.coffee').then (o) -> editor = o runs -> expect(editor.softTabs).toBe true @@ -3746,7 +3748,7 @@ describe "TextEditor", -> editor.destroy() waitsForPromise -> - atom.project.open('sample-with-tabs-and-leading-comment.coffee').then (o) -> editor = o + atom.workspace.open('sample-with-tabs-and-leading-comment.coffee').then (o) -> editor = o runs -> expect(editor.softTabs).toBe true @@ -3801,7 +3803,7 @@ describe "TextEditor", -> waitsForPromise -> atom.packages.activatePackage('language-coffee-script') waitsForPromise -> - atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o + atom.workspace.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o afterEach: -> atom.packages.deactivatePackages() @@ -4004,7 +4006,7 @@ describe "TextEditor", -> waitsForPromise -> atom.packages.activatePackage('language-coffee-script') waitsForPromise -> - atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o + atom.workspace.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o runs -> atom.config.set('editor.autoIndent', true, scopeSelector: '.source.js') @@ -4154,7 +4156,8 @@ describe "TextEditor", -> editor2 = null waitsForPromise -> - atom.project.open('sample.js', autoIndent: false).then (o) -> editor2 = o + atom.workspace.getActivePane().splitRight() + atom.workspace.open('sample.js', autoIndent: false).then (o) -> editor2 = o runs -> expect(editor.shouldPromptToSave()).toBeFalsy() diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index 4945b37ec..601064887 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -487,7 +487,7 @@ describe "TokenizedBuffer", -> tokenizedHandler = jasmine.createSpy("tokenized handler") waitsForPromise -> - atom.project.open('sample.js').then (o) -> editor = o + atom.workspace.open('sample.js').then (o) -> editor = o runs -> tokenizedBuffer = editor.displayBuffer.tokenizedBuffer @@ -500,7 +500,7 @@ describe "TokenizedBuffer", -> tokenizedHandler = jasmine.createSpy("tokenized handler") waitsForPromise -> - atom.project.open('sample.js').then (o) -> editor = o + atom.workspace.open('sample.js').then (o) -> editor = o runs -> tokenizedBuffer = editor.displayBuffer.tokenizedBuffer @@ -518,7 +518,7 @@ describe "TokenizedBuffer", -> tokenizedHandler = jasmine.createSpy("tokenized handler") waitsForPromise -> - atom.project.open('coffee.coffee').then (o) -> editor = o + atom.workspace.open('coffee.coffee').then (o) -> editor = o runs -> tokenizedBuffer = editor.displayBuffer.tokenizedBuffer @@ -905,7 +905,7 @@ describe "TokenizedBuffer", -> registration = atom.packages.onDidTriggerActivationHook('language-javascript:grammar-used', -> called = true) waitsForPromise -> - atom.project.open('sample.js', autoIndent: false).then (o) -> + atom.workspace.open('sample.js', autoIndent: false).then (o) -> editor = o waitsForPromise -> diff --git a/spec/tokenized-line-spec.coffee b/spec/tokenized-line-spec.coffee index 2914ec089..f1dce7b9e 100644 --- a/spec/tokenized-line-spec.coffee +++ b/spec/tokenized-line-spec.coffee @@ -7,7 +7,7 @@ describe "TokenizedLine", -> describe "::isOnlyWhitespace()", -> beforeEach -> waitsForPromise -> - atom.project.open('coffee.coffee').then (o) -> editor = o + atom.workspace.open('coffee.coffee').then (o) -> editor = o it "returns true when the line is only whitespace", -> expect(editor.tokenizedLineForScreenRow(3).isOnlyWhitespace()).toBe true diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 6b93e1eea..8341e011a 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -981,7 +981,7 @@ describe "Workspace", -> results = [] waitsForPromise -> - atom.project.open('a').then (o) -> + atom.workspace.open('a').then (o) -> editor = o editor.setText("Elephant") @@ -999,7 +999,7 @@ describe "Workspace", -> results = [] waitsForPromise -> - atom.project.open(temp.openSync().path).then (o) -> + atom.workspace.open(temp.openSync().path).then (o) -> editor = o editor.setText("Elephant") @@ -1221,7 +1221,7 @@ describe "Workspace", -> results = [] waitsForPromise -> - atom.project.open('sample.js').then (o) -> editor = o + atom.workspace.open('sample.js').then (o) -> editor = o runs -> expect(editor.isModified()).toBeFalsy() @@ -1242,7 +1242,7 @@ describe "Workspace", -> results = [] waitsForPromise -> - atom.project.open('sample-with-comments.js').then (o) -> editor = o + atom.workspace.open('sample-with-comments.js').then (o) -> editor = o waitsForPromise -> atom.workspace.replace /items/gi, 'items', [commentFilePath], (result) -> @@ -1257,7 +1257,7 @@ describe "Workspace", -> results = [] waitsForPromise -> - atom.project.open('sample.js').then (o) -> editor = o + atom.workspace.open('sample.js').then (o) -> editor = o runs -> editor.buffer.setTextInRange([[0, 0], [0, 0]], 'omg') diff --git a/src/atom.coffee b/src/atom.coffee index 242cb4960..712477fa2 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -211,16 +211,16 @@ class Atom extends Model @views.addViewProvider(Gutter, createGutterView) registerDefaultOpeners: -> - @workspace.addOpener (filePath) -> - switch filePath + @workspace.addOpener (uri) -> + switch uri when 'atom://.atom/stylesheet' - @project.open(@styles.getUserStyleSheetPath()) + @workspace.open(@styles.getUserStyleSheetPath()) when 'atom://.atom/keymap' - @project.open(@keymaps.getUserKeymapPath()) + @workspace.open(@keymaps.getUserKeymapPath()) when 'atom://.atom/config' - @project.open(@config.getUserConfigPath()) + @workspace.open(@config.getUserConfigPath()) when 'atom://.atom/init-script' - @project.open(@getUserInitScriptPath()) + @workspace.open(@getUserInitScriptPath()) reset: -> @config.reset() diff --git a/src/project.coffee b/src/project.coffee index 2a60ff7d5..6532b4aa5 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -287,40 +287,6 @@ class Project extends Model Section: Private ### - # Given a path to a file, this constructs and associates a new - # {TextEditor}, showing the file. - # - # * `filePath` The {String} path of the file to associate with. - # * `options` Options that you can pass to the {TextEditor} constructor. - # - # Returns a promise that resolves to an {TextEditor}. - open: (filePath, options={}) -> - filePath = @resolvePath(filePath) - - if filePath? - try - fs.closeSync(fs.openSync(filePath, 'r')) - catch error - # allow ENOENT errors to create an editor for paths that dont exist - throw error unless error.code is 'ENOENT' - - absoluteFilePath = @resolvePath(filePath) - - fileSize = fs.getSizeSync(absoluteFilePath) - - if fileSize >= 20 * 1048576 # 20MB - choice = atom.confirm - message: 'Atom will be unresponsive during the loading of very large files.' - detailedMessage: "Do you still want to load this file?" - buttons: ["Proceed", "Cancel"] - if choice is 1 - error = new Error - error.code = 'CANCELLED' - throw error - - @bufferForPath(absoluteFilePath).then (buffer) => - @buildEditorForBuffer(buffer, _.extend({fileSize}, options)) - # Retrieves all the {TextBuffer}s in the project; that is, the # buffers for all open files. # @@ -400,11 +366,6 @@ class Project extends Model [buffer] = @buffers.splice(index, 1) buffer?.destroy() - buildEditorForBuffer: (buffer, editorOptions) -> - largeFileMode = editorOptions.fileSize >= 2 * 1048576 # 2MB - editor = new TextEditor(_.extend({buffer, largeFileMode, registerEditor: true}, editorOptions)) - editor - eachBuffer: (args...) -> subscriber = args.shift() if args.length > 1 callback = args.shift() diff --git a/src/workspace.coffee b/src/workspace.coffee index b7c46f0d4..51910f90f 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -396,7 +396,7 @@ class Workspace extends Model item ?= opener(uri, options) for opener in @getOpeners() when not item try - item ?= @project.open(uri, options) + item ?= @openTextFile(uri, options) catch error switch error.code when 'CANCELLED' @@ -431,6 +431,35 @@ class Workspace extends Model @emitter.emit 'did-open', {uri, pane, item, index} item + openTextFile: (uri, options) -> + filePath = @project.resolvePath(uri) + + if filePath? + try + fs.closeSync(fs.openSync(filePath, 'r')) + catch error + # allow ENOENT errors to create an editor for paths that dont exist + throw error unless error.code is 'ENOENT' + + fileSize = fs.getSizeSync(filePath) + + largeFileMode = fileSize >= 2 * 1048576 # 2MB + if fileSize >= 20 * 1048576 # 20MB + choice = atom.confirm + message: 'Atom will be unresponsive during the loading of very large files.' + detailedMessage: "Do you still want to load this file?" + buttons: ["Proceed", "Cancel"] + if choice is 1 + error = new Error + error.code = 'CANCELLED' + throw error + + @project.bufferForPath(filePath, options).then (buffer) => + @buildTextEditor(_.extend({buffer, largeFileMode}, options)) + + buildTextEditor: (params) -> + new TextEditor(params) + # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. # From 3d118b8a330a827ae0d1899823922af11775ee56 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 21:20:35 -0600 Subject: [PATCH 061/316] Pass atom environment as second arg when deserializing objects --- src/atom.coffee | 2 +- src/deserializer-manager.coffee | 13 +++++++------ src/pane-axis.coffee | 9 ++++++--- src/pane.coffee | 3 +-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 712477fa2..3ccff0fd5 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -114,7 +114,7 @@ class Atom extends Model @disposables = new CompositeDisposable DeserializerManager = require './deserializer-manager' - @deserializers = new DeserializerManager() + @deserializers = new DeserializerManager(this) @deserializeTimings = {} @registerDeserializers() diff --git a/src/deserializer-manager.coffee b/src/deserializer-manager.coffee index 62c7e4401..29c7fd59d 100644 --- a/src/deserializer-manager.coffee +++ b/src/deserializer-manager.coffee @@ -21,7 +21,7 @@ # ``` module.exports = class DeserializerManager - constructor: -> + constructor: (@atomEnvironment) -> @deserializers = {} # Public: Register the given class(es) as deserializers. @@ -29,7 +29,10 @@ class DeserializerManager # * `deserializers` One or more deserializers to register. A deserializer can # be any object with a `.name` property and a `.deserialize()` method. A # common approach is to register a *constructor* as the deserializer for its - # instances by adding a `.deserialize()` class method. + # instances by adding a `.deserialize()` class method. When your method is + # called, it will be passed serialized state as the first argument and the + # {Atom} environment object as the second argument, which is useful if you + # wish to avoid referencing the `atom` global. add: (deserializers...) -> @deserializers[deserializer.name] = deserializer for deserializer in deserializers new Disposable => @@ -39,15 +42,13 @@ class DeserializerManager # Public: Deserialize the state and params. # # * `state` The state {Object} to deserialize. - # * `params` The params {Object} to pass as the second arguments to the - # deserialize method of the deserializer. - deserialize: (state, params) -> + deserialize: (state) -> return unless state? if deserializer = @get(state) stateVersion = state.get?('version') ? state.version return if deserializer.version? and deserializer.version isnt stateVersion - deserializer.deserialize(state, params) + deserializer.deserialize(state, @atomEnvironment) else console.warn "No deserializer found for", state diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 3bb4e285e..eb1aa6258 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -11,10 +11,10 @@ class PaneAxis extends Model @deserialize: (state, params) -> container = params?.container state.container = container - state.children = state.children.map (childState) -> atom.deserializers.deserialize(childState, {container}) + state.children = state.children.map (childState) -> atom.deserializers.deserialize(childState) new this(state) - constructor: ({@container, @orientation, children, flexScale}={}) -> + constructor: ({@orientation, children, flexScale}={}) -> @emitter = new Emitter @subscriptionsByChild = new WeakMap @subscriptions = new CompositeDisposable @@ -41,7 +41,10 @@ class PaneAxis extends Model getContainer: -> @container - setContainer: (@container) -> @container + setContainer: (container) -> + if container and container isnt @container + @container = container + child.setContainer(container) for child in @children getOrientation: -> @orientation diff --git a/src/pane.coffee b/src/pane.coffee index 45577dab7..98d1c2493 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -29,7 +29,6 @@ class Pane extends Model constructor: (params) -> super - @container = params?.container @activeItem = params?.activeItem @focused = params?.focused @@ -59,7 +58,7 @@ class Pane extends Model getContainer: -> @container setContainer: (container) -> - unless container is @container + if container and container isnt @container @container = container container.didAddPane({pane: this}) From 51abab930d53b8153d19e3b810b286cc12f7c81a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 21:38:02 -0600 Subject: [PATCH 062/316] Parameterize config on editor instead of using global atom.config --- spec/random-editor-spec.coffee | 4 +-- spec/selection-spec.coffee | 2 +- spec/text-editor-element-spec.coffee | 6 ++--- spec/text-editor-presenter-spec.coffee | 4 +-- spec/text-editor-spec.coffee | 15 ++++++------ src/text-editor-element.coffee | 2 +- src/text-editor.coffee | 34 +++++++++++++++++--------- src/workspace.coffee | 2 +- 8 files changed, 39 insertions(+), 30 deletions(-) diff --git a/spec/random-editor-spec.coffee b/spec/random-editor-spec.coffee index d235ebc25..3924a8412 100644 --- a/spec/random-editor-spec.coffee +++ b/spec/random-editor-spec.coffee @@ -15,7 +15,7 @@ describe "TextEditor", -> it "properly renders soft-wrapped lines when randomly mutated", -> times 10, (i) -> buffer = new TextBuffer - editor = new TextEditor({buffer}) + editor = atom.workspace.buildTextEditor({buffer}) editor.setEditorWidthInChars(80) tokenizedBuffer = editor.displayBuffer.tokenizedBuffer steps = [] @@ -80,7 +80,7 @@ describe "TextEditor", -> text getReferenceScreenLines = -> - referenceEditor = new TextEditor({}) + referenceEditor = atom.workspace.buildTextEditor() referenceEditor.setEditorWidthInChars(80) referenceEditor.setText(editor.getText()) referenceEditor.setSoftWrapped(editor.isSoftWrapped()) diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index e81f7906f..ec40e32cc 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -5,7 +5,7 @@ describe "Selection", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - editor = new TextEditor(buffer: buffer, tabLength: 2) + editor = atom.workspace.buildTextEditor(buffer: buffer, tabLength: 2) selection = editor.getLastSelection() afterEach -> diff --git a/spec/text-editor-element-spec.coffee b/spec/text-editor-element-spec.coffee index 148199425..251c178e7 100644 --- a/spec/text-editor-element-spec.coffee +++ b/spec/text-editor-element-spec.coffee @@ -33,7 +33,7 @@ describe "TextEditorElement", -> describe "when the model is assigned", -> it "adds the 'mini' attribute if .isMini() returns true on the model", -> element = new TextEditorElement - model = new TextEditor(mini: true) + model = atom.workspace.buildTextEditor(mini: true) element.setModel(model) expect(element.hasAttribute('mini')).toBe true @@ -67,7 +67,7 @@ describe "TextEditorElement", -> describe "when the editor is detached from the DOM and then reattached", -> it "does not render duplicate line numbers", -> - editor = new TextEditor + editor = atom.workspace.buildTextEditor() editor.setText('1\n2\n3') element = atom.views.getView(editor) @@ -80,7 +80,7 @@ describe "TextEditorElement", -> expect(element.shadowRoot.querySelectorAll('.line-number').length).toBe initialCount it "does not render duplicate decorations in custom gutters", -> - editor = new TextEditor + editor = atom.workspace.buildTextEditor() editor.setText('1\n2\n3') editor.addGutter({name: 'test-gutter'}) marker = editor.markBufferRange([[0, 0], [2, 0]]) diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 453196858..bc60da469 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -17,7 +17,7 @@ describe "TextEditorPresenter", -> spyOn(window, "clearInterval").andCallFake window.fakeClearInterval buffer = new TextBuffer(filePath: require.resolve('./fixtures/sample.js')) - editor = new TextEditor({buffer}) + editor = atom.workspace.buildTextEditor({buffer}) waitsForPromise -> buffer.load() afterEach -> @@ -2804,7 +2804,7 @@ describe "TextEditorPresenter", -> performSetup = -> buffer = new TextBuffer - editor = new TextEditor({buffer}) + editor = atom.workspace.buildTextEditor({buffer}) editor.setEditorWidthInChars(80) presenterParams = model: editor diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index 6d29073e1..e3eb5eb6d 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -31,7 +31,7 @@ describe "TextEditor", -> runs -> fs.mkdirSync(pathToOpen) - expect(TextEditor.deserialize(editor1.serialize())).toBeUndefined() + expect(TextEditor.deserialize(editor1.serialize(), atom)).toBeUndefined() it "restores selections and folds based on markers in the buffer", -> editor.setSelectedBufferRange([[1, 2], [3, 4]]) @@ -39,7 +39,7 @@ describe "TextEditor", -> editor.foldBufferRow(4) expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() - editor2 = TextEditor.deserialize(editor.serialize()) + editor2 = TextEditor.deserialize(editor.serialize(), atom) expect(editor2.id).toBe editor.id expect(editor2.getBuffer().getPath()).toBe editor.getBuffer().getPath() @@ -52,7 +52,7 @@ describe "TextEditor", -> atom.config.set('editor.showInvisibles', true) previousInvisibles = editor.tokenizedLineForScreenRow(0).invisibles - editor2 = TextEditor.deserialize(editor.serialize()) + editor2 = TextEditor.deserialize(editor.serialize(), atom) expect(previousInvisibles).toBeDefined() expect(editor2.displayBuffer.tokenizedLineForScreenRow(0).invisibles).toEqual previousInvisibles @@ -62,7 +62,7 @@ describe "TextEditor", -> state = editor.serialize() atom.config.set('editor.invisibles', eol: '?') - editor2 = TextEditor.deserialize(state) + editor2 = TextEditor.deserialize(state, atom) expect(editor.tokenizedLineForScreenRow(0).invisibles.eol).toBe '?' @@ -4411,11 +4411,10 @@ describe "TextEditor", -> describe '.get/setPlaceholderText()', -> it 'can be created with placeholderText', -> - TextBuffer = require 'text-buffer' - newEditor = new TextEditor - buffer: new TextBuffer + newEditor = atom.workspace.buildTextEditor( mini: true placeholderText: 'yep' + ) expect(newEditor.getPlaceholderText()).toBe 'yep' it 'models placeholderText and emits an event when changed', -> @@ -4443,7 +4442,7 @@ describe "TextEditor", -> describe "when there's no repository for the editor's file", -> it "doesn't do anything", -> - editor = new TextEditor({}) + editor = atom.workspace.buildTextEditor() editor.setText("stuff") editor.checkoutHeadRevision() diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 5f87bb6ff..d8667770f 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -99,7 +99,7 @@ class TextEditorElement extends HTMLElement @model ? @buildModel() buildModel: -> - @setModel(new TextEditor( + @setModel(atom.workspace.buildTextEditor( buffer: new TextBuffer(@textContent) softWrapped: false tabLength: 2 diff --git a/src/text-editor.coffee b/src/text-editor.coffee index e6719565c..18d61e06a 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -65,7 +65,7 @@ class TextEditor extends Model selectionFlashDuration: 500 gutterContainer: null - @deserialize: (state) -> + @deserialize: (state, atomEnvironment) -> try displayBuffer = DisplayBuffer.deserialize(state.displayBuffer) catch error @@ -75,12 +75,19 @@ class TextEditor extends Model throw error state.displayBuffer = displayBuffer + state.config = atomEnvironment.config state.registerEditor = true new this(state) - constructor: ({@softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, registerEditor, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode}={}) -> + constructor: (params={}) -> super + { + @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, + softWrapped, @displayBuffer, buffer, registerEditor, suppressCursorCreation, + @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config + } = params + @emitter = new Emitter @disposables = new CompositeDisposable @cursors = [] @@ -105,7 +112,7 @@ class TextEditor extends Model @languageMode = new LanguageMode(this) - @setEncoding(atom.config.get('core.fileEncoding', scope: @getRootScopeDescriptor())) + @setEncoding(@config.get('core.fileEncoding', scope: @getRootScopeDescriptor())) @gutterContainer = new GutterContainer(this) @lineNumberGutter = @gutterContainer.addGutter @@ -146,7 +153,7 @@ class TextEditor extends Model subscribeToTabTypeConfig: -> @tabTypeSubscription?.dispose() - @tabTypeSubscription = atom.config.observe 'editor.tabType', scope: @getRootScopeDescriptor(), => + @tabTypeSubscription = @config.observe 'editor.tabType', scope: @getRootScopeDescriptor(), => @softTabs = @shouldUseSoftTabs(defaultValue: @softTabs) destroyed: -> @@ -454,7 +461,10 @@ class TextEditor extends Model copy: -> displayBuffer = @displayBuffer.copy() softTabs = @getSoftTabs() - newEditor = new TextEditor({@buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, registerEditor: true}) + newEditor = new TextEditor({ + @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, + registerEditor: true, @config + }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) newEditor @@ -592,14 +602,14 @@ class TextEditor extends Model # Essential: Saves the editor's text buffer. # # See {TextBuffer::save} for more details. - save: -> @buffer.save(backup: atom.config.get('editor.backUpBeforeSaving')) + save: -> @buffer.save(backup: @config.get('editor.backUpBeforeSaving')) # Essential: Saves the editor's text buffer as the given path. # # See {TextBuffer::saveAs} for more details. # # * `filePath` A {String} path. - saveAs: (filePath) -> @buffer.saveAs(filePath, backup: atom.config.get('editor.backUpBeforeSaving')) + saveAs: (filePath) -> @buffer.saveAs(filePath, backup: @config.get('editor.backUpBeforeSaving')) # Determine whether the user should be prompted to save before closing # this editor. @@ -746,7 +756,7 @@ class TextEditor extends Model return false unless @emitWillInsertTextEvent(text) groupingInterval = if options.groupUndo - atom.config.get('editor.undoGroupingInterval') + @config.get('editor.undoGroupingInterval') else 0 @@ -2380,10 +2390,10 @@ class TextEditor extends Model # # Returns a {Boolean} shouldUseSoftTabs: ({defaultValue}) -> - tabType = atom.config.get('editor.tabType', scope: @getRootScopeDescriptor()) + tabType = @config.get('editor.tabType', scope: @getRootScopeDescriptor()) switch tabType when 'auto' - @usesSoftTabs() ? defaultValue ? atom.config.get('editor.softTabs') ? true + @usesSoftTabs() ? defaultValue ? @config.get('editor.softTabs') ? true when 'hard' false when 'soft' @@ -2906,10 +2916,10 @@ class TextEditor extends Model ### shouldAutoIndent: -> - atom.config.get("editor.autoIndent", scope: @getRootScopeDescriptor()) + @config.get("editor.autoIndent", scope: @getRootScopeDescriptor()) shouldAutoIndentOnPaste: -> - atom.config.get("editor.autoIndentOnPaste", scope: @getRootScopeDescriptor()) + @config.get("editor.autoIndentOnPaste", scope: @getRootScopeDescriptor()) ### Section: Event Handlers diff --git a/src/workspace.coffee b/src/workspace.coffee index 51910f90f..c0f13b714 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -458,7 +458,7 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(params) + new TextEditor(_.extend({@config}, params)) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From 979963a25cb48adea39c2cafb1cccb7f7748e22d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 21:40:10 -0600 Subject: [PATCH 063/316] Parameterize notification manager on TextEditor --- src/text-editor.coffee | 8 +++++--- src/workspace.coffee | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 18d61e06a..1174fb4b2 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -76,6 +76,7 @@ class TextEditor extends Model state.displayBuffer = displayBuffer state.config = atomEnvironment.config + staet.notificationManager = atomEnvironment.notifications state.registerEditor = true new this(state) @@ -85,7 +86,8 @@ class TextEditor extends Model { @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, registerEditor, suppressCursorCreation, - @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config + @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, + @notificationManager } = params @emitter = new Emitter @@ -463,7 +465,7 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - registerEditor: true, @config + registerEditor: true, @config, @notificationManager }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) @@ -2569,7 +2571,7 @@ class TextEditor extends Model list = list.map (item) -> "* #{item}" content = "Scopes at Cursor\n#{list.join('\n')}" - atom.notifications.addInfo(content, dismissable: true) + @notificationManager.addInfo(content, dismissable: true) # {Delegates to: DisplayBuffer.tokenForBufferPosition} tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition) diff --git a/src/workspace.coffee b/src/workspace.coffee index c0f13b714..26d662257 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -458,7 +458,7 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(_.extend({@config}, params)) + new TextEditor(_.extend({@config, @notificationManager}, params)) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From ad57dca1f761f820dccce22571c9d4ee503bf9b7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 21:41:56 -0600 Subject: [PATCH 064/316] Remove dead registerEditor parameter --- src/text-editor.coffee | 13 ++++--------- src/workspace.coffee | 2 -- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 1174fb4b2..c986408c5 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -55,7 +55,6 @@ GutterContainer = require './gutter-container' module.exports = class TextEditor extends Model callDisplayBufferCreatedHook: false - registerEditor: false buffer: null languageMode: null cursors: null @@ -76,8 +75,7 @@ class TextEditor extends Model state.displayBuffer = displayBuffer state.config = atomEnvironment.config - staet.notificationManager = atomEnvironment.notifications - state.registerEditor = true + state.notificationManager = atomEnvironment.notifications new this(state) constructor: (params={}) -> @@ -85,9 +83,8 @@ class TextEditor extends Model { @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, - softWrapped, @displayBuffer, buffer, registerEditor, suppressCursorCreation, - @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, - @notificationManager + softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, + lineNumberGutterVisible, largeFileMode, @config, @notificationManager } = params @emitter = new Emitter @@ -122,8 +119,6 @@ class TextEditor extends Model priority: 0 visible: lineNumberGutterVisible - atom.workspace?.editorAdded(this) if registerEditor - serialize: -> deserializer: 'TextEditor' id: @id @@ -465,7 +460,7 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - registerEditor: true, @config, @notificationManager + @config, @notificationManager }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) diff --git a/src/workspace.coffee b/src/workspace.coffee index 26d662257..6ad73b607 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -88,8 +88,6 @@ class Workspace extends Model _.uniq(packageNames) - editorAdded: (editor) -> - subscribeToActiveItem: -> @updateWindowTitle() @updateDocumentEdited() From e8038011454350b808b9fa837d2f4d4a8488edc9 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 21:48:05 -0600 Subject: [PATCH 065/316] Parameterize clipboard on TextEditor --- spec/spec-helper.coffee | 3 ++- src/atom.coffee | 2 +- src/text-editor.coffee | 9 +++++---- src/workspace.coffee | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 97bcbf04b..2c8320383 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -91,7 +91,8 @@ beforeEach -> config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion() + setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), + clipboard: atom.clipboard }) atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) diff --git a/src/atom.coffee b/src/atom.coffee index 3ccff0fd5..6e46497f4 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -175,7 +175,7 @@ class Atom extends Model @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), - setDocumentEdited: @setDocumentEdited.bind(this) + setDocumentEdited: @setDocumentEdited.bind(this), @clipboard }) @themes.workspace = @workspace diff --git a/src/text-editor.coffee b/src/text-editor.coffee index c986408c5..4859c64d4 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -76,6 +76,7 @@ class TextEditor extends Model state.displayBuffer = displayBuffer state.config = atomEnvironment.config state.notificationManager = atomEnvironment.notifications + state.clipboard = atomEnvironment.clipboard new this(state) constructor: (params={}) -> @@ -84,7 +85,7 @@ class TextEditor extends Model { @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, - lineNumberGutterVisible, largeFileMode, @config, @notificationManager + lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard } = params @emitter = new Emitter @@ -460,7 +461,7 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - @config, @notificationManager + @config, @notificationManager, @clipboard }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) @@ -590,7 +591,7 @@ class TextEditor extends Model # Copies the current file path to the native clipboard. copyPathToClipboard: -> if filePath = @getPath() - atom.clipboard.write(filePath) + @clipboard.write(filePath) ### Section: File Operations @@ -2618,7 +2619,7 @@ class TextEditor extends Model # # * `options` (optional) See {Selection::insertText}. pasteText: (options={}) -> - {text: clipboardText, metadata} = atom.clipboard.readWithMetadata() + {text: clipboardText, metadata} = @clipboard.readWithMetadata() return false unless @emitWillInsertTextEvent(clipboardText) metadata ?= {} diff --git a/src/workspace.coffee b/src/workspace.coffee index 6ad73b607..396bb9445 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -26,7 +26,7 @@ class Workspace extends Model constructor: (params) -> super - {@packageManager, @config, @project, @grammarRegistry, @notificationManager} = params + {@packageManager, @config, @project, @grammarRegistry, @notificationManager, @clipboard} = params {@setRepresentedFilename, @setDocumentEdited} = params @emitter = new Emitter @@ -456,7 +456,7 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(_.extend({@config, @notificationManager}, params)) + new TextEditor(_.extend({@config, @notificationManager, @clipboard}, params)) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From 8d7a08d07f6916ee6d6760384584f23ea87883da Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 22:00:00 -0600 Subject: [PATCH 066/316] Parameterize view registry on TextEditor --- spec/spec-helper.coffee | 2 +- src/atom.coffee | 2 +- src/text-editor.coffee | 60 +++++++++++++++++++++-------------------- src/workspace.coffee | 8 +++--- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 2c8320383..2fe53ceb3 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -92,7 +92,7 @@ beforeEach -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), - clipboard: atom.clipboard + clipboard: atom.clipboard, viewRegistry: atom.views }) atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) diff --git a/src/atom.coffee b/src/atom.coffee index 6e46497f4..1341ae0be 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -175,7 +175,7 @@ class Atom extends Model @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), - setDocumentEdited: @setDocumentEdited.bind(this), @clipboard + setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views }) @themes.workspace = @workspace diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 4859c64d4..cd64c1036 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -77,6 +77,7 @@ class TextEditor extends Model state.config = atomEnvironment.config state.notificationManager = atomEnvironment.notifications state.clipboard = atomEnvironment.clipboard + state.viewRegistry = atomEnvironment.views new this(state) constructor: (params={}) -> @@ -85,7 +86,8 @@ class TextEditor extends Model { @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, - lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard + lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard, + @viewRegistry } = params @emitter = new Emitter @@ -432,12 +434,12 @@ class TextEditor extends Model onDidChangeScrollTop: (callback) -> Grim.deprecate("This is now a view method. Call TextEditorElement::onDidChangeScrollTop instead.") - atom.views.getView(this).onDidChangeScrollTop(callback) + @viewRegistry.getView(this).onDidChangeScrollTop(callback) onDidChangeScrollLeft: (callback) -> Grim.deprecate("This is now a view method. Call TextEditorElement::onDidChangeScrollLeft instead.") - atom.views.getView(this).onDidChangeScrollLeft(callback) + @viewRegistry.getView(this).onDidChangeScrollLeft(callback) onDidRequestAutoscroll: (callback) -> @displayBuffer.onDidRequestAutoscroll(callback) @@ -461,7 +463,7 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - @config, @notificationManager, @clipboard + @config, @notificationManager, @clipboard, @viewRegistry }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) @@ -2872,24 +2874,24 @@ class TextEditor extends Model scrollToTop: -> Grim.deprecate("This is now a view method. Call TextEditorElement::scrollToTop instead.") - atom.views.getView(this).scrollToTop() + @viewRegistry.getView(this).scrollToTop() scrollToBottom: -> Grim.deprecate("This is now a view method. Call TextEditorElement::scrollToTop instead.") - atom.views.getView(this).scrollToBottom() + @viewRegistry.getView(this).scrollToBottom() scrollToScreenRange: (screenRange, options) -> @displayBuffer.scrollToScreenRange(screenRange, options) getHorizontalScrollbarHeight: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getHorizontalScrollbarHeight instead.") - atom.views.getView(this).getHorizontalScrollbarHeight() + @viewRegistry.getView(this).getHorizontalScrollbarHeight() getVerticalScrollbarWidth: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getVerticalScrollbarWidth instead.") - atom.views.getView(this).getVerticalScrollbarWidth() + @viewRegistry.getView(this).getVerticalScrollbarWidth() pageUp: -> @moveUp(@getRowsPerPage()) @@ -2956,19 +2958,19 @@ class TextEditor extends Model getFirstVisibleScreenRow: -> deprecate("This is now a view method. Call TextEditorElement::getFirstVisibleScreenRow instead.") - atom.views.getView(this).getVisibleRowRange()[0] + @viewRegistry.getView(this).getVisibleRowRange()[0] getLastVisibleScreenRow: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getLastVisibleScreenRow instead.") - atom.views.getView(this).getVisibleRowRange()[1] + @viewRegistry.getView(this).getVisibleRowRange()[1] pixelPositionForBufferPosition: (bufferPosition) -> Grim.deprecate("This method is deprecated on the model layer. Use `TextEditorElement::pixelPositionForBufferPosition` instead") - atom.views.getView(this).pixelPositionForBufferPosition(bufferPosition) + @viewRegistry.getView(this).pixelPositionForBufferPosition(bufferPosition) pixelPositionForScreenPosition: (screenPosition) -> Grim.deprecate("This method is deprecated on the model layer. Use `TextEditorElement::pixelPositionForScreenPosition` instead") - atom.views.getView(this).pixelPositionForScreenPosition(screenPosition) + @viewRegistry.getView(this).pixelPositionForScreenPosition(screenPosition) getSelectionMarkerAttributes: -> {type: 'selection', editorId: @id, invalidate: 'never', maintainHistory: true} @@ -2999,7 +3001,7 @@ class TextEditor extends Model @displayBuffer.setHeight(height) else Grim.deprecate("This is now a view method. Call TextEditorElement::setHeight instead.") - atom.views.getView(this).setHeight(height) + @viewRegistry.getView(this).setHeight(height) getHeight: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getHeight instead.") @@ -3012,7 +3014,7 @@ class TextEditor extends Model @displayBuffer.setWidth(width) else Grim.deprecate("This is now a view method. Call TextEditorElement::setWidth instead.") - atom.views.getView(this).setWidth(width) + @viewRegistry.getView(this).setWidth(width) getWidth: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getWidth instead.") @@ -3027,77 +3029,77 @@ class TextEditor extends Model getScrollTop: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollTop instead.") - atom.views.getView(this).getScrollTop() + @viewRegistry.getView(this).getScrollTop() setScrollTop: (scrollTop) -> Grim.deprecate("This is now a view method. Call TextEditorElement::setScrollTop instead.") - atom.views.getView(this).setScrollTop(scrollTop) + @viewRegistry.getView(this).setScrollTop(scrollTop) getScrollBottom: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollBottom instead.") - atom.views.getView(this).getScrollBottom() + @viewRegistry.getView(this).getScrollBottom() setScrollBottom: (scrollBottom) -> Grim.deprecate("This is now a view method. Call TextEditorElement::setScrollBottom instead.") - atom.views.getView(this).setScrollBottom(scrollBottom) + @viewRegistry.getView(this).setScrollBottom(scrollBottom) getScrollLeft: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollLeft instead.") - atom.views.getView(this).getScrollLeft() + @viewRegistry.getView(this).getScrollLeft() setScrollLeft: (scrollLeft) -> Grim.deprecate("This is now a view method. Call TextEditorElement::setScrollLeft instead.") - atom.views.getView(this).setScrollLeft(scrollLeft) + @viewRegistry.getView(this).setScrollLeft(scrollLeft) getScrollRight: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollRight instead.") - atom.views.getView(this).getScrollRight() + @viewRegistry.getView(this).getScrollRight() setScrollRight: (scrollRight) -> Grim.deprecate("This is now a view method. Call TextEditorElement::setScrollRight instead.") - atom.views.getView(this).setScrollRight(scrollRight) + @viewRegistry.getView(this).setScrollRight(scrollRight) getScrollHeight: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollHeight instead.") - atom.views.getView(this).getScrollHeight() + @viewRegistry.getView(this).getScrollHeight() getScrollWidth: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollWidth instead.") - atom.views.getView(this).getScrollWidth() + @viewRegistry.getView(this).getScrollWidth() getVisibleRowRange: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getVisibleRowRange instead.") - atom.views.getView(this).getVisibleRowRange() + @viewRegistry.getView(this).getVisibleRowRange() intersectsVisibleRowRange: (startRow, endRow) -> Grim.deprecate("This is now a view method. Call TextEditorElement::intersectsVisibleRowRange instead.") - atom.views.getView(this).intersectsVisibleRowRange(startRow, endRow) + @viewRegistry.getView(this).intersectsVisibleRowRange(startRow, endRow) selectionIntersectsVisibleRowRange: (selection) -> Grim.deprecate("This is now a view method. Call TextEditorElement::selectionIntersectsVisibleRowRange instead.") - atom.views.getView(this).selectionIntersectsVisibleRowRange(selection) + @viewRegistry.getView(this).selectionIntersectsVisibleRowRange(selection) screenPositionForPixelPosition: (pixelPosition) -> Grim.deprecate("This is now a view method. Call TextEditorElement::screenPositionForPixelPosition instead.") - atom.views.getView(this).screenPositionForPixelPosition(pixelPosition) + @viewRegistry.getView(this).screenPositionForPixelPosition(pixelPosition) pixelRectForScreenRange: (screenRange) -> Grim.deprecate("This is now a view method. Call TextEditorElement::pixelRectForScreenRange instead.") - atom.views.getView(this).pixelRectForScreenRange(screenRange) + @viewRegistry.getView(this).pixelRectForScreenRange(screenRange) ### Section: Utility diff --git a/src/workspace.coffee b/src/workspace.coffee index 396bb9445..8e7004cf5 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -26,8 +26,10 @@ class Workspace extends Model constructor: (params) -> super - {@packageManager, @config, @project, @grammarRegistry, @notificationManager, @clipboard} = params - {@setRepresentedFilename, @setDocumentEdited} = params + { + @packageManager, @config, @project, @grammarRegistry, @notificationManager, + @clipboard, @viewRegistry, @setRepresentedFilename, @setDocumentEdited + } = params @emitter = new Emitter @openers = [] @@ -456,7 +458,7 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(_.extend({@config, @notificationManager, @clipboard}, params)) + new TextEditor(_.extend({@config, @notificationManager, @clipboard, @viewRegistry}, params)) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From b729a9bb37095e99fcbd66349da176a2781d1069 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 Oct 2015 22:04:00 -0600 Subject: [PATCH 067/316] Parameterize project on TextEditor --- src/text-editor.coffee | 12 ++++++------ src/workspace.coffee | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index cd64c1036..aa9cb6fea 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -87,7 +87,7 @@ class TextEditor extends Model @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard, - @viewRegistry + @viewRegistry, @project } = params @emitter = new Emitter @@ -133,8 +133,8 @@ class TextEditor extends Model subscribeToBuffer: -> @buffer.retain() @disposables.add @buffer.onDidChangePath => - unless atom.project.getPaths().length > 0 - atom.project.setPaths([path.dirname(@getPath())]) + unless @project.getPaths().length > 0 + @project.setPaths([path.dirname(@getPath())]) @emitter.emit 'did-change-title', @getTitle() @emitter.emit 'did-change-path', @getPath() @disposables.add @buffer.onDidChangeEncoding => @@ -463,7 +463,7 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - @config, @notificationManager, @clipboard, @viewRegistry + @config, @notificationManager, @clipboard, @viewRegistry, @project }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) @@ -565,7 +565,7 @@ class TextEditor extends Model getLongTitle: -> if sessionPath = @getPath() fileName = path.basename(sessionPath) - directory = atom.project.relativize(path.dirname(sessionPath)) + directory = @project.relativize(path.dirname(sessionPath)) directory = if directory.length > 0 then directory else path.basename(path.dirname(sessionPath)) "#{fileName} - #{directory}" else @@ -625,7 +625,7 @@ class TextEditor extends Model checkoutHeadRevision: -> if filePath = this.getPath() - atom.project.repositoryForDirectory(new Directory(path.dirname(filePath))) + @project.repositoryForDirectory(new Directory(path.dirname(filePath))) .then (repository) => repository?.checkoutHeadForEditor(this) else diff --git a/src/workspace.coffee b/src/workspace.coffee index 8e7004cf5..e8e73cf11 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -458,7 +458,7 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(_.extend({@config, @notificationManager, @clipboard, @viewRegistry}, params)) + new TextEditor(_.extend({@config, @notificationManager, @clipboard, @viewRegistry, @project}, params)) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From 95fbff033dc47c6fb3b31dfeeb155c1f7233c7f7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 08:28:22 -0600 Subject: [PATCH 068/316] Throw when editor dependencies are undefined --- src/text-editor.coffee | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index aa9cb6fea..921cc26c1 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -90,6 +90,12 @@ class TextEditor extends Model @viewRegistry, @project } = params + throw new Error("Must pass a config parameter when constructing TextEditors") unless @config? + throw new Error("Must pass a notificationManager parameter when constructing TextEditors") unless @notificationManager? + throw new Error("Must pass a clipboard parameter when constructing TextEditors") unless @clipboard? + throw new Error("Must pass a viewRegistry parameter when constructing TextEditors") unless @viewRegistry? + throw new Error("Must pass a project parameter when constructing TextEditors") unless @project? + @emitter = new Emitter @disposables = new CompositeDisposable @cursors = [] From 332bad6598fe4c27b18512455ef88f9a3b93596c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 08:37:10 -0600 Subject: [PATCH 069/316] Assign project when deserializing TextEditors --- src/text-editor.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 921cc26c1..569d03c78 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -78,6 +78,7 @@ class TextEditor extends Model state.notificationManager = atomEnvironment.notifications state.clipboard = atomEnvironment.clipboard state.viewRegistry = atomEnvironment.views + state.project = atomEnvironment.project new this(state) constructor: (params={}) -> From d15d9be9ebc1da9a009e1e41e58da5c0dc4d1c57 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 08:49:12 -0600 Subject: [PATCH 070/316] Construct Workspace with all dependencies in specs --- spec/workspace-spec.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 8341e011a..b3bb5ae66 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -17,6 +17,7 @@ describe "Workspace", -> atom.workspace = workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, + clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() }) @@ -33,8 +34,9 @@ describe "Workspace", -> atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, + clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + setDocumentEdited: setDocumentEdited }) atom.workspace.deserialize(workspaceState, atom.deserializers) @@ -631,6 +633,7 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, + clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() }) @@ -689,6 +692,7 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, + clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() }) From 706ef8e8ce09b1cb2694cde4e4f6df12e2a6220e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 08:49:19 -0600 Subject: [PATCH 071/316] =?UTF-8?q?Don=E2=80=99t=20use=20atom.config=20glo?= =?UTF-8?q?bal=20in=20Cursor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cursor.coffee | 8 ++++---- src/text-editor.coffee | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 84396448c..c9ebca8c7 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -16,7 +16,7 @@ class Cursor extends Model visible: true # Instantiated by a {TextEditor} - constructor: ({@editor, @marker, id}) -> + constructor: ({@editor, @marker, @config, id}) -> @emitter = new Emitter @assignId(id) @@ -158,7 +158,7 @@ class Cursor extends Model [before, after] = @editor.getTextInBufferRange(range) return false if /\s/.test(before) or /\s/.test(after) - nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()).split('') + nonWordCharacters = @config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()).split('') _.contains(nonWordCharacters, before) isnt _.contains(nonWordCharacters, after) # Public: Returns whether this cursor is between a word's start and end. @@ -605,7 +605,7 @@ class Cursor extends Model # Returns a {RegExp}. wordRegExp: ({includeNonWordCharacters}={}) -> includeNonWordCharacters ?= true - nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()) + nonWordCharacters = @config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()) segments = ["^[\t ]*$"] segments.push("[^\\s#{_.escapeRegExp(nonWordCharacters)}]+") if includeNonWordCharacters @@ -620,7 +620,7 @@ class Cursor extends Model # # Returns a {RegExp}. subwordRegExp: (options={}) -> - nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()) + nonWordCharacters = @config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()) lowercaseLetters = 'a-z\\u00DF-\\u00F6\\u00F8-\\u00FF' uppercaseLetters = 'A-Z\\u00C0-\\u00D6\\u00D8-\\u00DE' snakeCamelSegment = "[#{uppercaseLetters}]?[#{lowercaseLetters}]+" diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 569d03c78..5befc3ce9 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -1757,7 +1757,7 @@ class TextEditor extends Model # Add a cursor based on the given {Marker}. addCursor: (marker) -> - cursor = new Cursor(editor: this, marker: marker) + cursor = new Cursor(editor: this, marker: marker, config: @config) @cursors.push(cursor) @decorateMarker(marker, type: 'line-number', class: 'cursor-line') @decorateMarker(marker, type: 'line-number', class: 'cursor-line-no-selection', onlyHead: true, onlyEmpty: true) From edd666b845a73ec87f28271d221ee7a23be252d8 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 08:58:05 -0600 Subject: [PATCH 072/316] =?UTF-8?q?Don=E2=80=99t=20use=20atom.config=20glo?= =?UTF-8?q?bal=20in=20DisplayBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/display-buffer-spec.coffee | 12 ++++++------ src/display-buffer.coffee | 29 +++++++++++++++-------------- src/text-editor.coffee | 4 ++-- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 7ed97f0d0..2778876f7 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -7,7 +7,7 @@ describe "DisplayBuffer", -> tabLength = 2 buffer = atom.project.bufferForPathSync('sample.js') - displayBuffer = new DisplayBuffer({buffer, tabLength}) + displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config}) changeHandler = jasmine.createSpy 'changeHandler' displayBuffer.onDidChange changeHandler @@ -49,7 +49,7 @@ describe "DisplayBuffer", -> it "updates the display buffer prior to invoking change handlers registered on the buffer", -> buffer.onDidChange -> expect(displayBuffer2.tokenizedLineForScreenRow(0).text).toBe "testing" - displayBuffer2 = new DisplayBuffer({buffer, tabLength}) + displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config}) buffer.setText("testing") describe "soft wrapping", -> @@ -232,7 +232,7 @@ describe "DisplayBuffer", -> describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", -> it "correctly renders the original wrapped line", -> buffer = atom.project.buildBufferSync(null, '') - displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30}) + displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, config: atom.config}) displayBuffer.setSoftWrapped(true) buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.") @@ -294,7 +294,7 @@ describe "DisplayBuffer", -> displayBuffer.destroy() buffer.release() buffer = atom.project.bufferForPathSync('two-hundred.txt') - displayBuffer = new DisplayBuffer({buffer, tabLength}) + displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config}) displayBuffer.onDidChange changeHandler describe "when folds are created and destroyed", -> @@ -408,7 +408,7 @@ describe "DisplayBuffer", -> describe "when there is another display buffer pointing to the same buffer", -> it "does not consider folds to be nested inside of folds from the other display buffer", -> - otherDisplayBuffer = new DisplayBuffer({buffer, tabLength}) + otherDisplayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config}) otherDisplayBuffer.createFold(1, 5) displayBuffer.createFold(2, 4) @@ -1154,7 +1154,7 @@ describe "DisplayBuffer", -> describe 'when there are multiple DisplayBuffers for a buffer', -> describe 'when a marker is created', -> it 'the second display buffer will not emit a marker-created event when the marker has been deleted in the first marker-created event', -> - displayBuffer2 = new DisplayBuffer({buffer, tabLength}) + displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config}) displayBuffer.onDidCreateMarker markerCreated1 = jasmine.createSpy().andCallFake (marker) -> marker.destroy() displayBuffer2.onDidCreateMarker markerCreated2 = jasmine.createSpy() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 27d1b44cf..d0776d5ca 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -27,11 +27,12 @@ class DisplayBuffer extends Model height: null width: null - @deserialize: (state) -> + @deserialize: (state, atomEnvironment) -> state.tokenizedBuffer = TokenizedBuffer.deserialize(state.tokenizedBuffer) + state.config = atomEnvironment.config new this(state) - constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, @largeFileMode}={}) -> + constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, @largeFileMode, @config}={}) -> super @emitter = new Emitter @@ -62,29 +63,29 @@ class DisplayBuffer extends Model oldConfigSettings = @configSettings @configSettings = - scrollPastEnd: atom.config.get('editor.scrollPastEnd', scope: scopeDescriptor) - softWrap: atom.config.get('editor.softWrap', scope: scopeDescriptor) - softWrapAtPreferredLineLength: atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor) - softWrapHangingIndent: atom.config.get('editor.softWrapHangingIndent', scope: scopeDescriptor) - preferredLineLength: atom.config.get('editor.preferredLineLength', scope: scopeDescriptor) + scrollPastEnd: @config.get('editor.scrollPastEnd', scope: scopeDescriptor) + softWrap: @config.get('editor.softWrap', scope: scopeDescriptor) + softWrapAtPreferredLineLength: @config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor) + softWrapHangingIndent: @config.get('editor.softWrapHangingIndent', scope: scopeDescriptor) + preferredLineLength: @config.get('editor.preferredLineLength', scope: scopeDescriptor) - subscriptions.add atom.config.onDidChange 'editor.softWrap', scope: scopeDescriptor, ({newValue}) => + subscriptions.add @config.onDidChange 'editor.softWrap', scope: scopeDescriptor, ({newValue}) => @configSettings.softWrap = newValue @updateWrappedScreenLines() - subscriptions.add atom.config.onDidChange 'editor.softWrapHangingIndent', scope: scopeDescriptor, ({newValue}) => + subscriptions.add @config.onDidChange 'editor.softWrapHangingIndent', scope: scopeDescriptor, ({newValue}) => @configSettings.softWrapHangingIndent = newValue @updateWrappedScreenLines() - subscriptions.add atom.config.onDidChange 'editor.softWrapAtPreferredLineLength', scope: scopeDescriptor, ({newValue}) => + subscriptions.add @config.onDidChange 'editor.softWrapAtPreferredLineLength', scope: scopeDescriptor, ({newValue}) => @configSettings.softWrapAtPreferredLineLength = newValue @updateWrappedScreenLines() if @isSoftWrapped() - subscriptions.add atom.config.onDidChange 'editor.preferredLineLength', scope: scopeDescriptor, ({newValue}) => + subscriptions.add @config.onDidChange 'editor.preferredLineLength', scope: scopeDescriptor, ({newValue}) => @configSettings.preferredLineLength = newValue - @updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor) + @updateWrappedScreenLines() if @isSoftWrapped() and @config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor) - subscriptions.add atom.config.observe 'editor.scrollPastEnd', scope: scopeDescriptor, (value) => + subscriptions.add @config.observe 'editor.scrollPastEnd', scope: scopeDescriptor, (value) => @configSettings.scrollPastEnd = value @updateWrappedScreenLines() if oldConfigSettings? and not _.isEqual(oldConfigSettings, @configSettings) @@ -98,7 +99,7 @@ class DisplayBuffer extends Model largeFileMode: @largeFileMode copy: -> - newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength(), @largeFileMode}) + newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength(), @largeFileMode, @config}) for marker in @findMarkers(displayBufferId: @id) marker.copy(displayBufferId: newDisplayBuffer.id) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 5befc3ce9..ab3e79d40 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -66,7 +66,7 @@ class TextEditor extends Model @deserialize: (state, atomEnvironment) -> try - displayBuffer = DisplayBuffer.deserialize(state.displayBuffer) + displayBuffer = DisplayBuffer.deserialize(state.displayBuffer, atomEnvironment) catch error if error.syscall is 'read' return # Error reading the file, don't deserialize an editor for it @@ -103,7 +103,7 @@ class TextEditor extends Model @selections = [] buffer ?= new TextBuffer - @displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped, ignoreInvisibles: @mini, largeFileMode}) + @displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped, ignoreInvisibles: @mini, largeFileMode, @config}) @buffer = @displayBuffer.buffer for marker in @findMarkers(@getSelectionMarkerAttributes()) From dc0709ef9eea0f203764c3fad6efee58acb40c02 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 09:19:46 -0600 Subject: [PATCH 073/316] =?UTF-8?q?Don=E2=80=99t=20use=20atom.assert=20glo?= =?UTF-8?q?bal=20in=20DisplayBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/display-buffer-spec.coffee | 12 ++++++------ spec/spec-helper.coffee | 2 +- spec/workspace-spec.coffee | 11 +++++++---- src/atom.coffee | 3 ++- src/display-buffer.coffee | 11 +++++++---- src/text-editor.coffee | 11 ++++++++--- src/tokenized-buffer.coffee | 2 +- src/workspace.coffee | 6 ++++-- 8 files changed, 36 insertions(+), 22 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 2778876f7..ff57111fc 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -7,7 +7,7 @@ describe "DisplayBuffer", -> tabLength = 2 buffer = atom.project.bufferForPathSync('sample.js') - displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config}) + displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) changeHandler = jasmine.createSpy 'changeHandler' displayBuffer.onDidChange changeHandler @@ -49,7 +49,7 @@ describe "DisplayBuffer", -> it "updates the display buffer prior to invoking change handlers registered on the buffer", -> buffer.onDidChange -> expect(displayBuffer2.tokenizedLineForScreenRow(0).text).toBe "testing" - displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config}) + displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) buffer.setText("testing") describe "soft wrapping", -> @@ -232,7 +232,7 @@ describe "DisplayBuffer", -> describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", -> it "correctly renders the original wrapped line", -> buffer = atom.project.buildBufferSync(null, '') - displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, config: atom.config}) + displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, config: atom.config, assert: ->}) displayBuffer.setSoftWrapped(true) buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.") @@ -294,7 +294,7 @@ describe "DisplayBuffer", -> displayBuffer.destroy() buffer.release() buffer = atom.project.bufferForPathSync('two-hundred.txt') - displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config}) + displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) displayBuffer.onDidChange changeHandler describe "when folds are created and destroyed", -> @@ -408,7 +408,7 @@ describe "DisplayBuffer", -> describe "when there is another display buffer pointing to the same buffer", -> it "does not consider folds to be nested inside of folds from the other display buffer", -> - otherDisplayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config}) + otherDisplayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) otherDisplayBuffer.createFold(1, 5) displayBuffer.createFold(2, 4) @@ -1154,7 +1154,7 @@ describe "DisplayBuffer", -> describe 'when there are multiple DisplayBuffers for a buffer', -> describe 'when a marker is created', -> it 'the second display buffer will not emit a marker-created event when the marker has been deleted in the first marker-created event', -> - displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config}) + displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) displayBuffer.onDidCreateMarker markerCreated1 = jasmine.createSpy().andCallFake (marker) -> marker.destroy() displayBuffer2.onDidCreateMarker markerCreated2 = jasmine.createSpy() diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 2fe53ceb3..cd3ead097 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -92,7 +92,7 @@ beforeEach -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), - clipboard: atom.clipboard, viewRegistry: atom.views + clipboard: atom.clipboard, viewRegistry: atom.views, assert: atom.assert.bind(atom) }) atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index b3bb5ae66..5255094a4 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -19,7 +19,8 @@ describe "Workspace", -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), + assert: atom.assert.bind(atom) }) waits(1) @@ -36,7 +37,7 @@ describe "Workspace", -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited + setDocumentEdited: setDocumentEdited, assert: atom.assert.bind(atom) }) atom.workspace.deserialize(workspaceState, atom.deserializers) @@ -635,7 +636,8 @@ describe "Workspace", -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), + assert: atom.assert.bind(atom) }) workspace2.deserialize(state, atom.deserializers) expect(jsPackage.loadGrammarsSync.callCount).toBe 1 @@ -694,7 +696,8 @@ describe "Workspace", -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, clipboard: atom.clipboard, viewRegistry: atom.views, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion() + setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), + assert: atom.assert.bind(atom) }) workspace2.deserialize(atom.workspace.serialize(), atom.deserializers) item = atom.workspace.getActivePaneItem() diff --git a/src/atom.coffee b/src/atom.coffee index 1341ae0be..dd6dbbcce 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -175,7 +175,8 @@ class Atom extends Model @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), - setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views + setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, + assert: @assert.bind(this) }) @themes.workspace = @workspace diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index d0776d5ca..06898fefe 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -30,9 +30,10 @@ class DisplayBuffer extends Model @deserialize: (state, atomEnvironment) -> state.tokenizedBuffer = TokenizedBuffer.deserialize(state.tokenizedBuffer) state.config = atomEnvironment.config + state.assert = atomEnvironment.assert new this(state) - constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, @largeFileMode, @config}={}) -> + constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, @largeFileMode, @config, @assert}={}) -> super @emitter = new Emitter @@ -99,7 +100,9 @@ class DisplayBuffer extends Model largeFileMode: @largeFileMode copy: -> - newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength(), @largeFileMode, @config}) + newDisplayBuffer = new DisplayBuffer({ + @buffer, tabLength: @getTabLength(), @largeFileMode, @config, @assert + }) for marker in @findMarkers(displayBufferId: @id) marker.copy(displayBufferId: newDisplayBuffer.id) @@ -1067,8 +1070,8 @@ class DisplayBuffer extends Model tokenizedLinesCount = @tokenizedBuffer.getLineCount() bufferLinesCount = @buffer.getLineCount() - atom.assert screenLinesCount is tokenizedLinesCount, "Display buffer line count out of sync with tokenized buffer", (error) -> + @assert screenLinesCount is tokenizedLinesCount, "Display buffer line count out of sync with tokenized buffer", (error) -> error.metadata = {screenLinesCount, tokenizedLinesCount, bufferLinesCount} - atom.assert screenLinesCount is bufferLinesCount, "Display buffer line count out of sync with buffer", (error) -> + @assert screenLinesCount is bufferLinesCount, "Display buffer line count out of sync with buffer", (error) -> error.metadata = {screenLinesCount, tokenizedLinesCount, bufferLinesCount} diff --git a/src/text-editor.coffee b/src/text-editor.coffee index ab3e79d40..54e80b632 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -79,6 +79,7 @@ class TextEditor extends Model state.clipboard = atomEnvironment.clipboard state.viewRegistry = atomEnvironment.views state.project = atomEnvironment.project + state.assert = atomEnvironment.assert.bind(atomEnvironment) new this(state) constructor: (params={}) -> @@ -88,7 +89,7 @@ class TextEditor extends Model @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard, - @viewRegistry, @project + @viewRegistry, @project, @assert } = params throw new Error("Must pass a config parameter when constructing TextEditors") unless @config? @@ -96,6 +97,7 @@ class TextEditor extends Model throw new Error("Must pass a clipboard parameter when constructing TextEditors") unless @clipboard? throw new Error("Must pass a viewRegistry parameter when constructing TextEditors") unless @viewRegistry? throw new Error("Must pass a project parameter when constructing TextEditors") unless @project? + throw new Error("Must pass an assert parameter when constructing TextEditors") unless @assert? @emitter = new Emitter @disposables = new CompositeDisposable @@ -103,7 +105,10 @@ class TextEditor extends Model @selections = [] buffer ?= new TextBuffer - @displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped, ignoreInvisibles: @mini, largeFileMode, @config}) + @displayBuffer ?= new DisplayBuffer({ + buffer, tabLength, softWrapped, ignoreInvisibles: @mini, largeFileMode, + @config, @assert + }) @buffer = @displayBuffer.buffer for marker in @findMarkers(@getSelectionMarkerAttributes()) @@ -470,7 +475,7 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - @config, @notificationManager, @clipboard, @viewRegistry, @project + @config, @notificationManager, @clipboard, @viewRegistry, @project, @assert }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 8721b0547..70989239e 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -21,7 +21,7 @@ class TokenizedBuffer extends Model configSettings: null changeCount: 0 - @deserialize: (state) -> + @deserialize: (state, atomEnvironment) -> state.buffer = atom.project.bufferForPathSync(state.bufferPath) new this(state) diff --git a/src/workspace.coffee b/src/workspace.coffee index e8e73cf11..c962d45b2 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -28,9 +28,11 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, - @clipboard, @viewRegistry, @setRepresentedFilename, @setDocumentEdited + @clipboard, @viewRegistry, @setRepresentedFilename, @setDocumentEdited, @assert } = params + debugger unless @assert? + @emitter = new Emitter @openers = [] @destroyedItemURIs = [] @@ -458,7 +460,7 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(_.extend({@config, @notificationManager, @clipboard, @viewRegistry, @project}, params)) + new TextEditor(_.extend({@config, @notificationManager, @clipboard, @viewRegistry, @project, @assert}, params)) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From 4f654529028e05b9c6ec85146a7bfd5b3ce9c76c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 09:30:30 -0600 Subject: [PATCH 074/316] =?UTF-8?q?Don=E2=80=99t=20use=20atom.config=20glo?= =?UTF-8?q?bal=20in=20TokenizedBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/token-iterator-spec.coffee | 2 +- spec/tokenized-buffer-spec.coffee | 30 +++++++++++++++--------------- src/display-buffer.coffee | 6 ++++-- src/tokenized-buffer.coffee | 13 +++++++------ 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/spec/token-iterator-spec.coffee b/spec/token-iterator-spec.coffee index ee8ac25e5..994fce563 100644 --- a/spec/token-iterator-spec.coffee +++ b/spec/token-iterator-spec.coffee @@ -24,7 +24,7 @@ describe "TokenIterator", -> end x x """) - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) tokenizedBuffer.setGrammar(grammar) tokenIterator = tokenizedBuffer.tokenizedLineForRow(1).getTokenIterator() diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index 601064887..bd832b505 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -27,7 +27,7 @@ describe "TokenizedBuffer", -> describe "when the buffer is destroyed", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) startTokenizing(tokenizedBuffer) it "stops tokenization", -> @@ -39,7 +39,7 @@ describe "TokenizedBuffer", -> describe "when the buffer contains soft-tabs", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) startTokenizing(tokenizedBuffer) tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') @@ -345,7 +345,7 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) startTokenizing(tokenizedBuffer) afterEach -> @@ -450,7 +450,7 @@ describe "TokenizedBuffer", -> 'abc\uD835\uDF97def' //\uD835\uDF97xyz """ - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) afterEach -> @@ -544,7 +544,7 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync() buffer.setText "
<%= User.find(2).full_name %>
" - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) tokenizedBuffer.setGrammar(atom.grammars.selectGrammar('test.erb')) fullyTokenize(tokenizedBuffer) @@ -566,7 +566,7 @@ describe "TokenizedBuffer", -> it "returns the correct token (regression)", -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([1, 0]).scopes).toEqual ["source.js"] expect(tokenizedBuffer.tokenForPosition([1, 1]).scopes).toEqual ["source.js"] @@ -575,7 +575,7 @@ describe "TokenizedBuffer", -> describe ".bufferRangeForScopeAtPosition(selector, position)", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) describe "when the selector does not match the token at the position", -> @@ -595,7 +595,7 @@ describe "TokenizedBuffer", -> it "updates the tab length of the tokenized lines", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' atom.config.set('editor.tabLength', 6) @@ -604,7 +604,7 @@ describe "TokenizedBuffer", -> it "does not allow the tab length to be less than 1", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' atom.config.set('editor.tabLength', 1) @@ -617,7 +617,7 @@ describe "TokenizedBuffer", -> it "updates the tokens with the appropriate invisible characters", -> buffer = new TextBuffer(text: " \t a line with tabs\tand \tspaces \t ") - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) atom.config.set("editor.showInvisibles", true) @@ -630,7 +630,7 @@ describe "TokenizedBuffer", -> it "assigns endOfLineInvisibles to tokenized lines", -> buffer = new TextBuffer(text: "a line that ends in a carriage-return-line-feed \r\na line that ends in just a line-feed\na line with no ending") - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) atom.config.set('editor.showInvisibles', true) atom.config.set("editor.invisibles", cr: 'R', eol: 'N') @@ -651,7 +651,7 @@ describe "TokenizedBuffer", -> describe "leading and trailing whitespace", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) it "assigns ::firstNonWhitespaceIndex on tokens that have leading whitespace", -> @@ -709,7 +709,7 @@ describe "TokenizedBuffer", -> describe ".indentLevel on tokenized lines", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) describe "when the line is non-empty", -> @@ -804,7 +804,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.insert [10, 0], " // multi-line\n // comment\n // block\n" buffer.insert [0, 0], "// multi-line\n// comment\n// block\n" - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) fullyTokenize(tokenizedBuffer) tokenizedBuffer.onDidChange (change) -> delete change.bufferChange @@ -881,7 +881,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.will-use-the-null-grammar') buffer.setText('a\nb\nc') - tokenizedBuffer = new TokenizedBuffer({buffer}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) tokenizeCallback = jasmine.createSpy('onDidTokenize') tokenizedBuffer.onDidTokenize(tokenizeCallback) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 06898fefe..aec58478a 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -28,7 +28,7 @@ class DisplayBuffer extends Model width: null @deserialize: (state, atomEnvironment) -> - state.tokenizedBuffer = TokenizedBuffer.deserialize(state.tokenizedBuffer) + state.tokenizedBuffer = TokenizedBuffer.deserialize(state.tokenizedBuffer, atomEnvironment) state.config = atomEnvironment.config state.assert = atomEnvironment.assert new this(state) @@ -39,7 +39,9 @@ class DisplayBuffer extends Model @emitter = new Emitter @disposables = new CompositeDisposable - @tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, ignoreInvisibles, @largeFileMode}) + @tokenizedBuffer ?= new TokenizedBuffer({ + tabLength, buffer, ignoreInvisibles, @largeFileMode, @config + }) @buffer = @tokenizedBuffer.buffer @charWidthsByScope = {} @markers = {} diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 70989239e..655ba049e 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -23,9 +23,10 @@ class TokenizedBuffer extends Model @deserialize: (state, atomEnvironment) -> state.buffer = atom.project.bufferForPathSync(state.bufferPath) + state.config = atomEnvironment.config new this(state) - constructor: ({@buffer, @tabLength, @ignoreInvisibles, @largeFileMode}) -> + constructor: ({@buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config}) -> @emitter = new Emitter @disposables = new CompositeDisposable @tokenIterator = new TokenIterator @@ -81,19 +82,19 @@ class TokenizedBuffer extends Model scopeOptions = {scope: @rootScopeDescriptor} @configSettings = - tabLength: atom.config.get('editor.tabLength', scopeOptions) - invisibles: atom.config.get('editor.invisibles', scopeOptions) - showInvisibles: atom.config.get('editor.showInvisibles', scopeOptions) + tabLength: @config.get('editor.tabLength', scopeOptions) + invisibles: @config.get('editor.invisibles', scopeOptions) + showInvisibles: @config.get('editor.showInvisibles', scopeOptions) if @configSubscriptions? @configSubscriptions.dispose() @disposables.remove(@configSubscriptions) @configSubscriptions = new CompositeDisposable - @configSubscriptions.add atom.config.onDidChange 'editor.tabLength', scopeOptions, ({newValue}) => + @configSubscriptions.add @config.onDidChange 'editor.tabLength', scopeOptions, ({newValue}) => @configSettings.tabLength = newValue @retokenizeLines() ['invisibles', 'showInvisibles'].forEach (key) => - @configSubscriptions.add atom.config.onDidChange "editor.#{key}", scopeOptions, ({newValue}) => + @configSubscriptions.add @config.onDidChange "editor.#{key}", scopeOptions, ({newValue}) => oldInvisibles = @getInvisiblesToShow() @configSettings[key] = newValue @retokenizeLines() unless _.isEqual(@getInvisiblesToShow(), oldInvisibles) From b2359f44a6cb7757010c1011c84f97f3dc4d8a93 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 11:13:38 -0600 Subject: [PATCH 075/316] =?UTF-8?q?Don=E2=80=99t=20use=20atom.grammars=20g?= =?UTF-8?q?lobal=20in=20TokenizedBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/display-buffer-spec.coffee | 25 +++++++++++++++++++------ spec/spec-helper.coffee | 3 ++- spec/token-iterator-spec.coffee | 2 +- spec/tokenized-buffer-spec.coffee | 30 +++++++++++++++--------------- spec/workspace-spec.coffee | 8 ++++---- src/atom.coffee | 2 +- src/display-buffer.coffee | 12 +++++++++--- src/text-editor.coffee | 9 ++++++--- src/tokenized-buffer.coffee | 27 ++++++++++++++++----------- src/workspace.coffee | 9 +++++++-- 10 files changed, 80 insertions(+), 47 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index ff57111fc..4dc65f57c 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -7,7 +7,9 @@ describe "DisplayBuffer", -> tabLength = 2 buffer = atom.project.bufferForPathSync('sample.js') - displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) + displayBuffer = new DisplayBuffer({ + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + }) changeHandler = jasmine.createSpy 'changeHandler' displayBuffer.onDidChange changeHandler @@ -49,7 +51,9 @@ describe "DisplayBuffer", -> it "updates the display buffer prior to invoking change handlers registered on the buffer", -> buffer.onDidChange -> expect(displayBuffer2.tokenizedLineForScreenRow(0).text).toBe "testing" - displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) + displayBuffer2 = new DisplayBuffer({ + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + }) buffer.setText("testing") describe "soft wrapping", -> @@ -232,7 +236,10 @@ describe "DisplayBuffer", -> describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", -> it "correctly renders the original wrapped line", -> buffer = atom.project.buildBufferSync(null, '') - displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, config: atom.config, assert: ->}) + displayBuffer = new DisplayBuffer({ + buffer, tabLength, editorWidthInChars: 30, config: atom.config, + grammarRegistry: atom.grammars, assert: -> + }) displayBuffer.setSoftWrapped(true) buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.") @@ -294,7 +301,9 @@ describe "DisplayBuffer", -> displayBuffer.destroy() buffer.release() buffer = atom.project.bufferForPathSync('two-hundred.txt') - displayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) + displayBuffer = new DisplayBuffer({ + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + }) displayBuffer.onDidChange changeHandler describe "when folds are created and destroyed", -> @@ -408,7 +417,9 @@ describe "DisplayBuffer", -> describe "when there is another display buffer pointing to the same buffer", -> it "does not consider folds to be nested inside of folds from the other display buffer", -> - otherDisplayBuffer = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) + otherDisplayBuffer = new DisplayBuffer({ + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + }) otherDisplayBuffer.createFold(1, 5) displayBuffer.createFold(2, 4) @@ -1154,7 +1165,9 @@ describe "DisplayBuffer", -> describe 'when there are multiple DisplayBuffers for a buffer', -> describe 'when a marker is created', -> it 'the second display buffer will not emit a marker-created event when the marker has been deleted in the first marker-created event', -> - displayBuffer2 = new DisplayBuffer({buffer, tabLength, config: atom.config, assert: ->}) + displayBuffer2 = new DisplayBuffer({ + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + }) displayBuffer.onDidCreateMarker markerCreated1 = jasmine.createSpy().andCallFake (marker) -> marker.destroy() displayBuffer2.onDidCreateMarker markerCreated2 = jasmine.createSpy() diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index cd3ead097..61ae8148e 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -92,7 +92,8 @@ beforeEach -> grammarRegistry: atom.grammars, notificationManager: atom.notifications, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), - clipboard: atom.clipboard, viewRegistry: atom.views, assert: atom.assert.bind(atom) + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, + assert: atom.assert.bind(atom) }) atom.themes.workspace = atom.workspace atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) diff --git a/spec/token-iterator-spec.coffee b/spec/token-iterator-spec.coffee index 994fce563..31ccc6be7 100644 --- a/spec/token-iterator-spec.coffee +++ b/spec/token-iterator-spec.coffee @@ -24,7 +24,7 @@ describe "TokenIterator", -> end x x """) - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) tokenizedBuffer.setGrammar(grammar) tokenIterator = tokenizedBuffer.tokenizedLineForRow(1).getTokenIterator() diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index bd832b505..60d356d2c 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -27,7 +27,7 @@ describe "TokenizedBuffer", -> describe "when the buffer is destroyed", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) startTokenizing(tokenizedBuffer) it "stops tokenization", -> @@ -39,7 +39,7 @@ describe "TokenizedBuffer", -> describe "when the buffer contains soft-tabs", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) startTokenizing(tokenizedBuffer) tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') @@ -345,7 +345,7 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) startTokenizing(tokenizedBuffer) afterEach -> @@ -450,7 +450,7 @@ describe "TokenizedBuffer", -> 'abc\uD835\uDF97def' //\uD835\uDF97xyz """ - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) afterEach -> @@ -544,7 +544,7 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync() buffer.setText "
<%= User.find(2).full_name %>
" - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) tokenizedBuffer.setGrammar(atom.grammars.selectGrammar('test.erb')) fullyTokenize(tokenizedBuffer) @@ -566,7 +566,7 @@ describe "TokenizedBuffer", -> it "returns the correct token (regression)", -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([1, 0]).scopes).toEqual ["source.js"] expect(tokenizedBuffer.tokenForPosition([1, 1]).scopes).toEqual ["source.js"] @@ -575,7 +575,7 @@ describe "TokenizedBuffer", -> describe ".bufferRangeForScopeAtPosition(selector, position)", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) describe "when the selector does not match the token at the position", -> @@ -595,7 +595,7 @@ describe "TokenizedBuffer", -> it "updates the tab length of the tokenized lines", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' atom.config.set('editor.tabLength', 6) @@ -604,7 +604,7 @@ describe "TokenizedBuffer", -> it "does not allow the tab length to be less than 1", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' atom.config.set('editor.tabLength', 1) @@ -617,7 +617,7 @@ describe "TokenizedBuffer", -> it "updates the tokens with the appropriate invisible characters", -> buffer = new TextBuffer(text: " \t a line with tabs\tand \tspaces \t ") - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) atom.config.set("editor.showInvisibles", true) @@ -630,7 +630,7 @@ describe "TokenizedBuffer", -> it "assigns endOfLineInvisibles to tokenized lines", -> buffer = new TextBuffer(text: "a line that ends in a carriage-return-line-feed \r\na line that ends in just a line-feed\na line with no ending") - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) atom.config.set('editor.showInvisibles', true) atom.config.set("editor.invisibles", cr: 'R', eol: 'N') @@ -651,7 +651,7 @@ describe "TokenizedBuffer", -> describe "leading and trailing whitespace", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) it "assigns ::firstNonWhitespaceIndex on tokens that have leading whitespace", -> @@ -709,7 +709,7 @@ describe "TokenizedBuffer", -> describe ".indentLevel on tokenized lines", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) describe "when the line is non-empty", -> @@ -804,7 +804,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.insert [10, 0], " // multi-line\n // comment\n // block\n" buffer.insert [0, 0], "// multi-line\n// comment\n// block\n" - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) fullyTokenize(tokenizedBuffer) tokenizedBuffer.onDidChange (change) -> delete change.bufferChange @@ -881,7 +881,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.will-use-the-null-grammar') buffer.setText('a\nb\nc') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config}) + tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) tokenizeCallback = jasmine.createSpy('onDidTokenize') tokenizedBuffer.onDidTokenize(tokenizeCallback) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 5255094a4..54f171ff8 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -17,7 +17,7 @@ describe "Workspace", -> atom.workspace = workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, - clipboard: atom.clipboard, viewRegistry: atom.views, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) @@ -35,7 +35,7 @@ describe "Workspace", -> atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, - clipboard: atom.clipboard, viewRegistry: atom.views, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, assert: atom.assert.bind(atom) }) @@ -634,7 +634,7 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, - clipboard: atom.clipboard, viewRegistry: atom.views, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) @@ -694,7 +694,7 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, notificationManager: atom.notifications, - clipboard: atom.clipboard, viewRegistry: atom.views, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) diff --git a/src/atom.coffee b/src/atom.coffee index dd6dbbcce..f3c3f10c0 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -176,7 +176,7 @@ class Atom extends Model @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, - assert: @assert.bind(this) + grammarRegistry: @grammars, assert: @assert.bind(this) }) @themes.workspace = @workspace diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index aec58478a..93d5c40ed 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -31,16 +31,22 @@ class DisplayBuffer extends Model state.tokenizedBuffer = TokenizedBuffer.deserialize(state.tokenizedBuffer, atomEnvironment) state.config = atomEnvironment.config state.assert = atomEnvironment.assert + state.grammarRegistry = atomEnvironment.grammars new this(state) - constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, @largeFileMode, @config, @assert}={}) -> + constructor: (params={}) -> super + { + tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, + @largeFileMode, @config, @assert, @grammarRegistry + } = params + @emitter = new Emitter @disposables = new CompositeDisposable @tokenizedBuffer ?= new TokenizedBuffer({ - tabLength, buffer, ignoreInvisibles, @largeFileMode, @config + tabLength, buffer, ignoreInvisibles, @largeFileMode, @config, @grammarRegistry }) @buffer = @tokenizedBuffer.buffer @charWidthsByScope = {} @@ -103,7 +109,7 @@ class DisplayBuffer extends Model copy: -> newDisplayBuffer = new DisplayBuffer({ - @buffer, tabLength: @getTabLength(), @largeFileMode, @config, @assert + @buffer, tabLength: @getTabLength(), @largeFileMode, @config, @assert, @grammarRegistry }) for marker in @findMarkers(displayBufferId: @id) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 54e80b632..0650c4e78 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -78,6 +78,7 @@ class TextEditor extends Model state.notificationManager = atomEnvironment.notifications state.clipboard = atomEnvironment.clipboard state.viewRegistry = atomEnvironment.views + state.grammarRegistry = atomEnvironment.grammars state.project = atomEnvironment.project state.assert = atomEnvironment.assert.bind(atomEnvironment) new this(state) @@ -89,13 +90,14 @@ class TextEditor extends Model @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard, - @viewRegistry, @project, @assert + @viewRegistry, @grammarRegistry, @project, @assert } = params throw new Error("Must pass a config parameter when constructing TextEditors") unless @config? throw new Error("Must pass a notificationManager parameter when constructing TextEditors") unless @notificationManager? throw new Error("Must pass a clipboard parameter when constructing TextEditors") unless @clipboard? throw new Error("Must pass a viewRegistry parameter when constructing TextEditors") unless @viewRegistry? + throw new Error("Must pass a grammarRegistry parameter when constructing TextEditors") unless @grammarRegistry? throw new Error("Must pass a project parameter when constructing TextEditors") unless @project? throw new Error("Must pass an assert parameter when constructing TextEditors") unless @assert? @@ -107,7 +109,7 @@ class TextEditor extends Model buffer ?= new TextBuffer @displayBuffer ?= new DisplayBuffer({ buffer, tabLength, softWrapped, ignoreInvisibles: @mini, largeFileMode, - @config, @assert + @config, @assert, @grammarRegistry }) @buffer = @displayBuffer.buffer @@ -475,7 +477,8 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - @config, @notificationManager, @clipboard, @viewRegistry, @project, @assert + @config, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, + @project, @assert }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 655ba049e..28d33ebf1 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -24,15 +24,20 @@ class TokenizedBuffer extends Model @deserialize: (state, atomEnvironment) -> state.buffer = atom.project.bufferForPathSync(state.bufferPath) state.config = atomEnvironment.config + state.grammarRegistry = atomEnvironment.grammars new this(state) - constructor: ({@buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config}) -> + constructor: (params) -> + { + @buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config, @grammarRegistry + } = params + @emitter = new Emitter @disposables = new CompositeDisposable @tokenIterator = new TokenIterator - @disposables.add atom.grammars.onDidAddGrammar(@grammarAddedOrUpdated) - @disposables.add atom.grammars.onDidUpdateGrammar(@grammarAddedOrUpdated) + @disposables.add @grammarRegistry.onDidAddGrammar(@grammarAddedOrUpdated) + @disposables.add @grammarRegistry.onDidUpdateGrammar(@grammarAddedOrUpdated) @disposables.add @buffer.preemptDidChange (e) => @handleBufferChange(e) @disposables.add @buffer.onDidChangePath (@bufferPath) => @reloadGrammar() @@ -66,7 +71,7 @@ class TokenizedBuffer extends Model if grammar.injectionSelector? @retokenizeLines() if @hasTokenForSelector(grammar.injectionSelector) else - newScore = atom.grammars.getGrammarScore(grammar, @buffer.getPath(), @getGrammarSelectionContent()) + newScore = @grammarRegistry.getGrammarScore(grammar, @buffer.getPath(), @getGrammarSelectionContent()) @setGrammar(grammar, newScore) if newScore > @currentGrammarScore setGrammar: (grammar, score) -> @@ -74,7 +79,7 @@ class TokenizedBuffer extends Model @grammar = grammar @rootScopeDescriptor = new ScopeDescriptor(scopes: [@grammar.scopeName]) - @currentGrammarScore = score ? atom.grammars.getGrammarScore(grammar, @buffer.getPath(), @getGrammarSelectionContent()) + @currentGrammarScore = score ? @grammarRegistry.getGrammarScore(grammar, @buffer.getPath(), @getGrammarSelectionContent()) @grammarUpdateDisposable?.dispose() @grammarUpdateDisposable = @grammar.onDidUpdate => @retokenizeLines() @@ -108,7 +113,7 @@ class TokenizedBuffer extends Model @buffer.getTextInRange([[0, 0], [10, 0]]) reloadGrammar: -> - if grammar = atom.grammars.selectGrammar(@buffer.getPath(), @getGrammarSelectionContent()) + if grammar = @grammarRegistry.selectGrammar(@buffer.getPath(), @getGrammarSelectionContent()) @setGrammar(grammar) else throw new Error("No grammar found for path: #{path}") @@ -156,7 +161,7 @@ class TokenizedBuffer extends Model tokenizeNextChunk: -> # Short circuit null grammar which can just use the placeholder tokens - if @grammar is atom.grammars.nullGrammar and @firstInvalidRow()? + if @grammar is @grammarRegistry.nullGrammar and @firstInvalidRow()? @invalidRows = [] @markTokenizationComplete() return @@ -473,13 +478,13 @@ class TokenizedBuffer extends Model position = Point.fromObject(position) {openScopes, tags} = @tokenizedLineForRow(position.row) - scopes = openScopes.map (tag) -> atom.grammars.scopeForId(tag) + scopes = openScopes.map (tag) => @grammarRegistry.scopeForId(tag) startColumn = 0 for tag, tokenIndex in tags if tag < 0 if tag % 2 is -1 - scopes.push(atom.grammars.scopeForId(tag)) + scopes.push(@grammarRegistry.scopeForId(tag)) else scopes.pop() else @@ -499,7 +504,7 @@ class TokenizedBuffer extends Model if tag % 2 is -1 startScopes.pop() else - startScopes.push(atom.grammars.scopeForId(tag)) + startScopes.push(@grammarRegistry.scopeForId(tag)) else break unless selectorMatchesAnyScope(selector, startScopes) startColumn -= tag @@ -509,7 +514,7 @@ class TokenizedBuffer extends Model tag = tags[endTokenIndex] if tag < 0 if tag % 2 is -1 - endScopes.push(atom.grammars.scopeForId(tag)) + endScopes.push(@grammarRegistry.scopeForId(tag)) else endScopes.pop() else diff --git a/src/workspace.coffee b/src/workspace.coffee index c962d45b2..b4e0abc71 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -28,7 +28,8 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, - @clipboard, @viewRegistry, @setRepresentedFilename, @setDocumentEdited, @assert + @clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, + @setDocumentEdited, @assert } = params debugger unless @assert? @@ -460,7 +461,11 @@ class Workspace extends Model @buildTextEditor(_.extend({buffer, largeFileMode}, options)) buildTextEditor: (params) -> - new TextEditor(_.extend({@config, @notificationManager, @clipboard, @viewRegistry, @project, @assert}, params)) + params = _.extend({ + @config, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, + @project, @assert + }, params) + new TextEditor(params) # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. From 122bf72c75cf1f8832d864a6200347d510142370 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 3 Oct 2015 11:31:30 -0600 Subject: [PATCH 076/316] =?UTF-8?q?Don=E2=80=99t=20use=20atom.packages=20g?= =?UTF-8?q?lobal=20in=20TokenizedBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/display-buffer-spec.coffee | 17 ++++++--- spec/token-iterator-spec.coffee | 4 +- spec/tokenized-buffer-spec.coffee | 61 +++++++++++++++++++++++-------- src/display-buffer.coffee | 9 +++-- src/text-editor.coffee | 12 +++--- src/tokenized-buffer.coffee | 6 ++- src/workspace.coffee | 4 +- 7 files changed, 79 insertions(+), 34 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 4dc65f57c..0703991de 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -8,7 +8,8 @@ describe "DisplayBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') displayBuffer = new DisplayBuffer({ - buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, + packageManager: atom.packages, assert: -> }) changeHandler = jasmine.createSpy 'changeHandler' displayBuffer.onDidChange changeHandler @@ -52,7 +53,8 @@ describe "DisplayBuffer", -> it "updates the display buffer prior to invoking change handlers registered on the buffer", -> buffer.onDidChange -> expect(displayBuffer2.tokenizedLineForScreenRow(0).text).toBe "testing" displayBuffer2 = new DisplayBuffer({ - buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, + packageManager: atom.packages, assert: -> }) buffer.setText("testing") @@ -238,7 +240,7 @@ describe "DisplayBuffer", -> buffer = atom.project.buildBufferSync(null, '') displayBuffer = new DisplayBuffer({ buffer, tabLength, editorWidthInChars: 30, config: atom.config, - grammarRegistry: atom.grammars, assert: -> + grammarRegistry: atom.grammars, packageManager: atom.packages, assert: -> }) displayBuffer.setSoftWrapped(true) @@ -302,7 +304,8 @@ describe "DisplayBuffer", -> buffer.release() buffer = atom.project.bufferForPathSync('two-hundred.txt') displayBuffer = new DisplayBuffer({ - buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, + packageManager: atom.packages, assert: -> }) displayBuffer.onDidChange changeHandler @@ -418,7 +421,8 @@ describe "DisplayBuffer", -> describe "when there is another display buffer pointing to the same buffer", -> it "does not consider folds to be nested inside of folds from the other display buffer", -> otherDisplayBuffer = new DisplayBuffer({ - buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, + packageManager: atom.packages, assert: -> }) otherDisplayBuffer.createFold(1, 5) @@ -1166,7 +1170,8 @@ describe "DisplayBuffer", -> describe 'when a marker is created', -> it 'the second display buffer will not emit a marker-created event when the marker has been deleted in the first marker-created event', -> displayBuffer2 = new DisplayBuffer({ - buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, assert: -> + buffer, tabLength, config: atom.config, grammarRegistry: atom.grammars, + packageManager: atom.packages, assert: -> }) displayBuffer.onDidCreateMarker markerCreated1 = jasmine.createSpy().andCallFake (marker) -> marker.destroy() displayBuffer2.onDidCreateMarker markerCreated2 = jasmine.createSpy() diff --git a/spec/token-iterator-spec.coffee b/spec/token-iterator-spec.coffee index 31ccc6be7..b71a879d3 100644 --- a/spec/token-iterator-spec.coffee +++ b/spec/token-iterator-spec.coffee @@ -24,7 +24,9 @@ describe "TokenIterator", -> end x x """) - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) tokenizedBuffer.setGrammar(grammar) tokenIterator = tokenizedBuffer.tokenizedLineForRow(1).getTokenIterator() diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index 60d356d2c..a9c538da2 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -27,7 +27,9 @@ describe "TokenizedBuffer", -> describe "when the buffer is destroyed", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) startTokenizing(tokenizedBuffer) it "stops tokenization", -> @@ -39,7 +41,9 @@ describe "TokenizedBuffer", -> describe "when the buffer contains soft-tabs", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) startTokenizing(tokenizedBuffer) tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') @@ -345,7 +349,9 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) startTokenizing(tokenizedBuffer) afterEach -> @@ -450,7 +456,9 @@ describe "TokenizedBuffer", -> 'abc\uD835\uDF97def' //\uD835\uDF97xyz """ - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) afterEach -> @@ -544,7 +552,9 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync() buffer.setText "
<%= User.find(2).full_name %>
" - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) tokenizedBuffer.setGrammar(atom.grammars.selectGrammar('test.erb')) fullyTokenize(tokenizedBuffer) @@ -566,7 +576,9 @@ describe "TokenizedBuffer", -> it "returns the correct token (regression)", -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([1, 0]).scopes).toEqual ["source.js"] expect(tokenizedBuffer.tokenForPosition([1, 1]).scopes).toEqual ["source.js"] @@ -575,7 +587,10 @@ describe "TokenizedBuffer", -> describe ".bufferRangeForScopeAtPosition(selector, position)", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, + packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) describe "when the selector does not match the token at the position", -> @@ -595,7 +610,9 @@ describe "TokenizedBuffer", -> it "updates the tab length of the tokenized lines", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' atom.config.set('editor.tabLength', 6) @@ -604,7 +621,9 @@ describe "TokenizedBuffer", -> it "does not allow the tab length to be less than 1", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' atom.config.set('editor.tabLength', 1) @@ -617,7 +636,9 @@ describe "TokenizedBuffer", -> it "updates the tokens with the appropriate invisible characters", -> buffer = new TextBuffer(text: " \t a line with tabs\tand \tspaces \t ") - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) atom.config.set("editor.showInvisibles", true) @@ -630,7 +651,9 @@ describe "TokenizedBuffer", -> it "assigns endOfLineInvisibles to tokenized lines", -> buffer = new TextBuffer(text: "a line that ends in a carriage-return-line-feed \r\na line that ends in just a line-feed\na line with no ending") - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) atom.config.set('editor.showInvisibles', true) atom.config.set("editor.invisibles", cr: 'R', eol: 'N') @@ -651,7 +674,9 @@ describe "TokenizedBuffer", -> describe "leading and trailing whitespace", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) it "assigns ::firstNonWhitespaceIndex on tokens that have leading whitespace", -> @@ -709,7 +734,9 @@ describe "TokenizedBuffer", -> describe ".indentLevel on tokenized lines", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) describe "when the line is non-empty", -> @@ -804,7 +831,9 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.insert [10, 0], " // multi-line\n // comment\n // block\n" buffer.insert [0, 0], "// multi-line\n// comment\n// block\n" - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) fullyTokenize(tokenizedBuffer) tokenizedBuffer.onDidChange (change) -> delete change.bufferChange @@ -881,7 +910,9 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.will-use-the-null-grammar') buffer.setText('a\nb\nc') - tokenizedBuffer = new TokenizedBuffer({buffer, config: atom.config, grammarRegistry: atom.grammars}) + tokenizedBuffer = new TokenizedBuffer({ + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + }) tokenizeCallback = jasmine.createSpy('onDidTokenize') tokenizedBuffer.onDidTokenize(tokenizeCallback) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 93d5c40ed..26226f515 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -32,6 +32,7 @@ class DisplayBuffer extends Model state.config = atomEnvironment.config state.assert = atomEnvironment.assert state.grammarRegistry = atomEnvironment.grammars + state.packageManager = atomEnvironment.packages new this(state) constructor: (params={}) -> @@ -39,14 +40,15 @@ class DisplayBuffer extends Model { tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles, - @largeFileMode, @config, @assert, @grammarRegistry + @largeFileMode, @config, @assert, @grammarRegistry, @packageManager } = params @emitter = new Emitter @disposables = new CompositeDisposable @tokenizedBuffer ?= new TokenizedBuffer({ - tabLength, buffer, ignoreInvisibles, @largeFileMode, @config, @grammarRegistry + tabLength, buffer, ignoreInvisibles, @largeFileMode, @config, + @grammarRegistry, @packageManager }) @buffer = @tokenizedBuffer.buffer @charWidthsByScope = {} @@ -109,7 +111,8 @@ class DisplayBuffer extends Model copy: -> newDisplayBuffer = new DisplayBuffer({ - @buffer, tabLength: @getTabLength(), @largeFileMode, @config, @assert, @grammarRegistry + @buffer, tabLength: @getTabLength(), @largeFileMode, @config, @assert, + @grammarRegistry, @packageManager }) for marker in @findMarkers(displayBufferId: @id) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 0650c4e78..14c3312a0 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -76,6 +76,7 @@ class TextEditor extends Model state.displayBuffer = displayBuffer state.config = atomEnvironment.config state.notificationManager = atomEnvironment.notifications + state.packageManager = atomEnvironment.packages state.clipboard = atomEnvironment.clipboard state.viewRegistry = atomEnvironment.views state.grammarRegistry = atomEnvironment.grammars @@ -89,12 +90,13 @@ class TextEditor extends Model { @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, - lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @clipboard, - @viewRegistry, @grammarRegistry, @project, @assert + lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @packageManager, + @clipboard, @viewRegistry, @grammarRegistry, @project, @assert } = params throw new Error("Must pass a config parameter when constructing TextEditors") unless @config? throw new Error("Must pass a notificationManager parameter when constructing TextEditors") unless @notificationManager? + throw new Error("Must pass a packageManager parameter when constructing TextEditors") unless @packageManager? throw new Error("Must pass a clipboard parameter when constructing TextEditors") unless @clipboard? throw new Error("Must pass a viewRegistry parameter when constructing TextEditors") unless @viewRegistry? throw new Error("Must pass a grammarRegistry parameter when constructing TextEditors") unless @grammarRegistry? @@ -109,7 +111,7 @@ class TextEditor extends Model buffer ?= new TextBuffer @displayBuffer ?= new DisplayBuffer({ buffer, tabLength, softWrapped, ignoreInvisibles: @mini, largeFileMode, - @config, @assert, @grammarRegistry + @config, @assert, @grammarRegistry, @packageManager }) @buffer = @displayBuffer.buffer @@ -477,8 +479,8 @@ class TextEditor extends Model softTabs = @getSoftTabs() newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, - @config, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, - @project, @assert + @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, + @grammarRegistry, @project, @assert }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 28d33ebf1..4f66cf96b 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -25,11 +25,13 @@ class TokenizedBuffer extends Model state.buffer = atom.project.bufferForPathSync(state.bufferPath) state.config = atomEnvironment.config state.grammarRegistry = atomEnvironment.grammars + state.packageManager = atomEnvironment.packages new this(state) constructor: (params) -> { - @buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config, @grammarRegistry + @buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config, + @grammarRegistry, @packageManager } = params @emitter = new Emitter @@ -106,7 +108,7 @@ class TokenizedBuffer extends Model @disposables.add(@configSubscriptions) @retokenizeLines() - atom.packages.triggerActivationHook("#{grammar.packageName}:grammar-used") + @packageManager.triggerActivationHook("#{grammar.packageName}:grammar-used") @emitter.emit 'did-change-grammar', grammar getGrammarSelectionContent: -> diff --git a/src/workspace.coffee b/src/workspace.coffee index b4e0abc71..423e70112 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -462,8 +462,8 @@ class Workspace extends Model buildTextEditor: (params) -> params = _.extend({ - @config, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, - @project, @assert + @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, + @grammarRegistry, @project, @assert }, params) new TextEditor(params) From 4d2d4c3cc47693062dfc93475d397268b47cbdc9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Oct 2015 10:51:01 -0700 Subject: [PATCH 077/316] Add deprecated shim for TextEditor export --- exports/atom.coffee | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/exports/atom.coffee b/exports/atom.coffee index 1ceb60fa9..c3601e1cc 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -2,6 +2,7 @@ TextBuffer = require 'text-buffer' {Point, Range} = TextBuffer {File, Directory} = require 'pathwatcher' {Emitter, Disposable, CompositeDisposable} = require 'event-kit' +Grim = require 'grim' module.exports = BufferedNodeProcess: require '../src/buffered-node-process' @@ -21,4 +22,20 @@ module.exports = # only be exported when not running as a child node process unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE module.exports.Task = require '../src/task' - module.exports.TextEditor = require '../src/text-editor' + + TextEditor = (params) -> + atom.workspace.buildTextEditor(params) + + TextEditor.prototype = require('../src/text-editor').prototype + + Object.defineProperty module.exports, 'TextEditor', + enumerable: true + get: -> + Grim.deprecate """ + The `TextEditor` constructor is no longer public. + + To construct a text editor, use `atom.workspace.buildTextEditor()`. + To check if an object is a text editor, look for for the existence of + a public method that you're using (e.g. `::getText`). + """ + TextEditor From d8b08d3240ab53a53f12a3feef39e10f4f5759d8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Oct 2015 10:51:36 -0700 Subject: [PATCH 078/316] Don't use atom.config global in LanguageMode --- src/language-mode.coffee | 8 ++++---- src/text-editor.coffee | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/language-mode.coffee b/src/language-mode.coffee index e60e85f7f..55707bad3 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -8,7 +8,7 @@ class LanguageMode # Sets up a `LanguageMode` for the given {TextEditor}. # # editor - The {TextEditor} to associate with - constructor: (@editor) -> + constructor: (@editor, @config) -> {@buffer} = @editor destroy: -> @@ -327,7 +327,7 @@ class LanguageMode @editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel) getRegexForProperty: (scopeDescriptor, property) -> - if pattern = atom.config.get(property, scope: scopeDescriptor) + if pattern = @config.get(property, scope: scopeDescriptor) new OnigRegExp(pattern) increaseIndentRegexForScopeDescriptor: (scopeDescriptor) -> @@ -343,8 +343,8 @@ class LanguageMode @getRegexForProperty(scopeDescriptor, 'editor.foldEndPattern') commentStartAndEndStringsForScope: (scope) -> - commentStartEntry = atom.config.getAll('editor.commentStart', {scope})[0] - commentEndEntry = _.find atom.config.getAll('editor.commentEnd', {scope}), (entry) -> + commentStartEntry = @config.getAll('editor.commentStart', {scope})[0] + commentEndEntry = _.find @config.getAll('editor.commentEnd', {scope}), (entry) -> entry.scopeSelector is commentStartEntry.scopeSelector commentStartString = commentStartEntry?.value commentEndString = commentEndEntry?.value diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 14c3312a0..c59cf1455 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -128,7 +128,7 @@ class TextEditor extends Model initialColumn = Math.max(parseInt(initialColumn) or 0, 0) @addCursorAtBufferPosition([initialLine, initialColumn]) - @languageMode = new LanguageMode(this) + @languageMode = new LanguageMode(this, @config) @setEncoding(@config.get('core.fileEncoding', scope: @getRootScopeDescriptor())) From e9cda3ea5cdb77bbbf9e9f88788a535af8a94ac9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 5 Oct 2015 11:50:33 +0200 Subject: [PATCH 079/316] Don't use atom.views global in PanelElement --- spec/panel-element-spec.coffee | 4 ++-- src/atom.coffee | 6 +++--- src/panel-element.coffee | 6 ++++-- src/view-registry.coffee | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/spec/panel-element-spec.coffee b/spec/panel-element-spec.coffee index 4c166c617..73108e25d 100644 --- a/spec/panel-element-spec.coffee +++ b/spec/panel-element-spec.coffee @@ -18,8 +18,8 @@ describe "PanelElement", -> beforeEach -> jasmineContent = document.body.querySelector('#jasmine-content') - atom.views.addViewProvider Panel, (model) -> - new PanelElement().initialize(model) + atom.views.addViewProvider Panel, (model, env) -> + new PanelElement().initialize(model, env) atom.views.addViewProvider TestPanelItem, (model) -> new TestPanelItemElement().initialize(model) diff --git a/src/atom.coffee b/src/atom.coffee index f3c3f10c0..951d8d16d 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -119,7 +119,7 @@ class Atom extends Model @registerDeserializers() ViewRegistry = require './view-registry' - @views = new ViewRegistry + @views = new ViewRegistry(this) @registerViewProviders() NotificationManager = require './notification-manager' @@ -199,8 +199,8 @@ class Atom extends Model new WorkspaceElement().initialize(model) @views.addViewProvider PanelContainer, (model) -> new PanelContainerElement().initialize(model) - @views.addViewProvider Panel, (model) -> - new PanelElement().initialize(model) + @views.addViewProvider Panel, (model, env) -> + new PanelElement().initialize(model, env) @views.addViewProvider PaneContainer, (model) -> new PaneContainerElement().initialize(model) @views.addViewProvider PaneAxis, (model) -> diff --git a/src/panel-element.coffee b/src/panel-element.coffee index 287d34940..8d6aadae4 100644 --- a/src/panel-element.coffee +++ b/src/panel-element.coffee @@ -5,7 +5,9 @@ class PanelElement extends HTMLElement createdCallback: -> @subscriptions = new CompositeDisposable - initialize: (@model) -> + initialize: (@model, {@views}) -> + throw new Error("Must pass a views parameter when initializing PanelElements") unless @views? + @appendChild(@getItemView()) @classList.add(@model.getClassName().split(' ')...) if @model.getClassName()? @@ -17,7 +19,7 @@ class PanelElement extends HTMLElement @model ?= new Panel getItemView: -> - atom.views.getView(@getModel().getItem()) + @views.getView(@getModel().getItem()) attachedCallback: -> @visibleChanged(@getModel().isVisible()) diff --git a/src/view-registry.coffee b/src/view-registry.coffee index 6af7bd024..c9abd8852 100644 --- a/src/view-registry.coffee +++ b/src/view-registry.coffee @@ -49,7 +49,7 @@ class ViewRegistry debouncedPerformDocumentPoll: null minimumPollInterval: 200 - constructor: -> + constructor: (@atomEnvironment) -> @views = new WeakMap @providers = [] @documentWriters = [] @@ -159,7 +159,7 @@ class ViewRegistry else if object?.jquery object[0] else if provider = @findProvider(object) - element = provider.createView?(object) + element = provider.createView?(object, @atomEnvironment) unless element? element = new provider.viewConstructor element.initialize?(object) ? element.setModel?(object) From 2479b0cae29b608da114d91dabec063489babadd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 5 Oct 2015 12:06:41 +0200 Subject: [PATCH 080/316] Don't use atom globals in WorkspaceElement --- src/atom.coffee | 4 +-- src/workspace-element.coffee | 49 ++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 951d8d16d..eed53dbf1 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -195,8 +195,8 @@ class Atom extends Model @deserializers.add(TextBuffer) registerViewProviders: -> - @views.addViewProvider Workspace, (model) -> - new WorkspaceElement().initialize(model) + @views.addViewProvider Workspace, (model, env) -> + new WorkspaceElement().initialize(model, env) @views.addViewProvider PanelContainer, (model) -> new PanelContainerElement().initialize(model) @views.addViewProvider Panel, (model, env) -> diff --git a/src/workspace-element.coffee b/src/workspace-element.coffee index c8ad1fe0d..b7a1575d8 100644 --- a/src/workspace-element.coffee +++ b/src/workspace-element.coffee @@ -8,12 +8,6 @@ module.exports = class WorkspaceElement extends HTMLElement globalTextEditorStyleSheet: null - createdCallback: -> - @subscriptions = new CompositeDisposable - @initializeContent() - @observeScrollbarStyle() - @observeTextEditorFontConfig() - attachedCallback: -> @focus() @@ -46,31 +40,42 @@ class WorkspaceElement extends HTMLElement observeTextEditorFontConfig: -> @updateGlobalTextEditorStyleSheet() - @subscriptions.add atom.config.onDidChange 'editor.fontSize', @updateGlobalTextEditorStyleSheet.bind(this) - @subscriptions.add atom.config.onDidChange 'editor.fontFamily', @updateGlobalTextEditorStyleSheet.bind(this) - @subscriptions.add atom.config.onDidChange 'editor.lineHeight', @updateGlobalTextEditorStyleSheet.bind(this) + @subscriptions.add @config.onDidChange 'editor.fontSize', @updateGlobalTextEditorStyleSheet.bind(this) + @subscriptions.add @config.onDidChange 'editor.fontFamily', @updateGlobalTextEditorStyleSheet.bind(this) + @subscriptions.add @config.onDidChange 'editor.lineHeight', @updateGlobalTextEditorStyleSheet.bind(this) updateGlobalTextEditorStyleSheet: -> styleSheetSource = """ atom-text-editor { - font-size: #{atom.config.get('editor.fontSize')}px; - font-family: #{atom.config.get('editor.fontFamily')}; - line-height: #{atom.config.get('editor.lineHeight')}; + font-size: #{@config.get('editor.fontSize')}px; + font-family: #{@config.get('editor.fontFamily')}; + line-height: #{@config.get('editor.lineHeight')}; } """ atom.styles.addStyleSheet(styleSheetSource, sourcePath: 'global-text-editor-styles') - initialize: (@model) -> - @paneContainer = atom.views.getView(@model.paneContainer) + initialize: (@model, {@views, @workspace, @project, @config, @styles}) -> + throw new Error("Must pass a views parameter when initializing WorskpaceElements") unless @views? + throw new Error("Must pass a workspace parameter when initializing WorskpaceElements") unless @workspace? + throw new Error("Must pass a project parameter when initializing WorskpaceElements") unless @project? + throw new Error("Must pass a config parameter when initializing WorskpaceElements") unless @config? + throw new Error("Must pass a styles parameter when initializing WorskpaceElements") unless @styles? + + @subscriptions = new CompositeDisposable + @initializeContent() + @observeScrollbarStyle() + @observeTextEditorFontConfig() + + @paneContainer = @views.getView(@model.paneContainer) @verticalAxis.appendChild(@paneContainer) @addEventListener 'focus', @handleFocus.bind(this) @panelContainers = - top: atom.views.getView(@model.panelContainers.top) - left: atom.views.getView(@model.panelContainers.left) - right: atom.views.getView(@model.panelContainers.right) - bottom: atom.views.getView(@model.panelContainers.bottom) - modal: atom.views.getView(@model.panelContainers.modal) + top: @views.getView(@model.panelContainers.top) + left: @views.getView(@model.panelContainers.left) + right: @views.getView(@model.panelContainers.right) + bottom: @views.getView(@model.panelContainers.bottom) + modal: @views.getView(@model.panelContainers.modal) @horizontalAxis.insertBefore(@panelContainers.left, @verticalAxis) @horizontalAxis.appendChild(@panelContainers.right) @@ -96,10 +101,10 @@ class WorkspaceElement extends HTMLElement focusPaneViewOnRight: -> @paneContainer.focusPaneViewOnRight() runPackageSpecs: -> - if activePath = atom.workspace.getActivePaneItem()?.getPath?() - [projectPath] = atom.project.relativizePath(activePath) + if activePath = @workspace.getActivePaneItem()?.getPath?() + [projectPath] = @project.relativizePath(activePath) else - [projectPath] = atom.project.getPaths() + [projectPath] = @project.getPaths() ipc.send('run-package-specs', path.join(projectPath, 'spec')) if projectPath module.exports = WorkspaceElement = document.registerElement 'atom-workspace', prototype: WorkspaceElement.prototype From d9776abea67dcbbfe67ab65fc0b1b589352963ab Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 15:09:52 -0600 Subject: [PATCH 081/316] Rename Atom to AtomEnvironment --- src/{atom.coffee => atom-environment.coffee} | 2 +- src/initialize-application-window.coffee | 4 ++-- src/initialize-test-window.coffee | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/{atom.coffee => atom-environment.coffee} (99%) diff --git a/src/atom.coffee b/src/atom-environment.coffee similarity index 99% rename from src/atom.coffee rename to src/atom-environment.coffee index eed53dbf1..e613361f8 100644 --- a/src/atom.coffee +++ b/src/atom-environment.coffee @@ -40,7 +40,7 @@ TextEditorElement = require './text-editor-element' # # An instance of this class is always available as the `atom` global. module.exports = -class Atom extends Model +class AtomEnvironment extends Model @version: 1 # Increment this when the serialization format changes workspaceParentSelectorctor: 'body' diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index a10cc9dba..b10208bb1 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -14,8 +14,8 @@ process.env.NODE_PATH = exportsPath # Make React faster process.env.NODE_ENV ?= 'production' unless devMode -Atom = require './atom' -window.atom = new Atom +AtomEnvironment = require './atom-environment' +window.atom = new AtomEnvironment atom.displayWindow() atom.loadStateSync() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index ad854d89a..9e60fa372 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -6,8 +6,8 @@ try ipc = require 'ipc' require '../src/window' - Atom = require '../src/atom' - window.atom = new Atom + AtomEnvironment = require '../src/atom-environment' + window.atom = new AtomEnvironment # Show window synchronously so a focusout doesn't fire on input elements # that are focused in the very first spec run. From dcb1d8296f94a05a63c7f0b5df416c8364ac3f14 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 15:21:46 -0600 Subject: [PATCH 082/316] Pass buildAtomEnvironment function to test runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t build an AtomEnvironment or assign it to the atom global until this function is called by the runner. --- spec/jasmine-test-runner.coffee | 4 +++- src/initialize-test-window.coffee | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 0f795af0a..35f08e2ac 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -5,7 +5,9 @@ path = require 'path' ipc = require 'ipc' StylesElement = require '../src/styles-element' -module.exports = ({logFile, headless, testPaths}) -> +module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> + window.atom = buildAtomEnvironment() + window[key] = value for key, value of require '../vendor/jasmine' require 'jasmine-tagged' diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 9e60fa372..ff30da4ac 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -4,14 +4,13 @@ require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') try path = require 'path' ipc = require 'ipc' - - require '../src/window' + remote = require 'remote' + {getWindowLoadSettings} = require './window-load-settings-helpers' AtomEnvironment = require '../src/atom-environment' - window.atom = new AtomEnvironment # Show window synchronously so a focusout doesn't fire on input elements # that are focused in the very first spec run. - atom.getCurrentWindow().show() unless atom.getLoadSettings().headless + remote.getCurrentWindow().show() unless getWindowLoadSettings().headless window.addEventListener 'keydown', (event) -> # Reload: cmd-r / ctrl-r @@ -27,22 +26,25 @@ try ipc.send('call-window-method', 'close') # Add 'exports' to module search path. - exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports') + exportsPath = path.join(getWindowLoadSettings().resourcePath, 'exports') require('module').globalPaths.push(exportsPath) process.env.NODE_PATH = exportsPath # Set NODE_PATH env variable since tasks may need it. document.title = "Spec Suite" - testRunner = require(atom.getLoadSettings().testRunnerPath) + testRunner = require(getWindowLoadSettings().testRunnerPath) testRunner({ - logFile: atom.getLoadSettings().logFile - headless: atom.getLoadSettings().headless - testPaths: atom.getLoadSettings().testPaths + logFile: getWindowLoadSettings().logFile + headless: getWindowLoadSettings().headless + testPaths: getWindowLoadSettings().testPaths + buildAtomEnvironment: -> new AtomEnvironment }) catch error - if atom?.getLoadSettings().headless + if getWindowLoadSettings().headless console.error(error.stack ? error) - atom.exit(1) + app = remote.require('app') + app.emit('will-exit') + remote.process.exit(status) else throw error From d34968b7509ed24a8086a9bf48fccaf2eb2a70d5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 15:26:25 -0600 Subject: [PATCH 083/316] Prevent GPU throttling for hidden test windows --- src/browser/atom-window.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 12d7ccd98..9ba4ed748 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -29,6 +29,10 @@ class AtomWindow 'web-preferences': 'direct-write': true 'subpixel-font-scaling': false + + if @isSpec + options['web-preferences']['page-visibility'] = true + # Don't set icon on Windows so the exe's ico will be used as window and # taskbar's icon. See https://github.com/atom/atom/issues/4811 for more. if process.platform is 'linux' From c4cfbab408a7ceaf714f5e8d443610b15fbd38af Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 16:50:11 -0600 Subject: [PATCH 084/316] Reset key bindings in AtomEnvironment::reset --- package.json | 2 +- spec/spec-helper.coffee | 1 - src/atom-environment.coffee | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 221004c12..25f7fb0e1 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "electronVersion": "0.30.7", "dependencies": { "async": "0.2.6", - "atom-keymap": "^6.0.0", + "atom-keymap": "^6.1.0", "babel-core": "^5.8.21", "bootstrap": "^3.3.4", "clear-cut": "^2.0.1", diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 61ae8148e..b14c5d4a3 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -96,7 +96,6 @@ beforeEach -> assert: atom.assert.bind(atom) }) atom.themes.workspace = atom.workspace - atom.keymaps.keyBindings = _.clone(keyBindingsToRestore) atom.commands.restoreSnapshot(commandsToRestore) atom.styles.restoreSnapshot(styleElementsToRestore) atom.views.clearDocumentRequests() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index e613361f8..a0eb4fe6f 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -227,6 +227,9 @@ class AtomEnvironment extends Model @config.reset() @setConfigSchema() + @keymaps.clear() + @keymaps.loadBundledKeymaps() + ### Section: Event Subscription ### From 75fbeab8b43f0d087e2b45599968634f2937400a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 16:50:19 -0600 Subject: [PATCH 085/316] :art: --- src/atom-environment.coffee | 12 ++++++------ src/config.coffee | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index a0eb4fe6f..7a0e590b0 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -15,6 +15,7 @@ WindowEventHandler = require './window-event-handler' StylesElement = require './styles-element' StorageFolder = require './storage-folder' {getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' +registerDefaultCommands = require './register-default-commands' Workspace = require './workspace' PanelContainer = require './panel-container' @@ -116,11 +117,11 @@ class AtomEnvironment extends Model DeserializerManager = require './deserializer-manager' @deserializers = new DeserializerManager(this) @deserializeTimings = {} - @registerDeserializers() + @registerDefaultDeserializers() ViewRegistry = require './view-registry' @views = new ViewRegistry(this) - @registerViewProviders() + @registerDefaultViewProviders() NotificationManager = require './notification-manager' @notifications = new NotificationManager @@ -139,7 +140,6 @@ class AtomEnvironment extends Model CommandRegistry = require './command-registry' @commands = new CommandRegistry - registerDefaultCommands = require './register-default-commands' registerDefaultCommands(this) PackageManager = require './package-manager' @@ -185,7 +185,7 @@ class AtomEnvironment extends Model setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} - registerDeserializers: -> + registerDefaultDeserializers: -> @deserializers.add(Workspace) @deserializers.add(PaneContainer) @deserializers.add(PaneAxis) @@ -194,7 +194,7 @@ class AtomEnvironment extends Model @deserializers.add(TextEditor) @deserializers.add(TextBuffer) - registerViewProviders: -> + registerDefaultViewProviders: -> @views.addViewProvider Workspace, (model, env) -> new WorkspaceElement().initialize(model, env) @views.addViewProvider PanelContainer, (model) -> @@ -224,7 +224,7 @@ class AtomEnvironment extends Model @workspace.open(@getUserInitScriptPath()) reset: -> - @config.reset() + @config.clear() @setConfigSchema() @keymaps.clear() diff --git a/src/config.coffee b/src/config.coffee index f914be820..bdeabba00 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -334,9 +334,9 @@ class Config constructor: ({@configDirPath, @resourcePath, @notificationManager}={}) -> @configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson']) @configFilePath ?= path.join(@configDirPath, 'config.cson') - @reset() + @clear() - reset: -> + clear: -> @emitter = new Emitter @schema = type: 'object' From ad8c0e93d4882f1a26ad53bbfdebc674a2c12bf0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 16:54:04 -0600 Subject: [PATCH 086/316] Reset deserializers in AtomEnvironment::reset --- src/atom-environment.coffee | 3 +++ src/deserializer-manager.coffee | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 7a0e590b0..0bb650aa9 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -224,6 +224,9 @@ class AtomEnvironment extends Model @workspace.open(@getUserInitScriptPath()) reset: -> + @deserializers.clear() + @registerDefaultDeserializers() + @config.clear() @setConfigSchema() diff --git a/src/deserializer-manager.coffee b/src/deserializer-manager.coffee index 29c7fd59d..7f6cb0f65 100644 --- a/src/deserializer-manager.coffee +++ b/src/deserializer-manager.coffee @@ -60,3 +60,6 @@ class DeserializerManager name = state.get?('deserializer') ? state.deserializer @deserializers[name] + + clear: -> + @deserializers = {} From e1c9f3332da7b15ac62b3ab34effb07b49a3ef26 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 5 Oct 2015 16:58:50 -0600 Subject: [PATCH 087/316] Reset commands in AtomEnvironment::reset --- spec/spec-helper.coffee | 1 - src/atom-environment.coffee | 3 +++ src/command-registry.coffee | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index b14c5d4a3..b8a354e21 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -96,7 +96,6 @@ beforeEach -> assert: atom.assert.bind(atom) }) atom.themes.workspace = atom.workspace - atom.commands.restoreSnapshot(commandsToRestore) atom.styles.restoreSnapshot(styleElementsToRestore) atom.views.clearDocumentRequests() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 0bb650aa9..140df9385 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -233,6 +233,9 @@ class AtomEnvironment extends Model @keymaps.clear() @keymaps.loadBundledKeymaps() + @commands.clear() + registerDefaultCommands(this) + ### Section: Event Subscription ### diff --git a/src/command-registry.coffee b/src/command-registry.coffee index 4cf002c7e..4808c7895 100644 --- a/src/command-registry.coffee +++ b/src/command-registry.coffee @@ -45,6 +45,9 @@ SequenceCount = 0 module.exports = class CommandRegistry constructor: (@rootNode) -> + @clear() + + clear: -> @registeredCommands = {} @selectorBasedListenersByCommandName = {} @inlineListenersByCommandName = {} From 112ee01bd920a748f01ff795c544eba0ddc55edc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 11:46:51 +0200 Subject: [PATCH 088/316] Don't use atom globals in TextEditorElement ...except when the element is instantiated via HTML --- spec/text-editor-component-spec.coffee | 4 +-- spec/text-editor-presenter-spec.coffee | 1 + src/atom-environment.coffee | 4 +-- src/text-editor-component.coffee | 37 +++++++++++++------------- src/text-editor-element.coffee | 34 ++++++++++++++++++----- src/text-editor-presenter.coffee | 14 +++++----- 6 files changed, 58 insertions(+), 36 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 836516759..be51d3a78 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -35,7 +35,7 @@ describe "TextEditorComponent", -> wrapperNode = new TextEditorElement() wrapperNode.tileSize = tileSize - wrapperNode.initialize(editor) + wrapperNode.initialize(editor, atom) wrapperNode.setUpdatedSynchronously(false) jasmine.attachToDOM(wrapperNode) @@ -2902,7 +2902,7 @@ describe "TextEditorComponent", -> wrapperNode = new TextEditorElement() wrapperNode.tileSize = tileSize - wrapperNode.initialize(editor) + wrapperNode.initialize(editor, atom) hiddenParent.appendChild(wrapperNode) {component} = wrapperNode diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index bc60da469..da816a050 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -39,6 +39,7 @@ describe "TextEditorPresenter", -> verticalScrollbarWidth: 10 scrollTop: 0 scrollLeft: 0 + config: atom.config new TextEditorPresenter(params) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 140df9385..162187bbe 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -207,8 +207,8 @@ class AtomEnvironment extends Model new PaneAxisElement().initialize(model) @views.addViewProvider Pane, (model) -> new PaneElement().initialize(model) - @views.addViewProvider TextEditor, (model) -> - new TextEditorElement().initialize(model) + @views.addViewProvider TextEditor, (model, env) -> + new TextEditorElement().initialize(model, env) @views.addViewProvider(Gutter, createGutterView) registerDefaultOpeners: -> diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index ef1711a04..a3bc9f7ee 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -38,15 +38,15 @@ class TextEditorComponent Object.defineProperty @prototype, "domNode", get: -> @domNodeValue set: (domNode) -> - atom.assert domNode?, "TextEditorComponent::domNode was set to null." + @assert domNode?, "TextEditorComponent::domNode was set to null." @domNodeValue = domNode - constructor: ({@editor, @hostElement, @rootElement, @stylesElement, @useShadowDOM, tileSize}) -> + constructor: ({@editor, @hostElement, @rootElement, @stylesElement, @useShadowDOM, tileSize, @views, @themes, @config, @workspace, @assert}) -> @tileSize = tileSize if tileSize? @disposables = new CompositeDisposable @observeConfig() - @setScrollSensitivity(atom.config.get('editor.scrollSensitivity')) + @setScrollSensitivity(@config.get('editor.scrollSensitivity')) @presenter = new TextEditorPresenter model: @editor @@ -58,6 +58,7 @@ class TextEditorComponent cursorBlinkPeriod: @cursorBlinkPeriod cursorBlinkResumeDelay: @cursorBlinkResumeDelay stoppedScrollingDelay: 200 + config: @config @presenter.onDidUpdateState(@requestUpdate) @@ -102,11 +103,11 @@ class TextEditorComponent @disposables.add @stylesElement.onDidAddStyleElement @onStylesheetsChanged @disposables.add @stylesElement.onDidUpdateStyleElement @onStylesheetsChanged @disposables.add @stylesElement.onDidRemoveStyleElement @onStylesheetsChanged - unless atom.themes.isInitialLoadComplete() - @disposables.add atom.themes.onDidChangeActiveThemes @onAllThemesLoaded + unless @themes.isInitialLoadComplete() + @disposables.add @themes.onDidChangeActiveThemes @onAllThemesLoaded @disposables.add scrollbarStyle.onDidChangePreferredScrollbarStyle @refreshScrollbars - @disposables.add atom.views.pollDocument(@pollDOM) + @disposables.add @views.pollDocument(@pollDOM) @updateSync() @checkForVisibilityChange() @@ -199,10 +200,10 @@ class TextEditorComponent @updateSync() else unless @updateRequested @updateRequested = true - atom.views.updateDocument => + @views.updateDocument => @updateRequested = false @updateSync() if @canUpdate() - atom.views.readDocument(@readAfterUpdateSync) + @views.readDocument(@readAfterUpdateSync) canUpdate: -> @mounted and @editor.isAlive() @@ -270,9 +271,9 @@ class TextEditorComponent timeoutId = setTimeout(writeSelectedTextToSelectionClipboard) observeConfig: -> - @disposables.add atom.config.onDidChange 'editor.fontSize', @sampleFontStyling - @disposables.add atom.config.onDidChange 'editor.fontFamily', @sampleFontStyling - @disposables.add atom.config.onDidChange 'editor.lineHeight', @sampleFontStyling + @disposables.add @config.onDidChange 'editor.fontSize', @sampleFontStyling + @disposables.add @config.onDidChange 'editor.fontFamily', @sampleFontStyling + @disposables.add @config.onDidChange 'editor.lineHeight', @sampleFontStyling onGrammarChanged: => if @scopedConfigDisposables? @@ -283,7 +284,7 @@ class TextEditorComponent @disposables.add(@scopedConfigDisposables) scope = @editor.getRootScopeDescriptor() - @scopedConfigDisposables.add atom.config.observe 'editor.scrollSensitivity', {scope}, @setScrollSensitivity + @scopedConfigDisposables.add @config.observe 'editor.scrollSensitivity', {scope}, @setScrollSensitivity focused: -> if @mounted @@ -343,11 +344,11 @@ class TextEditorComponent {wheelDeltaX, wheelDeltaY} = event # Ctrl+MouseWheel adjusts font size. - if event.ctrlKey and atom.config.get('editor.zoomFontWhenCtrlScrolling') + if event.ctrlKey and @config.get('editor.zoomFontWhenCtrlScrolling') if wheelDeltaY > 0 - atom.workspace.increaseFontSize() + @workspace.increaseFontSize() else if wheelDeltaY < 0 - atom.workspace.decreaseFontSize() + @workspace.decreaseFontSize() event.preventDefault() return @@ -540,7 +541,7 @@ class TextEditorComponent onStylesheetsChanged: (styleElement) => return unless @performedInitialMeasurement - return unless atom.themes.isInitialLoadComplete() + return unless @themes.isInitialLoadComplete() # This delay prevents the styling from going haywire when stylesheets are # reloaded in dev mode. It seems like a workaround for a browser bug, but @@ -647,7 +648,7 @@ class TextEditorComponent isVisible: -> # Investigating an exception that occurs here due to ::domNode being null. - atom.assert @domNode?, "TextEditorComponent::domNode was null.", (error) => + @assert @domNode?, "TextEditorComponent::domNode was null.", (error) => error.metadata = {@initialized} @domNode? and (@domNode.offsetHeight > 0 or @domNode.offsetWidth > 0) @@ -847,7 +848,7 @@ class TextEditorComponent @sampleFontStyling() setShowIndentGuide: (showIndentGuide) -> - atom.config.set("editor.showIndentGuide", showIndentGuide) + @config.set("editor.showIndentGuide", showIndentGuide) setScrollSensitivity: (scrollSensitivity) => if scrollSensitivity = parseInt(scrollSensitivity) diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index d8667770f..68d84a560 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -16,24 +16,32 @@ class TextEditorElement extends HTMLElement focusOnAttach: false hasTiledRendering: true logicalDisplayBuffer: true + alreadySetUp: false createdCallback: -> + # Use globals when the following instance variables aren't set. + @config = atom.config + @themes = atom.themes + @workspace = atom.workspace + @assert = atom.assert + @views = atom.views + @emitter = new Emitter @subscriptions = new CompositeDisposable - @initializeContent() + @addEventListener 'focus', @focused.bind(this) @addEventListener 'blur', @blurred.bind(this) - initializeContent: (attributes) -> @classList.add('editor') @setAttribute('tabindex', -1) - if atom.config.get('editor.useShadowDOM') + initializeContent: (attributes) -> + if @config.get('editor.useShadowDOM') @useShadowDOM = true unless ShadowStyleSheet? ShadowStyleSheet = document.createElement('style') - ShadowStyleSheet.textContent = atom.themes.loadLessStylesheet(require.resolve('../static/text-editor-shadow.less')) + ShadowStyleSheet.textContent = @themes.loadLessStylesheet(require.resolve('../static/text-editor-shadow.less')) @createShadowRoot() @@ -56,7 +64,7 @@ class TextEditorElement extends HTMLElement attachedCallback: -> @buildModel() unless @getModel()? - atom.assert(@model.isAlive(), "Attaching a view for a destroyed editor") + @assert(@model.isAlive(), "Attaching a view for a destroyed editor") @mountComponent() unless @component? @listenForComponentEvents() @component.checkForVisibilityChange() @@ -76,7 +84,13 @@ class TextEditorElement extends HTMLElement @subscriptions.add @component.onDidChangeScrollLeft => @emitter.emit("did-change-scroll-left", arguments...) - initialize: (model) -> + initialize: (model, {@views, @config, @themes, @workspace, @assert}) -> + throw new Error("Must pass a config parameter when initializing TextEditorElements") unless @views? + throw new Error("Must pass a config parameter when initializing TextEditorElements") unless @config? + throw new Error("Must pass a themes parameter when initializing TextEditorElements") unless @themes? + throw new Error("Must pass a workspace parameter when initializing TextEditorElements") unless @workspace? + throw new Error("Must pass a assert parameter when initializing TextEditorElements") unless @assert? + @setModel(model) this @@ -85,6 +99,7 @@ class TextEditorElement extends HTMLElement return if model.isDestroyed() @model = model + @initializeContent() @mountComponent() @addGrammarScopeAttribute() @addMiniAttribute() if @model.isMini() @@ -99,7 +114,7 @@ class TextEditorElement extends HTMLElement @model ? @buildModel() buildModel: -> - @setModel(atom.workspace.buildTextEditor( + @setModel(@workspace.buildTextEditor( buffer: new TextBuffer(@textContent) softWrapped: false tabLength: 2 @@ -117,6 +132,11 @@ class TextEditorElement extends HTMLElement editor: @model tileSize: @tileSize useShadowDOM: @useShadowDOM + views: @views + themes: @themes + config: @config + workspace: @workspace + assert: @assert ) @rootElement.appendChild(@component.getDomNode()) diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index f5ca2bd6e..ed5826ee8 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -14,7 +14,7 @@ class TextEditorPresenter minimumReflowInterval: 200 constructor: (params) -> - {@model, @autoHeight, @explicitHeight, @contentFrameWidth, @scrollTop, @scrollLeft, @scrollColumn, @scrollRow, @boundingClientRect, @windowWidth, @windowHeight, @gutterWidth} = params + {@model, @config, @autoHeight, @explicitHeight, @contentFrameWidth, @scrollTop, @scrollLeft, @scrollColumn, @scrollRow, @boundingClientRect, @windowWidth, @windowHeight, @gutterWidth} = params {horizontalScrollbarHeight, verticalScrollbarWidth} = params {@lineHeight, @baseCharacterWidth, @backgroundColor, @gutterBackgroundColor, @tileSize} = params {@cursorBlinkPeriod, @cursorBlinkResumeDelay, @stoppedScrollingDelay, @focused} = params @@ -169,9 +169,9 @@ class TextEditorPresenter observeConfig: -> configParams = {scope: @model.getRootScopeDescriptor()} - @scrollPastEnd = atom.config.get('editor.scrollPastEnd', configParams) - @showLineNumbers = atom.config.get('editor.showLineNumbers', configParams) - @showIndentGuide = atom.config.get('editor.showIndentGuide', configParams) + @scrollPastEnd = @config.get('editor.scrollPastEnd', configParams) + @showLineNumbers = @config.get('editor.showLineNumbers', configParams) + @showIndentGuide = @config.get('editor.showIndentGuide', configParams) if @configDisposables? @configDisposables?.dispose() @@ -180,19 +180,19 @@ class TextEditorPresenter @configDisposables = new CompositeDisposable @disposables.add(@configDisposables) - @configDisposables.add atom.config.onDidChange 'editor.showIndentGuide', configParams, ({newValue}) => + @configDisposables.add @config.onDidChange 'editor.showIndentGuide', configParams, ({newValue}) => @showIndentGuide = newValue @shouldUpdateContentState = true @emitDidUpdateState() - @configDisposables.add atom.config.onDidChange 'editor.scrollPastEnd', configParams, ({newValue}) => + @configDisposables.add @config.onDidChange 'editor.scrollPastEnd', configParams, ({newValue}) => @scrollPastEnd = newValue @shouldUpdateVerticalScrollState = true @shouldUpdateScrollbarsState = true @updateScrollHeight() @emitDidUpdateState() - @configDisposables.add atom.config.onDidChange 'editor.showLineNumbers', configParams, ({newValue}) => + @configDisposables.add @config.onDidChange 'editor.showLineNumbers', configParams, ({newValue}) => @showLineNumbers = newValue @shouldUpdateLineNumberGutterState = true @shouldUpdateGutterOrderState = true From b65bfc408e9ebbbb649d861fc7788d8f71bb4608 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 11:51:02 +0200 Subject: [PATCH 089/316] Don't use atom globals in PanelContainerElement --- spec/panel-container-element-spec.coffee | 4 ---- src/atom-environment.coffee | 4 ++-- src/panel-container-element.coffee | 4 +++- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/spec/panel-container-element-spec.coffee b/spec/panel-container-element-spec.coffee index bd4ed6bd9..65577221a 100644 --- a/spec/panel-container-element-spec.coffee +++ b/spec/panel-container-element-spec.coffee @@ -20,10 +20,6 @@ describe "PanelContainerElement", -> beforeEach -> jasmineContent = document.body.querySelector('#jasmine-content') - atom.views.addViewProvider Panel, (model) -> - new PanelElement().initialize(model) - atom.views.addViewProvider PanelContainer, (model) -> - new PaneContainerElement().initialize(model) atom.views.addViewProvider TestPanelContainerItem, (model) -> new TestPanelContainerItemElement().initialize(model) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 162187bbe..855e8c931 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -197,8 +197,8 @@ class AtomEnvironment extends Model registerDefaultViewProviders: -> @views.addViewProvider Workspace, (model, env) -> new WorkspaceElement().initialize(model, env) - @views.addViewProvider PanelContainer, (model) -> - new PanelContainerElement().initialize(model) + @views.addViewProvider PanelContainer, (model, env) -> + new PanelContainerElement().initialize(model, env) @views.addViewProvider Panel, (model, env) -> new PanelElement().initialize(model, env) @views.addViewProvider PaneContainer, (model) -> diff --git a/src/panel-container-element.coffee b/src/panel-container-element.coffee index e1459e6d6..26a1d2d8c 100644 --- a/src/panel-container-element.coffee +++ b/src/panel-container-element.coffee @@ -4,7 +4,9 @@ class PanelContainerElement extends HTMLElement createdCallback: -> @subscriptions = new CompositeDisposable - initialize: (@model) -> + initialize: (@model, {@views}) -> + throw new Error("Must pass a views parameter when initializing PanelContainerElements") unless @views? + @subscriptions.add @model.onDidAddPanel(@panelAdded.bind(this)) @subscriptions.add @model.onDidRemovePanel(@panelRemoved.bind(this)) @subscriptions.add @model.onDidDestroy(@destroyed.bind(this)) From 6e915c0afd0588f6e9349ab1a646c76e9b1cf7d1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 11:53:28 +0200 Subject: [PATCH 090/316] Don't use atom globals in PaneContainerElement --- src/atom-environment.coffee | 4 ++-- src/pane-container-element.coffee | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 855e8c931..7587a2320 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -201,8 +201,8 @@ class AtomEnvironment extends Model new PanelContainerElement().initialize(model, env) @views.addViewProvider Panel, (model, env) -> new PanelElement().initialize(model, env) - @views.addViewProvider PaneContainer, (model) -> - new PaneContainerElement().initialize(model) + @views.addViewProvider PaneContainer, (model, env) -> + new PaneContainerElement().initialize(model, env) @views.addViewProvider PaneAxis, (model) -> new PaneAxisElement().initialize(model) @views.addViewProvider Pane, (model) -> diff --git a/src/pane-container-element.coffee b/src/pane-container-element.coffee index b3d4e0036..9da452558 100644 --- a/src/pane-container-element.coffee +++ b/src/pane-container-element.coffee @@ -7,7 +7,9 @@ class PaneContainerElement extends HTMLElement @subscriptions = new CompositeDisposable @classList.add 'panes' - initialize: (@model) -> + initialize: (@model, {@views}) -> + throw new Error("Must pass a views parameter when initializing PaneContainerElements") unless @views? + @subscriptions.add @model.observeRoot(@rootChanged.bind(this)) this @@ -15,7 +17,7 @@ class PaneContainerElement extends HTMLElement focusedElement = document.activeElement if @hasFocus() @firstChild?.remove() if root? - view = atom.views.getView(root) + view = @views.getView(root) @appendChild(view) focusedElement?.focus() @@ -40,7 +42,7 @@ class PaneContainerElement extends HTMLElement y = pointB.y - pointA.y Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) - paneView = atom.views.getView(@model.getActivePane()) + paneView = @views.getView(@model.getActivePane()) box = @boundingBoxForPaneView(paneView) paneViews = _.toArray(@querySelectorAll('atom-pane')) From 721c5a167902b6a6cf9b475c37ae037f55869698 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 11:58:54 +0200 Subject: [PATCH 091/316] Don't use atom globals in PaneAxisElement --- spec/pane-container-element-spec.coffee | 2 +- src/atom-environment.coffee | 4 ++-- src/pane-axis-element.coffee | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/pane-container-element-spec.coffee b/spec/pane-container-element-spec.coffee index 46a8fbdbb..e17957333 100644 --- a/spec/pane-container-element-spec.coffee +++ b/spec/pane-container-element-spec.coffee @@ -9,7 +9,7 @@ describe "PaneContainerElement", -> child.nodeName.toLowerCase() for child in paneAxisElement.children paneAxis = new PaneAxis - paneAxisElement = new PaneAxisElement().initialize(paneAxis) + paneAxisElement = new PaneAxisElement().initialize(paneAxis, atom) expect(childTagNames()).toEqual [] diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 7587a2320..5ed6c2ef1 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -203,8 +203,8 @@ class AtomEnvironment extends Model new PanelElement().initialize(model, env) @views.addViewProvider PaneContainer, (model, env) -> new PaneContainerElement().initialize(model, env) - @views.addViewProvider PaneAxis, (model) -> - new PaneAxisElement().initialize(model) + @views.addViewProvider PaneAxis, (model, env) -> + new PaneAxisElement().initialize(model, env) @views.addViewProvider Pane, (model) -> new PaneElement().initialize(model) @views.addViewProvider TextEditor, (model, env) -> diff --git a/src/pane-axis-element.coffee b/src/pane-axis-element.coffee index 91f27858e..eaa26a9fe 100644 --- a/src/pane-axis-element.coffee +++ b/src/pane-axis-element.coffee @@ -8,7 +8,9 @@ class PaneAxisElement extends HTMLElement detachedCallback: -> @subscriptions.dispose() - initialize: (@model) -> + initialize: (@model, {@views}) -> + throw new Error("Must pass a views parameter when initializing TextEditorElements") unless @views? + @subscriptions.add @model.onDidAddChild(@childAdded.bind(this)) @subscriptions.add @model.onDidRemoveChild(@childRemoved.bind(this)) @subscriptions.add @model.onDidReplaceChild(@childReplaced.bind(this)) @@ -27,7 +29,7 @@ class PaneAxisElement extends HTMLElement element?.nodeName.toLowerCase() is 'atom-pane-resize-handle' childAdded: ({child, index}) -> - view = atom.views.getView(child) + view = @views.getView(child) @insertBefore(view, @children[index * 2]) prevElement = view.previousSibling @@ -43,7 +45,7 @@ class PaneAxisElement extends HTMLElement @insertBefore(resizeHandle, nextElement) childRemoved: ({child}) -> - view = atom.views.getView(child) + view = @views.getView(child) siblingView = view.previousSibling # make sure next sibling view is pane resize view if siblingView? and @isPaneResizeHandleElement(siblingView) From fa06124bb282c392f4dd6572c93f1ed4502fe409 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 12:11:23 +0200 Subject: [PATCH 092/316] Don't use atom globals in PaneElement --- spec/pane-element-spec.coffee | 4 ++-- src/atom-environment.coffee | 4 ++-- src/pane-element.coffee | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/spec/pane-element-spec.coffee b/spec/pane-element-spec.coffee index e20068bfc..bf3747199 100644 --- a/spec/pane-element-spec.coffee +++ b/spec/pane-element-spec.coffee @@ -4,6 +4,8 @@ describe "PaneElement", -> [paneElement, container, pane] = [] beforeEach -> + spyOn(atom, "open") + container = new PaneContainer(config: atom.config) pane = container.getActivePane() paneElement = atom.views.getView(pane) @@ -183,7 +185,6 @@ describe "PaneElement", -> describe "when a file is dragged to the pane", -> it "opens it", -> - spyOn(atom, "open") event = buildDragEvent("drop", [{path: "/fake1"}, {path: "/fake2"}]) paneElement.dispatchEvent(event) expect(atom.open.callCount).toBe 1 @@ -191,7 +192,6 @@ describe "PaneElement", -> describe "when a non-file is dragged to the pane", -> it "does nothing", -> - spyOn(atom, "open") event = buildDragEvent("drop", []) paneElement.dispatchEvent(event) expect(atom.open).not.toHaveBeenCalled() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 5ed6c2ef1..48145b8ce 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -205,8 +205,8 @@ class AtomEnvironment extends Model new PaneContainerElement().initialize(model, env) @views.addViewProvider PaneAxis, (model, env) -> new PaneAxisElement().initialize(model, env) - @views.addViewProvider Pane, (model) -> - new PaneElement().initialize(model) + @views.addViewProvider Pane, (model, env) -> + new PaneElement().initialize(model, env) @views.addViewProvider TextEditor, (model, env) -> new TextEditorElement().initialize(model, env) @views.addViewProvider(Gutter, createGutterView) diff --git a/src/pane-element.coffee b/src/pane-element.coffee index 41f110ddb..59f003300 100644 --- a/src/pane-element.coffee +++ b/src/pane-element.coffee @@ -44,14 +44,17 @@ class PaneElement extends HTMLElement event.stopPropagation() @getModel().activate() pathsToOpen = Array::map.call event.dataTransfer.files, (file) -> file.path - atom.open({pathsToOpen}) if pathsToOpen.length > 0 + @open({pathsToOpen}) if pathsToOpen.length > 0 @addEventListener 'focus', handleFocus, true @addEventListener 'blur', handleBlur, true @addEventListener 'dragover', handleDragOver @addEventListener 'drop', handleDrop - initialize: (@model) -> + initialize: (@model, {@views, @open}) -> + throw new Error("Must pass a views parameter when initializing PaneElements") unless @views? + throw new Error("Must pass a open parameter when initializing PaneElements") unless @open? + @subscriptions.add @model.onDidActivate(@activated.bind(this)) @subscriptions.add @model.observeActive(@activeStatusChanged.bind(this)) @subscriptions.add @model.observeActiveItem(@activeItemChanged.bind(this)) @@ -78,7 +81,7 @@ class PaneElement extends HTMLElement return unless item? hasFocus = @hasFocus() - itemView = atom.views.getView(item) + itemView = @views.getView(item) if itemPath = item.getPath?() @dataset.activeItemName = path.basename(itemPath) @@ -109,7 +112,7 @@ class PaneElement extends HTMLElement itemView.style.display = 'none' itemRemoved: ({item, index, destroyed}) -> - if viewToRemove = atom.views.getView(item) + if viewToRemove = @views.getView(item) viewToRemove.remove() paneDestroyed: -> @@ -118,7 +121,7 @@ class PaneElement extends HTMLElement flexScaleChanged: (flexScale) -> @style.flexGrow = flexScale - getActiveView: -> atom.views.getView(@model.getActiveItem()) + getActiveView: -> @views.getView(@model.getActiveItem()) hasFocus: -> this is document.activeElement or @contains(document.activeElement) From 8686b2009e0eadfb0b5f3c98f35df5b7312bc0c7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 13:58:15 +0200 Subject: [PATCH 093/316] Port leftover global in PanelContainerElement --- src/panel-container-element.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panel-container-element.coffee b/src/panel-container-element.coffee index 26a1d2d8c..40ce7e352 100644 --- a/src/panel-container-element.coffee +++ b/src/panel-container-element.coffee @@ -16,7 +16,7 @@ class PanelContainerElement extends HTMLElement getModel: -> @model panelAdded: ({panel, index}) -> - panelElement = atom.views.getView(panel) + panelElement = @views.getView(panel) panelElement.classList.add(@model.getLocation()) if @model.isModal() panelElement.classList.add("overlay", "from-top") @@ -35,7 +35,7 @@ class PanelContainerElement extends HTMLElement @hideAllPanelsExcept(panel) if visible panelRemoved: ({panel, index}) -> - @removeChild(atom.views.getView(panel)) + @removeChild(@views.getView(panel)) destroyed: -> @subscriptions.dispose() From 2532a9cd591450ffd32df3c0239c4bb3abf24d58 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:17:47 +0200 Subject: [PATCH 094/316] Don't use atom globals in StylesElement --- spec/jasmine-test-runner.coffee | 6 +++++- spec/styles-element-spec.coffee | 3 ++- src/atom-environment.coffee | 5 ++++- src/styles-element.coffee | 21 ++++++++++----------- src/text-editor-element.coffee | 9 ++++++--- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 35f08e2ac..7aa264b29 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -25,7 +25,11 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> jasmineContent = document.createElement('div') jasmineContent.setAttribute('id', 'jasmine-content') - document.head.appendChild(new StylesElement) + + stylesElement = new StylesElement + stylesElement.initialize(atom) + + document.head.appendChild(stylesElement) document.body.appendChild(jasmineContent) jasmineEnv.execute() diff --git a/spec/styles-element-spec.coffee b/spec/styles-element-spec.coffee index 7d2fe722a..ae2648644 100644 --- a/spec/styles-element-spec.coffee +++ b/spec/styles-element-spec.coffee @@ -6,6 +6,7 @@ describe "StylesElement", -> beforeEach -> element = new StylesElement + element.initialize(atom) document.querySelector('#jasmine-content').appendChild(element) addedStyleElements = [] removedStyleElements = [] @@ -99,8 +100,8 @@ describe "StylesElement", -> it "defers selector upgrade until the element is attached", -> element = new StylesElement + element.initialize(atom) element.setAttribute('context', 'atom-text-editor') - element.initialize() atom.styles.addStyleSheet ".editor {background: black;}", context: 'atom-text-editor' expect(element.firstChild.sheet).toBeNull() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 48145b8ce..ca059d2f8 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -547,7 +547,10 @@ class AtomEnvironment extends Model @config.load() @setBodyPlatformClass() - document.head.appendChild(new StylesElement) + + stylesElement = new StylesElement + stylesElement.initialize(this) + document.head.appendChild(stylesElement) @windowEventHandler = new WindowEventHandler(this) @packages.loadPackages() diff --git a/src/styles-element.coffee b/src/styles-element.coffee index fc3b888cf..e5ab9884e 100644 --- a/src/styles-element.coffee +++ b/src/styles-element.coffee @@ -14,6 +14,7 @@ class StylesElement extends HTMLElement @emitter.on 'did-update-style-element', callback createdCallback: -> + @subscriptions = new CompositeDisposable @emitter = new Emitter @styleElementClonesByOriginalElement = new WeakMap @@ -21,31 +22,29 @@ class StylesElement extends HTMLElement if @context is 'atom-text-editor' for styleElement in @children @upgradeDeprecatedSelectors(styleElement) - @initialize() + + @context = @getAttribute('context') ? undefined detachedCallback: -> @subscriptions.dispose() - @subscriptions = null + @subscriptions = new CompositeDisposable attributeChangedCallback: (attrName, oldVal, newVal) -> @contextChanged() if attrName is 'context' - initialize: -> - return if @subscriptions? + initialize: ({@styles}) -> + throw new Error("Must pass a styles parameter when initializing TextEditorElements") unless @styles? - @subscriptions = new CompositeDisposable - @context = @getAttribute('context') ? undefined - - @subscriptions.add atom.styles.observeStyleElements(@styleElementAdded.bind(this)) - @subscriptions.add atom.styles.onDidRemoveStyleElement(@styleElementRemoved.bind(this)) - @subscriptions.add atom.styles.onDidUpdateStyleElement(@styleElementUpdated.bind(this)) + @subscriptions.add @styles.observeStyleElements(@styleElementAdded.bind(this)) + @subscriptions.add @styles.onDidRemoveStyleElement(@styleElementRemoved.bind(this)) + @subscriptions.add @styles.onDidUpdateStyleElement(@styleElementUpdated.bind(this)) contextChanged: -> return unless @subscriptions? @styleElementRemoved(child) for child in Array::slice.call(@children) @context = @getAttribute('context') - @styleElementAdded(styleElement) for styleElement in atom.styles.getStyleElements() + @styleElementAdded(styleElement) for styleElement in @styles.getStyleElements() return styleElementAdded: (styleElement) -> diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 68d84a560..71219fe6a 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -4,6 +4,7 @@ Path = require 'path' TextBuffer = require 'text-buffer' TextEditor = require './text-editor' TextEditorComponent = require './text-editor-component' +StylesElement = require './styles-element' ShadowStyleSheet = null @@ -25,6 +26,7 @@ class TextEditorElement extends HTMLElement @workspace = atom.workspace @assert = atom.assert @views = atom.views + @styles = atom.styles @emitter = new Emitter @subscriptions = new CompositeDisposable @@ -46,9 +48,9 @@ class TextEditorElement extends HTMLElement @createShadowRoot() @shadowRoot.appendChild(ShadowStyleSheet.cloneNode(true)) - @stylesElement = document.createElement('atom-styles') + @stylesElement = new StylesElement + @stylesElement.initialize({@styles}) @stylesElement.setAttribute('context', 'atom-text-editor') - @stylesElement.initialize() @rootElement = document.createElement('div') @rootElement.classList.add('editor--private') @@ -84,12 +86,13 @@ class TextEditorElement extends HTMLElement @subscriptions.add @component.onDidChangeScrollLeft => @emitter.emit("did-change-scroll-left", arguments...) - initialize: (model, {@views, @config, @themes, @workspace, @assert}) -> + initialize: (model, {@views, @config, @themes, @workspace, @assert, @styles}) -> throw new Error("Must pass a config parameter when initializing TextEditorElements") unless @views? throw new Error("Must pass a config parameter when initializing TextEditorElements") unless @config? throw new Error("Must pass a themes parameter when initializing TextEditorElements") unless @themes? throw new Error("Must pass a workspace parameter when initializing TextEditorElements") unless @workspace? throw new Error("Must pass a assert parameter when initializing TextEditorElements") unless @assert? + throw new Error("Must pass a styles parameter when initializing TextEditorElements") unless @styles? @setModel(model) this From 45f536a5ee942744c6915e0d3f3593c49991504a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:18:43 +0200 Subject: [PATCH 095/316] Remove leftover global in WorkspaceElement --- src/workspace-element.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace-element.coffee b/src/workspace-element.coffee index b7a1575d8..c1d1f8f14 100644 --- a/src/workspace-element.coffee +++ b/src/workspace-element.coffee @@ -52,7 +52,7 @@ class WorkspaceElement extends HTMLElement line-height: #{@config.get('editor.lineHeight')}; } """ - atom.styles.addStyleSheet(styleSheetSource, sourcePath: 'global-text-editor-styles') + @styles.addStyleSheet(styleSheetSource, sourcePath: 'global-text-editor-styles') initialize: (@model, {@views, @workspace, @project, @config, @styles}) -> throw new Error("Must pass a views parameter when initializing WorskpaceElements") unless @views? From 6fed847cce97fd09336bff940ce55c943249529f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:22:10 +0200 Subject: [PATCH 096/316] Don't use atom globals in gutter components --- src/custom-gutter-component.coffee | 4 ++-- src/gutter-container-component.coffee | 6 +++--- src/line-number-gutter-component.coffee | 4 ++-- src/text-editor-component.coffee | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/custom-gutter-component.coffee b/src/custom-gutter-component.coffee index 32710ea46..9fd25fd3f 100644 --- a/src/custom-gutter-component.coffee +++ b/src/custom-gutter-component.coffee @@ -6,12 +6,12 @@ module.exports = class CustomGutterComponent - constructor: ({@gutter}) -> + constructor: ({@gutter, @views}) -> @decorationNodesById = {} @decorationItemsById = {} @visible = true - @domNode = atom.views.getView(@gutter) + @domNode = @views.getView(@gutter) @decorationsNode = @domNode.firstChild # Clear the contents in case the domNode is being reused. @decorationsNode.innerHTML = '' diff --git a/src/gutter-container-component.coffee b/src/gutter-container-component.coffee index 40e2c8c26..c5538324b 100644 --- a/src/gutter-container-component.coffee +++ b/src/gutter-container-component.coffee @@ -7,7 +7,7 @@ LineNumberGutterComponent = require './line-number-gutter-component' module.exports = class GutterContainerComponent - constructor: ({@onLineNumberGutterMouseDown, @editor, @domElementPool}) -> + constructor: ({@onLineNumberGutterMouseDown, @editor, @domElementPool, @views}) -> # An array of objects of the form: {name: {String}, component: {Object}} @gutterComponents = [] @gutterComponentsByGutterName = {} @@ -39,10 +39,10 @@ class GutterContainerComponent gutterComponent = @gutterComponentsByGutterName[gutter.name] if not gutterComponent if gutter.name is 'line-number' - gutterComponent = new LineNumberGutterComponent({onMouseDown: @onLineNumberGutterMouseDown, @editor, gutter, @domElementPool}) + gutterComponent = new LineNumberGutterComponent({onMouseDown: @onLineNumberGutterMouseDown, @editor, gutter, @domElementPool, @views}) @lineNumberGutterComponent = gutterComponent else - gutterComponent = new CustomGutterComponent({gutter}) + gutterComponent = new CustomGutterComponent({gutter, @views}) if visible then gutterComponent.showNode() else gutterComponent.hideNode() # Pass the gutter only the state that it needs. diff --git a/src/line-number-gutter-component.coffee b/src/line-number-gutter-component.coffee index b4a5bc168..bb66ff144 100644 --- a/src/line-number-gutter-component.coffee +++ b/src/line-number-gutter-component.coffee @@ -7,12 +7,12 @@ module.exports = class LineNumberGutterComponent extends TiledComponent dummyLineNumberNode: null - constructor: ({@onMouseDown, @editor, @gutter, @domElementPool}) -> + constructor: ({@onMouseDown, @editor, @gutter, @domElementPool, @views}) -> @visible = true @dummyLineNumberComponent = LineNumbersTileComponent.createDummy(@domElementPool) - @domNode = atom.views.getView(@gutter) + @domNode = @views.getView(@gutter) @lineNumbersNode = @domNode.firstChild @lineNumbersNode.innerHTML = '' diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index a3bc9f7ee..e207a4deb 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -172,7 +172,7 @@ class TextEditorComponent @overlayManager?.measureOverlays() mountGutterContainerComponent: -> - @gutterContainerComponent = new GutterContainerComponent({@editor, @onLineNumberGutterMouseDown, @domElementPool}) + @gutterContainerComponent = new GutterContainerComponent({@editor, @onLineNumberGutterMouseDown, @domElementPool, @views}) @domNode.insertBefore(@gutterContainerComponent.getDomNode(), @domNode.firstChild) becameVisible: -> From eba18092fb84560d433ccd3d0eec38ef668a4092 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:24:24 +0200 Subject: [PATCH 097/316] Don't use atom globals in LinesComponent --- src/lines-component.coffee | 4 ++-- src/lines-tile-component.coffee | 4 ++-- src/text-editor-component.coffee | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 0cda90d5c..87e4e235e 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -13,7 +13,7 @@ module.exports = class LinesComponent extends TiledComponent placeholderTextDiv: null - constructor: ({@presenter, @hostElement, @useShadowDOM, visible, @domElementPool}) -> + constructor: ({@presenter, @hostElement, @useShadowDOM, visible, @domElementPool, @assert}) -> @domNode = document.createElement('div') @domNode.classList.add('lines') @tilesNode = document.createElement("div") @@ -63,7 +63,7 @@ class LinesComponent extends TiledComponent @oldState.indentGuidesVisible = @newState.indentGuidesVisible - buildComponentForTile: (id) -> new LinesTileComponent({id, @presenter, @domElementPool}) + buildComponentForTile: (id) -> new LinesTileComponent({id, @presenter, @domElementPool, @assert}) buildEmptyState: -> {tiles: {}} diff --git a/src/lines-tile-component.coffee b/src/lines-tile-component.coffee index 627630e03..723591d9c 100644 --- a/src/lines-tile-component.coffee +++ b/src/lines-tile-component.coffee @@ -13,7 +13,7 @@ cloneObject = (object) -> module.exports = class LinesTileComponent - constructor: ({@presenter, @id, @domElementPool}) -> + constructor: ({@presenter, @id, @domElementPool, @assert}) -> @tokenIterator = new TokenIterator @measuredLines = new Set @lineNodesByLineId = {} @@ -361,7 +361,7 @@ class LinesTileComponent rangeForMeasurement.setEnd(textNode, i + charLength) else rangeForMeasurement.setEnd(textNode, textNodeLength) - atom.assert false, "Expected index to be less than the length of text node while measuring", (error) => + @assert false, "Expected index to be less than the length of text node while measuring", (error) => editor = @presenter.model screenRow = tokenizedLine.screenRow bufferRow = editor.bufferRowForScreenRow(screenRow) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index e207a4deb..d36cbbb05 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -85,7 +85,7 @@ class TextEditorComponent @hiddenInputComponent = new InputComponent @scrollViewNode.appendChild(@hiddenInputComponent.getDomNode()) - @linesComponent = new LinesComponent({@presenter, @hostElement, @useShadowDOM, @domElementPool}) + @linesComponent = new LinesComponent({@presenter, @hostElement, @useShadowDOM, @domElementPool, @assert}) @scrollViewNode.appendChild(@linesComponent.getDomNode()) @horizontalScrollbarComponent = new ScrollbarComponent({orientation: 'horizontal', onScroll: @onHorizontalScroll}) From 04fcc1112eef38f8a09e963363e89929d365f3cf Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:27:26 +0200 Subject: [PATCH 098/316] Fix some linter errors --- src/atom-environment.coffee | 2 +- src/window-load-settings-helpers.coffee | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index ca059d2f8..cc40952ff 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -176,7 +176,7 @@ class AtomEnvironment extends Model @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, - grammarRegistry: @grammars, assert: @assert.bind(this) + assert: @assert.bind(this) }) @themes.workspace = @workspace diff --git a/src/window-load-settings-helpers.coffee b/src/window-load-settings-helpers.coffee index 1ae76c442..59ee2f382 100644 --- a/src/window-load-settings-helpers.coffee +++ b/src/window-load-settings-helpers.coffee @@ -8,9 +8,9 @@ exports.getWindowLoadSettings = -> clone = _.deepClone(windowLoadSettings) # The windowLoadSettings.windowState could be large, request it only when needed. - clone.__defineGetter__ 'windowState', => + clone.__defineGetter__ 'windowState', -> remote.getCurrentWindow().loadSettings.windowState - clone.__defineSetter__ 'windowState', (value) => + clone.__defineSetter__ 'windowState', (value) -> remote.getCurrentWindow().loadSettings.windowState = value clone From df2d73a8df5a42e1373179e28e07f5c83ca73dd6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:41:43 +0200 Subject: [PATCH 099/316] Don't use atom globals in TokenizedBuffer --- spec/token-iterator-spec.coffee | 2 +- spec/tokenized-buffer-spec.coffee | 30 +++++++++++++++--------------- src/display-buffer.coffee | 2 +- src/tokenized-buffer.coffee | 9 +++++---- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/spec/token-iterator-spec.coffee b/spec/token-iterator-spec.coffee index b71a879d3..f876d30d1 100644 --- a/spec/token-iterator-spec.coffee +++ b/spec/token-iterator-spec.coffee @@ -25,7 +25,7 @@ describe "TokenIterator", -> x """) tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) tokenizedBuffer.setGrammar(grammar) diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index a9c538da2..e87125195 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -28,7 +28,7 @@ describe "TokenizedBuffer", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) startTokenizing(tokenizedBuffer) @@ -42,7 +42,7 @@ describe "TokenizedBuffer", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) startTokenizing(tokenizedBuffer) tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') @@ -350,7 +350,7 @@ describe "TokenizedBuffer", -> runs -> buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) startTokenizing(tokenizedBuffer) @@ -457,7 +457,7 @@ describe "TokenizedBuffer", -> //\uD835\uDF97xyz """ tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) @@ -553,7 +553,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync() buffer.setText "
<%= User.find(2).full_name %>
" tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) tokenizedBuffer.setGrammar(atom.grammars.selectGrammar('test.erb')) fullyTokenize(tokenizedBuffer) @@ -577,7 +577,7 @@ describe "TokenizedBuffer", -> it "returns the correct token (regression)", -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([1, 0]).scopes).toEqual ["source.js"] @@ -589,7 +589,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({ buffer, config: atom.config, grammarRegistry: atom.grammars, - packageManager: atom.packages + packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) @@ -611,7 +611,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' @@ -622,7 +622,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') buffer.setText('\ttest') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) expect(tokenizedBuffer.tokenForPosition([0, 0]).value).toBe ' ' @@ -637,7 +637,7 @@ describe "TokenizedBuffer", -> it "updates the tokens with the appropriate invisible characters", -> buffer = new TextBuffer(text: " \t a line with tabs\tand \tspaces \t ") tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) @@ -652,7 +652,7 @@ describe "TokenizedBuffer", -> it "assigns endOfLineInvisibles to tokenized lines", -> buffer = new TextBuffer(text: "a line that ends in a carriage-return-line-feed \r\na line that ends in just a line-feed\na line with no ending") tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) atom.config.set('editor.showInvisibles', true) @@ -675,7 +675,7 @@ describe "TokenizedBuffer", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) @@ -735,7 +735,7 @@ describe "TokenizedBuffer", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) @@ -832,7 +832,7 @@ describe "TokenizedBuffer", -> buffer.insert [10, 0], " // multi-line\n // comment\n // block\n" buffer.insert [0, 0], "// multi-line\n// comment\n// block\n" tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) fullyTokenize(tokenizedBuffer) tokenizedBuffer.onDidChange (change) -> @@ -911,7 +911,7 @@ describe "TokenizedBuffer", -> buffer.setText('a\nb\nc') tokenizedBuffer = new TokenizedBuffer({ - buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages + buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert }) tokenizeCallback = jasmine.createSpy('onDidTokenize') tokenizedBuffer.onDidTokenize(tokenizeCallback) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 26226f515..67fa49a32 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -48,7 +48,7 @@ class DisplayBuffer extends Model @tokenizedBuffer ?= new TokenizedBuffer({ tabLength, buffer, ignoreInvisibles, @largeFileMode, @config, - @grammarRegistry, @packageManager + @grammarRegistry, @packageManager, @assert }) @buffer = @tokenizedBuffer.buffer @charWidthsByScope = {} diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 4f66cf96b..45b0441b4 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -22,16 +22,17 @@ class TokenizedBuffer extends Model changeCount: 0 @deserialize: (state, atomEnvironment) -> - state.buffer = atom.project.bufferForPathSync(state.bufferPath) + state.buffer = atomEnvironment.project.bufferForPathSync(state.bufferPath) state.config = atomEnvironment.config state.grammarRegistry = atomEnvironment.grammars state.packageManager = atomEnvironment.packages + state.assert = atomEnvironment.assert new this(state) constructor: (params) -> { @buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config, - @grammarRegistry, @packageManager + @grammarRegistry, @packageManager, @assert } = params @emitter = new Emitter @@ -299,7 +300,7 @@ class TokenizedBuffer extends Model # undefined. This should paper over the problem but we want to figure out # what is happening: tokenizedLine = @tokenizedLineForRow(row) - atom.assert tokenizedLine?, "TokenizedLine is undefined", (error) => + @assert tokenizedLine?, "TokenizedLine is undefined", (error) => error.metadata = { row: row rowCount: @tokenizedLines.length @@ -399,7 +400,7 @@ class TokenizedBuffer extends Model loop break if scopes.pop() is matchingStartTag if scopes.length is 0 - atom.assert false, "Encountered an unmatched scope end tag.", (error) => + @assert false, "Encountered an unmatched scope end tag.", (error) => error.metadata = { grammarScopeName: @grammar.scopeName unmatchedEndTag: @grammar.scopeForId(tag) From cb950b65b0c2ec200b86a2af371661799fd56f74 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:43:41 +0200 Subject: [PATCH 100/316] :green_heart: Adapt specs to pass atom.views in ctors --- spec/custom-gutter-component-spec.coffee | 2 +- spec/gutter-container-component-spec.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/custom-gutter-component-spec.coffee b/spec/custom-gutter-component-spec.coffee index 4b7d81fba..5504e9c40 100644 --- a/spec/custom-gutter-component-spec.coffee +++ b/spec/custom-gutter-component-spec.coffee @@ -7,7 +7,7 @@ describe "CustomGutterComponent", -> beforeEach -> mockGutterContainer = {} gutter = new Gutter(mockGutterContainer, {name: 'test-gutter'}) - gutterComponent = new CustomGutterComponent({gutter}) + gutterComponent = new CustomGutterComponent({gutter, views: atom.views}) it "creates a gutter DOM node with only an empty 'custom-decorations' child node when it is initialized", -> expect(gutterComponent.getDomNode().classList.contains('gutter')).toBe true diff --git a/spec/gutter-container-component-spec.coffee b/spec/gutter-container-component-spec.coffee index 595067de5..73a9d0f6c 100644 --- a/spec/gutter-container-component-spec.coffee +++ b/spec/gutter-container-component-spec.coffee @@ -26,7 +26,7 @@ describe "GutterContainerComponent", -> domElementPool = new DOMElementPool mockEditor = {} mockMouseDown = -> - gutterContainerComponent = new GutterContainerComponent({editor: mockEditor, onMouseDown: mockMouseDown, domElementPool}) + gutterContainerComponent = new GutterContainerComponent({editor: mockEditor, onMouseDown: mockMouseDown, domElementPool, views: atom.views}) it "creates a DOM node with no child gutter nodes when it is initialized", -> expect(gutterContainerComponent.getDomNode() instanceof HTMLElement).toBe true From 464cfd4474a21f8f8097952ed32b4c5b23c2e466 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 14:52:40 +0200 Subject: [PATCH 101/316] Don't use atom.confirm in Workspace --- spec/workspace-spec.coffee | 6 ++++-- src/atom-environment.coffee | 3 +-- src/workspace.coffee | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 54f171ff8..10e0711bc 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -12,6 +12,8 @@ describe "Workspace", -> [workspace, setDocumentEdited] = [] beforeEach -> + spyOn(atom, 'confirm') + setDocumentEdited = jasmine.createSpy('setDocumentEdited') atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) atom.workspace = workspace = new Workspace({ @@ -20,7 +22,7 @@ describe "Workspace", -> clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), - assert: atom.assert.bind(atom) + assert: atom.assert.bind(atom), confirm: atom.confirm.bind(atom) }) waits(1) @@ -350,7 +352,7 @@ describe "Workspace", -> describe "when the file is over 20MB", -> it "prompts the user to make sure they want to open a file this big", -> spyOn(fs, 'getSizeSync').andReturn 20 * 1048577 # 20MB - spyOn(atom, 'confirm').andCallFake -> selectedButtonIndex + atom.confirm.andCallFake -> selectedButtonIndex selectedButtonIndex = 1 # cancel editor = null diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index cc40952ff..e275a4970 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -175,8 +175,7 @@ class AtomEnvironment extends Model @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), - setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, - assert: @assert.bind(this) + setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, assert: @assert.bind(this), confirm: @confirm.bind(this) }) @themes.workspace = @workspace diff --git a/src/workspace.coffee b/src/workspace.coffee index 423e70112..49e9bbccf 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -29,7 +29,7 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, - @setDocumentEdited, @assert + @setDocumentEdited, @assert, @confirm } = params debugger unless @assert? @@ -448,7 +448,7 @@ class Workspace extends Model largeFileMode = fileSize >= 2 * 1048576 # 2MB if fileSize >= 20 * 1048576 # 20MB - choice = atom.confirm + choice = @confirm message: 'Atom will be unresponsive during the loading of very large files.' detailedMessage: "Do you still want to load this file?" buttons: ["Proceed", "Cancel"] From 534f038631bebf6e045de75d837e53943f00c2a4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 15:06:32 +0200 Subject: [PATCH 102/316] Don't use atom globals in TokenIterator --- src/lines-component.coffee | 4 ++-- src/lines-tile-component.coffee | 4 ++-- src/text-editor-component.coffee | 4 ++-- src/text-editor-element.coffee | 5 ++++- src/token-iterator.coffee | 6 +++--- src/tokenized-buffer.coffee | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 87e4e235e..7a312f719 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -13,7 +13,7 @@ module.exports = class LinesComponent extends TiledComponent placeholderTextDiv: null - constructor: ({@presenter, @hostElement, @useShadowDOM, visible, @domElementPool, @assert}) -> + constructor: ({@presenter, @hostElement, @useShadowDOM, visible, @domElementPool, @assert, @grammars}) -> @domNode = document.createElement('div') @domNode.classList.add('lines') @tilesNode = document.createElement("div") @@ -63,7 +63,7 @@ class LinesComponent extends TiledComponent @oldState.indentGuidesVisible = @newState.indentGuidesVisible - buildComponentForTile: (id) -> new LinesTileComponent({id, @presenter, @domElementPool, @assert}) + buildComponentForTile: (id) -> new LinesTileComponent({id, @presenter, @domElementPool, @assert, @grammars}) buildEmptyState: -> {tiles: {}} diff --git a/src/lines-tile-component.coffee b/src/lines-tile-component.coffee index 723591d9c..47263da96 100644 --- a/src/lines-tile-component.coffee +++ b/src/lines-tile-component.coffee @@ -13,8 +13,8 @@ cloneObject = (object) -> module.exports = class LinesTileComponent - constructor: ({@presenter, @id, @domElementPool, @assert}) -> - @tokenIterator = new TokenIterator + constructor: ({@presenter, @id, @domElementPool, @assert, grammars}) -> + @tokenIterator = new TokenIterator(grammarRegistry: grammars) @measuredLines = new Set @lineNodesByLineId = {} @screenRowsByLineId = {} diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index d36cbbb05..529691ed2 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -41,7 +41,7 @@ class TextEditorComponent @assert domNode?, "TextEditorComponent::domNode was set to null." @domNodeValue = domNode - constructor: ({@editor, @hostElement, @rootElement, @stylesElement, @useShadowDOM, tileSize, @views, @themes, @config, @workspace, @assert}) -> + constructor: ({@editor, @hostElement, @rootElement, @stylesElement, @useShadowDOM, tileSize, @views, @themes, @config, @workspace, @assert, @grammars}) -> @tileSize = tileSize if tileSize? @disposables = new CompositeDisposable @@ -85,7 +85,7 @@ class TextEditorComponent @hiddenInputComponent = new InputComponent @scrollViewNode.appendChild(@hiddenInputComponent.getDomNode()) - @linesComponent = new LinesComponent({@presenter, @hostElement, @useShadowDOM, @domElementPool, @assert}) + @linesComponent = new LinesComponent({@presenter, @hostElement, @useShadowDOM, @domElementPool, @assert, @grammars}) @scrollViewNode.appendChild(@linesComponent.getDomNode()) @horizontalScrollbarComponent = new ScrollbarComponent({orientation: 'horizontal', onScroll: @onHorizontalScroll}) diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 71219fe6a..7c1ee2915 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -27,6 +27,7 @@ class TextEditorElement extends HTMLElement @assert = atom.assert @views = atom.views @styles = atom.styles + @grammars = atom.grammars @emitter = new Emitter @subscriptions = new CompositeDisposable @@ -86,13 +87,14 @@ class TextEditorElement extends HTMLElement @subscriptions.add @component.onDidChangeScrollLeft => @emitter.emit("did-change-scroll-left", arguments...) - initialize: (model, {@views, @config, @themes, @workspace, @assert, @styles}) -> + initialize: (model, {@views, @config, @themes, @workspace, @assert, @styles, @grammars}) -> throw new Error("Must pass a config parameter when initializing TextEditorElements") unless @views? throw new Error("Must pass a config parameter when initializing TextEditorElements") unless @config? throw new Error("Must pass a themes parameter when initializing TextEditorElements") unless @themes? throw new Error("Must pass a workspace parameter when initializing TextEditorElements") unless @workspace? throw new Error("Must pass a assert parameter when initializing TextEditorElements") unless @assert? throw new Error("Must pass a styles parameter when initializing TextEditorElements") unless @styles? + throw new Error("Must pass a grammars parameter when initializing TextEditorElements") unless @grammars? @setModel(model) this @@ -140,6 +142,7 @@ class TextEditorElement extends HTMLElement config: @config workspace: @workspace assert: @assert + grammars: @grammars ) @rootElement.appendChild(@component.getDomNode()) diff --git a/src/token-iterator.coffee b/src/token-iterator.coffee index de874d499..cc31ca98e 100644 --- a/src/token-iterator.coffee +++ b/src/token-iterator.coffee @@ -2,7 +2,7 @@ module.exports = class TokenIterator - constructor: (line) -> + constructor: ({@grammarRegistry}, line) -> @reset(line) if line? reset: (@line) -> @@ -11,7 +11,7 @@ class TokenIterator @bufferEnd = @bufferStart @screenStart = 0 @screenEnd = 0 - @scopes = @line.openScopes.map (id) -> atom.grammars.scopeForId(id) + @scopes = @line.openScopes.map (id) => @grammarRegistry.scopeForId(id) @scopeStarts = @scopes.slice() @scopeEnds = [] this @@ -31,7 +31,7 @@ class TokenIterator while @index < tags.length tag = tags[@index] if tag < 0 - scope = atom.grammars.scopeForId(tag) + scope = @grammarRegistry.scopeForId(tag) if tag % 2 is 0 if @scopeStarts[@scopeStarts.length - 1] is scope @scopeStarts.pop() diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 45b0441b4..2df29a31c 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -37,7 +37,7 @@ class TokenizedBuffer extends Model @emitter = new Emitter @disposables = new CompositeDisposable - @tokenIterator = new TokenIterator + @tokenIterator = new TokenIterator({@grammarRegistry}) @disposables.add @grammarRegistry.onDidAddGrammar(@grammarAddedOrUpdated) @disposables.add @grammarRegistry.onDidUpdateGrammar(@grammarAddedOrUpdated) From 097a035dc402d337e4950e80ba480e9f1acc77be Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 15:08:40 +0200 Subject: [PATCH 103/316] Don't use atom globals in OverlayManager --- src/overlay-manager.coffee | 4 ++-- src/text-editor-component.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/overlay-manager.coffee b/src/overlay-manager.coffee index 7858cb8a2..83787ad10 100644 --- a/src/overlay-manager.coffee +++ b/src/overlay-manager.coffee @@ -1,6 +1,6 @@ module.exports = class OverlayManager - constructor: (@presenter, @container) -> + constructor: (@presenter, @container, @views) -> @overlaysById = {} render: (state) -> @@ -28,7 +28,7 @@ class OverlayManager @presenter.setOverlayDimensions(decorationId, itemView.offsetWidth, itemView.offsetHeight, contentMargin) renderOverlay: (state, decorationId, {item, pixelPosition, class: klass}) -> - itemView = atom.views.getView(item) + itemView = @views.getView(item) cachedOverlay = @overlaysById[decorationId] unless overlayNode = cachedOverlay?.overlayNode overlayNode = document.createElement('atom-overlay') diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 529691ed2..f928f19d8 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -71,10 +71,10 @@ class TextEditorComponent insertionPoint = document.createElement('content') insertionPoint.setAttribute('select', 'atom-overlay') @domNode.appendChild(insertionPoint) - @overlayManager = new OverlayManager(@presenter, @hostElement) + @overlayManager = new OverlayManager(@presenter, @hostElement, @views) else @domNode.classList.add('editor-contents') - @overlayManager = new OverlayManager(@presenter, @domNode) + @overlayManager = new OverlayManager(@presenter, @domNode, @views) @scrollViewNode = document.createElement('div') @scrollViewNode.classList.add('scroll-view') From b7d6dd5e8cee461defdba201cc4696d73b95f1f7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 10:55:12 -0600 Subject: [PATCH 104/316] Reset view registry in AtomEnvironment::reset --- spec/text-editor-component-spec.coffee | 5 +++++ src/atom-environment.coffee | 3 +++ src/view-registry.coffee | 10 +++++----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index be51d3a78..b6d811e6e 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -22,6 +22,7 @@ describe "TextEditorComponent", -> nextAnimationFrame = noAnimationFrame spyOn(window, 'requestAnimationFrame').andCallFake (fn) -> + debugger if global.debug nextAnimationFrame = -> nextAnimationFrame = noAnimationFrame fn() @@ -54,6 +55,10 @@ describe "TextEditorComponent", -> component.measureDimensions() nextAnimationFrame() + # Mutating the DOM in the previous frame causes a document poll; clear it here + waits 0 + runs -> nextAnimationFrame() + afterEach -> contentNode.style.width = '' diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index e275a4970..60ef08ed7 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -226,6 +226,9 @@ class AtomEnvironment extends Model @deserializers.clear() @registerDefaultDeserializers() + @views.clear() + @registerDefaultViewProviders() + @config.clear() @setConfigSchema() diff --git a/src/view-registry.coffee b/src/view-registry.coffee index c9abd8852..3a46aa87a 100644 --- a/src/view-registry.coffee +++ b/src/view-registry.coffee @@ -50,14 +50,14 @@ class ViewRegistry minimumPollInterval: 200 constructor: (@atomEnvironment) -> + @observer = new MutationObserver(@requestDocumentPoll) + @clear() + + clear: -> @views = new WeakMap @providers = [] - @documentWriters = [] - @documentReaders = [] - @documentPollers = [] - - @observer = new MutationObserver(@requestDocumentPoll) @debouncedPerformDocumentPoll = _.throttle(@performDocumentPoll, @minimumPollInterval).bind(this) + @clearDocumentRequests() # Essential: Add a provider that will be used to construct views in the # workspace's view layer based on model objects in its model layer. From c192004b06b640f1b1e9e81fda13f199721efe90 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 16:30:17 +0200 Subject: [PATCH 105/316] Don't use atom.{config,styles} global in Package --- spec/package-spec.coffee | 30 +++++++++++++++--------------- src/atom-environment.coffee | 6 +++--- src/package-manager.coffee | 6 +++--- src/package.coffee | 30 +++++++++++++++--------------- src/theme-package.coffee | 4 ++-- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index c106689f2..d518613a2 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -13,29 +13,29 @@ describe "Package", -> it "does not activate it", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages) + pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) expect(pack.isCompatible()).toBe false expect(pack.incompatibleModules[0].name).toBe 'native-module' expect(pack.incompatibleModules[0].path).toBe path.join(packagePath, 'node_modules', 'native-module') it "utilizes _atomModuleCache if present to determine the package's native dependencies", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-ignored-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages) + pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) expect(pack.getNativeModuleDependencyPaths().length).toBe(1) # doesn't see the incompatible module expect(pack.isCompatible()).toBe true packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-cached-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages) + pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) expect(pack.isCompatible()).toBe false it "caches the incompatible native modules in local storage", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - expect(new Package(path: packagePath, packageManager: atom.packages).isCompatible()).toBe false + expect(new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 1 expect(global.localStorage.setItem.callCount).toBe 1 - expect(new Package(path: packagePath, packageManager: atom.packages).isCompatible()).toBe false + expect(new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 2 expect(global.localStorage.setItem.callCount).toBe 1 @@ -49,7 +49,7 @@ describe "Package", -> it "returns a promise resolving to the results of `apm rebuild`", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index') - pack = new Package(path: packagePath, packageManager: atom.packages) + pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) rebuildCallbacks = [] spyOn(pack, 'runRebuildProcess').andCallFake ((callback) -> rebuildCallbacks.push(callback)) @@ -63,7 +63,7 @@ describe "Package", -> it "persists build failures in local storage", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index') - pack = new Package(path: packagePath, packageManager: atom.packages) + pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) expect(pack.isCompatible()).toBe true expect(pack.getBuildFailureOutput()).toBeNull() @@ -79,7 +79,7 @@ describe "Package", -> expect(pack.isCompatible()).toBe false # A different package instance has the same failure output (simulates reload) - pack2 = new Package(path: packagePath, packageManager: atom.packages) + pack2 = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) expect(pack2.getBuildFailureOutput()).toBe 'It is broken' expect(pack2.isCompatible()).toBe false @@ -92,7 +92,7 @@ describe "Package", -> it "sets cached incompatible modules to an empty array when the rebuild completes (there may be a build error, but rebuilding *deletes* native modules)", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages) + pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) expect(pack.getIncompatibleNativeModules().length).toBeGreaterThan(0) @@ -118,14 +118,14 @@ describe "Package", -> it "loads and applies css", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "1234px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-index-css') - theme = new ThemePackage(path: themePath, packageManager: atom.packages) + theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "1234px" it "parses, loads and applies less", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "1234px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-index-less') - theme = new ThemePackage(path: themePath, packageManager: atom.packages) + theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "4321px" @@ -136,7 +136,7 @@ describe "Package", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe("103px") themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages) + theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe("101px") expect(getComputedStyle(editorElement).paddingRight).toBe("102px") @@ -149,7 +149,7 @@ describe "Package", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "30px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-without-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages) + theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "10px" expect(getComputedStyle(editorElement).paddingRight).toBe "20px" @@ -158,7 +158,7 @@ describe "Package", -> describe "reloading a theme", -> beforeEach -> themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages) + theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) theme.activate() it "reloads without readding to the stylesheets list", -> @@ -169,7 +169,7 @@ describe "Package", -> describe "events", -> beforeEach -> themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages) + theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) theme.activate() it "deactivated event fires on .deactivate()", -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 60ef08ed7..cbb4b218c 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -142,12 +142,12 @@ class AtomEnvironment extends Model @commands = new CommandRegistry registerDefaultCommands(this) - PackageManager = require './package-manager' - @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config}) - StyleManager = require './style-manager' @styles = new StyleManager({configDirPath}) + PackageManager = require './package-manager' + @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles}) + ThemeManager = require './theme-manager' @themes = new ThemeManager({ packageManager: @packages, configDirPath, resourcePath, safeMode, @config, diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 9b382d093..09a76c109 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -28,7 +28,7 @@ ThemePackage = require './theme-package' # settings and also by calling `enablePackage()/disablePackage()`. module.exports = class PackageManager - constructor: ({configDirPath, @devMode, safeMode, @resourcePath, @config}) -> + constructor: ({configDirPath, @devMode, safeMode, @resourcePath, @config, @styleManager}) -> @emitter = new Emitter @activationHookEmitter = new Emitter @packageDirPaths = [] @@ -354,9 +354,9 @@ class PackageManager return null if metadata.theme - pack = new ThemePackage({path: packagePath, metadata, packageManager: this}) + pack = new ThemePackage({path: packagePath, metadata, packageManager: this, @config, @styleManager}) else - pack = new Package({path: packagePath, metadata, packageManager: this}) + pack = new Package({path: packagePath, metadata, packageManager: this, @config, @styleManager}) pack.load() @loadedPackages[pack.name] = pack @emitter.emit 'did-load-package', pack diff --git a/src/package.coffee b/src/package.coffee index 584000b57..97bfd774e 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -29,7 +29,7 @@ class Package Section: Construction ### - constructor: ({@path, @metadata, @packageManager}) -> + constructor: ({@path, @metadata, @packageManager, @config, @styleManager}) -> @emitter = new Emitter @metadata ?= @packageManager.loadPackageMetadata(@path) @bundledPackage = @packageManager.isBundledPackagePath(@path) @@ -54,10 +54,10 @@ class Package ### enable: -> - atom.config.removeAtKeyPath('core.disabledPackages', @name) + @config.removeAtKeyPath('core.disabledPackages', @name) disable: -> - atom.config.pushAtKeyPath('core.disabledPackages', @name) + @config.pushAtKeyPath('core.disabledPackages', @name) isTheme: -> @metadata?.theme? @@ -114,7 +114,7 @@ class Package @activateConfig() @activateStylesheets() if @mainModule? and not @mainActivated - @mainModule.activate?(atom.packages.getPackageState(@name) ? {}) + @mainModule.activate?(@packageManager.getPackageState(@name) ? {}) @mainActivated = true @activateServices() catch error @@ -128,7 +128,7 @@ class Package @requireMainModule() unless @mainModule? if @mainModule? if @mainModule.config? and typeof @mainModule.config is 'object' - atom.config.setSchema @name, {type: 'object', properties: @mainModule.config} + @config.setSchema @name, {type: 'object', properties: @mainModule.config} @mainModule.activateConfig?() @configActivated = true @@ -146,13 +146,13 @@ class Package else context = undefined - @stylesheetDisposables.add(atom.styles.addStyleSheet(source, {sourcePath, priority, context})) + @stylesheetDisposables.add(@styleManager.addStyleSheet(source, {sourcePath, priority, context})) @stylesheetsActivated = true activateResources: -> @activationDisposables = new CompositeDisposable - keymapIsDisabled = _.include(atom.config.get("core.packagesWithKeymapsDisabled") ? [], @name) + keymapIsDisabled = _.include(@config.get("core.packagesWithKeymapsDisabled") ? [], @name) if keymapIsDisabled @deactivateKeymaps() else @@ -207,24 +207,24 @@ class Package for version, methodName of versions if typeof @mainModule[methodName] is 'function' servicesByVersion[version] = @mainModule[methodName]() - @activationDisposables.add atom.packages.serviceHub.provide(name, servicesByVersion) + @activationDisposables.add @packageManager.serviceHub.provide(name, servicesByVersion) for name, {versions} of @metadata.consumedServices for version, methodName of versions if typeof @mainModule[methodName] is 'function' - @activationDisposables.add atom.packages.serviceHub.consume(name, version, @mainModule[methodName].bind(@mainModule)) + @activationDisposables.add @packageManager.serviceHub.consume(name, version, @mainModule[methodName].bind(@mainModule)) return loadKeymaps: -> if @bundledPackage and @packageManager.packagesCache[@name]? - @keymaps = (["#{atom.packages.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps) + @keymaps = (["#{@packageManager.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps) else @keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath) ? {}] return loadMenus: -> if @bundledPackage and @packageManager.packagesCache[@name]? - @menus = (["#{atom.packages.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of @packageManager.packagesCache[@name].menus) + @menus = (["#{@packageManager.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of @packageManager.packagesCache[@name].menus) else @menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath) ? {}] return @@ -394,7 +394,7 @@ class Package if @bundledPackage and @packageManager.packagesCache[@name]? if @packageManager.packagesCache[@name].main - @mainModulePath = "#{atom.packages.resourcePath}#{path.sep}#{@packageManager.packagesCache[@name].main}" + @mainModulePath = "#{@packageManager.resourcePath}#{path.sep}#{@packageManager.packagesCache[@name].main}" else @mainModulePath = null else @@ -467,7 +467,7 @@ class Package @activationHookSubscriptions = new CompositeDisposable for hook in @getActivationHooks() do (hook) => - @activationHookSubscriptions.add(atom.packages.onDidTriggerActivationHook(hook, => @activateNow())) if hook? and _.isString(hook) and hook.trim().length > 0 + @activationHookSubscriptions.add(@packageManager.onDidTriggerActivationHook(hook, => @activateNow())) if hook? and _.isString(hook) and hook.trim().length > 0 return @@ -529,7 +529,7 @@ class Package isCompatible: -> return @compatible if @compatible? - if @path.indexOf(path.join(atom.packages.resourcePath, 'node_modules') + path.sep) is 0 + if @path.indexOf(path.join(@packageManager.resourcePath, 'node_modules') + path.sep) is 0 # Bundled packages are always considered compatible @compatible = true else if @getMainModulePath() @@ -565,7 +565,7 @@ class Package stderr = '' stdout = '' new BufferedProcess({ - command: atom.packages.getApmPath() + command: @packageManager.getApmPath() args: ['rebuild', '--no-color'] options: {cwd: @path} stderr: (output) -> stderr += output diff --git a/src/theme-package.coffee b/src/theme-package.coffee index 6d0a88052..084728869 100644 --- a/src/theme-package.coffee +++ b/src/theme-package.coffee @@ -7,10 +7,10 @@ class ThemePackage extends Package getStyleSheetPriority: -> 1 enable: -> - atom.config.unshiftAtKeyPath('core.themes', @name) + @config.unshiftAtKeyPath('core.themes', @name) disable: -> - atom.config.removeAtKeyPath('core.themes', @name) + @config.removeAtKeyPath('core.themes', @name) load: -> @loadTime = 0 From 7b25af5ad4eb0e807ce8b1cc3562e7cd8aa68966 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 18:53:50 +0200 Subject: [PATCH 106/316] Remove more globals from Package :fire: atom.{notifications,keymaps,commands,grammars,inDevMode} --- spec/package-spec.coffee | 37 ++++++++++++++++++++++--------------- src/atom-environment.coffee | 8 ++++---- src/package-manager.coffee | 12 ++++++++---- src/package.coffee | 20 ++++++++++---------- 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index d518613a2..9b5962018 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -3,6 +3,13 @@ Package = require '../src/package' ThemePackage = require '../src/theme-package' describe "Package", -> + build = (constructor, path) -> + new constructor(path: path, packageManager: atom.packages, config: atom.config, styleManager: atom.styles, notificationManager: atom.notifications, keymapManager: atom.keymaps, commandRegistry: atom.command, grammarRegistry: atom.grammars, inDevMode: atom.inDevMode) + + buildPackage = (packagePath) -> build(Package, packagePath) + + buildThemePackage = (themePath) -> build(ThemePackage, themePath) + describe "when the package contains incompatible native modules", -> beforeEach -> spyOn(atom, 'inDevMode').andReturn(false) @@ -13,29 +20,29 @@ describe "Package", -> it "does not activate it", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack = buildPackage(packagePath) expect(pack.isCompatible()).toBe false expect(pack.incompatibleModules[0].name).toBe 'native-module' expect(pack.incompatibleModules[0].path).toBe path.join(packagePath, 'node_modules', 'native-module') it "utilizes _atomModuleCache if present to determine the package's native dependencies", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-ignored-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack = buildPackage(packagePath) expect(pack.getNativeModuleDependencyPaths().length).toBe(1) # doesn't see the incompatible module expect(pack.isCompatible()).toBe true packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-cached-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack = buildPackage(packagePath) expect(pack.isCompatible()).toBe false it "caches the incompatible native modules in local storage", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - expect(new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles).isCompatible()).toBe false + expect(buildPackage(packagePath).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 1 expect(global.localStorage.setItem.callCount).toBe 1 - expect(new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles).isCompatible()).toBe false + expect(buildPackage(packagePath).isCompatible()).toBe false expect(global.localStorage.getItem.callCount).toBe 2 expect(global.localStorage.setItem.callCount).toBe 1 @@ -49,7 +56,7 @@ describe "Package", -> it "returns a promise resolving to the results of `apm rebuild`", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index') - pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack = buildPackage(packagePath) rebuildCallbacks = [] spyOn(pack, 'runRebuildProcess').andCallFake ((callback) -> rebuildCallbacks.push(callback)) @@ -63,7 +70,7 @@ describe "Package", -> it "persists build failures in local storage", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index') - pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack = buildPackage(packagePath) expect(pack.isCompatible()).toBe true expect(pack.getBuildFailureOutput()).toBeNull() @@ -79,7 +86,7 @@ describe "Package", -> expect(pack.isCompatible()).toBe false # A different package instance has the same failure output (simulates reload) - pack2 = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack2 = buildPackage(packagePath) expect(pack2.getBuildFailureOutput()).toBe 'It is broken' expect(pack2.isCompatible()).toBe false @@ -92,7 +99,7 @@ describe "Package", -> it "sets cached incompatible modules to an empty array when the rebuild completes (there may be a build error, but rebuilding *deletes* native modules)", -> packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module') - pack = new Package(path: packagePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + pack = buildPackage(packagePath) expect(pack.getIncompatibleNativeModules().length).toBeGreaterThan(0) @@ -118,14 +125,14 @@ describe "Package", -> it "loads and applies css", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "1234px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-index-css') - theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + theme = buildThemePackage(themePath) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "1234px" it "parses, loads and applies less", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "1234px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-index-less') - theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + theme = buildThemePackage(themePath) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "4321px" @@ -136,7 +143,7 @@ describe "Package", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe("103px") themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + theme = buildThemePackage(themePath) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe("101px") expect(getComputedStyle(editorElement).paddingRight).toBe("102px") @@ -149,7 +156,7 @@ describe "Package", -> expect(getComputedStyle(editorElement).paddingBottom).not.toBe "30px" themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-without-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + theme = buildThemePackage(themePath) theme.activate() expect(getComputedStyle(editorElement).paddingTop).toBe "10px" expect(getComputedStyle(editorElement).paddingRight).toBe "20px" @@ -158,7 +165,7 @@ describe "Package", -> describe "reloading a theme", -> beforeEach -> themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + theme = buildThemePackage(themePath) theme.activate() it "reloads without readding to the stylesheets list", -> @@ -169,7 +176,7 @@ describe "Package", -> describe "events", -> beforeEach -> themePath = atom.project.getDirectories()[0]?.resolve('packages/theme-with-package-file') - theme = new ThemePackage(path: themePath, packageManager: atom.packages, config: atom.config, styleManager: atom.styles) + theme = buildThemePackage(themePath) theme.activate() it "deactivated event fires on .deactivate()", -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index cbb4b218c..82fadfc31 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -142,11 +142,14 @@ class AtomEnvironment extends Model @commands = new CommandRegistry registerDefaultCommands(this) + GrammarRegistry = require './grammar-registry' + @grammars = new GrammarRegistry({@config}) + StyleManager = require './style-manager' @styles = new StyleManager({configDirPath}) PackageManager = require './package-manager' - @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles}) + @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications, grammarRegistry: @grammars, inDevMode: @inDevMode.bind(this)}) ThemeManager = require './theme-manager' @themes = new ThemeManager({ @@ -163,9 +166,6 @@ class AtomEnvironment extends Model Clipboard = require './clipboard' @clipboard = new Clipboard() - GrammarRegistry = require './grammar-registry' - @grammars = new GrammarRegistry({@config}) - Project = require './project' @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm}) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 09a76c109..775ebacc3 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -28,7 +28,7 @@ ThemePackage = require './theme-package' # settings and also by calling `enablePackage()/disablePackage()`. module.exports = class PackageManager - constructor: ({configDirPath, @devMode, safeMode, @resourcePath, @config, @styleManager}) -> + constructor: ({configDirPath, @devMode, safeMode, @resourcePath, @config, @styleManager, @notificationManager, @inDevMode, @keymapManager, @commandRegistry, @grammarRegistry}) -> @emitter = new Emitter @activationHookEmitter = new Emitter @packageDirPaths = [] @@ -353,10 +353,14 @@ class PackageManager console.warn "Could not load #{metadata.name}@#{metadata.version} because it uses deprecated APIs that have been removed." return null + options = { + path: packagePath, metadata, packageManager: this, + @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry + } if metadata.theme - pack = new ThemePackage({path: packagePath, metadata, packageManager: this, @config, @styleManager}) + pack = new ThemePackage(options) else - pack = new Package({path: packagePath, metadata, packageManager: this, @config, @styleManager}) + pack = new Package(options) pack.load() @loadedPackages[pack.name] = pack @emitter.emit 'did-load-package', pack @@ -446,7 +450,7 @@ class PackageManager detail = "#{error.message} in #{metadataPath}" stack = "#{error.stack}\n at #{metadataPath}:1:1" message = "Failed to load the #{path.basename(packagePath)} package" - atom.notifications.addError(message, {stack, detail, dismissable: true}) + @notificationManager.addError(message, {stack, detail, dismissable: true}) uninstallDirectory: (directory) -> symlinkPromise = new Promise (resolve) -> diff --git a/src/package.coffee b/src/package.coffee index 97bfd774e..018b3f535 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -29,7 +29,7 @@ class Package Section: Construction ### - constructor: ({@path, @metadata, @packageManager, @config, @styleManager}) -> + constructor: ({@path, @metadata, @packageManager, @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry}) -> @emitter = new Emitter @metadata ?= @packageManager.loadPackageMetadata(@path) @bundledPackage = @packageManager.isBundledPackagePath(@path) @@ -182,7 +182,7 @@ class Package @keymapDisposables = new CompositeDisposable() - @keymapDisposables.add(atom.keymaps.add(keymapPath, map)) for [keymapPath, map] in @keymaps + @keymapDisposables.add(@keymapManager.add(keymapPath, map)) for [keymapPath, map] in @keymaps atom.menu.update() @keymapActivated = true @@ -268,7 +268,7 @@ class Package grammarPaths = fs.listSync(grammarsDirPath, ['json', 'cson']) for grammarPath in grammarPaths try - grammar = atom.grammars.readGrammarSync(grammarPath) + grammar = @grammarRegistry.readGrammarSync(grammarPath) grammar.packageName = @name grammar.bundledPackage = @bundledPackage @grammars.push(grammar) @@ -283,11 +283,11 @@ class Package return Promise.resolve() if @grammarsLoaded loadGrammar = (grammarPath, callback) => - atom.grammars.readGrammar grammarPath, (error, grammar) => + @grammarRegistry.readGrammar grammarPath, (error, grammar) => if error? detail = "#{error.message} in #{grammarPath}" stack = "#{error.stack}\n at #{grammarPath}:1:1" - atom.notifications.addFatalError("Failed to load a #{@name} package grammar", {stack, detail, dismissable: true}) + @notificationManager.addFatalError("Failed to load a #{@name} package grammar", {stack, detail, dismissable: true}) else grammar.packageName = @name grammar.bundledPackage = @bundledPackage @@ -311,7 +311,7 @@ class Package if error? detail = "#{error.message} in #{settingsPath}" stack = "#{error.stack}\n at #{settingsPath}:1:1" - atom.notifications.addFatalError("Failed to load the #{@name} package settings", {stack, detail, dismissable: true}) + @notificationManager.addFatalError("Failed to load the #{@name} package settings", {stack, detail, dismissable: true}) else @settings.push(settings) settings.activate() if @settingsActivated @@ -428,7 +428,7 @@ class Package # Add dummy command so it appears in menu. # The real command will be registered on package activation try - @activationCommandSubscriptions.add atom.commands.add selector, command, -> + @activationCommandSubscriptions.add @commandRegistry.add selector, command, -> catch error if error.code is 'EBADSELECTOR' metadataPath = path.join(@path, 'package.json') @@ -436,7 +436,7 @@ class Package error.stack += "\n at #{metadataPath}:1:1" throw error - @activationCommandSubscriptions.add atom.commands.onWillDispatch (event) => + @activationCommandSubscriptions.add @commandRegistry.onWillDispatch (event) => return unless event.type is command currentTarget = event.target while currentTarget @@ -587,7 +587,7 @@ class Package # This information is cached in local storage on a per package/version basis # to minimize the impact on startup time. getIncompatibleNativeModules: -> - unless atom.inDevMode() + unless @inDevMode() try if arrayAsString = global.localStorage.getItem(@getIncompatibleNativeModulesStorageKey()) return JSON.parse(arrayAsString) @@ -628,4 +628,4 @@ class Package detail = error.message stack = error.stack ? error - atom.notifications.addFatalError(message, {stack, detail, dismissable: true}) + @notificationManager.addFatalError(message, {stack, detail, dismissable: true}) From 41089392012a68a00d8d6544f07e6829cd46a2df Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 19:07:58 +0200 Subject: [PATCH 107/316] Don't use atom.{themes,menu,contextMenu} global in Package --- spec/package-spec.coffee | 2 +- src/atom-environment.coffee | 4 ++++ src/package-manager.coffee | 8 +++++++- src/package.coffee | 14 +++++++------- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index 9b5962018..e3b94830b 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -4,7 +4,7 @@ ThemePackage = require '../src/theme-package' describe "Package", -> build = (constructor, path) -> - new constructor(path: path, packageManager: atom.packages, config: atom.config, styleManager: atom.styles, notificationManager: atom.notifications, keymapManager: atom.keymaps, commandRegistry: atom.command, grammarRegistry: atom.grammars, inDevMode: atom.inDevMode) + new constructor(path: path, packageManager: atom.packages, config: atom.config, styleManager: atom.styles, notificationManager: atom.notifications, keymapManager: atom.keymaps, commandRegistry: atom.command, grammarRegistry: atom.grammars, themeManager: atom.themes, menuManager: atom.menu, contextMenuManager: atom.contextMenu, inDevMode: atom.inDevMode) buildPackage = (packagePath) -> build(Package, packagePath) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 82fadfc31..349357824 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -163,6 +163,10 @@ class AtomEnvironment extends Model ContextMenuManager = require './context-menu-manager' @contextMenu = new ContextMenuManager({resourcePath, devMode, keymapManager: @keymaps}) + @packages.setMenuManager(@menu) + @packages.setContextMenuManager(@contextMenu) + @packages.setThemeManager(@themes) + Clipboard = require './clipboard' @clipboard = new Clipboard() diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 775ebacc3..beed62683 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -46,6 +46,12 @@ class PackageManager @packageActivators = [] @registerPackageActivator(this, ['atom', 'textmate']) + setContextMenuManager: (@contextMenuManager) -> + + setMenuManager: (@menuManager) -> + + setThemeManager: (@themeManager) -> + ### Section: Event Subscription ### @@ -355,7 +361,7 @@ class PackageManager options = { path: packagePath, metadata, packageManager: this, - @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry + @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry, @themeManager, @menuManager, @contextMenuManager } if metadata.theme pack = new ThemePackage(options) diff --git a/src/package.coffee b/src/package.coffee index 018b3f535..0e5cb1502 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -29,7 +29,7 @@ class Package Section: Construction ### - constructor: ({@path, @metadata, @packageManager, @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry}) -> + constructor: ({@path, @metadata, @packageManager, @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry, @themeManager, @menuManager, @contextMenuManager}) -> @emitter = new Emitter @metadata ?= @packageManager.loadPackageMetadata(@path) @bundledPackage = @packageManager.isBundledPackagePath(@path) @@ -161,14 +161,14 @@ class Package for [menuPath, map] in @menus when map['context-menu']? try itemsBySelector = map['context-menu'] - @activationDisposables.add(atom.contextMenu.add(itemsBySelector)) + @activationDisposables.add(@contextMenuManager.add(itemsBySelector)) catch error if error.code is 'EBADSELECTOR' error.message += " in #{menuPath}" error.stack += "\n at #{menuPath}:1:1" throw error - @activationDisposables.add(atom.menu.add(map['menu'])) for [menuPath, map] in @menus when map['menu']? + @activationDisposables.add(@menuManager.add(map['menu'])) for [menuPath, map] in @menus when map['menu']? unless @grammarsActivated grammar.activate() for grammar in @grammars @@ -183,7 +183,7 @@ class Package @keymapDisposables = new CompositeDisposable() @keymapDisposables.add(@keymapManager.add(keymapPath, map)) for [keymapPath, map] in @keymaps - atom.menu.update() + @menuManager.update() @keymapActivated = true @@ -191,7 +191,7 @@ class Package return if not @keymapActivated @keymapDisposables?.dispose() - atom.menu.update() + @menuManager.update() @keymapActivated = false @@ -244,8 +244,8 @@ class Package fs.listSync(menusDirPath, ['cson', 'json']) loadStylesheets: -> - @stylesheets = @getStylesheetPaths().map (stylesheetPath) -> - [stylesheetPath, atom.themes.loadStylesheet(stylesheetPath, true)] + @stylesheets = @getStylesheetPaths().map (stylesheetPath) => + [stylesheetPath, @themeManager.loadStylesheet(stylesheetPath, true)] getStylesheetsPath: -> path.join(@path, 'styles') From b2d178f64106da9fd45fa3b6b3cc626be8042132 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 19:33:23 +0200 Subject: [PATCH 108/316] :green_heart: Avoid resetting atom.grammars ...because it messes up subsequent tests that hit code paths that make use of atom.grammars. /cc: @nathansobo @maxbrunsfeld --- spec/package-manager-spec.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/package-manager-spec.coffee b/spec/package-manager-spec.coffee index 3121ad5e9..9a2edee0a 100644 --- a/spec/package-manager-spec.coffee +++ b/spec/package-manager-spec.coffee @@ -770,8 +770,6 @@ describe "PackageManager", -> atom.packages.deactivatePackages() atom.packages.unloadPackages() - GrammarRegistry = require '../src/grammar-registry' - atom.grammars = window.syntax = new GrammarRegistry(config: atom.config) jasmine.restoreDeprecationsSnapshot() it "activates all the packages, and none of the themes", -> From b5fc710f1538aa8c53af190ad08de9fec7b0bcb0 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 19:57:13 +0200 Subject: [PATCH 109/316] Don't use atom.clipboard global in Selection --- src/selection.coffee | 8 ++++---- src/text-editor.coffee | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/selection.coffee b/src/selection.coffee index 80929cac7..2ba66ebb0 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -14,7 +14,7 @@ class Selection extends Model initialScreenRange: null wordwise: false - constructor: ({@cursor, @marker, @editor, id}) -> + constructor: ({@cursor, @marker, @editor, id, @clipboard}) -> @emitter = new Emitter @assignId(id) @@ -611,7 +611,7 @@ class Selection extends Model startLevel = @editor.indentLevelForLine(precedingText) if maintainClipboard - {text: clipboardText, metadata} = atom.clipboard.readWithMetadata() + {text: clipboardText, metadata} = @clipboard.readWithMetadata() metadata ?= {} unless metadata.selections? metadata.selections = [{ @@ -624,9 +624,9 @@ class Selection extends Model indentBasis: startLevel, fullLine: fullLine }) - atom.clipboard.write([clipboardText, selectionText].join("\n"), metadata) + @clipboard.write([clipboardText, selectionText].join("\n"), metadata) else - atom.clipboard.write(selectionText, { + @clipboard.write(selectionText, { indentBasis: startLevel, fullLine: fullLine }) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index c59cf1455..73afbfad7 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -2250,7 +2250,7 @@ class TextEditor extends Model unless marker.getProperties().preserveFolds @destroyFoldsContainingBufferRange(marker.getBufferRange()) cursor = @addCursor(marker) - selection = new Selection(_.extend({editor: this, marker, cursor}, options)) + selection = new Selection(_.extend({editor: this, marker, cursor, @clipboard}, options)) @selections.push(selection) selectionBufferRange = selection.getBufferRange() @mergeIntersectingSelections(preserveFolds: marker.getProperties().preserveFolds) From ff86eb6a593de75906ec84cafb4c8d31426e15ea Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 19:59:20 +0200 Subject: [PATCH 110/316] Don't use atom.config global in ScopedProperties --- src/package.coffee | 2 +- src/scoped-properties.coffee | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/package.coffee b/src/package.coffee index 0e5cb1502..e4d803852 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -307,7 +307,7 @@ class Package @settings = [] loadSettingsFile = (settingsPath, callback) => - ScopedProperties.load settingsPath, (error, settings) => + ScopedProperties.load settingsPath, @config, (error, settings) => if error? detail = "#{error.message} in #{settingsPath}" stack = "#{error.stack}\n at #{settingsPath}:1:1" diff --git a/src/scoped-properties.coffee b/src/scoped-properties.coffee index 8bf4c5ed3..c7257083e 100644 --- a/src/scoped-properties.coffee +++ b/src/scoped-properties.coffee @@ -3,21 +3,21 @@ CSON = require 'season' module.exports = class ScopedProperties - @load: (scopedPropertiesPath, callback) -> + @load: (scopedPropertiesPath, config, callback) -> CSON.readFile scopedPropertiesPath, (error, scopedProperties={}) -> if error? callback(error) else - callback(null, new ScopedProperties(scopedPropertiesPath, scopedProperties)) + callback(null, new ScopedProperties(scopedPropertiesPath, scopedProperties, config)) - constructor: (@path, @scopedProperties) -> + constructor: (@path, @scopedProperties, @config) -> activate: -> for selector, properties of @scopedProperties - atom.config.set(null, properties, scopeSelector: selector, source: @path) + @config.set(null, properties, scopeSelector: selector, source: @path) return deactivate: -> for selector of @scopedProperties - atom.config.unset(null, scopeSelector: selector, source: @path) + @config.unset(null, scopeSelector: selector, source: @path) return From a3a6db7f687d3699ab722b1bb106447ef62f37cf Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 6 Oct 2015 21:13:57 +0200 Subject: [PATCH 111/316] Don't use atom.{config,confirm} global in GitRepository --- spec/git-repository-provider-spec.coffee | 12 +++++------- spec/git-spec.coffee | 7 ++++--- spec/spec-helper.coffee | 2 +- src/atom-environment.coffee | 2 +- src/git-repository-provider.coffee | 4 ++-- src/git-repository.coffee | 6 +++--- src/project.coffee | 4 ++-- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/spec/git-repository-provider-spec.coffee b/spec/git-repository-provider-spec.coffee index 13a0724d6..bbbfb4b03 100644 --- a/spec/git-repository-provider-spec.coffee +++ b/spec/git-repository-provider-spec.coffee @@ -6,11 +6,15 @@ GitRepository = require '../src/git-repository' GitRepositoryProvider = require '../src/git-repository-provider' describe "GitRepositoryProvider", -> + provider = null + + beforeEach -> + provider = new GitRepositoryProvider(atom.project, atom.config, atom.confirm) + describe ".repositoryForDirectory(directory)", -> describe "when specified a Directory with a Git repository", -> it "returns a Promise that resolves to a GitRepository", -> waitsForPromise -> - provider = new GitRepositoryProvider atom.project directory = new Directory path.join(__dirname, 'fixtures', 'git', 'master.git') provider.repositoryForDirectory(directory).then (result) -> expect(result).toBeInstanceOf GitRepository @@ -19,7 +23,6 @@ describe "GitRepositoryProvider", -> expect(result.getType()).toBe 'git' it "returns the same GitRepository for different Directory objects in the same repo", -> - provider = new GitRepositoryProvider atom.project firstRepo = null secondRepo = null @@ -38,7 +41,6 @@ describe "GitRepositoryProvider", -> describe "when specified a Directory without a Git repository", -> it "returns a Promise that resolves to null", -> waitsForPromise -> - provider = new GitRepositoryProvider atom.project directory = new Directory temp.mkdirSync('dir') provider.repositoryForDirectory(directory).then (result) -> expect(result).toBe null @@ -46,7 +48,6 @@ describe "GitRepositoryProvider", -> describe "when specified a Directory with an invalid Git repository", -> it "returns a Promise that resolves to null", -> waitsForPromise -> - provider = new GitRepositoryProvider atom.project dirPath = temp.mkdirSync('dir') fs.writeFileSync(path.join(dirPath, '.git', 'objects'), '') fs.writeFileSync(path.join(dirPath, '.git', 'HEAD'), '') @@ -59,7 +60,6 @@ describe "GitRepositoryProvider", -> describe "when specified a Directory with a valid gitfile-linked repository", -> it "returns a Promise that resolves to a GitRepository", -> waitsForPromise -> - provider = new GitRepositoryProvider atom.project gitDirPath = path.join(__dirname, 'fixtures', 'git', 'master.git') workDirPath = temp.mkdirSync('git-workdir') fs.writeFileSync(path.join(workDirPath, '.git'), 'gitdir: ' + gitDirPath+'\n') @@ -75,8 +75,6 @@ describe "GitRepositoryProvider", -> directory = null provider = null beforeEach -> - provider = new GitRepositoryProvider atom.project - # An implementation of Directory that does not implement existsSync(). subdirectory = {} directory = diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index 9359499bc..31ac176f7 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -124,8 +124,10 @@ describe "GitRepository", -> [filePath, editor] = [] beforeEach -> + spyOn(atom, "confirm") + workingDirPath = copyRepository() - repo = new GitRepository(workingDirPath) + repo = new GitRepository(workingDirPath, {project: atom.project, config: atom.config, confirm: atom.confirm}) filePath = path.join(workingDirPath, 'a.txt') fs.writeFileSync(filePath, 'ch ch changes') @@ -136,7 +138,7 @@ describe "GitRepository", -> editor = atom.workspace.getActiveTextEditor() it "displays a confirmation dialog by default", -> - spyOn(atom, 'confirm').andCallFake ({buttons}) -> buttons.OK() + atom.confirm.andCallFake ({buttons}) -> buttons.OK() atom.config.set('editor.confirmCheckoutHeadRevision', true) repo.checkoutHeadForEditor(editor) @@ -144,7 +146,6 @@ describe "GitRepository", -> expect(fs.readFileSync(filePath, 'utf8')).toBe '' it "does not display a dialog when confirmation is disabled", -> - spyOn(atom, 'confirm') atom.config.set('editor.confirmCheckoutHeadRevision', false) repo.checkoutHeadForEditor(editor) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index b8a354e21..7b21c22d3 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -85,7 +85,7 @@ beforeEach -> documentTitle = null projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures') atom.packages.serviceHub = new ServiceHub - atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) + atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, config: atom.config, confirm: atom.confirm}) atom.project.setPaths([projectPath]) atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 349357824..f2a3c8f2d 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -171,7 +171,7 @@ class AtomEnvironment extends Model @clipboard = new Clipboard() Project = require './project' - @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm}) + @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm, @config}) CommandInstaller = require './command-installer' @commandInstaller = new CommandInstaller(@getVersion(), @confirm.bind(this)) diff --git a/src/git-repository-provider.coffee b/src/git-repository-provider.coffee index 3b4df5d2b..1f2d2b776 100644 --- a/src/git-repository-provider.coffee +++ b/src/git-repository-provider.coffee @@ -48,7 +48,7 @@ isValidGitDirectorySync = (directory) -> module.exports = class GitRepositoryProvider - constructor: (@project) -> + constructor: (@project, @config, @confirm) -> # Keys are real paths that end in `.git`. # Values are the corresponding GitRepository objects. @pathToRepository = {} @@ -75,7 +75,7 @@ class GitRepositoryProvider gitDirPath = gitDir.getPath() repo = @pathToRepository[gitDirPath] unless repo - repo = GitRepository.open(gitDirPath, project: @project) + repo = GitRepository.open(gitDirPath, {@project, @config, @confirm}) return null unless repo repo.onDidDestroy(=> delete @pathToRepository[gitDirPath]) @pathToRepository[gitDirPath] = repo diff --git a/src/git-repository.coffee b/src/git-repository.coffee index 064b86dd3..e1ea58e44 100644 --- a/src/git-repository.coffee +++ b/src/git-repository.coffee @@ -80,7 +80,7 @@ class GitRepository for submodulePath, submoduleRepo of @repo.submodules submoduleRepo.upstream = {ahead: 0, behind: 0} - {@project, refreshOnWindowFocus} = options + {@project, @config, @confirm, refreshOnWindowFocus} = options refreshOnWindowFocus ?= true if refreshOnWindowFocus @@ -452,8 +452,8 @@ class GitRepository editor.buffer.reload() if editor.buffer.isModified() @checkoutHead(filePath) - if atom.config.get('editor.confirmCheckoutHeadRevision') - atom.confirm + if @config.get('editor.confirmCheckoutHeadRevision') + @confirm message: 'Confirm Checkout HEAD Revision' detailedMessage: "Are you sure you want to discard all changes to \"#{fileName}\" since the last Git commit?" buttons: diff --git a/src/project.coffee b/src/project.coffee index 6532b4aa5..4f135a0ef 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -21,7 +21,7 @@ class Project extends Model Section: Construction and Destruction ### - constructor: ({@confirm, @notificationManager, packageManager}) -> + constructor: ({@confirm, @notificationManager, packageManager, config}) -> @emitter = new Emitter @buffers = [] @paths = [] @@ -41,7 +41,7 @@ class Project extends Model # the same real path, so it is not a good key. @repositoryPromisesByPath = new Map() - @repositoryProviders = [new GitRepositoryProvider(this)] + @repositoryProviders = [new GitRepositoryProvider(this, config, confirm)] packageManager.serviceHub.consume( 'atom.repository-provider', '^0.1.0', From 9924288a6f8de7e6eb9737aa3f5087f8e6df626a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Oct 2015 13:44:24 -0700 Subject: [PATCH 112/316] Use atom environment argument to deserialize in Pane, PaneAxis --- spec/pane-spec.coffee | 8 ++++---- src/pane-axis.coffee | 7 +++---- src/pane-container.coffee | 2 +- src/pane.coffee | 6 ++---- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 8f18b6199..0e563cb09 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -741,12 +741,12 @@ describe "Pane", -> pane = new Pane(params) it "can serialize and deserialize the pane and all its items", -> - newPane = Pane.deserialize(pane.serialize()) + newPane = Pane.deserialize(pane.serialize(), atom) expect(newPane.getItems()).toEqual pane.getItems() it "restores the active item on deserialization", -> pane.activateItemAtIndex(1) - newPane = Pane.deserialize(pane.serialize()) + newPane = Pane.deserialize(pane.serialize(), atom) expect(newPane.getActiveItem()).toEqual newPane.itemAtIndex(1) it "does not include items that cannot be deserialized", -> @@ -754,11 +754,11 @@ describe "Pane", -> unserializable = {} pane.activateItem(unserializable) - newPane = Pane.deserialize(pane.serialize()) + newPane = Pane.deserialize(pane.serialize(), atom) expect(newPane.getActiveItem()).toEqual pane.itemAtIndex(0) expect(newPane.getItems().length).toBe pane.getItems().length - 1 it "includes the pane's focus state in the serialized state", -> pane.focus() - newPane = Pane.deserialize(pane.serialize()) + newPane = Pane.deserialize(pane.serialize(), atom) expect(newPane.focused).toBe true diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index eb1aa6258..d104e984b 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -8,10 +8,9 @@ class PaneAxis extends Model container: null orientation: null - @deserialize: (state, params) -> - container = params?.container - state.container = container - state.children = state.children.map (childState) -> atom.deserializers.deserialize(childState) + @deserialize: (state, {deserializers}) -> + state.children = state.children.map (childState) -> + deserializers.deserialize(childState) new this(state) constructor: ({@orientation, children, flexScale}={}) -> diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 60537424d..a061f122c 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -31,7 +31,7 @@ class PaneContainer extends Model deserialize: (state, deserializerManager) -> return unless state.version is @serializationVersion - @setRoot(deserializerManager.deserialize(state.root, {container: this})) + @setRoot(deserializerManager.deserialize(state.root)) activePane = find @getRoot().getPanes(), (pane) -> pane.id is state.activePaneId @setActivePane(activePane ? @getPanes()[0]) @destroyEmptyPanes() if @config.get('core.destroyEmptyPanes') diff --git a/src/pane.coffee b/src/pane.coffee index 98d1c2493..f1af017de 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -14,16 +14,14 @@ class Pane extends Model activeItem: undefined focused: false - @deserialize: (state, params) -> + @deserialize: (state, {deserializers}) -> {items, activeItemURI, activeItemUri} = state - state.container = params?.container activeItemURI ?= activeItemUri - state.items = compact(items.map (itemState) -> atom.deserializers.deserialize(itemState)) + state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState)) state.activeItem = find state.items, (item) -> if typeof item.getURI is 'function' itemURI = item.getURI() itemURI is activeItemURI - new this(state) constructor: (params) -> From 4988f6be119d1dca85d361a4ece74f77ec27e8ce Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Oct 2015 13:51:05 -0700 Subject: [PATCH 113/316] Remove application:run-all-specs command --- keymaps/darwin.cson | 1 - keymaps/linux.cson | 1 - keymaps/win32.cson | 1 - menus/darwin.cson | 1 - menus/linux.cson | 1 - menus/win32.cson | 1 - src/browser/atom-application.coffee | 1 - src/register-default-commands.coffee | 1 - 8 files changed, 8 deletions(-) diff --git a/keymaps/darwin.cson b/keymaps/darwin.cson index 87c1eb9da..bf2e43a33 100644 --- a/keymaps/darwin.cson +++ b/keymaps/darwin.cson @@ -18,7 +18,6 @@ 'ctrl-d': 'core:delete' # Atom Specific - 'cmd-alt-ctrl-s': 'application:run-all-specs' 'enter': 'core:confirm' 'escape': 'core:cancel' 'up': 'core:move-up' diff --git a/keymaps/linux.cson b/keymaps/linux.cson index 9e739521c..28f43a8fc 100644 --- a/keymaps/linux.cson +++ b/keymaps/linux.cson @@ -9,7 +9,6 @@ 'ctrl-alt-r': 'window:reload' 'ctrl-shift-i': 'window:toggle-dev-tools' 'ctrl-alt-p': 'window:run-package-specs' - 'ctrl-alt-s': 'application:run-all-specs' 'ctrl-shift-o': 'application:open-folder' 'ctrl-alt-o': 'application:add-project-folder' 'ctrl-shift-pageup': 'pane:move-item-left' diff --git a/keymaps/win32.cson b/keymaps/win32.cson index b3643207f..f052a64fc 100644 --- a/keymaps/win32.cson +++ b/keymaps/win32.cson @@ -15,7 +15,6 @@ 'ctrl-alt-r': 'window:reload' 'ctrl-alt-i': 'window:toggle-dev-tools' 'ctrl-alt-p': 'window:run-package-specs' - 'ctrl-alt-s': 'application:run-all-specs' 'ctrl-shift-o': 'application:open-folder' 'ctrl-alt-o': 'application:add-project-folder' 'ctrl-shift-left': 'pane:move-item-left' diff --git a/menus/darwin.cson b/menus/darwin.cson index 27318eb47..6fff290e2 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -164,7 +164,6 @@ label: 'Developer' submenu: [ { label: 'Open In Dev Mode…', command: 'application:open-dev' } - { label: 'Run Atom Specs', command: 'application:run-all-specs' } { label: 'Run Package Specs', command: 'window:run-package-specs' } { label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' } ] diff --git a/menus/linux.cson b/menus/linux.cson index 354a5ec96..fa831b4a4 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -121,7 +121,6 @@ label: 'Developer' submenu: [ { label: 'Open In &Dev Mode…', command: 'application:open-dev' } - { label: 'Run &Atom Specs', command: 'application:run-all-specs' } { label: 'Run Package &Specs', command: 'window:run-package-specs' } { label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' } ] diff --git a/menus/win32.cson b/menus/win32.cson index 791e9d68d..04da3d388 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -120,7 +120,6 @@ label: 'Developer' submenu: [ { label: 'Open In &Dev Mode…', command: 'application:open-dev' } - { label: 'Run &Atom Specs', command: 'application:run-all-specs' } { label: 'Run Package &Specs', command: 'window:run-package-specs' } { label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' } ] diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 8aaa237dc..6612d257a 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -162,7 +162,6 @@ class AtomApplication devMode: @focusedWindow()?.devMode safeMode: @focusedWindow()?.safeMode - @on 'application:run-all-specs', -> @runTests(headless: false, resourcePath: @devResourcePath, safeMode: @focusedWindow()?.safeMode) @on 'application:quit', -> app.quit() @on 'application:new-window', -> @openPath(_.extend(windowDimensions: @focusedWindow()?.getDimensions(), getLoadSettings())) @on 'application:new-file', -> (@focusedWindow() ? this).openPath() diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index df633b8a5..93b8d4fa8 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -19,7 +19,6 @@ module.exports = (atom) -> 'window:decrease-font-size': -> @getModel().decreaseFontSize() 'window:reset-font-size': -> @getModel().resetFontSize() 'application:about': -> ipc.send('command', 'application:about') - 'application:run-all-specs': -> ipc.send('command', 'application:run-all-specs') 'application:show-preferences': -> ipc.send('command', 'application:show-settings') 'application:show-settings': -> ipc.send('command', 'application:show-settings') 'application:quit': -> ipc.send('command', 'application:quit') From 5aee514ef518f26f2c42952d78ebc087f0036ae4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Oct 2015 13:55:41 -0700 Subject: [PATCH 114/316] :fire: debuggers --- spec/text-editor-component-spec.coffee | 1 - src/workspace.coffee | 2 -- 2 files changed, 3 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index b6d811e6e..3e405398b 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -22,7 +22,6 @@ describe "TextEditorComponent", -> nextAnimationFrame = noAnimationFrame spyOn(window, 'requestAnimationFrame').andCallFake (fn) -> - debugger if global.debug nextAnimationFrame = -> nextAnimationFrame = noAnimationFrame fn() diff --git a/src/workspace.coffee b/src/workspace.coffee index 49e9bbccf..49d45103a 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -32,8 +32,6 @@ class Workspace extends Model @setDocumentEdited, @assert, @confirm } = params - debugger unless @assert? - @emitter = new Emitter @openers = [] @destroyedItemURIs = [] From a28a42b610d82dd2bdf54d7674e05a4abef81f6f Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Tue, 6 Oct 2015 23:23:51 +0200 Subject: [PATCH 115/316] :fire: Remove duplicate key --- spec/spec-helper.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 7b21c22d3..36bab14dd 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -89,7 +89,7 @@ beforeEach -> atom.project.setPaths([projectPath]) atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - grammarRegistry: atom.grammars, notificationManager: atom.notifications, + notificationManager: atom.notifications, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, From 669eff5d203871e3d99048d06e20d15e5b2bbfc6 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Tue, 6 Oct 2015 23:30:22 +0200 Subject: [PATCH 116/316] :fire: Remove duplicate keys --- spec/workspace-spec.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 10e0711bc..b39570db0 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -18,7 +18,7 @@ describe "Workspace", -> atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) atom.workspace = workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - grammarRegistry: atom.grammars, notificationManager: atom.notifications, + notificationManager: atom.notifications, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), @@ -36,7 +36,7 @@ describe "Workspace", -> atom.project.deserialize(projectState, atom.deserializers) atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - grammarRegistry: atom.grammars, notificationManager: atom.notifications, + notificationManager: atom.notifications, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, assert: atom.assert.bind(atom) @@ -635,8 +635,8 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - grammarRegistry: atom.grammars, notificationManager: atom.notifications, - clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, + notificationManager: atom.notifications, clipboard: atom.clipboard, + viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) @@ -695,8 +695,8 @@ describe "Workspace", -> document.title = null workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - grammarRegistry: atom.grammars, notificationManager: atom.notifications, - clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, + notificationManager: atom.notifications, clipboard: atom.clipboard, + viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) From d8780927940598c9e89fc8de53b0c9b73314c287 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Tue, 6 Oct 2015 23:32:29 +0200 Subject: [PATCH 117/316] :art: Replace unnecessary fat arrow --- spec/text-editor-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index e3eb5eb6d..7929bddda 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -1770,7 +1770,7 @@ describe "TextEditor", -> editor2 = null waitsForPromise -> atom.workspace.getActivePane().splitRight() - atom.workspace.open(editor.getPath()).then (o) => editor2 = o + atom.workspace.open(editor.getPath()).then (o) -> editor2 = o runs -> expect(editor2.getText()).toBe(editor.getText()) From 13301b551c90cbc25b05fc126393be804aa9f80f Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Oct 2015 15:19:55 -0700 Subject: [PATCH 118/316] :memo: Document Workspace::buildTextEditor --- src/workspace.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/workspace.coffee b/src/workspace.coffee index 49d45103a..99c794421 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -458,6 +458,9 @@ class Workspace extends Model @project.bufferForPath(filePath, options).then (buffer) => @buildTextEditor(_.extend({buffer, largeFileMode}, options)) + # Extended: Create a new text editor. + # + # Returns a {TextEditor}. buildTextEditor: (params) -> params = _.extend({ @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, From 52c43a71d3deae35dc3f0790a8197b130be30893 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 7 Oct 2015 09:22:38 +0200 Subject: [PATCH 119/316] Pass legacyTestRunner parameter --- src/browser/atom-application.coffee | 6 +++++- src/initialize-test-window.coffee | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 6612d257a..c5242c5aa 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -512,11 +512,12 @@ class AtomApplication process.stderr.write 'Error: Specify at least one test path\n\n' process.exit(1) + legacyTestRunnerPath = @resolveLegacyTestRunnerPath() testRunnerPath = @resolveTestRunnerPath(testPaths[0]) isSpec = true devMode = true safeMode ?= false - new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, testPaths, logFile, safeMode}) + new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode}) resolveTestRunnerPath: (testPath) -> FindParentDir ?= require 'find-parent-dir' @@ -531,6 +532,9 @@ class AtomApplication process.stderr.write "Error: Could not resolve test runner path '#{packageMetadata.atomTestRunner}'" process.exit(1) + @resolveLegacyTestRunnerPath() + + resolveLegacyTestRunnerPath: -> try require.resolve(path.resolve(@devResourcePath, 'spec', 'jasmine-test-runner')) catch error diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index ff30da4ac..337c48744 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -32,12 +32,14 @@ try document.title = "Spec Suite" + legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) testRunner = require(getWindowLoadSettings().testRunnerPath) testRunner({ logFile: getWindowLoadSettings().logFile headless: getWindowLoadSettings().headless testPaths: getWindowLoadSettings().testPaths buildAtomEnvironment: -> new AtomEnvironment + legacyTestRunner: legacyTestRunner }) catch error From c3d85f85a4b170e2d6f1f03d56a8318b35b5b629 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 7 Oct 2015 14:30:04 +0200 Subject: [PATCH 120/316] :fire: Remove unused LOC --- src/text-editor-element.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 7c1ee2915..fc2d2c7e9 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -17,7 +17,6 @@ class TextEditorElement extends HTMLElement focusOnAttach: false hasTiledRendering: true logicalDisplayBuffer: true - alreadySetUp: false createdCallback: -> # Use globals when the following instance variables aren't set. From dc7a4a81684ceafab16ad38aff79846f2c8ba3b6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 15:09:57 -0600 Subject: [PATCH 121/316] Increase wait time in spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This kinda sucks, but it’s not the end of the world. --- spec/menu-manager-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/menu-manager-spec.coffee b/spec/menu-manager-spec.coffee index 5fcb2fee1..a2d76c1d0 100644 --- a/spec/menu-manager-spec.coffee +++ b/spec/menu-manager-spec.coffee @@ -71,7 +71,7 @@ describe "MenuManager", -> atom.keymaps.add 'test', 'atom-workspace': 'ctrl-b': 'b' atom.keymaps.add 'test', 'atom-text-editor': 'ctrl-b': 'unset!' - waits 1 + waits 50 runs -> expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() From aa682d5b19756faf03510e7fea782dcb8359a3a4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 15:12:56 -0600 Subject: [PATCH 122/316] Restore initial styles in AtomEnvironment::reset --- spec/spec-helper.coffee | 6 ++++-- src/atom-environment.coffee | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 36bab14dd..261373a52 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -19,7 +19,10 @@ TextEditorComponent = require '../src/text-editor-component' pathwatcher = require 'pathwatcher' clipboard = require '../src/safe-clipboard' -atom.themes.requireStylesheet '../static/jasmine' +jasmineStyle = document.createElement('style') +jasmineStyle.textContent = atom.themes.loadStylesheet(atom.themes.resolveStylesheet('../static/jasmine')) +document.head.appendChild(jasmineStyle) + atom.themes.initialLoadComplete = true fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') @@ -96,7 +99,6 @@ beforeEach -> assert: atom.assert.bind(atom) }) atom.themes.workspace = atom.workspace - atom.styles.restoreSnapshot(styleElementsToRestore) atom.views.clearDocumentRequests() atom.workspaceParentSelectorctor = '#jasmine-content' diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index f2a3c8f2d..e21ea9ff0 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -156,6 +156,7 @@ class AtomEnvironment extends Model packageManager: @packages, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, notificationManager: @notifications, viewRegistry: @views }) + @initialStyleElements = @styles.getSnapshot() MenuManager = require './menu-manager' @menu = new MenuManager({resourcePath, keymapManager: @keymaps, packageManager: @packages}) @@ -242,6 +243,8 @@ class AtomEnvironment extends Model @commands.clear() registerDefaultCommands(this) + @styles.restoreSnapshot(@initialStyleElements) + ### Section: Event Subscription ### From a9a6f38858150f583c40ad4bb88c7038f1d2483d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 15:39:38 -0600 Subject: [PATCH 123/316] =?UTF-8?q?Don=E2=80=99t=20clear=20document=20requ?= =?UTF-8?q?ests=20in=20spec=20helper;=20happens=20in=20reset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/spec-helper.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 261373a52..58d6e06ce 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -99,7 +99,6 @@ beforeEach -> assert: atom.assert.bind(atom) }) atom.themes.workspace = atom.workspace - atom.views.clearDocumentRequests() atom.workspaceParentSelectorctor = '#jasmine-content' From 499272dfa10d5547e2bead7b493e3b6ebd57de7a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 15:40:15 -0600 Subject: [PATCH 124/316] Remove unused locals in spec-helper --- spec/spec-helper.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 58d6e06ce..567329618 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -28,9 +28,6 @@ atom.themes.initialLoadComplete = true fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') atom.packages.packageDirPaths.unshift(fixturePackagesPath) atom.keymaps.loadBundledKeymaps() -keyBindingsToRestore = atom.keymaps.getKeyBindings() -commandsToRestore = atom.commands.getSnapshot() -styleElementsToRestore = atom.styles.getSnapshot() window.addEventListener 'core:close', -> window.close() From 0f4558c4483eaafc6c2f31074c6c93daf7c1918c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 15:45:01 -0600 Subject: [PATCH 125/316] =?UTF-8?q?Don=E2=80=99t=20load=20key=20bindings?= =?UTF-8?q?=20in=20spec=20helper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/spec-helper.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 567329618..f7c474d5f 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -27,7 +27,6 @@ atom.themes.initialLoadComplete = true fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') atom.packages.packageDirPaths.unshift(fixturePackagesPath) -atom.keymaps.loadBundledKeymaps() window.addEventListener 'core:close', -> window.close() From ca0dda77b6ddf8b53ecf0c1db63d9001ef9a6488 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Oct 2015 15:45:10 -0600 Subject: [PATCH 126/316] =?UTF-8?q?Don=E2=80=99t=20bind=20window:close=20i?= =?UTF-8?q?n=20spec=20helper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/spec-helper.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index f7c474d5f..78dfcc4c3 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -28,8 +28,6 @@ atom.themes.initialLoadComplete = true fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') atom.packages.packageDirPaths.unshift(fixturePackagesPath) -window.addEventListener 'core:close', -> window.close() - document.querySelector('html').style.overflow = 'auto' document.body.style.overflow = 'auto' From 4808c9f9e8572e20d14cc588b7132866671ecc6e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 7 Oct 2015 16:32:47 -0500 Subject: [PATCH 127/316] Eliminate config and confirm global references in Pane --- spec/pane-container-element-spec.coffee | 10 ++++---- spec/pane-container-spec.coffee | 34 ++++++++++++------------- spec/pane-element-spec.coffee | 2 +- spec/pane-spec.coffee | 10 ++++---- src/pane-container.coffee | 4 +-- src/workspace.coffee | 4 +-- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/spec/pane-container-element-spec.coffee b/spec/pane-container-element-spec.coffee index e17957333..98cfffd56 100644 --- a/spec/pane-container-element-spec.coffee +++ b/spec/pane-container-element-spec.coffee @@ -42,7 +42,7 @@ describe "PaneContainerElement", -> ] it "transfers focus to the next pane if a focused pane is removed", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerElement = atom.views.getView(container) leftPane = container.getActivePane() leftPaneElement = atom.views.getView(leftPane) @@ -58,7 +58,7 @@ describe "PaneContainerElement", -> describe "when a pane is split", -> it "builds appropriately-oriented atom-pane-axis elements", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerElement = atom.views.getView(container) pane1 = container.getActivePane() @@ -84,7 +84,7 @@ describe "PaneContainerElement", -> [container, containerElement] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerElement = atom.views.getView(container) document.querySelector('#jasmine-content').appendChild(containerElement) @@ -201,7 +201,7 @@ describe "PaneContainerElement", -> [leftPane, rightPane] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) leftPane = container.getActivePane() rightPane = leftPane.splitRight() @@ -252,7 +252,7 @@ describe "PaneContainerElement", -> element.tabIndex = -1 element - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getActivePane() pane1.activateItem(buildElement('1')) pane4 = pane1.splitDown(items: [buildElement('4')]) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index f577c3ba2..42dad2fa9 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -12,7 +12,7 @@ describe "PaneContainer", -> @deserialize: -> new this serialize: -> deserializer: 'Item' - containerA = new PaneContainer(config: atom.config) + containerA = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1A = containerA.getActivePane() pane1A.addItem(new Item) pane2A = pane1A.splitRight(items: [new Item]) @@ -22,7 +22,7 @@ describe "PaneContainer", -> it "preserves the focused pane across serialization", -> expect(pane3A.focused).toBe true - containerB = new PaneContainer(config: atom.config) + containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(pane3B.focused).toBe true @@ -31,7 +31,7 @@ describe "PaneContainer", -> pane3A.activate() expect(containerA.getActivePane()).toBe pane3A - containerB = new PaneContainer(config: atom.config) + containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(containerB.getActivePane()).toBe pane3B @@ -40,7 +40,7 @@ describe "PaneContainer", -> pane3A.activate() state = containerA.serialize() state.activePaneId = -22 - containerB = new PaneContainer(config: atom.config) + containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerB.deserialize(state, atom.deserializers) expect(containerB.getActivePane()).toBe containerB.getPanes()[0] @@ -51,7 +51,7 @@ describe "PaneContainer", -> describe "if the 'core.destroyEmptyPanes' config option is false (the default)", -> it "leaves the empty panes intact", -> state = containerA.serialize() - containerB = new PaneContainer(config: atom.config) + containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerB.deserialize(state, atom.deserializers) [leftPane, column] = containerB.getRoot().getChildren() [topPane, bottomPane] = column.getChildren() @@ -65,7 +65,7 @@ describe "PaneContainer", -> atom.config.set('core.destroyEmptyPanes', true) state = containerA.serialize() - containerB = new PaneContainer(config: atom.config) + containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) containerB.deserialize(state, atom.deserializers) [leftPane, rightPane] = containerB.getRoot().getChildren() @@ -73,7 +73,7 @@ describe "PaneContainer", -> expect(rightPane.getItems().length).toBe 1 it "does not allow the root pane to be destroyed", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) container.getRoot().destroy() expect(container.getRoot()).toBeDefined() expect(container.getRoot().isDestroyed()).toBe false @@ -82,7 +82,7 @@ describe "PaneContainer", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getRoot() it "returns the first pane if no pane has been made active", -> @@ -111,7 +111,7 @@ describe "PaneContainer", -> [container, pane1, pane2, observed] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object, new Object]) [pane1, pane2] = container.getPanes() @@ -131,7 +131,7 @@ describe "PaneContainer", -> describe "::observePanes()", -> it "invokes observers with all current and future panes", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() @@ -145,7 +145,7 @@ describe "PaneContainer", -> describe "::observePaneItems()", -> it "invokes observers with all current and future pane items", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object]) [pane1, pane2] = container.getPanes() @@ -165,7 +165,7 @@ describe "PaneContainer", -> shouldPromptToSave: -> true getURI: -> 'test' - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() pane1.addItem(new TestItem) @@ -185,7 +185,7 @@ describe "PaneContainer", -> describe "::onDidAddPane(callback)", -> it "invokes the given callback when panes are added", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) events = [] container.onDidAddPane (event) -> events.push(event) @@ -202,7 +202,7 @@ describe "PaneContainer", -> destroy: -> @_isDestroyed = true isDestroyed: -> @_isDestroyed - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) events = [] container.onWillDestroyPane (event) -> itemsDestroyed = (item.isDestroyed() for item in event.pane.getItems()) @@ -218,7 +218,7 @@ describe "PaneContainer", -> describe "::onDidDestroyPane(callback)", -> it "invokes the given callback when panes are destroyed", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) events = [] container.onDidDestroyPane (event) -> events.push(event) @@ -233,7 +233,7 @@ describe "PaneContainer", -> describe "::onWillDestroyPaneItem() and ::onDidDestroyPaneItem", -> it "invokes the given callbacks when an item will be destroyed on any pane", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getRoot() item1 = new Object item2 = new Object @@ -260,7 +260,7 @@ describe "PaneContainer", -> describe "::saveAll()", -> it "saves all open pane items", -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getRoot() pane2 = pane1.splitRight() diff --git a/spec/pane-element-spec.coffee b/spec/pane-element-spec.coffee index bf3747199..3fcdc4ffb 100644 --- a/spec/pane-element-spec.coffee +++ b/spec/pane-element-spec.coffee @@ -6,7 +6,7 @@ describe "PaneElement", -> beforeEach -> spyOn(atom, "open") - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane = container.getActivePane() paneElement = atom.views.getView(pane) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 0e563cb09..4186e33a1 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -38,7 +38,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) container.getActivePane().splitRight() [pane1, pane2] = container.getPanes() @@ -107,7 +107,7 @@ describe "Pane", -> it "throws an exception if the item is already present on a pane", -> item = new Item("A") - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getActivePane() pane1.addItem(item) pane2 = pane1.splitRight() @@ -502,7 +502,7 @@ describe "Pane", -> [item1, item2, item3, item4, item5] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getActivePane() pane1.addItems([new Item("A"), new Item("B"), new Item("C")]) pane2 = pane1.splitRight(items: [new Item("D"), new Item("E")]) @@ -555,7 +555,7 @@ describe "Pane", -> [pane1, container] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.getActivePane() pane1.addItem(new Item("A")) @@ -688,7 +688,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config) + container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) pane1 = container.root pane1.addItems([new Item("A"), new Item("B")]) pane2 = pane1.splitRight() diff --git a/src/pane-container.coffee b/src/pane-container.coffee index a061f122c..a91cee608 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -13,12 +13,12 @@ class PaneContainer extends Model constructor: (params) -> super - @config = params.config + {@config, @confirm} = params @emitter = new Emitter @subscriptions = new CompositeDisposable @itemRegistry = new ItemRegistry - @setRoot(new Pane(container: this)) + @setRoot(new Pane({container: this, @config, @confirm})) @setActivePane(@getRoot()) @monitorActivePaneItem() @monitorPaneItems() diff --git a/src/workspace.coffee b/src/workspace.coffee index 99c794421..ff7f14738 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -36,7 +36,7 @@ class Workspace extends Model @openers = [] @destroyedItemURIs = [] - @paneContainer = new PaneContainer(config: @config) + @paneContainer = new PaneContainer({@config, @confirm}) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @directorySearchers = [] @@ -414,7 +414,7 @@ class Workspace extends Model Promise.resolve(item) .then (item) => if not pane - pane = new Pane(items: [item]) + pane = new Pane({items: [item], @config, @confirm}) @paneContainer.root = pane @itemOpened(item) pane.activateItem(item) From 1d280e8d928ea27f0c0b904a67c8332760d44cd7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 8 Oct 2015 10:46:54 +0200 Subject: [PATCH 128/316] Introduce timeout option The idea with this commit is to implement a timeout functionality that does not rely on a system utility (such as unix `timeout`). Tests could hang because of a CPU-bound task and, as a result, we need to handle timeouts in a separate process. An ideal implementation would first spawn the timeout, which in turn would spawn the tests, acting as a supervisor and making sure they do not exceed the supplied time. However, setting up such an environment would have been trickier, thus the test process spawns the timeout cop before running any test. This, in turn, invokes a `setTimeout` function and kills the parent process as soon as the timeout gets triggered, logging to console the reason why the parent process was killed (and exiting the parent process with code 130). I haven't used `Task` because, in order to log stuff to the console, we need to fork the ChildProcess from `remote`, as otherwise nothing gets written out. --- src/browser/atom-application.coffee | 10 +++++----- src/browser/atom-window.coffee | 2 +- src/browser/main.coffee | 4 +++- src/initialize-test-window.coffee | 9 +++++++-- src/timeout-cop.js | 12 ++++++++++++ 5 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 src/timeout-cop.js diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index c5242c5aa..c7ac7c27a 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -65,7 +65,7 @@ class AtomApplication exit: (status) -> app.exit(status) constructor: (options) -> - {@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath} = options + {@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, @timeout} = options global.atomApplication = this @@ -87,9 +87,9 @@ class AtomApplication else @loadState() or @openPath(options) - openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, profileStartup}) -> + openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, profileStartup, timeout}) -> if test - @runTests({headless: true, @resourcePath, executedFrom, specDirectory, pathsToOpen, logFile}) + @runTests({headless: true, @resourcePath, executedFrom, specDirectory, pathsToOpen, logFile, timeout}) else if pathsToOpen.length > 0 @openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup}) else if urlsToOpen.length > 0 @@ -493,7 +493,7 @@ class AtomApplication # :specPath - The directory to load specs from. # :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages # and ~/.atom/dev/packages, defaults to false. - runTests: ({headless, resourcePath, executedFrom, specDirectory, pathsToOpen, logFile, safeMode}) -> + runTests: ({headless, resourcePath, executedFrom, specDirectory, pathsToOpen, logFile, safeMode, timeout}) -> if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath @@ -517,7 +517,7 @@ class AtomApplication isSpec = true devMode = true safeMode ?= false - new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode}) + new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode, timeout}) resolveTestRunnerPath: (testPath) -> FindParentDir ?= require 'find-parent-dir' diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 39350392d..2415e916b 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -19,7 +19,7 @@ class AtomWindow isSpec: null constructor: (settings={}) -> - {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode} = settings + {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode, @timeout} = settings locationsToOpen ?= [{pathToOpen}] if pathToOpen locationsToOpen ?= [] diff --git a/src/browser/main.coffee b/src/browser/main.coffee index f0709037d..b86828392 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -102,6 +102,7 @@ parseCommandLine = -> options.alias('s', 'spec-directory').string('s').describe('s', 'Set the directory from which to run package specs (default: Atom\'s spec directory).') options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.') options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.') + options.string('timeout').describe('timeout', 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).') options.alias('v', 'version').boolean('v').describe('v', 'Print the version.') options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.') options.string('socket-path') @@ -121,6 +122,7 @@ parseCommandLine = -> safeMode = args['safe'] pathsToOpen = args._ test = args['test'] + timeout = args['timeout'] specDirectory = args['spec-directory'] newWindow = args['new-window'] pidToKillWhenClosed = args['pid'] if args['wait'] @@ -158,6 +160,6 @@ parseCommandLine = -> {resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, - logFile, socketPath, profileStartup} + logFile, socketPath, profileStartup, timeout} start() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 337c48744..d8354a416 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -5,6 +5,7 @@ try path = require 'path' ipc = require 'ipc' remote = require 'remote' + app = remote.require('app') {getWindowLoadSettings} = require './window-load-settings-helpers' AtomEnvironment = require '../src/atom-environment' @@ -32,6 +33,12 @@ try document.title = "Spec Suite" + timeoutCop = null + if timeout = getWindowLoadSettings().timeout + ChildProcess = remote.require("child_process") + timeoutCop = ChildProcess.fork(require.resolve('./timeout-cop'), [remote.process.pid, timeout]) + app.on "will-exit", -> timeoutCop.kill() + legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) testRunner = require(getWindowLoadSettings().testRunnerPath) testRunner({ @@ -41,11 +48,9 @@ try buildAtomEnvironment: -> new AtomEnvironment legacyTestRunner: legacyTestRunner }) - catch error if getWindowLoadSettings().headless console.error(error.stack ? error) - app = remote.require('app') app.emit('will-exit') remote.process.exit(status) else diff --git a/src/timeout-cop.js b/src/timeout-cop.js new file mode 100644 index 000000000..c684540f2 --- /dev/null +++ b/src/timeout-cop.js @@ -0,0 +1,12 @@ +var parentProcessId = process.argv[2]; +var timeoutInMinutes = process.argv[3]; +var timeoutInMilliseconds = timeoutInMinutes * 1000 * 60 + +function exitTestRunner() { + process.kill(parentProcessId, "SIGINT"); + var errorMessage = "The test suite has timed out because it has been running"; + errorMessage += " for more than " + timeoutInMinutes + " minutes."; + console.log(errorMessage); +} + +setTimeout(exitTestRunner, timeoutInMilliseconds); From 5da32540b141371698cd58bcb89202e8aebc210b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 8 Oct 2015 11:54:11 +0200 Subject: [PATCH 129/316] :art: --- src/browser/atom-application.coffee | 2 +- src/browser/atom-window.coffee | 2 +- src/initialize-test-window.coffee | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index c7ac7c27a..58981f0d1 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -65,7 +65,7 @@ class AtomApplication exit: (status) -> app.exit(status) constructor: (options) -> - {@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, @timeout} = options + {@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, timeout} = options global.atomApplication = this diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 2415e916b..7823388dd 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -19,7 +19,7 @@ class AtomWindow isSpec: null constructor: (settings={}) -> - {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode, @timeout} = settings + {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode, timeout} = settings locationsToOpen ?= [{pathToOpen}] if pathToOpen locationsToOpen ?= [] diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index d8354a416..89ef44e4f 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -33,7 +33,6 @@ try document.title = "Spec Suite" - timeoutCop = null if timeout = getWindowLoadSettings().timeout ChildProcess = remote.require("child_process") timeoutCop = ChildProcess.fork(require.resolve('./timeout-cop'), [remote.process.pid, timeout]) From 9ac4034135231870f51baf07d9d01f408853e8b5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 8 Oct 2015 14:04:23 +0200 Subject: [PATCH 130/316] :fire: Drop --spec-directory --- build/tasks/spec-task.coffee | 8 ++++---- spec/spec-helper.coffee | 12 +++--------- src/browser/atom-application.coffee | 11 +++++------ src/browser/main.coffee | 17 ++--------------- 4 files changed, 14 insertions(+), 34 deletions(-) diff --git a/build/tasks/spec-task.coffee b/build/tasks/spec-task.coffee index b0e695798..27465efdf 100644 --- a/build/tasks/spec-task.coffee +++ b/build/tasks/spec-task.coffee @@ -54,14 +54,14 @@ module.exports = (grunt) -> if process.platform in ['darwin', 'linux'] options = cmd: appPath - args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{path.join(packagePath, 'spec')}"] + args: ['--test', "--resource-path=#{resourcePath}", path.join(packagePath, 'spec')] opts: cwd: packagePath env: _.extend({}, process.env, ATOM_PATH: rootDir) else if process.platform is 'win32' options = cmd: process.env.comspec - args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{path.join(packagePath, 'spec')}", "--log-file=ci.log"] + args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--log-file=ci.log", path.join(packagePath, 'spec')] opts: cwd: packagePath env: _.extend({}, process.env, ATOM_PATH: rootDir) @@ -95,7 +95,7 @@ module.exports = (grunt) -> if process.platform in ['darwin', 'linux'] options = cmd: appPath - args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}"] + args: ['--test', "--resource-path=#{resourcePath}", coreSpecsPath] opts: env: _.extend({}, process.env, ATOM_INTEGRATION_TESTS_ENABLED: true @@ -104,7 +104,7 @@ module.exports = (grunt) -> else if process.platform is 'win32' options = cmd: process.env.comspec - args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}", '--log-file=ci.log'] + args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", '--log-file=ci.log', coreSpecsPath] opts: env: _.extend({}, process.env, ATOM_INTEGRATION_TESTS_ENABLED: true diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 78dfcc4c3..ea3efb95a 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -68,19 +68,13 @@ specPackagePath = null specProjectPath = null isCoreSpec = false -{specDirectory, resourcePath} = atom.getLoadSettings() +{resourcePath} = atom.getLoadSettings() -if specDirectory - specPackagePath = path.resolve(specDirectory, '..') - try - specPackageName = JSON.parse(fs.readFileSync(path.join(specPackagePath, 'package.json')))?.name - specProjectPath = path.join(specDirectory, 'fixtures') - -isCoreSpec = specDirectory is fs.realpathSync(__dirname) beforeEach -> documentTitle = null - projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures') + + projectPath = path.join(@specDirectory, 'fixtures') atom.packages.serviceHub = new ServiceHub atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, config: atom.config, confirm: atom.confirm}) atom.project.setPaths([projectPath]) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 58981f0d1..c4d472e83 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -87,9 +87,9 @@ class AtomApplication else @loadState() or @openPath(options) - openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, profileStartup, timeout}) -> + openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout}) -> if test - @runTests({headless: true, @resourcePath, executedFrom, specDirectory, pathsToOpen, logFile, timeout}) + @runTests({headless: true, @resourcePath, executedFrom, pathsToOpen, logFile, timeout}) else if pathsToOpen.length > 0 @openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup}) else if urlsToOpen.length > 0 @@ -251,8 +251,8 @@ class AtomApplication win = BrowserWindow.fromWebContents(event.sender) @applicationMenu.update(win, template, keystrokesByCommand) - ipc.on 'run-package-specs', (event, specDirectory) => - @runTests({resourcePath: @devResourcePath, specDirectory: specDirectory, headless: false}) + ipc.on 'run-package-specs', (event, packageSpecPath) => + @runTests({resourcePath: @devResourcePath, pathsToOpen: [packageSpecPath], headless: false}) ipc.on 'command', (event, command) => @emit(command) @@ -493,7 +493,7 @@ class AtomApplication # :specPath - The directory to load specs from. # :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages # and ~/.atom/dev/packages, defaults to false. - runTests: ({headless, resourcePath, executedFrom, specDirectory, pathsToOpen, logFile, safeMode, timeout}) -> + runTests: ({headless, resourcePath, executedFrom, pathsToOpen, logFile, safeMode, timeout}) -> if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath @@ -503,7 +503,6 @@ class AtomApplication windowInitializationScript = require.resolve(path.resolve(__dirname, '..', '..', 'src', 'initialize-test-window')) testPaths = [] - testPaths.push(specDirectory) if specDirectory? if pathsToOpen? for pathToOpen in pathsToOpen testPaths.push(path.resolve(executedFrom, fs.normalize(pathToOpen))) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index b86828392..4755a7ff1 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -99,7 +99,6 @@ parseCommandLine = -> options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.') options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.') options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.') - options.alias('s', 'spec-directory').string('s').describe('s', 'Set the directory from which to run package specs (default: Atom\'s spec directory).') options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.') options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.') options.string('timeout').describe('timeout', 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).') @@ -123,7 +122,6 @@ parseCommandLine = -> pathsToOpen = args._ test = args['test'] timeout = args['timeout'] - specDirectory = args['spec-directory'] newWindow = args['new-window'] pidToKillWhenClosed = args['pid'] if args['wait'] logFile = args['log-file'] @@ -135,18 +133,7 @@ parseCommandLine = -> if args['resource-path'] devMode = true resourcePath = args['resource-path'] - else - # Set resourcePath based on the specDirectory if running specs on atom core - if specDirectory? - packageDirectoryPath = path.join(specDirectory, '..') - packageManifestPath = path.join(packageDirectoryPath, 'package.json') - if fs.statSyncNoException(packageManifestPath) - try - packageManifest = JSON.parse(fs.readFileSync(packageManifestPath)) - resourcePath = packageDirectoryPath if packageManifest.name is 'atom' - - if devMode - resourcePath ?= devResourcePath + resourcePath ?= devResourcePath if devMode unless fs.statSyncNoException(resourcePath) resourcePath = path.dirname(path.dirname(__dirname)) @@ -159,7 +146,7 @@ parseCommandLine = -> devResourcePath = normalizeDriveLetterName(devResourcePath) {resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test, - version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, + version, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, socketPath, profileStartup, timeout} start() From 24365b95df18b79fd8f995007a5d2735fecae424 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 8 Oct 2015 14:07:28 +0200 Subject: [PATCH 131/316] :lipstick: Satisfy linter requirements --- src/timeout-cop.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/timeout-cop.js b/src/timeout-cop.js index c684540f2..228a011bb 100644 --- a/src/timeout-cop.js +++ b/src/timeout-cop.js @@ -1,12 +1,14 @@ -var parentProcessId = process.argv[2]; -var timeoutInMinutes = process.argv[3]; -var timeoutInMilliseconds = timeoutInMinutes * 1000 * 60 +'use strict' -function exitTestRunner() { - process.kill(parentProcessId, "SIGINT"); - var errorMessage = "The test suite has timed out because it has been running"; - errorMessage += " for more than " + timeoutInMinutes + " minutes."; - console.log(errorMessage); +let parentProcessId = process.argv[2] +let timeoutInMinutes = process.argv[3] +let timeoutInMilliseconds = timeoutInMinutes * 1000 * 60 + +function exitTestRunner () { + process.kill(parentProcessId, 'SIGINT') + let errorMessage = 'The test suite has timed out because it has been running' + errorMessage += ' for more than ' + timeoutInMinutes + ' minutes.' + console.log(errorMessage) } -setTimeout(exitTestRunner, timeoutInMilliseconds); +setTimeout(exitTestRunner, timeoutInMilliseconds) From fa41cf68a44914d519792c8421055e99673020f5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 8 Oct 2015 15:48:54 +0200 Subject: [PATCH 132/316] :bug: Fix ::registerDefaultOpeners --- src/atom-environment.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index e21ea9ff0..7778bb878 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -216,7 +216,7 @@ class AtomEnvironment extends Model @views.addViewProvider(Gutter, createGutterView) registerDefaultOpeners: -> - @workspace.addOpener (uri) -> + @workspace.addOpener (uri) => switch uri when 'atom://.atom/stylesheet' @workspace.open(@styles.getUserStyleSheetPath()) From 19b07dbd97587bff101a840b9d53a1a545306ee5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 11:42:05 -0700 Subject: [PATCH 133/316] Rename atom-spec -> atom-environment-spec --- spec/{atom-spec.coffee => atom-environment-spec.coffee} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename spec/{atom-spec.coffee => atom-environment-spec.coffee} (98%) diff --git a/spec/atom-spec.coffee b/spec/atom-environment-spec.coffee similarity index 98% rename from spec/atom-spec.coffee rename to spec/atom-environment-spec.coffee index 1d8942e9d..73b5a6e9d 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -5,7 +5,7 @@ ThemeManager = require '../src/theme-manager' _ = require "underscore-plus" temp = require "temp" -describe "the `atom` global", -> +describe "AtomEnvironment", -> describe 'window sizing methods', -> describe '::getPosition and ::setPosition', -> originalPosition = null @@ -130,7 +130,7 @@ describe "the `atom` global", -> expect(result).toBe false expect(errors.length).toBe 1 expect(errors[0].message).toBe "Assertion failed: a == b" - expect(errors[0].stack).toContain('atom-spec') + expect(errors[0].stack).toContain('atom-environment-spec') describe "if passed a callback function", -> it "calls the callback with the assertion failure's error object", -> From 9664d3475015f5dba32eaa5c229b09d767b69123 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 11:45:04 -0700 Subject: [PATCH 134/316] Reset MenuManager in AtomEnvironment::reset --- spec/spec-helper.coffee | 1 - src/atom-environment.coffee | 2 ++ src/menu-manager.coffee | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index ea3efb95a..66036e3e7 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -146,7 +146,6 @@ beforeEach -> afterEach -> atom.packages.deactivatePackages() - atom.menu.template = [] atom.contextMenu.clear() atom.notifications.clear() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 7778bb878..0190e2b1e 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -245,6 +245,8 @@ class AtomEnvironment extends Model @styles.restoreSnapshot(@initialStyleElements) + @menu.clear() + ### Section: Event Subscription ### diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index c8096441a..fa78d3cd6 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -96,6 +96,10 @@ class MenuManager @unmerge(@template, item) for item in items @update() + clear: -> + @template = [] + @update() + # Should the binding for the given selector be included in the menu # commands. # From d0283d8f05fb690d28ceb82d619806bd3462639a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 11:46:39 -0700 Subject: [PATCH 135/316] Reset Clipboard in AtomEnvironment::reset --- src/atom-environment.coffee | 2 ++ src/clipboard.coffee | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 0190e2b1e..68b7e38df 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -247,6 +247,8 @@ class AtomEnvironment extends Model @menu.clear() + @clipboard.reset() + ### Section: Event Subscription ### diff --git a/src/clipboard.coffee b/src/clipboard.coffee index 84ff9ab3b..9511bdda9 100644 --- a/src/clipboard.coffee +++ b/src/clipboard.coffee @@ -14,8 +14,12 @@ clipboard = require './safe-clipboard' # ``` module.exports = class Clipboard - metadata: null - signatureForMetadata: null + constructor: -> + @reset() + + reset: -> + @metadata = null + @signatureForMetadata = null # Creates an `md5` hash of some text. # From 9a4cbb9e1644b6d9d01280d3296e497140c83b46 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 12:40:23 -0700 Subject: [PATCH 136/316] Wait for async service consumption in project spec --- spec/project-spec.coffee | 60 +++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 7e7925904..948acaab1 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -331,31 +331,35 @@ describe "Project", -> null }) - localPath = temp.mkdirSync('local-path') - remotePath = "ssh://foreign-directory:8080/exists" + waitsFor -> + atom.project.directoryProviders.length > 0 - atom.project.setPaths([localPath, remotePath]) + runs -> + localPath = temp.mkdirSync('local-path') + remotePath = "ssh://foreign-directory:8080/exists" - directories = atom.project.getDirectories() - expect(directories[0].getPath()).toBe localPath - expect(directories[0] instanceof Directory).toBe true - expect(directories[1].getPath()).toBe remotePath - expect(directories[1] instanceof DummyDirectory).toBe true + atom.project.setPaths([localPath, remotePath]) - # Make sure that DummyDirectory.contains() is honored. - remotePathSubdirectory = remotePath + "a/subdirectory" - atom.project.addPath(remotePathSubdirectory) - expect(atom.project.getDirectories().length).toBe 2 + directories = atom.project.getDirectories() + expect(directories[0].getPath()).toBe localPath + expect(directories[0] instanceof Directory).toBe true + expect(directories[1].getPath()).toBe remotePath + expect(directories[1] instanceof DummyDirectory).toBe true - # Make sure that a new DummyDirectory that is not contained by the first - # DummyDirectory can be added. - otherRemotePath = "ssh://other-foreign-directory:8080/" - atom.project.addPath(otherRemotePath) - newDirectories = atom.project.getDirectories() - expect(newDirectories.length).toBe 3 - otherDummyDirectory = newDirectories[2] - expect(otherDummyDirectory.getPath()).toBe otherRemotePath - expect(otherDummyDirectory instanceof DummyDirectory).toBe true + # Make sure that DummyDirectory.contains() is honored. + remotePathSubdirectory = remotePath + "a/subdirectory" + atom.project.addPath(remotePathSubdirectory) + expect(atom.project.getDirectories().length).toBe 2 + + # Make sure that a new DummyDirectory that is not contained by the first + # DummyDirectory can be added. + otherRemotePath = "ssh://other-foreign-directory:8080/" + atom.project.addPath(otherRemotePath) + newDirectories = atom.project.getDirectories() + expect(newDirectories.length).toBe 3 + otherDummyDirectory = newDirectories[2] + expect(otherDummyDirectory.getPath()).toBe otherRemotePath + expect(otherDummyDirectory instanceof DummyDirectory).toBe true describe "when a custom provider does not handle the path", -> it "creates a local directory for the path", -> @@ -366,11 +370,15 @@ describe "Project", -> atom.packages.serviceHub.provide( "atom.directory-provider", "0.1.0", directoryProvider) - tmp = temp.mkdirSync() - atom.project.setPaths([tmp]) - directories = atom.project.getDirectories() - expect(directories.length).toBe 1 - expect(directories[0].getPath()).toBe tmp + waitsFor -> + atom.project.directoryProviders.length > 0 + + runs -> + tmp = temp.mkdirSync() + atom.project.setPaths([tmp]) + directories = atom.project.getDirectories() + expect(directories.length).toBe 1 + expect(directories[0].getPath()).toBe tmp describe ".addPath(path)", -> it "calls callbacks registered with ::onDidChangePaths", -> From fb2a1284f6d77953b77c5e4060a5f034d5e018d7 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 12:41:07 -0700 Subject: [PATCH 137/316] Clear notifications and context menus in AtomEnvironment::reset --- spec/spec-helper.coffee | 3 --- src/atom-environment.coffee | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 66036e3e7..4a40c22d9 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -70,7 +70,6 @@ isCoreSpec = false {resourcePath} = atom.getLoadSettings() - beforeEach -> documentTitle = null @@ -146,8 +145,6 @@ beforeEach -> afterEach -> atom.packages.deactivatePackages() - atom.contextMenu.clear() - atom.notifications.clear() atom.workspace?.destroy() atom.workspace = null diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 68b7e38df..78c44a962 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -249,6 +249,10 @@ class AtomEnvironment extends Model @clipboard.reset() + @notifications.clear() + + @contextMenu.clear() + ### Section: Event Subscription ### From c268b4e050a6100cbc8a05304c056108b2ef18dc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 13:11:58 -0700 Subject: [PATCH 138/316] Remove unused stylesheet cleanup in spec-helper --- spec/spec-helper.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 4a40c22d9..91252f73f 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -154,8 +154,6 @@ afterEach -> atom.project?.destroy() atom.project = null - atom.themes.removeStylesheet('global-editor-styles') - delete atom.state.packageStates atom.reset() From 2af6f995b41f43f9f9b5703b810b1f3275269922 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 13:49:37 -0700 Subject: [PATCH 139/316] Clean up repository-providers when their providing packages are are deactivated --- spec/project-spec.coffee | 15 ++++++++++++++- src/project.coffee | 7 +++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 948acaab1..74836719d 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -16,7 +16,7 @@ describe "Project", -> # Wait for project's service consumers to be asynchronously added waits(1) - describe "when a new repository-provider is added", -> + describe "when a repository-provider service is provided", -> it "uses it to create repositories for any directories that need one", -> projectPath = temp.mkdirSync('atom-project') atom.project.setPaths([projectPath]) @@ -54,6 +54,19 @@ describe "Project", -> expect(atom.project.getRepositories()).toBe repositories + it "stops using it to create repositories when the service is removed", -> + atom.project.setPaths([]) + + disposable = atom.packages.serviceHub.provide("atom.repository-provider", "0.1.0", { + repositoryForDirectory: (directory) -> Promise.resolve(dummyRepository) + repositoryForDirectorySync: (directory) -> {destroy: -> null} + }) + + disposable.dispose() + + atom.project.addPath(temp.mkdirSync('atom-project')) + expect(atom.project.getRepositories()).toEqual [null] + describe "serialization", -> deserializedProject = null diff --git a/src/project.coffee b/src/project.coffee index 4f135a0ef..36a0b9229 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -3,7 +3,7 @@ url = require 'url' _ = require 'underscore-plus' fs = require 'fs-plus' -{Emitter} = require 'event-kit' +{Emitter, Disposable} = require 'event-kit' TextBuffer = require 'text-buffer' DefaultDirectoryProvider = require './default-directory-provider' @@ -53,7 +53,10 @@ class Project extends Model # @repositoryProviders has been updated. if null in @repositories @setPaths(@getPaths()) - ) + + new Disposable => + @repositoryProviders.splice(@repositoryProviders.indexOf(provider), 1) + ) destroyed: -> buffer.destroy() for buffer in @getBuffers() From b754f1e1255ef02da99e7ec6553d18c01b1df886 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 15:11:43 -0700 Subject: [PATCH 140/316] Clean up project specs for custom directory and repository providers --- spec/project-spec.coffee | 214 +++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 121 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 74836719d..1137d5545 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -16,57 +16,6 @@ describe "Project", -> # Wait for project's service consumers to be asynchronously added waits(1) - describe "when a repository-provider service is provided", -> - it "uses it to create repositories for any directories that need one", -> - projectPath = temp.mkdirSync('atom-project') - atom.project.setPaths([projectPath]) - expect(atom.project.getRepositories()).toEqual [null] - expect(atom.project.repositoryProviders.length).toEqual 1 - - dummyRepository = {destroy: -> null} - - atom.packages.serviceHub.provide("atom.repository-provider", "0.1.0", { - repositoryForDirectory: (directory) -> Promise.resolve(dummyRepository) - repositoryForDirectorySync: (directory) -> dummyRepository - }) - - repository = null - - waitsFor "repository to be updated", -> - repository = atom.project.getRepositories()[0] - - runs -> - expect(repository).toBe dummyRepository - - it "does not create any new repositories if every directory has a repository", -> - repositories = atom.project.getRepositories() - expect(repositories.length).toEqual 1 - [repository] = repositories - expect(repository).toBeTruthy() - - # Register a new RepositoryProvider. - dummyRepository = destroy: -> - repositoryProvider = - repositoryForDirectory: (directory) -> Promise.resolve(dummyRepository) - repositoryForDirectorySync: (directory) -> dummyRepository - atom.packages.serviceHub.provide( - "atom.repository-provider", "0.1.0", repositoryProvider) - - expect(atom.project.getRepositories()).toBe repositories - - it "stops using it to create repositories when the service is removed", -> - atom.project.setPaths([]) - - disposable = atom.packages.serviceHub.provide("atom.repository-provider", "0.1.0", { - repositoryForDirectory: (directory) -> Promise.resolve(dummyRepository) - repositoryForDirectorySync: (directory) -> {destroy: -> null} - }) - - disposable.dispose() - - atom.project.addPath(temp.mkdirSync('atom-project')) - expect(atom.project.getRepositories()).toEqual [null] - describe "serialization", -> deserializedProject = null @@ -162,6 +111,99 @@ describe "Project", -> expect(notification.getMessage()).toContain '`resurrect`' expect(notification.getMessage()).toContain 'fixtures/dir/a' + describe "when a custom repository-provider service is provided", -> + [fakeRepositoryProvider, fakeRepository] = [] + + beforeEach -> + fakeRepository = {destroy: -> null} + fakeRepositoryProvider = { + repositoryForDirectory: (directory) -> Promise.resolve(fakeRepository) + repositoryForDirectorySync: (directory) -> fakeRepository + } + + it "uses it to create repositories for any directories that need one", -> + projectPath = temp.mkdirSync('atom-project') + atom.project.setPaths([projectPath]) + expect(atom.project.getRepositories()).toEqual [null] + + atom.packages.serviceHub.provide("atom.repository-provider", "0.1.0", fakeRepositoryProvider) + waitsFor -> atom.project.repositoryProviders.length > 1 + runs -> atom.project.getRepositories()[0] is fakeRepository + + it "does not create any new repositories if every directory has a repository", -> + repositories = atom.project.getRepositories() + expect(repositories.length).toEqual 1 + expect(repositories[0]).toBeTruthy() + + atom.packages.serviceHub.provide("atom.repository-provider", "0.1.0", fakeRepositoryProvider) + waitsFor -> atom.project.repositoryProviders.length > 1 + runs -> expect(atom.project.getRepositories()).toBe repositories + + it "stops using it to create repositories when the service is removed", -> + atom.project.setPaths([]) + + disposable = atom.packages.serviceHub.provide("atom.repository-provider", "0.1.0", fakeRepositoryProvider) + waitsFor -> atom.project.repositoryProviders.length > 1 + runs -> + disposable.dispose() + atom.project.addPath(temp.mkdirSync('atom-project')) + expect(atom.project.getRepositories()).toEqual [null] + + describe "when a custom directory-provider service is provided", -> + class DummyDirectory + constructor: (@path) -> + getPath: -> @path + getFile: -> {existsSync: -> false} + getSubdirectory: -> {existsSync: -> false} + isRoot: -> true + existsSync: -> @path.endsWith('does-exist') + contains: (filePath) -> filePath.startsWith(@path) + + beforeEach -> + atom.packages.serviceHub.provide("atom.directory-provider", "0.1.0", { + directoryForURISync: (uri) -> + if uri.startsWith("ssh://") + new DummyDirectory(uri) + else + null + }) + + waitsFor -> + atom.project.directoryProviders.length > 0 + + it "uses the provider's custom directories for any paths that it handles", -> + localPath = temp.mkdirSync('local-path') + remotePath = "ssh://foreign-directory:8080/does-exist" + + atom.project.setPaths([localPath, remotePath]) + + directories = atom.project.getDirectories() + expect(directories[0].getPath()).toBe localPath + expect(directories[0] instanceof Directory).toBe true + expect(directories[1].getPath()).toBe remotePath + expect(directories[1] instanceof DummyDirectory).toBe true + + # It does not add new remote paths if their directories do not exist + # and they are contained by existing remote paths. + childRemotePath = remotePath + "/subdirectory/that/does-not-exist" + atom.project.addPath(childRemotePath) + expect(atom.project.getDirectories().length).toBe 2 + + # It does add new remote paths if their directories exist. + childRemotePath = remotePath + "/subdirectory/that/does-exist" + atom.project.addPath(childRemotePath) + directories = atom.project.getDirectories() + expect(directories[2].getPath()).toBe childRemotePath + expect(directories[2] instanceof DummyDirectory).toBe true + + # It does add new remote paths to be added if they are not contained by + # previous remote paths. + otherRemotePath = "ssh://other-foreign-directory:8080/" + atom.project.addPath(otherRemotePath) + directories = atom.project.getDirectories() + expect(directories[3].getPath()).toBe otherRemotePath + expect(directories[3] instanceof DummyDirectory).toBe true + describe ".open(path)", -> [absolutePath, newBufferHandler] = [] @@ -323,76 +365,6 @@ describe "Project", -> expect(directories.length).toBe 1 expect(directories[0].getPath()).toBe path.normalize(nonLocalFsDirectory) - describe "when a custom directory provider has been added", -> - describe "when custom provider handles the given path", -> - it "creates a directory using that provider", -> - class DummyDirectory - constructor: (@path) -> - getPath: -> @path - getFile: -> {existsSync: -> false} - getSubdirectory: -> {existsSync: -> false} - isRoot: -> true - existsSync: -> /does-exist/.test(@path) - off: -> - contains: (filePath) -> filePath.startsWith(@path) - - atom.packages.serviceHub.provide("atom.directory-provider", "0.1.0", { - directoryForURISync: (uri) -> - if uri.startsWith("ssh://") - new DummyDirectory(uri) - else - null - }) - - waitsFor -> - atom.project.directoryProviders.length > 0 - - runs -> - localPath = temp.mkdirSync('local-path') - remotePath = "ssh://foreign-directory:8080/exists" - - atom.project.setPaths([localPath, remotePath]) - - directories = atom.project.getDirectories() - expect(directories[0].getPath()).toBe localPath - expect(directories[0] instanceof Directory).toBe true - expect(directories[1].getPath()).toBe remotePath - expect(directories[1] instanceof DummyDirectory).toBe true - - # Make sure that DummyDirectory.contains() is honored. - remotePathSubdirectory = remotePath + "a/subdirectory" - atom.project.addPath(remotePathSubdirectory) - expect(atom.project.getDirectories().length).toBe 2 - - # Make sure that a new DummyDirectory that is not contained by the first - # DummyDirectory can be added. - otherRemotePath = "ssh://other-foreign-directory:8080/" - atom.project.addPath(otherRemotePath) - newDirectories = atom.project.getDirectories() - expect(newDirectories.length).toBe 3 - otherDummyDirectory = newDirectories[2] - expect(otherDummyDirectory.getPath()).toBe otherRemotePath - expect(otherDummyDirectory instanceof DummyDirectory).toBe true - - describe "when a custom provider does not handle the path", -> - it "creates a local directory for the path", -> - directoryProvider = - directoryForURISync: (uri) -> null - directoryForURI: (uri) -> throw new Error("This should not be called.") - - atom.packages.serviceHub.provide( - "atom.directory-provider", "0.1.0", directoryProvider) - - waitsFor -> - atom.project.directoryProviders.length > 0 - - runs -> - tmp = temp.mkdirSync() - atom.project.setPaths([tmp]) - directories = atom.project.getDirectories() - expect(directories.length).toBe 1 - expect(directories[0].getPath()).toBe tmp - describe ".addPath(path)", -> it "calls callbacks registered with ::onDidChangePaths", -> onDidChangePathsSpy = jasmine.createSpy('onDidChangePaths spy') From a9c8640ab18be253001e4d7580924c465903bbcb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 15:20:13 -0700 Subject: [PATCH 141/316] Stop using directory providers when their providing packages are deactivated --- spec/project-spec.coffee | 9 ++++++++- src/project.coffee | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 1137d5545..2c88aad50 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -159,8 +159,10 @@ describe "Project", -> existsSync: -> @path.endsWith('does-exist') contains: (filePath) -> filePath.startsWith(@path) + serviceDisposable = null + beforeEach -> - atom.packages.serviceHub.provide("atom.directory-provider", "0.1.0", { + serviceDisposable = atom.packages.serviceHub.provide("atom.directory-provider", "0.1.0", { directoryForURISync: (uri) -> if uri.startsWith("ssh://") new DummyDirectory(uri) @@ -204,6 +206,11 @@ describe "Project", -> expect(directories[3].getPath()).toBe otherRemotePath expect(directories[3] instanceof DummyDirectory).toBe true + it "stops using the provider when the service is removed", -> + serviceDisposable.dispose() + atom.project.setPaths(["ssh://foreign-directory:8080/does-exist"]) + expect(atom.project.getDirectories()[0] instanceof Directory).toBe true + describe ".open(path)", -> [absolutePath, newBufferHandler] = [] diff --git a/src/project.coffee b/src/project.coffee index 36a0b9229..c33510ec4 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -33,7 +33,11 @@ class Project extends Model packageManager.serviceHub.consume( 'atom.directory-provider', '^0.1.0', - (provider) => @directoryProviders.unshift(provider)) + (provider) => + @directoryProviders.unshift(provider) + new Disposable => + @directoryProviders.splice(@directoryProviders.indexOf(provider), 1) + ) # Mapping from the real path of a {Directory} to a {Promise} that resolves # to either a {Repository} or null. Ideally, the {Directory} would be used From 4835fef7bef14f05879552dc025bd539441141dc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 16:29:54 -0700 Subject: [PATCH 142/316] Reset service-hub in AtomEnvironment::reset() --- package.json | 2 +- spec/spec-helper.coffee | 1 - src/atom-environment.coffee | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 25f7fb0e1..394f05bda 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "scrollbar-style": "^3.2", "season": "^5.3", "semver": "^4.3.3", - "service-hub": "^0.6.2", + "service-hub": "^0.7.0", "source-map-support": "^0.3.2", "stacktrace-parser": "0.1.1", "temp": "0.8.1", diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 91252f73f..73790a231 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -74,7 +74,6 @@ beforeEach -> documentTitle = null projectPath = path.join(@specDirectory, 'fixtures') - atom.packages.serviceHub = new ServiceHub atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, config: atom.config, confirm: atom.confirm}) atom.project.setPaths([projectPath]) atom.workspace = new Workspace({ diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 78c44a962..9154b1f1e 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -253,6 +253,8 @@ class AtomEnvironment extends Model @contextMenu.clear() + @packages.serviceHub.clear() + ### Section: Event Subscription ### From 04c85e3aaef3089bd610cdaca83530cadec61e0b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 17:21:55 -0700 Subject: [PATCH 143/316] Avoid using atom global in registerDefaultCommands --- src/register-default-commands.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index 93b8d4fa8..ac286b45f 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -115,7 +115,7 @@ module.exports = (atom) -> 'editor:select-line': -> @selectLinesContainingCursors() ) - atom.commands.add 'atom-text-editor', stopEventPropagationAndGroupUndo( + atom.commands.add 'atom-text-editor', stopEventPropagationAndGroupUndo(atom.config, 'core:backspace': -> @backspace() 'core:delete': -> @delete() 'core:cut': -> @cutSelectedText() @@ -175,7 +175,7 @@ module.exports = (atom) -> 'editor:scroll-to-cursor': -> @scrollToCursorPosition() ) - atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo( + atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo(atom.config, 'editor:indent': -> @indent() 'editor:auto-indent': -> @autoIndentSelectedRows() 'editor:indent-selected-rows': -> @indentSelectedRows() @@ -200,13 +200,13 @@ stopEventPropagation = (commandListeners) -> commandListener.call(@getModel(), event) newCommandListeners -stopEventPropagationAndGroupUndo = (commandListeners) -> +stopEventPropagationAndGroupUndo = (config, commandListeners) -> newCommandListeners = {} for commandName, commandListener of commandListeners do (commandListener) -> newCommandListeners[commandName] = (event) -> event.stopPropagation() model = @getModel() - model.transact atom.config.get('editor.undoGroupingInterval'), -> + model.transact config.get('editor.undoGroupingInterval'), -> commandListener.call(model, event) newCommandListeners From 5c545c0898dc138dd123900e378d84d728b47466 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 17:34:41 -0700 Subject: [PATCH 144/316] Don't register CommandRegistry's window listeners in AtomEnvironment constructor --- spec/command-registry-spec.coffee | 16 ++++++++++++++++ spec/jasmine-test-runner.coffee | 2 ++ src/atom-environment.coffee | 2 ++ src/command-registry.coffee | 13 +++++++++---- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/spec/command-registry-spec.coffee b/spec/command-registry-spec.coffee index f8194aae6..ecdd42fd6 100644 --- a/spec/command-registry-spec.coffee +++ b/spec/command-registry-spec.coffee @@ -16,6 +16,7 @@ describe "CommandRegistry", -> document.querySelector('#jasmine-content').appendChild(parent) registry = new CommandRegistry + registry.attach(parent) afterEach -> registry.destroy() @@ -277,3 +278,18 @@ describe "CommandRegistry", -> {name: 'namespace:command-2', displayName: 'Namespace: Command 2'} {name: 'namespace:command-1', displayName: 'Namespace: Command 1'} ] + + describe "::attach(rootNode)", -> + it "adds event listeners for any previously-added commands", -> + registry2 = new CommandRegistry + + commandSpy = jasmine.createSpy('command-callback') + registry2.add '.grandchild', 'command-1', commandSpy + + grandchild.dispatchEvent(new CustomEvent('command-1', bubbles: true)) + expect(commandSpy).not.toHaveBeenCalled() + + registry2.attach(parent) + + grandchild.dispatchEvent(new CustomEvent('command-1', bubbles: true)) + expect(commandSpy).toHaveBeenCalled() diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 7aa264b29..b75e90d12 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -32,6 +32,8 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> document.head.appendChild(stylesElement) document.body.appendChild(jasmineContent) + atom.commands.attach(window) + jasmineEnv.execute() disableFocusMethods = -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 9154b1f1e..29d9fcb57 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -589,6 +589,8 @@ class AtomEnvironment extends Model @setAutoHideMenuBar(newValue) @setAutoHideMenuBar(true) if @config.get('core.autoHideMenuBar') + @commands.attach(window) + @openInitialEmptyEditorIfNecessary() unloadEditorWindow: -> diff --git a/src/command-registry.coffee b/src/command-registry.coffee index 4808c7895..db2cf498d 100644 --- a/src/command-registry.coffee +++ b/src/command-registry.coffee @@ -44,7 +44,8 @@ SequenceCount = 0 # ``` module.exports = class CommandRegistry - constructor: (@rootNode) -> + constructor: -> + @rootNode = null @clear() clear: -> @@ -53,9 +54,13 @@ class CommandRegistry @inlineListenersByCommandName = {} @emitter = new Emitter + attach: (@rootNode) -> + @commandRegistered(command) for command of @selectorBasedListenersByCommandName + @commandRegistered(command) for command of @inlineListenersByCommandName + destroy: -> for commandName of @registeredCommands - window.removeEventListener(commandName, @handleCommandEvent, true) + @rootNode.removeEventListener(commandName, @handleCommandEvent, true) return # Public: Add one or more command listeners associated with a selector. @@ -256,8 +261,8 @@ class CommandRegistry matched commandRegistered: (commandName) -> - unless @registeredCommands[commandName] - window.addEventListener(commandName, @handleCommandEvent, true) + if @rootNode? and not @registeredCommands[commandName] + @rootNode.addEventListener(commandName, @handleCommandEvent, true) @registeredCommands[commandName] = true class SelectorBasedListener From 7617c35856f29d81fc3e5096223fa8a0beb59fc2 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 17:51:27 -0700 Subject: [PATCH 145/316] Rename AtomEnvironment::removeEditorWindow -> ::destroy --- spec/atom-environment-spec.coffee | 39 +++++++++++++++++-------------- src/atom-environment.coffee | 23 +++++++++--------- src/window-event-handler.coffee | 2 +- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 73b5a6e9d..a1847519b 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -1,9 +1,9 @@ -Exec = require('child_process').exec +_ = require "underscore-plus" path = require 'path' +temp = require 'temp' Package = require '../src/package' ThemeManager = require '../src/theme-manager' -_ = require "underscore-plus" -temp = require "temp" +AtomEnvironment = require '../src/atom-environment' describe "AtomEnvironment", -> describe 'window sizing methods', -> @@ -217,28 +217,33 @@ describe "AtomEnvironment", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> - workspaceState = atom.workspace.serialize() - grammarsState = {grammarOverridesByPath: atom.grammars.grammarOverridesByPath} - projectState = atom.project.serialize() + atomEnvironment = new AtomEnvironment + spyOn(atomEnvironment, 'saveStateSync') - atom.unloadEditorWindow() + workspaceState = atomEnvironment.workspace.serialize() + grammarsState = {grammarOverridesByPath: atomEnvironment.grammars.grammarOverridesByPath} + projectState = atomEnvironment.project.serialize() - expect(atom.state.workspace).toEqual workspaceState - expect(atom.state.grammars).toEqual grammarsState - expect(atom.state.project).toEqual projectState - expect(atom.saveStateSync).toHaveBeenCalled() + atomEnvironment.unloadEditorWindow() - describe "::removeEditorWindow()", -> + expect(atomEnvironment.state.workspace).toEqual workspaceState + expect(atomEnvironment.state.grammars).toEqual grammarsState + expect(atomEnvironment.state.project).toEqual projectState + expect(atomEnvironment.saveStateSync).toHaveBeenCalled() + + describe "::destroy()", -> it "unsubscribes from all buffers", -> + atomEnvironment = new AtomEnvironment + waitsForPromise -> - atom.workspace.open("sample.js") + atomEnvironment.workspace.open("sample.js") runs -> - buffer = atom.workspace.getActivePaneItem().buffer - pane = atom.workspace.getActivePane() + buffer = atomEnvironment.workspace.getActivePaneItem().buffer + pane = atomEnvironment.workspace.getActivePane() pane.splitRight(copyActiveItem: true) - expect(atom.workspace.getTextEditors().length).toBe 2 + expect(atomEnvironment.workspace.getTextEditors().length).toBe 2 - atom.removeEditorWindow() + atomEnvironment.destroy() expect(buffer.getSubscriptionCount()).toBe 0 diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 29d9fcb57..b4af72fc7 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -255,6 +255,17 @@ class AtomEnvironment extends Model @packages.serviceHub.clear() + destroy: -> + return if not @project + + @workspace?.destroy() + @workspace = null + @themes.workspace = null + @project?.destroy() + @project = null + + @windowEventHandler?.unsubscribe() + ### Section: Event Subscription ### @@ -604,18 +615,6 @@ class AtomEnvironment extends Model @state.packageStates = @packages.packageStates @state.fullScreen = @isFullScreen() @saveStateSync() - @windowState = null - - removeEditorWindow: -> - return if not @project - - @workspace?.destroy() - @workspace = null - @themes.workspace = null - @project?.destroy() - @project = null - - @windowEventHandler?.unsubscribe() openInitialEmptyEditorIfNecessary: -> return unless @config.get('core.openEmptyEditorOnStart') diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index ceb9c126e..16d5cfd0c 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -187,7 +187,7 @@ class WindowEventHandler confirmed handleWindowUnload: => - @atomEnv.removeEditorWindow() + @atomEnv.destroy() handleWindowToggleFullScreen: => @atomEnv.toggleFullScreen() From 43d0241685d690a250a3c0dd4e536dcf1f339514 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 8 Oct 2015 17:54:43 -0700 Subject: [PATCH 146/316] Reset project in AtomEnvironment::reset --- spec/spec-helper.coffee | 9 ++---- src/atom-environment.coffee | 2 ++ src/project.coffee | 59 ++++++++++++++++++------------------- 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 73790a231..034a2e35c 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -9,7 +9,6 @@ Grim = require 'grim' KeymapManager = require '../src/keymap-extensions' {Point} = require 'text-buffer' -Project = require '../src/project' Workspace = require '../src/workspace' ServiceHub = require 'service-hub' TextEditor = require '../src/text-editor' @@ -73,9 +72,8 @@ isCoreSpec = false beforeEach -> documentTitle = null - projectPath = path.join(@specDirectory, 'fixtures') - atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, config: atom.config, confirm: atom.confirm}) - atom.project.setPaths([projectPath]) + atom.project.setPaths([path.join(@specDirectory, 'fixtures')]) + atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, notificationManager: atom.notifications, @@ -150,9 +148,6 @@ afterEach -> atom.themes.workspace = null delete atom.state.workspace - atom.project?.destroy() - atom.project = null - delete atom.state.packageStates atom.reset() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index b4af72fc7..0dfbd9bb4 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -255,6 +255,8 @@ class AtomEnvironment extends Model @packages.serviceHub.clear() + @project.reset(@packages) + destroy: -> return if not @project diff --git a/src/project.coffee b/src/project.coffee index c33510ec4..7de4c6b69 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -27,45 +27,22 @@ class Project extends Model @paths = [] @rootDirectories = [] @repositories = [] - @directoryProviders = [] @defaultDirectoryProvider = new DefaultDirectoryProvider() - packageManager.serviceHub.consume( - 'atom.directory-provider', - '^0.1.0', - (provider) => - @directoryProviders.unshift(provider) - new Disposable => - @directoryProviders.splice(@directoryProviders.indexOf(provider), 1) - ) - - # Mapping from the real path of a {Directory} to a {Promise} that resolves - # to either a {Repository} or null. Ideally, the {Directory} would be used - # as the key; however, there can be multiple {Directory} objects created for - # the same real path, so it is not a good key. @repositoryPromisesByPath = new Map() - @repositoryProviders = [new GitRepositoryProvider(this, config, confirm)] - packageManager.serviceHub.consume( - 'atom.repository-provider', - '^0.1.0', - (provider) => - @repositoryProviders.push(provider) - - # If a path in getPaths() does not have a corresponding Repository, try - # to assign one by running through setPaths() again now that - # @repositoryProviders has been updated. - if null in @repositories - @setPaths(@getPaths()) - - new Disposable => - @repositoryProviders.splice(@repositoryProviders.indexOf(provider), 1) - ) + @consumeServices(packageManager) destroyed: -> - buffer.destroy() for buffer in @getBuffers() + buffer.destroy() for buffer in @buffers @setPaths([]) + reset: (packageManager) -> + buffer.destroy() for buffer in @buffers + @buffers = [] + @setPaths([]) + @consumeServices(packageManager) + destroyUnretainedBuffers: -> buffer.destroy() for buffer in @getBuffers() when not buffer.isRetained() return @@ -294,6 +271,26 @@ class Project extends Model Section: Private ### + consumeServices: ({serviceHub}) -> + serviceHub.consume( + 'atom.directory-provider', + '^0.1.0', + (provider) => + @directoryProviders.unshift(provider) + new Disposable => + @directoryProviders.splice(@directoryProviders.indexOf(provider), 1) + ) + + serviceHub.consume( + 'atom.repository-provider', + '^0.1.0', + (provider) => + @repositoryProviders.push(provider) + @setPaths(@getPaths()) if null in @repositories + new Disposable => + @repositoryProviders.splice(@repositoryProviders.indexOf(provider), 1) + ) + # Retrieves all the {TextBuffer}s in the project; that is, the # buffers for all open files. # From 4863b71fd71df1793364343de37c2fb3a45ca270 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 9 Oct 2015 08:55:11 +0200 Subject: [PATCH 147/316] Set timeout in the main process --- src/browser/atom-application.coffee | 9 ++++++++- src/browser/atom-window.coffee | 2 +- src/initialize-test-window.coffee | 8 +------- src/timeout-cop.js | 14 -------------- 4 files changed, 10 insertions(+), 23 deletions(-) delete mode 100644 src/timeout-cop.js diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index c4d472e83..2e534e7c8 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -497,6 +497,13 @@ class AtomApplication if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath + timeout = Number.parseFloat(timeout) + unless Number.isNaN(timeout) + timeoutHandler = -> + console.log "The test suite has timed out because it has been running for more than #{timeout} minutes." + process.exit(124) # Use the same exit code as the UNIX timeout util. + setTimeout(timeoutHandler, timeout * 60 * 1000) + try windowInitializationScript = require.resolve(path.resolve(@devResourcePath, 'src', 'initialize-test-window')) catch error @@ -516,7 +523,7 @@ class AtomApplication isSpec = true devMode = true safeMode ?= false - new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode, timeout}) + new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode}) resolveTestRunnerPath: (testPath) -> FindParentDir ?= require 'find-parent-dir' diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 7823388dd..39350392d 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -19,7 +19,7 @@ class AtomWindow isSpec: null constructor: (settings={}) -> - {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode, timeout} = settings + {@resourcePath, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode} = settings locationsToOpen ?= [{pathToOpen}] if pathToOpen locationsToOpen ?= [] diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 89ef44e4f..405d6901a 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -5,7 +5,6 @@ try path = require 'path' ipc = require 'ipc' remote = require 'remote' - app = remote.require('app') {getWindowLoadSettings} = require './window-load-settings-helpers' AtomEnvironment = require '../src/atom-environment' @@ -33,11 +32,6 @@ try document.title = "Spec Suite" - if timeout = getWindowLoadSettings().timeout - ChildProcess = remote.require("child_process") - timeoutCop = ChildProcess.fork(require.resolve('./timeout-cop'), [remote.process.pid, timeout]) - app.on "will-exit", -> timeoutCop.kill() - legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) testRunner = require(getWindowLoadSettings().testRunnerPath) testRunner({ @@ -50,7 +44,7 @@ try catch error if getWindowLoadSettings().headless console.error(error.stack ? error) - app.emit('will-exit') + remote.require('app').emit('will-exit') remote.process.exit(status) else throw error diff --git a/src/timeout-cop.js b/src/timeout-cop.js deleted file mode 100644 index 228a011bb..000000000 --- a/src/timeout-cop.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -let parentProcessId = process.argv[2] -let timeoutInMinutes = process.argv[3] -let timeoutInMilliseconds = timeoutInMinutes * 1000 * 60 - -function exitTestRunner () { - process.kill(parentProcessId, 'SIGINT') - let errorMessage = 'The test suite has timed out because it has been running' - errorMessage += ' for more than ' + timeoutInMinutes + ' minutes.' - console.log(errorMessage) -} - -setTimeout(exitTestRunner, timeoutInMilliseconds) From 60e4b78da39bb7911ff81266c8bb020e03850874 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 9 Oct 2015 10:04:04 +0200 Subject: [PATCH 148/316] Move package reset down into PackageManager --- spec/spec-helper.coffee | 5 ----- src/atom-environment.coffee | 4 +++- src/package-manager.coffee | 5 +++++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 034a2e35c..a13ba9b9c 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -91,8 +91,6 @@ beforeEach -> spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout - atom.packages.packageStates = {} - serializedWindowState = null spyOn(atom, 'saveStateSync') @@ -141,14 +139,11 @@ beforeEach -> addCustomMatchers(this) afterEach -> - atom.packages.deactivatePackages() - atom.workspace?.destroy() atom.workspace = null atom.themes.workspace = null delete atom.state.workspace - delete atom.state.packageStates atom.reset() document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 0dfbd9bb4..289f4a1dc 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -253,10 +253,12 @@ class AtomEnvironment extends Model @contextMenu.clear() - @packages.serviceHub.clear() + @packages.reset() @project.reset(@packages) + @state.packageStates = {} + destroy: -> return if not @project diff --git a/src/package-manager.coffee b/src/package-manager.coffee index beed62683..b4af8ecdb 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -52,6 +52,11 @@ class PackageManager setThemeManager: (@themeManager) -> + reset: -> + @serviceHub.clear() + @deactivatePackages() + @packageStates = {} + ### Section: Event Subscription ### From 74a9e41d9f6ee94fea220d4310862d77d2a42090 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Tue, 6 Oct 2015 11:51:07 +0200 Subject: [PATCH 149/316] Add descriptions for config settings --- src/config-schema.coffee | 44 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index d8eeb6fe3..e34de62d9 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -12,24 +12,27 @@ module.exports = default: [".git", ".hg", ".svn", ".DS_Store", "._*", "Thumbs.db"] items: type: 'string' + description: 'List of string glob patterns. Files and directories matching these patterns will be ignored by some packages, such as the fuzzy finder and tree view. Individual packages might have additional config settings for ignoring names.' excludeVcsIgnoredPaths: type: 'boolean' default: true title: 'Exclude VCS Ignored Paths' + description: 'Files and directories ignored by the current project\'s VCS system will be ignored by some packages, such as the fuzzy finder and find and replace. For example, project\'s using Git have these paths defined in the .gitignore file. Individual packages might have additional config settings for ignoring VCS ignored files and folders.' followSymlinks: type: 'boolean' default: true title: 'Follow symlinks' - description: 'Used when searching and when opening files with the fuzzy finder.' + description: 'Follow symbolic links when searching files and when opening files with the fuzzy finder.' disabledPackages: type: 'array' default: [] items: type: 'string' + description: 'List of names of installed packages which are not loaded at startup.' customFileTypes: type: 'object' default: {} - description: 'Associates scope names (e.g. "source.js") with arrays of file extensions and file names (e.g. ["Somefile", ".js2"])' + description: 'Associates scope names (e.g. `"source.js"`) with arrays of file extensions and file names (e.g. `["Somefile", ".js2"]`)' additionalProperties: type: 'array' items: @@ -39,15 +42,19 @@ module.exports = default: ['one-dark-ui', 'one-dark-syntax'] items: type: 'string' + description: 'Names of UI and syntax themes which will be used when Atom starts.' projectHome: type: 'string' default: path.join(fs.getHomeDirectory(), 'github') + description: 'The directory where projects are assumed to be located. Packages created using the Package Generator will be stored here by default.' audioBeep: type: 'boolean' default: true + description: 'Trigger the system\'s beep sound when certain actions cannot be executed or there are no results.' destroyEmptyPanes: type: 'boolean' default: true + description: 'When the last item of a pane is removed, remove that pane as well.' fileEncoding: description: 'Default character set encoding to use when reading and writing files.' type: 'string' @@ -90,7 +97,7 @@ module.exports = 'windows866' ] openEmptyEditorOnStart: - description: 'Automatically opens an empty editor when atom starts.' + description: 'Automatically open an empty editor when on startup.' type: 'boolean' default: true @@ -113,41 +120,52 @@ module.exports = fontFamily: type: 'string' default: '' + description: 'The name of the font family used for editor text.' fontSize: type: 'integer' default: 14 minimum: 1 maximum: 100 + description: 'Height in pixels of editor text.' lineHeight: type: ['string', 'number'] default: 1.5 + description: 'Height of editor lines, as a multiplier of font size.' showInvisibles: type: 'boolean' default: false + description: 'Render placeholders for invisible characters, such as tabs, spaces and newlines.' showIndentGuide: type: 'boolean' default: false + description: 'Show indentation indicators in the editor.' showLineNumbers: type: 'boolean' default: true + description: 'Show line numbers in the editor\'s gutter.' autoIndent: type: 'boolean' default: true - description: 'Automatically indent the cursor when inserting a newline' + description: 'Automatically indent the cursor when inserting a newline.' + type: 'boolean' autoIndentOnPaste: type: 'boolean' default: true + description: 'Automatically indent pasted text based on the indentation of the previous line.' nonWordCharacters: type: 'string' default: "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-…" + description: 'A string of non-word characters to define word boundaries.' preferredLineLength: type: 'integer' default: 80 minimum: 1 + description: 'Identifies the length of a line which is used when wrapping text with the `Soft Wrap At Preferred Line Length` setting enabled, in number of characters.' tabLength: type: 'integer' default: 2 enum: [1, 2, 3, 4, 6, 8] + description: 'Number of spaces used to represent a tab.' softWrap: type: 'boolean' default: false @@ -155,32 +173,36 @@ module.exports = softTabs: type: 'boolean' default: true + description: 'If the `Tab Type` config setting is set to "auto" and autodetection of tab type from buffer content fails, then this config setting determines whether a soft tab or a hard tab will be inserted when the Tab key is pressed.' tabType: type: 'string' default: 'auto' enum: ['auto', 'soft', 'hard'] - description: 'Determine character inserted during Tab keypress.' + description: 'Determine character inserted when Tab key is pressed. Possible values: "auto", "soft" and "hard". When set to "soft" or "hard", soft tabs (spaces) or hard tabs (tab characters) are used. When set to "auto", the editor auto-detects the tab type based on the contents of the buffer, or uses the value of the Soft Tabs config setting if auto-dection fails.' softWrapAtPreferredLineLength: type: 'boolean' default: false - description: 'Will wrap to the number of characters defined by the `Preferred Line Length` setting. This will only take effect when soft wrap is enabled globally or for the current language.' + description: 'Instead of wrapping lines to the window\'s width, wrap lines to the number of characters defined by the `Preferred Line Length` setting. This will only take effect when the soft wrap config setting is enabled globally or for the current language.' softWrapHangingIndent: type: 'integer' default: 0 minimum: 0 + description: 'When soft wrap is enabled, defines length of additional indentation applied to wrapped lines, in number of characters.' scrollSensitivity: type: 'integer' default: 40 minimum: 10 maximum: 200 + description: 'Determines how fast the editor scrolls when using a mouse or trackpad.' scrollPastEnd: type: 'boolean' default: false + description: 'Allow the editor to be scrolled past the end of the last line.' undoGroupingInterval: type: 'integer' default: 300 minimum: 0 - description: 'Time interval in milliseconds within which operations will be grouped together in the undo history' + description: 'Time interval in milliseconds within which text editing operations will be grouped together in the undo history.' useShadowDOM: type: 'boolean' default: true @@ -190,33 +212,39 @@ module.exports = type: 'boolean' default: true title: 'Confirm Checkout HEAD Revision' + description: 'Show confirmation dialog when checking out the HEAD revision and discarding changes to current file since last commit.' backUpBeforeSaving: type: 'boolean' default: false description: 'Ensure file contents aren\'t lost if there is an I/O error during save by making a temporary backup copy.' invisibles: type: 'object' + description: 'A hash of characters Atom will use to render whitespace characters. Keys are whitespace character types, values are rendered characters (use value false to turn off individual whitespace character types).' properties: eol: type: ['boolean', 'string'] default: '\u00ac' maximumLength: 1 + description: 'Character used to render newline characters (\\n) when the `Show Invisibles` setting is enabled. ' space: type: ['boolean', 'string'] default: '\u00b7' maximumLength: 1 + description: 'Character used to render leading and trailing space characters when the `Show Invisibles` setting is enabled.' tab: type: ['boolean', 'string'] default: '\u00bb' maximumLength: 1 + description: 'Character used to render hard tab characters (\\t) when the `Show Invisibles` setting is enabled.' cr: type: ['boolean', 'string'] default: '\u00a4' maximumLength: 1 + description: 'Character used to render carriage return characters (for Microsoft-style line endings) when the `Show Invisibles` setting is enabled.' zoomFontWhenCtrlScrolling: type: 'boolean' default: process.platform isnt 'darwin' - description: 'Increase/decrease the editor font size when pressing the Ctrl key and scrolling the mouse up/down.' + description: 'Change the editor font size when pressing the Ctrl key and scrolling the mouse up/down.' if process.platform in ['win32', 'linux'] module.exports.core.properties.autoHideMenuBar = From 35764e33923ec2b50005fa757082485c1d6d5800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C5=BDu=C5=BEak?= Date: Fri, 9 Oct 2015 13:04:17 +0200 Subject: [PATCH 150/316] Remove extra word --- src/config-schema.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index e34de62d9..a5f33fa62 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -97,7 +97,7 @@ module.exports = 'windows866' ] openEmptyEditorOnStart: - description: 'Automatically open an empty editor when on startup.' + description: 'Automatically open an empty editor on startup.' type: 'boolean' default: true From 5d9ae3d0db7443de633bfdfa2acad941a41981bd Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Fri, 9 Oct 2015 14:50:14 +0200 Subject: [PATCH 151/316] Remove duplicate key --- src/config-schema.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index a5f33fa62..b452fb543 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -147,7 +147,6 @@ module.exports = type: 'boolean' default: true description: 'Automatically indent the cursor when inserting a newline.' - type: 'boolean' autoIndentOnPaste: type: 'boolean' default: true From fe7b15b684d19f33a902e736db5ee501da144860 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Fri, 9 Oct 2015 14:51:49 +0200 Subject: [PATCH 152/316] Fix typos --- src/config-schema.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index b452fb543..38182efb5 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -17,7 +17,7 @@ module.exports = type: 'boolean' default: true title: 'Exclude VCS Ignored Paths' - description: 'Files and directories ignored by the current project\'s VCS system will be ignored by some packages, such as the fuzzy finder and find and replace. For example, project\'s using Git have these paths defined in the .gitignore file. Individual packages might have additional config settings for ignoring VCS ignored files and folders.' + description: 'Files and directories ignored by the current project\'s VCS system will be ignored by some packages, such as the fuzzy finder and find and replace. For example, projects using Git have these paths defined in the .gitignore file. Individual packages might have additional config settings for ignoring VCS ignored files and folders.' followSymlinks: type: 'boolean' default: true @@ -177,7 +177,7 @@ module.exports = type: 'string' default: 'auto' enum: ['auto', 'soft', 'hard'] - description: 'Determine character inserted when Tab key is pressed. Possible values: "auto", "soft" and "hard". When set to "soft" or "hard", soft tabs (spaces) or hard tabs (tab characters) are used. When set to "auto", the editor auto-detects the tab type based on the contents of the buffer, or uses the value of the Soft Tabs config setting if auto-dection fails.' + description: 'Determine character inserted when Tab key is pressed. Possible values: "auto", "soft" and "hard". When set to "soft" or "hard", soft tabs (spaces) or hard tabs (tab characters) are used. When set to "auto", the editor auto-detects the tab type based on the contents of the buffer, or uses the value of the Soft Tabs config setting if auto-detection fails.' softWrapAtPreferredLineLength: type: 'boolean' default: false From 4ce814320db76a5d5bdf82054b437d5710ee3aae Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 9 Oct 2015 17:41:32 +0200 Subject: [PATCH 153/316] Call side effects methods after instantiating instance variables This prevents a :bug: where the `onDidLoadBundledKeymaps` was fired before `MenuManager` had the chance to listen to it thereby not showing the appropriate menu entries. --- src/atom-environment.coffee | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 289f4a1dc..9571e38c1 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -117,30 +117,24 @@ class AtomEnvironment extends Model DeserializerManager = require './deserializer-manager' @deserializers = new DeserializerManager(this) @deserializeTimings = {} - @registerDefaultDeserializers() ViewRegistry = require './view-registry' @views = new ViewRegistry(this) - @registerDefaultViewProviders() NotificationManager = require './notification-manager' @notifications = new NotificationManager Config = require './config' @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) - @setConfigSchema() KeymapManager = require './keymap-extensions' @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) - @keymaps.subscribeToFileReadFailure() - @keymaps.loadBundledKeymaps() TooltipManager = require './tooltip-manager' @tooltips = new TooltipManager(keymapManager: @keymaps) CommandRegistry = require './command-registry' @commands = new CommandRegistry - registerDefaultCommands(this) GrammarRegistry = require './grammar-registry' @grammars = new GrammarRegistry({@config}) @@ -156,7 +150,6 @@ class AtomEnvironment extends Model packageManager: @packages, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, notificationManager: @notifications, viewRegistry: @views }) - @initialStyleElements = @styles.getSnapshot() MenuManager = require './menu-manager' @menu = new MenuManager({resourcePath, keymapManager: @keymaps, packageManager: @packages}) @@ -184,7 +177,15 @@ class AtomEnvironment extends Model }) @themes.workspace = @workspace + @initialStyleElements = @styles.getSnapshot() + + @setConfigSchema() + @keymaps.subscribeToFileReadFailure() + @keymaps.loadBundledKeymaps() + registerDefaultCommands(this) @registerDefaultOpeners() + @registerDefaultDeserializers() + @registerDefaultViewProviders() setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} From 1a8beef74fc415a77b65aff71efd3fc9a1545294 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 9 Oct 2015 18:37:24 +0200 Subject: [PATCH 154/316] :bug: Load config schema before loading base stylesheets --- src/atom-environment.coffee | 5 ++++- src/theme-manager.coffee | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 9571e38c1..b3e0eabfe 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -126,6 +126,7 @@ class AtomEnvironment extends Model Config = require './config' @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) + @setConfigSchema() KeymapManager = require './keymap-extensions' @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) @@ -177,11 +178,12 @@ class AtomEnvironment extends Model }) @themes.workspace = @workspace + @themes.loadBaseStylesheets() @initialStyleElements = @styles.getSnapshot() - @setConfigSchema() @keymaps.subscribeToFileReadFailure() @keymaps.loadBundledKeymaps() + registerDefaultCommands(this) @registerDefaultOpeners() @registerDefaultDeserializers() @@ -585,6 +587,7 @@ class AtomEnvironment extends Model stylesElement = new StylesElement stylesElement.initialize(this) + document.head.appendChild(stylesElement) @windowEventHandler = new WindowEventHandler(this) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 4ccee0a4c..649478841 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -17,7 +17,6 @@ class ThemeManager @packageManager.registerPackageActivator(this, ['theme']) @packageManager.onDidActivateInitialPackages => @onDidChangeActiveThemes => @packageManager.reloadActivePackageStyleSheets() - @loadBaseStylesheets() ### Section: Event Subscription From 778023c78b3cebc98aec1d16fa0eb16fa818e0ba Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Oct 2015 13:44:03 -0700 Subject: [PATCH 155/316] Make factory for StylesElements on atom.styles --- spec/jasmine-test-runner.coffee | 6 +----- spec/styles-element-spec.coffee | 4 ++-- src/atom-environment.coffee | 5 +---- src/style-manager.coffee | 6 ++++++ src/styles-element.coffee | 12 ++++++------ src/text-editor-element.coffee | 2 +- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index b75e90d12..a245379e2 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -3,7 +3,6 @@ _ = require 'underscore-plus' fs = require 'fs-plus' path = require 'path' ipc = require 'ipc' -StylesElement = require '../src/styles-element' module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> window.atom = buildAtomEnvironment() @@ -26,10 +25,7 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> jasmineContent = document.createElement('div') jasmineContent.setAttribute('id', 'jasmine-content') - stylesElement = new StylesElement - stylesElement.initialize(atom) - - document.head.appendChild(stylesElement) + document.head.appendChild(atom.styles.buildStylesElement()) document.body.appendChild(jasmineContent) atom.commands.attach(window) diff --git a/spec/styles-element-spec.coffee b/spec/styles-element-spec.coffee index ae2648644..b1a57938c 100644 --- a/spec/styles-element-spec.coffee +++ b/spec/styles-element-spec.coffee @@ -6,7 +6,7 @@ describe "StylesElement", -> beforeEach -> element = new StylesElement - element.initialize(atom) + element.initialize(atom.styles) document.querySelector('#jasmine-content').appendChild(element) addedStyleElements = [] removedStyleElements = [] @@ -100,7 +100,7 @@ describe "StylesElement", -> it "defers selector upgrade until the element is attached", -> element = new StylesElement - element.initialize(atom) + element.initialize(atom.styles) element.setAttribute('context', 'atom-text-editor') atom.styles.addStyleSheet ".editor {background: black;}", context: 'atom-text-editor' diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index b3e0eabfe..e398df1f9 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -585,10 +585,7 @@ class AtomEnvironment extends Model @config.load() @setBodyPlatformClass() - stylesElement = new StylesElement - stylesElement.initialize(this) - - document.head.appendChild(stylesElement) + document.head.appendChild(@styles.buildStylesElement()) @windowEventHandler = new WindowEventHandler(this) @packages.loadPackages() diff --git a/src/style-manager.coffee b/src/style-manager.coffee index 11dc4b97f..8b3349b7a 100644 --- a/src/style-manager.coffee +++ b/src/style-manager.coffee @@ -1,6 +1,7 @@ fs = require 'fs-plus' path = require 'path' {Emitter, Disposable} = require 'event-kit' +StylesElement = require './styles-element' # Extended: A singleton instance of this class available via `atom.styles`, # which you can use to globally query and observe the set of active style @@ -154,6 +155,11 @@ class StyleManager return + buildStylesElement: -> + stylesElement = new StylesElement + stylesElement.initialize(this) + stylesElement + ### Section: Paths ### diff --git a/src/styles-element.coffee b/src/styles-element.coffee index e5ab9884e..d1e6bf3d9 100644 --- a/src/styles-element.coffee +++ b/src/styles-element.coffee @@ -32,19 +32,19 @@ class StylesElement extends HTMLElement attributeChangedCallback: (attrName, oldVal, newVal) -> @contextChanged() if attrName is 'context' - initialize: ({@styles}) -> - throw new Error("Must pass a styles parameter when initializing TextEditorElements") unless @styles? + initialize: (@styleManager) -> + throw new Error("Must pass a styleManager parameter when initializing a StylesElement") unless @styleManager? - @subscriptions.add @styles.observeStyleElements(@styleElementAdded.bind(this)) - @subscriptions.add @styles.onDidRemoveStyleElement(@styleElementRemoved.bind(this)) - @subscriptions.add @styles.onDidUpdateStyleElement(@styleElementUpdated.bind(this)) + @subscriptions.add @styleManager.observeStyleElements(@styleElementAdded.bind(this)) + @subscriptions.add @styleManager.onDidRemoveStyleElement(@styleElementRemoved.bind(this)) + @subscriptions.add @styleManager.onDidUpdateStyleElement(@styleElementUpdated.bind(this)) contextChanged: -> return unless @subscriptions? @styleElementRemoved(child) for child in Array::slice.call(@children) @context = @getAttribute('context') - @styleElementAdded(styleElement) for styleElement in @styles.getStyleElements() + @styleElementAdded(styleElement) for styleElement in @styleManager.getStyleElements() return styleElementAdded: (styleElement) -> diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index fc2d2c7e9..9fe0e9091 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -49,7 +49,7 @@ class TextEditorElement extends HTMLElement @shadowRoot.appendChild(ShadowStyleSheet.cloneNode(true)) @stylesElement = new StylesElement - @stylesElement.initialize({@styles}) + @stylesElement.initialize(@styles) @stylesElement.setAttribute('context', 'atom-text-editor') @rootElement = document.createElement('div') From b467c83e7644461ec49f31e7a587cb39080ea8fd Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Oct 2015 13:46:51 -0700 Subject: [PATCH 156/316] Remove unused requires in spec-helper --- spec/spec-helper.coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index a13ba9b9c..fa3104090 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -6,16 +6,14 @@ path = require 'path' _ = require 'underscore-plus' fs = require 'fs-plus' Grim = require 'grim' -KeymapManager = require '../src/keymap-extensions' +pathwatcher = require 'pathwatcher' {Point} = require 'text-buffer' Workspace = require '../src/workspace' -ServiceHub = require 'service-hub' TextEditor = require '../src/text-editor' TextEditorElement = require '../src/text-editor-element' TokenizedBuffer = require '../src/tokenized-buffer' TextEditorComponent = require '../src/text-editor-component' -pathwatcher = require 'pathwatcher' clipboard = require '../src/safe-clipboard' jasmineStyle = document.createElement('style') From 369f3d2648df2e8e076296bd9fecd77cf3468e1a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Oct 2015 17:18:26 -0700 Subject: [PATCH 157/316] Don't use atom.{notifications,config,deserializers,confirm} in Pane Still need to get rid of one use of showSaveDialogSync --- spec/pane-container-spec.coffee | 52 +++++++++------- spec/pane-spec.coffee | 90 +++++++++++++++------------ spec/window-event-handler-spec.coffee | 70 +++++---------------- spec/workspace-spec.coffee | 12 ++-- src/atom-environment.coffee | 2 +- src/pane-container.coffee | 4 +- src/pane.coffee | 31 +++++---- src/workspace.coffee | 4 +- 8 files changed, 127 insertions(+), 138 deletions(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 42dad2fa9..1442f24e4 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -2,6 +2,16 @@ PaneContainer = require '../src/pane-container' Pane = require '../src/pane' describe "PaneContainer", -> + [confirm, params] = [] + + beforeEach -> + confirm = jasmine.createSpy('confirm').andReturn(0) + params = { + config: atom.config, + confirm: confirm, + deserializerManager: atom.deserializers + } + describe "serialization", -> [containerA, pane1A, pane2A, pane3A] = [] @@ -12,7 +22,7 @@ describe "PaneContainer", -> @deserialize: -> new this serialize: -> deserializer: 'Item' - containerA = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerA = new PaneContainer(params) pane1A = containerA.getActivePane() pane1A.addItem(new Item) pane2A = pane1A.splitRight(items: [new Item]) @@ -22,7 +32,7 @@ describe "PaneContainer", -> it "preserves the focused pane across serialization", -> expect(pane3A.focused).toBe true - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(pane3B.focused).toBe true @@ -31,7 +41,7 @@ describe "PaneContainer", -> pane3A.activate() expect(containerA.getActivePane()).toBe pane3A - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(containerA.serialize(), atom.deserializers) [pane1B, pane2B, pane3B] = containerB.getPanes() expect(containerB.getActivePane()).toBe pane3B @@ -40,7 +50,7 @@ describe "PaneContainer", -> pane3A.activate() state = containerA.serialize() state.activePaneId = -22 - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(state, atom.deserializers) expect(containerB.getActivePane()).toBe containerB.getPanes()[0] @@ -51,7 +61,7 @@ describe "PaneContainer", -> describe "if the 'core.destroyEmptyPanes' config option is false (the default)", -> it "leaves the empty panes intact", -> state = containerA.serialize() - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(state, atom.deserializers) [leftPane, column] = containerB.getRoot().getChildren() [topPane, bottomPane] = column.getChildren() @@ -65,7 +75,7 @@ describe "PaneContainer", -> atom.config.set('core.destroyEmptyPanes', true) state = containerA.serialize() - containerB = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + containerB = new PaneContainer(params) containerB.deserialize(state, atom.deserializers) [leftPane, rightPane] = containerB.getRoot().getChildren() @@ -73,7 +83,7 @@ describe "PaneContainer", -> expect(rightPane.getItems().length).toBe 1 it "does not allow the root pane to be destroyed", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().destroy() expect(container.getRoot()).toBeDefined() expect(container.getRoot().isDestroyed()).toBe false @@ -82,7 +92,7 @@ describe "PaneContainer", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) pane1 = container.getRoot() it "returns the first pane if no pane has been made active", -> @@ -111,7 +121,7 @@ describe "PaneContainer", -> [container, pane1, pane2, observed] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object, new Object]) [pane1, pane2] = container.getPanes() @@ -131,7 +141,7 @@ describe "PaneContainer", -> describe "::observePanes()", -> it "invokes observers with all current and future panes", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() @@ -145,7 +155,7 @@ describe "PaneContainer", -> describe "::observePaneItems()", -> it "invokes observers with all current and future pane items", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().addItems([new Object, new Object]) container.getRoot().splitRight(items: [new Object]) [pane1, pane2] = container.getPanes() @@ -165,27 +175,27 @@ describe "PaneContainer", -> shouldPromptToSave: -> true getURI: -> 'test' - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) container.getRoot().splitRight() [pane1, pane2] = container.getPanes() pane1.addItem(new TestItem) pane2.addItem(new TestItem) it "returns true if the user saves all modified files when prompted", -> - spyOn(atom, "confirm").andReturn(0) + confirm.andReturn(0) saved = container.confirmClose() expect(saved).toBeTruthy() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() it "returns false if the user cancels saving any modified file", -> - spyOn(atom, "confirm").andReturn(1) + confirm.andReturn(1) saved = container.confirmClose() expect(saved).toBeFalsy() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() describe "::onDidAddPane(callback)", -> it "invokes the given callback when panes are added", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) events = [] container.onDidAddPane (event) -> events.push(event) @@ -202,7 +212,7 @@ describe "PaneContainer", -> destroy: -> @_isDestroyed = true isDestroyed: -> @_isDestroyed - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) events = [] container.onWillDestroyPane (event) -> itemsDestroyed = (item.isDestroyed() for item in event.pane.getItems()) @@ -218,7 +228,7 @@ describe "PaneContainer", -> describe "::onDidDestroyPane(callback)", -> it "invokes the given callback when panes are destroyed", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) events = [] container.onDidDestroyPane (event) -> events.push(event) @@ -233,7 +243,7 @@ describe "PaneContainer", -> describe "::onWillDestroyPaneItem() and ::onDidDestroyPaneItem", -> it "invokes the given callbacks when an item will be destroyed on any pane", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) pane1 = container.getRoot() item1 = new Object item2 = new Object @@ -260,7 +270,7 @@ describe "PaneContainer", -> describe "::saveAll()", -> it "saves all open pane items", -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(params) pane1 = container.getRoot() pane2 = pane1.splitRight() diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 4186e33a1..ca277f9af 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -1,10 +1,11 @@ +{extend} = require 'underscore-plus' {Emitter} = require 'event-kit' Pane = require '../src/pane' PaneAxis = require '../src/pane-axis' PaneContainer = require '../src/pane-container' describe "Pane", -> - deserializerDisposable = null + [confirm, deserializerDisposable] = [] class Item @deserialize: ({name, uri}) -> new this(name, uri) @@ -19,18 +20,27 @@ describe "Pane", -> isDestroyed: -> @destroyed beforeEach -> + confirm = jasmine.createSpy('confirm') deserializerDisposable = atom.deserializers.add(Item) afterEach -> deserializerDisposable.dispose() + paneParams = (params) -> + extend({ + confirm: confirm, + config: atom.config, + deserializerManager: atom.deserializers, + notificationManager: atom.notifications + }, params) + describe "construction", -> it "sets the active item to the first item", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) it "compacts the items array", -> - pane = new Pane(items: [undefined, new Item("A"), null, new Item("B")]) + pane = new Pane(paneParams(items: [undefined, new Item("A"), null, new Item("B")])) expect(pane.getItems().length).toBe 2 expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) @@ -38,7 +48,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) container.getActivePane().splitRight() [pane1, pane2] = container.getPanes() @@ -76,14 +86,14 @@ describe "Pane", -> describe "::addItem(item, index)", -> it "adds the item at the given index", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) [item1, item2] = pane.getItems() item3 = new Item("C") pane.addItem(item3, 1) expect(pane.getItems()).toEqual [item1, item3, item2] it "adds the item after the active item if no index is provided", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItem(item2) item4 = new Item("D") @@ -91,13 +101,13 @@ describe "Pane", -> expect(pane.getItems()).toEqual [item1, item2, item4, item3] it "sets the active item after adding the first item", -> - pane = new Pane + pane = new Pane(paneParams()) item = new Item("A") pane.addItem(item) expect(pane.getActiveItem()).toBe item it "invokes ::onDidAddItem() observers", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) events = [] pane.onDidAddItem (event) -> events.push(event) @@ -107,14 +117,14 @@ describe "Pane", -> it "throws an exception if the item is already present on a pane", -> item = new Item("A") - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) pane1 = container.getActivePane() pane1.addItem(item) pane2 = pane1.splitRight() expect(-> pane2.addItem(item)).toThrow() it "throws an exception if the item isn't an object", -> - pane = new Pane(items: []) + pane = new Pane(paneParams(items: [])) expect(-> pane.addItem(null)).toThrow() expect(-> pane.addItem('foo')).toThrow() expect(-> pane.addItem(1)).toThrow() @@ -123,7 +133,7 @@ describe "Pane", -> pane = null beforeEach -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) it "changes the active item to the current item", -> expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) @@ -144,7 +154,7 @@ describe "Pane", -> describe "::activateNextItem() and ::activatePreviousItem()", -> it "sets the active item to the next/previous item, looping around at either end", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() expect(pane.getActiveItem()).toBe item1 @@ -159,7 +169,7 @@ describe "Pane", -> describe "::moveItemRight() and ::moveItemLeft()", -> it "moves the active item to the right and left, without looping around at either end", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItemAtIndex(0) @@ -177,7 +187,7 @@ describe "Pane", -> describe "::activateItemAtIndex(index)", -> it "activates the item at the given index", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItemAtIndex(2) expect(pane.getActiveItem()).toBe item3 @@ -196,7 +206,7 @@ describe "Pane", -> [pane, item1, item2, item3] = [] beforeEach -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() it "removes the item from the items list and destroyes it", -> @@ -260,7 +270,7 @@ describe "Pane", -> describe "when the item has a uri", -> it "saves the item before destroying it", -> itemURI = "test" - spyOn(atom, 'confirm').andReturn(0) + confirm.andReturn(0) pane.destroyItem(item1) expect(item1.save).toHaveBeenCalled() @@ -272,7 +282,7 @@ describe "Pane", -> itemURI = null spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path") - spyOn(atom, 'confirm').andReturn(0) + confirm.andReturn(0) pane.destroyItem(item1) expect(atom.showSaveDialogSync).toHaveBeenCalled() @@ -282,7 +292,7 @@ describe "Pane", -> describe "if the [Don't Save] option is selected", -> it "removes and destroys the item without saving it", -> - spyOn(atom, 'confirm').andReturn(2) + confirm.andReturn(2) pane.destroyItem(item1) expect(item1.save).not.toHaveBeenCalled() @@ -291,7 +301,7 @@ describe "Pane", -> describe "if the [Cancel] option is selected", -> it "does not save, remove, or destroy the item", -> - spyOn(atom, 'confirm').andReturn(1) + confirm.andReturn(1) pane.destroyItem(item1) expect(item1.save).not.toHaveBeenCalled() @@ -316,19 +326,19 @@ describe "Pane", -> describe "::destroyActiveItem()", -> it "destroys the active item", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) activeItem = pane.getActiveItem() pane.destroyActiveItem() expect(activeItem.isDestroyed()).toBe true expect(activeItem in pane.getItems()).toBe false it "does not throw an exception if there are no more items", -> - pane = new Pane + pane = new Pane(paneParams()) pane.destroyActiveItem() describe "::destroyItems()", -> it "destroys all items", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.destroyItems() expect(item1.isDestroyed()).toBe true @@ -338,7 +348,7 @@ describe "Pane", -> describe "::observeItems()", -> it "invokes the observer with all current and future items", -> - pane = new Pane(items: [new Item, new Item]) + pane = new Pane(paneParams(items: [new Item, new Item])) [item1, item2] = pane.getItems() observed = [] @@ -351,14 +361,14 @@ describe "Pane", -> describe "when an item emits a destroyed event", -> it "removes it from the list of items", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.itemAtIndex(1).destroy() expect(pane.getItems()).toEqual [item1, item3] describe "::destroyInactiveItems()", -> it "destroys all items but the active item", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) [item1, item2, item3] = pane.getItems() pane.activateItem(item2) pane.destroyInactiveItems() @@ -368,7 +378,7 @@ describe "Pane", -> pane = null beforeEach -> - pane = new Pane(items: [new Item("A")]) + pane = new Pane(paneParams(items: [new Item("A")])) spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') describe "when the active item has a uri", -> @@ -423,7 +433,7 @@ describe "Pane", -> pane = null beforeEach -> - pane = new Pane(items: [new Item("A")]) + pane = new Pane(paneParams(items: [new Item("A")])) spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') describe "when the current item has a saveAs method", -> @@ -461,7 +471,7 @@ describe "Pane", -> describe "::itemForURI(uri)", -> it "returns the item for which a call to .getURI() returns the given uri", -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])) [item1, item2, item3] = pane.getItems() item1.uri = "a" item2.uri = "b" @@ -473,7 +483,7 @@ describe "Pane", -> [pane, item1, item2, item3, item4] = [] beforeEach -> - pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])) [item1, item2, item3, item4] = pane.getItems() it "moves the item to the given index and invokes ::onDidMoveItem observers", -> @@ -502,7 +512,7 @@ describe "Pane", -> [item1, item2, item3, item4, item5] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) pane1 = container.getActivePane() pane1.addItems([new Item("A"), new Item("B"), new Item("C")]) pane2 = pane1.splitRight(items: [new Item("D"), new Item("E")]) @@ -555,7 +565,7 @@ describe "Pane", -> [pane1, container] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm, deserializerManager: atom.deserializers) pane1 = container.getActivePane() pane1.addItem(new Item("A")) @@ -655,32 +665,32 @@ describe "Pane", -> describe "::close()", -> it "prompts to save unsaved items before destroying the pane", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) [item1, item2] = pane.getItems() item1.shouldPromptToSave = -> true item1.getURI = -> "/test/path" item1.save = jasmine.createSpy("save") - spyOn(atom, 'confirm').andReturn(0) + confirm.andReturn(0) pane.close() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() expect(item1.save).toHaveBeenCalled() expect(pane.isDestroyed()).toBe true it "does not destroy the pane if cancel is called", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) + pane = new Pane(paneParams(items: [new Item("A"), new Item("B")])) [item1, item2] = pane.getItems() item1.shouldPromptToSave = -> true item1.getURI = -> "/test/path" item1.save = jasmine.createSpy("save") - spyOn(atom, 'confirm').andReturn(1) + confirm.andReturn(1) pane.close() - expect(atom.confirm).toHaveBeenCalled() + expect(confirm).toHaveBeenCalled() expect(item1.save).not.toHaveBeenCalled() expect(pane.isDestroyed()).toBe false @@ -688,7 +698,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: atom.confirm.bind(atom)) + container = new PaneContainer(config: atom.config, confirm: confirm) pane1 = container.root pane1.addItems([new Item("A"), new Item("B")]) pane2 = pane1.splitRight() @@ -735,10 +745,10 @@ describe "Pane", -> pane = null beforeEach -> - params = + pane = new Pane(paneParams( items: [new Item("A", "a"), new Item("B", "b"), new Item("C", "c")] flexScale: 2 - pane = new Pane(params) + )) it "can serialize and deserialize the pane and all its items", -> newPane = Pane.deserialize(pane.serialize(), atom) diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 07bcae5a3..dd3b6031a 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -4,6 +4,7 @@ fs = require 'fs-plus' temp = require 'temp' TextEditor = require '../src/text-editor' WindowEventHandler = require '../src/window-event-handler' +ipc = require 'ipc' describe "WindowEventHandler", -> [projectPath, windowEventHandler] = [] @@ -50,64 +51,25 @@ describe "WindowEventHandler", -> describe "beforeunload event", -> beforeEach -> jasmine.unspy(TextEditor.prototype, "shouldPromptToSave") + spyOn(ipc, 'send') describe "when pane items are modified", -> - it "prompts user to save and calls atom.workspace.confirmClose", -> - editor = null - spyOn(atom.workspace, 'confirmClose').andCallThrough() - spyOn(atom, "confirm").andReturn(2) + editor = null + beforeEach -> + waitsForPromise -> atom.workspace.open("sample.js").then (o) -> editor = o + runs -> editor.insertText("I look different, I feel different.") - waitsForPromise -> - atom.workspace.open("sample.js").then (o) -> editor = o + it "prompts the user to save them, and allows the unload to continue if they confirm", -> + spyOn(atom.workspace, 'confirmClose').andReturn(true) + window.dispatchEvent(new CustomEvent('beforeunload')) + expect(atom.workspace.confirmClose).toHaveBeenCalled() + expect(ipc.send).not.toHaveBeenCalledWith('cancel-window-close') - runs -> - editor.insertText("I look different, I feel different.") - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.workspace.confirmClose).toHaveBeenCalled() - expect(atom.confirm).toHaveBeenCalled() - - it "prompts user to save and handler returns true if don't save", -> - editor = null - spyOn(atom, "confirm").andReturn(2) - - waitsForPromise -> - atom.workspace.open("sample.js").then (o) -> editor = o - - runs -> - editor.insertText("I look different, I feel different.") - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.confirm).toHaveBeenCalled() - - it "prompts user to save and handler returns false if dialog is canceled", -> - editor = null - spyOn(atom, "confirm").andReturn(1) - waitsForPromise -> - atom.workspace.open("sample.js").then (o) -> editor = o - - runs -> - editor.insertText("I look different, I feel different.") - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.confirm).toHaveBeenCalled() - - describe "when the same path is modified in multiple panes", -> - it "prompts to save the item", -> - return - editor = null - filePath = path.join(temp.mkdirSync('atom-file'), 'file.txt') - fs.writeFileSync(filePath, 'hello') - spyOn(atom.workspace, 'confirmClose').andCallThrough() - spyOn(atom, 'confirm').andReturn(0) - - waitsForPromise -> - atom.workspace.open(filePath).then (o) -> editor = o - - runs -> - atom.workspace.getActivePane().splitRight(copyActiveItem: true) - editor.setText('world') - window.dispatchEvent(new CustomEvent('beforeunload')) - expect(atom.workspace.confirmClose).toHaveBeenCalled() - expect(atom.confirm.callCount).toBe 1 - expect(fs.readFileSync(filePath, 'utf8')).toBe 'world' + it "cancels the unload if the user selects cancel", -> + spyOn(atom.workspace, 'confirmClose').andReturn(false) + window.dispatchEvent(new CustomEvent('beforeunload')) + expect(atom.workspace.confirmClose).toHaveBeenCalled() + expect(ipc.send).toHaveBeenCalledWith('cancel-window-close') describe "when a link is clicked", -> it "opens the http/https links in an external application", -> diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index b39570db0..fc5fb5fff 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -18,7 +18,7 @@ describe "Workspace", -> atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) atom.workspace = workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), @@ -36,7 +36,7 @@ describe "Workspace", -> atom.project.deserialize(projectState, atom.deserializers) atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, assert: atom.assert.bind(atom) @@ -635,8 +635,8 @@ describe "Workspace", -> workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, clipboard: atom.clipboard, - viewRegistry: atom.views, grammarRegistry: atom.grammars, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) @@ -695,8 +695,8 @@ describe "Workspace", -> document.title = null workspace2 = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, clipboard: atom.clipboard, - viewRegistry: atom.views, grammarRegistry: atom.grammars, + notificationManager: atom.notifications, deserializerManager: atom.deserializers, + clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), assert: atom.assert.bind(atom) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index e398df1f9..3445a0a49 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -172,7 +172,7 @@ class AtomEnvironment extends Model @commandInstaller = new CommandInstaller(@getVersion(), @confirm.bind(this)) @workspace = new Workspace({ - @config, @project, packageManager: @packages, grammarRegistry: @grammars, + @config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers, notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, assert: @assert.bind(this), confirm: @confirm.bind(this) }) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index a91cee608..16a1274d6 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -13,12 +13,12 @@ class PaneContainer extends Model constructor: (params) -> super - {@config, @confirm} = params + {@config, notificationManager, deserializerManager, confirm} = params @emitter = new Emitter @subscriptions = new CompositeDisposable @itemRegistry = new ItemRegistry - @setRoot(new Pane({container: this, @config, @confirm})) + @setRoot(new Pane({container: this, @config, notificationManager, deserializerManager, confirm})) @setActivePane(@getRoot()) @monitorActivePaneItem() @monitorPaneItems() diff --git a/src/pane.coffee b/src/pane.coffee index f1af017de..beb6a4136 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -14,7 +14,7 @@ class Pane extends Model activeItem: undefined focused: false - @deserialize: (state, {deserializers}) -> + @deserialize: (state, {deserializers, config, notifications, confirm}) -> {items, activeItemURI, activeItemUri} = state activeItemURI ?= activeItemUri state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState)) @@ -22,13 +22,20 @@ class Pane extends Model if typeof item.getURI is 'function' itemURI = item.getURI() itemURI is activeItemURI - new this(state) + new Pane(extend(state, { + deserializerManager: deserializers, + notificationManager: notifications, + confirm: confirm, + config: config + })) constructor: (params) -> super - @activeItem = params?.activeItem - @focused = params?.focused + { + @activeItem, @focused, @confirm, @notificationManager, @config, + @deserializerManager + } = params @emitter = new Emitter @itemSubscriptions = new WeakMap @@ -390,7 +397,7 @@ class Pane extends Model @items.splice(index, 1) @emitter.emit 'did-remove-item', {item, index, destroyed: not moved, moved} @container?.didDestroyPaneItem({item, index, pane: this}) unless moved - @destroy() if @items.length is 0 and atom.config.get('core.destroyEmptyPanes') + @destroy() if @items.length is 0 and @config.get('core.destroyEmptyPanes') # Public: Move the given item to the given index. # @@ -456,7 +463,7 @@ class Pane extends Model else return true - chosen = atom.confirm + chosen = @confirm message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?" detailedMessage: "Your changes will be lost if you close this item without saving." buttons: ["Save", "Cancel", "Don't Save"] @@ -549,7 +556,7 @@ class Pane extends Model copyActiveItem: -> if @activeItem? - @activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize()) + @activeItem.copy?() ? @deserializerManager.deserialize(@activeItem.serialize()) ### Section: Lifecycle @@ -641,7 +648,7 @@ class Pane extends Model @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this], @flexScale})) @setFlexScale(1) - newPane = new @constructor(params) + newPane = new Pane(extend({@confirm, @deserializerManager, @config}, params)) switch side when 'before' then @parent.insertChildBefore(this, newPane) when 'after' then @parent.insertChildAfter(this, newPane) @@ -683,12 +690,12 @@ class Pane extends Model handleSaveError: (error, item) -> itemPath = error.path ? item?.getPath?() - addWarningWithPath = (message, options) -> + addWarningWithPath = (message, options) => message = "#{message} '#{itemPath}'" if itemPath - atom.notifications.addWarning(message, options) + @notificationManager.addWarning(message, options) if error.code is 'EISDIR' or error.message?.endsWith?('is a directory') - atom.notifications.addWarning("Unable to save file: #{error.message}") + @notificationManager.addWarning("Unable to save file: #{error.message}") else if error.code is 'EACCES' addWarningWithPath('Unable to save file: Permission denied') else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST'] @@ -711,6 +718,6 @@ class Pane extends Model addWarningWithPath('Unable to save file: Invalid seek') else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message) fileName = errorMatch[1] - atom.notifications.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to") + @notificationManager.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to") else throw error diff --git a/src/workspace.coffee b/src/workspace.coffee index ff7f14738..6d87fbbf4 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -29,14 +29,14 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, - @setDocumentEdited, @assert, @confirm + @setDocumentEdited, @assert, @confirm, deserializerManager } = params @emitter = new Emitter @openers = [] @destroyedItemURIs = [] - @paneContainer = new PaneContainer({@config, @confirm}) + @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, deserializerManager}) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @directorySearchers = [] From 75463829f9c715a81ca7ad0c1a0d70da06ea47e2 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Oct 2015 17:26:19 -0700 Subject: [PATCH 158/316] Pass inDevMode to package-manager as a boolean value Rather than as a bound function --- spec/package-spec.coffee | 11 ++++++++--- src/atom-environment.coffee | 6 +++++- src/package.coffee | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index e3b94830b..248190af3 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -4,7 +4,14 @@ ThemePackage = require '../src/theme-package' describe "Package", -> build = (constructor, path) -> - new constructor(path: path, packageManager: atom.packages, config: atom.config, styleManager: atom.styles, notificationManager: atom.notifications, keymapManager: atom.keymaps, commandRegistry: atom.command, grammarRegistry: atom.grammars, themeManager: atom.themes, menuManager: atom.menu, contextMenuManager: atom.contextMenu, inDevMode: atom.inDevMode) + new constructor( + path: path, packageManager: atom.packages, config: atom.config, + styleManager: atom.styles, notificationManager: atom.notifications, + keymapManager: atom.keymaps, commandRegistry: atom.command, + grammarRegistry: atom.grammars, themeManager: atom.themes, + menuManager: atom.menu, contextMenuManager: atom.contextMenu, + inDevMode: false + ) buildPackage = (packagePath) -> build(Package, packagePath) @@ -12,7 +19,6 @@ describe "Package", -> describe "when the package contains incompatible native modules", -> beforeEach -> - spyOn(atom, 'inDevMode').andReturn(false) items = {} spyOn(global.localStorage, 'setItem').andCallFake (key, item) -> items[key] = item; undefined spyOn(global.localStorage, 'getItem').andCallFake (key) -> items[key] ? null @@ -48,7 +54,6 @@ describe "Package", -> describe "::rebuild()", -> beforeEach -> - spyOn(atom, 'inDevMode').andReturn(false) items = {} spyOn(global.localStorage, 'setItem').andCallFake (key, item) -> items[key] = item; undefined spyOn(global.localStorage, 'getItem').andCallFake (key) -> items[key] ? null diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 3445a0a49..0bf2a5f12 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -144,7 +144,11 @@ class AtomEnvironment extends Model @styles = new StyleManager({configDirPath}) PackageManager = require './package-manager' - @packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications, grammarRegistry: @grammars, inDevMode: @inDevMode.bind(this)}) + @packages = new PackageManager({ + devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, + commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications, + grammarRegistry: @grammars, inDevMode: @inDevMode() + }) ThemeManager = require './theme-manager' @themes = new ThemeManager({ diff --git a/src/package.coffee b/src/package.coffee index e4d803852..d1d63ef2f 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -587,7 +587,7 @@ class Package # This information is cached in local storage on a per package/version basis # to minimize the impact on startup time. getIncompatibleNativeModules: -> - unless @inDevMode() + unless @inDevMode try if arrayAsString = global.localStorage.getItem(@getIncompatibleNativeModulesStorageKey()) return JSON.parse(arrayAsString) From 74c0836be50eb0cf009a858c22f03cb52a65d968 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Oct 2015 17:34:22 -0700 Subject: [PATCH 159/316] :fire: Duplicate devMode/inDevMode parameter to Package, PackageManager --- spec/package-spec.coffee | 2 +- src/atom-environment.coffee | 2 +- src/package-manager.coffee | 12 +++++++++--- src/package.coffee | 10 ++++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index 248190af3..63a80a7db 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -10,7 +10,7 @@ describe "Package", -> keymapManager: atom.keymaps, commandRegistry: atom.command, grammarRegistry: atom.grammars, themeManager: atom.themes, menuManager: atom.menu, contextMenuManager: atom.contextMenu, - inDevMode: false + devMode: false ) buildPackage = (packagePath) -> build(Package, packagePath) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 0bf2a5f12..8d50cda6b 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -147,7 +147,7 @@ class AtomEnvironment extends Model @packages = new PackageManager({ devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications, - grammarRegistry: @grammars, inDevMode: @inDevMode() + grammarRegistry: @grammars }) ThemeManager = require './theme-manager' diff --git a/src/package-manager.coffee b/src/package-manager.coffee index b4af8ecdb..aeabf62a3 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -28,7 +28,12 @@ ThemePackage = require './theme-package' # settings and also by calling `enablePackage()/disablePackage()`. module.exports = class PackageManager - constructor: ({configDirPath, @devMode, safeMode, @resourcePath, @config, @styleManager, @notificationManager, @inDevMode, @keymapManager, @commandRegistry, @grammarRegistry}) -> + constructor: (params) -> + { + configDirPath, @devMode, safeMode, @resourcePath, @config, @styleManager, + @notificationManager, @keymapManager, @commandRegistry, @grammarRegistry + } = params + @emitter = new Emitter @activationHookEmitter = new Emitter @packageDirPaths = [] @@ -365,8 +370,9 @@ class PackageManager return null options = { - path: packagePath, metadata, packageManager: this, - @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry, @themeManager, @menuManager, @contextMenuManager + path: packagePath, metadata, packageManager: this, @config, @styleManager, + @commandRegistry, @keymapManager, @devMode, @notificationManager, + @grammarRegistry, @themeManager, @menuManager, @contextMenuManager } if metadata.theme pack = new ThemePackage(options) diff --git a/src/package.coffee b/src/package.coffee index d1d63ef2f..00963ef28 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -29,7 +29,13 @@ class Package Section: Construction ### - constructor: ({@path, @metadata, @packageManager, @config, @styleManager, @commandRegistry, @keymapManager, @inDevMode, @notificationManager, @grammarRegistry, @themeManager, @menuManager, @contextMenuManager}) -> + constructor: (params) -> + { + @path, @metadata, @packageManager, @config, @styleManager, @commandRegistry, + @keymapManager, @devMode, @notificationManager, @grammarRegistry, @themeManager, + @menuManager, @contextMenuManager + } = params + @emitter = new Emitter @metadata ?= @packageManager.loadPackageMetadata(@path) @bundledPackage = @packageManager.isBundledPackagePath(@path) @@ -587,7 +593,7 @@ class Package # This information is cached in local storage on a per package/version basis # to minimize the impact on startup time. getIncompatibleNativeModules: -> - unless @inDevMode + unless @devMode try if arrayAsString = global.localStorage.getItem(@getIncompatibleNativeModulesStorageKey()) return JSON.parse(arrayAsString) From 5d6713f6fa3508f1a1552d8e2a844838e4971397 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sun, 11 Oct 2015 18:11:54 +0200 Subject: [PATCH 160/316] Pass deserializerManager in Workspace --- spec/spec-helper.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index fa3104090..8a0276415 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -78,7 +78,7 @@ beforeEach -> setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, - assert: atom.assert.bind(atom) + assert: atom.assert.bind(atom), deserializerManager: atom.deserializers }) atom.themes.workspace = atom.workspace From f77f62625e52cfdce410aab9b349dccecf3b7ffd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sun, 11 Oct 2015 18:12:11 +0200 Subject: [PATCH 161/316] Add `activateItem` config to `Workspace::open` Now that we have deleted `Project::open(...)`, all the methods that previously used it need to switch to `Workspace::open(...)` instead. These two methods, however, are not idempotent because the latter performs additional operations. Since some specs relied on not activating an item after opening it, this commit adds a parameter to prevent such activation. Refs: https://github.com/atom/tabs/commit/1ebcf166c73a9d55932a78b1246dbd5a50077ec5 --- src/workspace.coffee | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 6d87fbbf4..743c32e12 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -336,6 +336,8 @@ class Workspace extends Model # item will be opened in the rightmost pane of the current active pane's row. # * `activatePane` A {Boolean} indicating whether to call {Pane::activate} on # containing pane. Defaults to `true`. + # * `activateItem` A {Boolean} indicating whether to call {Pane::activateItem} + # on containing pane. Defaults to `true`. # * `searchAllPanes` A {Boolean}. If `true`, the workspace will attempt to # activate an existing item for the given URI on any pane. # If `false`, only the active pane will be searched for @@ -374,9 +376,12 @@ class Workspace extends Model # initially. Defaults to `0`. # * `activatePane` A {Boolean} indicating whether to call {Pane::activate} on # the containing pane. Defaults to `true`. + # * `activateItem` A {Boolean} indicating whether to call {Pane::activateItem} + # on containing pane. Defaults to `true`. openSync: (uri='', options={}) -> {initialLine, initialColumn} = options activatePane = options.activatePane ? true + activateItem = options.activateItem ? true uri = @project.resolvePath(uri) item = @getActivePane().itemForURI(uri) @@ -384,13 +389,14 @@ class Workspace extends Model item ?= opener(uri, options) for opener in @getOpeners() when not item item ?= @project.openSync(uri, {initialLine, initialColumn}) - @getActivePane().activateItem(item) + @getActivePane().activateItem(item) if activateItem @itemOpened(item) @getActivePane().activate() if activatePane item openURIInPane: (uri, pane, options={}) -> activatePane = options.activatePane ? true + activateItem = options.activateItem ? true if uri? item = pane.itemForURI(uri) @@ -417,7 +423,7 @@ class Workspace extends Model pane = new Pane({items: [item], @config, @confirm}) @paneContainer.root = pane @itemOpened(item) - pane.activateItem(item) + pane.activateItem(item) if activateItem pane.activate() if activatePane initialLine = initialColumn = 0 From e1a1474b8dc7f85e2d516fb9beb695c51c557fea Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sun, 11 Oct 2015 19:27:19 +0200 Subject: [PATCH 162/316] :bug: Clear views after resetting everything else This prevents a bug where calling `::getView` returns two different instances if such method is invoked after views are cleared out (e.g. packages deactivation in `packageManager.reset()`). --- src/atom-environment.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 8d50cda6b..d991312be 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -238,9 +238,6 @@ class AtomEnvironment extends Model @deserializers.clear() @registerDefaultDeserializers() - @views.clear() - @registerDefaultViewProviders() - @config.clear() @setConfigSchema() @@ -264,6 +261,9 @@ class AtomEnvironment extends Model @project.reset(@packages) + @views.clear() + @registerDefaultViewProviders() + @state.packageStates = {} destroy: -> From aebc1229f16b09d77b1a14125c5b935c7123fc85 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 12 Oct 2015 08:29:43 +0200 Subject: [PATCH 163/316] Always install uncaught error handler --- spec/atom-environment-spec.coffee | 4 ---- src/atom-environment.coffee | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index a1847519b..ecce91428 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -48,10 +48,6 @@ describe "AtomEnvironment", -> beforeEach -> spyOn atom, 'openDevTools' spyOn atom, 'executeJavaScriptInDevTools' - atom.installUncaughtErrorHandler() - - afterEach: -> - atom.uninstallUncaughtErrorHandler() it "will open the dev tools when an error is triggered", -> try diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index d991312be..9ca6d3e0b 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -193,6 +193,8 @@ class AtomEnvironment extends Model @registerDefaultDeserializers() @registerDefaultViewProviders() + @installUncaughtErrorHandler() + setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -579,8 +581,6 @@ class AtomEnvironment extends Model # Call this method when establishing a real application window. startEditorWindow: -> - @installUncaughtErrorHandler() - @commandInstaller.installAtomCommand false, (error) -> console.warn error.message if error? @commandInstaller.installApmCommand false, (error) -> From 612664fd4d745d7911ace147308acf7c6c45954a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 12 Oct 2015 09:00:58 +0200 Subject: [PATCH 164/316] :memo: Remember how/when to reset AtomEnviroment::workspace --- src/atom-environment.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 9ca6d3e0b..3cc90cba6 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -261,6 +261,9 @@ class AtomEnvironment extends Model @packages.reset() + # TODO: reset workspace after de-activating packages, but *before* resetting + # @project. + @project.reset(@packages) @views.clear() From 56e13bba694cf1940a7ed343d69d49bcc9de5a84 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 12 Oct 2015 10:39:35 +0200 Subject: [PATCH 165/316] Reset Workspace in AtomEnvironment --- spec/spec-helper.coffee | 14 +++--------- spec/workspace-spec.coffee | 36 ++++++++++++++----------------- src/atom-environment.coffee | 5 +++-- src/workspace-element.coffee | 1 - src/workspace.coffee | 42 ++++++++++++++++++++++++++++++------ 5 files changed, 57 insertions(+), 41 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 8a0276415..52cb9ac37 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -72,14 +72,6 @@ beforeEach -> atom.project.setPaths([path.join(@specDirectory, 'fixtures')]) - atom.workspace = new Workspace({ - config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, - setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: atom.setDocumentEdited.bind(atom), atomVersion: atom.getVersion(), - clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, - assert: atom.assert.bind(atom), deserializerManager: atom.deserializers - }) atom.themes.workspace = atom.workspace atom.workspaceParentSelectorctor = '#jasmine-content' @@ -137,10 +129,10 @@ beforeEach -> addCustomMatchers(this) afterEach -> - atom.workspace?.destroy() - atom.workspace = null + # unless jasmine.getEnv().currentSpec.results().passed() + # jasmine.getEnv().specFilter = -> false + # atom.themes.workspace = null - delete atom.state.workspace atom.reset() diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index fc5fb5fff..1a1ed0aad 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -12,18 +12,11 @@ describe "Workspace", -> [workspace, setDocumentEdited] = [] beforeEach -> - spyOn(atom, 'confirm') - - setDocumentEdited = jasmine.createSpy('setDocumentEdited') + workspace = atom.workspace + workspace.resetFontSize() + spyOn(workspace, "confirm") + setDocumentEdited = spyOn(workspace, 'setDocumentEdited') atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) - atom.workspace = workspace = new Workspace({ - config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, deserializerManager: atom.deserializers, - clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, - setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), - assert: atom.assert.bind(atom), confirm: atom.confirm.bind(atom) - }) waits(1) describe "serialization", -> @@ -32,14 +25,16 @@ describe "Workspace", -> projectState = atom.project.serialize() atom.workspace.destroy() atom.project.destroy() - atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm}) + atom.project = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm.bind(atom)}) atom.project.deserialize(projectState, atom.deserializers) atom.workspace = new Workspace({ config: atom.config, project: atom.project, packageManager: atom.packages, - notificationManager: atom.notifications, deserializerManager: atom.deserializers, - clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, - setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, assert: atom.assert.bind(atom) + grammarRegistry: atom.grammars, deserializerManager: atom.deserializers, + notificationManager: atom.notifications, clipboard: atom.clipboard, + setRepresentedFilename: atom.setRepresentedFilename.bind(atom), + setDocumentEdited: atom.setDocumentEdited.bind(atom), + viewRegistry: atom.views, assert: atom.assert.bind(atom), + confirm: atom.confirm.bind(atom) }) atom.workspace.deserialize(workspaceState, atom.deserializers) @@ -352,7 +347,8 @@ describe "Workspace", -> describe "when the file is over 20MB", -> it "prompts the user to make sure they want to open a file this big", -> spyOn(fs, 'getSizeSync').andReturn 20 * 1048577 # 20MB - atom.confirm.andCallFake -> selectedButtonIndex + workspace.confirm.andCallFake -> selectedButtonIndex + atom.workspace.confirm() selectedButtonIndex = 1 # cancel editor = null @@ -361,16 +357,16 @@ describe "Workspace", -> runs -> expect(editor).toBeUndefined() - expect(atom.confirm).toHaveBeenCalled() + expect(workspace.confirm).toHaveBeenCalled() - atom.confirm.reset() + workspace.confirm.reset() selectedButtonIndex = 0 # open the file waitsForPromise -> workspace.open('sample.js').then (e) -> editor = e runs -> - expect(atom.confirm).toHaveBeenCalled() + expect(workspace.confirm).toHaveBeenCalled() expect(editor.displayBuffer.largeFileMode).toBe true describe "when passed a path that matches a custom opener", -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 3cc90cba6..efb18d291 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -261,8 +261,8 @@ class AtomEnvironment extends Model @packages.reset() - # TODO: reset workspace after de-activating packages, but *before* resetting - # @project. + @workspace.reset(@packages) + @registerDefaultOpeners() @project.reset(@packages) @@ -270,6 +270,7 @@ class AtomEnvironment extends Model @registerDefaultViewProviders() @state.packageStates = {} + delete @state.workspace destroy: -> return if not @project diff --git a/src/workspace-element.coffee b/src/workspace-element.coffee index c1d1f8f14..fb4b19dc3 100644 --- a/src/workspace-element.coffee +++ b/src/workspace-element.coffee @@ -13,7 +13,6 @@ class WorkspaceElement extends HTMLElement detachedCallback: -> @subscriptions.dispose() - @model.destroy() initializeContent: -> @classList.add 'workspace' diff --git a/src/workspace.coffee b/src/workspace.coffee index 743c32e12..6f0cc4ca1 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -29,22 +29,18 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, @clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, - @setDocumentEdited, @assert, @confirm, deserializerManager + @setDocumentEdited, @assert, @confirm, @deserializerManager } = params @emitter = new Emitter @openers = [] @destroyedItemURIs = [] - @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, deserializerManager}) + @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, @deserializerManager}) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) - @directorySearchers = [] @defaultDirectorySearcher = new DefaultDirectorySearcher() - @packageManager.serviceHub.consume( - 'atom.directory-searcher', - '^0.1.0', - (provider) => @directorySearchers.unshift(provider)) + @consumeServices(@packageManager) @panelContainers = top: new PanelContainer({location: 'top'}) @@ -56,6 +52,38 @@ class Workspace extends Model @subscribeToActiveItem() @subscribeToFontSize() + reset: (@packageManager) -> + @emitter.dispose() + @emitter = new Emitter + + @paneContainer.destroy() + panelContainer.destroy() for panelContainer in @panelContainers + + @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, @deserializerManager}) + @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) + + @panelContainers = + top: new PanelContainer({location: 'top'}) + left: new PanelContainer({location: 'left'}) + right: new PanelContainer({location: 'right'}) + bottom: new PanelContainer({location: 'bottom'}) + modal: new PanelContainer({location: 'modal'}) + + @originalFontSize = null + @openers = [] + @destroyedItemURIs = [] + @consumeServices(@packageManager) + + @subscribeToActiveItem() + @subscribeToFontSize() + + consumeServices: ({serviceHub}) -> + @directorySearchers = [] + serviceHub.consume( + 'atom.directory-searcher', + '^0.1.0', + (provider) => @directorySearchers.unshift(provider)) + # Called by the Serializable mixin during serialization. serialize: -> deserializer: 'Workspace' From 304d35a30023d08c8a31d4d25a95bcdd4060c39d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 12 Oct 2015 15:39:56 +0200 Subject: [PATCH 166/316] Shim process stdout and stderr --- src/initialize-test-window.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 405d6901a..4744f8544 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -30,6 +30,10 @@ try require('module').globalPaths.push(exportsPath) process.env.NODE_PATH = exportsPath # Set NODE_PATH env variable since tasks may need it. + # Shim process stdout and stderr so that they can be logged out to console. + process.stdout = remote.process.stdout + process.stderr = remote.process.stderr + document.title = "Spec Suite" legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) From 3ee0be33d5e25c3305ebeae3488a483a629077a5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 12 Oct 2015 19:46:12 +0200 Subject: [PATCH 167/316] :racehorse: Speed up test suite by disposing Project::emitter --- src/atom-environment.coffee | 4 ++-- src/project.coffee | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index efb18d291..a4acb57d0 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -261,11 +261,11 @@ class AtomEnvironment extends Model @packages.reset() + @project.reset(@packages) + @workspace.reset(@packages) @registerDefaultOpeners() - @project.reset(@packages) - @views.clear() @registerDefaultViewProviders() diff --git a/src/project.coffee b/src/project.coffee index 7de4c6b69..645a54896 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -38,7 +38,10 @@ class Project extends Model @setPaths([]) reset: (packageManager) -> - buffer.destroy() for buffer in @buffers + @emitter.dispose() + @emitter = new Emitter + + buffer?.destroy() for buffer in @buffers @buffers = [] @setPaths([]) @consumeServices(packageManager) From 29fe98581e91911588704c1d88f1dcf658a00eb0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 12 Oct 2015 13:54:35 -0600 Subject: [PATCH 168/316] =?UTF-8?q?Don=E2=80=99t=20assign=20atom.themes.wo?= =?UTF-8?q?rkspace=20in=20spec-helper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/spec-helper.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 52cb9ac37..7953563e7 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -72,8 +72,6 @@ beforeEach -> atom.project.setPaths([path.join(@specDirectory, 'fixtures')]) - atom.themes.workspace = atom.workspace - atom.workspaceParentSelectorctor = '#jasmine-content' window.resetTimeouts() @@ -132,8 +130,6 @@ afterEach -> # unless jasmine.getEnv().currentSpec.results().passed() # jasmine.getEnv().specFilter = -> false # - atom.themes.workspace = null - atom.reset() document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent From c82e331b7d5fc5bc9c5a6564f60c96697d9c4dea Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 12 Oct 2015 14:12:13 -0600 Subject: [PATCH 169/316] Return a Disposable from mocked method to avoid exception it specs --- spec/text-editor-element-spec.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/text-editor-element-spec.coffee b/spec/text-editor-element-spec.coffee index 251c178e7..e7d5831eb 100644 --- a/spec/text-editor-element-spec.coffee +++ b/spec/text-editor-element-spec.coffee @@ -1,5 +1,6 @@ TextEditorElement = require '../src/text-editor-element' TextEditor = require '../src/text-editor' +{Disposable} = require 'event-kit' # The rest of text-editor-component-spec will be moved to this file when React # is eliminated. This covers only concerns related to the wrapper element for now @@ -159,6 +160,7 @@ describe "TextEditorElement", -> initialThemeLoadComplete spyOn(atom.themes, 'onDidChangeActiveThemes').andCallFake (fn) -> themeReloadCallback = fn + new Disposable atom.config.set("editor.useShadowDOM", false) From 79d9a13ea71e23af9942e412b839ea30198aab81 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 12 Oct 2015 15:01:18 -0600 Subject: [PATCH 170/316] Fix ENOENT exceptions in text-editor-spec --- spec/text-editor-spec.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index 7929bddda..92a6435e8 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -114,7 +114,7 @@ describe "TextEditor", -> atom.config.set('core.fileEncoding', 'utf16le') waitsForPromise -> - atom.workspace.open('a').then (o) -> editor1 = o + atom.workspace.open('dir/a').then (o) -> editor1 = o runs -> expect(editor1.getTabLength()).toBe 4 @@ -128,7 +128,7 @@ describe "TextEditor", -> atom.config.set('core.fileEncoding', 'macroman') waitsForPromise -> - atom.workspace.open('b').then (o) -> editor2 = o + atom.workspace.open('dir/b').then (o) -> editor2 = o runs -> expect(editor2.getTabLength()).toBe 8 @@ -144,13 +144,13 @@ describe "TextEditor", -> atom.config.set('core.fileEncoding', 'macroman', scopeSelector: '.js') waitsForPromise -> - atom.workspace.open('a').then (o) -> editor1 = o + atom.workspace.open('dir/a').then (o) -> editor1 = o runs -> expect(editor1.getEncoding()).toBe 'utf16le' waitsForPromise -> - atom.workspace.open('test.js').then (o) -> editor2 = o + atom.workspace.open('sample-with-comments.js').then (o) -> editor2 = o runs -> expect(editor2.getEncoding()).toBe 'macroman' From 69e8b0cfb1a824d492f9b7856aa389243e9324c8 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 12 Oct 2015 15:19:55 -0600 Subject: [PATCH 171/316] Prevent title change during specs --- spec/atom-environment-spec.coffee | 4 ++-- spec/jasmine-test-runner.coffee | 10 ++++++++-- spec/spec-helper.coffee | 7 ------- src/atom-environment.coffee | 5 ++++- src/initialize-test-window.coffee | 2 +- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index ecce91428..7edce76ce 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -213,7 +213,7 @@ describe "AtomEnvironment", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> - atomEnvironment = new AtomEnvironment + atomEnvironment = new AtomEnvironment(setRepresentedFilename: ->) spyOn(atomEnvironment, 'saveStateSync') workspaceState = atomEnvironment.workspace.serialize() @@ -229,7 +229,7 @@ describe "AtomEnvironment", -> describe "::destroy()", -> it "unsubscribes from all buffers", -> - atomEnvironment = new AtomEnvironment + atomEnvironment = new AtomEnvironment(setRepresentedFilename: ->) waitsForPromise -> atomEnvironment.workspace.open("sample.js") diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index a245379e2..a8d165562 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -5,11 +5,17 @@ path = require 'path' ipc = require 'ipc' module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> - window.atom = buildAtomEnvironment() - window[key] = value for key, value of require '../vendor/jasmine' require 'jasmine-tagged' + # Allow document.title to be assigned in specs without screwing up spec window title + documentTitle = null + Object.defineProperty document, 'title', + get: -> documentTitle + set: (title) -> documentTitle = title + + window.atom = buildAtomEnvironment({setRepresentedFilename: jasmine.createSpy('setRepresentedFilename')}) + require './spec-helper' disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI requireSpecs(testPath) for testPath in testPaths diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 7953563e7..a9446fa93 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -28,12 +28,6 @@ atom.packages.packageDirPaths.unshift(fixturePackagesPath) document.querySelector('html').style.overflow = 'auto' document.body.style.overflow = 'auto' -# Allow document.title to be assigned in specs without screwing up spec window title -documentTitle = null -Object.defineProperty document, 'title', - get: -> documentTitle - set: (title) -> documentTitle = title - Set.prototype.jasmineToString = -> result = "Set {" first = true @@ -112,7 +106,6 @@ beforeEach -> # make editor display updates synchronous TextEditorElement::setUpdatedSynchronously(true) - spyOn(atom, "setRepresentedFilename") spyOn(pathwatcher.File.prototype, "detectResurrectionAfterDelay").andCallFake -> @detectResurrection() spyOn(TextEditor.prototype, "shouldPromptToSave").andReturn false diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index a4acb57d0..a1619deec 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -104,7 +104,10 @@ class AtomEnvironment extends Model ### # Call .loadOrCreate instead - constructor: -> + constructor: (params={}) -> + {setRepresentedFilename} = params + @setRepresentedFilename = setRepresentedFilename if setRepresentedFilename? + @state = {version: @constructor.version} @loadTime = null diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 4744f8544..28e22c0d6 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -42,7 +42,7 @@ try logFile: getWindowLoadSettings().logFile headless: getWindowLoadSettings().headless testPaths: getWindowLoadSettings().testPaths - buildAtomEnvironment: -> new AtomEnvironment + buildAtomEnvironment: (params) -> new AtomEnvironment(params) legacyTestRunner: legacyTestRunner }) catch error From f7a3e6c425ca69c3c8a4063319cc6ea3d18bc447 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 12 Oct 2015 16:12:46 -0600 Subject: [PATCH 172/316] =?UTF-8?q?Don=E2=80=99t=20load=20base=20style=20s?= =?UTF-8?q?heets=20until=20config=20is=20loaded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to know what themes are active in order to load the correct LESS variables. --- spec/spec-helper.coffee | 4 +++- src/atom-environment.coffee | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index a9446fa93..95665efa5 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -20,6 +20,8 @@ jasmineStyle = document.createElement('style') jasmineStyle.textContent = atom.themes.loadStylesheet(atom.themes.resolveStylesheet('../static/jasmine')) document.head.appendChild(jasmineStyle) +atom.themes.loadBaseStylesheets() +initialStyleElements = atom.styles.getSnapshot() atom.themes.initialLoadComplete = true fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') @@ -123,7 +125,7 @@ afterEach -> # unless jasmine.getEnv().currentSpec.results().passed() # jasmine.getEnv().specFilter = -> false # - atom.reset() + atom.reset(stylesSnapshot: initialStyleElements) document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index a1619deec..00b50456e 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -185,9 +185,6 @@ class AtomEnvironment extends Model }) @themes.workspace = @workspace - @themes.loadBaseStylesheets() - @initialStyleElements = @styles.getSnapshot() - @keymaps.subscribeToFileReadFailure() @keymaps.loadBundledKeymaps() @@ -239,7 +236,7 @@ class AtomEnvironment extends Model when 'atom://.atom/init-script' @workspace.open(@getUserInitScriptPath()) - reset: -> + reset: (params) -> @deserializers.clear() @registerDefaultDeserializers() @@ -252,7 +249,7 @@ class AtomEnvironment extends Model @commands.clear() registerDefaultCommands(this) - @styles.restoreSnapshot(@initialStyleElements) + @styles.restoreSnapshot(params?.stylesSnapshot ? []) @menu.clear() @@ -594,6 +591,7 @@ class AtomEnvironment extends Model console.warn error.message if error? @config.load() + @themes.loadBaseStylesheets() @setBodyPlatformClass() document.head.appendChild(@styles.buildStylesElement()) From 4a59da91944bf20c3102bf30a655b835f653fb5f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 08:35:02 +0200 Subject: [PATCH 173/316] Express timeout in seconds --- src/browser/atom-application.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 2e534e7c8..b183bcb14 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -497,12 +497,12 @@ class AtomApplication if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath - timeout = Number.parseFloat(timeout) - unless Number.isNaN(timeout) + timeoutInSeconds = Number.parseFloat(timeout) + unless Number.isNaN(timeoutInSeconds) timeoutHandler = -> - console.log "The test suite has timed out because it has been running for more than #{timeout} minutes." + console.log "The test suite has timed out because it has been running for more than #{timeoutInSeconds} seconds." process.exit(124) # Use the same exit code as the UNIX timeout util. - setTimeout(timeoutHandler, timeout * 60 * 1000) + setTimeout(timeoutHandler, timeoutInSeconds * 1000) try windowInitializationScript = require.resolve(path.resolve(@devResourcePath, 'src', 'initialize-test-window')) From cf5d94f084597b960bfd4f6c40424c07a9883df5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 09:02:37 +0200 Subject: [PATCH 174/316] Return a promise in test runners --- spec/jasmine-test-runner.coffee | 18 +++++++++++------- src/initialize-test-window.coffee | 13 +++++++++---- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index a8d165562..dec7652a8 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -22,8 +22,10 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> setSpecType('user') + resolveWithExitCode = null + promise = new Promise (resolve, reject) -> resolveWithExitCode = resolve jasmineEnv = jasmine.getEnv() - jasmineEnv.addReporter(buildReporter({logFile, headless})) + jasmineEnv.addReporter(buildReporter({logFile, headless, resolveWithExitCode})) TimeReporter = require './time-reporter' jasmineEnv.addReporter(new TimeReporter()) jasmineEnv.setIncludedTags([process.platform]) @@ -37,6 +39,7 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> atom.commands.attach(window) jasmineEnv.execute() + promise disableFocusMethods = -> ['fdescribe', 'ffdescribe', 'fffdescribe', 'fit', 'ffit', 'fffit'].forEach (methodName) -> @@ -68,14 +71,14 @@ setSpecType = (specType) -> setSpecDirectory = (specDirectory) -> setSpecField('specDirectory', specDirectory) -buildReporter = ({logFile, headless}) -> +buildReporter = ({logFile, headless, resolveWithExitCode}) -> if headless - buildTerminalReporter(logFile) + buildTerminalReporter(logFile, resolveWithExitCode) else AtomReporter = require './atom-reporter' reporter = new AtomReporter() -buildTerminalReporter = (logFile) -> +buildTerminalReporter = (logFile, resolveWithExitCode) -> logStream = fs.openSync(logFile, 'w') if logFile? log = (str) -> if logStream? @@ -94,9 +97,10 @@ buildTerminalReporter = (logFile) -> if grim.getDeprecationsLength() > 0 grim.logDeprecations() - return atom.exit(1) + resolveWithExitCode(1) + return if runner.results().failedCount > 0 - atom.exit(1) + resolveWithExitCode(1) else - atom.exit(0) + resolveWithExitCode(0) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 28e22c0d6..b3d85e423 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -1,10 +1,14 @@ # Start the crash reporter before anything else. require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') +remote = require 'remote' + +exitWithStatusCode = (status) => + remote.require('app').emit('will-exit') + remote.process.exit(status) try path = require 'path' ipc = require 'ipc' - remote = require 'remote' {getWindowLoadSettings} = require './window-load-settings-helpers' AtomEnvironment = require '../src/atom-environment' @@ -38,17 +42,18 @@ try legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) testRunner = require(getWindowLoadSettings().testRunnerPath) - testRunner({ + promise = testRunner({ logFile: getWindowLoadSettings().logFile headless: getWindowLoadSettings().headless testPaths: getWindowLoadSettings().testPaths buildAtomEnvironment: (params) -> new AtomEnvironment(params) legacyTestRunner: legacyTestRunner }) + + promise.then(exitWithStatusCode) if getWindowLoadSettings().headless catch error if getWindowLoadSettings().headless console.error(error.stack ? error) - remote.require('app').emit('will-exit') - remote.process.exit(status) + exitWithStatusCode(1) else throw error From dbf65b4d9760609ea7427199991759ae70565aa3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 10:44:13 +0200 Subject: [PATCH 175/316] :arrow_up: Bump dependencies --- package.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index b54222510..6170b2b65 100644 --- a/package.json +++ b/package.json @@ -75,10 +75,10 @@ "autocomplete-atom-api": "0.9.2", "autocomplete-css": "0.11.0", "autocomplete-html": "0.7.2", - "autocomplete-plus": "2.22.0", + "autocomplete-plus": "2.23.0", "autocomplete-snippets": "1.7.1", "autoflow": "0.26.0", - "autosave": "0.22.0", + "autosave": "0.23.0", "background-tips": "0.26.0", "bookmarks": "0.38.0", "bracket-matcher": "0.78.0", @@ -87,7 +87,7 @@ "dev-live-reload": "0.47.0", "encoding-selector": "0.21.0", "exception-reporting": "0.37.0", - "find-and-replace": "0.185.0", + "find-and-replace": "0.186.0", "fuzzy-finder": "0.90.0", "git-diff": "0.56.0", "go-to-line": "0.30.0", @@ -97,26 +97,26 @@ "keybinding-resolver": "0.33.0", "line-ending-selector": "0.0.5", "link": "0.31.0", - "markdown-preview": "0.154.0", + "markdown-preview": "0.155.0", "metrics": "0.52.0", "notifications": "0.59.0", "open-on-github": "0.38.0", "package-generator": "0.40.0", "release-notes": "0.53.0", "settings-view": "0.229.0", - "snippets": "0.100.0", + "snippets": "0.101.0", "spell-check": "0.61.0", "status-bar": "0.79.0", "styleguide": "0.44.0", "symbols-view": "0.109.0", - "tabs": "0.84.0", + "tabs": "0.85.0", "timecop": "0.33.0", "tree-view": "0.190.0", "update-package-dependencies": "0.10.0", - "welcome": "0.30.0", + "welcome": "0.31.0", "whitespace": "0.31.0", "wrap-guide": "0.38.0", - "language-c": "0.48.0", + "language-c": "0.49.0", "language-clojure": "0.18.0", "language-coffee-script": "0.42.0", "language-csharp": "0.11.0", @@ -127,14 +127,14 @@ "language-html": "0.42.0", "language-hyperlink": "0.14.0", "language-java": "0.16.0", - "language-javascript": "0.96.0", + "language-javascript": "0.97.0", "language-json": "0.17.0", "language-less": "0.28.2", "language-make": "0.19.0", "language-mustache": "0.13.0", "language-objective-c": "0.15.0", "language-perl": "0.30.0", - "language-php": "0.30.0", + "language-php": "0.31.0", "language-property-list": "0.8.0", "language-python": "0.40.0", "language-ruby": "0.60.0", From 3ac0656a26bf3f2f25dea23cbb92b32c0f90258b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 11:29:51 +0200 Subject: [PATCH 176/316] Reset Workspace before Project Otherwise some paths will be leaked. --- src/atom-environment.coffee | 6 ++++-- src/workspace.coffee | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 00b50456e..380ba722f 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -261,11 +261,13 @@ class AtomEnvironment extends Model @packages.reset() - @project.reset(@packages) - @workspace.reset(@packages) @registerDefaultOpeners() + @project.reset(@packages) + + @workspace.subscribeToEvents() + @views.clear() @registerDefaultViewProviders() diff --git a/src/workspace.coffee b/src/workspace.coffee index 37f4ac5a6..0a66c226a 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -49,8 +49,7 @@ class Workspace extends Model bottom: new PanelContainer({location: 'bottom'}) modal: new PanelContainer({location: 'modal'}) - @subscribeToActiveItem() - @subscribeToFontSize() + @subscribeToEvents() reset: (@packageManager) -> @emitter.dispose() @@ -74,6 +73,7 @@ class Workspace extends Model @destroyedItemURIs = [] @consumeServices(@packageManager) + subscribeToEvents: -> @subscribeToActiveItem() @subscribeToFontSize() From e51bad5618fe445bd9b1786c522da20265648796 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 12:33:58 +0200 Subject: [PATCH 177/316] :bug: Install WindowEventHandler in ctor --- spec/window-event-handler-spec.coffee | 1 + src/atom-environment.coffee | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index dd3b6031a..57ce1468b 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -10,6 +10,7 @@ describe "WindowEventHandler", -> [projectPath, windowEventHandler] = [] beforeEach -> + atom.windowEventHandler.unsubscribe() spyOn(atom, 'hide') initialPath = atom.project.getPaths()[0] spyOn(atom, 'getLoadSettings').andCallFake -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 380ba722f..2cc13f48b 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -194,6 +194,7 @@ class AtomEnvironment extends Model @registerDefaultViewProviders() @installUncaughtErrorHandler() + @windowEventHandler = new WindowEventHandler(this) setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -597,7 +598,6 @@ class AtomEnvironment extends Model @setBodyPlatformClass() document.head.appendChild(@styles.buildStylesElement()) - @windowEventHandler = new WindowEventHandler(this) @packages.loadPackages() From 1df90a220e32eeabdd08ec992f93f5ab47a50585 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 13:59:51 +0200 Subject: [PATCH 178/316] :arrow_up: Bump more dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6170b2b65..6c5273809 100644 --- a/package.json +++ b/package.json @@ -87,8 +87,8 @@ "dev-live-reload": "0.47.0", "encoding-selector": "0.21.0", "exception-reporting": "0.37.0", - "find-and-replace": "0.186.0", - "fuzzy-finder": "0.90.0", + "find-and-replace": "0.187.0", + "fuzzy-finder": "0.91.0", "git-diff": "0.56.0", "go-to-line": "0.30.0", "grammar-selector": "0.47.0", From 6459891c89ac299da84b678ddfa541101c17a3e0 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 15:30:45 +0200 Subject: [PATCH 179/316] :green_heart: Make sure to destroy AtomEnvironment in specs --- spec/atom-environment-spec.coffee | 2 ++ spec/window-event-handler-spec.coffee | 3 ++- src/atom-environment.coffee | 10 ++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 7edce76ce..6d3d7ff04 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -227,6 +227,8 @@ describe "AtomEnvironment", -> expect(atomEnvironment.state.project).toEqual projectState expect(atomEnvironment.saveStateSync).toHaveBeenCalled() + atomEnvironment.destroy() + describe "::destroy()", -> it "unsubscribes from all buffers", -> atomEnvironment = new AtomEnvironment(setRepresentedFilename: ->) diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 57ce1468b..76dd9ef6b 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -10,7 +10,7 @@ describe "WindowEventHandler", -> [projectPath, windowEventHandler] = [] beforeEach -> - atom.windowEventHandler.unsubscribe() + atom.uninstallWindowEventHandler() spyOn(atom, 'hide') initialPath = atom.project.getPaths()[0] spyOn(atom, 'getLoadSettings').andCallFake -> @@ -23,6 +23,7 @@ describe "WindowEventHandler", -> afterEach -> windowEventHandler.unsubscribe() + atom.installWindowEventHandler() describe "when the window is loaded", -> it "doesn't have .is-blurred on the body tag", -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 2cc13f48b..cee3002f0 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -194,7 +194,7 @@ class AtomEnvironment extends Model @registerDefaultViewProviders() @installUncaughtErrorHandler() - @windowEventHandler = new WindowEventHandler(this) + @installWindowEventHandler() setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -284,7 +284,7 @@ class AtomEnvironment extends Model @project?.destroy() @project = null - @windowEventHandler?.unsubscribe() + @uninstallWindowEventHandler() ### Section: Event Subscription @@ -661,6 +661,12 @@ class AtomEnvironment extends Model uninstallUncaughtErrorHandler: -> window.onerror = @previousWindowErrorHandler + installWindowEventHandler: -> + @windowEventHandler = new WindowEventHandler(this) + + uninstallWindowEventHandler: -> + @windowEventHandler?.unsubscribe() + ### Section: Messaging the User ### From 695fad501ce0bcda680c9bfb9527f7402d25a430 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 13 Oct 2015 19:04:57 +0200 Subject: [PATCH 180/316] :arrow_up: find-and-replace --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c5273809..db13e1f14 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "dev-live-reload": "0.47.0", "encoding-selector": "0.21.0", "exception-reporting": "0.37.0", - "find-and-replace": "0.187.0", + "find-and-replace": "0.187.1", "fuzzy-finder": "0.91.0", "git-diff": "0.56.0", "go-to-line": "0.30.0", From 47961a8e6b0e0b0fc898538bb73e8dd6dd68af10 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 13 Oct 2015 11:00:53 -0700 Subject: [PATCH 181/316] Fix setting default values in config --- package.json | 2 +- spec/config-spec.coffee | 38 ++++++++++++++++++++++++++++---------- src/config.coffee | 19 +++++++++++++------ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index dbc569bee..0a7933b8e 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "jasmine-json": "~0.0", "jasmine-tagged": "^1.1.4", "jquery": "^2.1.1", - "key-path-helpers": "^0.3.0", + "key-path-helpers": "^0.4.0", "less-cache": "0.22", "marked": "^0.3.4", "normalize-package-data": "^2.0.0", diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 5aff0eff2..7a2e9e5a0 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -153,13 +153,27 @@ describe "Config", -> describe "when the value equals the default value", -> it "does not store the value in the user's config", -> - atom.config.setDefaults "foo", - same: 1 - changes: 1 - sameArray: [1, 2, 3] - sameObject: {a: 1, b: 2} - null: null - undefined: undefined + atom.config.setSchema "foo", + type: 'object' + properties: + same: + type: 'number' + default: 1 + changes: + type: 'number' + default: 1 + sameArray: + type: 'array' + default: [1, 2, 3] + sameObject: + type: 'object' + default: {a: 1, b: 2} + null: + type: '*' + default: null + undefined: + type: '*' + default: undefined expect(atom.config.settings.foo).toBeUndefined() atom.config.set('foo.same', 1) @@ -169,11 +183,15 @@ describe "Config", -> atom.config.set('foo.undefined', null) atom.config.set('foo.sameObject', {b: 2, a: 1}) - expect(atom.config.get("foo.same", sources: [atom.config.getUserConfigPath()])).toBeUndefined() + userConfigPath = atom.config.getUserConfigPath() + + expect(atom.config.get("foo.same", sources: [userConfigPath])).toBeUndefined() + + expect(atom.config.get("foo.changes")).toBe 2 + expect(atom.config.get("foo.changes", sources: [userConfigPath])).toBe 2 - expect(atom.config.get("foo.changes", sources: [atom.config.getUserConfigPath()])).toBe 2 atom.config.set('foo.changes', 1) - expect(atom.config.get("foo.changes", sources: [atom.config.getUserConfigPath()])).toBeUndefined() + expect(atom.config.get("foo.changes", sources: [userConfigPath])).toBeUndefined() describe "when a 'scopeSelector' is given", -> it "sets the value and overrides the others", -> diff --git a/src/config.coffee b/src/config.coffee index 176390869..b0579716b 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -5,7 +5,10 @@ CSON = require 'season' path = require 'path' async = require 'async' pathWatcher = require 'pathwatcher' -{pushKeyPath, splitKeyPath, getValueAtKeyPath, setValueAtKeyPath} = require 'key-path-helpers' +{ + getValueAtKeyPath, setValueAtKeyPath, deleteValueAtKeyPath, + pushKeyPath, splitKeyPath, +} = require 'key-path-helpers' Color = require './color' ScopedPropertyStore = require 'scoped-property-store' @@ -832,12 +835,16 @@ class Config setRawValue: (keyPath, value) -> defaultValue = getValueAtKeyPath(@defaultSettings, keyPath) - value = undefined if _.isEqual(defaultValue, value) - - if keyPath? - setValueAtKeyPath(@settings, keyPath, value) + if _.isEqual(defaultValue, value) + if keyPath? + deleteValueAtKeyPath(@settings, keyPath) + else + @settings = null else - @settings = value + if keyPath? + setValueAtKeyPath(@settings, keyPath, value) + else + @settings = value @emitChangeEvent() observeKeyPath: (keyPath, options, callback) -> From a8ca3165a03e83e0f0e3032b9e0045b91531fffd Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 14:41:52 -0600 Subject: [PATCH 182/316] Remove dead code --- spec/spec-helper.coffee | 17 +---------------- src/atom-environment.coffee | 3 --- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 95665efa5..7d81541a4 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -56,11 +56,6 @@ if process.env.CI else jasmine.getEnv().defaultTimeoutInterval = 5000 -specPackageName = null -specPackagePath = null -specProjectPath = null -isCoreSpec = false - {resourcePath} = atom.getLoadSettings() beforeEach -> @@ -75,17 +70,10 @@ beforeEach -> spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout - serializedWindowState = null - spyOn(atom, 'saveStateSync') atom.grammars.clearGrammarOverrides() - spy = spyOn(atom.packages, 'resolvePackagePath').andCallFake (packageName) -> - if specPackageName and packageName is specPackageName - resolvePackagePath(specPackagePath) - else - resolvePackagePath(packageName) - resolvePackagePath = _.bind(spy.originalValue, atom.packages) + spyOn(atom.packages, 'resolvePackagePath').andCallThrough() # prevent specs from modifying Atom's menus spyOn(atom.menu, 'sendToBrowserProcess') @@ -122,9 +110,6 @@ beforeEach -> addCustomMatchers(this) afterEach -> - # unless jasmine.getEnv().currentSpec.results().passed() - # jasmine.getEnv().specFilter = -> false - # atom.reset(stylesSnapshot: initialStyleElements) document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index cee3002f0..648abf021 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -747,9 +747,6 @@ class AtomEnvironment extends Model false - deserializeWorkspace: -> - - loadThemes: -> @themes.load() From e92cb86335e76bc6751d01d6a2198d2adcdbb1de Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 15:42:57 -0600 Subject: [PATCH 183/316] Introduce ApplicationDelegate to AtomEnvironment All external actions are performed via this delegate for test-isolation purposes. --- spec/atom-environment-spec.coffee | 8 ++- spec/jasmine-test-runner.coffee | 6 +- src/application-delegate.coffee | 97 +++++++++++++++++++++++++++++ src/atom-environment.coffee | 89 ++++++++++---------------- src/browser/atom-application.coffee | 5 -- src/initialize-test-window.coffee | 4 +- 6 files changed, 143 insertions(+), 66 deletions(-) create mode 100644 src/application-delegate.coffee diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 6d3d7ff04..44d78cac7 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -213,7 +213,9 @@ describe "AtomEnvironment", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> - atomEnvironment = new AtomEnvironment(setRepresentedFilename: ->) + atomEnvironment = new AtomEnvironment(applicationDelegate: { + isWindowFullScreen: -> false + }) spyOn(atomEnvironment, 'saveStateSync') workspaceState = atomEnvironment.workspace.serialize() @@ -231,7 +233,9 @@ describe "AtomEnvironment", -> describe "::destroy()", -> it "unsubscribes from all buffers", -> - atomEnvironment = new AtomEnvironment(setRepresentedFilename: ->) + atomEnvironment = new AtomEnvironment(applicationDelegate: { + isWindowFullScreen: -> false + }) waitsForPromise -> atomEnvironment.workspace.open("sample.js") diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index dec7652a8..d9af15b0d 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -14,7 +14,11 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> get: -> documentTitle set: (title) -> documentTitle = title - window.atom = buildAtomEnvironment({setRepresentedFilename: jasmine.createSpy('setRepresentedFilename')}) + ApplicationDelegate = require '../src/application-delegate' + applicationDelegate = new ApplicationDelegate() + applicationDelegate.setWindowRepresentedFilename = -> + applicationDelegate.setWindowDocumentEdited = -> + window.atom = buildAtomEnvironment({applicationDelegate}) require './spec-helper' disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee new file mode 100644 index 000000000..cc6e8bda7 --- /dev/null +++ b/src/application-delegate.coffee @@ -0,0 +1,97 @@ +remote = require 'remote' +shell = require 'shell' + +module.exports = +class ApplicationDelegate + open: (params) -> + ipc.send('open', params) + + pickFolder: -> + responseChannel = "atom-pick-folder-response" + ipc.on responseChannel, (path) -> + ipc.removeAllListeners(responseChannel) + callback(path) + ipc.send("pick-folder", responseChannel) + + getCurrentWindow: -> + remote.getCurrentWindow() + + closeWindow: -> + remote.getCurrentWindow().close() + + getWindowSize: -> + [width, height] = remote.getCurrentWindow().getSize() + {width, height} + + setWindowSize: (width, height) -> + remote.getCurrentWindow().setSize(width, height) + + getWindowPosition: -> + [x, y] = remote.getCurrentWindow().getPosition() + {x, y} + + setWindowPosition: (x, y) -> + remote.getCurrentWindow().setPosition(x, y) + + centerWindow: -> + remote.getCurrentWindow().center() + + focusWindow: -> + remote.getCurrentWindow().focus() + + showWindow: -> + remote.getCurrentWindow().show() + + hideWindow: -> + remote.getCurrentWindow().hide() + + restartWindow: -> + remote.getCurrentWindow().restart() + + isWindowMaximized: -> + remote.getCurrentWindow().isMaximized() + + maximizeWindow: -> + remote.getCurrentWindow().maximize() + + isWindowFullScreen: -> + remote.getCurrentWindow().isFullScreen() + + setWindowFullScreen: (fullScreen=false) -> + remote.getCurrentWindow().setFullScreen(fullScreen) + + openWindowDevTools: -> + remote.getCurrentWindow().openDevTools() + + toggleWindowDevTools: -> + remote.getCurrentWindow().toggleDevTools() + + executeJavaScriptInWindowDevTools: (code) -> + remote.getCurrentWindow().executeJavaScriptInDevTools(code) + + setWindowDocumentEdited: (edited) -> + remote.getCurrentWindow().setDocumentEdited(edited) + + setRepresentedFilename: (filename) -> + remote.getCurrentWindow().setRepresentedFilename(filename) + + setAutoHideWindowMenuBar: (autoHide) -> + remote.getCurrentWindow().setAutoHideMenuBar(autoHide) + + setWindowMenuBarVisibility: (visible) -> + remote.getCurrentWindow().setMenuBarVisibility(visible) + + getPrimaryDisplayWorkAreaSize: -> + screen = remote.require 'screen' + screen.getPrimaryDisplay().workAreaSize + + showMessageDialog: (params) -> + dialog = remote.require('dialog') + dialog.showMessageBox remote.getCurrentWindow(), params + + showSaveDialog: (params) -> + dialog = remote.require('dialog') + dialog.showSaveDialog remote.getCurrentWindow(), params + + playBeepSound: -> + shell.beep() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 648abf021..febf134da 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -1,9 +1,5 @@ crypto = require 'crypto' -ipc = require 'ipc' -os = require 'os' path = require 'path' -remote = require 'remote' -shell = require 'shell' _ = require 'underscore-plus' {deprecate} = require 'grim' @@ -105,8 +101,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {setRepresentedFilename} = params - @setRepresentedFilename = setRepresentedFilename if setRepresentedFilename? + {@applicationDelegate} = params @state = {version: @constructor.version} @@ -390,7 +385,7 @@ class AtomEnvironment extends Model # Calling this method without an options parameter will open a prompt to pick # a file/folder to open in the new window. # - # * `options` An {Object} with the following keys: + # * `params` An {Object} with the following keys: # * `pathsToOpen` An {Array} of {String} paths to open. # * `newWindow` A {Boolean}, true to always open a new window instead of # reusing existing windows depending on the paths to open. @@ -399,8 +394,8 @@ class AtomEnvironment extends Model # repository and also loads all the packages in ~/.atom/dev/packages # * `safeMode` A {Boolean}, true to open the window in safe mode. Safe # mode prevents all packages installed to ~/.atom/packages from loading. - open: (options) -> - ipc.send('open', options) + open: (params) -> + @applicationDelegate.open(params) # Extended: Prompt the user to select one or more folders. # @@ -408,83 +403,77 @@ class AtomEnvironment extends Model # * `paths` An {Array} of {String} paths that the user selected, or `null` # if the user dismissed the dialog. pickFolder: (callback) -> - responseChannel = "atom-pick-folder-response" - ipc.on responseChannel, (path) -> - ipc.removeAllListeners(responseChannel) - callback(path) - ipc.send("pick-folder", responseChannel) + @applicationDelegate.pickFolder(callback) # Essential: Close the current window. close: -> - @getCurrentWindow().close() + @applicationDelegate.closeWindow() # Essential: Get the size of current window. # # Returns an {Object} in the format `{width: 1000, height: 700}` getSize: -> - [width, height] = @getCurrentWindow().getSize() - {width, height} + @applicationDelegate.getWindowSize() # Essential: Set the size of current window. # # * `width` The {Number} of pixels. # * `height` The {Number} of pixels. setSize: (width, height) -> - @getCurrentWindow().setSize(width, height) + @applicationDelegate.setWindowSize(width, height) # Essential: Get the position of current window. # # Returns an {Object} in the format `{x: 10, y: 20}` getPosition: -> - [x, y] = @getCurrentWindow().getPosition() - {x, y} + @applicationDelegate.getWindowPosition() # Essential: Set the position of current window. # # * `x` The {Number} of pixels. # * `y` The {Number} of pixels. setPosition: (x, y) -> - ipc.send('call-window-method', 'setPosition', x, y) + @applicationDelegate.setWindowPosition(x, y) # Extended: Get the current window getCurrentWindow: -> - remote.getCurrentWindow() + @applicationDelegate.getCurrentWindow() # Extended: Move current window to the center of the screen. center: -> - ipc.send('call-window-method', 'center') + @applicationDelegate.centerWindow() # Extended: Focus the current window. focus: -> - ipc.send('call-window-method', 'focus') + @applicationDelegate.focusWindow() window.focus() # Extended: Show the current window. show: -> - ipc.send('call-window-method', 'show') + @applicationDelegate.showWindow() # Extended: Hide the current window. hide: -> - ipc.send('call-window-method', 'hide') + @applicationDelegate.hideWindow() # Extended: Reload the current window. reload: -> - ipc.send('call-window-method', 'restart') + @applicationDelegate.restartWindow() # Extended: Returns a {Boolean} that is `true` if the current window is maximized. isMaximized: -> - @getCurrentWindow().isMaximized() + @applicationDelegate.isWindowMaximized() maximize: -> - ipc.send('call-window-method', 'maximize') + @applicationDelegate.maximizeWindow() # Extended: Returns a {Boolean} that is `true` if the current window is in full screen mode. isFullScreen: -> - @getCurrentWindow().isFullScreen() + @applicationDelegate.isWindowFullScreen() # Extended: Set the full screen state of the current window. setFullScreen: (fullScreen=false) -> - ipc.send('call-window-method', 'setFullScreen', fullScreen) + @applicationDelegate.setWindowFullScreen(fullScreen) if fullScreen document.body.classList.add("fullscreen") else @@ -564,8 +553,7 @@ class AtomEnvironment extends Model if @isValidDimensions(dimensions) dimensions else - screen = remote.require 'screen' - {width, height} = screen.getPrimaryDisplay().workAreaSize + {width, height} = @applicationDelegate.getPrimaryDisplayWorkAreaSize() {x: 0, y: 0, width: Math.min(1024, width), height} restoreWindowDimensions: -> @@ -673,7 +661,7 @@ class AtomEnvironment extends Model # Essential: Visually and audibly trigger a beep. beep: -> - shell.beep() if @config.get('core.audioBeep') + @applicationDelegate.playBeepSound() if @config.get('core.audioBeep') @emitter.emit 'did-beep' # Essential: A flexible way to open a dialog akin to an alert dialog. @@ -703,12 +691,12 @@ class AtomEnvironment extends Model else buttonLabels = Object.keys(buttons) - dialog = remote.require('dialog') - chosen = dialog.showMessageBox @getCurrentWindow(), + chosen = @applicationDelegate.showMessageDialog( type: 'info' message: message detail: detailedMessage buttons: buttonLabels + ) if _.isArray(buttons) chosen @@ -722,15 +710,15 @@ class AtomEnvironment extends Model # Extended: Open the dev tools for the current window. openDevTools: -> - ipc.send('call-window-method', 'openDevTools') + @applicationDelegate.openWindowDevTools() # Extended: Toggle the visibility of the dev tools for the current window. toggleDevTools: -> - ipc.send('call-window-method', 'toggleDevTools') + @applicationDelegate.toggleWindowDevTools() # Extended: Execute code in dev tools. executeJavaScriptInDevTools: (code) -> - ipc.send('call-window-method', 'executeJavaScriptInDevTools', code) + @applicationDelegate.executeJavaScriptInWindowDevTools(code) ### Section: Private @@ -755,16 +743,11 @@ class AtomEnvironment extends Model @disposables.add @project.onDidChangePaths => @updateLoadSetting('initialPaths', @project.getPaths()) - exit: (status) -> - app = remote.require('app') - app.emit('will-exit') - remote.process.exit(status) - setDocumentEdited: (edited) -> - ipc.send('call-window-method', 'setDocumentEdited', edited) + @applicationDelegate.setWindowDocumentEdited?(edited) setRepresentedFilename: (filename) -> - ipc.send('call-window-method', 'setRepresentedFilename', filename) + @applicationDelegate.setWindowRepresentedFilename?(filename) addProjectFolder: -> @pickFolder (selectedPaths = []) => @@ -778,11 +761,9 @@ class AtomEnvironment extends Model options = defaultPath: options else options = _.clone(options) - currentWindow = @getCurrentWindow() - dialog = remote.require('dialog') options.title ?= 'Save File' options.defaultPath ?= @project?.getPaths()[0] - dialog.showSaveDialog currentWindow, options + @applicationDelegate.showSaveDialog(options) saveStateSync: -> if storageKey = @getStateKey(@project?.getPaths()) @@ -834,12 +815,6 @@ class AtomEnvironment extends Model getStorageFolder: -> @storageFolder ?= new StorageFolder(@getConfigDirPath()) - crashMainProcess: -> - remote.process.crash() - - crashRenderProcess: -> - process.crash() - getUserInitScriptPath: -> initScriptPath = fs.resolve(@getConfigDirPath(), 'init', ['js', 'coffee']) initScriptPath ? path.join(@getConfigDirPath(), 'init.coffee') @@ -885,8 +860,8 @@ class AtomEnvironment extends Model document.body.classList.add("platform-#{process.platform}") setAutoHideMenuBar: (autoHide) -> - ipc.send('call-window-method', 'setAutoHideMenuBar', autoHide) - ipc.send('call-window-method', 'setMenuBarVisibility', not autoHide) + @applicationDelegate.setAutoHideWindowMenuBar(autoHide) + @applicationDelegate.setWindowMenuBarVisibility(not autoHide) # Preserve this deprecation until 2.0. Sorry. Should have removed Q sooner. Promise.prototype.done = (callback) -> diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index b183bcb14..8ef056237 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -216,11 +216,6 @@ class AtomApplication @killAllProcesses() @deleteSocketFile() - app.on 'will-exit', => - @saveState(false) - @killAllProcesses() - @deleteSocketFile() - app.on 'open-file', (event, pathToOpen) => event.preventDefault() @openPath({pathToOpen}) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index b3d85e423..6985d983b 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -3,7 +3,7 @@ require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') remote = require 'remote' exitWithStatusCode = (status) => - remote.require('app').emit('will-exit') + remote.require('app').emit('will-quit') remote.process.exit(status) try @@ -11,6 +11,7 @@ try ipc = require 'ipc' {getWindowLoadSettings} = require './window-load-settings-helpers' AtomEnvironment = require '../src/atom-environment' + ApplicationDelegate = require '../src/application-delegate' # Show window synchronously so a focusout doesn't fire on input elements # that are focused in the very first spec run. @@ -47,6 +48,7 @@ try headless: getWindowLoadSettings().headless testPaths: getWindowLoadSettings().testPaths buildAtomEnvironment: (params) -> new AtomEnvironment(params) + buildDefaultApplicationDelegate: (params) -> new ApplicationDelegate() legacyTestRunner: legacyTestRunner }) From 83a0cf28cd45d7ac3070643fb1ab58df464db340 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 15:47:45 -0600 Subject: [PATCH 184/316] :art: Signed-off-by: Max Brunsfeld --- src/atom-environment.coffee | 2 +- src/window-event-handler.coffee | 60 ++++++++++++++++----------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index febf134da..bf798d451 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -650,7 +650,7 @@ class AtomEnvironment extends Model window.onerror = @previousWindowErrorHandler installWindowEventHandler: -> - @windowEventHandler = new WindowEventHandler(this) + @windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate}) uninstallWindowEventHandler: -> @windowEventHandler?.unsubscribe() diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 16d5cfd0c..94fdf55c5 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -8,7 +8,7 @@ listen = require './delegated-listener' # Handles low-level events related to the window. module.exports = class WindowEventHandler - constructor: (@atomEnv) -> + constructor: ({@atomEnvironment}) -> @reloadRequested = false @subscriptions = new CompositeDisposable @@ -28,17 +28,17 @@ class WindowEventHandler @subscriptions.add listen(document, 'click', 'a', @handleLinkClick) @subscriptions.add listen(document, 'submit', 'form', @handleFormSubmit) - @subscriptions.add @atomEnv.commands.add window, + @subscriptions.add @atomEnvironment.commands.add window, 'window:toggle-full-screen': @handleWindowToggleFullScreen 'window:close': @handleWindowClose 'window:reload': @handleWindowReload 'window:toggle-dev-tools': @handleWindowToggleDevTools if process.platform in ['win32', 'linux'] - @subscriptions.add @atomEnv.commands.add window, + @subscriptions.add @atomEnvironment.commands.add window, 'window:toggle-menu-bar': @handleWindowToggleMenuBar - @subscriptions.add @atomEnv.commands.add document, + @subscriptions.add @atomEnvironment.commands.add document, 'core:focus-next': @handleFocusNext 'core:focus-previous': @handleFocusPrevious @@ -50,7 +50,7 @@ class WindowEventHandler bindCommandToAction = (command, action) => @addEventListener document, command, (event) => if event.target.webkitMatchesSelector('.native-key-bindings') - @atomEnv.getCurrentWindow().webContents[action]() + @atomEnvironment.getCurrentWindow().webContents[action]() bindCommandToAction('core:copy', 'copy') bindCommandToAction('core:paste', 'paste') @@ -73,7 +73,7 @@ class WindowEventHandler @subscriptions.add(new Disposable(-> target.removeEventListener(eventName, handler))) handleDocumentKeydown: (event) => - @atomEnv.keymaps.handleKeyboardEvent(event) + @atomEnvironment.keymaps.handleKeyboardEvent(event) event.stopImmediatePropagation() handleDrop: (event) -> @@ -137,77 +137,77 @@ class WindowEventHandler handleIPCMessage: (message, detail) => switch message when 'open-locations' - needsProjectPaths = @atomEnv.project?.getPaths().length is 0 + needsProjectPaths = @atomEnvironment.project?.getPaths().length is 0 for {pathToOpen, initialLine, initialColumn} in detail if pathToOpen? and needsProjectPaths if fs.existsSync(pathToOpen) - @atomEnv.project.addPath(pathToOpen) + @atomEnvironment.project.addPath(pathToOpen) else if fs.existsSync(path.dirname(pathToOpen)) - @atomEnv.project.addPath(path.dirname(pathToOpen)) + @atomEnvironment.project.addPath(path.dirname(pathToOpen)) else - @atomEnv.project.addPath(pathToOpen) + @atomEnvironment.project.addPath(pathToOpen) unless fs.isDirectorySync(pathToOpen) - @atomEnv.workspace?.open(pathToOpen, {initialLine, initialColumn}) + @atomEnvironment.workspace?.open(pathToOpen, {initialLine, initialColumn}) return when 'update-available' - @atomEnv.updateAvailable(detail) + @atomEnvironment.updateAvailable(detail) handleIPCCommand: (command, args...) => activeElement = document.activeElement # Use the workspace element view if body has focus - if activeElement is document.body and workspaceElement = @atomEnv.views.getView(@atomEnv.workspace) + if activeElement is document.body and workspaceElement = @atomEnvironment.views.getView(@atomEnvironment.workspace) activeElement = workspaceElement - @atomEnv.commands.dispatch(activeElement, command, args[0]) + @atomEnvironment.commands.dispatch(activeElement, command, args[0]) handleIPCContextCommand: (command, args...) => - @atomEnv.commands.dispatch(@atomEnv.contextMenu.activeElement, command, args) + @atomEnvironment.commands.dispatch(@atomEnvironment.contextMenu.activeElement, command, args) handleWindowFocus: -> document.body.classList.remove('is-blurred') handleWindowBlur: => document.body.classList.add('is-blurred') - @atomEnv.storeDefaultWindowDimensions() + @atomEnvironment.storeDefaultWindowDimensions() handleWindowBeforeunload: => - confirmed = @atomEnv.workspace?.confirmClose(windowCloseRequested: true) - @atomEnv.hide() if confirmed and not @reloadRequested and @atomEnv.getCurrentWindow().isWebViewFocused() + confirmed = @atomEnvironment.workspace?.confirmClose(windowCloseRequested: true) + @atomEnvironment.hide() if confirmed and not @reloadRequested and @atomEnvironment.getCurrentWindow().isWebViewFocused() @reloadRequested = false - @atomEnv.storeDefaultWindowDimensions() - @atomEnv.storeWindowDimensions() + @atomEnvironment.storeDefaultWindowDimensions() + @atomEnvironment.storeWindowDimensions() if confirmed - @atomEnv.unloadEditorWindow() + @atomEnvironment.unloadEditorWindow() else ipc.send('cancel-window-close') confirmed handleWindowUnload: => - @atomEnv.destroy() + @atomEnvironment.destroy() handleWindowToggleFullScreen: => - @atomEnv.toggleFullScreen() + @atomEnvironment.toggleFullScreen() handleWindowClose: => - @atomEnv.close() + @atomEnvironment.close() handleWindowReload: => @reloadRequested = true - @atomEnv.reload() + @atomEnvironment.reload() handleWindowToggleDevTools: => - @atomEnv.toggleDevTools() + @atomEnvironment.toggleDevTools() handleWindowToggleMenuBar: => - @atomEnv.config.set('core.autoHideMenuBar', not @atomEnv.config.get('core.autoHideMenuBar')) + @atomEnvironment.config.set('core.autoHideMenuBar', not @atomEnvironment.config.get('core.autoHideMenuBar')) - if @atomEnv.config.get('core.autoHideMenuBar') + if @atomEnvironment.config.get('core.autoHideMenuBar') detail = "To toggle, press the Alt key or execute the window:toggle-menu-bar command" - @atomEnv.notifications.addInfo('Menu bar hidden', {detail}) + @atomEnvironment.notifications.addInfo('Menu bar hidden', {detail}) handleLinkClick: (event) -> event.preventDefault() @@ -221,4 +221,4 @@ class WindowEventHandler handleDocumentContextmenu: (event) => event.preventDefault() - @atomEnv.contextMenu.showForEvent(event) + @atomEnvironment.contextMenu.showForEvent(event) From f989ed65e1ffd684b338867d964c5de62e83eab3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 16:57:02 -0600 Subject: [PATCH 185/316] Move ipc handling from WindowEventHandler to ApplicationDelegate Signed-off-by: Max Brunsfeld --- src/application-delegate.coffee | 32 +++++++++++++++++++++- src/atom-environment.coffee | 32 ++++++++++++++++++++++ src/initialize-application-window.coffee | 3 +- src/window-event-handler.coffee | 35 ------------------------ 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index cc6e8bda7..7cc76c50c 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -1,12 +1,14 @@ +ipc = require 'ipc' remote = require 'remote' shell = require 'shell' +{Disposable} = require 'event-kit' module.exports = class ApplicationDelegate open: (params) -> ipc.send('open', params) - pickFolder: -> + pickFolder: (callback) -> responseChannel = "atom-pick-folder-response" ipc.on responseChannel, (path) -> ipc.removeAllListeners(responseChannel) @@ -95,3 +97,31 @@ class ApplicationDelegate playBeepSound: -> shell.beep() + + onDidOpenLocations: (callback) -> + outerCallback = (message, detail) -> + if message is 'open-locations' + callback(detail) + + ipc.on('message', outerCallback) + new Disposable -> + ipc.removeEventListener('message', outerCallback) + + onUpdateAvailable: (callback) -> + outerCallback = (message, detail) -> + if message is 'update-available' + callback(detail) + + ipc.on('message', outerCallback) + new Disposable -> + ipc.removeEventListener('message', outerCallback) + + onApplicationMenuCommand: (callback) -> + ipc.on('command', callback) + new Disposable -> + ipc.removeEventListener('command', callback) + + onContextMenuCommand: (callback) -> + ipc.on('context-command', callback) + new Disposable -> + ipc.removeEventListener('context-command', callback) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index bf798d451..4cb256a03 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -581,6 +581,11 @@ class AtomEnvironment extends Model @commandInstaller.installApmCommand false, (error) -> console.warn error.message if error? + @disposables.add(@applicationDelegate.onDidOpenLocations(@openLocations.bind(this))) + @disposables.add(@applicationDelegate.onUpdateAvailable(@updateAvailable.bind(this))) + @disposables.add(@applicationDelegate.onApplicationMenuCommand(@dispatchApplicationMenuCommand.bind(this))) + @disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this))) + @config.load() @themes.loadBaseStylesheets() @setBodyPlatformClass() @@ -863,6 +868,33 @@ class AtomEnvironment extends Model @applicationDelegate.setAutoHideWindowMenuBar(autoHide) @applicationDelegate.setWindowMenuBarVisibility(not autoHide) + dispatchApplicationMenuCommand: (command, arg) -> + activeElement = document.activeElement + # Use the workspace element if body has focus + if activeElement is document.body and workspaceElement = @views.getView(@workspace) + activeElement = workspaceElement + @commands.dispatch(activeElement, command, arg) + + dispatchContextMenuCommand: (command, args...) -> + @commands.dispatch(@contextMenu.activeElement, command, args) + + openLocations: (locations) -> + needsProjectPaths = @project?.getPaths().length is 0 + + for {pathToOpen, initialLine, initialColumn} in locations + if pathToOpen? and needsProjectPaths + if fs.existsSync(pathToOpen) + @project.addPath(pathToOpen) + else if fs.existsSync(path.dirname(pathToOpen)) + @project.addPath(path.dirname(pathToOpen)) + else + @project.addPath(pathToOpen) + + unless fs.isDirectorySync(pathToOpen) + @workspace?.open(pathToOpen, {initialLine, initialColumn}) + + return + # Preserve this deprecation until 2.0. Sorry. Should have removed Q sooner. Promise.prototype.done = (callback) -> deprecate("Atom now uses ES6 Promises instead of Q. Call promise.then instead of promise.done") diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index b10208bb1..242201b32 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -15,7 +15,8 @@ process.env.NODE_PATH = exportsPath process.env.NODE_ENV ?= 'production' unless devMode AtomEnvironment = require './atom-environment' -window.atom = new AtomEnvironment +ApplicationDelegate = require './application-delegate' +window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate}) atom.displayWindow() atom.loadStateSync() diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 94fdf55c5..5b25ff18f 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -12,10 +12,6 @@ class WindowEventHandler @reloadRequested = false @subscriptions = new CompositeDisposable - @on(ipc, 'message', @handleIPCMessage) - @on(ipc, 'command', @handleIPCCommand) - @on(ipc, 'context-command', @handleIPCContextCommand) - @addEventListener(window, 'focus', @handleWindowFocus) @addEventListener(window, 'blur', @handleWindowBlur) @addEventListener(window, 'beforeunload', @handleWindowBeforeunload) @@ -134,37 +130,6 @@ class WindowEventHandler else if highestElement? highestElement.focus() - handleIPCMessage: (message, detail) => - switch message - when 'open-locations' - needsProjectPaths = @atomEnvironment.project?.getPaths().length is 0 - - for {pathToOpen, initialLine, initialColumn} in detail - if pathToOpen? and needsProjectPaths - if fs.existsSync(pathToOpen) - @atomEnvironment.project.addPath(pathToOpen) - else if fs.existsSync(path.dirname(pathToOpen)) - @atomEnvironment.project.addPath(path.dirname(pathToOpen)) - else - @atomEnvironment.project.addPath(pathToOpen) - - unless fs.isDirectorySync(pathToOpen) - @atomEnvironment.workspace?.open(pathToOpen, {initialLine, initialColumn}) - return - when 'update-available' - @atomEnvironment.updateAvailable(detail) - - handleIPCCommand: (command, args...) => - activeElement = document.activeElement - # Use the workspace element view if body has focus - if activeElement is document.body and workspaceElement = @atomEnvironment.views.getView(@atomEnvironment.workspace) - activeElement = workspaceElement - - @atomEnvironment.commands.dispatch(activeElement, command, args[0]) - - handleIPCContextCommand: (command, args...) => - @atomEnvironment.commands.dispatch(@atomEnvironment.contextMenu.activeElement, command, args) - handleWindowFocus: -> document.body.classList.remove('is-blurred') From 919571f328d165912a7bc2fef95ccc078b9ad181 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 17:10:30 -0600 Subject: [PATCH 186/316] Use ApplicationDelegate in WindowEventHandler Signed-off-by: Max Brunsfeld --- spec/window-event-handler-spec.coffee | 4 ++-- src/application-delegate.coffee | 6 ++++++ src/browser/atom-application.coffee | 2 +- src/window-event-handler.coffee | 14 ++++++-------- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 76dd9ef6b..cc9e14a97 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -65,13 +65,13 @@ describe "WindowEventHandler", -> spyOn(atom.workspace, 'confirmClose').andReturn(true) window.dispatchEvent(new CustomEvent('beforeunload')) expect(atom.workspace.confirmClose).toHaveBeenCalled() - expect(ipc.send).not.toHaveBeenCalledWith('cancel-window-close') + expect(ipc.send).not.toHaveBeenCalledWith('did-cancel-window-unload') it "cancels the unload if the user selects cancel", -> spyOn(atom.workspace, 'confirmClose').andReturn(false) window.dispatchEvent(new CustomEvent('beforeunload')) expect(atom.workspace.confirmClose).toHaveBeenCalled() - expect(ipc.send).toHaveBeenCalledWith('cancel-window-close') + expect(ipc.send).toHaveBeenCalledWith('did-cancel-window-unload') describe "when a link is clicked", -> it "opens the http/https links in an external application", -> diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index 7cc76c50c..cbbd10a69 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -125,3 +125,9 @@ class ApplicationDelegate ipc.on('context-command', callback) new Disposable -> ipc.removeEventListener('context-command', callback) + + didCancelWindowUnload: -> + ipc.send('did-cancel-window-unload') + + openExternal: (url) -> + shell.openExternal(url) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 8ef056237..d63ee4e78 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -264,7 +264,7 @@ class AtomApplication @promptForPath "folder", (selectedPaths) -> event.sender.send(responseChannel, selectedPaths) - ipc.on 'cancel-window-close', => + ipc.on 'did-cancel-window-unload', => @quitting = false clipboard = require '../safe-clipboard' diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 5b25ff18f..f4b844405 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -1,14 +1,12 @@ path = require 'path' {Disposable, CompositeDisposable} = require 'event-kit' -ipc = require 'ipc' -shell = require 'shell' fs = require 'fs-plus' listen = require './delegated-listener' # Handles low-level events related to the window. module.exports = class WindowEventHandler - constructor: ({@atomEnvironment}) -> + constructor: ({@atomEnvironment, @applicationDelegate}) -> @reloadRequested = false @subscriptions = new CompositeDisposable @@ -46,7 +44,7 @@ class WindowEventHandler bindCommandToAction = (command, action) => @addEventListener document, command, (event) => if event.target.webkitMatchesSelector('.native-key-bindings') - @atomEnvironment.getCurrentWindow().webContents[action]() + @applicationDelegate.getCurrentWindow().webContents[action]() bindCommandToAction('core:copy', 'copy') bindCommandToAction('core:paste', 'paste') @@ -147,7 +145,7 @@ class WindowEventHandler if confirmed @atomEnvironment.unloadEditorWindow() else - ipc.send('cancel-window-close') + @applicationDelegate.didCancelWindowUnload() confirmed @@ -176,9 +174,9 @@ class WindowEventHandler handleLinkClick: (event) -> event.preventDefault() - location = event.currentTarget?.getAttribute('href') - if location and location[0] isnt '#' and /^https?:\/\//.test(location) - shell.openExternal(location) + uri = event.currentTarget?.getAttribute('href') + if uri and uri[0] isnt '#' and /^https?:\/\//.test(uri) + @applicationDelegate.openExternal(uri) handleFormSubmit: (event) -> # Prevent form submits from changing the current window's URL From ed1c37cdbf53dc7f949799c5af3662cd18b54672 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 17:28:12 -0600 Subject: [PATCH 187/316] Bind confirm when deserializing panes Signed-off-by: Max Brunsfeld --- src/pane.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pane.coffee b/src/pane.coffee index beb6a4136..4a6d919c1 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -14,7 +14,9 @@ class Pane extends Model activeItem: undefined focused: false - @deserialize: (state, {deserializers, config, notifications, confirm}) -> + @deserialize: (state, atomEnvironment) -> + {deserializers, config, notifications} = atomEnvironment + confirm = atomEnvironment.confirm.bind(atomEnvironment) {items, activeItemURI, activeItemUri} = state activeItemURI ?= activeItemUri state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState)) From 432a59b8e5e775fcba13c6ec8f8dc7e5bd704b35 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 17:53:01 -0600 Subject: [PATCH 188/316] Move tests from window-event-handler-spec for moved functionality Signed-off-by: Max Brunsfeld --- spec/atom-environment-spec.coffee | 57 ++++++++++++++++++++ spec/window-event-handler-spec.coffee | 78 +-------------------------- src/atom-environment.coffee | 5 +- 3 files changed, 62 insertions(+), 78 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 44d78cac7..1c6ec011d 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -249,3 +249,60 @@ describe "AtomEnvironment", -> atomEnvironment.destroy() expect(buffer.getSubscriptionCount()).toBe 0 + + describe "::openLocations(locations) (called via IPC from browser process)", -> + beforeEach -> + spyOn(atom.workspace, 'open') + atom.project.setPaths([]) + + describe "when the opened path exists", -> + it "adds it to the project's paths", -> + pathToOpen = __filename + atom.openLocations([{pathToOpen}]) + expect(atom.project.getPaths()[0]).toBe __dirname + + describe "when the opened path does not exist but its parent directory does", -> + it "adds the parent directory to the project paths", -> + pathToOpen = path.join(__dirname, 'this-path-does-not-exist.txt') + atom.openLocations([{pathToOpen}]) + expect(atom.project.getPaths()[0]).toBe __dirname + + describe "when the opened path is a file", -> + it "opens it in the workspace", -> + pathToOpen = __filename + atom.openLocations([{pathToOpen}]) + expect(atom.workspace.open.mostRecentCall.args[0]).toBe __filename + + describe "when the opened path is a directory", -> + it "does not open it in the workspace", -> + pathToOpen = __dirname + atom.openLocations([{pathToOpen}]) + expect(atom.workspace.open.callCount).toBe 0 + + describe "when the opened path is a uri", -> + it "adds it to the project's paths as is", -> + pathToOpen = 'remote://server:7644/some/dir/path' + atom.openLocations([{pathToOpen}]) + expect(atom.project.getPaths()[0]).toBe pathToOpen + + describe "::updateAvailable(info) (called via IPC from browser process)", -> + subscription = null + + afterEach -> + subscription?.dispose() + + it "invokes onUpdateAvailable listeners", -> + atom.listenForUpdates() + + updateAvailableHandler = jasmine.createSpy("update-available-handler") + subscription = atom.onUpdateAvailable updateAvailableHandler + + autoUpdater = require('remote').require('auto-updater') + autoUpdater.emit 'update-downloaded', null, "notes", "version" + + waitsFor -> + updateAvailableHandler.callCount > 0 + + runs -> + {releaseVersion} = updateAvailableHandler.mostRecentCall.args[0] + expect(releaseVersion).toBe 'version' diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index cc9e14a97..037c15cb0 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -18,7 +18,7 @@ describe "WindowEventHandler", -> loadSettings.initialPath = initialPath loadSettings atom.project.destroy() - windowEventHandler = new WindowEventHandler(atom) + windowEventHandler = new WindowEventHandler({atomEnvironment: atom, applicationDelegate: atom.applicationDelegate}) projectPath = atom.project.getPaths()[0] afterEach -> @@ -188,62 +188,6 @@ describe "WindowEventHandler", -> elements.dispatchEvent(new CustomEvent("core:focus-previous", bubbles: true)) expect(document.activeElement.tabIndex).toBe 7 - describe "the window:open-locations event", -> - beforeEach -> - spyOn(atom.workspace, 'open') - atom.project.setPaths([]) - - describe "when the opened path exists", -> - it "adds it to the project's paths", -> - pathToOpen = __filename - atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}] - - waitsFor -> - atom.project.getPaths().length is 1 - - runs -> - expect(atom.project.getPaths()[0]).toBe __dirname - - describe "when the opened path does not exist but its parent directory does", -> - it "adds the parent directory to the project paths", -> - pathToOpen = path.join(__dirname, 'this-path-does-not-exist.txt') - atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}] - - waitsFor -> - atom.project.getPaths().length is 1 - - runs -> - expect(atom.project.getPaths()[0]).toBe __dirname - - describe "when the opened path is a file", -> - it "opens it in the workspace", -> - pathToOpen = __filename - atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}] - - waitsFor -> - atom.workspace.open.callCount is 1 - - runs -> - expect(atom.workspace.open.mostRecentCall.args[0]).toBe __filename - - - describe "when the opened path is a directory", -> - it "does not open it in the workspace", -> - pathToOpen = __dirname - atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}] - expect(atom.workspace.open.callCount).toBe 0 - - describe "when the opened path is a uri", -> - it "adds it to the project's paths as is", -> - pathToOpen = 'remote://server:7644/some/dir/path' - atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}] - - waitsFor -> - atom.project.getPaths().length is 1 - - runs -> - expect(atom.project.getPaths()[0]).toBe pathToOpen - describe "when keydown events occur on the document", -> it "dispatches the event via the KeymapManager and CommandRegistry", -> dispatchedCommands = [] @@ -256,23 +200,3 @@ describe "WindowEventHandler", -> expect(dispatchedCommands.length).toBe 1 expect(dispatchedCommands[0].type).toBe 'foo-command' - - describe "when an update becomes available", -> - subscription = null - - afterEach -> - subscription?.dispose() - - it "invokes onUpdateAvailable listeners", -> - updateAvailableHandler = jasmine.createSpy("update-available-handler") - subscription = atom.onUpdateAvailable updateAvailableHandler - - autoUpdater = require('remote').require('auto-updater') - autoUpdater.emit 'update-downloaded', null, "notes", "version" - - waitsFor -> - updateAvailableHandler.callCount > 0 - - runs -> - {releaseVersion} = updateAvailableHandler.mostRecentCall.args[0] - expect(releaseVersion).toBe 'version' diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 4cb256a03..5dc127525 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -582,9 +582,9 @@ class AtomEnvironment extends Model console.warn error.message if error? @disposables.add(@applicationDelegate.onDidOpenLocations(@openLocations.bind(this))) - @disposables.add(@applicationDelegate.onUpdateAvailable(@updateAvailable.bind(this))) @disposables.add(@applicationDelegate.onApplicationMenuCommand(@dispatchApplicationMenuCommand.bind(this))) @disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this))) + @listenForUpdates() @config.load() @themes.loadBaseStylesheets() @@ -861,6 +861,9 @@ class AtomEnvironment extends Model updateAvailable: (details) -> @emitter.emit 'update-available', details + listenForUpdates: -> + @disposables.add(@applicationDelegate.onUpdateAvailable(@updateAvailable.bind(this))) + setBodyPlatformClass: -> document.body.classList.add("platform-#{process.platform}") From cc0bf23f7829a32ac73b5630768bff6c231ef4be Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 17:57:48 -0600 Subject: [PATCH 189/316] Add setRepresentedDirectoryPaths to ApplicationDelegate Also, use it to provide the default path in showSaveDialog --- src/application-delegate.coffee | 13 +++++++++++++ src/atom-environment.coffee | 13 +------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index cbbd10a69..10ef81e71 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -1,7 +1,9 @@ +_ = require 'underscore-plus' ipc = require 'ipc' remote = require 'remote' shell = require 'shell' {Disposable} = require 'event-kit' +{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' module.exports = class ApplicationDelegate @@ -77,6 +79,11 @@ class ApplicationDelegate setRepresentedFilename: (filename) -> remote.getCurrentWindow().setRepresentedFilename(filename) + setRepresentedDirectoryPaths: (paths) -> + loadSettings = getWindowLoadSettings() + loadSettings['initialPaths'] = value + setWindowLoadSettings(loadSettings) + setAutoHideWindowMenuBar: (autoHide) -> remote.getCurrentWindow().setAutoHideMenuBar(autoHide) @@ -92,6 +99,12 @@ class ApplicationDelegate dialog.showMessageBox remote.getCurrentWindow(), params showSaveDialog: (params) -> + if _.isString(params) + params = defaultPath: params + else + params = _.clone(params) + params.title ?= 'Save File' + params.defaultPath ?= getWindowLoadSettings().initialPaths[0] dialog = remote.require('dialog') dialog.showSaveDialog remote.getCurrentWindow(), params diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 5dc127525..1706459c6 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -371,11 +371,6 @@ class AtomEnvironment extends Model getLoadSettings: -> getWindowLoadSettings() - updateLoadSetting: (key, value) -> - loadSettings = @getLoadSettings() - loadSettings[key] = value - setWindowLoadSettings(loadSettings) - ### Section: Managing The Atom Window ### @@ -746,7 +741,7 @@ class AtomEnvironment extends Model # Notify the browser project of the window's current project path watchProjectPath: -> @disposables.add @project.onDidChangePaths => - @updateLoadSetting('initialPaths', @project.getPaths()) + @applicationDelegate.setRepresentedDirectoryPaths(@project.getPaths()) setDocumentEdited: (edited) -> @applicationDelegate.setWindowDocumentEdited?(edited) @@ -762,12 +757,6 @@ class AtomEnvironment extends Model callback(showSaveDialogSync()) showSaveDialogSync: (options={}) -> - if _.isString(options) - options = defaultPath: options - else - options = _.clone(options) - options.title ?= 'Save File' - options.defaultPath ?= @project?.getPaths()[0] @applicationDelegate.showSaveDialog(options) saveStateSync: -> From 20e07649d4e81b11ceed43616da735f16fee131d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 18:09:35 -0600 Subject: [PATCH 190/316] Move confirm into ApplicationDelegate Signed-off-by: Max Brunsfeld --- src/application-delegate.coffee | 23 +++++++++++++++++++++-- src/atom-environment.coffee | 21 ++------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index 10ef81e71..74a3dd04b 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -94,9 +94,28 @@ class ApplicationDelegate screen = remote.require 'screen' screen.getPrimaryDisplay().workAreaSize - showMessageDialog: (params) -> + confirm: ({message, detailedMessage, buttons}) -> + buttons ?= {} + if _.isArray(buttons) + buttonLabels = buttons + else + buttonLabels = Object.keys(buttons) + dialog = remote.require('dialog') - dialog.showMessageBox remote.getCurrentWindow(), params + chosen = dialog.showMessageBox(remote.getCurrentWindow(), { + type: 'info' + message: message + detail: detailedMessage + buttons: buttonLabels + }) + + if _.isArray(buttons) + chosen + else + callback = buttons[buttonLabels[chosen]] + callback?() + + showMessageDialog: (params) -> showSaveDialog: (params) -> if _.isString(params) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 1706459c6..9d0c9d76a 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -684,25 +684,8 @@ class AtomEnvironment extends Model # button names and the values are callbacks to invoke when clicked. # # Returns the chosen button index {Number} if the buttons option was an array. - confirm: ({message, detailedMessage, buttons}={}) -> - buttons ?= {} - if _.isArray(buttons) - buttonLabels = buttons - else - buttonLabels = Object.keys(buttons) - - chosen = @applicationDelegate.showMessageDialog( - type: 'info' - message: message - detail: detailedMessage - buttons: buttonLabels - ) - - if _.isArray(buttons) - chosen - else - callback = buttons[buttonLabels[chosen]] - callback?() + confirm: (params={}) -> + @applicationDelegate.confirm(params) ### Section: Managing the Dev Tools From e0ab4b33f5c4116b423a46103922eb02b2184dc1 Mon Sep 17 00:00:00 2001 From: Wliu Date: Tue, 13 Oct 2015 20:31:22 -0400 Subject: [PATCH 191/316] Simplify Node versions to "0.10.x or above" --- docs/build-instructions/linux.md | 8 ++++---- docs/build-instructions/os-x.md | 2 +- docs/build-instructions/windows.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 2fc46c0b2..85e40a2bc 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -7,8 +7,8 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. * OS with 64-bit or 32-bit architecture * C++ toolchain * [Git](http://git-scm.com/) - * [node.js](http://nodejs.org/download/) (0.10.x or 0.12.x) or [io.js](https://iojs.org) (1.x or 2.x) - * [npm](https://www.npmjs.com/) v1.4.x (bundled with Node.js) + * [node.js](http://nodejs.org/download/) (0.10.x or above) + * [npm](https://www.npmjs.com/) v1.4.x or above (automatically bundled with Node.js) * `npm -v` to check the version. * `npm config set python /usr/bin/python2 -g` to ensure that gyp uses python2. * You might need to run this command as `sudo`, depending on how you have set up [npm](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os). @@ -17,7 +17,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. ### Ubuntu / Debian * `sudo apt-get install build-essential git libgnome-keyring-dev fakeroot` -* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions). +* Instructions for [node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions). * Make sure the command `node` is available after Node.js installation (some systems install it as `nodejs`). * Use `which node` to check if it is available. * Use `sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10` to update it. @@ -25,7 +25,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. ### Fedora / CentOS / RHEL * `sudo dnf --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools` -* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#enterprise-linux-and-fedora). +* Instructions for [node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#enterprise-linux-and-fedora). ### Arch diff --git a/docs/build-instructions/os-x.md b/docs/build-instructions/os-x.md index 7273a29fd..e97ab6f5a 100644 --- a/docs/build-instructions/os-x.md +++ b/docs/build-instructions/os-x.md @@ -3,7 +3,7 @@ ## Requirements * OS X 10.8 or later - * [node.js](http://nodejs.org/download/) (0.10.x or 0.12.x) or [io.js](https://iojs.org) (1.x or 2.x) + * [node.js](http://nodejs.org/download/) (0.10.x or above) * Command Line Tools for [Xcode](https://developer.apple.com/xcode/downloads/) (run `xcode-select --install` to install) ## Instructions diff --git a/docs/build-instructions/windows.md b/docs/build-instructions/windows.md index 600a7479d..df0a80c13 100644 --- a/docs/build-instructions/windows.md +++ b/docs/build-instructions/windows.md @@ -5,7 +5,7 @@ ### On Windows 7 * [Visual C++ 2010 Express](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_4) * [Visual Studio 2010 Service Pack 1](http://www.microsoft.com/en-us/download/details.aspx?id=23691) - * [node.js](http://nodejs.org/download/) (0.10.x or 0.12.x) or [io.js](https://iojs.org) (1.x or 2.x) + * [node.js](http://nodejs.org/download/) (0.10.x or above) * For 64-bit builds of node and native modules you **must** have the [Windows 7 64-bit SDK](http://www.microsoft.com/en-us/download/details.aspx?id=8279). You may also need the [compiler update for the Windows SDK 7.1](http://www.microsoft.com/en-us/download/details.aspx?id=4422) @@ -20,7 +20,7 @@ * [Visual Studio Express 2013 or 2015 for Windows Desktop](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_2) * For VS 2015, be sure to customize the installation to include Visual C++. It's not installed by default. * Some have experienced issues with Node locating C++ on VS 2015. If so, try VS 2013. - * [node.js](http://nodejs.org/download/) (0.10.x, 0.12.x or 4.x) or [io.js](https://iojs.org) (1.x or 2.x) + * [node.js](http://nodejs.org/download/) (0.10.x or above) * [Python](https://www.python.org/downloads/) v2.7.x (required by [node-gyp](https://github.com/TooTallNate/node-gyp)) * [GitHub Desktop](http://desktop.github.com/) From 84aa8471b48ef9206b010949c24f80665b922d75 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 18:54:48 -0600 Subject: [PATCH 192/316] Pass AppDelegate to Workspace, Pane instead of bound functions Signed-off-by: Max Brunsfeld --- spec/atom-environment-spec.coffee | 8 ++------ spec/jasmine-test-runner.coffee | 2 +- spec/pane-container-spec.coffee | 4 ++-- spec/pane-spec.coffee | 27 ++++++++++++++------------- spec/sample-with-comments.js | 1 + spec/sample.js | 1 + spec/workspace-spec.coffee | 26 ++++++++++---------------- src/atom-environment.coffee | 3 +-- src/pane-container.coffee | 4 ++-- src/pane.coffee | 15 ++++++--------- src/workspace.coffee | 23 ++++++++++------------- 11 files changed, 50 insertions(+), 64 deletions(-) create mode 100644 spec/sample-with-comments.js create mode 100644 spec/sample.js diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 1c6ec011d..574994564 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -213,9 +213,7 @@ describe "AtomEnvironment", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> - atomEnvironment = new AtomEnvironment(applicationDelegate: { - isWindowFullScreen: -> false - }) + atomEnvironment = new AtomEnvironment(applicationDelegate: atom.applicationDelegate) spyOn(atomEnvironment, 'saveStateSync') workspaceState = atomEnvironment.workspace.serialize() @@ -233,9 +231,7 @@ describe "AtomEnvironment", -> describe "::destroy()", -> it "unsubscribes from all buffers", -> - atomEnvironment = new AtomEnvironment(applicationDelegate: { - isWindowFullScreen: -> false - }) + atomEnvironment = new AtomEnvironment(applicationDelegate: atom.applicationDelegate) waitsForPromise -> atomEnvironment.workspace.open("sample.js") diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index d9af15b0d..136be9215 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -16,7 +16,7 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> ApplicationDelegate = require '../src/application-delegate' applicationDelegate = new ApplicationDelegate() - applicationDelegate.setWindowRepresentedFilename = -> + applicationDelegate.setRepresentedFilename = -> applicationDelegate.setWindowDocumentEdited = -> window.atom = buildAtomEnvironment({applicationDelegate}) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 34c38f535..b94815e45 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -5,11 +5,11 @@ describe "PaneContainer", -> [confirm, params] = [] beforeEach -> - confirm = jasmine.createSpy('confirm').andReturn(0) + confirm = spyOn(atom.applicationDelegate, 'confirm').andReturn(0) params = { config: atom.config, - confirm: confirm, deserializerManager: atom.deserializers + applicationDelegate: atom.applicationDelegate } describe "serialization", -> diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index ca277f9af..0c7a22b77 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -5,7 +5,7 @@ PaneAxis = require '../src/pane-axis' PaneContainer = require '../src/pane-container' describe "Pane", -> - [confirm, deserializerDisposable] = [] + [confirm, showSaveDialog, deserializerDisposable] = [] class Item @deserialize: ({name, uri}) -> new this(name, uri) @@ -20,7 +20,8 @@ describe "Pane", -> isDestroyed: -> @destroyed beforeEach -> - confirm = jasmine.createSpy('confirm') + confirm = spyOn(atom.applicationDelegate, 'confirm') + showSaveDialog = spyOn(atom.applicationDelegate, 'showSaveDialog') deserializerDisposable = atom.deserializers.add(Item) afterEach -> @@ -28,7 +29,7 @@ describe "Pane", -> paneParams = (params) -> extend({ - confirm: confirm, + applicationDelegate: atom.applicationDelegate, config: atom.config, deserializerManager: atom.deserializers, notificationManager: atom.notifications @@ -48,7 +49,7 @@ describe "Pane", -> [container, pane1, pane2] = [] beforeEach -> - container = new PaneContainer(config: atom.config, confirm: confirm) + container = new PaneContainer(config: atom.config, applicationDelegate: atom.applicationDelegate) container.getActivePane().splitRight() [pane1, pane2] = container.getPanes() @@ -117,7 +118,7 @@ describe "Pane", -> it "throws an exception if the item is already present on a pane", -> item = new Item("A") - container = new PaneContainer(config: atom.config, confirm: confirm) + container = new PaneContainer(config: atom.config, applicationDelegate: atom.applicationDelegate) pane1 = container.getActivePane() pane1.addItem(item) pane2 = pane1.splitRight() @@ -281,11 +282,11 @@ describe "Pane", -> it "presents a save-as dialog, then saves the item with the given uri before removing and destroying it", -> itemURI = null - spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path") + showSaveDialog.andReturn("/selected/path") confirm.andReturn(0) pane.destroyItem(item1) - expect(atom.showSaveDialogSync).toHaveBeenCalled() + expect(showSaveDialog).toHaveBeenCalled() expect(item1.saveAs).toHaveBeenCalledWith("/selected/path") expect(item1 in pane.getItems()).toBe false expect(item1.isDestroyed()).toBe true @@ -379,7 +380,7 @@ describe "Pane", -> beforeEach -> pane = new Pane(paneParams(items: [new Item("A")])) - spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') + showSaveDialog.andReturn('/selected/path') describe "when the active item has a uri", -> beforeEach -> @@ -401,14 +402,14 @@ describe "Pane", -> it "opens a save dialog and saves the current item as the selected path", -> pane.getActiveItem().saveAs = jasmine.createSpy("saveAs") pane.saveActiveItem() - expect(atom.showSaveDialogSync).toHaveBeenCalled() + expect(showSaveDialog).toHaveBeenCalled() expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path') describe "when the current item has no saveAs method", -> it "does nothing", -> expect(pane.getActiveItem().saveAs).toBeUndefined() pane.saveActiveItem() - expect(atom.showSaveDialogSync).not.toHaveBeenCalled() + expect(showSaveDialog).not.toHaveBeenCalled() describe "when the item's saveAs method throws a well-known IO error", -> notificationSpy = null @@ -434,21 +435,21 @@ describe "Pane", -> beforeEach -> pane = new Pane(paneParams(items: [new Item("A")])) - spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') + showSaveDialog.andReturn('/selected/path') describe "when the current item has a saveAs method", -> it "opens the save dialog and calls saveAs on the item with the selected path", -> pane.getActiveItem().path = __filename pane.getActiveItem().saveAs = jasmine.createSpy("saveAs") pane.saveActiveItemAs() - expect(atom.showSaveDialogSync).toHaveBeenCalledWith(defaultPath: __filename) + expect(showSaveDialog).toHaveBeenCalledWith(defaultPath: __filename) expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path') describe "when the current item does not have a saveAs method", -> it "does nothing", -> expect(pane.getActiveItem().saveAs).toBeUndefined() pane.saveActiveItemAs() - expect(atom.showSaveDialogSync).not.toHaveBeenCalled() + expect(showSaveDialog).not.toHaveBeenCalled() describe "when the item's saveAs method throws a well-known IO error", -> notificationSpy = null diff --git a/spec/sample-with-comments.js b/spec/sample-with-comments.js new file mode 100644 index 000000000..66dc9051d --- /dev/null +++ b/spec/sample-with-comments.js @@ -0,0 +1 @@ +undefined \ No newline at end of file diff --git a/spec/sample.js b/spec/sample.js new file mode 100644 index 000000000..66dc9051d --- /dev/null +++ b/spec/sample.js @@ -0,0 +1 @@ +undefined \ No newline at end of file diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 1a1ed0aad..5850100e0 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -14,8 +14,8 @@ describe "Workspace", -> beforeEach -> workspace = atom.workspace workspace.resetFontSize() - spyOn(workspace, "confirm") - setDocumentEdited = spyOn(workspace, 'setDocumentEdited') + spyOn(atom.applicationDelegate, "confirm") + setDocumentEdited = spyOn(atom.applicationDelegate, 'setWindowDocumentEdited') atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) waits(1) @@ -31,10 +31,8 @@ describe "Workspace", -> config: atom.config, project: atom.project, packageManager: atom.packages, grammarRegistry: atom.grammars, deserializerManager: atom.deserializers, notificationManager: atom.notifications, clipboard: atom.clipboard, - setRepresentedFilename: atom.setRepresentedFilename.bind(atom), - setDocumentEdited: atom.setDocumentEdited.bind(atom), + applicationDelegate: atom.applicationDelegate, viewRegistry: atom.views, assert: atom.assert.bind(atom), - confirm: atom.confirm.bind(atom) }) atom.workspace.deserialize(workspaceState, atom.deserializers) @@ -347,8 +345,8 @@ describe "Workspace", -> describe "when the file is over 20MB", -> it "prompts the user to make sure they want to open a file this big", -> spyOn(fs, 'getSizeSync').andReturn 20 * 1048577 # 20MB - workspace.confirm.andCallFake -> selectedButtonIndex - atom.workspace.confirm() + atom.applicationDelegate.confirm.andCallFake -> selectedButtonIndex + atom.applicationDelegate.confirm() selectedButtonIndex = 1 # cancel editor = null @@ -357,16 +355,16 @@ describe "Workspace", -> runs -> expect(editor).toBeUndefined() - expect(workspace.confirm).toHaveBeenCalled() + expect(atom.applicationDelegate.confirm).toHaveBeenCalled() - workspace.confirm.reset() + atom.applicationDelegate.confirm.reset() selectedButtonIndex = 0 # open the file waitsForPromise -> workspace.open('sample.js').then (e) -> editor = e runs -> - expect(workspace.confirm).toHaveBeenCalled() + expect(atom.applicationDelegate.confirm).toHaveBeenCalled() expect(editor.displayBuffer.largeFileMode).toBe true describe "when passed a path that matches a custom opener", -> @@ -633,9 +631,7 @@ describe "Workspace", -> config: atom.config, project: atom.project, packageManager: atom.packages, notificationManager: atom.notifications, deserializerManager: atom.deserializers, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, - setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), - assert: atom.assert.bind(atom) + applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom) }) workspace2.deserialize(state, atom.deserializers) expect(jsPackage.loadGrammarsSync.callCount).toBe 1 @@ -693,9 +689,7 @@ describe "Workspace", -> config: atom.config, project: atom.project, packageManager: atom.packages, notificationManager: atom.notifications, deserializerManager: atom.deserializers, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, - setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), - setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(), - assert: atom.assert.bind(atom) + applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom) }) workspace2.deserialize(atom.workspace.serialize(), atom.deserializers) item = atom.workspace.getActivePaneItem() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 9d0c9d76a..ea92a0792 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -175,8 +175,7 @@ class AtomEnvironment extends Model @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers, - notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), - setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, assert: @assert.bind(this), confirm: @confirm.bind(this) + notificationManager: @notifications, @applicationDelegate, @clipboard, viewRegistry: @views, assert: @assert.bind(this) }) @themes.workspace = @workspace diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 94ae65757..8ad082a5f 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -15,12 +15,12 @@ class PaneContainer extends Model constructor: (params) -> super - {@config, notificationManager, deserializerManager, confirm} = params + {@config, applicationDelegate, notificationManager, deserializerManager} = params @emitter = new Emitter @subscriptions = new CompositeDisposable @itemRegistry = new ItemRegistry - @setRoot(new Pane({container: this, @config, notificationManager, deserializerManager, confirm})) + @setRoot(new Pane({container: this, @config, applicationDelegate, notificationManager, deserializerManager})) @setActivePane(@getRoot()) @monitorActivePaneItem() @monitorPaneItems() diff --git a/src/pane.coffee b/src/pane.coffee index 4a6d919c1..5f0d8dc1b 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -14,9 +14,7 @@ class Pane extends Model activeItem: undefined focused: false - @deserialize: (state, atomEnvironment) -> - {deserializers, config, notifications} = atomEnvironment - confirm = atomEnvironment.confirm.bind(atomEnvironment) + @deserialize: (state, {deserializers, applicationDelegate, config, notifications}) -> {items, activeItemURI, activeItemUri} = state activeItemURI ?= activeItemUri state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState)) @@ -27,15 +25,14 @@ class Pane extends Model new Pane(extend(state, { deserializerManager: deserializers, notificationManager: notifications, - confirm: confirm, - config: config + config, applicationDelegate })) constructor: (params) -> super { - @activeItem, @focused, @confirm, @notificationManager, @config, + @activeItem, @focused, @applicationDelegate, @notificationManager, @config, @deserializerManager } = params @@ -465,7 +462,7 @@ class Pane extends Model else return true - chosen = @confirm + chosen = @applicationDelegate.confirm message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?" detailedMessage: "Your changes will be lost if you close this item without saving." buttons: ["Save", "Cancel", "Don't Save"] @@ -518,7 +515,7 @@ class Pane extends Model saveOptions = item.getSaveDialogOptions?() ? {} saveOptions.defaultPath ?= item.getPath() - newItemPath = atom.showSaveDialogSync(saveOptions) + newItemPath = @applicationDelegate.showSaveDialog(saveOptions) if newItemPath try item.saveAs(newItemPath) @@ -650,7 +647,7 @@ class Pane extends Model @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this], @flexScale})) @setFlexScale(1) - newPane = new Pane(extend({@confirm, @deserializerManager, @config}, params)) + newPane = new Pane(extend({@applicationDelegate, @deserializerManager, @config}, params)) switch side when 'before' then @parent.insertChildBefore(this, newPane) when 'after' then @parent.insertChildAfter(this, newPane) diff --git a/src/workspace.coffee b/src/workspace.coffee index 0970fa686..b66445bbf 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -28,15 +28,15 @@ class Workspace extends Model { @packageManager, @config, @project, @grammarRegistry, @notificationManager, - @clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, - @setDocumentEdited, @assert, @confirm, @deserializerManager + @clipboard, @viewRegistry, @grammarRegistry, @applicationDelegate, @assert, + @deserializerManager } = params @emitter = new Emitter @openers = [] @destroyedItemURIs = [] - @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, @deserializerManager}) + @paneContainer = new PaneContainer({@config, @applicationDelegate, @notificationManager, @deserializerManager}) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @defaultDirectorySearcher = new DefaultDirectorySearcher() @@ -58,7 +58,7 @@ class Workspace extends Model @paneContainer.destroy() panelContainer.destroy() for panelContainer in @panelContainers - @paneContainer = new PaneContainer({@config, @confirm, @notificationManager, @deserializerManager}) + @paneContainer = new PaneContainer({@config, @applicationDelegate, @notificationManager, @deserializerManager}) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @panelContainers = @@ -163,19 +163,19 @@ class Workspace extends Model if item? and projectPath? document.title = "#{itemTitle} - #{projectPath} - #{appName}" - @setRepresentedFilename(itemPath ? projectPath) + @applicationDelegate.setRepresentedFilename(itemPath ? projectPath) else if projectPath? document.title = "#{projectPath} - #{appName}" - @setRepresentedFilename(projectPath) + @applicationDelegate.setRepresentedFilename(projectPath) else document.title = "#{itemTitle} - #{appName}" - @setRepresentedFilename("") + @applicationDelegate.setRepresentedFilename("") # On OS X, fades the application window's proxy icon when the current file # has been modified. updateDocumentEdited: => modified = @getActivePaneItem()?.isModified?() ? false - @setDocumentEdited(modified) + @applicationDelegate.setWindowDocumentEdited(modified) ### Section: Event Subscription @@ -470,9 +470,6 @@ class Workspace extends Model Promise.resolve(item) .then (item) => - if not pane - pane = new Pane({items: [item], @config, @confirm}) - @paneContainer.root = pane @itemOpened(item) pane.activateItem(item) if activateItem pane.activate() if activatePane @@ -503,7 +500,7 @@ class Workspace extends Model largeFileMode = fileSize >= 2 * 1048576 # 2MB if fileSize >= 20 * 1048576 # 20MB - choice = @confirm + choice = @applicationDelegate.confirm message: 'Atom will be unresponsive during the loading of very large files.' detailedMessage: "Do you still want to load this file?" buttons: ["Proceed", "Cancel"] @@ -521,7 +518,7 @@ class Workspace extends Model buildTextEditor: (params) -> params = _.extend({ @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, - @grammarRegistry, @project, @assert + @grammarRegistry, @project, @assert, @applicationDelegate }, params) new TextEditor(params) From 306ddf5491289d4760c473c51034c7c4f6021f1b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:10:56 -0600 Subject: [PATCH 193/316] Use ApplicationDelegate in CommandInstaller instead of bound confirm --- src/atom-environment.coffee | 2 +- src/command-installer.coffee | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index ea92a0792..dbb144678 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -171,7 +171,7 @@ class AtomEnvironment extends Model @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm, @config}) CommandInstaller = require './command-installer' - @commandInstaller = new CommandInstaller(@getVersion(), @confirm.bind(this)) + @commandInstaller = new CommandInstaller(@getVersion(), @applicationDelegate) @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers, diff --git a/src/command-installer.coffee b/src/command-installer.coffee index b224d531f..3d366037c 100644 --- a/src/command-installer.coffee +++ b/src/command-installer.coffee @@ -26,7 +26,7 @@ symlinkCommandWithPrivilegeSync = (sourcePath, destinationPath) -> module.exports = class CommandInstaller - constructor: (@appVersion, @confirm) -> + constructor: (@appVersion, @applicationDelegate) -> getInstallDirectory: -> "/usr/local/bin" @@ -36,7 +36,7 @@ class CommandInstaller installShellCommandsInteractively: -> showErrorDialog = (error) -> - @confirm + @applicationDelegate.confirm message: "Failed to install shell commands" detailedMessage: error.message @@ -48,7 +48,7 @@ class CommandInstaller if error? showErrorDialog(error) else - @confirm + @applicationDelegate.confirm message: "Commands installed." detailedMessage: "The shell commands `atom` and `apm` are installed." From f9a269ed995c4151678aef787573fe44657ed6dd Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:11:55 -0600 Subject: [PATCH 194/316] Prompt about checking out head revision in TextEditor, not GitRepository This allows us not to inject confirm or ApplicationDelegate into Project, GitRepositoryProvider, and GitRepository. --- src/atom-environment.coffee | 2 +- src/git-repository-provider.coffee | 4 ++-- src/git-repository.coffee | 19 ++----------------- src/project.coffee | 4 ++-- src/text-editor.coffee | 22 +++++++++++++++++----- 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index dbb144678..a53541940 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -168,7 +168,7 @@ class AtomEnvironment extends Model @clipboard = new Clipboard() Project = require './project' - @project = new Project({notificationManager: @notifications, packageManager: @packages, @confirm, @config}) + @project = new Project({notificationManager: @notifications, packageManager: @packages, @config}) CommandInstaller = require './command-installer' @commandInstaller = new CommandInstaller(@getVersion(), @applicationDelegate) diff --git a/src/git-repository-provider.coffee b/src/git-repository-provider.coffee index 1f2d2b776..593324d0c 100644 --- a/src/git-repository-provider.coffee +++ b/src/git-repository-provider.coffee @@ -48,7 +48,7 @@ isValidGitDirectorySync = (directory) -> module.exports = class GitRepositoryProvider - constructor: (@project, @config, @confirm) -> + constructor: (@project, @config) -> # Keys are real paths that end in `.git`. # Values are the corresponding GitRepository objects. @pathToRepository = {} @@ -75,7 +75,7 @@ class GitRepositoryProvider gitDirPath = gitDir.getPath() repo = @pathToRepository[gitDirPath] unless repo - repo = GitRepository.open(gitDirPath, {@project, @config, @confirm}) + repo = GitRepository.open(gitDirPath, {@project, @config}) return null unless repo repo.onDidDestroy(=> delete @pathToRepository[gitDirPath]) @pathToRepository[gitDirPath] = repo diff --git a/src/git-repository.coffee b/src/git-repository.coffee index e1ea58e44..1663f9ad4 100644 --- a/src/git-repository.coffee +++ b/src/git-repository.coffee @@ -80,7 +80,7 @@ class GitRepository for submodulePath, submoduleRepo of @repo.submodules submoduleRepo.upstream = {ahead: 0, behind: 0} - {@project, @config, @confirm, refreshOnWindowFocus} = options + {@project, @config, refreshOnWindowFocus} = options refreshOnWindowFocus ?= true if refreshOnWindowFocus @@ -443,25 +443,10 @@ class GitRepository # Subscribes to editor view event. checkoutHeadForEditor: (editor) -> - filePath = editor.getPath() - return unless filePath - - fileName = basename(filePath) - - checkoutHead = => + if filePath = editor.getPath() editor.buffer.reload() if editor.buffer.isModified() @checkoutHead(filePath) - if @config.get('editor.confirmCheckoutHeadRevision') - @confirm - message: 'Confirm Checkout HEAD Revision' - detailedMessage: "Are you sure you want to discard all changes to \"#{fileName}\" since the last Git commit?" - buttons: - OK: checkoutHead - Cancel: null - else - checkoutHead() - # Returns the corresponding {Repository} getRepo: (path) -> if @repo? diff --git a/src/project.coffee b/src/project.coffee index 645a54896..935e3a213 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -21,7 +21,7 @@ class Project extends Model Section: Construction and Destruction ### - constructor: ({@confirm, @notificationManager, packageManager, config}) -> + constructor: ({@notificationManager, packageManager, config}) -> @emitter = new Emitter @buffers = [] @paths = [] @@ -30,7 +30,7 @@ class Project extends Model @directoryProviders = [] @defaultDirectoryProvider = new DefaultDirectoryProvider() @repositoryPromisesByPath = new Map() - @repositoryProviders = [new GitRepositoryProvider(this, config, confirm)] + @repositoryProviders = [new GitRepositoryProvider(this, config)] @consumeServices(packageManager) destroyed: -> diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 875b437aa..5f5610dec 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -82,6 +82,7 @@ class TextEditor extends Model state.grammarRegistry = atomEnvironment.grammars state.project = atomEnvironment.project state.assert = atomEnvironment.assert.bind(atomEnvironment) + state.applicationDelegate = atomEnvironment.applicationDelegate new this(state) constructor: (params={}) -> @@ -91,7 +92,7 @@ class TextEditor extends Model @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @packageManager, - @clipboard, @viewRegistry, @grammarRegistry, @project, @assert + @clipboard, @viewRegistry, @grammarRegistry, @project, @assert, @applicationDelegate } = params throw new Error("Must pass a config parameter when constructing TextEditors") unless @config? @@ -480,7 +481,7 @@ class TextEditor extends Model newEditor = new TextEditor({ @buffer, displayBuffer, @tabLength, softTabs, suppressCursorCreation: true, @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, - @grammarRegistry, @project, @assert + @grammarRegistry, @project, @assert, @applicationDelegate }) for marker in @findMarkers(editorId: @id) marker.copy(editorId: newEditor.id, preserveFolds: true) @@ -642,9 +643,20 @@ class TextEditor extends Model checkoutHeadRevision: -> if filePath = this.getPath() - @project.repositoryForDirectory(new Directory(path.dirname(filePath))) - .then (repository) => - repository?.checkoutHeadForEditor(this) + checkoutHead = => + @project.repositoryForDirectory(new Directory(path.dirname(filePath))) + .then (repository) => + repository?.checkoutHeadForEditor(this) + + if @config.get('editor.confirmCheckoutHeadRevision') + @applicationDelegate.confirm + message: 'Confirm Checkout HEAD Revision' + detailedMessage: "Are you sure you want to discard all changes to \"#{path.basename(filePath)}\" since the last Git commit?" + buttons: + OK: checkoutHead + Cancel: null + else + checkoutHead() else Promise.resolve(false) From c8407167eea47765715d2587fac6365813e265b0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:20:06 -0600 Subject: [PATCH 195/316] Pass specific parameters to registerDefaultCommands --- src/atom-environment.coffee | 7 +++++-- src/register-default-commands.coffee | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index a53541940..d4d88cade 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -182,7 +182,7 @@ class AtomEnvironment extends Model @keymaps.subscribeToFileReadFailure() @keymaps.loadBundledKeymaps() - registerDefaultCommands(this) + @registerDefaultCommands() @registerDefaultOpeners() @registerDefaultDeserializers() @registerDefaultViewProviders() @@ -202,6 +202,9 @@ class AtomEnvironment extends Model @deserializers.add(TextEditor) @deserializers.add(TextBuffer) + registerDefaultCommands: -> + registerDefaultCommands({commandRegistry: @commands, @config, @commandInstaller}) + registerDefaultViewProviders: -> @views.addViewProvider Workspace, (model, env) -> new WorkspaceElement().initialize(model, env) @@ -242,7 +245,7 @@ class AtomEnvironment extends Model @keymaps.loadBundledKeymaps() @commands.clear() - registerDefaultCommands(this) + @registerDefaultCommands() @styles.restoreSnapshot(params?.stylesSnapshot ? []) diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index ac286b45f..80b7ff6c6 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -1,7 +1,7 @@ ipc = require 'ipc' -module.exports = (atom) -> - atom.commands.add 'atom-workspace', +module.exports = ({commandRegistry, commandInstaller, config}) -> + commandRegistry.add 'atom-workspace', 'pane:show-next-item': -> @getModel().getActivePane().activateNextItem() 'pane:show-previous-item': -> @getModel().getActivePane().activatePreviousItem() 'pane:show-item-1': -> @getModel().getActivePane().activateItemAtIndex(0) @@ -51,19 +51,19 @@ module.exports = (atom) -> 'window:focus-pane-on-left': -> @focusPaneViewOnLeft() 'window:focus-pane-on-right': -> @focusPaneViewOnRight() 'window:save-all': -> @getModel().saveAll() - 'window:toggle-invisibles': -> atom.config.set("editor.showInvisibles", not atom.config.get("editor.showInvisibles")) + 'window:toggle-invisibles': -> config.set("editor.showInvisibles", not config.get("editor.showInvisibles")) 'window:log-deprecation-warnings': -> Grim.logDeprecations() - 'window:toggle-auto-indent': -> atom.config.set("editor.autoIndent", not atom.config.get("editor.autoIndent")) + 'window:toggle-auto-indent': -> config.set("editor.autoIndent", not config.get("editor.autoIndent")) 'pane:reopen-closed-item': -> @getModel().reopenItem() 'core:close': -> @getModel().destroyActivePaneItemOrEmptyPane() 'core:save': -> @getModel().saveActivePaneItem() 'core:save-as': -> @getModel().saveActivePaneItemAs() if process.platform is 'darwin' - atom.commands.add 'atom-workspace', 'window:install-shell-commands', -> - atom.commandInstaller.installShellCommandsInteractively() + commandRegistry.add 'atom-workspace', 'window:install-shell-commands', -> + commandInstaller.installShellCommandsInteractively() - atom.commands.add 'atom-pane', + commandRegistry.add 'atom-pane', 'pane:save-items': -> @getModel().saveItems() 'pane:split-left': -> @getModel().splitLeft(copyActiveItem: true) 'pane:split-right': -> @getModel().splitRight(copyActiveItem: true) @@ -74,7 +74,7 @@ module.exports = (atom) -> 'pane:increase-size': -> @getModel().increaseSize() 'pane:decrease-size': -> @getModel().decreaseSize() - atom.commands.add 'atom-text-editor', stopEventPropagation( + commandRegistry.add 'atom-text-editor', stopEventPropagation( 'core:undo': -> @undo() 'core:redo': -> @redo() 'core:move-left': -> @moveLeft() @@ -115,7 +115,7 @@ module.exports = (atom) -> 'editor:select-line': -> @selectLinesContainingCursors() ) - atom.commands.add 'atom-text-editor', stopEventPropagationAndGroupUndo(atom.config, + commandRegistry.add 'atom-text-editor', stopEventPropagationAndGroupUndo(config, 'core:backspace': -> @backspace() 'core:delete': -> @delete() 'core:cut': -> @cutSelectedText() @@ -138,7 +138,7 @@ module.exports = (atom) -> 'editor:copy-selection': -> @copyOnlySelectedText() ) - atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagation( + commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagation( 'core:move-up': -> @moveUp() 'core:move-down': -> @moveDown() 'core:move-to-top': -> @moveToTop() @@ -170,12 +170,12 @@ module.exports = (atom) -> 'editor:fold-at-indent-level-9': -> @foldAllAtIndentLevel(8) 'editor:log-cursor-scope': -> @logCursorScope() 'editor:copy-path': -> @copyPathToClipboard() - 'editor:toggle-indent-guide': -> atom.config.set('editor.showIndentGuide', not atom.config.get('editor.showIndentGuide')) - 'editor:toggle-line-numbers': -> atom.config.set('editor.showLineNumbers', not atom.config.get('editor.showLineNumbers')) + 'editor:toggle-indent-guide': -> config.set('editor.showIndentGuide', not config.get('editor.showIndentGuide')) + 'editor:toggle-line-numbers': -> config.set('editor.showLineNumbers', not config.get('editor.showLineNumbers')) 'editor:scroll-to-cursor': -> @scrollToCursorPosition() ) - atom.commands.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo(atom.config, + commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo(config, 'editor:indent': -> @indent() 'editor:auto-indent': -> @autoIndentSelectedRows() 'editor:indent-selected-rows': -> @indentSelectedRows() From 65ae175e7228f59fdee1ecb68b8a0fdf46a6506d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:35:51 -0600 Subject: [PATCH 196/316] Pass explicit window global into AtomEnvironment on construction --- spec/atom-environment-spec.coffee | 4 ++-- spec/jasmine-test-runner.coffee | 2 +- spec/window-event-handler-spec.coffee | 2 +- src/atom-environment.coffee | 4 ++-- src/initialize-application-window.coffee | 2 +- src/window-event-handler.coffee | 20 ++++++++++---------- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 574994564..032349381 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -213,7 +213,7 @@ describe "AtomEnvironment", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> - atomEnvironment = new AtomEnvironment(applicationDelegate: atom.applicationDelegate) + atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window}) spyOn(atomEnvironment, 'saveStateSync') workspaceState = atomEnvironment.workspace.serialize() @@ -231,7 +231,7 @@ describe "AtomEnvironment", -> describe "::destroy()", -> it "unsubscribes from all buffers", -> - atomEnvironment = new AtomEnvironment(applicationDelegate: atom.applicationDelegate) + atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window}) waitsForPromise -> atomEnvironment.workspace.open("sample.js") diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 136be9215..00a2dcdd0 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -18,7 +18,7 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> applicationDelegate = new ApplicationDelegate() applicationDelegate.setRepresentedFilename = -> applicationDelegate.setWindowDocumentEdited = -> - window.atom = buildAtomEnvironment({applicationDelegate}) + window.atom = buildAtomEnvironment({applicationDelegate, window}) require './spec-helper' disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 037c15cb0..655dc149c 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -18,7 +18,7 @@ describe "WindowEventHandler", -> loadSettings.initialPath = initialPath loadSettings atom.project.destroy() - windowEventHandler = new WindowEventHandler({atomEnvironment: atom, applicationDelegate: atom.applicationDelegate}) + windowEventHandler = new WindowEventHandler({atomEnvironment: atom, applicationDelegate: atom.applicationDelegate, window}) projectPath = atom.project.getPaths()[0] afterEach -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index d4d88cade..39eac92a1 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -101,7 +101,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate} = params + {@applicationDelegate, @window} = params @state = {version: @constructor.version} @@ -652,7 +652,7 @@ class AtomEnvironment extends Model window.onerror = @previousWindowErrorHandler installWindowEventHandler: -> - @windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate}) + @windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate, @window}) uninstallWindowEventHandler: -> @windowEventHandler?.unsubscribe() diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 242201b32..71dac6898 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -16,7 +16,7 @@ process.env.NODE_ENV ?= 'production' unless devMode AtomEnvironment = require './atom-environment' ApplicationDelegate = require './application-delegate' -window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate}) +window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate, window}) atom.displayWindow() atom.loadStateSync() diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index bec5bc6cb..cf5a957ca 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -3,17 +3,17 @@ path = require 'path' fs = require 'fs-plus' listen = require './delegated-listener' -# Handles low-level events related to the window. +# Handles low-level events related to the @window. module.exports = class WindowEventHandler - constructor: ({@atomEnvironment, @applicationDelegate}) -> + constructor: ({@atomEnvironment, @applicationDelegate, @window}) -> @reloadRequested = false @subscriptions = new CompositeDisposable - @previousOnbeforeunloadHandler = window.onbeforeunload - window.onbeforeunload = @handleWindowBeforeunload - @addEventListener(window, 'focus', @handleWindowFocus) - @addEventListener(window, 'blur', @handleWindowBlur) + @previousOnbeforeunloadHandler = @window.onbeforeunload + @window.onbeforeunload = @handleWindowBeforeunload + @addEventListener(@window, 'focus', @handleWindowFocus) + @addEventListener(@window, 'blur', @handleWindowBlur) @addEventListener(document, 'keydown', @handleDocumentKeydown) @addEventListener(document, 'drop', @handleDocumentDrop) @@ -22,15 +22,15 @@ class WindowEventHandler @subscriptions.add listen(document, 'click', 'a', @handleLinkClick) @subscriptions.add listen(document, 'submit', 'form', @handleFormSubmit) - @subscriptions.add @atomEnvironment.commands.add window, + @subscriptions.add @atomEnvironment.commands.add @window, 'window:toggle-full-screen': @handleWindowToggleFullScreen 'window:close': @handleWindowClose 'window:reload': @handleWindowReload 'window:toggle-dev-tools': @handleWindowToggleDevTools if process.platform in ['win32', 'linux'] - @subscriptions.add @atomEnvironment.commands.add window, - 'window:toggle-menu-bar': @handleWindowToggleMenuBar + @subscriptions.add @atomEnvironment.commands.add @window, + '@window:toggle-menu-bar': @handleWindowToggleMenuBar @subscriptions.add @atomEnvironment.commands.add document, 'core:focus-next': @handleFocusNext @@ -54,7 +54,7 @@ class WindowEventHandler bindCommandToAction('core:cut', 'cut') unsubscribe: -> - window.onbeforeunload = @previousOnbeforeunloadHandler + @window.onbeforeunload = @previousOnbeforeunloadHandler @subscriptions.dispose() on: (target, eventName, handler) -> From 99b06e149b8390a20c78ba2af3cbd17e977e61d6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:37:26 -0600 Subject: [PATCH 197/316] Remove AtomEnvironment::requireWithGlobals --- src/atom-environment.coffee | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 39eac92a1..4ee2d5deb 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -807,28 +807,6 @@ class AtomEnvironment extends Model detail: error.message dismissable: true - # Require the module with the given globals. - # - # The globals will be set on the `window` object and removed after the - # require completes. - # - # * `id` The {String} module name or path. - # * `globals` An optional {Object} to set as globals during require. - requireWithGlobals: (id, globals={}) -> - existingGlobals = {} - for key, value of globals - existingGlobals[key] = window[key] - window[key] = value - - require(id) - - for key, value of existingGlobals - if value is undefined - delete window[key] - else - window[key] = value - return - onUpdateAvailable: (callback) -> @emitter.on 'update-available', callback From 54ce7495785f7106cb691321e80e37ed74b2192e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:38:02 -0600 Subject: [PATCH 198/316] Remove unused local --- src/atom-environment.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 4ee2d5deb..d9694d4ef 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -10,7 +10,7 @@ Model = require './model' WindowEventHandler = require './window-event-handler' StylesElement = require './styles-element' StorageFolder = require './storage-folder' -{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' +{getWindowLoadSettings} = require './window-load-settings-helpers' registerDefaultCommands = require './register-default-commands' Workspace = require './workspace' From 5941d9464a1b5dea7fe2cb2b735643faca4e4708 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:39:34 -0600 Subject: [PATCH 199/316] =?UTF-8?q?Don=E2=80=99t=20use=20window=20global?= =?UTF-8?q?=20in=20AtomEnvironment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/atom-environment.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index d9694d4ef..c116f777b 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -443,7 +443,7 @@ class AtomEnvironment extends Model # Extended: Focus the current window. focus: -> @applicationDelegate.focusWindow() - window.focus() + @window.focus() # Extended: Show the current window. show: -> From 903ecca1f78a3397dacdffc006c9604e099374be Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:47:12 -0600 Subject: [PATCH 200/316] Parameterize document on AtomEnvironment --- spec/atom-environment-spec.coffee | 4 ++-- spec/jasmine-test-runner.coffee | 2 +- spec/window-event-handler-spec.coffee | 2 +- src/atom-environment.coffee | 18 +++++++-------- src/initialize-application-window.coffee | 2 +- src/window-event-handler.coffee | 28 ++++++++++++------------ 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 032349381..5150540bc 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -213,7 +213,7 @@ describe "AtomEnvironment", -> describe "::unloadEditorWindow()", -> it "saves the serialized state of the window so it can be deserialized after reload", -> - atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window}) + atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window, document}) spyOn(atomEnvironment, 'saveStateSync') workspaceState = atomEnvironment.workspace.serialize() @@ -231,7 +231,7 @@ describe "AtomEnvironment", -> describe "::destroy()", -> it "unsubscribes from all buffers", -> - atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window}) + atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window, document}) waitsForPromise -> atomEnvironment.workspace.open("sample.js") diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 00a2dcdd0..173936133 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -18,7 +18,7 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> applicationDelegate = new ApplicationDelegate() applicationDelegate.setRepresentedFilename = -> applicationDelegate.setWindowDocumentEdited = -> - window.atom = buildAtomEnvironment({applicationDelegate, window}) + window.atom = buildAtomEnvironment({applicationDelegate, window, document}) require './spec-helper' disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI diff --git a/spec/window-event-handler-spec.coffee b/spec/window-event-handler-spec.coffee index 655dc149c..3148942b4 100644 --- a/spec/window-event-handler-spec.coffee +++ b/spec/window-event-handler-spec.coffee @@ -18,7 +18,7 @@ describe "WindowEventHandler", -> loadSettings.initialPath = initialPath loadSettings atom.project.destroy() - windowEventHandler = new WindowEventHandler({atomEnvironment: atom, applicationDelegate: atom.applicationDelegate, window}) + windowEventHandler = new WindowEventHandler({atomEnvironment: atom, applicationDelegate: atom.applicationDelegate, window, document}) projectPath = atom.project.getPaths()[0] afterEach -> diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index c116f777b..85e54d292 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -101,7 +101,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate, @window} = params + {@applicationDelegate, @window, @document} = params @state = {version: @constructor.version} @@ -472,9 +472,9 @@ class AtomEnvironment extends Model setFullScreen: (fullScreen=false) -> @applicationDelegate.setWindowFullScreen(fullScreen) if fullScreen - document.body.classList.add("fullscreen") + @document.body.classList.add("fullscreen") else - document.body.classList.remove("fullscreen") + @document.body.classList.remove("fullscreen") # Extended: Toggle the full screen state of the current window. toggleFullScreen: -> @@ -587,13 +587,13 @@ class AtomEnvironment extends Model @themes.loadBaseStylesheets() @setBodyPlatformClass() - document.head.appendChild(@styles.buildStylesElement()) + @document.head.appendChild(@styles.buildStylesElement()) @packages.loadPackages() workspaceElement = @views.getView(@workspace) @keymaps.defaultTarget = workspaceElement - document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) + @document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) @watchProjectPath() @@ -652,7 +652,7 @@ class AtomEnvironment extends Model window.onerror = @previousWindowErrorHandler installWindowEventHandler: -> - @windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate, @window}) + @windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate, @window, @document}) uninstallWindowEventHandler: -> @windowEventHandler?.unsubscribe() @@ -817,16 +817,16 @@ class AtomEnvironment extends Model @disposables.add(@applicationDelegate.onUpdateAvailable(@updateAvailable.bind(this))) setBodyPlatformClass: -> - document.body.classList.add("platform-#{process.platform}") + @document.body.classList.add("platform-#{process.platform}") setAutoHideMenuBar: (autoHide) -> @applicationDelegate.setAutoHideWindowMenuBar(autoHide) @applicationDelegate.setWindowMenuBarVisibility(not autoHide) dispatchApplicationMenuCommand: (command, arg) -> - activeElement = document.activeElement + activeElement = @document.activeElement # Use the workspace element if body has focus - if activeElement is document.body and workspaceElement = @views.getView(@workspace) + if activeElement is @document.body and workspaceElement = @views.getView(@workspace) activeElement = workspaceElement @commands.dispatch(activeElement, command, arg) diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 71dac6898..44bec588e 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -16,7 +16,7 @@ process.env.NODE_ENV ?= 'production' unless devMode AtomEnvironment = require './atom-environment' ApplicationDelegate = require './application-delegate' -window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate, window}) +window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate, window, document}) atom.displayWindow() atom.loadStateSync() diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index cf5a957ca..18191ccaa 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -6,7 +6,7 @@ listen = require './delegated-listener' # Handles low-level events related to the @window. module.exports = class WindowEventHandler - constructor: ({@atomEnvironment, @applicationDelegate, @window}) -> + constructor: ({@atomEnvironment, @applicationDelegate, @window, @document}) -> @reloadRequested = false @subscriptions = new CompositeDisposable @@ -15,12 +15,12 @@ class WindowEventHandler @addEventListener(@window, 'focus', @handleWindowFocus) @addEventListener(@window, 'blur', @handleWindowBlur) - @addEventListener(document, 'keydown', @handleDocumentKeydown) - @addEventListener(document, 'drop', @handleDocumentDrop) - @addEventListener(document, 'dragover', @handleDocumentDragover) - @addEventListener(document, 'contextmenu', @handleDocumentContextmenu) - @subscriptions.add listen(document, 'click', 'a', @handleLinkClick) - @subscriptions.add listen(document, 'submit', 'form', @handleFormSubmit) + @addEventListener(@document, 'keydown', @handleDocumentKeydown) + @addEventListener(@document, 'drop', @handleDocumentDrop) + @addEventListener(@document, 'dragover', @handleDocumentDragover) + @addEventListener(@document, 'contextmenu', @handleDocumentContextmenu) + @subscriptions.add listen(@document, 'click', 'a', @handleLinkClick) + @subscriptions.add listen(@document, 'submit', 'form', @handleFormSubmit) @subscriptions.add @atomEnvironment.commands.add @window, 'window:toggle-full-screen': @handleWindowToggleFullScreen @@ -32,7 +32,7 @@ class WindowEventHandler @subscriptions.add @atomEnvironment.commands.add @window, '@window:toggle-menu-bar': @handleWindowToggleMenuBar - @subscriptions.add @atomEnvironment.commands.add document, + @subscriptions.add @atomEnvironment.commands.add @document, 'core:focus-next': @handleFocusNext 'core:focus-previous': @handleFocusPrevious @@ -42,7 +42,7 @@ class WindowEventHandler # `.native-key-bindings` class. handleNativeKeybindings: -> bindCommandToAction = (command, action) => - @addEventListener document, command, (event) => + @addEventListener @document, command, (event) => if event.target.webkitMatchesSelector('.native-key-bindings') @applicationDelegate.getCurrentWindow().webContents[action]() @@ -81,14 +81,14 @@ class WindowEventHandler event.dataTransfer.dropEffect = 'none' eachTabIndexedElement: (callback) -> - for element in document.querySelectorAll('[tabindex]') + for element in @document.querySelectorAll('[tabindex]') continue if element.disabled continue unless element.tabIndex >= 0 callback(element, element.tabIndex) return handleFocusNext: => - focusedTabIndex = document.activeElement.tabIndex ? -Infinity + focusedTabIndex = @document.activeElement.tabIndex ? -Infinity nextElement = null nextTabIndex = Infinity @@ -109,7 +109,7 @@ class WindowEventHandler lowestElement.focus() handleFocusPrevious: => - focusedTabIndex = document.activeElement.tabIndex ? Infinity + focusedTabIndex = @document.activeElement.tabIndex ? Infinity previousElement = null previousTabIndex = -Infinity @@ -130,10 +130,10 @@ class WindowEventHandler highestElement.focus() handleWindowFocus: -> - document.body.classList.remove('is-blurred') + @document.body.classList.remove('is-blurred') handleWindowBlur: => - document.body.classList.add('is-blurred') + @document.body.classList.add('is-blurred') @atomEnvironment.storeDefaultWindowDimensions() handleWindowBeforeunload: => From 3ef6a9b63b87e97c2075a6243c12632ed66d5959 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 19:54:29 -0600 Subject: [PATCH 201/316] Remove workspaceParentSelector and always attach to document body Tests never call startEditorWindow anyway. --- spec/spec-helper.coffee | 2 -- src/atom-environment.coffee | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 7d81541a4..c659a6954 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -63,8 +63,6 @@ beforeEach -> atom.project.setPaths([path.join(@specDirectory, 'fixtures')]) - atom.workspaceParentSelectorctor = '#jasmine-content' - window.resetTimeouts() spyOn(_._, "now").andCallFake -> window.now spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 85e54d292..d8b8ed754 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -40,7 +40,6 @@ module.exports = class AtomEnvironment extends Model @version: 1 # Increment this when the serialization format changes - workspaceParentSelectorctor: 'body' lastUncaughtError: null ### @@ -593,7 +592,7 @@ class AtomEnvironment extends Model workspaceElement = @views.getView(@workspace) @keymaps.defaultTarget = workspaceElement - @document.querySelector(@workspaceParentSelectorctor).appendChild(workspaceElement) + @document.body.appendChild(workspaceElement) @watchProjectPath() From 74d644ac7334e433d1567f5950182bb7e03dbb77 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 20:09:56 -0600 Subject: [PATCH 202/316] Clear GrammarRegistry in AtomEnvironment::reset --- package.json | 2 +- spec/spec-helper.coffee | 1 - src/atom-environment.coffee | 2 ++ src/grammar-registry.coffee | 3 --- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6c0cd4254..250d0ecdd 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "color": "^0.7.3", "event-kit": "^1.3.0", "find-parent-dir": "^0.3.0", - "first-mate": "^5.0.0", + "first-mate": "^5.1.0", "fs-plus": "^2.8.0", "fstream": "0.1.24", "fuzzaldrin": "^2.1", diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index c659a6954..7ed77bc2a 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -69,7 +69,6 @@ beforeEach -> spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout spyOn(atom, 'saveStateSync') - atom.grammars.clearGrammarOverrides() spyOn(atom.packages, 'resolvePackagePath').andCallThrough() diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index d8b8ed754..de410ef23 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -246,6 +246,8 @@ class AtomEnvironment extends Model @commands.clear() @registerDefaultCommands() + @grammars.clear() + @styles.restoreSnapshot(params?.stylesSnapshot ? []) @menu.clear() diff --git a/src/grammar-registry.coffee b/src/grammar-registry.coffee index 65d6b1731..4a5352275 100644 --- a/src/grammar-registry.coffee +++ b/src/grammar-registry.coffee @@ -123,6 +123,3 @@ class GrammarRegistry extends FirstMate.GrammarRegistry clearGrammarOverrides: -> @grammarOverridesByPath = {} undefined - - clearObservers: -> - @emitter = new Emitter From 974743d46cfd60f00beaef6e107e5477ca6c6c68 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Oct 2015 20:11:52 -0600 Subject: [PATCH 203/316] Attach CommandRegistry to window in constructor --- src/atom-environment.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index de410ef23..363371ed7 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -133,6 +133,7 @@ class AtomEnvironment extends Model CommandRegistry = require './command-registry' @commands = new CommandRegistry + @commands.attach(@window) GrammarRegistry = require './grammar-registry' @grammars = new GrammarRegistry({@config}) @@ -607,8 +608,6 @@ class AtomEnvironment extends Model @setAutoHideMenuBar(newValue) @setAutoHideMenuBar(true) if @config.get('core.autoHideMenuBar') - @commands.attach(window) - @openInitialEmptyEditorIfNecessary() unloadEditorWindow: -> From a3190e455137ac7cdceacdd1dd3bc257b6ff5787 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 09:18:54 +0200 Subject: [PATCH 204/316] Use @window when (un)installing uncaught error handler --- src/atom-environment.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 363371ed7..1b592fc73 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -628,8 +628,8 @@ class AtomEnvironment extends Model @workspace.open(null) installUncaughtErrorHandler: -> - @previousWindowErrorHandler = window.onerror - window.onerror = => + @previousWindowErrorHandler = @window.onerror + @window.onerror = => @lastUncaughtError = Array::slice.call(arguments) [message, url, line, column, originalError] = @lastUncaughtError @@ -649,7 +649,7 @@ class AtomEnvironment extends Model @emitter.emit 'did-throw-error', {message, url, line, column, originalError} uninstallUncaughtErrorHandler: -> - window.onerror = @previousWindowErrorHandler + @window.onerror = @previousWindowErrorHandler installWindowEventHandler: -> @windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate, @window, @document}) From 0ea84ab19286dd779c655cbfc332797d0abcf6db Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 09:31:50 +0200 Subject: [PATCH 205/316] Register default target for keymaps in ctor --- src/atom-environment.coffee | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 1b592fc73..ed1271d8f 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -186,6 +186,7 @@ class AtomEnvironment extends Model @registerDefaultOpeners() @registerDefaultDeserializers() @registerDefaultViewProviders() + @registerDefaultTargetForKeymaps() @installUncaughtErrorHandler() @installWindowEventHandler() @@ -234,6 +235,9 @@ class AtomEnvironment extends Model when 'atom://.atom/init-script' @workspace.open(@getUserInitScriptPath()) + registerDefaultTargetForKeymaps: -> + @keymaps.defaultTarget = @views.getView(@workspace) + reset: (params) -> @deserializers.clear() @registerDefaultDeserializers() @@ -593,9 +597,7 @@ class AtomEnvironment extends Model @packages.loadPackages() - workspaceElement = @views.getView(@workspace) - @keymaps.defaultTarget = workspaceElement - @document.body.appendChild(workspaceElement) + @document.body.appendChild(@views.getView(@workspace)) @watchProjectPath() From f5f2d5dcd60cebee687d50375ac180183c43d290 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 09:50:50 +0200 Subject: [PATCH 206/316] Remove remaining references to window global --- src/atom-environment.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index ed1271d8f..c6979a90f 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -574,8 +574,8 @@ class AtomEnvironment extends Model return if @inSpecMode() workspaceElement = @views.getView(@workspace) - backgroundColor = window.getComputedStyle(workspaceElement)['background-color'] - window.localStorage.setItem('atom:window-background-color', backgroundColor) + backgroundColor = @window.getComputedStyle(workspaceElement)['background-color'] + @window.localStorage.setItem('atom:window-background-color', backgroundColor) # Call this method when establishing a real application window. startEditorWindow: -> From 57f6fc5772245ae9b3f7d19c964019af7d7f054f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 09:56:46 +0200 Subject: [PATCH 207/316] Observe core.autoHideMenuBar in AtomEnvironment ctor --- src/atom-environment.coffee | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index c6979a90f..aafe1f9fe 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -191,6 +191,8 @@ class AtomEnvironment extends Model @installUncaughtErrorHandler() @installWindowEventHandler() + @observeAutoHideMenuBar() + setConfigSchema: -> @config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))} @@ -238,6 +240,11 @@ class AtomEnvironment extends Model registerDefaultTargetForKeymaps: -> @keymaps.defaultTarget = @views.getView(@workspace) + observeAutoHideMenuBar: -> + @disposables.add @config.onDidChange 'core.autoHideMenuBar', ({newValue}) => + @setAutoHideMenuBar(newValue) + @setAutoHideMenuBar(true) if @config.get('core.autoHideMenuBar') + reset: (params) -> @deserializers.clear() @registerDefaultDeserializers() @@ -606,9 +613,6 @@ class AtomEnvironment extends Model @requireUserInitScript() unless @getLoadSettings().safeMode @menu.update() - @disposables.add @config.onDidChange 'core.autoHideMenuBar', ({newValue}) => - @setAutoHideMenuBar(newValue) - @setAutoHideMenuBar(true) if @config.get('core.autoHideMenuBar') @openInitialEmptyEditorIfNecessary() From ed201d41cd81d9bc7daade267ace3227d3955833 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 10:11:53 +0200 Subject: [PATCH 208/316] :green_heart: Clear CommandRegistry on AtomEnvironment destruction --- src/atom-environment.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index aafe1f9fe..866c71945 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -288,11 +288,13 @@ class AtomEnvironment extends Model destroy: -> return if not @project + @disposables.dispose() @workspace?.destroy() @workspace = null @themes.workspace = null @project?.destroy() @project = null + @commands.clear() @uninstallWindowEventHandler() From d9af8686ed006e27f04e3c50c03413fd37917168 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 10:29:56 +0200 Subject: [PATCH 209/316] :fire: Avoid attaching CommandRegistry to window twice --- spec/jasmine-test-runner.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 173936133..5f365b16b 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -40,8 +40,6 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> document.head.appendChild(atom.styles.buildStylesElement()) document.body.appendChild(jasmineContent) - atom.commands.attach(window) - jasmineEnv.execute() promise From b25d3e944bfacbfbeb28879e060b4bfae2d0b15a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 12:41:00 +0200 Subject: [PATCH 210/316] Parameterize configDirPath and move config.load in ctor --- spec/jasmine-test-runner.coffee | 1 - spec/spec-helper.coffee | 6 +----- src/atom-environment.coffee | 22 +++++++++++++--------- src/config.coffee | 15 ++++++++++++--- src/initialize-application-window.coffee | 2 +- src/package-manager.coffee | 2 +- src/storage-folder.coffee | 6 +++++- src/style-manager.coffee | 2 ++ 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 5f365b16b..04b875ac8 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -37,7 +37,6 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> jasmineContent = document.createElement('div') jasmineContent.setAttribute('id', 'jasmine-content') - document.head.appendChild(atom.styles.buildStylesElement()) document.body.appendChild(jasmineContent) jasmineEnv.execute() diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 7ed77bc2a..9ec8e6460 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -20,10 +20,6 @@ jasmineStyle = document.createElement('style') jasmineStyle.textContent = atom.themes.loadStylesheet(atom.themes.resolveStylesheet('../static/jasmine')) document.head.appendChild(jasmineStyle) -atom.themes.loadBaseStylesheets() -initialStyleElements = atom.styles.getSnapshot() -atom.themes.initialLoadComplete = true - fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') atom.packages.packageDirPaths.unshift(fixturePackagesPath) @@ -107,7 +103,7 @@ beforeEach -> addCustomMatchers(this) afterEach -> - atom.reset(stylesSnapshot: initialStyleElements) + atom.reset() document.getElementById('jasmine-content').innerHTML = '' unless window.debugContent diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 866c71945..05e99509c 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -105,8 +105,7 @@ class AtomEnvironment extends Model @state = {version: @constructor.version} @loadTime = null - {devMode, safeMode, resourcePath} = @getLoadSettings() - configDirPath = @getConfigDirPath() + {devMode, safeMode, resourcePath, configDirPath} = @getLoadSettings() @emitter = new Emitter @disposables = new CompositeDisposable @@ -179,6 +178,16 @@ class AtomEnvironment extends Model }) @themes.workspace = @workspace + @config.load() + + @themes.loadBaseStylesheets() + @initialStyleElements = @styles.getSnapshot() + @themes.initialLoadComplete = true + @setBodyPlatformClass() + + @stylesElement = @styles.buildStylesElement() + @document.head.appendChild(@stylesElement) + @keymaps.subscribeToFileReadFailure() @keymaps.loadBundledKeymaps() @@ -260,7 +269,7 @@ class AtomEnvironment extends Model @grammars.clear() - @styles.restoreSnapshot(params?.stylesSnapshot ? []) + @styles.restoreSnapshot(@initialStyleElements) @menu.clear() @@ -295,6 +304,7 @@ class AtomEnvironment extends Model @project?.destroy() @project = null @commands.clear() + @stylesElement.remove() @uninstallWindowEventHandler() @@ -598,12 +608,6 @@ class AtomEnvironment extends Model @disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this))) @listenForUpdates() - @config.load() - @themes.loadBaseStylesheets() - @setBodyPlatformClass() - - @document.head.appendChild(@styles.buildStylesElement()) - @packages.loadPackages() @document.body.appendChild(@views.getView(@workspace)) diff --git a/src/config.coffee b/src/config.coffee index bdeabba00..2faf35f22 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -332,8 +332,9 @@ class Config # Created during initialization, available as `atom.config` constructor: ({@configDirPath, @resourcePath, @notificationManager}={}) -> - @configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson']) - @configFilePath ?= path.join(@configDirPath, 'config.cson') + if @configDirPath? + @configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson']) + @configFilePath ?= path.join(@configDirPath, 'config.cson') @clear() clear: -> @@ -356,6 +357,8 @@ class Config @save() debouncedSave = _.debounce(save, 100) + shouldNotAccessFileSystem: -> not @configDirPath? + ### Section: Config Subscription ### @@ -726,7 +729,7 @@ class Config ### initializeConfigDirectory: (done) -> - return if fs.existsSync(@configDirPath) + return if fs.existsSync(@configDirPath) or @shouldNotAccessFileSystem() fs.makeTreeSync(@configDirPath) @@ -742,6 +745,8 @@ class Config fs.traverseTree(templateConfigDirPath, onConfigDirFile, (path) -> true) loadUserConfig: -> + return if @shouldNotAccessFileSystem() + unless fs.existsSync(@configFilePath) fs.makeTreeSync(path.dirname(@configFilePath)) CSON.writeFileSync(@configFilePath, {}) @@ -765,6 +770,8 @@ class Config @notifyFailure(message, detail) observeUserConfig: -> + return if @shouldNotAccessFileSystem() + try @watchSubscription ?= pathWatcher.watch @configFilePath, (eventType) => @requestLoad() if eventType is 'change' and @watchSubscription? @@ -784,6 +791,8 @@ class Config @notificationManager.addError(errorMessage, {detail, dismissable: true}) save: -> + return if @shouldNotAccessFileSystem() + allSettings = {'*': @settings} allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource(@getUserConfigPath()) try diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 44bec588e..71b1f3b15 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -16,7 +16,7 @@ process.env.NODE_ENV ?= 'production' unless devMode AtomEnvironment = require './atom-environment' ApplicationDelegate = require './application-delegate' -window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate, window, document}) +window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate, window, document, configDirPath: process.env.ATOM_HOME}) atom.displayWindow() atom.loadStateSync() diff --git a/src/package-manager.coffee b/src/package-manager.coffee index aeabf62a3..f6cef9465 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -37,7 +37,7 @@ class PackageManager @emitter = new Emitter @activationHookEmitter = new Emitter @packageDirPaths = [] - unless safeMode + if configDirPath? and not safeMode if @devMode @packageDirPaths.push(path.join(configDirPath, "dev", "packages")) @packageDirPaths.push(path.join(configDirPath, "packages")) diff --git a/src/storage-folder.coffee b/src/storage-folder.coffee index bf969dee2..da8af3f2e 100644 --- a/src/storage-folder.coffee +++ b/src/storage-folder.coffee @@ -4,12 +4,16 @@ fs = require "fs-plus" module.exports = class StorageFolder constructor: (containingPath) -> - @path = path.join(containingPath, "storage") + @path = path.join(containingPath, "storage") if containingPath? store: (name, object) -> + return unless @path? + fs.writeFileSync(@pathForKey(name), JSON.stringify(object), 'utf8') load: (name) -> + return unless @path? + statePath = @pathForKey(name) try stateString = fs.readFileSync(statePath, 'utf8') diff --git a/src/style-manager.coffee b/src/style-manager.coffee index 8b3349b7a..8f932d229 100644 --- a/src/style-manager.coffee +++ b/src/style-manager.coffee @@ -168,6 +168,8 @@ class StyleManager # # Returns a {String}. getUserStyleSheetPath: -> + return "" unless @configDirPath? + stylesheetPath = fs.resolve(path.join(@configDirPath, 'styles'), ['css', 'less']) if fs.isFileSync(stylesheetPath) stylesheetPath From 4b10f8a2b0e71678386203aed5aab442e95535b9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 12:47:33 +0200 Subject: [PATCH 211/316] :fire: Avoid mocking atom.config in spec-helper --- spec/config-spec.coffee | 2 ++ spec/spec-helper.coffee | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 5aff0eff2..44c594d29 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -7,6 +7,8 @@ describe "Config", -> dotAtomPath = null beforeEach -> + spyOn(atom.config, "load") + spyOn(atom.config, "save") dotAtomPath = temp.path('dot-atom-dir') atom.config.configDirPath = dotAtomPath atom.config.configFilePath = path.join(atom.config.configDirPath, "atom.config.cson") diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 9ec8e6460..ebbc3c977 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -71,9 +71,7 @@ beforeEach -> # prevent specs from modifying Atom's menus spyOn(atom.menu, 'sendToBrowserProcess') - # reset config before each spec; don't load or save from/to `config.json` - spyOn(atom.config, 'load') - spyOn(atom.config, 'save') + # reset config before each spec atom.config.set "core.destroyEmptyPanes", false atom.config.set "editor.fontFamily", "Courier" atom.config.set "editor.fontSize", 16 @@ -83,8 +81,6 @@ beforeEach -> atom.config.set "editor.useShadowDOM", true advanceClock(1000) window.setTimeout.reset() - atom.config.load.reset() - atom.config.save.reset() # make editor display updates synchronous TextEditorElement::setUpdatedSynchronously(true) From c5860ce6b64b365192faba6cef8784ff705f80a9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 12:59:22 +0200 Subject: [PATCH 212/316] :bug: Fix typo --- src/application-delegate.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index 74a3dd04b..3492df05c 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -81,7 +81,7 @@ class ApplicationDelegate setRepresentedDirectoryPaths: (paths) -> loadSettings = getWindowLoadSettings() - loadSettings['initialPaths'] = value + loadSettings['initialPaths'] = paths setWindowLoadSettings(loadSettings) setAutoHideWindowMenuBar: (autoHide) -> From 789af9fc6970ed9ce9aaefe1d424ea941e733563 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 13:01:54 +0200 Subject: [PATCH 213/316] Use params instead of loadSettings --- src/atom-environment.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 05e99509c..2d0e4a632 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -100,12 +100,12 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate, @window, @document} = params + {@applicationDelegate, @window, @document, configDirPath} = params @state = {version: @constructor.version} @loadTime = null - {devMode, safeMode, resourcePath, configDirPath} = @getLoadSettings() + {devMode, safeMode, resourcePath} = @getLoadSettings() @emitter = new Emitter @disposables = new CompositeDisposable From e916bd83b2b201ee7f4ce776b3b33cc9bd02f6f8 Mon Sep 17 00:00:00 2001 From: Wliu Date: Wed, 14 Oct 2015 13:03:22 +0000 Subject: [PATCH 214/316] :memo: node.js -> Node.js [ci skip] --- docs/build-instructions/linux.md | 6 +++--- docs/build-instructions/os-x.md | 2 +- docs/build-instructions/windows.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 85e40a2bc..07150394b 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -7,7 +7,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. * OS with 64-bit or 32-bit architecture * C++ toolchain * [Git](http://git-scm.com/) - * [node.js](http://nodejs.org/download/) (0.10.x or above) + * [Node.js](http://nodejs.org/download/) (0.10.x or above) * [npm](https://www.npmjs.com/) v1.4.x or above (automatically bundled with Node.js) * `npm -v` to check the version. * `npm config set python /usr/bin/python2 -g` to ensure that gyp uses python2. @@ -17,7 +17,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. ### Ubuntu / Debian * `sudo apt-get install build-essential git libgnome-keyring-dev fakeroot` -* Instructions for [node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions). +* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#debian-and-ubuntu-based-linux-distributions). * Make sure the command `node` is available after Node.js installation (some systems install it as `nodejs`). * Use `which node` to check if it is available. * Use `sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10` to update it. @@ -25,7 +25,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. ### Fedora / CentOS / RHEL * `sudo dnf --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools` -* Instructions for [node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#enterprise-linux-and-fedora). +* Instructions for [Node.js](https://github.com/nodejs/node-v0.x-archive/wiki/Installing-Node.js-via-package-manager#enterprise-linux-and-fedora). ### Arch diff --git a/docs/build-instructions/os-x.md b/docs/build-instructions/os-x.md index e97ab6f5a..76da080c9 100644 --- a/docs/build-instructions/os-x.md +++ b/docs/build-instructions/os-x.md @@ -3,7 +3,7 @@ ## Requirements * OS X 10.8 or later - * [node.js](http://nodejs.org/download/) (0.10.x or above) + * [Node.js](http://nodejs.org/download/) (0.10.x or above) * Command Line Tools for [Xcode](https://developer.apple.com/xcode/downloads/) (run `xcode-select --install` to install) ## Instructions diff --git a/docs/build-instructions/windows.md b/docs/build-instructions/windows.md index df0a80c13..74dddf8f8 100644 --- a/docs/build-instructions/windows.md +++ b/docs/build-instructions/windows.md @@ -5,7 +5,7 @@ ### On Windows 7 * [Visual C++ 2010 Express](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_4) * [Visual Studio 2010 Service Pack 1](http://www.microsoft.com/en-us/download/details.aspx?id=23691) - * [node.js](http://nodejs.org/download/) (0.10.x or above) + * [Node.js](http://nodejs.org/download/) (0.10.x or above) * For 64-bit builds of node and native modules you **must** have the [Windows 7 64-bit SDK](http://www.microsoft.com/en-us/download/details.aspx?id=8279). You may also need the [compiler update for the Windows SDK 7.1](http://www.microsoft.com/en-us/download/details.aspx?id=4422) @@ -20,7 +20,7 @@ * [Visual Studio Express 2013 or 2015 for Windows Desktop](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_2) * For VS 2015, be sure to customize the installation to include Visual C++. It's not installed by default. * Some have experienced issues with Node locating C++ on VS 2015. If so, try VS 2013. - * [node.js](http://nodejs.org/download/) (0.10.x or above) + * [Node.js](http://nodejs.org/download/) (0.10.x or above) * [Python](https://www.python.org/downloads/) v2.7.x (required by [node-gyp](https://github.com/TooTallNate/node-gyp)) * [GitHub Desktop](http://desktop.github.com/) From 6b01811d2082c0947ccc25f0005bf415d15ec96e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 15:59:25 +0200 Subject: [PATCH 215/316] Avoid stack overflow when scrolling with non-integer values We were mistakenly using the rounded scroll top to guard against such cases. This fixes it by using `@realScrollTop` instead. --- spec/text-editor-presenter-spec.coffee | 28 ++++++++++++++++++++++++++ src/text-editor-presenter.coffee | 6 ++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 69fa7bd9d..71cdcb7f1 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -724,6 +724,20 @@ describe "TextEditorPresenter", -> expect(presenter.getState().content.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1 describe ".scrollTop", -> + it "doesn't get stuck when setting a non-integer position in an event listener", -> + presenter = buildPresenter(scrollTop: 0, lineHeight: 10, explicitHeight: 20) + expect(presenter.getState().content.scrollTop).toBe(0) + + presenter.onDidChangeScrollTop -> + presenter.setScrollTop(1.5) + presenter.getState() # trigger scroll update + + presenter.setScrollTop(1.5) + presenter.getState() # trigger scroll update + + expect(presenter.getScrollTop()).toBe(2) + expect(presenter.getRealScrollTop()).toBe(1.5) + it "changes based on the scroll operation that was performed last", -> presenter = buildPresenter(scrollTop: 0, lineHeight: 10, explicitHeight: 20) expect(presenter.getState().content.scrollTop).toBe(0) @@ -837,6 +851,20 @@ describe "TextEditorPresenter", -> expect(presenter.getState().content.scrollTop).toBe presenter.contentHeight - presenter.clientHeight describe ".scrollLeft", -> + it "doesn't get stuck when setting a non-integer position in an event listener", -> + presenter = buildPresenter(scrollLeft: 0, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 10) + expect(presenter.getState().content.scrollLeft).toBe(0) + + presenter.onDidChangeScrollLeft -> + presenter.setScrollLeft(1.5) + presenter.getState() # trigger scroll update + + presenter.setScrollLeft(1.5) + presenter.getState() # trigger scroll update + + expect(presenter.getScrollLeft()).toBe(2) + expect(presenter.getRealScrollLeft()).toBe(1.5) + it "changes based on the scroll operation that was performed last", -> presenter = buildPresenter(scrollLeft: 0, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 10) expect(presenter.getState().content.scrollLeft).toBe(0) diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 184d597cc..efa7845fe 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -22,6 +22,8 @@ class TextEditorPresenter @gutterWidth ?= 0 @tileSize ?= 6 + @realScrollTop = @scrollTop + @realScrollLeft = @scrollLeft @disposables = new CompositeDisposable @emitter = new Emitter @visibleHighlights = {} @@ -775,7 +777,7 @@ class TextEditorPresenter updateScrollTop: (scrollTop) -> scrollTop = @constrainScrollTop(scrollTop) - if scrollTop isnt @scrollTop and not Number.isNaN(scrollTop) + if scrollTop isnt @realScrollTop and not Number.isNaN(scrollTop) @realScrollTop = scrollTop @scrollTop = Math.round(scrollTop) @scrollRow = Math.round(@scrollTop / @lineHeight) @@ -792,7 +794,7 @@ class TextEditorPresenter updateScrollLeft: (scrollLeft) -> scrollLeft = @constrainScrollLeft(scrollLeft) - if scrollLeft isnt @scrollLeft and not Number.isNaN(scrollLeft) + if scrollLeft isnt @realScrollLeft and not Number.isNaN(scrollLeft) @realScrollLeft = scrollLeft @scrollLeft = Math.round(scrollLeft) @scrollColumn = Math.round(@scrollLeft / @baseCharacterWidth) From 582fa571b8f678626ed7cd4a6ea4f2e96453bc33 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 16:20:42 +0200 Subject: [PATCH 216/316] :memo: Better spec description --- spec/text-editor-presenter-spec.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 71cdcb7f1..541599ea8 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -724,7 +724,7 @@ describe "TextEditorPresenter", -> expect(presenter.getState().content.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1 describe ".scrollTop", -> - it "doesn't get stuck when setting a non-integer position in an event listener", -> + it "doesn't get stuck when repeatedly setting the same non-integer position in a scroll event listener", -> presenter = buildPresenter(scrollTop: 0, lineHeight: 10, explicitHeight: 20) expect(presenter.getState().content.scrollTop).toBe(0) @@ -851,7 +851,7 @@ describe "TextEditorPresenter", -> expect(presenter.getState().content.scrollTop).toBe presenter.contentHeight - presenter.clientHeight describe ".scrollLeft", -> - it "doesn't get stuck when setting a non-integer position in an event listener", -> + it "doesn't get stuck when repeatedly setting the same non-integer position in a scroll event listener", -> presenter = buildPresenter(scrollLeft: 0, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 10) expect(presenter.getState().content.scrollLeft).toBe(0) From 8dc61a667be1d2c7a7969fdda3eff7f3859fd6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C5=BDu=C5=BEak?= Date: Wed, 14 Oct 2015 17:16:14 +0200 Subject: [PATCH 217/316] :arrow_up: settings-view@0.230.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b7d079123..111eee78f 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "open-on-github": "0.38.0", "package-generator": "0.40.0", "release-notes": "0.53.0", - "settings-view": "0.229.0", + "settings-view": "0.230.0", "snippets": "0.100.0", "spell-check": "0.61.0", "status-bar": "0.79.0", From 6a53034a12a9e1c9a6fe8d9595f09aef9573c23e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 17:48:47 +0200 Subject: [PATCH 218/316] Move GrammarRegistry reset after Workspace ...as some elements could still use grammars upon Workspace destruction. --- src/atom-environment.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 2d0e4a632..6834cbcc5 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -267,8 +267,6 @@ class AtomEnvironment extends Model @commands.clear() @registerDefaultCommands() - @grammars.clear() - @styles.restoreSnapshot(@initialStyleElements) @menu.clear() @@ -288,6 +286,8 @@ class AtomEnvironment extends Model @workspace.subscribeToEvents() + @grammars.clear() + @views.clear() @registerDefaultViewProviders() From b3a7fe3fc9721542b8f52ff9373f0a8765bdf612 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Wed, 14 Oct 2015 18:01:43 +0200 Subject: [PATCH 219/316] Clarify how auto-detection works --- src/config-schema.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index 38182efb5..08956d470 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -177,7 +177,7 @@ module.exports = type: 'string' default: 'auto' enum: ['auto', 'soft', 'hard'] - description: 'Determine character inserted when Tab key is pressed. Possible values: "auto", "soft" and "hard". When set to "soft" or "hard", soft tabs (spaces) or hard tabs (tab characters) are used. When set to "auto", the editor auto-detects the tab type based on the contents of the buffer, or uses the value of the Soft Tabs config setting if auto-detection fails.' + description: 'Determine character inserted when Tab key is pressed. Possible values: "auto", "soft" and "hard". When set to "soft" or "hard", soft tabs (spaces) or hard tabs (tab characters) are used. When set to "auto", the editor auto-detects the tab type based on the contents of the buffer (it uses the first leading whitespace on a non-comment line), or uses the value of the Soft Tabs config setting if auto-detection fails.' softWrapAtPreferredLineLength: type: 'boolean' default: false From f2a32eb1dc09bcce49428e129671e96ff80e4a0a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 14 Oct 2015 18:25:25 +0200 Subject: [PATCH 220/316] Return empty string unless configDirPath is passed --- src/keymap-extensions.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/keymap-extensions.coffee b/src/keymap-extensions.coffee index 61ce1a315..82f2e8b99 100644 --- a/src/keymap-extensions.coffee +++ b/src/keymap-extensions.coffee @@ -20,6 +20,8 @@ KeymapManager::loadBundledKeymaps = -> @emitter.emit 'did-load-bundled-keymaps' KeymapManager::getUserKeymapPath = -> + return "" unless @configDirPath? + if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap')) userKeymapPath else From 974b45ce2c51e517638254aaa90b89b2262a413f Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 14 Oct 2015 09:50:49 -0700 Subject: [PATCH 221/316] :arrow_up: line-ending-selector --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 111eee78f..ef3a284b7 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "image-view": "0.55.0", "incompatible-packages": "0.25.0", "keybinding-resolver": "0.33.0", - "line-ending-selector": "0.1.0", + "line-ending-selector": "0.2.0", "link": "0.31.0", "markdown-preview": "0.154.0", "metrics": "0.52.0", From 6c3b8cc034f98fa982b8900d245fb0c950f0a282 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 14 Oct 2015 13:51:55 -0700 Subject: [PATCH 222/316] Prepare 1.1.0-beta1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 030a4626b..3d5038068 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.2.0-dev", + "version": "1.1.0-beta1", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From df66ca8d73407ee68e6b0554bce25361ea03a04f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 14:56:26 -0600 Subject: [PATCH 223/316] Remove unused params --- src/atom-environment.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 6834cbcc5..5c6b21504 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -254,7 +254,7 @@ class AtomEnvironment extends Model @setAutoHideMenuBar(newValue) @setAutoHideMenuBar(true) if @config.get('core.autoHideMenuBar') - reset: (params) -> + reset: -> @deserializers.clear() @registerDefaultDeserializers() From c1d5cdcd643b22204659f6f228ef49b3e19cc76d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 15:02:00 -0600 Subject: [PATCH 224/316] Group requires at the top of atom-environment.coffee --- src/atom-environment.coffee | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 5c6b21504..1b0864b08 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -13,6 +13,22 @@ StorageFolder = require './storage-folder' {getWindowLoadSettings} = require './window-load-settings-helpers' registerDefaultCommands = require './register-default-commands' +DeserializerManager = require './deserializer-manager' +ViewRegistry = require './view-registry' +NotificationManager = require './notification-manager' +Config = require './config' +KeymapManager = require './keymap-extensions' +TooltipManager = require './tooltip-manager' +CommandRegistry = require './command-registry' +GrammarRegistry = require './grammar-registry' +StyleManager = require './style-manager' +PackageManager = require './package-manager' +ThemeManager = require './theme-manager' +MenuManager = require './menu-manager' +ContextMenuManager = require './context-menu-manager' +CommandInstaller = require './command-installer' +Clipboard = require './clipboard' +Project = require './project' Workspace = require './workspace' PanelContainer = require './panel-container' Panel = require './panel' @@ -110,66 +126,50 @@ class AtomEnvironment extends Model @emitter = new Emitter @disposables = new CompositeDisposable - DeserializerManager = require './deserializer-manager' @deserializers = new DeserializerManager(this) @deserializeTimings = {} - ViewRegistry = require './view-registry' @views = new ViewRegistry(this) - NotificationManager = require './notification-manager' @notifications = new NotificationManager - Config = require './config' @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) @setConfigSchema() - KeymapManager = require './keymap-extensions' @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) - TooltipManager = require './tooltip-manager' @tooltips = new TooltipManager(keymapManager: @keymaps) - CommandRegistry = require './command-registry' @commands = new CommandRegistry @commands.attach(@window) - GrammarRegistry = require './grammar-registry' @grammars = new GrammarRegistry({@config}) - StyleManager = require './style-manager' @styles = new StyleManager({configDirPath}) - PackageManager = require './package-manager' @packages = new PackageManager({ devMode, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications, grammarRegistry: @grammars }) - ThemeManager = require './theme-manager' @themes = new ThemeManager({ packageManager: @packages, configDirPath, resourcePath, safeMode, @config, styleManager: @styles, notificationManager: @notifications, viewRegistry: @views }) - MenuManager = require './menu-manager' @menu = new MenuManager({resourcePath, keymapManager: @keymaps, packageManager: @packages}) - ContextMenuManager = require './context-menu-manager' @contextMenu = new ContextMenuManager({resourcePath, devMode, keymapManager: @keymaps}) @packages.setMenuManager(@menu) @packages.setContextMenuManager(@contextMenu) @packages.setThemeManager(@themes) - Clipboard = require './clipboard' @clipboard = new Clipboard() - Project = require './project' @project = new Project({notificationManager: @notifications, packageManager: @packages, @config}) - CommandInstaller = require './command-installer' @commandInstaller = new CommandInstaller(@getVersion(), @applicationDelegate) @workspace = new Workspace({ From 82cbf01c5b9452b776fc38478cd3ac8355011e70 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 15:04:25 -0600 Subject: [PATCH 225/316] Set useCapture to true when handling keydown events in test windows Prevents these events from getting intercepted by other handlers. --- src/initialize-test-window.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 6985d983b..feefa9e5a 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -17,7 +17,7 @@ try # that are focused in the very first spec run. remote.getCurrentWindow().show() unless getWindowLoadSettings().headless - window.addEventListener 'keydown', (event) -> + handleKeydown = (event) -> # Reload: cmd-r / ctrl-r if (event.metaKey or event.ctrlKey) and event.keyCode is 82 ipc.send('call-window-method', 'restart') @@ -30,6 +30,8 @@ try if (event.metaKey or event.ctrlKey) and event.keyCode is 87 ipc.send('call-window-method', 'close') + window.addEventListener('keydown', handleKeydown, true) + # Add 'exports' to module search path. exportsPath = path.join(getWindowLoadSettings().resourcePath, 'exports') require('module').globalPaths.push(exportsPath) From a85a8d20de340f6cc3135733528f4b94b7a6e12b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 15:57:34 -0600 Subject: [PATCH 226/316] =?UTF-8?q?Don=E2=80=99t=20register=20defaultTarge?= =?UTF-8?q?t=20for=20keymaps=20in=20constructor=20after=20all?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We’re clearing the views on reset, so this view will end up being different between test runs. Also, we didn’t previously always create the workspace view in many cases, and it makes sense to apply that here. We may want to get the default target for the keymap via a function so we can defer view creation until one is needed. --- src/atom-environment.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 1b0864b08..ed56831bf 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -195,7 +195,6 @@ class AtomEnvironment extends Model @registerDefaultOpeners() @registerDefaultDeserializers() @registerDefaultViewProviders() - @registerDefaultTargetForKeymaps() @installUncaughtErrorHandler() @installWindowEventHandler() @@ -608,6 +607,8 @@ class AtomEnvironment extends Model @disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this))) @listenForUpdates() + @registerDefaultTargetForKeymaps() + @packages.loadPackages() @document.body.appendChild(@views.getView(@workspace)) From f0da8f6324139460fbf0b76e25f71a584b860519 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 16:35:00 -0600 Subject: [PATCH 227/316] Resolve package names to package currently being tested This logic existed previously, but I accidentally removed it. --- spec/spec-helper.coffee | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index ebbc3c977..ef2fa60a0 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -7,6 +7,7 @@ _ = require 'underscore-plus' fs = require 'fs-plus' Grim = require 'grim' pathwatcher = require 'pathwatcher' +FindParentDir = require 'find-parent-dir' {Point} = require 'text-buffer' Workspace = require '../src/workspace' @@ -52,12 +53,19 @@ if process.env.CI else jasmine.getEnv().defaultTimeoutInterval = 5000 -{resourcePath} = atom.getLoadSettings() +{resourcePath, testPaths} = atom.getLoadSettings() + +if specPackagePath = FindParentDir.sync(testPaths[0], 'package.json') + packageMetadata = require(path.join(specPackagePath, 'package.json')) + specPackageName = packageMetadata.name + +if specDirectory = FindParentDir.sync(testPaths[0], 'fixtures') + specProjectPath = path.join(specDirectory, 'fixtures') beforeEach -> documentTitle = null - atom.project.setPaths([path.join(@specDirectory, 'fixtures')]) + atom.project.setPaths([specProjectPath]) window.resetTimeouts() spyOn(_._, "now").andCallFake -> window.now @@ -66,7 +74,12 @@ beforeEach -> spyOn(atom, 'saveStateSync') - spyOn(atom.packages, 'resolvePackagePath').andCallThrough() + spy = spyOn(atom.packages, 'resolvePackagePath').andCallFake (packageName) -> + if specPackageName and packageName is specPackageName + resolvePackagePath(specPackagePath) + else + resolvePackagePath(packageName) + resolvePackagePath = _.bind(spy.originalValue, atom.packages) # prevent specs from modifying Atom's menus spyOn(atom.menu, 'sendToBrowserProcess') From a6a175c4a6d5e3531769c4e926145704fc8abf0e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 16:40:40 -0600 Subject: [PATCH 228/316] =?UTF-8?q?Don=E2=80=99t=20hide=20window=20when=20?= =?UTF-8?q?reloading=20specs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/window-event-handler.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 18191ccaa..bff5ee5b7 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -138,7 +138,8 @@ class WindowEventHandler handleWindowBeforeunload: => confirmed = @atomEnvironment.workspace?.confirmClose(windowCloseRequested: true) - @atomEnvironment.hide() if confirmed and not @reloadRequested and @atomEnvironment.getCurrentWindow().isWebViewFocused() + if confirmed and not @reloadRequested and not @atomEnvironment.inSpecMode() and @atomEnvironment.getCurrentWindow().isWebViewFocused() + @atomEnvironment.hide() @reloadRequested = false @atomEnvironment.storeDefaultWindowDimensions() From 95dd628d42dabd4628a8324f29f41fbddfb2e68e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 17:10:30 -0600 Subject: [PATCH 229/316] Fix for packages with no spec/fixtures directory --- spec/spec-helper.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index ef2fa60a0..61cdec1ab 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -61,6 +61,8 @@ if specPackagePath = FindParentDir.sync(testPaths[0], 'package.json') if specDirectory = FindParentDir.sync(testPaths[0], 'fixtures') specProjectPath = path.join(specDirectory, 'fixtures') +else + specProjectPath = path.join(__dirname, 'fixtures') beforeEach -> documentTitle = null From 9d59514248d8d2e4cbaf7fc1f1992de1e099354e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 14 Oct 2015 16:49:21 -0700 Subject: [PATCH 230/316] Add Making your first contribution section to guide --- CONTRIBUTING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 19d4367f3..e09cd2593 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,7 @@ By participating, you are expected to uphold this code. Please report unacceptab #### Table Of Contents * [Submitting Issues](#submitting-issues) +* [Making your first contribution](#making-your-first-contribution) * [Pull Requests](#pull-requests) * [Git Commit Messages](#git-commit-messages) * [CoffeeScript Styleguide](#coffeescript-styleguide) @@ -60,6 +61,13 @@ you're having an issue with Atom core, open an issue on this repository. For more information on how to work with Atom's official packages, see [Contributing to Atom Packages](https://github.com/atom/atom/blob/master/docs/contributing-to-packages.md) +## Making your first contribution + +Unsure where to begin contributing to Atom? You can start by looking through these `beginner` and `help-wanted` issues: + +* [Beginner issues][beginner] +* [Help wanted issues][help-wanted] + ## Pull Requests * Include screenshots and animated GIFs in your pull request whenever possible. @@ -352,3 +360,6 @@ Please open an issue on `atom/atom` if you have suggestions for new labels, and [search-atom-org-label-requires-changes]: https://github.com/pulls?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Arequires-changes [search-atom-repo-label-needs-testing]: https://github.com/pulls?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Aneeds-testing [search-atom-org-label-needs-testing]: https://github.com/pulls?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Aneeds-testing + +[beginner]:https://github.com/issues?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3Ahelp-wanted+user%3Aatom+sort%3Acomments-desc +[help-wanted]:https://github.com/issues?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted+user%3Aatom+sort%3Acomments-desc From 1c9d5616da5dc32bf04e0fb05d6d7605d1f4fd45 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 14 Oct 2015 16:51:42 -0700 Subject: [PATCH 231/316] Title case --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e09cd2593..ddb3ec92e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ By participating, you are expected to uphold this code. Please report unacceptab #### Table Of Contents * [Submitting Issues](#submitting-issues) -* [Making your first contribution](#making-your-first-contribution) +* [Your First Contribution](#your-first-contribution`) * [Pull Requests](#pull-requests) * [Git Commit Messages](#git-commit-messages) * [CoffeeScript Styleguide](#coffeescript-styleguide) @@ -61,7 +61,7 @@ you're having an issue with Atom core, open an issue on this repository. For more information on how to work with Atom's official packages, see [Contributing to Atom Packages](https://github.com/atom/atom/blob/master/docs/contributing-to-packages.md) -## Making your first contribution +## Your First Contribution Unsure where to begin contributing to Atom? You can start by looking through these `beginner` and `help-wanted` issues: From a4efded72f26378a4e3742f1c32e65f1172665c2 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 14 Oct 2015 21:32:25 -0400 Subject: [PATCH 232/316] :memo: Fix typo /cc @benogle --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ddb3ec92e..7f9dc8638 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ By participating, you are expected to uphold this code. Please report unacceptab #### Table Of Contents * [Submitting Issues](#submitting-issues) -* [Your First Contribution](#your-first-contribution`) +* [Your First Contribution](#your-first-contribution) * [Pull Requests](#pull-requests) * [Git Commit Messages](#git-commit-messages) * [CoffeeScript Styleguide](#coffeescript-styleguide) From 9df40b4f4e7165c4f61e4f4d897bae19c8c6c4bc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 19:53:16 -0600 Subject: [PATCH 233/316] Remove unnecessary fat arrow --- src/initialize-test-window.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index feefa9e5a..3f3d286d7 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -2,7 +2,7 @@ require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') remote = require 'remote' -exitWithStatusCode = (status) => +exitWithStatusCode = (status) -> remote.require('app').emit('will-quit') remote.process.exit(status) From dc44d11a2cee008a0b1ff4ed6784420e125cd4fc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 20:05:06 -0600 Subject: [PATCH 234/316] =?UTF-8?q?Don=E2=80=99t=20load/save=20config=20if?= =?UTF-8?q?=20enablePersistence=20option=20is=20false?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/config-spec.coffee | 4 ++++ spec/jasmine-test-runner.coffee | 6 +++++- src/atom-environment.coffee | 4 ++-- src/config.coffee | 6 +++--- src/initialize-application-window.coffee | 7 ++++++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 7329ac6c9..bb9ab89a8 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -11,8 +11,12 @@ describe "Config", -> spyOn(atom.config, "save") dotAtomPath = temp.path('dot-atom-dir') atom.config.configDirPath = dotAtomPath + atom.config.enablePersistence = true atom.config.configFilePath = path.join(atom.config.configDirPath, "atom.config.cson") + afterEach -> + atom.config.enablePersistence = false + describe ".get(keyPath, {scope, sources, excludeSources})", -> it "allows a key path's value to be read", -> expect(atom.config.set("foo.bar.baz", 42)).toBe true diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 04b875ac8..8d1eeac85 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -18,7 +18,11 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) -> applicationDelegate = new ApplicationDelegate() applicationDelegate.setRepresentedFilename = -> applicationDelegate.setWindowDocumentEdited = -> - window.atom = buildAtomEnvironment({applicationDelegate, window, document}) + window.atom = buildAtomEnvironment({ + applicationDelegate, window, document, + configDirPath: process.env.ATOM_HOME + enablePersistence: false + }) require './spec-helper' disableFocusMethods() if process.env.JANKY_SHA1 or process.env.CI diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index ed56831bf..acccef475 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -116,7 +116,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate, @window, @document, configDirPath} = params + {@applicationDelegate, @window, @document, configDirPath, @enablePersistence} = params @state = {version: @constructor.version} @@ -133,7 +133,7 @@ class AtomEnvironment extends Model @notifications = new NotificationManager - @config = new Config({configDirPath, resourcePath, notificationManager: @notifications}) + @config = new Config({configDirPath, resourcePath, notificationManager: @notifications, @enablePersistence}) @setConfigSchema() @keymaps = new KeymapManager({configDirPath, resourcePath, notificationManager: @notifications}) diff --git a/src/config.coffee b/src/config.coffee index 3a616c9a7..cb09a8d83 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -334,8 +334,8 @@ class Config value # Created during initialization, available as `atom.config` - constructor: ({@configDirPath, @resourcePath, @notificationManager}={}) -> - if @configDirPath? + constructor: ({@configDirPath, @resourcePath, @notificationManager, @enablePersistence}={}) -> + if @enablePersistence? @configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson']) @configFilePath ?= path.join(@configDirPath, 'config.cson') @clear() @@ -360,7 +360,7 @@ class Config @save() debouncedSave = _.debounce(save, 100) - shouldNotAccessFileSystem: -> not @configDirPath? + shouldNotAccessFileSystem: -> not @enablePersistence ### Section: Config Subscription diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 71b1f3b15..acf50bc5d 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -16,7 +16,12 @@ process.env.NODE_ENV ?= 'production' unless devMode AtomEnvironment = require './atom-environment' ApplicationDelegate = require './application-delegate' -window.atom = new AtomEnvironment({applicationDelegate: new ApplicationDelegate, window, document, configDirPath: process.env.ATOM_HOME}) +window.atom = new AtomEnvironment({ + window, document, + applicationDelegate: new ApplicationDelegate, + configDirPath: process.env.ATOM_HOME + enablePersistence: true +}) atom.displayWindow() atom.loadStateSync() From b58b3504f4e060b3098018da593d990a5060843d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Oct 2015 22:10:51 -0600 Subject: [PATCH 235/316] Only load/save AtomEnvironment state if persistence is enabled --- spec/atom-environment-spec.coffee | 9 ++++++--- spec/spec-helper.coffee | 2 -- src/atom-environment.coffee | 4 ++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 5150540bc..f9dbc02f9 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -141,10 +141,13 @@ describe "AtomEnvironment", -> expect(errors).toEqual [] describe "saving and loading", -> - it "selects the state based on the current project paths", -> - jasmine.unspy(atom, 'saveStateSync') - # jasmine.unspy(atom, 'loadStateSync') + beforeEach -> + atom.enablePersistence = true + afterEach -> + atom.enablePersistence = false + + it "selects the state based on the current project paths", -> [dir1, dir2] = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")] loadSettings = _.extend atom.getLoadSettings(), diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 61cdec1ab..9a2ef83ce 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -74,8 +74,6 @@ beforeEach -> spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout - spyOn(atom, 'saveStateSync') - spy = spyOn(atom.packages, 'resolvePackagePath').andCallFake (packageName) -> if specPackageName and packageName is specPackageName resolvePackagePath(specPackagePath) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index acccef475..f60f2ec97 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -758,12 +758,16 @@ class AtomEnvironment extends Model @applicationDelegate.showSaveDialog(options) saveStateSync: -> + return unless @enablePersistence + if storageKey = @getStateKey(@project?.getPaths()) @getStorageFolder().store(storageKey, @state) else @getCurrentWindow().loadSettings.windowState = JSON.stringify(@state) loadStateSync: -> + return unless @enablePersistence + startTime = Date.now() if stateKey = @getStateKey(@getLoadSettings().initialPaths) From edddb6516e3e0ab0a59865ba64ecba21f1245ae2 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 09:54:29 +0200 Subject: [PATCH 236/316] Remove shim to `remote.process` This doesn't seem to work as expected. I think it's just better to encourage emitting an event like 'write-to-stdout' or using directly `remote.process`. /cc: @nathansobo --- src/initialize-test-window.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 3f3d286d7..ad15429ff 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -37,10 +37,6 @@ try require('module').globalPaths.push(exportsPath) process.env.NODE_PATH = exportsPath # Set NODE_PATH env variable since tasks may need it. - # Shim process stdout and stderr so that they can be logged out to console. - process.stdout = remote.process.stdout - process.stderr = remote.process.stderr - document.title = "Spec Suite" legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) From c38cd48555b681067ba73eff497b115dedc90bce Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 09:56:11 +0200 Subject: [PATCH 237/316] Bring back failure reports when running `grunt run-specs` Log output to stderr as we did before, so that grunt can, in turn, output it to console when specs fail. Welcome back build failures! :tada: /cc: @nathansobo @maxbrunsfeld --- spec/jasmine-test-runner.coffee | 2 +- src/browser/atom-application.coffee | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/jasmine-test-runner.coffee b/spec/jasmine-test-runner.coffee index 8d1eeac85..7ef34ce54 100644 --- a/spec/jasmine-test-runner.coffee +++ b/spec/jasmine-test-runner.coffee @@ -89,7 +89,7 @@ buildTerminalReporter = (logFile, resolveWithExitCode) -> if logStream? fs.writeSync(logStream, str) else - ipc.send 'write-to-stdout', str + ipc.send 'write-to-stderr', str {TerminalReporter} = require 'jasmine-tagged' new TerminalReporter diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index e63e3a766..b8e3e7bc2 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -277,6 +277,9 @@ class AtomApplication ipc.on 'write-to-stdout', (event, output) -> process.stdout.write(output) + ipc.on 'write-to-stderr', (event, output) -> + process.stderr.write(output) + # Public: Executes the given command. # # If it isn't handled globally, delegate to the currently focused window. From 82fbec0879b7955752d3769afd44c39898f26f32 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 11:05:12 +0200 Subject: [PATCH 238/316] :bug: Give priority to initial window background Otherwise, since we now add styles element right during AtomEnvironment construction, the default background gets showed (i.e. white on my machine). /cc: @nathansobo --- static/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/index.js b/static/index.js index 5f90591f0..9bd1f7b20 100644 --- a/static/index.js +++ b/static/index.js @@ -168,7 +168,7 @@ var backgroundStylesheet = document.createElement('style') backgroundStylesheet.type = 'text/css' - backgroundStylesheet.innerText = 'html, body { background: ' + backgroundColor + '; }' + backgroundStylesheet.innerText = 'html, body { background: ' + backgroundColor + ' !important; }' document.head.appendChild(backgroundStylesheet) // Remove once the page loads From eddf2bd2da284bfe534713086a20876c2d89bcc5 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Thu, 15 Oct 2015 11:27:13 +0200 Subject: [PATCH 239/316] :arrow_up: settings-view@0.230.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 030a4626b..9191f39db 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "open-on-github": "0.38.0", "package-generator": "0.40.0", "release-notes": "0.53.0", - "settings-view": "0.230.0", + "settings-view": "0.230.1", "snippets": "0.100.0", "spell-check": "0.61.0", "status-bar": "0.79.0", From 3c33a7ba9f4e17d09240974907cf50d0d8899aa6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 15:22:11 +0200 Subject: [PATCH 240/316] Soft wrap based on default character width --- spec/display-buffer-spec.coffee | 6 ++++-- src/display-buffer.coffee | 29 ++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 7ed97f0d0..a6b6242d4 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -52,10 +52,11 @@ describe "DisplayBuffer", -> displayBuffer2 = new DisplayBuffer({buffer, tabLength}) buffer.setText("testing") - describe "soft wrapping", -> + fdescribe "soft wrapping", -> beforeEach -> - displayBuffer.setSoftWrapped(true) + displayBuffer.setDefaultCharWidth(1) displayBuffer.setEditorWidthInChars(50) + displayBuffer.setSoftWrapped(true) changeHandler.reset() describe "rendering of soft-wrapped lines", -> @@ -233,6 +234,7 @@ describe "DisplayBuffer", -> it "correctly renders the original wrapped line", -> buffer = atom.project.buildBufferSync(null, '') displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30}) + displayBuffer.setDefaultCharWidth(1) displayBuffer.setSoftWrapped(true) buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.") diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 339fa11c1..a545235c2 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -262,6 +262,33 @@ class DisplayBuffer extends Model else @getEditorWidthInChars() + getMaxLengthPerLine: -> + if @configSettings.softWrapAtPreferredLineLength + Math.min(@getEditorWidthInChars(), @configSettings.preferredLineLength) + else + @getEditorWidthInChars() + + getSoftWrapColumnForTokenizedLine: (tokenizedLine) -> + lineMaxWidth = @getMaxLengthPerLine() * @getDefaultCharWidth() + iterator = tokenizedLine.getTokenIterator() + column = 0 + currentWidth = 0 + while iterator.next() + textIndex = 0 + text = iterator.getText() + while textIndex < text.length + if iterator.isPairedCharacter() + charLength = 2 + else + charLength = 1 + + charWidth = @getDefaultCharWidth() + return column if currentWidth + charWidth > lineMaxWidth + currentWidth += charWidth + column += charLength + textIndex += charLength + column + # Gets the screen line for the given screen row. # # * `screenRow` - A {Number} indicating the screen row. @@ -958,7 +985,7 @@ class DisplayBuffer extends Model else softWraps = 0 if @isSoftWrapped() - while wrapScreenColumn = tokenizedLine.findWrapColumn(@getSoftWrapColumn()) + while wrapScreenColumn = tokenizedLine.findWrapColumn(@getSoftWrapColumnForTokenizedLine(tokenizedLine)) [wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt( wrapScreenColumn, @configSettings.softWrapHangingIndent From b2a7f4a28e092b98234befbd5979c81a15756c8c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 15:52:15 +0200 Subject: [PATCH 241/316] Create utility function to recognize double width characters --- spec/text-utils-spec.coffee | 13 +++++++++++++ src/text-utils.coffee | 26 +++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/spec/text-utils-spec.coffee b/spec/text-utils-spec.coffee index 6a03bb02f..a8bdbc2f7 100644 --- a/spec/text-utils-spec.coffee +++ b/spec/text-utils-spec.coffee @@ -44,3 +44,16 @@ describe 'text utilities', -> expect(textUtils.isPairedCharacter('ae\u0301c', 2)).toBe false expect(textUtils.isPairedCharacter('ae\u0301c', 3)).toBe false expect(textUtils.isPairedCharacter('ae\u0301c', 4)).toBe false + + describe ".isDoubleWidthCharacter(character)", -> + it "returns true when the character is either japanese, korean, chinese or a full width form", -> + expect(textUtils.isDoubleWidthCharacter("我")).toBe(true) + + expect(textUtils.isDoubleWidthCharacter("私")).toBe(true) + + expect(textUtils.isDoubleWidthCharacter("우")).toBe(true) + + expect(textUtils.isDoubleWidthCharacter("B")).toBe(true) + expect(textUtils.isDoubleWidthCharacter(",")).toBe(true) + + expect(textUtils.isDoubleWidthCharacter("a")).toBe(false) diff --git a/src/text-utils.coffee b/src/text-utils.coffee index 37955dcd6..1995094fe 100644 --- a/src/text-utils.coffee +++ b/src/text-utils.coffee @@ -57,6 +57,30 @@ isPairedCharacter = (string, index=0) -> isVariationSequence(charCodeA, charCodeB) or isCombinedCharacter(charCodeA, charCodeB) +isKoreanCharacter = (charCode) -> + 0xAC00 <= charCode <= 0xD7A3 or + 0x1100 <= charCode <= 0x11FF or + 0x3130 <= charCode <= 0x318F or + 0xA960 <= charCode <= 0xA97F or + 0xD7B0 <= charCode <= 0xD7FF + +isJapaneseCharacter = (charCode) -> + 0x3000 <= charCode <= 0x30ff + +isCjkUnifiedIdeograph = (charCode) -> + 0x4e00 <= charCode <= 0x9faf + +isFullWidthForm = (charCode) -> + 0xFF01 <= charCode <= 0xFF5E + +isDoubleWidthCharacter = (character) -> + charCode = character.charCodeAt(0) + + isKoreanCharacter(charCode) or + isJapaneseCharacter(charCode) or + isCjkUnifiedIdeograph(charCode) or + isFullWidthForm(charCode) + # Does the given string contain at least surrogate pair, variation sequence, # or combined character? # @@ -70,4 +94,4 @@ hasPairedCharacter = (string) -> index++ false -module.exports = {isPairedCharacter, hasPairedCharacter} +module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter} From c2ee942df14b4863cb49c6f28f34bef49d39d127 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 16:24:08 +0200 Subject: [PATCH 242/316] Take double width chars into account when soft wrapping --- spec/display-buffer-spec.coffee | 10 ++++++++++ src/display-buffer.coffee | 13 ++++++++++++- src/token-iterator.coffee | 4 ++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index a6b6242d4..69d78bf70 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -60,6 +60,16 @@ describe "DisplayBuffer", -> changeHandler.reset() describe "rendering of soft-wrapped lines", -> + describe "when there are double width characters", -> + it "takes them into account when finding the soft wrap column", -> + displayBuffer.setDoubleWidthCharWidth(5) + buffer.setText("私たちのフ是一个地方,数千名学生12345业余爱们的板作为우리포럼hello world this is a pretty long latin line") + + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("私たちのフ是一个地方") + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe(",数千名学生12345业余爱") + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("们的板作为우리포럼hello ") + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe("world this is a pretty long latin line") + describe "when editor.softWrapAtPreferredLineLength is set", -> it "uses the preferred line length as the soft wrap column when it is less than the configured soft wrap column", -> atom.config.set('editor.preferredLineLength', 100) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index a545235c2..948101385 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -195,6 +195,12 @@ class DisplayBuffer extends Model @defaultCharWidth = defaultCharWidth defaultCharWidth + getDoubleWidthCharWidth: -> @doubleWidthCharWidth + setDoubleWidthCharWidth: (doubleWidthCharWidth) -> + if doubleWidthCharWidth isnt @doubleWidthCharWidth + @doubleWidthCharWidth = doubleWidthCharWidth + doubleWidthCharWidth + getCursorWidth: -> 1 scrollToScreenRange: (screenRange, options = {}) -> @@ -282,8 +288,13 @@ class DisplayBuffer extends Model else charLength = 1 - charWidth = @getDefaultCharWidth() + if iterator.hasDoubleWidthCharacterAt(textIndex) + charWidth = @getDoubleWidthCharWidth() + else + charWidth = @getDefaultCharWidth() + return column if currentWidth + charWidth > lineMaxWidth + currentWidth += charWidth column += charLength textIndex += charLength diff --git a/src/token-iterator.coffee b/src/token-iterator.coffee index de874d499..4c4686635 100644 --- a/src/token-iterator.coffee +++ b/src/token-iterator.coffee @@ -1,4 +1,5 @@ {SoftTab, HardTab, PairedCharacter, SoftWrapIndent} = require './special-token-symbols' +{isDoubleWidthCharacter} = require './text-utils' module.exports = class TokenIterator @@ -82,5 +83,8 @@ class TokenIterator isPairedCharacter: -> @line.specialTokens[@index] is PairedCharacter + hasDoubleWidthCharacterAt: (charIndex) -> + isDoubleWidthCharacter(@getText()[charIndex]) + isAtomic: -> @isSoftTab() or @isHardTab() or @isSoftWrapIndentation() or @isPairedCharacter() From 20b0523833e45060ce1add1cad1b28540f0ddbb7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 16:41:27 +0200 Subject: [PATCH 243/316] :green_heart: --- spec/display-buffer-spec.coffee | 4 +++- spec/text-editor-component-spec.coffee | 2 ++ spec/text-editor-presenter-spec.coffee | 5 +++++ spec/text-editor-spec.coffee | 12 ++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 69d78bf70..bfe2e12ab 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -52,7 +52,7 @@ describe "DisplayBuffer", -> displayBuffer2 = new DisplayBuffer({buffer, tabLength}) buffer.setText("testing") - fdescribe "soft wrapping", -> + describe "soft wrapping", -> beforeEach -> displayBuffer.setDefaultCharWidth(1) displayBuffer.setEditorWidthInChars(50) @@ -648,6 +648,7 @@ describe "DisplayBuffer", -> beforeEach -> tabLength = 4 + displayBuffer.setDefaultCharWidth(1) displayBuffer.setTabLength(tabLength) displayBuffer.setSoftWrapped(true) displayBuffer.setEditorWidthInChars(50) @@ -765,6 +766,7 @@ describe "DisplayBuffer", -> it "correctly translates positions on soft wrapped lines containing tabs", -> buffer.setText('\t\taa bb cc dd ee ff gg') displayBuffer.setSoftWrapped(true) + displayBuffer.setDefaultCharWidth(1) displayBuffer.setEditorWidthInChars(10) expect(displayBuffer.screenPositionForBufferPosition([0, 10], wrapAtSoftNewlines: true)).toEqual [1, 4] expect(displayBuffer.bufferPositionForScreenPosition([1, 0])).toEqual [0, 9] diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index f6936e4c4..11454aaef 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -3208,7 +3208,9 @@ describe "TextEditorComponent", -> atom.config.set 'editor.preferredLineLength', 17, scopeSelector: '.source.coffee' atom.config.set 'editor.softWrapAtPreferredLineLength', true, scopeSelector: '.source.coffee' + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(20) + coffeeEditor.setDefaultCharWidth(1) coffeeEditor.setEditorWidthInChars(20) it "wraps lines when editor.softWrap is true for a matching scope", -> diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 541599ea8..acb9c29ae 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -1258,6 +1258,7 @@ describe "TextEditorPresenter", -> it "only applies decorations to screen rows that are spanned by their marker when lines are soft-wrapped", -> editor.setText("a line that wraps, ok") editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(16) marker = editor.markBufferRange([[0, 0], [0, 2]]) editor.decorateMarker(marker, type: 'line', class: 'a') @@ -2243,6 +2244,7 @@ describe "TextEditorPresenter", -> it "contains states for line numbers that are visible on screen", -> editor.foldBufferRow(4) editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(50) presenter = buildPresenter(explicitHeight: 25, scrollTop: 30, lineHeight: 10, tileSize: 2) @@ -2258,6 +2260,7 @@ describe "TextEditorPresenter", -> it "updates when the editor's content changes", -> editor.foldBufferRow(4) editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(50) presenter = buildPresenter(explicitHeight: 35, scrollTop: 30, tileSize: 2) @@ -2288,6 +2291,7 @@ describe "TextEditorPresenter", -> it "correctly handles the first screen line being soft-wrapped", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(30) presenter = buildPresenter(explicitHeight: 25, scrollTop: 50, tileSize: 2) @@ -2416,6 +2420,7 @@ describe "TextEditorPresenter", -> it "only applies line-number decorations to screen rows that are spanned by their marker when lines are soft-wrapped", -> editor.setText("a line that wraps, ok") editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(16) marker = editor.markBufferRange([[0, 0], [0, 2]]) editor.decorateMarker(marker, type: 'line-number', class: 'a') diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index e95818900..daba04714 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -272,6 +272,7 @@ describe "TextEditor", -> describe "when soft-wrap is enabled and code is folded", -> beforeEach -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(50) editor.createFold(2, 3) @@ -327,6 +328,7 @@ describe "TextEditor", -> describe "when the cursor was moved down from the beginning of an indented soft-wrapped line", -> it "moves to the beginning of the previous line", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(50) editor.setCursorScreenPosition([3, 0]) @@ -379,6 +381,7 @@ describe "TextEditor", -> describe "when the cursor is at the beginning of an indented soft-wrapped line", -> it "moves to the beginning of the line's continuation on the next screen row", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(50) editor.setCursorScreenPosition([3, 0]) @@ -446,6 +449,7 @@ describe "TextEditor", -> describe "when line is wrapped and follow previous line indentation", -> beforeEach -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(50) it "wraps to the end of the previous line", -> @@ -604,6 +608,7 @@ describe "TextEditor", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToEndOfScreenLine() @@ -623,6 +628,7 @@ describe "TextEditor", -> describe ".moveToBeginningOfLine()", -> it "moves cursor to the beginning of the buffer line", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToBeginningOfLine() @@ -632,6 +638,7 @@ describe "TextEditor", -> describe ".moveToEndOfLine()", -> it "moves cursor to the end of the buffer line", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([0, 2]) editor.moveToEndOfLine() @@ -642,6 +649,7 @@ describe "TextEditor", -> describe "when soft wrap is on", -> it "moves to the first character of the current screen line or the beginning of the screen line if it's already on the first character", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition [2, 5] editor.addCursorAtScreenPosition [8, 7] @@ -1548,6 +1556,7 @@ describe "TextEditor", -> describe "when lines are soft-wrapped", -> beforeEach -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(40) it "skips soft-wrap indentation tokens", -> @@ -1633,6 +1642,7 @@ describe "TextEditor", -> it "can add selections to soft-wrapped line segments", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(40) editor.setSelectedScreenRange([[4, 10], [4, 15]]) @@ -1659,6 +1669,7 @@ describe "TextEditor", -> describe "when lines are soft-wrapped", -> beforeEach -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(40) it "skips soft-wrap indentation tokens", -> @@ -2703,6 +2714,7 @@ describe "TextEditor", -> describe "when soft wrap is on", -> it "cuts up to the end of the line", -> editor.setSoftWrapped(true) + editor.setDefaultCharWidth(1) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([2, 2]) editor.cutToEndOfLine() From 27dc3da9e5ac871b4519555abaf8152b46e2311a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 17:53:36 +0200 Subject: [PATCH 244/316] :art: Conflate setting default and double-width chars width Because they will always change together, and having two different setters seems highly error-prone. --- spec/display-buffer-spec.coffee | 2 +- src/display-buffer.coffee | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index bfe2e12ab..ee0197903 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -62,7 +62,7 @@ describe "DisplayBuffer", -> describe "rendering of soft-wrapped lines", -> describe "when there are double width characters", -> it "takes them into account when finding the soft wrap column", -> - displayBuffer.setDoubleWidthCharWidth(5) + displayBuffer.setDefaultCharWidth(1, 5) buffer.setText("私たちのフ是一个地方,数千名学生12345业余爱们的板作为우리포럼hello world this is a pretty long latin line") expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("私たちのフ是一个地方") diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 948101385..aa70ea554 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -189,17 +189,13 @@ class DisplayBuffer extends Model getLineHeightInPixels: -> @lineHeightInPixels setLineHeightInPixels: (@lineHeightInPixels) -> @lineHeightInPixels - getDefaultCharWidth: -> @defaultCharWidth - setDefaultCharWidth: (defaultCharWidth) -> - if defaultCharWidth isnt @defaultCharWidth - @defaultCharWidth = defaultCharWidth - defaultCharWidth - getDoubleWidthCharWidth: -> @doubleWidthCharWidth - setDoubleWidthCharWidth: (doubleWidthCharWidth) -> - if doubleWidthCharWidth isnt @doubleWidthCharWidth + getDefaultCharWidth: -> @defaultCharWidth + setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth=defaultCharWidth) -> + if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth + @defaultCharWidth = defaultCharWidth @doubleWidthCharWidth = doubleWidthCharWidth - doubleWidthCharWidth + defaultCharWidth getCursorWidth: -> 1 From 4c66341624d4447a3fd9519bb2d30abde57cabb9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 18:08:35 +0200 Subject: [PATCH 245/316] Measure double width char widths --- spec/text-editor-component-spec.coffee | 10 ++++++++++ src/lines-component.coffee | 18 +++++++++++++++--- src/text-editor-presenter.coffee | 7 ++++--- src/text-editor.coffee | 5 ++++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 11454aaef..9032598e8 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2891,6 +2891,16 @@ describe "TextEditorComponent", -> expect(editor.consolidateSelections).toHaveBeenCalled() expect(event.abortKeyBinding).toHaveBeenCalled() + describe "when changing the font", -> + it "measures the default char width and the double width char width", -> + expect(editor.getDefaultCharWidth()).toBe(12) + + component.setFontSize(10) + nextAnimationFrame() + + expect(editor.getDefaultCharWidth()).toBe(6) + expect(editor.getDoubleWidthCharWidth()).toBe(10) + describe "hiding and showing the editor", -> describe "when the editor is hidden when it is mounted", -> it "defers measurement and rendering until the editor becomes visible", -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 2a721a0aa..8a97ccbfd 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -7,7 +7,9 @@ DummyLineNode.className = 'line' DummyLineNode.style.position = 'absolute' DummyLineNode.style.visibility = 'hidden' DummyLineNode.appendChild(document.createElement('span')) -DummyLineNode.firstChild.textContent = 'x' +DummyLineNode.firstChild.textContent = 'xフ' + +RangeForMeasurement = document.createRange() module.exports = class LinesComponent extends TiledComponent @@ -76,12 +78,22 @@ class LinesComponent extends TiledComponent measureLineHeightAndDefaultCharWidth: -> @domNode.appendChild(DummyLineNode) + textNode = DummyLineNode.firstChild.childNodes[0] + lineHeightInPixels = DummyLineNode.getBoundingClientRect().height - charWidth = DummyLineNode.firstChild.getBoundingClientRect().width + + RangeForMeasurement.setStart(textNode, 0) + RangeForMeasurement.setEnd(textNode, 1) + defaultCharWidth = RangeForMeasurement.getBoundingClientRect().width + + RangeForMeasurement.setStart(textNode, 1) + RangeForMeasurement.setEnd(textNode, 2) + doubleWidthCharWidth = RangeForMeasurement.getBoundingClientRect().width + @domNode.removeChild(DummyLineNode) @presenter.setLineHeight(lineHeightInPixels) - @presenter.setBaseCharacterWidth(charWidth) + @presenter.setBaseCharacterWidth(defaultCharWidth, doubleWidthCharWidth) lineNodeForLineIdAndScreenRow: (lineId, screenRow) -> tile = @presenter.tileForRow(screenRow) diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index efa7845fe..92ccb2d56 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -1122,10 +1122,11 @@ class TextEditorPresenter @mouseWheelScreenRow = screenRow @didStartScrolling() - setBaseCharacterWidth: (baseCharacterWidth) -> - unless @baseCharacterWidth is baseCharacterWidth + setBaseCharacterWidth: (baseCharacterWidth, doubleWidthCharWidth) -> + unless @baseCharacterWidth is baseCharacterWidth and @doubleWidthCharWidth is doubleWidthCharWidth @baseCharacterWidth = baseCharacterWidth - @model.setDefaultCharWidth(baseCharacterWidth) + @doubleWidthCharWidth = doubleWidthCharWidth + @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth) @characterWidthsChanged() characterWidthsChanged: -> diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 4d517ac99..e4b0c8a37 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -2976,8 +2976,11 @@ class TextEditor extends Model getLineHeightInPixels: -> @displayBuffer.getLineHeightInPixels() setLineHeightInPixels: (lineHeightInPixels) -> @displayBuffer.setLineHeightInPixels(lineHeightInPixels) + getDoubleWidthCharWidth: -> @displayBuffer.getDoubleWidthCharWidth() + getDefaultCharWidth: -> @displayBuffer.getDefaultCharWidth() - setDefaultCharWidth: (defaultCharWidth) -> @displayBuffer.setDefaultCharWidth(defaultCharWidth) + setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth=defaultCharWidth) -> + @displayBuffer.setDefaultCharWidth(defaultCharWidth, doubleWidthCharWidth) setHeight: (height, reentrant=false) -> if reentrant From 4818d47980b96b7bd98ce99da992f58b7286513e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 18:10:26 +0200 Subject: [PATCH 246/316] Update wrapped screen lines when default width changes --- spec/display-buffer-spec.coffee | 4 ++-- src/display-buffer.coffee | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index ee0197903..aafca68fe 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -54,16 +54,16 @@ describe "DisplayBuffer", -> describe "soft wrapping", -> beforeEach -> - displayBuffer.setDefaultCharWidth(1) displayBuffer.setEditorWidthInChars(50) displayBuffer.setSoftWrapped(true) + displayBuffer.setDefaultCharWidth(1) changeHandler.reset() describe "rendering of soft-wrapped lines", -> describe "when there are double width characters", -> it "takes them into account when finding the soft wrap column", -> - displayBuffer.setDefaultCharWidth(1, 5) buffer.setText("私たちのフ是一个地方,数千名学生12345业余爱们的板作为우리포럼hello world this is a pretty long latin line") + displayBuffer.setDefaultCharWidth(1, 5) expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("私たちのフ是一个地方") expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe(",数千名学生12345业余爱") diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index aa70ea554..60dedb9f8 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -195,6 +195,7 @@ class DisplayBuffer extends Model if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth @defaultCharWidth = defaultCharWidth @doubleWidthCharWidth = doubleWidthCharWidth + @updateWrappedScreenLines() if @isSoftWrapped() defaultCharWidth getCursorWidth: -> 1 From 43229a1b9eed0671b2e46652ea0a53f4c770339f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 18:35:49 +0200 Subject: [PATCH 247/316] :art: --- src/display-buffer.coffee | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 60dedb9f8..3d960e2d3 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -195,7 +195,7 @@ class DisplayBuffer extends Model if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth @defaultCharWidth = defaultCharWidth @doubleWidthCharWidth = doubleWidthCharWidth - @updateWrappedScreenLines() if @isSoftWrapped() + @updateWrappedScreenLines() if @isSoftWrapped() and @getWidth()? defaultCharWidth getCursorWidth: -> 1 @@ -265,14 +265,8 @@ class DisplayBuffer extends Model else @getEditorWidthInChars() - getMaxLengthPerLine: -> - if @configSettings.softWrapAtPreferredLineLength - Math.min(@getEditorWidthInChars(), @configSettings.preferredLineLength) - else - @getEditorWidthInChars() - getSoftWrapColumnForTokenizedLine: (tokenizedLine) -> - lineMaxWidth = @getMaxLengthPerLine() * @getDefaultCharWidth() + lineMaxWidth = Math.round(@getSoftWrapColumn() * @getDefaultCharWidth()) iterator = tokenizedLine.getTokenIterator() column = 0 currentWidth = 0 From abf306943ae0f43ee618b56d15d0e855ba420aea Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 18:49:54 +0200 Subject: [PATCH 248/316] :bug: Measure latin chars with subpixel font scaling --- spec/text-editor-component-spec.coffee | 4 ++-- src/display-buffer.coffee | 2 +- src/lines-component.coffee | 14 +++++--------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 9032598e8..6f7d3aa95 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2893,12 +2893,12 @@ describe "TextEditorComponent", -> describe "when changing the font", -> it "measures the default char width and the double width char width", -> - expect(editor.getDefaultCharWidth()).toBe(12) + expect(editor.getDefaultCharWidth()).toBeCloseTo(12, 0) component.setFontSize(10) nextAnimationFrame() - expect(editor.getDefaultCharWidth()).toBe(6) + expect(editor.getDefaultCharWidth()).toBeCloseTo(6, 0) expect(editor.getDoubleWidthCharWidth()).toBe(10) describe "hiding and showing the editor", -> diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 3d960e2d3..197d7858c 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -266,7 +266,7 @@ class DisplayBuffer extends Model @getEditorWidthInChars() getSoftWrapColumnForTokenizedLine: (tokenizedLine) -> - lineMaxWidth = Math.round(@getSoftWrapColumn() * @getDefaultCharWidth()) + lineMaxWidth = @getSoftWrapColumn() * @getDefaultCharWidth() iterator = tokenizedLine.getTokenIterator() column = 0 currentWidth = 0 diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 8a97ccbfd..cce55b675 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -7,7 +7,9 @@ DummyLineNode.className = 'line' DummyLineNode.style.position = 'absolute' DummyLineNode.style.visibility = 'hidden' DummyLineNode.appendChild(document.createElement('span')) -DummyLineNode.firstChild.textContent = 'xフ' +DummyLineNode.appendChild(document.createElement('span')) +DummyLineNode.children[0].textContent = 'x' +DummyLineNode.children[1].textContent = '我' RangeForMeasurement = document.createRange() @@ -81,14 +83,8 @@ class LinesComponent extends TiledComponent textNode = DummyLineNode.firstChild.childNodes[0] lineHeightInPixels = DummyLineNode.getBoundingClientRect().height - - RangeForMeasurement.setStart(textNode, 0) - RangeForMeasurement.setEnd(textNode, 1) - defaultCharWidth = RangeForMeasurement.getBoundingClientRect().width - - RangeForMeasurement.setStart(textNode, 1) - RangeForMeasurement.setEnd(textNode, 2) - doubleWidthCharWidth = RangeForMeasurement.getBoundingClientRect().width + defaultCharWidth = DummyLineNode.children[0].getBoundingClientRect().width + doubleWidthCharWidth = DummyLineNode.children[1].getBoundingClientRect().width @domNode.removeChild(DummyLineNode) From 1fc9a25b5c824235edc8feac5946277d58d9b883 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 18:57:11 +0200 Subject: [PATCH 249/316] Recognize half width characters --- spec/text-utils-spec.coffee | 7 +++++++ src/text-utils.coffee | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/spec/text-utils-spec.coffee b/spec/text-utils-spec.coffee index a8bdbc2f7..81df866f4 100644 --- a/spec/text-utils-spec.coffee +++ b/spec/text-utils-spec.coffee @@ -57,3 +57,10 @@ describe 'text utilities', -> expect(textUtils.isDoubleWidthCharacter(",")).toBe(true) expect(textUtils.isDoubleWidthCharacter("a")).toBe(false) + + describe ".isHalfWidthCharacter(character)", -> + it "returns true when the character is an half width form", -> + expect(textUtils.isHalfWidthCharacter("ハ")).toBe(true) + expect(textUtils.isHalfWidthCharacter("ヒ")).toBe(true) + expect(textUtils.isHalfWidthCharacter("ᆲ")).toBe(true) + expect(textUtils.isHalfWidthCharacter("B")).toBe(false) diff --git a/src/text-utils.coffee b/src/text-utils.coffee index 1995094fe..3b0634948 100644 --- a/src/text-utils.coffee +++ b/src/text-utils.coffee @@ -81,6 +81,11 @@ isDoubleWidthCharacter = (character) -> isCjkUnifiedIdeograph(charCode) or isFullWidthForm(charCode) +isHalfWidthCharacter = (character) -> + charCode = character.charCodeAt(0) + + 0xFF65 <= charCode <= 0xFFDC + # Does the given string contain at least surrogate pair, variation sequence, # or combined character? # @@ -94,4 +99,4 @@ hasPairedCharacter = (string) -> index++ false -module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter} +module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter, isHalfWidthCharacter} From a3c3b48caa481615cffdb34383b930a469597dc9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 18:59:12 +0200 Subject: [PATCH 250/316] Recognize full width symbols --- spec/text-utils-spec.coffee | 1 + src/text-utils.coffee | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/text-utils-spec.coffee b/spec/text-utils-spec.coffee index 81df866f4..f95d7c22c 100644 --- a/spec/text-utils-spec.coffee +++ b/spec/text-utils-spec.coffee @@ -55,6 +55,7 @@ describe 'text utilities', -> expect(textUtils.isDoubleWidthCharacter("B")).toBe(true) expect(textUtils.isDoubleWidthCharacter(",")).toBe(true) + expect(textUtils.isDoubleWidthCharacter("¢")).toBe(true) expect(textUtils.isDoubleWidthCharacter("a")).toBe(false) diff --git a/src/text-utils.coffee b/src/text-utils.coffee index 3b0634948..dfb834252 100644 --- a/src/text-utils.coffee +++ b/src/text-utils.coffee @@ -71,7 +71,8 @@ isCjkUnifiedIdeograph = (charCode) -> 0x4e00 <= charCode <= 0x9faf isFullWidthForm = (charCode) -> - 0xFF01 <= charCode <= 0xFF5E + 0xFF01 <= charCode <= 0xFF5E or + 0xFFE0 <= charCode <= 0xFFE6 isDoubleWidthCharacter = (character) -> charCode = character.charCodeAt(0) From 8f7b303fc5927811b876c73bccd066618bd4fbe1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 19:01:23 +0200 Subject: [PATCH 251/316] Recognize half width symbols --- spec/text-utils-spec.coffee | 1 + src/text-utils.coffee | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spec/text-utils-spec.coffee b/spec/text-utils-spec.coffee index f95d7c22c..eace87513 100644 --- a/spec/text-utils-spec.coffee +++ b/spec/text-utils-spec.coffee @@ -64,4 +64,5 @@ describe 'text utilities', -> expect(textUtils.isHalfWidthCharacter("ハ")).toBe(true) expect(textUtils.isHalfWidthCharacter("ヒ")).toBe(true) expect(textUtils.isHalfWidthCharacter("ᆲ")).toBe(true) + expect(textUtils.isHalfWidthCharacter("■")).toBe(true) expect(textUtils.isHalfWidthCharacter("B")).toBe(false) diff --git a/src/text-utils.coffee b/src/text-utils.coffee index dfb834252..cfe0e807c 100644 --- a/src/text-utils.coffee +++ b/src/text-utils.coffee @@ -65,10 +65,10 @@ isKoreanCharacter = (charCode) -> 0xD7B0 <= charCode <= 0xD7FF isJapaneseCharacter = (charCode) -> - 0x3000 <= charCode <= 0x30ff + 0x3000 <= charCode <= 0x30FF isCjkUnifiedIdeograph = (charCode) -> - 0x4e00 <= charCode <= 0x9faf + 0x4E00 <= charCode <= 0x9FAF isFullWidthForm = (charCode) -> 0xFF01 <= charCode <= 0xFF5E or @@ -85,7 +85,8 @@ isDoubleWidthCharacter = (character) -> isHalfWidthCharacter = (character) -> charCode = character.charCodeAt(0) - 0xFF65 <= charCode <= 0xFFDC + 0xFF65 <= charCode <= 0xFFDC or + 0xFFE8 <= charCode <= 0xFFEE # Does the given string contain at least surrogate pair, variation sequence, # or combined character? From 91e9f16ff691d1b380b95537cd993f7e05948ce1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 19:22:12 +0200 Subject: [PATCH 252/316] :green_heart: --- src/display-buffer.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 197d7858c..2becff4e4 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -195,7 +195,7 @@ class DisplayBuffer extends Model if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth @defaultCharWidth = defaultCharWidth @doubleWidthCharWidth = doubleWidthCharWidth - @updateWrappedScreenLines() if @isSoftWrapped() and @getWidth()? + @updateWrappedScreenLines() if @isSoftWrapped() and @getEditorWidthInChars()? defaultCharWidth getCursorWidth: -> 1 From c616e86a00374ab56fcc1a379e48b3a02ea9c95a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 19:23:50 +0200 Subject: [PATCH 253/316] Take into account half width chars as well --- spec/display-buffer-spec.coffee | 9 +++++++++ src/display-buffer.coffee | 11 ++++++++++- src/text-editor.coffee | 6 ++++-- src/token-iterator.coffee | 5 ++++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index aafca68fe..ad1dba691 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -70,6 +70,15 @@ describe "DisplayBuffer", -> expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("们的板作为우리포럼hello ") expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe("world this is a pretty long latin line") + describe "when there are half width characters", -> + it "takes them into account when finding the soft wrap column", -> + displayBuffer.setDefaultCharWidth(1, 0, 5) + buffer.setText("abcᆰᆱᆲネヌネノハヒフヒフヌᄡ○○○hello world this is a pretty long line") + + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("abcᆰᆱᆲネヌネノハヒ") + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe("フヒフヌᄡ○○○hello ") + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("world this is a pretty long line") + describe "when editor.softWrapAtPreferredLineLength is set", -> it "uses the preferred line length as the soft wrap column when it is less than the configured soft wrap column", -> atom.config.set('editor.preferredLineLength', 100) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 2becff4e4..50e4741c8 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -189,12 +189,19 @@ class DisplayBuffer extends Model getLineHeightInPixels: -> @lineHeightInPixels setLineHeightInPixels: (@lineHeightInPixels) -> @lineHeightInPixels + getHalfWidthCharWidth: -> @halfWidthCharWidth + getDoubleWidthCharWidth: -> @doubleWidthCharWidth + getDefaultCharWidth: -> @defaultCharWidth - setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth=defaultCharWidth) -> + + setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) -> + doubleWidthCharWidth ?= defaultCharWidth + halfWidthCharWidth ?= defaultCharWidth if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth @defaultCharWidth = defaultCharWidth @doubleWidthCharWidth = doubleWidthCharWidth + @halfWidthCharWidth = halfWidthCharWidth @updateWrappedScreenLines() if @isSoftWrapped() and @getEditorWidthInChars()? defaultCharWidth @@ -281,6 +288,8 @@ class DisplayBuffer extends Model if iterator.hasDoubleWidthCharacterAt(textIndex) charWidth = @getDoubleWidthCharWidth() + else if iterator.hasHalfWidthCharacterAt(textIndex) + charWidth = @getHalfWidthCharWidth() else charWidth = @getDefaultCharWidth() diff --git a/src/text-editor.coffee b/src/text-editor.coffee index e4b0c8a37..58d590687 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -2976,11 +2976,13 @@ class TextEditor extends Model getLineHeightInPixels: -> @displayBuffer.getLineHeightInPixels() setLineHeightInPixels: (lineHeightInPixels) -> @displayBuffer.setLineHeightInPixels(lineHeightInPixels) + getHalfWidthCharWidth: -> @displayBuffer.getHalfWidthCharWidth() + getDoubleWidthCharWidth: -> @displayBuffer.getDoubleWidthCharWidth() getDefaultCharWidth: -> @displayBuffer.getDefaultCharWidth() - setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth=defaultCharWidth) -> - @displayBuffer.setDefaultCharWidth(defaultCharWidth, doubleWidthCharWidth) + setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) -> + @displayBuffer.setDefaultCharWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) setHeight: (height, reentrant=false) -> if reentrant diff --git a/src/token-iterator.coffee b/src/token-iterator.coffee index 4c4686635..9a5b63892 100644 --- a/src/token-iterator.coffee +++ b/src/token-iterator.coffee @@ -1,5 +1,5 @@ {SoftTab, HardTab, PairedCharacter, SoftWrapIndent} = require './special-token-symbols' -{isDoubleWidthCharacter} = require './text-utils' +{isDoubleWidthCharacter, isHalfWidthCharacter} = require './text-utils' module.exports = class TokenIterator @@ -86,5 +86,8 @@ class TokenIterator hasDoubleWidthCharacterAt: (charIndex) -> isDoubleWidthCharacter(@getText()[charIndex]) + hasHalfWidthCharacterAt: (charIndex) -> + isHalfWidthCharacter(@getText()[charIndex]) + isAtomic: -> @isSoftTab() or @isHardTab() or @isSoftWrapIndentation() or @isPairedCharacter() From 7394cc531cb4c029cb1980e93a14a3aba9c1230e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 20:06:38 +0200 Subject: [PATCH 254/316] Measure half width characters --- spec/text-editor-component-spec.coffee | 1 + src/lines-component.coffee | 5 ++++- src/text-editor-presenter.coffee | 7 ++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 6f7d3aa95..a110f9347 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2900,6 +2900,7 @@ describe "TextEditorComponent", -> expect(editor.getDefaultCharWidth()).toBeCloseTo(6, 0) expect(editor.getDoubleWidthCharWidth()).toBe(10) + expect(editor.getHalfWidthCharWidth()).toBe(5) describe "hiding and showing the editor", -> describe "when the editor is hidden when it is mounted", -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index cce55b675..031a790f8 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -8,8 +8,10 @@ DummyLineNode.style.position = 'absolute' DummyLineNode.style.visibility = 'hidden' DummyLineNode.appendChild(document.createElement('span')) DummyLineNode.appendChild(document.createElement('span')) +DummyLineNode.appendChild(document.createElement('span')) DummyLineNode.children[0].textContent = 'x' DummyLineNode.children[1].textContent = '我' +DummyLineNode.children[2].textContent = 'ハ' RangeForMeasurement = document.createRange() @@ -85,11 +87,12 @@ class LinesComponent extends TiledComponent lineHeightInPixels = DummyLineNode.getBoundingClientRect().height defaultCharWidth = DummyLineNode.children[0].getBoundingClientRect().width doubleWidthCharWidth = DummyLineNode.children[1].getBoundingClientRect().width + halfWidthCharWidth = DummyLineNode.children[2].getBoundingClientRect().width @domNode.removeChild(DummyLineNode) @presenter.setLineHeight(lineHeightInPixels) - @presenter.setBaseCharacterWidth(defaultCharWidth, doubleWidthCharWidth) + @presenter.setBaseCharacterWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) lineNodeForLineIdAndScreenRow: (lineId, screenRow) -> tile = @presenter.tileForRow(screenRow) diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 92ccb2d56..c7f260b79 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -1122,11 +1122,12 @@ class TextEditorPresenter @mouseWheelScreenRow = screenRow @didStartScrolling() - setBaseCharacterWidth: (baseCharacterWidth, doubleWidthCharWidth) -> - unless @baseCharacterWidth is baseCharacterWidth and @doubleWidthCharWidth is doubleWidthCharWidth + setBaseCharacterWidth: (baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth) -> + unless @baseCharacterWidth is baseCharacterWidth and @doubleWidthCharWidth is doubleWidthCharWidth and @halfWidthCharWidth is halfWidthCharWidth @baseCharacterWidth = baseCharacterWidth @doubleWidthCharWidth = doubleWidthCharWidth - @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth) + @halfWidthCharWidth = halfWidthCharWidth + @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth) @characterWidthsChanged() characterWidthsChanged: -> From be1b2e6122aa273e7714c0ca0519b9f5d19e49ef Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Oct 2015 12:08:07 -0600 Subject: [PATCH 255/316] Increase timeout when waiting for atom-workspace to exist Signed-off-by: Max Brunsfeld --- spec/integration/startup-spec.coffee | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/integration/startup-spec.coffee b/spec/integration/startup-spec.coffee index 74dd80f9e..8e1e7c4d7 100644 --- a/spec/integration/startup-spec.coffee +++ b/spec/integration/startup-spec.coffee @@ -29,7 +29,7 @@ describe "Starting Atom", -> runAtom [path.join(tempDirPath, "new-file")], {ATOM_HOME: atomHome}, (client) -> client .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .treeViewRootDirectories() @@ -55,7 +55,7 @@ describe "Starting Atom", -> runAtom ["#{filePath}:3"], {ATOM_HOME: atomHome}, (client) -> client .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .waitForExist("atom-text-editor", 5000) .then (exists) -> expect(exists).toBe true @@ -80,7 +80,7 @@ describe "Starting Atom", -> runAtom ["#{filePath}:2:2"], {ATOM_HOME: atomHome}, (client) -> client .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .waitForExist("atom-text-editor", 5000) .then (exists) -> expect(exists).toBe true @@ -98,7 +98,7 @@ describe "Starting Atom", -> runAtom ["#{filePath}: "], {ATOM_HOME: atomHome}, (client) -> client .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .waitForExist("atom-text-editor", 5000) .then (exists) -> expect(exists).toBe true @@ -114,7 +114,7 @@ describe "Starting Atom", -> runAtom [path.join(tempDirPath, "new-file")], {ATOM_HOME: atomHome}, (client) -> client .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 5000) # Opening another file reuses the same window and does not change the @@ -131,7 +131,7 @@ describe "Starting Atom", -> .waitForNewWindow(-> @startAnotherAtom([otherTempDirPath], ATOM_HOME: atomHome) , 5000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(0, 1000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([otherTempDirPath]) @@ -140,14 +140,14 @@ describe "Starting Atom", -> it "remembers the state of the window", -> runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(0, 3000) .execute -> atom.workspace.open() .waitForPaneItemCount(1, 3000) runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 5000) describe "opening multiple directories simultaneously", -> @@ -157,14 +157,14 @@ describe "Starting Atom", -> runAtom [tempDirPath, otherTempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([tempDirPath, otherTempDirPath]) # Opening one of those directories again reuses the same window and # does not change the project paths. .startAnotherAtom([nestedDir], ATOM_HOME: atomHome) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([tempDirPath, otherTempDirPath]) @@ -247,6 +247,6 @@ describe "Starting Atom", -> runAtom [remoteDirectory], {ATOM_HOME: atomHome}, (client) -> client .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 5000) + .waitForExist("atom-workspace", 10000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([remoteDirectory]) From c9eb75cbe1f68228187d4afa7b798aff24f80b48 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 20:14:38 +0200 Subject: [PATCH 256/316] :memo: Better wording on specs --- spec/text-editor-component-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index a110f9347..ab87e00a8 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2892,7 +2892,7 @@ describe "TextEditorComponent", -> expect(event.abortKeyBinding).toHaveBeenCalled() describe "when changing the font", -> - it "measures the default char width and the double width char width", -> + it "measures the default char, the double width char and the half width char widths ", -> expect(editor.getDefaultCharWidth()).toBeCloseTo(12, 0) component.setFontSize(10) From 52946db17994e2f5595500b834f86c8008b11cd2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Oct 2015 12:54:33 -0600 Subject: [PATCH 257/316] Ensure windows/workspace present before proceeding in integration specs Signed-off-by: Max Brunsfeld --- spec/integration/helpers/start-atom.coffee | 12 ++++++++--- spec/integration/startup-spec.coffee | 25 ---------------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/spec/integration/helpers/start-atom.coffee b/spec/integration/helpers/start-atom.coffee index 6a7144141..b8768f532 100644 --- a/spec/integration/helpers/start-atom.coffee +++ b/spec/integration/helpers/start-atom.coffee @@ -91,7 +91,8 @@ buildAtomClient = (args, env) -> cb(null) .addCommand "treeViewRootDirectories", (cb) -> - @execute(-> + @waitForExist('.tree-view', 10000) + .execute(-> for element in document.querySelectorAll(".tree-view .project-root > .header .name") element.dataset.path , cb) @@ -104,7 +105,8 @@ buildAtomClient = (args, env) -> .then ({value: newWindowHandles}) -> [newWindowHandle] = difference(newWindowHandles, oldWindowHandles) return done() unless newWindowHandle - @window(newWindowHandle, done) + @window(newWindowHandle) + .waitForExist('atom-workspace', 10000, done) .addCommand "startAnotherAtom", (args, env, done) -> @call -> @@ -168,7 +170,11 @@ module.exports = (args, env, fn) -> jasmine.getEnv().currentSpec.fail(new Error(err.response?.body?.value?.message)) finish() - fn(client.init()).then(finish) + fn( + client.init() + .waitUntil((-> @windowHandles().then ({value}) -> value.length > 0), 10000) + .waitForExist("atom-workspace", 10000) + ).then(finish) , 30000) waitsFor("webdriver to stop", chromeDriverDown, 15000) diff --git a/spec/integration/startup-spec.coffee b/spec/integration/startup-spec.coffee index 8e1e7c4d7..36342470d 100644 --- a/spec/integration/startup-spec.coffee +++ b/spec/integration/startup-spec.coffee @@ -28,8 +28,6 @@ describe "Starting Atom", -> it "opens the parent directory and creates an empty text editor", -> runAtom [path.join(tempDirPath, "new-file")], {ATOM_HOME: atomHome}, (client) -> client - .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .treeViewRootDirectories() @@ -54,8 +52,6 @@ describe "Starting Atom", -> runAtom ["#{filePath}:3"], {ATOM_HOME: atomHome}, (client) -> client - .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .waitForExist("atom-text-editor", 5000) .then (exists) -> expect(exists).toBe true @@ -79,8 +75,6 @@ describe "Starting Atom", -> runAtom ["#{filePath}:2:2"], {ATOM_HOME: atomHome}, (client) -> client - .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .waitForExist("atom-text-editor", 5000) .then (exists) -> expect(exists).toBe true @@ -97,8 +91,6 @@ describe "Starting Atom", -> filePath = path.join(tempDirPath, "new-file") runAtom ["#{filePath}: "], {ATOM_HOME: atomHome}, (client) -> client - .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 1000) .waitForExist("atom-text-editor", 5000) .then (exists) -> expect(exists).toBe true @@ -113,8 +105,6 @@ describe "Starting Atom", -> runAtom [path.join(tempDirPath, "new-file")], {ATOM_HOME: atomHome}, (client) -> client - .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 5000) # Opening another file reuses the same window and does not change the @@ -131,7 +121,6 @@ describe "Starting Atom", -> .waitForNewWindow(-> @startAnotherAtom([otherTempDirPath], ATOM_HOME: atomHome) , 5000) - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(0, 1000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([otherTempDirPath]) @@ -140,14 +129,12 @@ describe "Starting Atom", -> it "remembers the state of the window", -> runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(0, 3000) .execute -> atom.workspace.open() .waitForPaneItemCount(1, 3000) runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace", 10000) .waitForPaneItemCount(1, 5000) describe "opening multiple directories simultaneously", -> @@ -157,14 +144,12 @@ describe "Starting Atom", -> runAtom [tempDirPath, otherTempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace", 10000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([tempDirPath, otherTempDirPath]) # Opening one of those directories again reuses the same window and # does not change the project paths. .startAnotherAtom([nestedDir], ATOM_HOME: atomHome) - .waitForExist("atom-workspace", 10000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([tempDirPath, otherTempDirPath]) @@ -172,7 +157,6 @@ describe "Starting Atom", -> it "reuses that window to open a directory", -> runAtom [], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace") .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([]) @@ -188,7 +172,6 @@ describe "Starting Atom", -> it "opens a new window with a single untitled buffer", -> runAtom [], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace") .waitForPaneItemCount(1, 5000) # Opening with no file paths always creates a new window, even if @@ -196,7 +179,6 @@ describe "Starting Atom", -> .waitForNewWindow(-> @startAnotherAtom([], ATOM_HOME: atomHome) , 5000) - .waitForExist("atom-workspace") .waitForPaneItemCount(1, 5000) it "doesn't open a new window if openEmptyEditorOnStart is disabled", -> @@ -207,17 +189,14 @@ describe "Starting Atom", -> runAtom [], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace") .waitForPaneItemCount(0, 5000) it "reopens any previously opened windows", -> runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) -> client - .waitForExist("atom-workspace") .waitForNewWindow(-> @startAnotherAtom([otherTempDirPath], ATOM_HOME: atomHome) , 5000) - .waitForExist("atom-workspace") runAtom [], {ATOM_HOME: atomHome}, (client) -> windowProjectPaths = [] @@ -226,12 +205,10 @@ describe "Starting Atom", -> .waitForWindowCount(2, 10000) .then ({value: windowHandles}) -> @window(windowHandles[0]) - .waitForExist("atom-workspace") .treeViewRootDirectories() .then ({value: directories}) -> windowProjectPaths.push(directories) .window(windowHandles[1]) - .waitForExist("atom-workspace") .treeViewRootDirectories() .then ({value: directories}) -> windowProjectPaths.push(directories) @@ -246,7 +223,5 @@ describe "Starting Atom", -> remoteDirectory = 'remote://server:3437/some/directory/path' runAtom [remoteDirectory], {ATOM_HOME: atomHome}, (client) -> client - .waitForWindowCount(1, 1000) - .waitForExist("atom-workspace", 10000) .treeViewRootDirectories() .then ({value}) -> expect(value).toEqual([remoteDirectory]) From 4766c98bbe66422fadfaa23fb160411dfc66eb11 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 15 Oct 2015 21:02:21 +0200 Subject: [PATCH 258/316] Treat Korean characters as different kinds of chars --- spec/display-buffer-spec.coffee | 11 +++++++++++ spec/text-editor-component-spec.coffee | 3 ++- spec/text-utils-spec.coffee | 14 +++++++++++--- src/display-buffer.coffee | 10 ++++++++-- src/lines-component.coffee | 5 ++++- src/text-editor-presenter.coffee | 7 ++++--- src/text-editor.coffee | 6 ++++-- src/text-utils.coffee | 19 ++++++++++--------- src/token-iterator.coffee | 5 ++++- 9 files changed, 58 insertions(+), 22 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index ad1dba691..19eccd58d 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -79,6 +79,17 @@ describe "DisplayBuffer", -> expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe("フヒフヌᄡ○○○hello ") expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("world this is a pretty long line") + describe "when there are korean characters", -> + it "takes them into account when finding the soft wrap column", -> + displayBuffer.setDefaultCharWidth(1, 0, 0, 10) + buffer.setText("1234세계를 향한 대화, 유니코 제10회유니코드국제") + + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("1234세계를 ") + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe("향한 대화, ") + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("유니코 ") + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe("제10회유니") + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe("코드국제") + describe "when editor.softWrapAtPreferredLineLength is set", -> it "uses the preferred line length as the soft wrap column when it is less than the configured soft wrap column", -> atom.config.set('editor.preferredLineLength', 100) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index ab87e00a8..45e1dbb6b 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2892,13 +2892,14 @@ describe "TextEditorComponent", -> expect(event.abortKeyBinding).toHaveBeenCalled() describe "when changing the font", -> - it "measures the default char, the double width char and the half width char widths ", -> + it "measures the default char, the korean char, the double width char and the half width char widths", -> expect(editor.getDefaultCharWidth()).toBeCloseTo(12, 0) component.setFontSize(10) nextAnimationFrame() expect(editor.getDefaultCharWidth()).toBeCloseTo(6, 0) + expect(editor.getKoreanCharWidth()).toBeCloseTo(9, 0) expect(editor.getDoubleWidthCharWidth()).toBe(10) expect(editor.getHalfWidthCharWidth()).toBe(5) diff --git a/spec/text-utils-spec.coffee b/spec/text-utils-spec.coffee index eace87513..dd528b37e 100644 --- a/spec/text-utils-spec.coffee +++ b/spec/text-utils-spec.coffee @@ -46,13 +46,11 @@ describe 'text utilities', -> expect(textUtils.isPairedCharacter('ae\u0301c', 4)).toBe false describe ".isDoubleWidthCharacter(character)", -> - it "returns true when the character is either japanese, korean, chinese or a full width form", -> + it "returns true when the character is either japanese, chinese or a full width form", -> expect(textUtils.isDoubleWidthCharacter("我")).toBe(true) expect(textUtils.isDoubleWidthCharacter("私")).toBe(true) - expect(textUtils.isDoubleWidthCharacter("우")).toBe(true) - expect(textUtils.isDoubleWidthCharacter("B")).toBe(true) expect(textUtils.isDoubleWidthCharacter(",")).toBe(true) expect(textUtils.isDoubleWidthCharacter("¢")).toBe(true) @@ -65,4 +63,14 @@ describe 'text utilities', -> expect(textUtils.isHalfWidthCharacter("ヒ")).toBe(true) expect(textUtils.isHalfWidthCharacter("ᆲ")).toBe(true) expect(textUtils.isHalfWidthCharacter("■")).toBe(true) + expect(textUtils.isHalfWidthCharacter("B")).toBe(false) + + describe ".isKoreanCharacter(character)", -> + it "returns true when the character is a korean character", -> + expect(textUtils.isKoreanCharacter("우")).toBe(true) + expect(textUtils.isKoreanCharacter("가")).toBe(true) + expect(textUtils.isKoreanCharacter("ㅢ")).toBe(true) + expect(textUtils.isKoreanCharacter("ㄼ")).toBe(true) + + expect(textUtils.isKoreanCharacter("O")).toBe(false) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 50e4741c8..2a93aa951 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -189,19 +189,23 @@ class DisplayBuffer extends Model getLineHeightInPixels: -> @lineHeightInPixels setLineHeightInPixels: (@lineHeightInPixels) -> @lineHeightInPixels + getKoreanCharWidth: -> @koreanCharWidth + getHalfWidthCharWidth: -> @halfWidthCharWidth getDoubleWidthCharWidth: -> @doubleWidthCharWidth getDefaultCharWidth: -> @defaultCharWidth - setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) -> + setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) -> doubleWidthCharWidth ?= defaultCharWidth halfWidthCharWidth ?= defaultCharWidth - if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth + koreanCharWidth ?= defaultCharWidth + if defaultCharWidth isnt @defaultCharWidth or doubleWidthCharWidth isnt @doubleWidthCharWidth and halfWidthCharWidth isnt @halfWidthCharWidth and koreanCharWidth isnt @koreanCharWidth @defaultCharWidth = defaultCharWidth @doubleWidthCharWidth = doubleWidthCharWidth @halfWidthCharWidth = halfWidthCharWidth + @koreanCharWidth = koreanCharWidth @updateWrappedScreenLines() if @isSoftWrapped() and @getEditorWidthInChars()? defaultCharWidth @@ -290,6 +294,8 @@ class DisplayBuffer extends Model charWidth = @getDoubleWidthCharWidth() else if iterator.hasHalfWidthCharacterAt(textIndex) charWidth = @getHalfWidthCharWidth() + else if iterator.hasKoreanCharacterAt(textIndex) + charWidth = @getKoreanCharWidth() else charWidth = @getDefaultCharWidth() diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 031a790f8..98b274fae 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -9,9 +9,11 @@ DummyLineNode.style.visibility = 'hidden' DummyLineNode.appendChild(document.createElement('span')) DummyLineNode.appendChild(document.createElement('span')) DummyLineNode.appendChild(document.createElement('span')) +DummyLineNode.appendChild(document.createElement('span')) DummyLineNode.children[0].textContent = 'x' DummyLineNode.children[1].textContent = '我' DummyLineNode.children[2].textContent = 'ハ' +DummyLineNode.children[3].textContent = '세' RangeForMeasurement = document.createRange() @@ -88,11 +90,12 @@ class LinesComponent extends TiledComponent defaultCharWidth = DummyLineNode.children[0].getBoundingClientRect().width doubleWidthCharWidth = DummyLineNode.children[1].getBoundingClientRect().width halfWidthCharWidth = DummyLineNode.children[2].getBoundingClientRect().width + koreanCharWidth = DummyLineNode.children[3].getBoundingClientRect().width @domNode.removeChild(DummyLineNode) @presenter.setLineHeight(lineHeightInPixels) - @presenter.setBaseCharacterWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) + @presenter.setBaseCharacterWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) lineNodeForLineIdAndScreenRow: (lineId, screenRow) -> tile = @presenter.tileForRow(screenRow) diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index c7f260b79..985ca1c95 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -1122,12 +1122,13 @@ class TextEditorPresenter @mouseWheelScreenRow = screenRow @didStartScrolling() - setBaseCharacterWidth: (baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth) -> - unless @baseCharacterWidth is baseCharacterWidth and @doubleWidthCharWidth is doubleWidthCharWidth and @halfWidthCharWidth is halfWidthCharWidth + setBaseCharacterWidth: (baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) -> + unless @baseCharacterWidth is baseCharacterWidth and @doubleWidthCharWidth is doubleWidthCharWidth and @halfWidthCharWidth is halfWidthCharWidth and koreanCharWidth is @koreanCharWidth @baseCharacterWidth = baseCharacterWidth @doubleWidthCharWidth = doubleWidthCharWidth @halfWidthCharWidth = halfWidthCharWidth - @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth) + @koreanCharWidth = koreanCharWidth + @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) @characterWidthsChanged() characterWidthsChanged: -> diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 58d590687..2610c5970 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -2976,13 +2976,15 @@ class TextEditor extends Model getLineHeightInPixels: -> @displayBuffer.getLineHeightInPixels() setLineHeightInPixels: (lineHeightInPixels) -> @displayBuffer.setLineHeightInPixels(lineHeightInPixels) + getKoreanCharWidth: -> @displayBuffer.getKoreanCharWidth() + getHalfWidthCharWidth: -> @displayBuffer.getHalfWidthCharWidth() getDoubleWidthCharWidth: -> @displayBuffer.getDoubleWidthCharWidth() getDefaultCharWidth: -> @displayBuffer.getDefaultCharWidth() - setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) -> - @displayBuffer.setDefaultCharWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth) + setDefaultCharWidth: (defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) -> + @displayBuffer.setDefaultCharWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) setHeight: (height, reentrant=false) -> if reentrant diff --git a/src/text-utils.coffee b/src/text-utils.coffee index cfe0e807c..82bed4da5 100644 --- a/src/text-utils.coffee +++ b/src/text-utils.coffee @@ -57,13 +57,6 @@ isPairedCharacter = (string, index=0) -> isVariationSequence(charCodeA, charCodeB) or isCombinedCharacter(charCodeA, charCodeB) -isKoreanCharacter = (charCode) -> - 0xAC00 <= charCode <= 0xD7A3 or - 0x1100 <= charCode <= 0x11FF or - 0x3130 <= charCode <= 0x318F or - 0xA960 <= charCode <= 0xA97F or - 0xD7B0 <= charCode <= 0xD7FF - isJapaneseCharacter = (charCode) -> 0x3000 <= charCode <= 0x30FF @@ -77,7 +70,6 @@ isFullWidthForm = (charCode) -> isDoubleWidthCharacter = (character) -> charCode = character.charCodeAt(0) - isKoreanCharacter(charCode) or isJapaneseCharacter(charCode) or isCjkUnifiedIdeograph(charCode) or isFullWidthForm(charCode) @@ -88,6 +80,15 @@ isHalfWidthCharacter = (character) -> 0xFF65 <= charCode <= 0xFFDC or 0xFFE8 <= charCode <= 0xFFEE +isKoreanCharacter = (character) -> + charCode = character.charCodeAt(0) + + 0xAC00 <= charCode <= 0xD7A3 or + 0x1100 <= charCode <= 0x11FF or + 0x3130 <= charCode <= 0x318F or + 0xA960 <= charCode <= 0xA97F or + 0xD7B0 <= charCode <= 0xD7FF + # Does the given string contain at least surrogate pair, variation sequence, # or combined character? # @@ -101,4 +102,4 @@ hasPairedCharacter = (string) -> index++ false -module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter, isHalfWidthCharacter} +module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter, isHalfWidthCharacter, isKoreanCharacter} diff --git a/src/token-iterator.coffee b/src/token-iterator.coffee index 9a5b63892..120f62fe4 100644 --- a/src/token-iterator.coffee +++ b/src/token-iterator.coffee @@ -1,5 +1,5 @@ {SoftTab, HardTab, PairedCharacter, SoftWrapIndent} = require './special-token-symbols' -{isDoubleWidthCharacter, isHalfWidthCharacter} = require './text-utils' +{isDoubleWidthCharacter, isHalfWidthCharacter, isKoreanCharacter} = require './text-utils' module.exports = class TokenIterator @@ -89,5 +89,8 @@ class TokenIterator hasHalfWidthCharacterAt: (charIndex) -> isHalfWidthCharacter(@getText()[charIndex]) + hasKoreanCharacterAt: (charIndex) -> + isKoreanCharacter(@getText()[charIndex]) + isAtomic: -> @isSoftTab() or @isHardTab() or @isSoftWrapIndentation() or @isPairedCharacter() From 28ed6f3d9f66666c874ef0a499ad18ebc9da6824 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Oct 2015 13:26:30 -0600 Subject: [PATCH 259/316] Restore async window method calls Signed-off-by: Max Brunsfeld --- src/application-delegate.coffee | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index 3492df05c..79afee802 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -21,48 +21,48 @@ class ApplicationDelegate remote.getCurrentWindow() closeWindow: -> - remote.getCurrentWindow().close() + ipc.send("call-window-method", "close") getWindowSize: -> [width, height] = remote.getCurrentWindow().getSize() {width, height} setWindowSize: (width, height) -> - remote.getCurrentWindow().setSize(width, height) + ipc.send("call-window-method", "setSize", width, height) getWindowPosition: -> [x, y] = remote.getCurrentWindow().getPosition() {x, y} setWindowPosition: (x, y) -> - remote.getCurrentWindow().setPosition(x, y) + ipc.send("call-window-method", "setPosition", x, y) centerWindow: -> - remote.getCurrentWindow().center() + ipc.send("call-window-method", "center") focusWindow: -> - remote.getCurrentWindow().focus() + ipc.send("call-window-method", "focus") showWindow: -> - remote.getCurrentWindow().show() + ipc.send("call-window-method", "show") hideWindow: -> - remote.getCurrentWindow().hide() + ipc.send("call-window-method", "hide") restartWindow: -> - remote.getCurrentWindow().restart() + ipc.send("call-window-method", "restart") isWindowMaximized: -> remote.getCurrentWindow().isMaximized() maximizeWindow: -> - remote.getCurrentWindow().maximize() + ipc.send("call-window-method", "maximize") isWindowFullScreen: -> remote.getCurrentWindow().isFullScreen() setWindowFullScreen: (fullScreen=false) -> - remote.getCurrentWindow().setFullScreen(fullScreen) + ipc.send("call-window-method", "setFullScreen", fullScreen) openWindowDevTools: -> remote.getCurrentWindow().openDevTools() @@ -74,10 +74,10 @@ class ApplicationDelegate remote.getCurrentWindow().executeJavaScriptInDevTools(code) setWindowDocumentEdited: (edited) -> - remote.getCurrentWindow().setDocumentEdited(edited) + ipc.send("call-window-method", "setDocumentEdited", edited) setRepresentedFilename: (filename) -> - remote.getCurrentWindow().setRepresentedFilename(filename) + ipc.send("call-window-method", "setRepresentedFilename", filename) setRepresentedDirectoryPaths: (paths) -> loadSettings = getWindowLoadSettings() @@ -85,7 +85,7 @@ class ApplicationDelegate setWindowLoadSettings(loadSettings) setAutoHideWindowMenuBar: (autoHide) -> - remote.getCurrentWindow().setAutoHideMenuBar(autoHide) + ipc.send("call-window-method", "setAutoHideMenuBar", autoHide) setWindowMenuBarVisibility: (visible) -> remote.getCurrentWindow().setMenuBarVisibility(visible) From 93fe0208a5cbf89fa6cdc524cba996490bb33697 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 15 Oct 2015 15:12:57 -0700 Subject: [PATCH 260/316] Make atom.setSize() synchronous again, for now This method is public, and a spec for TextEditorComponent dependend on it staying synchronous --- src/application-delegate.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index 79afee802..f2b425137 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -28,7 +28,7 @@ class ApplicationDelegate {width, height} setWindowSize: (width, height) -> - ipc.send("call-window-method", "setSize", width, height) + remote.getCurrentWindow().setSize(width, height) getWindowPosition: -> [x, y] = remote.getCurrentWindow().getPosition() From e6a494cfdb2db86dcfeccf948bd42100b82210f7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Oct 2015 16:45:29 -0600 Subject: [PATCH 261/316] Fix busted merge --- package.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/package.json b/package.json index 037121f42..473c69423 100644 --- a/package.json +++ b/package.json @@ -103,13 +103,8 @@ "open-on-github": "0.38.0", "package-generator": "0.40.0", "release-notes": "0.53.0", -<<<<<<< HEAD - "settings-view": "0.230.0", - "snippets": "0.101.0", -======= "settings-view": "0.230.1", - "snippets": "0.100.0", ->>>>>>> origin/master + "snippets": "0.101.0", "spell-check": "0.61.0", "status-bar": "0.79.0", "styleguide": "0.44.0", From 27526f492c4f5add68473aa48fb5c36fe291debb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 15 Oct 2015 18:01:20 -0700 Subject: [PATCH 262/316] Fix fall-back to dev resource path in main --- src/browser/main.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 4755a7ff1..6a141cf1a 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -133,7 +133,7 @@ parseCommandLine = -> if args['resource-path'] devMode = true resourcePath = args['resource-path'] - resourcePath ?= devResourcePath if devMode + resourcePath ?= devResourcePath if devMode unless fs.statSyncNoException(resourcePath) resourcePath = path.dirname(path.dirname(__dirname)) From fd0b062e8e6833ff113fb45a48590b7b023f1878 Mon Sep 17 00:00:00 2001 From: simurai Date: Fri, 16 Oct 2015 10:55:22 +0900 Subject: [PATCH 263/316] :arrow_up: tree-view@v0.192.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 473c69423..a0c79c47d 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "symbols-view": "0.109.0", "tabs": "0.85.0", "timecop": "0.33.0", - "tree-view": "0.190.0", + "tree-view": "0.192.0", "update-package-dependencies": "0.10.0", "welcome": "0.31.0", "whitespace": "0.31.0", From 21aee18911ea33f0e4ff416f8f3b14c6ac51385e Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Fri, 16 Oct 2015 07:20:30 +0200 Subject: [PATCH 264/316] :arrow_up: tree-view@0.192.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a0c79c47d..f3279644d 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "symbols-view": "0.109.0", "tabs": "0.85.0", "timecop": "0.33.0", - "tree-view": "0.192.0", + "tree-view": "0.192.1", "update-package-dependencies": "0.10.0", "welcome": "0.31.0", "whitespace": "0.31.0", From 4df007eb878cb8cb4e10e29ae107dc0d1394d1a5 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Fri, 16 Oct 2015 09:14:57 +0200 Subject: [PATCH 265/316] :arrow_up: tree-view@0.192.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3279644d..4b89dc162 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "symbols-view": "0.109.0", "tabs": "0.85.0", "timecop": "0.33.0", - "tree-view": "0.192.1", + "tree-view": "0.192.2", "update-package-dependencies": "0.10.0", "welcome": "0.31.0", "whitespace": "0.31.0", From eb3133b7e7c351e53f377b1d2d46162e361d095d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 16 Oct 2015 10:30:45 +0200 Subject: [PATCH 266/316] :green_heart: --- spec/display-buffer-spec.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 3e1178749..68dd9c754 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -68,17 +68,17 @@ describe "DisplayBuffer", -> describe "rendering of soft-wrapped lines", -> describe "when there are double width characters", -> it "takes them into account when finding the soft wrap column", -> - buffer.setText("私たちのフ是一个地方,数千名学生12345业余爱们的板作为우리포럼hello world this is a pretty long latin line") - displayBuffer.setDefaultCharWidth(1, 5) + buffer.setText("私たちのフ是一个地方,数千名学生12345业余爱们的板作为hello world this is a pretty long latin line") + displayBuffer.setDefaultCharWidth(1, 5, 0, 0) expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("私たちのフ是一个地方") expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe(",数千名学生12345业余爱") - expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("们的板作为우리포럼hello ") - expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe("world this is a pretty long latin line") + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe("们的板作为hello world this is a ") + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe("pretty long latin line") describe "when there are half width characters", -> it "takes them into account when finding the soft wrap column", -> - displayBuffer.setDefaultCharWidth(1, 0, 5) + displayBuffer.setDefaultCharWidth(1, 0, 5, 0) buffer.setText("abcᆰᆱᆲネヌネノハヒフヒフヌᄡ○○○hello world this is a pretty long line") expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe("abcᆰᆱᆲネヌネノハヒ") From 3f53a726209a9c280606b536af2037d533b7fd82 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 16 Oct 2015 10:38:51 +0200 Subject: [PATCH 267/316] :racehorse: Cache text in TokenIterator --- src/token-iterator.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/token-iterator.coffee b/src/token-iterator.coffee index 92529d0e9..de914e4b5 100644 --- a/src/token-iterator.coffee +++ b/src/token-iterator.coffee @@ -53,6 +53,8 @@ class TokenIterator else @screenEnd = @screenStart + tag @bufferEnd = @bufferStart + tag + + @text = @line.text.substring(@screenStart, @screenEnd) return true false @@ -68,8 +70,7 @@ class TokenIterator getScopes: -> @scopes - getText: -> - @line.text.substring(@screenStart, @screenEnd) + getText: -> @text isSoftTab: -> @line.specialTokens[@index] is SoftTab From e843c2f05821a58e7a38396b1d81998406d3b309 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 16 Oct 2015 10:44:18 +0200 Subject: [PATCH 268/316] :racehorse: Fetch scopes only if required --- src/display-buffer.coffee | 2 +- src/lines-yardstick.coffee | 4 ++-- src/token-iterator.coffee | 45 +++++++++++++++++++++++--------------- src/tokenized-line.coffee | 2 +- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index b3a5a628c..eccdfb7f3 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -293,7 +293,7 @@ class DisplayBuffer extends Model getSoftWrapColumnForTokenizedLine: (tokenizedLine) -> lineMaxWidth = @getSoftWrapColumn() * @getDefaultCharWidth() - iterator = tokenizedLine.getTokenIterator() + iterator = tokenizedLine.getTokenIterator(false) column = 0 currentWidth = 0 while iterator.next() diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index 3254451f1..fa00bae40 100644 --- a/src/lines-yardstick.coffee +++ b/src/lines-yardstick.coffee @@ -40,7 +40,7 @@ class LinesYardstick previousColumn = 0 previousLeft = 0 - @tokenIterator.reset(line) + @tokenIterator.reset(line, false) while @tokenIterator.next() text = @tokenIterator.getText() textIndex = 0 @@ -112,7 +112,7 @@ class LinesYardstick indexWithinTextNode = null charIndex = 0 - @tokenIterator.reset(line) + @tokenIterator.reset(line, false) while @tokenIterator.next() break if foundIndexWithinTextNode? diff --git a/src/token-iterator.coffee b/src/token-iterator.coffee index de914e4b5..8f0fe202f 100644 --- a/src/token-iterator.coffee +++ b/src/token-iterator.coffee @@ -3,18 +3,16 @@ module.exports = class TokenIterator - constructor: ({@grammarRegistry}, line) -> - @reset(line) if line? + constructor: ({@grammarRegistry}, line, enableScopes) -> + @reset(line, enableScopes) if line? - reset: (@line) -> + reset: (@line, @enableScopes=true) -> @index = null @bufferStart = @line.startBufferColumn @bufferEnd = @bufferStart @screenStart = 0 @screenEnd = 0 - @scopes = @line.openScopes.map (id) => @grammarRegistry.scopeForId(id) - @scopeStarts = @scopes.slice() - @scopeEnds = [] + @resetScopes() if @enableScopes this next: -> @@ -22,26 +20,16 @@ class TokenIterator if @index? @index++ - @scopeEnds.length = 0 - @scopeStarts.length = 0 @bufferStart = @bufferEnd @screenStart = @screenEnd + @clearScopeStartsAndEnds() if @enableScopes else @index = 0 while @index < tags.length tag = tags[@index] if tag < 0 - scope = @grammarRegistry.scopeForId(tag) - if tag % 2 is 0 - if @scopeStarts[@scopeStarts.length - 1] is scope - @scopeStarts.pop() - else - @scopeEnds.push(scope) - @scopes.pop() - else - @scopeStarts.push(scope) - @scopes.push(scope) + @handleScopeForTag(tag) if @enableScopes @index++ else if @isHardTab() @@ -59,6 +47,27 @@ class TokenIterator false + resetScopes: -> + @scopes = @line.openScopes.map (id) => @grammarRegistry.scopeForId(id) + @scopeStarts = @scopes.slice() + @scopeEnds = [] + + clearScopeStartsAndEnds: -> + @scopeEnds.length = 0 + @scopeStarts.length = 0 + + handleScopeForTag: (tag) -> + scope = @grammarRegistry.scopeForId(tag) + if tag % 2 is 0 + if @scopeStarts[@scopeStarts.length - 1] is scope + @scopeStarts.pop() + else + @scopeEnds.push(scope) + @scopes.pop() + else + @scopeStarts.push(scope) + @scopes.push(scope) + getBufferStart: -> @bufferStart getBufferEnd: -> @bufferEnd diff --git a/src/tokenized-line.coffee b/src/tokenized-line.coffee index bf234b6d3..2a27d3f12 100644 --- a/src/tokenized-line.coffee +++ b/src/tokenized-line.coffee @@ -184,7 +184,7 @@ class TokenizedLine @lineIsWhitespaceOnly = true @firstTrailingWhitespaceIndex = 0 - getTokenIterator: -> @tokenIterator.reset(this) + getTokenIterator: -> @tokenIterator.reset(this, arguments...) Object.defineProperty @prototype, 'tokens', get: -> iterator = @getTokenIterator() From 05c6c9f9be9bc2d591d2ab87db8e9f8e2e0c21c4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 16 Oct 2015 11:14:20 +0200 Subject: [PATCH 269/316] Soft wrap only when we know lineMaxWidth --- src/display-buffer.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index eccdfb7f3..1021955cf 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -293,6 +293,10 @@ class DisplayBuffer extends Model getSoftWrapColumnForTokenizedLine: (tokenizedLine) -> lineMaxWidth = @getSoftWrapColumn() * @getDefaultCharWidth() + + return if Number.isNaN(lineMaxWidth) + return 0 if lineMaxWidth is 0 + iterator = tokenizedLine.getTokenIterator(false) column = 0 currentWidth = 0 From cd47c7be02e497ba9fb4a95dbbe3c1a7891b3790 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 16 Oct 2015 11:22:03 +0200 Subject: [PATCH 270/316] Fix leftover spec --- spec/text-editor-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index dd01b816f..8ce026741 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -1531,6 +1531,7 @@ describe "TextEditor", -> it "can add selections to soft-wrapped line segments", -> editor.setSoftWrapped(true) editor.setEditorWidthInChars(40) + editor.setDefaultCharWidth(1) editor.setSelectedScreenRange([[3, 10], [3, 15]]) editor.addSelectionBelow() From 9354b865dd9df0c383b9518b52db5db7cbb82b7f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 16:06:33 +0800 Subject: [PATCH 271/316] :arrow_up: electron@0.33.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b89dc162..3505728fa 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "0.30.7", + "electronVersion": "0.33.1", "dependencies": { "async": "0.2.6", "atom-keymap": "^6.1.0", From 70fc6dd524afb83fee61cb3836d189358721fbe2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 12:38:44 +0800 Subject: [PATCH 272/316] registerProtocol has been deprecated --- src/browser/atom-protocol-handler.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/atom-protocol-handler.coffee b/src/browser/atom-protocol-handler.coffee index 0865f3ad8..0fda8095b 100644 --- a/src/browser/atom-protocol-handler.coffee +++ b/src/browser/atom-protocol-handler.coffee @@ -29,7 +29,7 @@ class AtomProtocolHandler # Creates the 'atom' custom protocol handler. registerAtomProtocol: -> - protocol.registerProtocol 'atom', (request) => + protocol.registerFileProtocol 'atom', (request, callback) => relativePath = path.normalize(request.url.substr(7)) if relativePath.indexOf('assets/') is 0 @@ -41,4 +41,4 @@ class AtomProtocolHandler filePath = path.join(loadPath, relativePath) break if fs.statSyncNoException(filePath).isFile?() - new protocol.RequestFileJob(filePath) + callback(filePath) From a5c9fcec2c6c2ee932b740142a2f52648959df59 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 12:39:24 +0800 Subject: [PATCH 273/316] Disable pinch-to-zoom, fixes #8850 --- src/atom-environment.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index f60f2ec97..813d8f531 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -1,5 +1,6 @@ crypto = require 'crypto' path = require 'path' +webFrame = require 'web-frame' _ = require 'underscore-plus' {deprecate} = require 'grim' @@ -188,6 +189,9 @@ class AtomEnvironment extends Model @stylesElement = @styles.buildStylesElement() @document.head.appendChild(@stylesElement) + # Disable pinch-to-zoom. + webFrame.setZoomLevelLimits(1, 1) + @keymaps.subscribeToFileReadFailure() @keymaps.loadBundledKeymaps() From 224f2e973f61c71926fd702da48c444c2f3873e5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 25 Sep 2015 13:55:20 +0200 Subject: [PATCH 274/316] Adhere to `CoffeeScript.compile` contract ...which always returns the source map as a string. This is needed because `Buffer` now requires to be initialized with either a number, a buffer, an array or a string. --- spec/compile-cache-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/compile-cache-spec.coffee b/spec/compile-cache-spec.coffee index 94910bb58..d80e05fc5 100644 --- a/spec/compile-cache-spec.coffee +++ b/spec/compile-cache-spec.coffee @@ -18,7 +18,7 @@ describe 'CompileCache', -> CompileCache.resetCacheStats() spyOn(Babel, 'transform').andReturn {code: 'the-babel-code'} - spyOn(CoffeeScript, 'compile').andReturn {js: 'the-coffee-code', v3SourceMap: {}} + spyOn(CoffeeScript, 'compile').andReturn {js: 'the-coffee-code', v3SourceMap: "{}"} spyOn(TypeScriptSimple::, 'compile').andReturn 'the-typescript-code' spyOn(CSONParser, 'parse').andReturn {the: 'cson-data'} From 23d5dc872654c3bc353d0a3a24d782c30659ebbc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 25 Sep 2015 13:59:00 +0200 Subject: [PATCH 275/316] Change invalid.js fixture for babel transpilation The previous file was considered invalid on the earlier version of electron, but it now compiles correctly because of the updated ES6 support. --- spec/fixtures/babel/invalid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/fixtures/babel/invalid.js b/spec/fixtures/babel/invalid.js index 4af6a59e2..f02fd2fd6 100644 --- a/spec/fixtures/babel/invalid.js +++ b/spec/fixtures/babel/invalid.js @@ -1,3 +1,3 @@ 'use 6to6'; -module.exports = v => v + 1 +module.exports = async function hello() {} From 0f7c85288336e38aa7b82337497758370be1312a Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Sat, 26 Sep 2015 15:42:00 -0400 Subject: [PATCH 276/316] :arrow_up: electron@0.33.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3505728fa..e323e9bdd 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "0.33.1", + "electronVersion": "0.33.3", "dependencies": { "async": "0.2.6", "atom-keymap": "^6.1.0", From 5f2b5a16dfeb340b323896b62d9fcd8e613ac91c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 26 Sep 2015 16:38:51 -0600 Subject: [PATCH 277/316] Use WebContents.prototype.isLoading instead of defunct .loaded Fixes cmd-o interaction. --- src/browser/atom-window.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 3be46b5fc..3cbf277ea 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -88,7 +88,7 @@ class AtomWindow hash: encodeURIComponent(JSON.stringify(loadSettings)) getLoadSettings: -> - if @browserWindow.webContents?.loaded + if @browserWindow.webContents? and not @browserWindow.webContents.isLoading() hash = url.parse(@browserWindow.webContents.getUrl()).hash.substr(1) JSON.parse(decodeURIComponent(hash)) From f0b7356ba0486c5cbbe7420c27ee23550b176444 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Fri, 2 Oct 2015 08:48:37 +0200 Subject: [PATCH 278/316] :arrow_up: electron@0.33.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e323e9bdd..3660dab0d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "0.33.3", + "electronVersion": "0.33.4", "dependencies": { "async": "0.2.6", "atom-keymap": "^6.1.0", From bbf25e7da15e4759341ffad26299639a1cc788ab Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Mon, 5 Oct 2015 07:31:04 +0200 Subject: [PATCH 279/316] :arrow_up: electron@0.33.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3660dab0d..22af172ad 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "0.33.4", + "electronVersion": "0.33.5", "dependencies": { "async": "0.2.6", "atom-keymap": "^6.1.0", From 1bfcea35b615bf59ab96ec267423cffc0d19b081 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 5 Oct 2015 15:19:35 -0400 Subject: [PATCH 280/316] :arrow_up: electron@0.33.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 22af172ad..fb600d215 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "0.33.5", + "electronVersion": "0.33.6", "dependencies": { "async": "0.2.6", "atom-keymap": "^6.1.0", From 661607857fbeceee467d9ce9ce602f9e61eb606d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Oct 2015 18:38:17 -0600 Subject: [PATCH 281/316] Fix spec failures due to slight changes in DOM positioning --- spec/lines-yardstick-spec.coffee | 16 ++++++++-------- spec/text-editor-component-spec.coffee | 12 ++++++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index 1f5a01560..022f535f4 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -76,10 +76,10 @@ describe "LinesYardstick", -> expect(linesYardstick.pixelPositionForScreenPosition([0, 0])).toEqual({left: 0, top: 0}) expect(linesYardstick.pixelPositionForScreenPosition([0, 1])).toEqual({left: 7, top: 0}) - expect(linesYardstick.pixelPositionForScreenPosition([0, 5])).toEqual({left: 37.8046875, top: 0}) - expect(linesYardstick.pixelPositionForScreenPosition([1, 6])).toEqual({left: 43.20703125, top: 14}) - expect(linesYardstick.pixelPositionForScreenPosition([1, 9])).toEqual({left: 72.20703125, top: 14}) - expect(linesYardstick.pixelPositionForScreenPosition([2, Infinity])).toEqual({left: 288.046875, top: 28}) + expect(linesYardstick.pixelPositionForScreenPosition([0, 5])).toEqual({left: 37.78125, top: 0}) + expect(linesYardstick.pixelPositionForScreenPosition([1, 6])).toEqual({left: 43.171875, top: 14}) + expect(linesYardstick.pixelPositionForScreenPosition([1, 9])).toEqual({left: 72.171875, top: 14}) + expect(linesYardstick.pixelPositionForScreenPosition([2, Infinity])).toEqual({left: 287.859375, top: 28}) it "reuses already computed pixel positions unless it is invalidated", -> atom.styles.addStyleSheet """ @@ -105,9 +105,9 @@ describe "LinesYardstick", -> linesYardstick.invalidateCache() - expect(linesYardstick.pixelPositionForScreenPosition([1, 2])).toEqual({left: 24.00390625, top: 14}) - expect(linesYardstick.pixelPositionForScreenPosition([2, 6])).toEqual({left: 72.01171875, top: 28}) - expect(linesYardstick.pixelPositionForScreenPosition([5, 10])).toEqual({left: 120.01171875, top: 70}) + expect(linesYardstick.pixelPositionForScreenPosition([1, 2])).toEqual({left: 24, top: 14}) + expect(linesYardstick.pixelPositionForScreenPosition([2, 6])).toEqual({left: 72, top: 28}) + expect(linesYardstick.pixelPositionForScreenPosition([5, 10])).toEqual({left: 120, top: 70}) it "correctly handles RTL characters", -> atom.styles.addStyleSheet """ @@ -156,7 +156,7 @@ describe "LinesYardstick", -> expect(linesYardstick.screenPositionForPixelPosition({top: 32, left: 24.3})).toEqual([2, 3]) expect(linesYardstick.screenPositionForPixelPosition({top: 46, left: 66.5})).toEqual([3, 9]) expect(linesYardstick.screenPositionForPixelPosition({top: 80, left: 99.9})).toEqual([5, 14]) - expect(linesYardstick.screenPositionForPixelPosition({top: 80, left: 224.4365234375})).toEqual([5, 29]) + expect(linesYardstick.screenPositionForPixelPosition({top: 80, left: 224.2365234375})).toEqual([5, 29]) expect(linesYardstick.screenPositionForPixelPosition({top: 80, left: 225})).toEqual([5, 30]) it "clips pixel positions above buffer start", -> diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index b0f3ace51..91020f299 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -3482,12 +3482,14 @@ describe "TextEditorComponent", -> editor.moveRight() nextAnimationFrame() - right = wrapperNode.pixelPositionForScreenPosition([0, 6]).left + + margin = component.presenter.getHorizontalScrollMarginInPixels() + right = wrapperNode.pixelPositionForScreenPosition([0, 4]).left + margin expect(wrapperNode.getScrollRight()).toBeCloseTo right, 0 editor.moveRight() nextAnimationFrame() - right = wrapperNode.pixelPositionForScreenPosition([0, 7]).left + right = wrapperNode.pixelPositionForScreenPosition([0, 5]).left + margin expect(wrapperNode.getScrollRight()).toBeCloseTo right, 0 it "scrolls left when the last cursor gets closer than ::horizontalScrollMargin to the left of the editor", -> @@ -3499,12 +3501,14 @@ describe "TextEditorComponent", -> editor.moveLeft() nextAnimationFrame() - left = wrapperNode.pixelPositionForScreenPosition([6, 59]).left + + margin = component.presenter.getHorizontalScrollMarginInPixels() + left = wrapperNode.pixelPositionForScreenPosition([6, 61]).left - margin expect(wrapperNode.getScrollLeft()).toBeCloseTo left, 0 editor.moveLeft() nextAnimationFrame() - left = wrapperNode.pixelPositionForScreenPosition([6, 58]).left + left = wrapperNode.pixelPositionForScreenPosition([6, 60]).left - margin expect(wrapperNode.getScrollLeft()).toBeCloseTo left, 0 it "scrolls down when inserting lines makes the document longer than the editor's height", -> From badba2810e2e0ce12b6138ab273b0821c468ca87 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Oct 2015 18:49:16 -0600 Subject: [PATCH 282/316] Add disablePinchToZoom to ApplicationDelegate --- src/application-delegate.coffee | 4 ++++ src/atom-environment.coffee | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index f2b425137..1999c6e83 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -2,6 +2,7 @@ _ = require 'underscore-plus' ipc = require 'ipc' remote = require 'remote' shell = require 'shell' +webFrame = require 'web-frame' {Disposable} = require 'event-kit' {getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' @@ -163,3 +164,6 @@ class ApplicationDelegate openExternal: (url) -> shell.openExternal(url) + + disablePinchToZoom: -> + webFrame.setZoomLevelLimits(1, 1) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 813d8f531..004cfbc80 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -1,6 +1,5 @@ crypto = require 'crypto' path = require 'path' -webFrame = require 'web-frame' _ = require 'underscore-plus' {deprecate} = require 'grim' @@ -189,8 +188,7 @@ class AtomEnvironment extends Model @stylesElement = @styles.buildStylesElement() @document.head.appendChild(@stylesElement) - # Disable pinch-to-zoom. - webFrame.setZoomLevelLimits(1, 1) + @applicationDelegate.disablePinchToZoom() @keymaps.subscribeToFileReadFailure() @keymaps.loadBundledKeymaps() From eb2a6a3388bcaeb536730b520197b3db89aaa34a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 16 Oct 2015 12:21:32 -0600 Subject: [PATCH 283/316] Mock process.cwd to make test pass in headless mode --- spec/module-cache-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/module-cache-spec.coffee b/spec/module-cache-spec.coffee index 5cf6bd2fd..3a995aec7 100644 --- a/spec/module-cache-spec.coffee +++ b/spec/module-cache-spec.coffee @@ -86,6 +86,7 @@ describe 'ModuleCache', -> exports.load = function() { require('underscore-plus'); }; """ + spyOn(process, 'cwd').andReturn('/') # Required when running this test from CLI packageMain = require(indexPath) Module._findPath.reset() expect(-> packageMain.load()).toThrow() From 4093e6d135846a250d8b31216cff94106c69e885 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 16 Oct 2015 12:42:02 -0600 Subject: [PATCH 284/316] :arrow_up: wrap-guide --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fb600d215..d7e05d99d 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "update-package-dependencies": "0.10.0", "welcome": "0.31.0", "whitespace": "0.31.0", - "wrap-guide": "0.38.0", + "wrap-guide": "0.38.1", "language-c": "0.49.0", "language-clojure": "0.18.0", "language-coffee-script": "0.42.0", From cd9e24ea33aba91962d90a51f1055971cb2ea124 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 12:04:35 -0700 Subject: [PATCH 285/316] Don't prevent renderer-side reloads --- src/browser/atom-window.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 3be46b5fc..592ce0c3b 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -146,7 +146,9 @@ class AtomWindow when 0 then @browserWindow.destroy() when 1 then @browserWindow.restart() - @browserWindow.webContents.on 'will-navigate', (event) -> event.preventDefault() + @browserWindow.webContents.on 'will-navigate', (event, url) => + unless url is @browserWindow.webContents.getUrl() + event.preventDefault() @setupContextMenu() From 56d5cea762671db803d8c7fbc2e77217ae06c6e0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 14:20:20 -0700 Subject: [PATCH 286/316] :arrow_up: donna --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index da11dc97a..4c0f460a7 100644 --- a/build/package.json +++ b/build/package.json @@ -8,7 +8,7 @@ "dependencies": { "asar": "^0.8.0", "async": "~0.2.9", - "donna": "^1.0.12", + "donna": "^1.0.13", "formidable": "~1.0.14", "fs-plus": "2.x", "github-releases": "~0.3.0", From e4246fefa3837fd20bf0e32315c3e6405a492233 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 15:42:15 -0700 Subject: [PATCH 287/316] :arrow_up: spellcheck --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7e05d99d..83a70f5c2 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "release-notes": "0.53.0", "settings-view": "0.230.1", "snippets": "0.101.0", - "spell-check": "0.61.0", + "spell-check": "0.61.1", "status-bar": "0.79.0", "styleguide": "0.44.0", "symbols-view": "0.109.0", From 52d0556c6e3e83b0c0873f41218521cdde098a85 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 15:47:32 -0700 Subject: [PATCH 288/316] :arrow_up: line-ending-selector --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 83a70f5c2..dabddef52 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "image-view": "0.55.0", "incompatible-packages": "0.25.0", "keybinding-resolver": "0.33.0", - "line-ending-selector": "0.2.0", + "line-ending-selector": "0.3.0", "link": "0.31.0", "markdown-preview": "0.155.0", "metrics": "0.52.0", From 7d743827820969871e8724e6f353887a3ddfc105 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 16:18:40 -0700 Subject: [PATCH 289/316] Fix extra child node removal in PanelContainerElement --- src/panel-container-element.coffee | 4 ---- src/panel-element.coffee | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/panel-container-element.coffee b/src/panel-container-element.coffee index 40ce7e352..b66a0cd90 100644 --- a/src/panel-container-element.coffee +++ b/src/panel-container-element.coffee @@ -8,7 +8,6 @@ class PanelContainerElement extends HTMLElement throw new Error("Must pass a views parameter when initializing PanelContainerElements") unless @views? @subscriptions.add @model.onDidAddPanel(@panelAdded.bind(this)) - @subscriptions.add @model.onDidRemovePanel(@panelRemoved.bind(this)) @subscriptions.add @model.onDidDestroy(@destroyed.bind(this)) @classList.add(@model.getLocation()) this @@ -34,9 +33,6 @@ class PanelContainerElement extends HTMLElement @subscriptions.add panel.onDidChangeVisible (visible) => @hideAllPanelsExcept(panel) if visible - panelRemoved: ({panel, index}) -> - @removeChild(@views.getView(panel)) - destroyed: -> @subscriptions.dispose() @parentNode?.removeChild(this) diff --git a/src/panel-element.coffee b/src/panel-element.coffee index 8d6aadae4..72fd6ebf2 100644 --- a/src/panel-element.coffee +++ b/src/panel-element.coffee @@ -32,6 +32,6 @@ class PanelElement extends HTMLElement destroyed: -> @subscriptions.dispose() - @parentNode?.removeChild(this) + @remove() module.exports = PanelElement = document.registerElement 'atom-panel', prototype: PanelElement.prototype From c36b4bd16930f0c6b639ab0d38b93c95d73a922c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 14:56:36 -0700 Subject: [PATCH 290/316] Make Error.prepareStackTrace read-only (again) This time, we've provided a way for Grim to access an Error's raw stack trace array --- package.json | 2 +- src/compile-cache.js | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index dabddef52..a615ac151 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "fstream": "0.1.24", "fuzzaldrin": "^2.1", "git-utils": "^4", - "grim": "1.4.2", + "grim": "1.5.0", "jasmine-json": "~0.0", "jasmine-tagged": "^1.1.4", "jquery": "^2.1.1", diff --git a/src/compile-cache.js b/src/compile-cache.js index e10bf6803..d3eafc2c6 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -158,6 +158,27 @@ require('source-map-support').install({ } }) +var sourceMapPrepareStackTrace = Error.prepareStackTrace +var prepareStackTrace = sourceMapPrepareStackTrace + +// Prevent coffee-script from reassigning Error.prepareStackTrace +Object.defineProperty(Error, 'prepareStackTrace', { + get: function () { return prepareStackTrace }, + set: function (newValue) {} +}) + +// Enable Grim to access the raw stack without reassigning Error.prepareStackTrace +Error.prototype.getRawStack = function () { + prepareStackTrace = getRawStack + var result = this.stack + prepareStackTrace = sourceMapPrepareStackTrace + return result +} + +function getRawStack (error, stack) { + return stack +} + Object.keys(COMPILERS).forEach(function (extension) { var compiler = COMPILERS[extension] From f31328baec58998d7f168cbd348b61241e1288a5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 15:27:37 -0700 Subject: [PATCH 291/316] Disable linter warning for Error prototype method --- src/compile-cache.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compile-cache.js b/src/compile-cache.js index d3eafc2c6..f7726b4b3 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -168,14 +168,14 @@ Object.defineProperty(Error, 'prepareStackTrace', { }) // Enable Grim to access the raw stack without reassigning Error.prepareStackTrace -Error.prototype.getRawStack = function () { +Error.prototype.getRawStack = function () { // eslint-disable-line no-extend-native prepareStackTrace = getRawStack var result = this.stack prepareStackTrace = sourceMapPrepareStackTrace return result } -function getRawStack (error, stack) { +function getRawStack (_, stack) { return stack } From 82103f9da00933476055f1f665d6fd08d93e7b2a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 16 Oct 2015 16:49:24 -0700 Subject: [PATCH 292/316] Remove unused spec-helper requires --- spec/spec-helper.coffee | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 9a2ef83ce..f31c67298 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -1,6 +1,5 @@ -require '../src/window' - require 'jasmine-json' +require '../src/window' require '../vendor/jasmine-jquery' path = require 'path' _ = require 'underscore-plus' @@ -9,12 +8,9 @@ Grim = require 'grim' pathwatcher = require 'pathwatcher' FindParentDir = require 'find-parent-dir' -{Point} = require 'text-buffer' -Workspace = require '../src/workspace' TextEditor = require '../src/text-editor' TextEditorElement = require '../src/text-editor-element' TokenizedBuffer = require '../src/tokenized-buffer' -TextEditorComponent = require '../src/text-editor-component' clipboard = require '../src/safe-clipboard' jasmineStyle = document.createElement('style') From 1c0420b3bbfb245bb88ec55219365642e289c329 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Fri, 16 Oct 2015 19:57:40 -0400 Subject: [PATCH 293/316] :fire: subpixel-font-scaling This option was removed in Electron v0.33.9 --- src/browser/atom-window.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 16456d274..4a402f5da 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -28,7 +28,6 @@ class AtomWindow title: 'Atom' 'web-preferences': 'direct-write': true - 'subpixel-font-scaling': true if @isSpec options['web-preferences']['page-visibility'] = true From 6495f1a5314320cbc6d9a5936aab24e507e2d21d Mon Sep 17 00:00:00 2001 From: Wliu Date: Fri, 16 Oct 2015 19:58:47 -0400 Subject: [PATCH 294/316] Revert ":fire: subpixel-font-scaling" This reverts commit 1c0420b3bbfb245bb88ec55219365642e289c329. --- src/browser/atom-window.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 4a402f5da..16456d274 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -28,6 +28,7 @@ class AtomWindow title: 'Atom' 'web-preferences': 'direct-write': true + 'subpixel-font-scaling': true if @isSpec options['web-preferences']['page-visibility'] = true From 306729f20cc04fae3a73d65885c474278288ff42 Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Sat, 17 Oct 2015 16:53:25 +0200 Subject: [PATCH 295/316] :bug: Use fat arrow to capture correct scope Fixes #9186 --- src/command-installer.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command-installer.coffee b/src/command-installer.coffee index 3d366037c..5a6a7f94e 100644 --- a/src/command-installer.coffee +++ b/src/command-installer.coffee @@ -44,7 +44,7 @@ class CommandInstaller if error? showErrorDialog(error) else - @installApmCommand true, (error) -> + @installApmCommand true, (error) => if error? showErrorDialog(error) else From 2cb77aa4b95e00bf5cc05c7c759cffa771d6a8ee Mon Sep 17 00:00:00 2001 From: Thomas Johansen Date: Sat, 17 Oct 2015 16:54:29 +0200 Subject: [PATCH 296/316] :bug: Use fat arrow to capture correct scope Fixes #9187 --- src/window-event-handler.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index bff5ee5b7..dbb3be463 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -174,7 +174,7 @@ class WindowEventHandler detail = "To toggle, press the Alt key or execute the window:toggle-menu-bar command" @atomEnvironment.notifications.addInfo('Menu bar hidden', {detail}) - handleLinkClick: (event) -> + handleLinkClick: (event) => event.preventDefault() uri = event.currentTarget?.getAttribute('href') if uri and uri[0] isnt '#' and /^https?:\/\//.test(uri) From abee4c1db410834aa790e99e8e4f3c84e85171b3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 17 Oct 2015 10:39:26 -0600 Subject: [PATCH 297/316] Default devMode to true ASAP if running Atom in test mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, we ran the window in devMode, but didn’t set devMode to true early enough to compute the correct resource path. This caused errors when attempting to load the bundled keymaps when running atom —test without the —dev flag. --- src/browser/atom-application.coffee | 5 ++--- src/browser/main.coffee | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index b8e3e7bc2..ab7a45db9 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -91,7 +91,7 @@ class AtomApplication openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout}) -> if test - @runTests({headless: true, @resourcePath, executedFrom, pathsToOpen, logFile, timeout}) + @runTests({headless: true, devMode, @resourcePath, executedFrom, pathsToOpen, logFile, timeout}) else if pathsToOpen.length > 0 @openPaths({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup}) else if urlsToOpen.length > 0 @@ -494,7 +494,7 @@ class AtomApplication # :specPath - The directory to load specs from. # :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages # and ~/.atom/dev/packages, defaults to false. - runTests: ({headless, resourcePath, executedFrom, pathsToOpen, logFile, safeMode, timeout}) -> + runTests: ({headless, devMode, resourcePath, executedFrom, pathsToOpen, logFile, safeMode, timeout}) -> if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath) resourcePath = @resourcePath @@ -522,7 +522,6 @@ class AtomApplication legacyTestRunnerPath = @resolveLegacyTestRunnerPath() testRunnerPath = @resolveTestRunnerPath(testPaths[0]) isSpec = true - devMode = true safeMode ?= false new AtomWindow({windowInitializationScript, resourcePath, headless, isSpec, devMode, testRunnerPath, legacyTestRunnerPath, testPaths, logFile, safeMode}) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 6a141cf1a..990002671 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -133,6 +133,8 @@ parseCommandLine = -> if args['resource-path'] devMode = true resourcePath = args['resource-path'] + + devMode = true if test resourcePath ?= devResourcePath if devMode unless fs.statSyncNoException(resourcePath) From c35411cd29a047db92a9974bc3d972cd3d654fbb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 17 Oct 2015 10:52:39 -0600 Subject: [PATCH 298/316] :art: --- src/initialize-test-window.coffee | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index ad15429ff..ecacddd4e 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -13,9 +13,11 @@ try AtomEnvironment = require '../src/atom-environment' ApplicationDelegate = require '../src/application-delegate' + {testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings() + # Show window synchronously so a focusout doesn't fire on input elements # that are focused in the very first spec run. - remote.getCurrentWindow().show() unless getWindowLoadSettings().headless + remote.getCurrentWindow().show() unless headless handleKeydown = (event) -> # Reload: cmd-r / ctrl-r @@ -39,15 +41,13 @@ try document.title = "Spec Suite" - legacyTestRunner = require(getWindowLoadSettings().legacyTestRunnerPath) - testRunner = require(getWindowLoadSettings().testRunnerPath) + testRunner = require(testRunnerPath) + legacyTestRunner = require(legacyTestRunnerPath) + buildAtomEnvironment = (params) -> new AtomEnvironment(params) + buildDefaultApplicationDelegate = (params) -> new ApplicationDelegate() + promise = testRunner({ - logFile: getWindowLoadSettings().logFile - headless: getWindowLoadSettings().headless - testPaths: getWindowLoadSettings().testPaths - buildAtomEnvironment: (params) -> new AtomEnvironment(params) - buildDefaultApplicationDelegate: (params) -> new ApplicationDelegate() - legacyTestRunner: legacyTestRunner + logFile, headless, testPaths, buildAtomEnvironment, buildDefaultApplicationDelegate, legacyTestRunner }) promise.then(exitWithStatusCode) if getWindowLoadSettings().headless From 979b08f5fe18ce0a764c4037f5633ea552d94854 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 17 Oct 2015 10:55:23 -0600 Subject: [PATCH 299/316] Override console.log/error/warn in headless mode to log to stdout/stderr --- src/initialize-test-window.coffee | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index ecacddd4e..27ef46acc 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -15,9 +15,19 @@ try {testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings() - # Show window synchronously so a focusout doesn't fire on input elements - # that are focused in the very first spec run. - remote.getCurrentWindow().show() unless headless + if headless + # Override logging in headless mode so it goes to the console, regardless + # of the --enable-logging flag to Electron. + console.log = (args...) -> + ipc.send 'write-to-stdout', args.join(' ') + '\n' + console.warn = (args...) -> + ipc.send 'write-to-stderr', args.join(' ') + '\n' + console.error = (args...) -> + ipc.send 'write-to-stderr', args.join(' ') + '\n' + else + # Show window synchronously so a focusout doesn't fire on input elements + # that are focused in the very first spec run. + remote.getCurrentWindow().show() handleKeydown = (event) -> # Reload: cmd-r / ctrl-r From 2603a3f611471b814cb9eca0233ab4b1248781ab Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Sun, 18 Oct 2015 15:13:27 -0400 Subject: [PATCH 300/316] :arrow_up: notifications@0.60.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a615ac151..3764782c6 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "link": "0.31.0", "markdown-preview": "0.155.0", "metrics": "0.52.0", - "notifications": "0.59.0", + "notifications": "0.60.0", "open-on-github": "0.38.0", "package-generator": "0.40.0", "release-notes": "0.53.0", From f916aa068204510cd8a82e7ae5d9300e745a0f44 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 19 Oct 2015 14:48:36 -0600 Subject: [PATCH 301/316] :arrow_up: language-php --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3764782c6..d07184ed5 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "language-mustache": "0.13.0", "language-objective-c": "0.15.0", "language-perl": "0.30.0", - "language-php": "0.31.0", + "language-php": "0.32.0", "language-property-list": "0.8.0", "language-python": "0.40.0", "language-ruby": "0.60.0", From 1593cdbf7aac25f4198abe67ccfca7850fd6a752 Mon Sep 17 00:00:00 2001 From: Wliu Date: Mon, 19 Oct 2015 18:19:43 -0400 Subject: [PATCH 302/316] :bug: Fix toggle-menu-bar command --- src/window-event-handler.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index dbb3be463..c786f7e9c 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -30,7 +30,7 @@ class WindowEventHandler if process.platform in ['win32', 'linux'] @subscriptions.add @atomEnvironment.commands.add @window, - '@window:toggle-menu-bar': @handleWindowToggleMenuBar + 'window:toggle-menu-bar': @handleWindowToggleMenuBar @subscriptions.add @atomEnvironment.commands.add @document, 'core:focus-next': @handleFocusNext From 7d7687bab3b05a7ac3782c32f04d2df34fc6aa41 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 19 Oct 2015 20:03:25 -0400 Subject: [PATCH 303/316] :arrow_up: language-python@0.41.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d07184ed5..c6d7b3701 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "language-perl": "0.30.0", "language-php": "0.32.0", "language-property-list": "0.8.0", - "language-python": "0.40.0", + "language-python": "0.41.0", "language-ruby": "0.60.0", "language-ruby-on-rails": "0.23.0", "language-sass": "0.42.0", From dc76115454420b58e8aec6d0c063ca5c11ca9220 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 19 Oct 2015 20:03:49 -0400 Subject: [PATCH 304/316] :arrow_up: language-less@0.28.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c6d7b3701..3d8ecbe0b 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "language-java": "0.16.0", "language-javascript": "0.97.0", "language-json": "0.17.0", - "language-less": "0.28.2", + "language-less": "0.28.3", "language-make": "0.19.0", "language-mustache": "0.13.0", "language-objective-c": "0.15.0", From 401bc9834078fe53056ec4f09bb85193c2d6fa0a Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 19 Oct 2015 20:04:14 -0400 Subject: [PATCH 305/316] :arrow_up: language-xml@0.33.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d8ecbe0b..757a66772 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "language-text": "0.7.0", "language-todo": "0.27.0", "language-toml": "0.16.0", - "language-xml": "0.33.0", + "language-xml": "0.33.1", "language-yaml": "0.24.0" }, "private": true, From c162eb892db392d28ada43e180999ea85ffda4ca Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 19 Oct 2015 20:04:38 -0400 Subject: [PATCH 306/316] :arrow_up: language-json@0.17.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 757a66772..e5f8f8b38 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "language-hyperlink": "0.14.0", "language-java": "0.16.0", "language-javascript": "0.97.0", - "language-json": "0.17.0", + "language-json": "0.17.1", "language-less": "0.28.3", "language-make": "0.19.0", "language-mustache": "0.13.0", From ec9d1231aa8e2400cc7205e6a5aee37cc9a7f2a3 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 19 Oct 2015 18:16:04 -0700 Subject: [PATCH 307/316] :arrow_up: metrics@0.53.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e5f8f8b38..c4ca986e7 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "line-ending-selector": "0.3.0", "link": "0.31.0", "markdown-preview": "0.155.0", - "metrics": "0.52.0", + "metrics": "0.53.0", "notifications": "0.60.0", "open-on-github": "0.38.0", "package-generator": "0.40.0", From 40e3b08a8cecad654e88d13da20cdce59ec7cd2a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 20 Oct 2015 08:36:27 +0200 Subject: [PATCH 308/316] Add TextEditorElement::getMaxScrollTop --- spec/text-editor-element-spec.coffee | 21 +++++++++++++++++++++ src/text-editor-component.coffee | 3 +++ src/text-editor-element.coffee | 6 ++++++ src/text-editor-presenter.coffee | 7 +++++++ 4 files changed, 37 insertions(+) diff --git a/spec/text-editor-element-spec.coffee b/spec/text-editor-element-spec.coffee index e7d5831eb..c60a9762f 100644 --- a/spec/text-editor-element-spec.coffee +++ b/spec/text-editor-element-spec.coffee @@ -236,6 +236,27 @@ describe "TextEditorElement", -> jasmine.attachToDOM(element) expect(element.getDefaultCharacterWidth()).toBeGreaterThan(0) + describe "::getMaxScrollTop", -> + it "returns the maximum scroll top that can be applied to the element", -> + editor = atom.workspace.buildTextEditor() + editor.setText('1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16') + element = atom.views.getView(editor) + element.style.lineHeight = "10px" + element.style.width = "200px" + + expect(element.getMaxScrollTop()).toBe(0) + + jasmine.attachToDOM(element) + + element.setHeight(100) + expect(element.getMaxScrollTop()).toBe(60) + + element.setHeight(120) + expect(element.getMaxScrollTop()).toBe(40) + + element.setHeight(200) + expect(element.getMaxScrollTop()).toBe(0) + describe "on TextEditor::setMini", -> it "changes the element's 'mini' attribute", -> element = new TextEditorElement diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 8a6d885c2..d72c50382 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -421,6 +421,9 @@ class TextEditorComponent getScrollWidth: -> @presenter.getScrollWidth() + getMaxScrollTop: -> + @presenter.getMaxScrollTop() + getVerticalScrollbarWidth: -> @presenter.getVerticalScrollbarWidth() diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index 9fe0e9091..55e23d2da 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -210,6 +210,12 @@ class TextEditorElement extends HTMLElement getDefaultCharacterWidth: -> @getModel().getDefaultCharWidth() + # Extended: Get the maximum scroll top that can be applied to this element. + # + # Returns a {Number} of pixels. + getMaxScrollTop: -> + @component?.getMaxScrollTop() + # Extended: Converts a buffer position to a pixel position. # # * `bufferPosition` An object that represents a buffer position. It can be either diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index f416f171c..2e1d73c56 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -982,6 +982,13 @@ class TextEditorPresenter getScrollWidth: -> @scrollWidth + getMaxScrollTop: -> + scrollHeight = @getScrollHeight() + clientHeight = @getClientHeight() + return 0 unless scrollHeight? and clientHeight? + + scrollHeight - clientHeight + setHorizontalScrollbarHeight: (horizontalScrollbarHeight) -> unless @measuredHorizontalScrollbarHeight is horizontalScrollbarHeight oldHorizontalScrollbarHeight = @measuredHorizontalScrollbarHeight From 5fc521fedc8116613b9e25e14a6d3c05b378af4c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 20 Oct 2015 08:37:15 +0200 Subject: [PATCH 309/316] Add deprecated method to TextEditor --- src/text-editor.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 4c6a0f514..30d5694c4 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -3103,6 +3103,11 @@ class TextEditor extends Model @viewRegistry.getView(this).getScrollWidth() + getMaxScrollTop: -> + Grim.deprecate("This is now a view method. Call TextEditorElement::getMaxScrollTop instead.") + + @viewRegistry.getView(this).getMaxScrollTop() + getVisibleRowRange: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getVisibleRowRange instead.") From 8dd7841204c0c425b88b66fca6c8aaf2b3744280 Mon Sep 17 00:00:00 2001 From: simurai Date: Tue, 20 Oct 2015 22:46:58 +0900 Subject: [PATCH 310/316] :arrow_up: solarized-dark-syntax@v0.39.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4ca986e7..ac343f75f 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "one-dark-syntax": "1.1.1", "one-light-syntax": "1.1.1", "one-light-ui": "1.1.5", - "solarized-dark-syntax": "0.38.1", + "solarized-dark-syntax": "0.39.0", "solarized-light-syntax": "0.22.1", "about": "1.1.0", "archive-view": "0.61.0", From 7ae249baf79d1d4ed72e11d9456b2ed2af67e2d0 Mon Sep 17 00:00:00 2001 From: simurai Date: Tue, 20 Oct 2015 22:47:55 +0900 Subject: [PATCH 311/316] :arrow_up: solarized-light-syntax@v0.23.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac343f75f..4dde16c10 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "one-light-syntax": "1.1.1", "one-light-ui": "1.1.5", "solarized-dark-syntax": "0.39.0", - "solarized-light-syntax": "0.22.1", + "solarized-light-syntax": "0.23.0", "about": "1.1.0", "archive-view": "0.61.0", "autocomplete-atom-api": "0.9.2", From 8321c9f52ee8f05e128a7a8c3af89bd0b341eb7a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 Oct 2015 09:16:14 -0600 Subject: [PATCH 312/316] :arrow_up: status-bar --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4dde16c10..3ee8d4b56 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "settings-view": "0.230.1", "snippets": "0.101.0", "spell-check": "0.61.1", - "status-bar": "0.79.0", + "status-bar": "0.80.0", "styleguide": "0.44.0", "symbols-view": "0.109.0", "tabs": "0.85.0", From b203a4ee33eebd815d33bce592dfa3159fa361b7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 Oct 2015 13:32:21 -0600 Subject: [PATCH 313/316] :arrow_up: apm --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 3f366d857..e41f77af0 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.1.1" + "atom-package-manager": "1.3.0" } } From 11796977dbc909291b1fdc33b74e42a19bb9e6f0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 Oct 2015 19:51:46 -0600 Subject: [PATCH 314/316] :arrow_up: apm --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index e41f77af0..2a2e26db0 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.3.0" + "atom-package-manager": "1.4.0" } } From 33839d1f0e464ee136e12e67d5488d25cd1bc097 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 Oct 2015 19:48:17 -0600 Subject: [PATCH 315/316] Pass current options to loadState --- src/browser/atom-application.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index ab7a45db9..1ca403e98 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -87,7 +87,7 @@ class AtomApplication if options.pathsToOpen?.length > 0 or options.urlsToOpen?.length > 0 or options.test @openWithOptions(options) else - @loadState() or @openPath(options) + @loadState(options) or @openPath(options) openWithOptions: ({pathsToOpen, executedFrom, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, logFile, profileStartup, timeout}) -> if test @@ -441,15 +441,15 @@ class AtomApplication if states.length > 0 or allowEmpty @storageFolder.store('application.json', states) - loadState: -> + loadState: (options) -> if (states = @storageFolder.load('application.json'))?.length > 0 for state in states - @openWithOptions({ + @openWithOptions(_.extend(options, { pathsToOpen: state.initialPaths urlsToOpen: [] devMode: @devMode safeMode: @safeMode - }) + })) true else false From 74d06a85f82ab6404cebc302bd9a99ffc8466a15 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Tue, 20 Oct 2015 22:13:04 -0400 Subject: [PATCH 316/316] :arrow_up: language-sql@0.18.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ee8d4b56..8264a8472 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "language-sass": "0.42.0", "language-shellscript": "0.19.0", "language-source": "0.9.0", - "language-sql": "0.17.0", + "language-sql": "0.18.0", "language-text": "0.7.0", "language-todo": "0.27.0", "language-toml": "0.16.0",