mirror of
https://github.com/atom/atom.git
synced 2026-01-25 14:59:03 -05:00
Merge branch 'master' into dh-async-repo
This commit is contained in:
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "1.4.0"
|
||||
"atom-package-manager": "1.4.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ module.exports = (grunt) ->
|
||||
loadingGif: path.resolve(__dirname, '..', 'resources', 'win', 'loading.gif')
|
||||
iconUrl: "https://raw.githubusercontent.com/atom/atom/master/resources/app-icons/#{channel}/atom.ico"
|
||||
setupIcon: path.resolve(__dirname, '..', 'resources', 'app-icons', channel, 'atom.ico')
|
||||
remoteReleases: 'https://atom.io/api/updates'
|
||||
remoteReleases: "https://atom.io/api/updates?version=#{metadata.version}"
|
||||
|
||||
shell:
|
||||
'kill-atom':
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"grunt-peg": "~1.1.0",
|
||||
"grunt-shell": "~0.3.1",
|
||||
"grunt-standard": "^1.0.2",
|
||||
"legal-eagle": "~0.11.0",
|
||||
"legal-eagle": "~0.12.0",
|
||||
"minidump": "~0.9",
|
||||
"npm": "2.13.3",
|
||||
"rcedit": "~0.3.0",
|
||||
|
||||
29
package.json
29
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "1.2.0-dev",
|
||||
"version": "1.3.0-dev",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -18,6 +18,7 @@
|
||||
"atom-keymap": "^6.1.0",
|
||||
"babel-core": "^5.8.21",
|
||||
"bootstrap": "^3.3.4",
|
||||
"cached-run-in-this-context": "0.4.0",
|
||||
"clear-cut": "^2.0.1",
|
||||
"coffee-script": "1.8.0",
|
||||
"color": "^0.7.3",
|
||||
@@ -86,12 +87,12 @@
|
||||
"background-tips": "0.26.0",
|
||||
"bookmarks": "0.38.0",
|
||||
"bracket-matcher": "0.79.0",
|
||||
"command-palette": "0.36.0",
|
||||
"command-palette": "0.37.0",
|
||||
"deprecation-cop": "0.54.0",
|
||||
"dev-live-reload": "0.47.0",
|
||||
"encoding-selector": "0.21.0",
|
||||
"exception-reporting": "0.37.0",
|
||||
"find-and-replace": "0.189.0",
|
||||
"find-and-replace": "0.190.0",
|
||||
"fuzzy-finder": "0.93.0",
|
||||
"git-diff": "0.57.0",
|
||||
"go-to-line": "0.30.0",
|
||||
@@ -113,9 +114,9 @@
|
||||
"status-bar": "0.80.0",
|
||||
"styleguide": "0.45.0",
|
||||
"symbols-view": "0.110.0",
|
||||
"tabs": "0.87.0",
|
||||
"tabs": "0.88.0",
|
||||
"timecop": "0.33.0",
|
||||
"tree-view": "0.194.0",
|
||||
"tree-view": "0.196.0",
|
||||
"update-package-dependencies": "0.10.0",
|
||||
"welcome": "0.32.0",
|
||||
"whitespace": "0.32.0",
|
||||
@@ -124,14 +125,14 @@
|
||||
"language-clojure": "0.18.0",
|
||||
"language-coffee-script": "0.43.0",
|
||||
"language-csharp": "0.11.0",
|
||||
"language-css": "0.34.0",
|
||||
"language-css": "0.35.0",
|
||||
"language-gfm": "0.81.0",
|
||||
"language-git": "0.10.0",
|
||||
"language-go": "0.39.0",
|
||||
"language-go": "0.40.0",
|
||||
"language-html": "0.42.0",
|
||||
"language-hyperlink": "0.15.0",
|
||||
"language-java": "0.16.0",
|
||||
"language-javascript": "0.97.0",
|
||||
"language-java": "0.16.1",
|
||||
"language-javascript": "0.98.0",
|
||||
"language-json": "0.17.1",
|
||||
"language-less": "0.28.3",
|
||||
"language-make": "0.19.0",
|
||||
@@ -142,15 +143,15 @@
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.41.0",
|
||||
"language-ruby": "0.60.0",
|
||||
"language-ruby-on-rails": "0.23.0",
|
||||
"language-sass": "0.42.0",
|
||||
"language-shellscript": "0.19.0",
|
||||
"language-ruby-on-rails": "0.24.0",
|
||||
"language-sass": "0.42.1",
|
||||
"language-shellscript": "0.20.0",
|
||||
"language-source": "0.9.0",
|
||||
"language-sql": "0.18.0",
|
||||
"language-sql": "0.19.0",
|
||||
"language-text": "0.7.0",
|
||||
"language-todo": "0.27.0",
|
||||
"language-toml": "0.16.0",
|
||||
"language-xml": "0.33.1",
|
||||
"language-xml": "0.34.0",
|
||||
"language-yaml": "0.24.0"
|
||||
},
|
||||
"private": true,
|
||||
|
||||
@@ -8,18 +8,22 @@ var semver = require('semver')
|
||||
series([
|
||||
section('Preparing to roll the railcars'),
|
||||
checkCleanWorkingTree,
|
||||
run('git fetch origin master:master beta:beta stable:stable'),
|
||||
run('git checkout master'),
|
||||
run('git pull --ff-only origin master'),
|
||||
run('git fetch origin beta:beta stable:stable'),
|
||||
run('git fetch origin --tags'),
|
||||
|
||||
section('Checking that merges will be fast-forwards'),
|
||||
run('git branch --contains beta | grep master'),
|
||||
run('git branch --contains stable | grep beta'),
|
||||
|
||||
section('Updating stable branch'),
|
||||
run('git checkout stable'),
|
||||
run('git merge --ff-only origin/stable'),
|
||||
run('git merge --ff-only origin/beta'),
|
||||
bumpStableVersion,
|
||||
|
||||
section('Updating beta branch'),
|
||||
run('git checkout beta'),
|
||||
run('git merge --ff-only origin/beta'),
|
||||
run('git merge --ff-only origin/master'),
|
||||
run('git merge --strategy ours origin/stable'),
|
||||
bumpBetaVersion,
|
||||
@@ -44,11 +48,12 @@ function checkCleanWorkingTree (next) {
|
||||
}
|
||||
|
||||
function bumpStableVersion (next) {
|
||||
run('npm version patch')(next)
|
||||
var newVersion = getCurrentVersion().replace(/-beta.*$/, '')
|
||||
run('npm version ' + newVersion)(next)
|
||||
}
|
||||
|
||||
function bumpBetaVersion (next) {
|
||||
var newVersion = semver.inc(getCurrentVersion(), 'preminor', 'beta')
|
||||
var newVersion = getCurrentVersion().replace(/-dev$/, '-beta0')
|
||||
run('npm version ' + newVersion)(next)
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,17 @@ describe "AtomEnvironment", ->
|
||||
expect(atom.project.getPaths()).toEqual(initialPaths)
|
||||
|
||||
describe "::unloadEditorWindow()", ->
|
||||
it "saves the BlobStore so it can be loaded after reload", ->
|
||||
configDirPath = temp.mkdirSync()
|
||||
fakeBlobStore = jasmine.createSpyObj("blob store", ["save"])
|
||||
atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, enablePersistence: true, configDirPath, blobStore: fakeBlobStore, window, document})
|
||||
|
||||
atomEnvironment.unloadEditorWindow()
|
||||
|
||||
expect(fakeBlobStore.save).toHaveBeenCalled()
|
||||
|
||||
atomEnvironment.destroy()
|
||||
|
||||
it "saves the serialized state of the window so it can be deserialized after reload", ->
|
||||
atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window, document})
|
||||
spyOn(atomEnvironment, 'saveStateSync')
|
||||
|
||||
68
spec/atom-portable-spec.coffee
Normal file
68
spec/atom-portable-spec.coffee
Normal file
@@ -0,0 +1,68 @@
|
||||
path = require "path"
|
||||
fs = require 'fs-plus'
|
||||
temp = require "temp"
|
||||
AtomPortable = require "../src/browser/atom-portable"
|
||||
|
||||
portableModeCommonPlatformBehavior = (platform) ->
|
||||
describe "with ATOM_HOME environment variable", ->
|
||||
it "returns false", ->
|
||||
expect(AtomPortable.isPortableInstall(platform, "C:\\some\\path")).toBe false
|
||||
|
||||
describe "without ATOM_HOME environment variable", ->
|
||||
environmentAtomHome = undefined
|
||||
portableAtomHomePath = path.join(path.dirname(process.execPath), "..", ".atom")
|
||||
portableAtomHomeNaturallyExists = fs.existsSync(portableAtomHomePath)
|
||||
portableAtomHomeBackupPath = "#{portableAtomHomePath}.temp"
|
||||
|
||||
beforeEach ->
|
||||
fs.renameSync(portableAtomHomePath, portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomePath)
|
||||
|
||||
afterEach ->
|
||||
if portableAtomHomeNaturallyExists
|
||||
fs.renameSync(portableAtomHomeBackupPath, portableAtomHomePath) if not fs.existsSync(portableAtomHomePath)
|
||||
else
|
||||
fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath)
|
||||
fs.removeSync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath)
|
||||
|
||||
describe "with .atom directory sibling to exec", ->
|
||||
beforeEach ->
|
||||
fs.mkdirSync(portableAtomHomePath) if not fs.existsSync(portableAtomHomePath)
|
||||
|
||||
describe "without .atom directory sibling to exec", ->
|
||||
beforeEach ->
|
||||
fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath)
|
||||
|
||||
it "returns false", ->
|
||||
expect(AtomPortable.isPortableInstall(platform, environmentAtomHome)).toBe false
|
||||
|
||||
describe "Set Portable Mode on #win32", ->
|
||||
portableAtomHomePath = path.join(path.dirname(process.execPath), "..", ".atom")
|
||||
portableAtomHomeNaturallyExists = fs.existsSync(portableAtomHomePath)
|
||||
portableAtomHomeBackupPath = "#{portableAtomHomePath}.temp"
|
||||
|
||||
beforeEach ->
|
||||
fs.renameSync(portableAtomHomePath, portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomePath)
|
||||
|
||||
afterEach ->
|
||||
if portableAtomHomeNaturallyExists
|
||||
fs.renameSync(portableAtomHomeBackupPath, portableAtomHomePath) if not fs.existsSync(portableAtomHomePath)
|
||||
else
|
||||
fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath)
|
||||
fs.removeSync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath)
|
||||
|
||||
it "creates a portable home directory", ->
|
||||
expect(fs.existsSync(portableAtomHomePath)).toBe false
|
||||
|
||||
AtomPortable.setPortable(process.env.ATOM_HOME)
|
||||
expect(fs.existsSync(portableAtomHomePath)).toBe true
|
||||
|
||||
describe "Check for Portable Mode", ->
|
||||
describe "Windows", ->
|
||||
portableModeCommonPlatformBehavior "win32"
|
||||
|
||||
describe "Mac", ->
|
||||
it "returns false", ->
|
||||
expect(AtomPortable.isPortableInstall("darwin", "darwin")).toBe false
|
||||
|
||||
describe "Linux", ->
|
||||
portableModeCommonPlatformBehavior "linux"
|
||||
69
spec/file-system-blob-store-spec.coffee
Normal file
69
spec/file-system-blob-store-spec.coffee
Normal file
@@ -0,0 +1,69 @@
|
||||
temp = require 'temp'
|
||||
FileSystemBlobStore = require '../src/file-system-blob-store'
|
||||
|
||||
describe "FileSystemBlobStore", ->
|
||||
[storageDirectory, blobStore] = []
|
||||
|
||||
beforeEach ->
|
||||
storageDirectory = temp.path()
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
it "is empty when the file doesn't exist", ->
|
||||
expect(blobStore.get("foo")).toBeUndefined()
|
||||
expect(blobStore.get("bar")).toBeUndefined()
|
||||
|
||||
it "allows to read and write buffers from/to memory without persisting them", ->
|
||||
blobStore.set("foo", new Buffer("foo"))
|
||||
blobStore.set("bar", new Buffer("bar"))
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(blobStore.get("bar")).toEqual(new Buffer("bar"))
|
||||
|
||||
it "persists buffers when saved and retrieves them on load, giving priority to in-memory ones", ->
|
||||
blobStore.set("foo", new Buffer("foo"))
|
||||
blobStore.set("bar", new Buffer("bar"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(blobStore.get("bar")).toEqual(new Buffer("bar"))
|
||||
|
||||
blobStore.set("foo", new Buffer("changed"))
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("changed"))
|
||||
|
||||
it "persists both in-memory and previously stored buffers when saved", ->
|
||||
blobStore.set("foo", new Buffer("foo"))
|
||||
blobStore.set("bar", new Buffer("bar"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
blobStore.set("bar", new Buffer("changed"))
|
||||
blobStore.set("qux", new Buffer("qux"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(blobStore.get("bar")).toEqual(new Buffer("changed"))
|
||||
expect(blobStore.get("qux")).toEqual(new Buffer("qux"))
|
||||
|
||||
it "allows to delete keys from both memory and stored buffers", ->
|
||||
blobStore.set("a", new Buffer("a"))
|
||||
blobStore.set("b", new Buffer("b"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
blobStore.set("b", new Buffer("b"))
|
||||
blobStore.set("c", new Buffer("c"))
|
||||
blobStore.delete("b")
|
||||
blobStore.delete("c")
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
expect(blobStore.get("a")).toEqual(new Buffer("a"))
|
||||
expect(blobStore.get("b")).toBeUndefined()
|
||||
expect(blobStore.get("c")).toBeUndefined()
|
||||
1
spec/fixtures/native-cache/file-1.js
vendored
Normal file
1
spec/fixtures/native-cache/file-1.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = function () { return 1; }
|
||||
1
spec/fixtures/native-cache/file-2.js
vendored
Normal file
1
spec/fixtures/native-cache/file-2.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = function () { return 2; }
|
||||
1
spec/fixtures/native-cache/file-3.js
vendored
Normal file
1
spec/fixtures/native-cache/file-3.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = function () { return 3; }
|
||||
0
spec/fixtures/testdir/sample-theme-1/readme
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-1/readme
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-1/src/js/main.js
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-1/src/js/main.js
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-2/readme
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-2/readme
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-2/src/js/main.js
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-2/src/js/main.js
vendored
Normal file
@@ -2,7 +2,7 @@ LinesYardstick = require "../src/lines-yardstick"
|
||||
{toArray} = require 'underscore-plus'
|
||||
|
||||
describe "LinesYardstick", ->
|
||||
[editor, mockPresenter, mockLineNodesProvider, createdLineNodes, linesYardstick] = []
|
||||
[editor, mockPresenter, mockLineNodesProvider, createdLineNodes, linesYardstick, buildLineNode] = []
|
||||
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
@@ -49,10 +49,10 @@ describe "LinesYardstick", ->
|
||||
buildLineNode(screenRow)
|
||||
textNodesForLineIdAndScreenRow: (lineId, screenRow) ->
|
||||
lineNode = @lineNodeForLineIdAndScreenRow(lineId, screenRow)
|
||||
iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT)
|
||||
textNodes = []
|
||||
for span in lineNode.children
|
||||
for textNode in span.childNodes
|
||||
textNodes.push(textNode)
|
||||
while textNode = iterator.nextNode()
|
||||
textNodes.push(textNode)
|
||||
textNodes
|
||||
|
||||
editor.setLineHeightInPixels(14)
|
||||
@@ -126,6 +126,33 @@ describe "LinesYardstick", ->
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 9]).left).toBe 67
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 11]).left).toBe 84
|
||||
|
||||
it "doesn't report a width greater than 0 when the character to measure is at the beginning of a text node", ->
|
||||
# This spec documents what seems to be a bug in Chromium, because we'd
|
||||
# expect that Range(0, 0).getBoundingClientRect().width to always be zero.
|
||||
atom.styles.addStyleSheet """
|
||||
* {
|
||||
font-size: 11px;
|
||||
font-family: monospace;
|
||||
}
|
||||
"""
|
||||
|
||||
text = " \\vec{w}_j^r(\\text{new}) &= \\vec{w}_j^r(\\text{old}) + \\Delta\\vec{w}_j^r, \\\\"
|
||||
buildLineNode = (screenRow) ->
|
||||
lineNode = document.createElement("div")
|
||||
lineNode.style.whiteSpace = "pre"
|
||||
# We couldn't reproduce the problem with a simple string, so we're
|
||||
# attaching the full one that comes from a bug report.
|
||||
lineNode.innerHTML = '<span><span> </span><span> </span><span><span>\\</span>vec</span><span><span>{</span>w<span>}</span></span>_j^r(<span><span>\\</span>text</span><span><span>{</span>new<span>}</span></span>) &= <span><span>\\</span>vec</span><span><span>{</span>w<span>}</span></span>_j^r(<span><span>\\</span>text</span><span><span>{</span>old<span>}</span></span>) + <span><span>\\</span>Delta</span><span><span>\\</span>vec</span><span><span>{</span>w<span>}</span></span>_j^r, <span>\\\\</span></span>'
|
||||
jasmine.attachToDOM(lineNode)
|
||||
createdLineNodes.push(lineNode)
|
||||
lineNode
|
||||
|
||||
editor.setText(text)
|
||||
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 35]).left).toBe 230.90625
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 36]).left).toBe 237.5
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 37]).left).toBe 244.09375
|
||||
|
||||
it "doesn't measure invisible lines if it is explicitly told so", ->
|
||||
atom.styles.addStyleSheet """
|
||||
* {
|
||||
|
||||
47
spec/native-compile-cache-spec.coffee
Normal file
47
spec/native-compile-cache-spec.coffee
Normal file
@@ -0,0 +1,47 @@
|
||||
describe "NativeCompileCache", ->
|
||||
nativeCompileCache = require '../src/native-compile-cache'
|
||||
[fakeCacheStore, cachedFiles] = []
|
||||
|
||||
beforeEach ->
|
||||
cachedFiles = []
|
||||
fakeCacheStore = jasmine.createSpyObj("cache store", ["set", "get", "has", "delete"])
|
||||
nativeCompileCache.setCacheStore(fakeCacheStore)
|
||||
nativeCompileCache.install()
|
||||
|
||||
it "writes and reads from the cache storage when requiring files", ->
|
||||
fakeCacheStore.has.andReturn(false)
|
||||
fakeCacheStore.set.andCallFake (filename, cacheBuffer) ->
|
||||
cachedFiles.push({filename, cacheBuffer})
|
||||
|
||||
fn1 = require('./fixtures/native-cache/file-1')
|
||||
fn2 = require('./fixtures/native-cache/file-2')
|
||||
|
||||
expect(cachedFiles.length).toBe(2)
|
||||
|
||||
expect(cachedFiles[0].filename).toBe(require.resolve('./fixtures/native-cache/file-1'))
|
||||
expect(cachedFiles[0].cacheBuffer).toBeInstanceOf(Uint8Array)
|
||||
expect(cachedFiles[0].cacheBuffer.length).toBeGreaterThan(0)
|
||||
expect(fn1()).toBe(1)
|
||||
|
||||
expect(cachedFiles[1].filename).toBe(require.resolve('./fixtures/native-cache/file-2'))
|
||||
expect(cachedFiles[1].cacheBuffer).toBeInstanceOf(Uint8Array)
|
||||
expect(cachedFiles[1].cacheBuffer.length).toBeGreaterThan(0)
|
||||
expect(fn2()).toBe(2)
|
||||
|
||||
fakeCacheStore.has.andReturn(true)
|
||||
fakeCacheStore.get.andReturn(cachedFiles[0].cacheBuffer)
|
||||
fakeCacheStore.set.reset()
|
||||
|
||||
fn1 = require('./fixtures/native-cache/file-1')
|
||||
|
||||
expect(fakeCacheStore.set).not.toHaveBeenCalled()
|
||||
expect(fn1()).toBe(1)
|
||||
|
||||
it "deletes previously cached code when the cache is not valid", ->
|
||||
fakeCacheStore.has.andReturn(true)
|
||||
fakeCacheStore.get.andCallFake -> new Buffer("an invalid cache")
|
||||
|
||||
fn3 = require('./fixtures/native-cache/file-3')
|
||||
|
||||
expect(fakeCacheStore.delete).toHaveBeenCalledWith(require.resolve('./fixtures/native-cache/file-3'))
|
||||
expect(fn3()).toBe(3)
|
||||
@@ -38,6 +38,7 @@ describe "PackageManager", ->
|
||||
expect(-> pack.reloadStylesheets()).not.toThrow()
|
||||
expect(addErrorHandler.callCount).toBe 2
|
||||
expect(addErrorHandler.argsForCall[1][0].message).toContain("Failed to reload the package-with-invalid-styles package stylesheets")
|
||||
expect(addErrorHandler.argsForCall[1][0].options.packageName).toEqual "package-with-invalid-styles"
|
||||
|
||||
it "returns null if the package has an invalid package.json", ->
|
||||
addErrorHandler = jasmine.createSpy()
|
||||
@@ -45,6 +46,7 @@ describe "PackageManager", ->
|
||||
expect(atom.packages.loadPackage("package-with-broken-package-json")).toBeNull()
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
expect(addErrorHandler.argsForCall[0][0].message).toContain("Failed to load the package-with-broken-package-json package")
|
||||
expect(addErrorHandler.argsForCall[0][0].options.packageName).toEqual "package-with-broken-package-json"
|
||||
|
||||
it "normalizes short repository urls in package.json", ->
|
||||
{metadata} = atom.packages.loadPackage("package-with-short-url-package-json")
|
||||
@@ -230,6 +232,7 @@ describe "PackageManager", ->
|
||||
expect(-> atom.packages.activatePackage('package-with-invalid-activation-commands')).not.toThrow()
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
expect(addErrorHandler.argsForCall[0][0].message).toContain("Failed to activate the package-with-invalid-activation-commands package")
|
||||
expect(addErrorHandler.argsForCall[0][0].options.packageName).toEqual "package-with-invalid-activation-commands"
|
||||
|
||||
it "adds a notification when the context menu is invalid", ->
|
||||
addErrorHandler = jasmine.createSpy()
|
||||
@@ -237,6 +240,7 @@ describe "PackageManager", ->
|
||||
expect(-> atom.packages.activatePackage('package-with-invalid-context-menu')).not.toThrow()
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
expect(addErrorHandler.argsForCall[0][0].message).toContain("Failed to activate the package-with-invalid-context-menu package")
|
||||
expect(addErrorHandler.argsForCall[0][0].options.packageName).toEqual "package-with-invalid-context-menu"
|
||||
|
||||
it "adds a notification when the grammar is invalid", ->
|
||||
addErrorHandler = jasmine.createSpy()
|
||||
@@ -250,6 +254,7 @@ describe "PackageManager", ->
|
||||
runs ->
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
expect(addErrorHandler.argsForCall[0][0].message).toContain("Failed to load a package-with-invalid-grammar package grammar")
|
||||
expect(addErrorHandler.argsForCall[0][0].options.packageName).toEqual "package-with-invalid-grammar"
|
||||
|
||||
it "adds a notification when the settings are invalid", ->
|
||||
addErrorHandler = jasmine.createSpy()
|
||||
@@ -263,6 +268,7 @@ describe "PackageManager", ->
|
||||
runs ->
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
expect(addErrorHandler.argsForCall[0][0].message).toContain("Failed to load the package-with-invalid-settings package settings")
|
||||
expect(addErrorHandler.argsForCall[0][0].options.packageName).toEqual "package-with-invalid-settings"
|
||||
|
||||
describe "when the package metadata includes `activationHooks`", ->
|
||||
[mainModule, promise] = []
|
||||
@@ -351,6 +357,7 @@ describe "PackageManager", ->
|
||||
expect(-> atom.packages.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
expect(addErrorHandler.argsForCall[0][0].message).toContain("Failed to load the package-that-throws-an-exception package")
|
||||
expect(addErrorHandler.argsForCall[0][0].options.packageName).toEqual "package-that-throws-an-exception"
|
||||
|
||||
describe "when the package is not found", ->
|
||||
it "rejects the promise", ->
|
||||
|
||||
@@ -168,6 +168,37 @@ describe "TextEditor", ->
|
||||
buffer.setPath(undefined)
|
||||
expect(editor.getLongTitle()).toBe 'untitled'
|
||||
|
||||
describe ".getUniqueTitle()", ->
|
||||
it "returns file name when there is no opened file with identical name", ->
|
||||
expect(editor.getUniqueTitle()).toBe 'sample.js'
|
||||
buffer.setPath(undefined)
|
||||
expect(editor.getLongTitle()).toBe 'untitled'
|
||||
|
||||
it "returns <parent-directory>/<filename> when opened files has identical file names", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(path.join('sample-theme-1', 'readme')).then (o) ->
|
||||
editor1 = o
|
||||
atom.workspace.open(path.join('sample-theme-2', 'readme')).then (o) ->
|
||||
editor2 = o
|
||||
runs ->
|
||||
expect(editor1.getUniqueTitle()).toBe 'sample-theme-1/readme'
|
||||
expect(editor2.getUniqueTitle()).toBe 'sample-theme-2/readme'
|
||||
|
||||
it "or returns <parent-directory>/.../<filename> when opened files has identical file names", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(path.join('sample-theme-1', 'src', 'js', 'main.js')).then (o) ->
|
||||
editor1 = o
|
||||
atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'main.js')).then (o) ->
|
||||
editor2 = o
|
||||
runs ->
|
||||
expect(editor1.getUniqueTitle()).toBe 'sample-theme-1/.../main.js'
|
||||
expect(editor2.getUniqueTitle()).toBe 'sample-theme-2/.../main.js'
|
||||
|
||||
|
||||
it "notifies ::onDidChangeTitle observers when the underlying buffer path changes", ->
|
||||
observed = []
|
||||
editor.onDidChangeTitle (title) -> observed.push(title)
|
||||
@@ -827,6 +858,185 @@ describe "TextEditor", ->
|
||||
editor.moveToBeginningOfNextWord()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [11, 9]
|
||||
|
||||
describe ".moveToPreviousSubwordBoundary", ->
|
||||
it "does not move the cursor when there is no previous subword boundary", ->
|
||||
editor.setText('')
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 0])
|
||||
|
||||
it "stops at word and underscore boundaries", ->
|
||||
editor.setText("sub_word \n")
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 8])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 0])
|
||||
|
||||
editor.setText(" word\n")
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "stops at camelCase boundaries", ->
|
||||
editor.setText(" getPreviousWord\n")
|
||||
editor.setCursorBufferPosition([0, 16])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 12])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "skips consecutive non-word characters", ->
|
||||
editor.setText("e, => \n")
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "skips consecutive uppercase characters", ->
|
||||
editor.setText(" AAADF \n")
|
||||
editor.setCursorBufferPosition([0, 7])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 6])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.setText("ALPhA\n")
|
||||
editor.setCursorBufferPosition([0, 4])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 2])
|
||||
|
||||
it "skips consecutive numbers", ->
|
||||
editor.setText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 4])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "works with multiple cursors", ->
|
||||
editor.setText("curOp\ncursorOptions\n")
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
editor.addCursorAtBufferPosition([1, 13])
|
||||
[cursor1, cursor2] = editor.getCursors()
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 3])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 6])
|
||||
|
||||
it "works with non-English characters", ->
|
||||
editor.setText("supåTøåst \n")
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.setText("supaÖast \n")
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
describe ".moveToNextSubwordBoundary", ->
|
||||
it "does not move the cursor when there is no next subword boundary", ->
|
||||
editor.setText('')
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 0])
|
||||
|
||||
it "stops at word and underscore boundaries", ->
|
||||
editor.setText(" sub_word \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 9])
|
||||
|
||||
editor.setText("word \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
it "stops at camelCase boundaries", ->
|
||||
editor.setText("getPreviousWord \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 11])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 15])
|
||||
|
||||
it "skips consecutive non-word characters", ->
|
||||
editor.setText(", => \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
it "skips consecutive uppercase characters", ->
|
||||
editor.setText(" AAADF \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 6])
|
||||
|
||||
editor.setText("ALPhA\n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 2])
|
||||
|
||||
it "skips consecutive numbers", ->
|
||||
editor.setText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
it "works with multiple cursors", ->
|
||||
editor.setText("curOp\ncursorOptions\n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.addCursorAtBufferPosition([1, 0])
|
||||
[cursor1, cursor2] = editor.getCursors()
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 3])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 6])
|
||||
|
||||
it "works with non-English characters", ->
|
||||
editor.setText("supåTøåst \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.setText("supaÖast \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
describe ".moveToBeginningOfNextParagraph()", ->
|
||||
it "moves the cursor before the first line of the next paragraph", ->
|
||||
editor.setCursorBufferPosition [0, 6]
|
||||
@@ -1299,6 +1509,128 @@ describe "TextEditor", ->
|
||||
expect(selection4.getBufferRange()).toEqual [[3, 30], [3, 31]]
|
||||
expect(selection4.isReversed()).toBeFalsy()
|
||||
|
||||
describe ".selectToPreviousSubwordBoundary", ->
|
||||
it "selects subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("_word\n")
|
||||
editor.insertText(" getPreviousWord\n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
editor.addCursorAtBufferPosition([1, 7])
|
||||
editor.addCursorAtBufferPosition([2, 5])
|
||||
editor.addCursorAtBufferPosition([3, 3])
|
||||
[selection1, selection2, selection3, selection4] = editor.getSelections()
|
||||
|
||||
editor.selectToPreviousSubwordBoundary()
|
||||
expect(selection1.getBufferRange()).toEqual([[0, 1], [0, 5]])
|
||||
expect(selection1.isReversed()).toBeTruthy()
|
||||
expect(selection2.getBufferRange()).toEqual([[1, 4], [1, 7]])
|
||||
expect(selection2.isReversed()).toBeTruthy()
|
||||
expect(selection3.getBufferRange()).toEqual([[2, 3], [2, 5]])
|
||||
expect(selection3.isReversed()).toBeTruthy()
|
||||
expect(selection4.getBufferRange()).toEqual([[3, 1], [3, 3]])
|
||||
expect(selection4.isReversed()).toBeTruthy()
|
||||
|
||||
describe ".selectToNextSubwordBoundary", ->
|
||||
it "selects subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("word_\n")
|
||||
editor.insertText("getPreviousWord\n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
editor.addCursorAtBufferPosition([1, 7])
|
||||
editor.addCursorAtBufferPosition([2, 2])
|
||||
editor.addCursorAtBufferPosition([3, 1])
|
||||
[selection1, selection2, selection3, selection4] = editor.getSelections()
|
||||
|
||||
editor.selectToNextSubwordBoundary()
|
||||
expect(selection1.getBufferRange()).toEqual([[0, 1], [0, 4]])
|
||||
expect(selection1.isReversed()).toBeFalsy()
|
||||
expect(selection2.getBufferRange()).toEqual([[1, 7], [1, 11]])
|
||||
expect(selection2.isReversed()).toBeFalsy()
|
||||
expect(selection3.getBufferRange()).toEqual([[2, 2], [2, 5]])
|
||||
expect(selection3.isReversed()).toBeFalsy()
|
||||
expect(selection4.getBufferRange()).toEqual([[3, 1], [3, 3]])
|
||||
expect(selection4.isReversed()).toBeFalsy()
|
||||
|
||||
describe ".deleteToBeginningOfSubword", ->
|
||||
it "deletes subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("_word\n")
|
||||
editor.insertText(" getPreviousWord\n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
editor.addCursorAtBufferPosition([1, 7])
|
||||
editor.addCursorAtBufferPosition([2, 5])
|
||||
editor.addCursorAtBufferPosition([3, 3])
|
||||
[cursor1, cursor2, cursor3, cursor4] = editor.getCursors()
|
||||
|
||||
editor.deleteToBeginningOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('_')
|
||||
expect(buffer.lineForRow(1)).toBe(' getviousWord')
|
||||
expect(buffer.lineForRow(2)).toBe('e, ')
|
||||
expect(buffer.lineForRow(3)).toBe(' ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 1])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 4])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 3])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 1])
|
||||
|
||||
editor.deleteToBeginningOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('')
|
||||
expect(buffer.lineForRow(1)).toBe(' viousWord')
|
||||
expect(buffer.lineForRow(2)).toBe('e ')
|
||||
expect(buffer.lineForRow(3)).toBe(' ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 1])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 1])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 0])
|
||||
|
||||
editor.deleteToBeginningOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('')
|
||||
expect(buffer.lineForRow(1)).toBe('viousWord')
|
||||
expect(buffer.lineForRow(2)).toBe(' ')
|
||||
expect(buffer.lineForRow(3)).toBe('')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 0])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 0])
|
||||
expect(cursor4.getBufferPosition()).toEqual([2, 1])
|
||||
|
||||
describe ".deleteToEndOfSubword", ->
|
||||
it "deletes subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("word_\n")
|
||||
editor.insertText("getPreviousWord \n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.addCursorAtBufferPosition([1, 0])
|
||||
editor.addCursorAtBufferPosition([2, 2])
|
||||
editor.addCursorAtBufferPosition([3, 0])
|
||||
[cursor1, cursor2, cursor3, cursor4] = editor.getCursors()
|
||||
|
||||
editor.deleteToEndOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('_')
|
||||
expect(buffer.lineForRow(1)).toBe('PreviousWord ')
|
||||
expect(buffer.lineForRow(2)).toBe('e, ')
|
||||
expect(buffer.lineForRow(3)).toBe('88 ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 0])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 2])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 0])
|
||||
|
||||
editor.deleteToEndOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('')
|
||||
expect(buffer.lineForRow(1)).toBe('Word ')
|
||||
expect(buffer.lineForRow(2)).toBe('e,')
|
||||
expect(buffer.lineForRow(3)).toBe(' ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 0])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 2])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 0])
|
||||
|
||||
describe ".selectWordsContainingCursors()", ->
|
||||
describe "when the cursor is inside a word", ->
|
||||
it "selects the entire word", ->
|
||||
@@ -4160,6 +4492,36 @@ describe "TextEditor", ->
|
||||
"""
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[13, 0], [14, 2]]
|
||||
|
||||
describe ".moveLineUp()", ->
|
||||
it "moves the line under the cursor up", ->
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
editor.moveLineUp()
|
||||
expect(editor.getTextInBufferRange([[0, 0], [0, 30]])).toBe " var sort = function(items) {"
|
||||
expect(editor.indentationForBufferRow(0)).toBe 1
|
||||
expect(editor.indentationForBufferRow(1)).toBe 0
|
||||
|
||||
it "updates the line's indentation when the editor.autoIndent setting is true", ->
|
||||
atom.config.set('editor.autoIndent', true)
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
editor.moveLineUp()
|
||||
expect(editor.indentationForBufferRow(0)).toBe 0
|
||||
expect(editor.indentationForBufferRow(1)).toBe 0
|
||||
|
||||
describe ".moveLineDown()", ->
|
||||
it "moves the line under the cursor down", ->
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveLineDown()
|
||||
expect(editor.getTextInBufferRange([[1, 0], [1, 31]])).toBe "var quicksort = function () {"
|
||||
expect(editor.indentationForBufferRow(0)).toBe 1
|
||||
expect(editor.indentationForBufferRow(1)).toBe 0
|
||||
|
||||
it "updates the line's indentation when the editor.autoIndent setting is true", ->
|
||||
atom.config.set('editor.autoIndent', true)
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveLineDown()
|
||||
expect(editor.indentationForBufferRow(0)).toBe 1
|
||||
expect(editor.indentationForBufferRow(1)).toBe 2
|
||||
|
||||
describe ".shouldPromptToSave()", ->
|
||||
it "returns false when an edit session's buffer is in use by more than one session", ->
|
||||
jasmine.unspy(editor, 'shouldPromptToSave')
|
||||
@@ -4461,307 +4823,6 @@ describe "TextEditor", ->
|
||||
|
||||
waitsForPromise -> editor.checkoutHeadRevision()
|
||||
|
||||
describe ".moveToPreviousSubwordBoundary", ->
|
||||
it "does not move the cursor when there is no previous subword boundary", ->
|
||||
editor.setText('')
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 0])
|
||||
|
||||
it "stops at word and underscore boundaries", ->
|
||||
editor.setText("sub_word \n")
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 8])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 0])
|
||||
|
||||
editor.setText(" word\n")
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "stops at camelCase boundaries", ->
|
||||
editor.setText(" getPreviousWord\n")
|
||||
editor.setCursorBufferPosition([0, 16])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 12])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "skips consecutive non-word characters", ->
|
||||
editor.setText("e, => \n")
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "skips consecutive uppercase characters", ->
|
||||
editor.setText(" AAADF \n")
|
||||
editor.setCursorBufferPosition([0, 7])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 6])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.setText("ALPhA\n")
|
||||
editor.setCursorBufferPosition([0, 4])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 2])
|
||||
|
||||
it "skips consecutive numbers", ->
|
||||
editor.setText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 4])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
it "works with multiple cursors", ->
|
||||
editor.setText("curOp\ncursorOptions\n")
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
editor.addCursorAtBufferPosition([1, 13])
|
||||
[cursor1, cursor2] = editor.getCursors()
|
||||
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 3])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 6])
|
||||
|
||||
it "works with non-English characters", ->
|
||||
editor.setText("supåTøåst \n")
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.setText("supaÖast \n")
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
editor.moveToPreviousSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
describe ".moveToNextSubwordBoundary", ->
|
||||
it "does not move the cursor when there is no next subword boundary", ->
|
||||
editor.setText('')
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 0])
|
||||
|
||||
it "stops at word and underscore boundaries", ->
|
||||
editor.setText(" sub_word \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 9])
|
||||
|
||||
editor.setText("word \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
it "stops at camelCase boundaries", ->
|
||||
editor.setText("getPreviousWord \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 11])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 15])
|
||||
|
||||
it "skips consecutive non-word characters", ->
|
||||
editor.setText(", => \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
it "skips consecutive uppercase characters", ->
|
||||
editor.setText(" AAADF \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 6])
|
||||
|
||||
editor.setText("ALPhA\n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 2])
|
||||
|
||||
it "skips consecutive numbers", ->
|
||||
editor.setText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 1])
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 3])
|
||||
|
||||
it "works with multiple cursors", ->
|
||||
editor.setText("curOp\ncursorOptions\n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.addCursorAtBufferPosition([1, 0])
|
||||
[cursor1, cursor2] = editor.getCursors()
|
||||
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 3])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 6])
|
||||
|
||||
it "works with non-English characters", ->
|
||||
editor.setText("supåTøåst \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
editor.setText("supaÖast \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.moveToNextSubwordBoundary()
|
||||
expect(editor.getCursorBufferPosition()).toEqual([0, 4])
|
||||
|
||||
describe ".selectToPreviousSubwordBoundary", ->
|
||||
it "selects subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("_word\n")
|
||||
editor.insertText(" getPreviousWord\n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
editor.addCursorAtBufferPosition([1, 7])
|
||||
editor.addCursorAtBufferPosition([2, 5])
|
||||
editor.addCursorAtBufferPosition([3, 3])
|
||||
[selection1, selection2, selection3, selection4] = editor.getSelections()
|
||||
|
||||
editor.selectToPreviousSubwordBoundary()
|
||||
expect(selection1.getBufferRange()).toEqual([[0, 1], [0, 5]])
|
||||
expect(selection1.isReversed()).toBeTruthy()
|
||||
expect(selection2.getBufferRange()).toEqual([[1, 4], [1, 7]])
|
||||
expect(selection2.isReversed()).toBeTruthy()
|
||||
expect(selection3.getBufferRange()).toEqual([[2, 3], [2, 5]])
|
||||
expect(selection3.isReversed()).toBeTruthy()
|
||||
expect(selection4.getBufferRange()).toEqual([[3, 1], [3, 3]])
|
||||
expect(selection4.isReversed()).toBeTruthy()
|
||||
|
||||
describe ".selectToNextSubwordBoundary", ->
|
||||
it "selects subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("word_\n")
|
||||
editor.insertText("getPreviousWord\n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
editor.addCursorAtBufferPosition([1, 7])
|
||||
editor.addCursorAtBufferPosition([2, 2])
|
||||
editor.addCursorAtBufferPosition([3, 1])
|
||||
[selection1, selection2, selection3, selection4] = editor.getSelections()
|
||||
|
||||
editor.selectToNextSubwordBoundary()
|
||||
expect(selection1.getBufferRange()).toEqual([[0, 1], [0, 4]])
|
||||
expect(selection1.isReversed()).toBeFalsy()
|
||||
expect(selection2.getBufferRange()).toEqual([[1, 7], [1, 11]])
|
||||
expect(selection2.isReversed()).toBeFalsy()
|
||||
expect(selection3.getBufferRange()).toEqual([[2, 2], [2, 5]])
|
||||
expect(selection3.isReversed()).toBeFalsy()
|
||||
expect(selection4.getBufferRange()).toEqual([[3, 1], [3, 3]])
|
||||
expect(selection4.isReversed()).toBeFalsy()
|
||||
|
||||
describe ".deleteToBeginningOfSubword", ->
|
||||
it "deletes subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("_word\n")
|
||||
editor.insertText(" getPreviousWord\n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
editor.addCursorAtBufferPosition([1, 7])
|
||||
editor.addCursorAtBufferPosition([2, 5])
|
||||
editor.addCursorAtBufferPosition([3, 3])
|
||||
[cursor1, cursor2, cursor3, cursor4] = editor.getCursors()
|
||||
|
||||
editor.deleteToBeginningOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('_')
|
||||
expect(buffer.lineForRow(1)).toBe(' getviousWord')
|
||||
expect(buffer.lineForRow(2)).toBe('e, ')
|
||||
expect(buffer.lineForRow(3)).toBe(' ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 1])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 4])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 3])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 1])
|
||||
|
||||
editor.deleteToBeginningOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('')
|
||||
expect(buffer.lineForRow(1)).toBe(' viousWord')
|
||||
expect(buffer.lineForRow(2)).toBe('e ')
|
||||
expect(buffer.lineForRow(3)).toBe(' ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 1])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 1])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 0])
|
||||
|
||||
editor.deleteToBeginningOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('')
|
||||
expect(buffer.lineForRow(1)).toBe('viousWord')
|
||||
expect(buffer.lineForRow(2)).toBe(' ')
|
||||
expect(buffer.lineForRow(3)).toBe('')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 0])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 0])
|
||||
expect(cursor4.getBufferPosition()).toEqual([2, 1])
|
||||
|
||||
describe ".deleteToEndOfSubword", ->
|
||||
it "deletes subwords", ->
|
||||
editor.setText("")
|
||||
editor.insertText("word_\n")
|
||||
editor.insertText("getPreviousWord \n")
|
||||
editor.insertText("e, => \n")
|
||||
editor.insertText(" 88 \n")
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.addCursorAtBufferPosition([1, 0])
|
||||
editor.addCursorAtBufferPosition([2, 2])
|
||||
editor.addCursorAtBufferPosition([3, 0])
|
||||
[cursor1, cursor2, cursor3, cursor4] = editor.getCursors()
|
||||
|
||||
editor.deleteToEndOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('_')
|
||||
expect(buffer.lineForRow(1)).toBe('PreviousWord ')
|
||||
expect(buffer.lineForRow(2)).toBe('e, ')
|
||||
expect(buffer.lineForRow(3)).toBe('88 ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 0])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 2])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 0])
|
||||
|
||||
editor.deleteToEndOfSubword()
|
||||
expect(buffer.lineForRow(0)).toBe('')
|
||||
expect(buffer.lineForRow(1)).toBe('Word ')
|
||||
expect(buffer.lineForRow(2)).toBe('e,')
|
||||
expect(buffer.lineForRow(3)).toBe(' ')
|
||||
expect(cursor1.getBufferPosition()).toEqual([0, 0])
|
||||
expect(cursor2.getBufferPosition()).toEqual([1, 0])
|
||||
expect(cursor3.getBufferPosition()).toEqual([2, 2])
|
||||
expect(cursor4.getBufferPosition()).toEqual([3, 0])
|
||||
|
||||
describe 'gutters', ->
|
||||
describe 'the TextEditor constructor', ->
|
||||
it 'creates a line-number gutter', ->
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
crypto = require 'crypto'
|
||||
path = require 'path'
|
||||
ipc = require 'ipc'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{deprecate} = require 'grim'
|
||||
@@ -116,7 +117,7 @@ class AtomEnvironment extends Model
|
||||
|
||||
# Call .loadOrCreate instead
|
||||
constructor: (params={}) ->
|
||||
{@applicationDelegate, @window, @document, configDirPath, @enablePersistence} = params
|
||||
{@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence} = params
|
||||
|
||||
@state = {version: @constructor.version}
|
||||
|
||||
@@ -203,6 +204,15 @@ class AtomEnvironment extends Model
|
||||
|
||||
@observeAutoHideMenuBar()
|
||||
|
||||
checkPortableHomeWritable = ->
|
||||
responseChannel = "check-portable-home-writable-response"
|
||||
ipc.on responseChannel, (response) ->
|
||||
ipc.removeAllListeners(responseChannel)
|
||||
atom.notifications.addWarning("#{response.message.replace(/([\\\.+\\-_#!])/g, '\\$1')}") if not response.writable
|
||||
ipc.send('check-portable-home-writable', responseChannel)
|
||||
|
||||
checkPortableHomeWritable()
|
||||
|
||||
setConfigSchema: ->
|
||||
@config.setSchema null, {type: 'object', properties: _.clone(require('./config-schema'))}
|
||||
|
||||
@@ -306,6 +316,7 @@ class AtomEnvironment extends Model
|
||||
@project = null
|
||||
@commands.clear()
|
||||
@stylesElement.remove()
|
||||
@config.unobserveUserConfig()
|
||||
|
||||
@uninstallWindowEventHandler()
|
||||
|
||||
@@ -636,6 +647,7 @@ class AtomEnvironment extends Model
|
||||
@state.packageStates = @packages.packageStates
|
||||
@state.fullScreen = @isFullScreen()
|
||||
@saveStateSync()
|
||||
@saveBlobStoreSync()
|
||||
|
||||
openInitialEmptyEditorIfNecessary: ->
|
||||
return unless @config.get('core.openEmptyEditorOnStart')
|
||||
@@ -759,6 +771,11 @@ class AtomEnvironment extends Model
|
||||
showSaveDialogSync: (options={}) ->
|
||||
@applicationDelegate.showSaveDialog(options)
|
||||
|
||||
saveBlobStoreSync: ->
|
||||
return unless @enablePersistence
|
||||
|
||||
@blobStore.save()
|
||||
|
||||
saveStateSync: ->
|
||||
return unless @enablePersistence
|
||||
|
||||
|
||||
35
src/browser/atom-portable.coffee
Normal file
35
src/browser/atom-portable.coffee
Normal file
@@ -0,0 +1,35 @@
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
ipc = require 'ipc'
|
||||
|
||||
module.exports =
|
||||
class AtomPortable
|
||||
@getPortableAtomHomePath: ->
|
||||
execDirectoryPath = path.dirname(process.execPath)
|
||||
path.join(execDirectoryPath, '..', '.atom')
|
||||
|
||||
@setPortable: (existingAtomHome) ->
|
||||
fs.copySync(existingAtomHome, @getPortableAtomHomePath())
|
||||
|
||||
@isPortableInstall: (platform, environmentAtomHome, defaultHome) ->
|
||||
return false unless platform in ['linux', 'win32']
|
||||
return false if environmentAtomHome
|
||||
return false if not fs.existsSync(@getPortableAtomHomePath())
|
||||
# currently checking only that the directory exists and is writable,
|
||||
# probably want to do some integrity checks on contents in future
|
||||
@isPortableAtomHomePathWritable(defaultHome)
|
||||
|
||||
@isPortableAtomHomePathWritable: (defaultHome) ->
|
||||
writable = false
|
||||
message = ""
|
||||
try
|
||||
writePermissionTestFile = path.join(@getPortableAtomHomePath(), "write.test")
|
||||
fs.writeFileSync(writePermissionTestFile, "test") if not fs.existsSync(writePermissionTestFile)
|
||||
fs.removeSync(writePermissionTestFile)
|
||||
writable = true
|
||||
catch error
|
||||
message = "Failed to use portable Atom home directory (#{@getPortableAtomHomePath()}). Using the default instead (#{defaultHome}). #{error.message}"
|
||||
|
||||
ipc.on 'check-portable-home-writable', (event) ->
|
||||
event.sender.send 'check-portable-home-writable-response', {writable, message}
|
||||
writable
|
||||
@@ -49,6 +49,7 @@ class AtomWindow
|
||||
loadSettings.resourcePath = @resourcePath
|
||||
loadSettings.devMode ?= false
|
||||
loadSettings.safeMode ?= false
|
||||
loadSettings.atomHome = process.env.ATOM_HOME
|
||||
|
||||
# Only send to the first non-spec window created
|
||||
if @constructor.includeShellLoadTime and not @isSpec
|
||||
|
||||
@@ -12,15 +12,14 @@ yargs = require 'yargs'
|
||||
console.log = require 'nslog'
|
||||
|
||||
start = ->
|
||||
setupAtomHome()
|
||||
args = parseCommandLine()
|
||||
setupAtomHome(args)
|
||||
setupCompileCache()
|
||||
return if handleStartupEventWithSquirrel()
|
||||
|
||||
# NB: This prevents Win10 from showing dupe items in the taskbar
|
||||
app.setAppUserModelId('com.squirrel.atom.atom')
|
||||
|
||||
args = parseCommandLine()
|
||||
|
||||
addPathToOpen = (event, pathToOpen) ->
|
||||
event.preventDefault()
|
||||
args.pathsToOpen.push(pathToOpen)
|
||||
@@ -57,11 +56,25 @@ handleStartupEventWithSquirrel = ->
|
||||
setupCrashReporter = ->
|
||||
crashReporter.start(productName: 'Atom', companyName: 'GitHub')
|
||||
|
||||
setupAtomHome = ->
|
||||
setupAtomHome = ({setPortable}) ->
|
||||
return if process.env.ATOM_HOME
|
||||
|
||||
atomHome = path.join(app.getHomeDir(), '.atom')
|
||||
AtomPortable = require './atom-portable'
|
||||
|
||||
if setPortable and not AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)
|
||||
try
|
||||
AtomPortable.setPortable(atomHome)
|
||||
catch error
|
||||
console.log("Failed copying portable directory '#{atomHome}' to '#{AtomPortable.getPortableAtomHomePath()}'")
|
||||
console.log("#{error.message} #{error.stack}")
|
||||
|
||||
if AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)
|
||||
atomHome = AtomPortable.getPortableAtomHomePath()
|
||||
|
||||
try
|
||||
atomHome = fs.realpathSync(atomHome)
|
||||
|
||||
process.env.ATOM_HOME = atomHome
|
||||
|
||||
setupCompileCache = ->
|
||||
@@ -100,6 +113,7 @@ parseCommandLine = ->
|
||||
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.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.')
|
||||
options.boolean('portable').describe('portable', 'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.')
|
||||
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.')
|
||||
@@ -129,6 +143,7 @@ parseCommandLine = ->
|
||||
profileStartup = args['profile-startup']
|
||||
urlsToOpen = []
|
||||
devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH ? path.join(app.getHomeDir(), 'github', 'atom')
|
||||
setPortable = args.portable
|
||||
|
||||
if args['resource-path']
|
||||
devMode = true
|
||||
@@ -149,6 +164,6 @@ parseCommandLine = ->
|
||||
|
||||
{resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test,
|
||||
version, pidToKillWhenClosed, devMode, safeMode, newWindow,
|
||||
logFile, socketPath, profileStartup, timeout}
|
||||
logFile, socketPath, profileStartup, timeout, setPortable}
|
||||
|
||||
start()
|
||||
|
||||
111
src/file-system-blob-store.js
Normal file
111
src/file-system-blob-store.js
Normal file
@@ -0,0 +1,111 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs-plus')
|
||||
const path = require('path')
|
||||
|
||||
module.exports =
|
||||
class FileSystemBlobStore {
|
||||
static load (directory) {
|
||||
let instance = new FileSystemBlobStore(directory)
|
||||
instance.load()
|
||||
return instance
|
||||
}
|
||||
|
||||
constructor (directory) {
|
||||
this.inMemoryBlobs = new Map()
|
||||
this.blobFilename = path.join(directory, 'BLOB')
|
||||
this.blobMapFilename = path.join(directory, 'MAP')
|
||||
this.lockFilename = path.join(directory, 'LOCK')
|
||||
this.storedBlob = new Buffer(0)
|
||||
this.storedBlobMap = {}
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!fs.existsSync(this.blobMapFilename)) {
|
||||
return
|
||||
}
|
||||
if (!fs.existsSync(this.blobFilename)) {
|
||||
return
|
||||
}
|
||||
this.storedBlob = fs.readFileSync(this.blobFilename)
|
||||
this.storedBlobMap = JSON.parse(fs.readFileSync(this.blobMapFilename))
|
||||
}
|
||||
|
||||
save () {
|
||||
let dump = this.getDump()
|
||||
let blobToStore = Buffer.concat(dump[0])
|
||||
let mapToStore = JSON.stringify(dump[1])
|
||||
|
||||
let acquiredLock = false
|
||||
try {
|
||||
fs.writeFileSync(this.lockFilename, 'LOCK', {flag: 'wx'})
|
||||
acquiredLock = true
|
||||
|
||||
fs.writeFileSync(this.blobFilename, blobToStore)
|
||||
fs.writeFileSync(this.blobMapFilename, mapToStore)
|
||||
} catch (error) {
|
||||
// Swallow the exception silently only if we fail to acquire the lock.
|
||||
if (error.code !== 'EEXIST') {
|
||||
throw error
|
||||
}
|
||||
} finally {
|
||||
if (acquiredLock) {
|
||||
fs.unlinkSync(this.lockFilename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
has (key) {
|
||||
return this.inMemoryBlobs.hasOwnProperty(key) || this.storedBlobMap.hasOwnProperty(key)
|
||||
}
|
||||
|
||||
get (key) {
|
||||
return this.getFromMemory(key) || this.getFromStorage(key)
|
||||
}
|
||||
|
||||
set (key, buffer) {
|
||||
return this.inMemoryBlobs.set(key, buffer)
|
||||
}
|
||||
|
||||
delete (key) {
|
||||
this.inMemoryBlobs.delete(key)
|
||||
delete this.storedBlobMap[key]
|
||||
}
|
||||
|
||||
getFromMemory (key) {
|
||||
return this.inMemoryBlobs.get(key)
|
||||
}
|
||||
|
||||
getFromStorage (key) {
|
||||
if (!this.storedBlobMap[key]) {
|
||||
return
|
||||
}
|
||||
|
||||
return this.storedBlob.slice.apply(this.storedBlob, this.storedBlobMap[key])
|
||||
}
|
||||
|
||||
getDump () {
|
||||
let buffers = []
|
||||
let blobMap = {}
|
||||
let currentBufferStart = 0
|
||||
|
||||
function dump (key, getBufferByKey) {
|
||||
let buffer = getBufferByKey(key)
|
||||
buffers.push(buffer)
|
||||
blobMap[key] = [currentBufferStart, currentBufferStart + buffer.length]
|
||||
currentBufferStart += buffer.length
|
||||
}
|
||||
|
||||
for (let key of this.inMemoryBlobs.keys()) {
|
||||
dump(key, this.getFromMemory.bind(this))
|
||||
}
|
||||
|
||||
for (let key of Object.keys(this.storedBlobMap)) {
|
||||
if (!blobMap[key]) {
|
||||
dump(key, this.getFromStorage.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
return [buffers, blobMap]
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,34 @@
|
||||
# Like sands through the hourglass, so are the days of our lives.
|
||||
module.exports = ({blobStore}) ->
|
||||
path = require 'path'
|
||||
require './window'
|
||||
{getWindowLoadSettings} = require './window-load-settings-helpers'
|
||||
|
||||
path = require 'path'
|
||||
require './window'
|
||||
{getWindowLoadSettings} = require './window-load-settings-helpers'
|
||||
{resourcePath, isSpec, devMode} = getWindowLoadSettings()
|
||||
|
||||
{resourcePath, isSpec, devMode} = getWindowLoadSettings()
|
||||
# Add application-specific exports to module search path.
|
||||
exportsPath = path.join(resourcePath, 'exports')
|
||||
require('module').globalPaths.push(exportsPath)
|
||||
process.env.NODE_PATH = exportsPath
|
||||
|
||||
# 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
|
||||
|
||||
# Make React faster
|
||||
process.env.NODE_ENV ?= 'production' unless devMode
|
||||
AtomEnvironment = require './atom-environment'
|
||||
ApplicationDelegate = require './application-delegate'
|
||||
window.atom = new AtomEnvironment({
|
||||
window, document, blobStore,
|
||||
applicationDelegate: new ApplicationDelegate,
|
||||
configDirPath: process.env.ATOM_HOME
|
||||
enablePersistence: true
|
||||
})
|
||||
|
||||
AtomEnvironment = require './atom-environment'
|
||||
ApplicationDelegate = require './application-delegate'
|
||||
window.atom = new AtomEnvironment({
|
||||
window, document,
|
||||
applicationDelegate: new ApplicationDelegate,
|
||||
configDirPath: process.env.ATOM_HOME
|
||||
enablePersistence: true
|
||||
})
|
||||
atom.displayWindow()
|
||||
atom.loadStateSync()
|
||||
atom.startEditorWindow()
|
||||
|
||||
atom.displayWindow()
|
||||
atom.loadStateSync()
|
||||
atom.startEditorWindow()
|
||||
|
||||
# Workaround for focus getting cleared upon window creation
|
||||
windowFocused = ->
|
||||
window.removeEventListener('focus', windowFocused)
|
||||
setTimeout (-> document.querySelector('atom-workspace').focus()), 0
|
||||
window.addEventListener('focus', windowFocused)
|
||||
# Workaround for focus getting cleared upon window creation
|
||||
windowFocused = ->
|
||||
window.removeEventListener('focus', windowFocused)
|
||||
setTimeout (-> document.querySelector('atom-workspace').focus()), 0
|
||||
window.addEventListener('focus', windowFocused)
|
||||
|
||||
@@ -1,69 +1,78 @@
|
||||
# Start the crash reporter before anything else.
|
||||
require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
|
||||
remote = require 'remote'
|
||||
cloneObject = (object) ->
|
||||
clone = {}
|
||||
clone[key] = value for key, value of object
|
||||
clone
|
||||
|
||||
exitWithStatusCode = (status) ->
|
||||
remote.require('app').emit('will-quit')
|
||||
remote.process.exit(status)
|
||||
module.exports = ({blobStore}) ->
|
||||
# Start the crash reporter before anything else.
|
||||
require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
|
||||
remote = require 'remote'
|
||||
|
||||
try
|
||||
path = require 'path'
|
||||
ipc = require 'ipc'
|
||||
{getWindowLoadSettings} = require './window-load-settings-helpers'
|
||||
AtomEnvironment = require '../src/atom-environment'
|
||||
ApplicationDelegate = require '../src/application-delegate'
|
||||
exitWithStatusCode = (status) ->
|
||||
remote.require('app').emit('will-quit')
|
||||
remote.process.exit(status)
|
||||
|
||||
{testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings()
|
||||
try
|
||||
path = require 'path'
|
||||
ipc = require 'ipc'
|
||||
{getWindowLoadSettings} = require './window-load-settings-helpers'
|
||||
AtomEnvironment = require '../src/atom-environment'
|
||||
ApplicationDelegate = require '../src/application-delegate'
|
||||
|
||||
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()
|
||||
{testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings()
|
||||
|
||||
handleKeydown = (event) ->
|
||||
# Reload: cmd-r / ctrl-r
|
||||
if (event.metaKey or event.ctrlKey) and event.keyCode is 82
|
||||
ipc.send('call-window-method', 'restart')
|
||||
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()
|
||||
|
||||
# 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')
|
||||
handleKeydown = (event) ->
|
||||
# Reload: cmd-r / ctrl-r
|
||||
if (event.metaKey or event.ctrlKey) and event.keyCode is 82
|
||||
ipc.send('call-window-method', 'restart')
|
||||
|
||||
# Reload: cmd-w / ctrl-w
|
||||
if (event.metaKey or event.ctrlKey) and event.keyCode is 87
|
||||
ipc.send('call-window-method', 'close')
|
||||
# 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')
|
||||
|
||||
window.addEventListener('keydown', handleKeydown, true)
|
||||
# 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(getWindowLoadSettings().resourcePath, 'exports')
|
||||
require('module').globalPaths.push(exportsPath)
|
||||
process.env.NODE_PATH = exportsPath # Set NODE_PATH env variable since tasks may need it.
|
||||
window.addEventListener('keydown', handleKeydown, true)
|
||||
|
||||
document.title = "Spec Suite"
|
||||
# Add 'exports' to module search path.
|
||||
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.
|
||||
|
||||
testRunner = require(testRunnerPath)
|
||||
legacyTestRunner = require(legacyTestRunnerPath)
|
||||
buildAtomEnvironment = (params) -> new AtomEnvironment(params)
|
||||
buildDefaultApplicationDelegate = (params) -> new ApplicationDelegate()
|
||||
document.title = "Spec Suite"
|
||||
|
||||
promise = testRunner({
|
||||
logFile, headless, testPaths, buildAtomEnvironment, buildDefaultApplicationDelegate, legacyTestRunner
|
||||
})
|
||||
testRunner = require(testRunnerPath)
|
||||
legacyTestRunner = require(legacyTestRunnerPath)
|
||||
buildDefaultApplicationDelegate = -> new ApplicationDelegate()
|
||||
buildAtomEnvironment = (params) ->
|
||||
params = cloneObject(params)
|
||||
params.blobStore = blobStore unless params.hasOwnProperty("blobStore")
|
||||
new AtomEnvironment(params)
|
||||
|
||||
promise.then(exitWithStatusCode) if getWindowLoadSettings().headless
|
||||
catch error
|
||||
if getWindowLoadSettings().headless
|
||||
console.error(error.stack ? error)
|
||||
exitWithStatusCode(1)
|
||||
else
|
||||
throw error
|
||||
promise = testRunner({
|
||||
logFile, headless, testPaths, buildAtomEnvironment, buildDefaultApplicationDelegate, legacyTestRunner
|
||||
})
|
||||
|
||||
promise.then(exitWithStatusCode) if getWindowLoadSettings().headless
|
||||
catch error
|
||||
if getWindowLoadSettings().headless
|
||||
console.error(error.stack ? error)
|
||||
exitWithStatusCode(1)
|
||||
else
|
||||
throw error
|
||||
|
||||
@@ -159,9 +159,12 @@ class LinesYardstick
|
||||
0
|
||||
|
||||
leftPixelPositionForCharInTextNode: (lineNode, textNode, charIndex) ->
|
||||
@rangeForMeasurement.setStart(textNode, 0)
|
||||
@rangeForMeasurement.setEnd(textNode, charIndex)
|
||||
width = @rangeForMeasurement.getBoundingClientRect().width
|
||||
if charIndex is 0
|
||||
width = 0
|
||||
else
|
||||
@rangeForMeasurement.setStart(textNode, 0)
|
||||
@rangeForMeasurement.setEnd(textNode, charIndex)
|
||||
width = @rangeForMeasurement.getBoundingClientRect().width
|
||||
|
||||
@rangeForMeasurement.setStart(textNode, 0)
|
||||
@rangeForMeasurement.setEnd(textNode, textNode.textContent.length)
|
||||
|
||||
101
src/native-compile-cache.js
Normal file
101
src/native-compile-cache.js
Normal file
@@ -0,0 +1,101 @@
|
||||
'use strict'
|
||||
|
||||
const Module = require('module')
|
||||
const path = require('path')
|
||||
const cachedVm = require('cached-run-in-this-context')
|
||||
|
||||
class NativeCompileCache {
|
||||
constructor () {
|
||||
this.cacheStore = null
|
||||
this.previousModuleCompile = null
|
||||
}
|
||||
|
||||
setCacheStore (store) {
|
||||
this.cacheStore = store
|
||||
}
|
||||
|
||||
install () {
|
||||
this.savePreviousModuleCompile()
|
||||
this.overrideModuleCompile()
|
||||
}
|
||||
|
||||
uninstall () {
|
||||
this.restorePreviousModuleCompile()
|
||||
}
|
||||
|
||||
savePreviousModuleCompile () {
|
||||
this.previousModuleCompile = Module.prototype._compile
|
||||
}
|
||||
|
||||
overrideModuleCompile () {
|
||||
let cacheStore = this.cacheStore
|
||||
let resolvedArgv = null
|
||||
// Here we override Node's module.js
|
||||
// (https://github.com/atom/node/blob/atom/lib/module.js#L378), changing
|
||||
// only the bits that affect compilation in order to use the cached one.
|
||||
Module.prototype._compile = function (content, filename) {
|
||||
let self = this
|
||||
// remove shebang
|
||||
content = content.replace(/^\#\!.*/, '')
|
||||
function require (path) {
|
||||
return self.require(path)
|
||||
}
|
||||
require.resolve = function (request) {
|
||||
return Module._resolveFilename(request, self)
|
||||
}
|
||||
require.main = process.mainModule
|
||||
|
||||
// Enable support to add extra extension types
|
||||
require.extensions = Module._extensions
|
||||
require.cache = Module._cache
|
||||
|
||||
let dirname = path.dirname(filename)
|
||||
|
||||
// create wrapper function
|
||||
let wrapper = Module.wrap(content)
|
||||
|
||||
let compiledWrapper = null
|
||||
if (cacheStore.has(filename)) {
|
||||
let buffer = cacheStore.get(filename)
|
||||
let compilationResult = cachedVm.runInThisContextCached(wrapper, filename, buffer)
|
||||
compiledWrapper = compilationResult.result
|
||||
if (compilationResult.wasRejected) {
|
||||
cacheStore.delete(filename)
|
||||
}
|
||||
} else {
|
||||
let compilationResult = cachedVm.runInThisContext(wrapper, filename)
|
||||
if (compilationResult.cacheBuffer) {
|
||||
cacheStore.set(filename, compilationResult.cacheBuffer)
|
||||
}
|
||||
compiledWrapper = compilationResult.result
|
||||
}
|
||||
if (global.v8debug) {
|
||||
if (!resolvedArgv) {
|
||||
// we enter the repl if we're not given a filename argument.
|
||||
if (process.argv[1]) {
|
||||
resolvedArgv = Module._resolveFilename(process.argv[1], null)
|
||||
} else {
|
||||
resolvedArgv = 'repl'
|
||||
}
|
||||
}
|
||||
|
||||
// Set breakpoint on module start
|
||||
if (filename === resolvedArgv) {
|
||||
// Installing this dummy debug event listener tells V8 to start
|
||||
// the debugger. Without it, the setBreakPoint() fails with an
|
||||
// 'illegal access' error.
|
||||
global.v8debug.Debug.setListener(function () {})
|
||||
global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0)
|
||||
}
|
||||
}
|
||||
let args = [self.exports, require, self, filename, dirname, process, global]
|
||||
return compiledWrapper.apply(self.exports, args)
|
||||
}
|
||||
}
|
||||
|
||||
restorePreviousModuleCompile () {
|
||||
Module.prototype._compile = this.previousModuleCompile
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new NativeCompileCache()
|
||||
@@ -467,7 +467,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"
|
||||
@notificationManager.addError(message, {stack, detail, dismissable: true})
|
||||
@notificationManager.addError(message, {stack, detail, packageName: path.basename(packagePath), dismissable: true})
|
||||
|
||||
uninstallDirectory: (directory) ->
|
||||
symlinkPromise = new Promise (resolve) ->
|
||||
|
||||
@@ -293,7 +293,7 @@ class Package
|
||||
if error?
|
||||
detail = "#{error.message} in #{grammarPath}"
|
||||
stack = "#{error.stack}\n at #{grammarPath}:1:1"
|
||||
@notificationManager.addFatalError("Failed to load a #{@name} package grammar", {stack, detail, dismissable: true})
|
||||
@notificationManager.addFatalError("Failed to load a #{@name} package grammar", {stack, detail, packageName: @name, dismissable: true})
|
||||
else
|
||||
grammar.packageName = @name
|
||||
grammar.bundledPackage = @bundledPackage
|
||||
@@ -317,7 +317,7 @@ class Package
|
||||
if error?
|
||||
detail = "#{error.message} in #{settingsPath}"
|
||||
stack = "#{error.stack}\n at #{settingsPath}:1:1"
|
||||
@notificationManager.addFatalError("Failed to load the #{@name} package settings", {stack, detail, dismissable: true})
|
||||
@notificationManager.addFatalError("Failed to load the #{@name} package settings", {stack, detail, packageName: @name, dismissable: true})
|
||||
else
|
||||
@settings.push(settings)
|
||||
settings.activate() if @settingsActivated
|
||||
@@ -634,4 +634,4 @@ class Package
|
||||
detail = error.message
|
||||
stack = error.stack ? error
|
||||
|
||||
@notificationManager.addFatalError(message, {stack, detail, dismissable: true})
|
||||
@notificationManager.addFatalError(message, {stack, detail, packageName: @name, dismissable: true})
|
||||
|
||||
@@ -573,6 +573,45 @@ class TextEditor extends Model
|
||||
else
|
||||
'untitled'
|
||||
|
||||
# Essential: Get unique title for display in other parts of the UI
|
||||
# such as the window title.
|
||||
#
|
||||
# If the editor's buffer is unsaved, its title is "untitled"
|
||||
# If the editor's buffer is saved, its unique title is formatted as one
|
||||
# of the following,
|
||||
# * "<filename>" when it is the only editing buffer with this file name.
|
||||
# * "<unique-dir-prefix>/.../<filename>", where the "..." may be omitted
|
||||
# if the the direct parent directory is already different.
|
||||
#
|
||||
# Returns a {String}
|
||||
getUniqueTitle: ->
|
||||
if sessionPath = @getPath()
|
||||
title = @getTitle()
|
||||
|
||||
# find text editors with identical file name.
|
||||
paths = []
|
||||
for textEditor in atom.workspace.getTextEditors() when textEditor isnt this
|
||||
if textEditor.getTitle() is title
|
||||
paths.push(textEditor.getPath())
|
||||
if paths.length is 0
|
||||
return title
|
||||
fileName = path.basename(sessionPath)
|
||||
|
||||
# find the first directory in all these paths that is unique
|
||||
nLevel = 0
|
||||
while (_.some(paths, (apath) -> path.basename(apath) is path.basename(sessionPath)))
|
||||
sessionPath = path.dirname(sessionPath)
|
||||
paths = _.map(paths, (apath) -> path.dirname(apath))
|
||||
nLevel += 1
|
||||
|
||||
directory = path.basename sessionPath
|
||||
if nLevel > 1
|
||||
path.join(directory, "...", fileName)
|
||||
else
|
||||
path.join(directory, fileName)
|
||||
else
|
||||
'untitled'
|
||||
|
||||
# Essential: Get the editor's long title for display in other parts of the UI
|
||||
# such as the window title.
|
||||
#
|
||||
@@ -879,6 +918,7 @@ class TextEditor extends Model
|
||||
@foldBufferRow(foldedRow)
|
||||
|
||||
@setSelectedBufferRange(selection.translate([-insertDelta]), preserveFolds: true, autoscroll: true)
|
||||
@autoIndentSelectedRows() if @shouldAutoIndent()
|
||||
|
||||
# Move lines intersecting the most recent selection down by one row in screen
|
||||
# coordinates.
|
||||
@@ -935,6 +975,7 @@ class TextEditor extends Model
|
||||
@foldBufferRow(foldedRow)
|
||||
|
||||
@setSelectedBufferRange(selection.translate([insertDelta]), preserveFolds: true, autoscroll: true)
|
||||
@autoIndentSelectedRows() if @shouldAutoIndent()
|
||||
|
||||
# Duplicate the most recent cursor's current line.
|
||||
duplicateLines: ->
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
(function () {
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var FileSystemBlobStore = require('../src/file-system-blob-store')
|
||||
var NativeCompileCache = require('../src/native-compile-cache')
|
||||
|
||||
var loadSettings = null
|
||||
var loadSettingsError = null
|
||||
var blobStore = null
|
||||
|
||||
window.onload = function () {
|
||||
try {
|
||||
@@ -13,8 +15,11 @@
|
||||
console.error('Unhandled promise rejection %o with error: %o', promise, error)
|
||||
})
|
||||
|
||||
// Ensure ATOM_HOME is always set before anything else is required
|
||||
setupAtomHome()
|
||||
blobStore = FileSystemBlobStore.load(
|
||||
path.join(process.env.ATOM_HOME, 'blob-store/')
|
||||
)
|
||||
NativeCompileCache.setCacheStore(blobStore)
|
||||
NativeCompileCache.install()
|
||||
|
||||
// Normalize to make sure drive letter case is consistent on Windows
|
||||
process.resourcesPath = path.normalize(process.resourcesPath)
|
||||
@@ -76,28 +81,11 @@
|
||||
setupVmCompatibility()
|
||||
setupCsonCache(CompileCache.getCacheDirectory())
|
||||
|
||||
require(loadSettings.windowInitializationScript)
|
||||
var initialize = require(loadSettings.windowInitializationScript)
|
||||
initialize({blobStore: blobStore})
|
||||
require('ipc').sendChannel('window-command', 'window:loaded')
|
||||
}
|
||||
|
||||
function setupAtomHome () {
|
||||
if (!process.env.ATOM_HOME) {
|
||||
var home
|
||||
if (process.platform === 'win32') {
|
||||
home = process.env.USERPROFILE
|
||||
} else {
|
||||
home = process.env.HOME
|
||||
}
|
||||
var atomHome = path.join(home, '.atom')
|
||||
try {
|
||||
atomHome = fs.realpathSync(atomHome)
|
||||
} catch (error) {
|
||||
// Ignore since the path might just not exist yet.
|
||||
}
|
||||
process.env.ATOM_HOME = atomHome
|
||||
}
|
||||
}
|
||||
|
||||
function setupCsonCache (cacheDir) {
|
||||
require('season').setCacheDir(path.join(cacheDir, 'cson'))
|
||||
}
|
||||
@@ -181,6 +169,20 @@
|
||||
}, false)
|
||||
}
|
||||
|
||||
var setupAtomHome = function () {
|
||||
if (process.env.ATOM_HOME) {
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure ATOM_HOME is always set before anything else is required
|
||||
// This is because of a difference in Linux not inherited between browser and render processes
|
||||
// https://github.com/atom/atom/issues/5412
|
||||
if (loadSettings && loadSettings.atomHome) {
|
||||
process.env.ATOM_HOME = loadSettings.atomHome
|
||||
}
|
||||
}
|
||||
|
||||
parseLoadSettings()
|
||||
setupAtomHome()
|
||||
setupWindowBackground()
|
||||
})()
|
||||
|
||||
Reference in New Issue
Block a user