Merge branch 'master' into as-ns-startup-snapshot

This commit is contained in:
Antonio Scandurra 2017-03-16 10:52:34 +01:00
commit a8b885c4d5
11 changed files with 121 additions and 77 deletions

View File

@ -137,6 +137,7 @@
{ label: 'Open In &Dev Mode…', command: 'application:open-dev' }
{ label: '&Reload Window', command: 'window:reload' }
{ label: 'Run Package &Specs', command: 'window:run-package-specs' }
{ label: 'Run &Benchmarks', command: 'window:run-benchmarks' }
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
]
}

View File

@ -136,6 +136,7 @@
{ label: 'Open In &Dev Mode…', command: 'application:open-dev' }
{ label: '&Reload Window', command: 'window:reload' }
{ label: 'Run Package &Specs', command: 'window:run-package-specs' }
{ label: 'Run &Benchmarks', command: 'window:run-benchmarks' }
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
]
}

View File

@ -67,12 +67,12 @@
"random-words": "0.0.1",
"resolve": "^1.1.6",
"runas": "^3.1",
"scandal": "^3.0.0",
"scandal": "^3.1.0",
"scoped-property-store": "^0.17.0",
"scrollbar-style": "^3.2",
"season": "^6.0.0",
"semver": "^4.3.3",
"service-hub": "^0.7.2",
"service-hub": "^0.7.3",
"sinon": "1.17.4",
"source-map-support": "^0.3.2",
"temp": "0.8.1",
@ -97,10 +97,10 @@
"solarized-light-syntax": "1.1.2",
"about": "1.7.5",
"archive-view": "0.63.1",
"autocomplete-atom-api": "0.10.0",
"autocomplete-css": "0.15.1",
"autocomplete-html": "0.7.2",
"autocomplete-plus": "2.34.2",
"autocomplete-atom-api": "0.10.1",
"autocomplete-css": "0.15.2",
"autocomplete-html": "0.7.3",
"autocomplete-plus": "2.35.0",
"autocomplete-snippets": "1.11.0",
"autoflow": "0.29.0",
"autosave": "0.24.1",
@ -119,7 +119,7 @@
"go-to-line": "0.32.0",
"grammar-selector": "0.49.3",
"image-view": "0.61.2",
"incompatible-packages": "0.27.1",
"incompatible-packages": "0.27.2",
"keybinding-resolver": "0.36.4",
"line-ending-selector": "0.6.2",
"link": "0.31.3",

View File

@ -10,7 +10,7 @@ const spawnSync = require('./spawn-sync')
const CONFIG = require('../config')
module.exports = function (packagedAppPath, codeSign) {
module.exports = (packagedAppPath, codeSign) => {
const archSuffix = process.arch === 'ia32' ? '' : '-' + process.arch
const options = {
appDirectory: packagedAppPath,
@ -23,7 +23,7 @@ module.exports = function (packagedAppPath, codeSign) {
}
const signing = codeSign && (process.env.ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL || process.env.ATOM_WIN_CODE_SIGNING_CERT_PATH)
let certPath = process.env.ATOM_WIN_CODE_SIGNING_CERT_PATH;
let certPath = process.env.ATOM_WIN_CODE_SIGNING_CERT_PATH
if (signing) {
if (!certPath) {
@ -42,7 +42,7 @@ module.exports = function (packagedAppPath, codeSign) {
console.log('Skipping code-signing. Specify the --code-sign option and provide a ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL environment variable to perform code-signing'.gray)
}
const cleanUp = function () {
const cleanUp = () => {
if (fs.existsSync(certPath) && !process.env.ATOM_WIN_CODE_SIGNING_CERT_PATH) {
console.log(`Deleting certificate at ${certPath}`)
fs.removeSync(certPath)
@ -57,7 +57,7 @@ module.exports = function (packagedAppPath, codeSign) {
}
// Squirrel signs its own copy of the executables but we need them for the portable ZIP
const extractSignedExes = function() {
const extractSignedExes = () => {
if (signing) {
for (let nupkgPath of glob.sync(`${CONFIG.buildOutputPath}/*-full.nupkg`)) {
if (nupkgPath.includes(CONFIG.appMetadata.version)) {
@ -73,12 +73,9 @@ module.exports = function (packagedAppPath, codeSign) {
console.log(`Creating Windows Installer for ${packagedAppPath}`)
return electronInstaller.createWindowsInstaller(options)
.then(extractSignedExes, function (error) {
console.log(`Extracting signed executables failed:\n${error}`)
cleanUp()
})
.then(cleanUp, function (error) {
console.log(`Windows installer creation failed:\n${error}`)
.then(extractSignedExes)
.then(cleanUp, error => {
cleanUp()
return Promise.reject(error)
})
}

View File

@ -5,7 +5,7 @@ const path = require('path')
const syncRequest = require('sync-request')
module.exports = function (downloadURL, destinationPath) {
console.log(`Dowloading file from GitHub Repository to ${destinationPath}`)
console.log(`Downloading file from GitHub Repository to ${destinationPath}`)
const response = syncRequest('GET', downloadURL, {
'headers': {'Accept': 'application/vnd.github.v3.raw', 'User-Agent': 'Atom Build'}
})

View File

@ -4868,8 +4868,8 @@ describe "TextEditor", ->
editor.replaceSelectedText {}, -> '123'
expect(buffer.lineForRow(0)).toBe '123var quicksort = function () {'
editor.replaceSelectedText {selectWordIfEmpty: true}, -> 'var'
editor.setCursorBufferPosition([0])
editor.replaceSelectedText {selectWordIfEmpty: true}, -> 'var'
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {'
editor.setCursorBufferPosition([10])
@ -4882,6 +4882,12 @@ describe "TextEditor", ->
editor.replaceSelectedText {}, -> 'ia'
expect(buffer.lineForRow(0)).toBe 'via quicksort = function () {'
it "replaces the selected text and selects the replacement text", ->
editor.setSelectedBufferRange([[0, 4], [0, 9]])
editor.replaceSelectedText {}, -> 'whatnot'
expect(buffer.lineForRow(0)).toBe 'var whatnotsort = function () {'
expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [0, 11]]
describe ".transpose()", ->
it "swaps two characters", ->
editor.buffer.setText("abc")
@ -4902,7 +4908,7 @@ describe "TextEditor", ->
editor.setCursorScreenPosition([0, 1])
editor.upperCase()
expect(editor.lineTextForBufferRow(0)).toBe 'ABC'
expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]]
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 3]]
describe "when there is a selection", ->
it "upper cases the current selection", ->
@ -4919,7 +4925,7 @@ describe "TextEditor", ->
editor.setCursorScreenPosition([0, 1])
editor.lowerCase()
expect(editor.lineTextForBufferRow(0)).toBe 'abc'
expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]]
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 3]]
describe "when there is a selection", ->
it "lower cases the current selection", ->

View File

@ -1336,7 +1336,9 @@ i = /test/; #FIXME\
it('calls the callback with all regex results in all files in the project', () => {
const results = []
waitsForPromise(() =>
atom.workspace.scan(/(a)+/, result => results.push(result))
atom.workspace.scan(
/(a)+/, {leadingContextLineCount: 1, trailingContextLineCount: 1},
result => results.push(result))
)
runs(() => {
@ -1349,14 +1351,16 @@ i = /test/; #FIXME\
lineTextOffset: 0,
range: [[0, 0], [0, 3]],
leadingContextLines: [],
trailingContextLines: []
trailingContextLines: ['cc aa cc']
})
})
})
it('works with with escaped literals (like $ and ^)', () => {
const results = []
waitsForPromise(() => atom.workspace.scan(/\$\w+/, result => results.push(result)))
waitsForPromise(() => atom.workspace.scan(
/\$\w+/, {leadingContextLineCount: 1, trailingContextLineCount: 1},
result => results.push(result)))
runs(() => {
expect(results.length).toBe(1)
@ -1368,7 +1372,7 @@ i = /test/; #FIXME\
lineText: 'dollar$bill',
lineTextOffset: 0,
range: [[2, 6], [2, 11]],
leadingContextLines: [],
leadingContextLines: ['cc aa cc'],
trailingContextLines: []
})
})

View File

@ -11,13 +11,16 @@ class DirectorySearch
excludeVcsIgnores: options.excludeVcsIgnores
globalExclusions: options.exclusions
follow: options.follow
searchOptions =
leadingContextLineCount: options.leadingContextLineCount
trailingContextLineCount: options.trailingContextLineCount
@task = new Task(require.resolve('./scan-handler'))
@task.on 'scan:result-found', options.didMatch
@task.on 'scan:file-error', options.didError
@task.on 'scan:paths-searched', options.didSearchPaths
@promise = new Promise (resolve, reject) =>
@task.on('task:cancelled', reject)
@task.start rootPaths, regex.source, scanHandlerOptions, =>
@task.start rootPaths, regex.source, scanHandlerOptions, searchOptions, =>
@task.terminate()
resolve()

View File

@ -2,13 +2,13 @@ path = require "path"
async = require "async"
{PathSearcher, PathScanner, search} = require 'scandal'
module.exports = (rootPaths, regexSource, options) ->
module.exports = (rootPaths, regexSource, options, searchOptions={}) ->
callback = @async()
PATHS_COUNTER_SEARCHED_CHUNK = 50
pathsSearched = 0
searcher = new PathSearcher()
searcher = new PathSearcher(searchOptions)
searcher.on 'file-error', ({code, path, message}) ->
emit('scan:file-error', {code, path, message})

View File

@ -1328,12 +1328,12 @@ class TextEditor extends Model
replaceSelectedText: (options={}, fn) ->
{selectWordIfEmpty} = options
@mutateSelectedText (selection) ->
range = selection.getBufferRange()
selection.getBufferRange()
if selectWordIfEmpty and selection.isEmpty()
selection.selectWord()
text = selection.getText()
selection.deleteSelectedText()
selection.insertText(fn(text))
range = selection.insertText(fn(text))
selection.setBufferRange(range)
# Split multi-line selections into one selection per line.
@ -2826,6 +2826,11 @@ class TextEditor extends Model
# {::backwardsScanInBufferRange} to avoid tripping over your own changes.
#
# * `regex` A {RegExp} to search for.
# * `options` (optional) {Object}
# * `leadingContextLineCount` {Number} default `0`; The number of lines
# before the matched line to include in the results object.
# * `trailingContextLineCount` {Number} default `0`; The number of lines
# after the matched line to include in the results object.
# * `iterator` A {Function} that's called on each match
# * `object` {Object}
# * `match` The current regular expression match.
@ -2833,7 +2838,12 @@ class TextEditor extends Model
# * `range` The {Range} of the match.
# * `stop` Call this {Function} to terminate the scan.
# * `replace` Call this {Function} with a {String} to replace the match.
scan: (regex, iterator) -> @buffer.scan(regex, iterator)
scan: (regex, options={}, iterator) ->
if _.isFunction(options)
iterator = options
options = {}
@buffer.scan(regex, options, iterator)
# Essential: Scan regular expression matches in a given range, calling the given
# iterator function on each match.

View File

@ -511,9 +511,8 @@ module.exports = class Workspace extends Model {
//
// Returns a {Promise} that resolves to the {TextEditor} for the file URI.
open (uri_, options = {}) {
const { searchAllPanes } = options
const { split } = options
const uri = this.project.resolvePath(uri_)
const {searchAllPanes, split} = options
if (!atom.config.get('core.allowPendingPaneItems')) {
options.pending = false
@ -526,7 +525,7 @@ module.exports = class Workspace extends Model {
}
let pane
if (searchAllPanes) { pane = this.paneContainer.paneForURI(uri) }
if (searchAllPanes) { pane = this.paneForURI(uri) }
if (pane == null) {
switch (split) {
case 'left':
@ -547,7 +546,16 @@ module.exports = class Workspace extends Model {
}
}
return this.openURIInPane(uri, pane, options)
let item
if (uri != null) {
item = pane.itemForURI(uri)
}
if (item == null) {
item = this.createItemForURI(uri, options)
}
return Promise.resolve(item)
.then(item => this.openItem(item, Object.assign({pane, uri}, options)))
}
// Open Atom's license in the active pane.
@ -597,26 +605,28 @@ module.exports = class Workspace extends Model {
}
openURIInPane (uri, pane, options = {}) {
const activatePane = options.activatePane != null ? options.activatePane : true
const activateItem = options.activateItem != null ? options.activateItem : true
let item
if (uri != null) {
item = pane.itemForURI(uri)
if (item == null) {
for (let opener of this.getOpeners()) {
item = opener(uri, options)
if (item != null) break
}
} else if (!options.pending && (pane.getPendingItem() === item)) {
pane.clearPendingItem()
}
if (item == null) {
item = this.createItemForURI(uri, options)
}
return Promise.resolve(item)
.then(item => this.openItem(item, Object.assign({pane, uri}, options)))
}
// Returns a {Promise} that resolves to the {TextEditor} (or other item) for the given URI.
createItemForURI (uri, options) {
if (uri != null) {
for (let opener of this.getOpeners()) {
const item = opener(uri, options)
if (item != null) return Promise.resolve(item)
}
}
try {
if (item == null) {
item = this.openTextFile(uri, options)
}
return this.openTextFile(uri, options)
} catch (error) {
switch (error.code) {
case 'CANCELLED':
@ -644,40 +654,46 @@ module.exports = class Workspace extends Model {
throw error
}
}
}
return Promise.resolve(item)
.then(item => {
let initialColumn
if (pane.isDestroyed()) {
return item
}
openItem (item, options = {}) {
const {pane} = options
this.itemOpened(item)
if (activateItem) {
pane.activateItem(item, {pending: options.pending})
}
if (activatePane) {
pane.activate()
}
if (item == null) return undefined
if (pane.isDestroyed()) return item
let initialLine = initialColumn = 0
if (!Number.isNaN(options.initialLine)) {
initialLine = options.initialLine
}
if (!Number.isNaN(options.initialColumn)) {
initialColumn = options.initialColumn
}
if ((initialLine >= 0) || (initialColumn >= 0)) {
if (typeof item.setCursorBufferPosition === 'function') {
item.setCursorBufferPosition([initialLine, initialColumn])
}
}
if (!options.pending && (pane.getPendingItem() === item)) {
pane.clearPendingItem()
}
const index = pane.getActiveItemIndex()
this.emitter.emit('did-open', {uri, pane, item, index})
return item
const activatePane = options.activatePane != null ? options.activatePane : true
const activateItem = options.activateItem != null ? options.activateItem : true
this.itemOpened(item)
if (activateItem) {
pane.activateItem(item, {pending: options.pending})
}
if (activatePane) {
pane.activate()
}
let initialColumn = 0
let initialLine = 0
if (!Number.isNaN(options.initialLine)) {
initialLine = options.initialLine
}
if (!Number.isNaN(options.initialColumn)) {
initialColumn = options.initialColumn
}
if ((initialLine >= 0) || (initialColumn >= 0)) {
if (typeof item.setCursorBufferPosition === 'function') {
item.setCursorBufferPosition([initialLine, initialColumn])
}
)
}
const index = pane.getActiveItemIndex()
const uri = options.uri == null && typeof item.getURI === 'function' ? item.getURI() : options.uri
this.emitter.emit('did-open', {uri, pane, item, index})
return item
}
openTextFile (uri, options) {
@ -1186,6 +1202,10 @@ module.exports = class Workspace extends Model {
// * `paths` An {Array} of glob patterns to search within.
// * `onPathsSearched` (optional) {Function} to be periodically called
// with number of paths searched.
// * `leadingContextLineCount` {Number} default `0`; The number of lines
// before the matched line to include in the results object.
// * `trailingContextLineCount` {Number} default `0`; The number of lines
// after the matched line to include in the results object.
// * `iterator` {Function} callback on each file found.
//
// Returns a {Promise} with a `cancel()` method that will cancel all
@ -1245,6 +1265,8 @@ module.exports = class Workspace extends Model {
excludeVcsIgnores: this.config.get('core.excludeVcsIgnoredPaths'),
exclusions: this.config.get('core.ignoredNames'),
follow: this.config.get('core.followSymlinks'),
leadingContextLineCount: options.leadingContextLineCount || 0,
trailingContextLineCount: options.trailingContextLineCount || 0,
didMatch: result => {
if (!this.project.isPathModified(result.filePath)) {
return iterator(result)