mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-10 10:17:11 +03:00
Merge branch 'master' into as-block-decorations
This commit is contained in:
commit
f81843d465
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,18 +1 @@
|
||||
See https://atom.io/releases
|
||||
|
||||
## 1.4.0
|
||||
|
||||
* Switching encoding is now fast also with large files.
|
||||
* Fixed an issue where disabling and re-enabling a package caused custom keymaps to be overridden.
|
||||
* Fixed restoring untitled editors on restart. The new behavior never prompts to save new/changed files when closing a window or quitting Atom.
|
||||
|
||||
## 1.3.0
|
||||
|
||||
* The tree-view now sorts directory entries more naturally, in a locale-sensitive way.
|
||||
* Lines can now be moved up and down with multiple cursors.
|
||||
* Improved the performance of marker-dependent code paths such as spell-check and find and replace.
|
||||
* Fixed copying and pasting in native input fields.
|
||||
* By default, windows with no pane items are now closed via the `core:close` command. The previous behavior can be restored via the `Close Empty Windows` option in settings.
|
||||
* Fixed an issue where characters were inserted when toggling the settings view on some keyboard layouts.
|
||||
* Modules can now temporarily override `Error.prepareStackTrace`. There is also an `Error.prototype.getRawStack()` method if you just need access to the raw v8 trace structure.
|
||||
* Fixed a problem that caused blurry fonts on monitors that have a slightly higher resolution than 96 DPI.
|
||||
|
@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "1.5.0"
|
||||
"atom-package-manager": "1.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ _ = require 'underscore-plus'
|
||||
packageJson = require '../package.json'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
require('time-grunt')(grunt)
|
||||
|
||||
grunt.loadNpmTasks('grunt-babel')
|
||||
grunt.loadNpmTasks('grunt-coffeelint')
|
||||
grunt.loadNpmTasks('grunt-lesslint')
|
||||
@ -36,7 +38,6 @@ module.exports = (grunt) ->
|
||||
buildDir = grunt.option('build-dir')
|
||||
buildDir ?= path.join(os.tmpdir(), 'atom-build')
|
||||
buildDir = path.resolve(buildDir)
|
||||
disableAutoUpdate = grunt.option('no-auto-update') ? false
|
||||
|
||||
channel = grunt.option('channel')
|
||||
releasableBranches = ['stable', 'beta']
|
||||
@ -179,7 +180,7 @@ module.exports = (grunt) ->
|
||||
pkg: grunt.file.readJSON('package.json')
|
||||
|
||||
atom: {
|
||||
appName, channel, metadata, disableAutoUpdate,
|
||||
appName, channel, metadata,
|
||||
appFileName, apmFileName,
|
||||
appDir, buildDir, contentsDir, installDir, shellAppDir, symbolsDir,
|
||||
}
|
||||
@ -255,7 +256,7 @@ module.exports = (grunt) ->
|
||||
outputDir: 'electron'
|
||||
downloadDir: electronDownloadDir
|
||||
rebuild: true # rebuild native modules after electron is updated
|
||||
token: process.env.ATOM_ACCESS_TOKEN
|
||||
token: process.env.ATOM_ACCESS_TOKEN ? 'da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4'
|
||||
|
||||
'create-windows-installer':
|
||||
installer:
|
||||
|
@ -37,6 +37,7 @@
|
||||
"runas": "^3.1",
|
||||
"tello": "1.0.5",
|
||||
"temp": "~0.8.1",
|
||||
"time-grunt": "1.2.2",
|
||||
"underscore-plus": "1.x",
|
||||
"unzip": "~0.1.9",
|
||||
"vm-compatibility-layer": "~0.1.0",
|
||||
|
@ -186,5 +186,4 @@ module.exports = (grunt) ->
|
||||
dependencies = ['compile', 'generate-license:save', 'generate-module-cache', 'compile-packages-slug']
|
||||
dependencies.push('copy-info-plist') if process.platform is 'darwin'
|
||||
dependencies.push('set-exe-icon') if process.platform is 'win32'
|
||||
dependencies.push('disable-autoupdate') if grunt.config.get('atom.disableAutoUpdate')
|
||||
grunt.task.run(dependencies...)
|
||||
|
@ -1,12 +0,0 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
|
||||
grunt.registerTask 'disable-autoupdate', 'Set up disableAutoUpdate field in package.json file', ->
|
||||
appDir = fs.realpathSync(grunt.config.get('atom.appDir'))
|
||||
|
||||
metadata = grunt.file.readJSON(path.join(appDir, 'package.json'))
|
||||
metadata._disableAutoUpdate = grunt.config.get('atom.disableAutoUpdate')
|
||||
|
||||
grunt.file.write(path.join(appDir, 'package.json'), JSON.stringify(metadata))
|
5
dot-atom/.gitignore
vendored
5
dot-atom/.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
storage
|
||||
blob-store
|
||||
compile-cache
|
||||
dev
|
||||
.npm
|
||||
storage
|
||||
.node-gyp
|
||||
.npm
|
||||
|
@ -13,7 +13,7 @@
|
||||
'ctrl-alt-o': 'application:add-project-folder'
|
||||
'ctrl-shift-pageup': 'pane:move-item-left'
|
||||
'ctrl-shift-pagedown': 'pane:move-item-right'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
'f11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-,': 'application:show-settings'
|
||||
|
@ -19,7 +19,7 @@
|
||||
'ctrl-alt-o': 'application:add-project-folder'
|
||||
'ctrl-shift-left': 'pane:move-item-left'
|
||||
'ctrl-shift-right': 'pane:move-item-right'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
'f11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-,': 'application:show-settings'
|
||||
|
@ -110,36 +110,9 @@
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Selection'
|
||||
submenu: [
|
||||
{ label: 'Add Selection Above', command: 'editor:add-selection-above' }
|
||||
{ label: 'Add Selection Below', command: 'editor:add-selection-below' }
|
||||
{ label: 'Single Selection', command: 'editor:consolidate-selections'}
|
||||
{ label: 'Split into Lines', command: 'editor:split-selections-into-lines'}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select to Top', command: 'core:select-to-top' }
|
||||
{ label: 'Select to Bottom', command: 'core:select-to-bottom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select Line', command: 'editor:select-line' }
|
||||
{ label: 'Select Word', command: 'editor:select-word' }
|
||||
{ label: 'Select to Beginning of Word', command: 'editor:select-to-beginning-of-word' }
|
||||
{ label: 'Select to Beginning of Line', command: 'editor:select-to-beginning-of-line' }
|
||||
{ label: 'Select to First Character of Line', command: 'editor:select-to-first-character-of-line' }
|
||||
{ label: 'Select to End of Word', command: 'editor:select-to-end-of-word' }
|
||||
{ label: 'Select to End of Line', command: 'editor:select-to-end-of-line' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Find'
|
||||
submenu: []
|
||||
}
|
||||
|
||||
{
|
||||
label: 'View'
|
||||
submenu: [
|
||||
{ label: 'Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle Full Screen', command: 'window:toggle-full-screen' }
|
||||
{
|
||||
label: 'Panes'
|
||||
@ -164,6 +137,7 @@
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ 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: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
@ -177,6 +151,32 @@
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Selection'
|
||||
submenu: [
|
||||
{ label: 'Add Selection Above', command: 'editor:add-selection-above' }
|
||||
{ label: 'Add Selection Below', command: 'editor:add-selection-below' }
|
||||
{ label: 'Single Selection', command: 'editor:consolidate-selections'}
|
||||
{ label: 'Split into Lines', command: 'editor:split-selections-into-lines'}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select to Top', command: 'core:select-to-top' }
|
||||
{ label: 'Select to Bottom', command: 'core:select-to-bottom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select Line', command: 'editor:select-line' }
|
||||
{ label: 'Select Word', command: 'editor:select-word' }
|
||||
{ label: 'Select to Beginning of Word', command: 'editor:select-to-beginning-of-word' }
|
||||
{ label: 'Select to Beginning of Line', command: 'editor:select-to-beginning-of-line' }
|
||||
{ label: 'Select to First Character of Line', command: 'editor:select-to-first-character-of-line' }
|
||||
{ label: 'Select to End of Word', command: 'editor:select-to-end-of-word' }
|
||||
{ label: 'Select to End of Line', command: 'editor:select-to-end-of-line' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Find'
|
||||
submenu: []
|
||||
}
|
||||
|
||||
{
|
||||
label: 'Packages'
|
||||
submenu: []
|
||||
|
@ -95,7 +95,6 @@
|
||||
{
|
||||
label: '&View'
|
||||
submenu: [
|
||||
{ label: '&Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' }
|
||||
{ label: 'Toggle Menu Bar', command: 'window:toggle-menu-bar' }
|
||||
{
|
||||
@ -121,6 +120,7 @@
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ 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: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
|
@ -94,7 +94,6 @@
|
||||
{
|
||||
label: '&View'
|
||||
submenu: [
|
||||
{ label: '&Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' }
|
||||
{ label: 'Toggle Menu Bar', command: 'window:toggle-menu-bar' }
|
||||
{
|
||||
@ -120,6 +119,7 @@
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ 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: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
|
41
package.json
41
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "1.5.0-dev",
|
||||
"version": "1.6.0-dev",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@ -22,17 +22,17 @@
|
||||
"clear-cut": "^2.0.1",
|
||||
"coffee-script": "1.8.0",
|
||||
"color": "^0.7.3",
|
||||
"event-kit": "^1.3.0",
|
||||
"event-kit": "^1.5.0",
|
||||
"find-parent-dir": "^0.3.0",
|
||||
"first-mate": "^5.1.1",
|
||||
"fs-plus": "^2.8.0",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"git-utils": "^4.0.7",
|
||||
"git-utils": "^4.1.0",
|
||||
"grim": "1.5.0",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.4",
|
||||
"jquery": "^2.1.1",
|
||||
"jquery": "2.1.4",
|
||||
"key-path-helpers": "^0.4.0",
|
||||
"less-cache": "0.22",
|
||||
"line-top-index": "0.2.0",
|
||||
@ -53,7 +53,7 @@
|
||||
"service-hub": "^0.7.0",
|
||||
"source-map-support": "^0.3.2",
|
||||
"temp": "0.8.1",
|
||||
"text-buffer": "8.1.3",
|
||||
"text-buffer": "8.1.4",
|
||||
"typescript-simple": "1.0.0",
|
||||
"underscore-plus": "^1.6.6",
|
||||
"yargs": "^3.23.0"
|
||||
@ -66,12 +66,12 @@
|
||||
"base16-tomorrow-dark-theme": "1.1.0",
|
||||
"base16-tomorrow-light-theme": "1.1.1",
|
||||
"one-dark-ui": "1.1.9",
|
||||
"one-dark-syntax": "1.1.1",
|
||||
"one-light-syntax": "1.1.1",
|
||||
"one-light-ui": "1.1.9",
|
||||
"one-dark-syntax": "1.1.2",
|
||||
"one-light-syntax": "1.1.2",
|
||||
"solarized-dark-syntax": "0.39.0",
|
||||
"solarized-light-syntax": "0.23.0",
|
||||
"about": "1.1.0",
|
||||
"about": "1.3.0",
|
||||
"archive-view": "0.61.0",
|
||||
"autocomplete-atom-api": "0.9.2",
|
||||
"autocomplete-css": "0.11.0",
|
||||
@ -103,16 +103,15 @@
|
||||
"notifications": "0.62.1",
|
||||
"open-on-github": "0.40.0",
|
||||
"package-generator": "0.41.0",
|
||||
"release-notes": "0.53.0",
|
||||
"settings-view": "0.232.1",
|
||||
"settings-view": "0.232.3",
|
||||
"snippets": "1.0.1",
|
||||
"spell-check": "0.63.0",
|
||||
"spell-check": "0.65.0",
|
||||
"status-bar": "0.80.0",
|
||||
"styleguide": "0.45.0",
|
||||
"symbols-view": "0.110.1",
|
||||
"tabs": "0.88.0",
|
||||
"timecop": "0.33.0",
|
||||
"tree-view": "0.198.0",
|
||||
"tree-view": "0.198.1",
|
||||
"update-package-dependencies": "0.10.0",
|
||||
"welcome": "0.33.0",
|
||||
"whitespace": "0.32.1",
|
||||
@ -122,24 +121,24 @@
|
||||
"language-coffee-script": "0.46.0",
|
||||
"language-csharp": "0.11.0",
|
||||
"language-css": "0.36.0",
|
||||
"language-gfm": "0.82.0",
|
||||
"language-gfm": "0.83.0",
|
||||
"language-git": "0.11.0",
|
||||
"language-go": "0.41.0",
|
||||
"language-html": "0.43.1",
|
||||
"language-go": "0.42.0",
|
||||
"language-html": "0.44.0",
|
||||
"language-hyperlink": "0.16.0",
|
||||
"language-java": "0.17.0",
|
||||
"language-javascript": "0.104.0",
|
||||
"language-json": "0.17.2",
|
||||
"language-javascript": "0.105.0",
|
||||
"language-json": "0.17.3",
|
||||
"language-less": "0.29.0",
|
||||
"language-make": "0.21.0",
|
||||
"language-mustache": "0.13.0",
|
||||
"language-objective-c": "0.15.1",
|
||||
"language-perl": "0.32.0",
|
||||
"language-php": "0.34.0",
|
||||
"language-php": "0.36.0",
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.42.1",
|
||||
"language-ruby": "0.65.0",
|
||||
"language-ruby-on-rails": "0.24.0",
|
||||
"language-python": "0.43.0",
|
||||
"language-ruby": "0.68.0",
|
||||
"language-ruby-on-rails": "0.25.0",
|
||||
"language-sass": "0.45.0",
|
||||
"language-shellscript": "0.21.0",
|
||||
"language-source": "0.9.0",
|
||||
|
@ -5,8 +5,16 @@ var verifyRequirements = require('./utils/verify-requirements');
|
||||
var safeExec = require('./utils/child-process-wrapper.js').safeExec;
|
||||
var path = require('path');
|
||||
|
||||
var t0, t1
|
||||
|
||||
// Executes an array of commands one by one.
|
||||
function executeCommands(commands, done, index) {
|
||||
if (index != undefined) {
|
||||
t1 = Date.now()
|
||||
console.log("=> Took " + (t1 - t0) + "ms.");
|
||||
console.log();
|
||||
}
|
||||
|
||||
index = (index == undefined ? 0 : index);
|
||||
if (index < commands.length) {
|
||||
var command = commands[index];
|
||||
@ -17,6 +25,7 @@ function executeCommands(commands, done, index) {
|
||||
options = command.options;
|
||||
command = command.command;
|
||||
}
|
||||
t0 = Date.now()
|
||||
safeExec(command, options, executeCommands.bind(this, commands, done, index + 1));
|
||||
}
|
||||
else
|
||||
@ -96,7 +105,10 @@ function bootstrap() {
|
||||
message: 'Installing apm...',
|
||||
options: apmInstallOptions
|
||||
},
|
||||
apmPath + ' clean' + apmFlags,
|
||||
{
|
||||
command: apmPath + ' clean' + apmFlags,
|
||||
message: 'Deleting old packages...'
|
||||
},
|
||||
moduleInstallCommand,
|
||||
dedupeApmCommand + ' ' + packagesToDedupe.join(' '),
|
||||
];
|
||||
|
@ -1,4 +1,26 @@
|
||||
# Users may have this environment variable set. Currently, it causes babel to
|
||||
# log to stderr, which causes errors on Windows.
|
||||
# See https://github.com/atom/electron/issues/2033
|
||||
process.env.DEBUG='*'
|
||||
|
||||
path = require('path')
|
||||
temp = require('temp').track()
|
||||
CompileCache = require('../src/compile-cache')
|
||||
|
||||
describe "Babel transpiler support", ->
|
||||
originalCacheDir = null
|
||||
|
||||
beforeEach ->
|
||||
originalCacheDir = CompileCache.getCacheDirectory()
|
||||
CompileCache.setCacheDirectory(temp.mkdirSync('compile-cache'))
|
||||
for cacheKey in Object.keys(require.cache)
|
||||
if cacheKey.startsWith(path.join(__dirname, 'fixtures', 'babel'))
|
||||
console.log('deleting', cacheKey)
|
||||
delete require.cache[cacheKey]
|
||||
|
||||
afterEach ->
|
||||
CompileCache.setCacheDirectory(originalCacheDir)
|
||||
|
||||
describe 'when a .js file starts with /** @babel */;', ->
|
||||
it "transpiles it using babel", ->
|
||||
transpiled = require('./fixtures/babel/babel-comment.js')
|
||||
@ -17,3 +39,12 @@ describe "Babel transpiler support", ->
|
||||
describe "when a .js file does not start with 'use babel';", ->
|
||||
it "does not transpile it using babel", ->
|
||||
expect(-> require('./fixtures/babel/invalid.js')).toThrow()
|
||||
|
||||
it "does not try to log to stdout or stderr while parsing the file", ->
|
||||
spyOn(process.stderr, 'write')
|
||||
spyOn(process.stdout, 'write')
|
||||
|
||||
transpiled = require('./fixtures/babel/babel-double-quotes.js')
|
||||
|
||||
expect(process.stdout.write).not.toHaveBeenCalled()
|
||||
expect(process.stderr.write).not.toHaveBeenCalled()
|
||||
|
@ -872,6 +872,26 @@ describe "Config", ->
|
||||
atom.config.loadUserConfig()
|
||||
expect(atom.config.get("foo.bar")).toBe "baz"
|
||||
|
||||
describe "when the config file fails to load", ->
|
||||
addErrorHandler = null
|
||||
|
||||
beforeEach ->
|
||||
atom.notifications.onDidAddNotification addErrorHandler = jasmine.createSpy()
|
||||
spyOn(fs, "existsSync").andCallFake ->
|
||||
error = new Error()
|
||||
error.code = 'EPERM'
|
||||
throw error
|
||||
|
||||
it "creates a notification and does not try to save later changes to disk", ->
|
||||
load = -> atom.config.loadUserConfig()
|
||||
expect(load).not.toThrow()
|
||||
expect(addErrorHandler.callCount).toBe 1
|
||||
|
||||
atom.config.set("foo.bar", "baz")
|
||||
advanceClock(100)
|
||||
expect(atom.config.save).not.toHaveBeenCalled()
|
||||
expect(atom.config.get("foo.bar")).toBe "baz"
|
||||
|
||||
describe ".observeUserConfig()", ->
|
||||
updatedHandler = null
|
||||
|
||||
|
@ -1253,6 +1253,13 @@ describe "DisplayBuffer", ->
|
||||
decoration.destroy()
|
||||
expect(displayBuffer.decorationForId(decoration.id)).not.toBeDefined()
|
||||
|
||||
it "does not allow destroyed markers to be decorated", ->
|
||||
marker.destroy()
|
||||
expect(->
|
||||
displayBuffer.decorateMarker(marker, {type: 'overlay', item: document.createElement('div')})
|
||||
).toThrow("Cannot decorate a destroyed marker")
|
||||
expect(displayBuffer.getOverlayDecorations()).toEqual []
|
||||
|
||||
describe "when a decoration is updated via Decoration::update()", ->
|
||||
it "emits an 'updated' event containing the new and old params", ->
|
||||
decoration.onDidChangeProperties updatedSpy = jasmine.createSpy()
|
||||
|
@ -19,9 +19,8 @@ class FakeLinesYardstick
|
||||
setScopedCharacterWidth: (scopeNames, character, width) ->
|
||||
@getScopedCharacterWidths(scopeNames)[character] = width
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition, clip=true) ->
|
||||
pixelPositionForScreenPosition: (screenPosition) ->
|
||||
screenPosition = Point.fromObject(screenPosition)
|
||||
screenPosition = @model.clipScreenPosition(screenPosition) if clip
|
||||
|
||||
targetRow = screenPosition.row
|
||||
targetColumn = screenPosition.column
|
||||
|
@ -125,6 +125,27 @@ describe "Starting Atom", ->
|
||||
.treeViewRootDirectories()
|
||||
.then ({value}) -> expect(value).toEqual([otherTempDirPath])
|
||||
|
||||
it "opens the new window offset from the other window", ->
|
||||
runAtom [path.join(tempDirPath, "new-file")], {ATOM_HOME: atomHome}, (client) ->
|
||||
win0Position = null
|
||||
win1Position = null
|
||||
client
|
||||
.waitForWindowCount(1, 10000)
|
||||
.execute -> atom.getPosition()
|
||||
.then ({value}) -> win0Position = value
|
||||
.waitForNewWindow(->
|
||||
@startAnotherAtom([path.join(temp.mkdirSync("a-third-dir"), "a-file")], ATOM_HOME: atomHome)
|
||||
, 5000)
|
||||
.waitForWindowCount(2, 10000)
|
||||
.execute -> atom.getPosition()
|
||||
.then ({value}) -> win1Position = value
|
||||
.then ->
|
||||
expect(win1Position.x).toBeGreaterThan(win0Position.x)
|
||||
# Ideally we'd test the y coordinate too, but if the window's
|
||||
# already as tall as it can be, then OS X won't move it down outside
|
||||
# the screen.
|
||||
# expect(win1Position.y).toBeGreaterThan(win0Position.y)
|
||||
|
||||
describe "reopening a directory that was previously opened", ->
|
||||
it "remembers the state of the window", ->
|
||||
runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) ->
|
||||
|
@ -1,6 +1,7 @@
|
||||
LinesYardstick = require '../src/lines-yardstick'
|
||||
LineTopIndex = require 'line-top-index'
|
||||
{toArray} = require 'underscore-plus'
|
||||
{Point} = require 'text-buffer'
|
||||
|
||||
describe "LinesYardstick", ->
|
||||
[editor, mockLineNodesProvider, createdLineNodes, linesYardstick, buildLineNode] = []
|
||||
@ -66,12 +67,12 @@ describe "LinesYardstick", ->
|
||||
}
|
||||
"""
|
||||
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 0])).toEqual({left: 0, top: 0})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 1])).toEqual({left: 7, top: 0})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 5])).toEqual({left: 37.78125, top: 0})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([1, 6])).toEqual({left: 43.171875, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([1, 9])).toEqual({left: 72.171875, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([2, Infinity])).toEqual({left: 287.859375, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 0))).toEqual({left: 0, top: 0})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 1))).toEqual({left: 7, top: 0})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 5))).toEqual({left: 37.78125, top: 0})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 6))).toEqual({left: 43.171875, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 9))).toEqual({left: 72.171875, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(2, Infinity))).toEqual({left: 287.859375, top: 28})
|
||||
|
||||
it "reuses already computed pixel positions unless it is invalidated", ->
|
||||
atom.styles.addStyleSheet """
|
||||
@ -81,9 +82,9 @@ describe "LinesYardstick", ->
|
||||
}
|
||||
"""
|
||||
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([1, 2])).toEqual({left: 19.203125, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([2, 6])).toEqual({left: 57.609375, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([5, 10])).toEqual({left: 95.609375, top: 70})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 2))).toEqual({left: 19.203125, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(2, 6))).toEqual({left: 57.609375, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(5, 10))).toEqual({left: 95.609375, top: 70})
|
||||
|
||||
atom.styles.addStyleSheet """
|
||||
* {
|
||||
@ -91,15 +92,15 @@ describe "LinesYardstick", ->
|
||||
}
|
||||
"""
|
||||
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([1, 2])).toEqual({left: 19.203125, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([2, 6])).toEqual({left: 57.609375, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([5, 10])).toEqual({left: 95.609375, top: 70})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 2))).toEqual({left: 19.203125, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(2, 6))).toEqual({left: 57.609375, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(5, 10))).toEqual({left: 95.609375, top: 70})
|
||||
|
||||
linesYardstick.invalidateCache()
|
||||
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([1, 2])).toEqual({left: 24, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([2, 6])).toEqual({left: 72, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([5, 10])).toEqual({left: 120, top: 70})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 2))).toEqual({left: 24, top: 14})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(2, 6))).toEqual({left: 72, top: 28})
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(5, 10))).toEqual({left: 120, top: 70})
|
||||
|
||||
it "correctly handles RTL characters", ->
|
||||
atom.styles.addStyleSheet """
|
||||
@ -110,13 +111,13 @@ describe "LinesYardstick", ->
|
||||
"""
|
||||
|
||||
editor.setText("السلام عليكم")
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 0]).left).toBe 0
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 1]).left).toBe 8
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 2]).left).toBe 16
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 5]).left).toBe 33
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 7]).left).toBe 50
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 9]).left).toBe 67
|
||||
expect(linesYardstick.pixelPositionForScreenPosition([0, 11]).left).toBe 84
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 0)).left).toBe 0
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 1)).left).toBe 8
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 2)).left).toBe 16
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 5)).left).toBe 33
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 7)).left).toBe 50
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 9)).left).toBe 67
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(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
|
||||
@ -141,9 +142,9 @@ describe "LinesYardstick", ->
|
||||
|
||||
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
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 35)).left).toBe 230.90625
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 36)).left).toBe 237.5
|
||||
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 37)).left).toBe 244.09375
|
||||
|
||||
describe "::screenPositionForPixelPosition(pixelPosition)", ->
|
||||
it "converts pixel positions to screen positions", ->
|
||||
|
@ -1026,6 +1026,16 @@ describe "PackageManager", ->
|
||||
expect(atom.packages.enablePackage("this-doesnt-exist")).toBeNull()
|
||||
expect(console.warn.callCount).toBe 1
|
||||
|
||||
it "does not disable an already disabled package", ->
|
||||
packageName = 'package-with-main'
|
||||
atom.config.pushAtKeyPath('core.disabledPackages', packageName)
|
||||
atom.packages.observeDisabledPackages()
|
||||
expect(atom.config.get('core.disabledPackages')).toContain packageName
|
||||
|
||||
atom.packages.disablePackage(packageName)
|
||||
packagesDisabled = atom.config.get('core.disabledPackages').filter((pack) -> pack is packageName)
|
||||
expect(packagesDisabled.length).toEqual 1
|
||||
|
||||
describe "with themes", ->
|
||||
didChangeActiveThemesHandler = null
|
||||
|
||||
|
@ -18,6 +18,8 @@ describe "Pane", ->
|
||||
onDidDestroy: (fn) -> @emitter.on('did-destroy', fn)
|
||||
destroy: -> @destroyed = true; @emitter.emit('did-destroy')
|
||||
isDestroyed: -> @destroyed
|
||||
isPending: -> @pending
|
||||
pending: false
|
||||
|
||||
beforeEach ->
|
||||
confirm = spyOn(atom.applicationDelegate, 'confirm')
|
||||
@ -153,6 +155,26 @@ describe "Pane", ->
|
||||
pane.activateItem(pane.itemAtIndex(1))
|
||||
expect(observed).toEqual [pane.itemAtIndex(1)]
|
||||
|
||||
it "replaces pending items", ->
|
||||
itemC = new Item("C")
|
||||
itemD = new Item("D")
|
||||
itemC.pending = true
|
||||
itemD.pending = true
|
||||
|
||||
expect(itemC.isPending()).toBe true
|
||||
pane.activateItem(itemC)
|
||||
expect(pane.getItems().length).toBe 3
|
||||
expect(pane.getActiveItem()).toBe pane.itemAtIndex(1)
|
||||
|
||||
expect(itemD.isPending()).toBe true
|
||||
pane.activateItem(itemD)
|
||||
expect(pane.getItems().length).toBe 3
|
||||
expect(pane.getActiveItem()).toBe pane.itemAtIndex(1)
|
||||
|
||||
pane.activateItem(pane.itemAtIndex(2))
|
||||
expect(pane.getItems().length).toBe 2
|
||||
expect(pane.getActiveItem()).toBe pane.itemAtIndex(1)
|
||||
|
||||
describe "::activateNextItem() and ::activatePreviousItem()", ->
|
||||
it "sets the active item to the next/previous item, looping around at either end", ->
|
||||
pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")]))
|
||||
|
@ -4809,6 +4809,13 @@ describe('TextEditorComponent', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('::pixelPositionForScreenPosition()', () => {
|
||||
it('returns the correct horizontal position, even if it is on a row that has not yet been rendered (regression)', () => {
|
||||
editor.setTextInBufferRange([[5, 0], [6, 0]], 'hello world\n')
|
||||
expect(wrapperNode.pixelPositionForScreenPosition([5, Infinity]).left).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('middle mouse paste on Linux', function () {
|
||||
let originalPlatform
|
||||
|
||||
|
@ -5804,3 +5804,29 @@ describe "TextEditor", ->
|
||||
screenRange: marker1.getRange(),
|
||||
rangeIsReversed: false
|
||||
}
|
||||
|
||||
describe "pending state", ->
|
||||
editor1 = null
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.txt', pending: true).then (o) -> editor1 = o
|
||||
|
||||
it "should open file in pending state if 'pending' option is true", ->
|
||||
expect(editor1.isPending()).toBe true
|
||||
expect(editor.isPending()).toBe false # By default pending status is false
|
||||
|
||||
it "invokes ::onDidTerminatePendingState observers if pending status is terminated", ->
|
||||
events = []
|
||||
editor1.onDidTerminatePendingState (event) -> events.push(event)
|
||||
editor1.terminatePendingState()
|
||||
expect(editor1.isPending()).toBe false
|
||||
expect(events).toEqual [editor1]
|
||||
|
||||
it "should terminate pending state when buffer is changed", ->
|
||||
events = []
|
||||
editor1.onDidTerminatePendingState (event) -> events.push(event)
|
||||
expect(editor1.isPending()).toBe true
|
||||
editor1.insertText('I\'ll be back!')
|
||||
advanceClock(500)
|
||||
expect(editor1.isPending()).toBe false
|
||||
expect(events).toEqual [editor1]
|
||||
|
@ -42,6 +42,10 @@ exports.getCachePath = function (sourceCode) {
|
||||
exports.compile = function (sourceCode, filePath) {
|
||||
if (!babel) {
|
||||
babel = require('babel-core')
|
||||
var Logger = require('babel-core/lib/transformation/file/logger')
|
||||
var noop = function () {}
|
||||
Logger.prototype.debug = noop
|
||||
Logger.prototype.verbose = noop
|
||||
}
|
||||
|
||||
var options = {filename: filePath}
|
||||
|
@ -103,8 +103,6 @@ class ApplicationMenu
|
||||
downloadingUpdateItem.visible = false
|
||||
installUpdateItem.visible = false
|
||||
|
||||
return if @autoUpdateManager.isDisabled()
|
||||
|
||||
switch state
|
||||
when 'idle', 'error', 'no-update-available'
|
||||
checkForUpdateItem.visible = true
|
||||
@ -119,9 +117,10 @@ class ApplicationMenu
|
||||
#
|
||||
# Returns an Array of menu item Objects.
|
||||
getDefaultTemplate: ->
|
||||
template = [
|
||||
[
|
||||
label: "Atom"
|
||||
submenu: [
|
||||
{label: "Check for Update", metadata: {autoUpdate: true}}
|
||||
{label: 'Reload', accelerator: 'Command+R', click: => @focusedWindow()?.reload()}
|
||||
{label: 'Close Window', accelerator: 'Command+Shift+W', click: => @focusedWindow()?.close()}
|
||||
{label: 'Toggle Dev Tools', accelerator: 'Command+Alt+I', click: => @focusedWindow()?.toggleDevTools()}
|
||||
@ -129,10 +128,6 @@ class ApplicationMenu
|
||||
]
|
||||
]
|
||||
|
||||
# Add `Check for Update` button if autoUpdateManager is enabled.
|
||||
template[0].submenu.unshift({label: "Check for Update", metadata: {autoUpdate: true}}) unless @autoUpdateManager.isDisabled()
|
||||
template
|
||||
|
||||
focusedWindow: ->
|
||||
_.find global.atomApplication.windows, (atomWindow) -> atomWindow.isFocused()
|
||||
|
||||
|
@ -74,8 +74,7 @@ class AtomApplication
|
||||
@pidsToOpenWindows = {}
|
||||
@windows = []
|
||||
|
||||
disableAutoUpdate = require(path.join(@resourcePath, 'package.json'))._disableAutoUpdate ? false
|
||||
@autoUpdateManager = new AutoUpdateManager(@version, options.test, disableAutoUpdate)
|
||||
@autoUpdateManager = new AutoUpdateManager(@version, options.test, @resourcePath)
|
||||
@applicationMenu = new ApplicationMenu(@version, @autoUpdateManager)
|
||||
@atomProtocolHandler = new AtomProtocolHandler(@resourcePath, @safeMode)
|
||||
|
||||
@ -167,7 +166,7 @@ class AtomApplication
|
||||
safeMode: @focusedWindow()?.safeMode
|
||||
|
||||
@on 'application:quit', -> app.quit()
|
||||
@on 'application:new-window', -> @openPath(_.extend(windowDimensions: @focusedWindow()?.getDimensions(), getLoadSettings()))
|
||||
@on 'application:new-window', -> @openPath(getLoadSettings())
|
||||
@on 'application:new-file', -> (@focusedWindow() ? this).openPath()
|
||||
@on 'application:open', -> @promptForPathToOpen('all', getLoadSettings())
|
||||
@on 'application:open-file', -> @promptForPathToOpen('file', getLoadSettings())
|
||||
@ -229,7 +228,7 @@ class AtomApplication
|
||||
@openUrl({urlToOpen, @devMode, @safeMode})
|
||||
|
||||
app.on 'activate-with-no-open-windows', (event) =>
|
||||
event.preventDefault()
|
||||
event?.preventDefault()
|
||||
@emit('application:new-window')
|
||||
|
||||
# A request from the associated render process to open a new render process.
|
||||
@ -360,6 +359,23 @@ class AtomApplication
|
||||
focusedWindow: ->
|
||||
_.find @windows, (atomWindow) -> atomWindow.isFocused()
|
||||
|
||||
# Get the platform-specific window offset for new windows.
|
||||
getWindowOffsetForCurrentPlatform: ->
|
||||
offsetByPlatform =
|
||||
darwin: 22
|
||||
win32: 26
|
||||
offsetByPlatform[process.platform] ? 0
|
||||
|
||||
# Get the dimensions for opening a new window by cascading as appropriate to
|
||||
# the platform.
|
||||
getDimensionsForNewWindow: ->
|
||||
dimensions = (@focusedWindow() ? @lastFocusedWindow)?.getDimensions()
|
||||
offset = @getWindowOffsetForCurrentPlatform()
|
||||
if dimensions? and offset?
|
||||
dimensions.x += offset
|
||||
dimensions.y += offset
|
||||
dimensions
|
||||
|
||||
# Public: Opens a single path, in an existing window if possible.
|
||||
#
|
||||
# options -
|
||||
@ -370,7 +386,7 @@ class AtomApplication
|
||||
# :safeMode - Boolean to control the opened window's safe mode.
|
||||
# :profileStartup - Boolean to control creating a profile of the startup time.
|
||||
# :window - {AtomWindow} to open file paths in.
|
||||
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window}) ->
|
||||
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window} = {}) ->
|
||||
@openPaths({pathsToOpen: [pathToOpen], pidToKillWhenClosed, newWindow, devMode, safeMode, profileStartup, window})
|
||||
|
||||
# Public: Opens multiple paths, in existing windows if possible.
|
||||
@ -417,6 +433,7 @@ class AtomApplication
|
||||
|
||||
windowInitializationScript ?= require.resolve('../initialize-application-window')
|
||||
resourcePath ?= @resourcePath
|
||||
windowDimensions ?= @getDimensionsForNewWindow()
|
||||
openedWindow = new AtomWindow({locationsToOpen, windowInitializationScript, resourcePath, devMode, safeMode, windowDimensions, profileStartup})
|
||||
|
||||
if pidToKillWhenClosed?
|
||||
|
@ -1,5 +1,6 @@
|
||||
autoUpdater = null
|
||||
_ = require 'underscore-plus'
|
||||
Config = require '../config'
|
||||
{EventEmitter} = require 'events'
|
||||
path = require 'path'
|
||||
|
||||
@ -15,10 +16,13 @@ module.exports =
|
||||
class AutoUpdateManager
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
|
||||
constructor: (@version, @testMode, @disabled) ->
|
||||
constructor: (@version, @testMode, resourcePath) ->
|
||||
@state = IdleState
|
||||
@iconPath = path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
|
||||
@config = new Config({configDirPath: process.env.ATOM_HOME, resourcePath, enablePersistence: true})
|
||||
@config.setSchema null, {type: 'object', properties: _.clone(require('../config-schema'))}
|
||||
@config.load()
|
||||
process.nextTick => @setupAutoUpdater()
|
||||
|
||||
setupAutoUpdater: ->
|
||||
@ -46,9 +50,13 @@ class AutoUpdateManager
|
||||
@setState(UpdateAvailableState)
|
||||
@emitUpdateAvailableEvent(@getWindows()...)
|
||||
|
||||
# Only check for updates periodically if enabled and running in release
|
||||
# version.
|
||||
@scheduleUpdateCheck() unless /\w{7}/.test(@version) or @disabled
|
||||
@config.onDidChange 'core.automaticallyUpdate', ({newValue}) =>
|
||||
if newValue
|
||||
@scheduleUpdateCheck()
|
||||
else
|
||||
@cancelScheduledUpdateCheck()
|
||||
|
||||
@scheduleUpdateCheck() if @config.get 'core.automaticallyUpdate'
|
||||
|
||||
switch process.platform
|
||||
when 'win32'
|
||||
@ -56,9 +64,6 @@ class AutoUpdateManager
|
||||
when 'linux'
|
||||
@setState(UnsupportedState)
|
||||
|
||||
isDisabled: ->
|
||||
@disabled
|
||||
|
||||
emitUpdateAvailableEvent: (windows...) ->
|
||||
return unless @releaseVersion?
|
||||
for atomWindow in windows
|
||||
@ -74,10 +79,18 @@ class AutoUpdateManager
|
||||
@state
|
||||
|
||||
scheduleUpdateCheck: ->
|
||||
checkForUpdates = => @check(hidePopups: true)
|
||||
fourHours = 1000 * 60 * 60 * 4
|
||||
setInterval(checkForUpdates, fourHours)
|
||||
checkForUpdates()
|
||||
# Only schedule update check periodically if running in release version and
|
||||
# and there is no existing scheduled update check.
|
||||
unless /\w{7}/.test(@version) or @checkForUpdatesIntervalID
|
||||
checkForUpdates = => @check(hidePopups: true)
|
||||
fourHours = 1000 * 60 * 60 * 4
|
||||
@checkForUpdatesIntervalID = setInterval(checkForUpdates, fourHours)
|
||||
checkForUpdates()
|
||||
|
||||
cancelScheduledUpdateCheck: ->
|
||||
if @checkForUpdatesIntervalID
|
||||
clearInterval(@checkForUpdatesIntervalID)
|
||||
@checkForUpdatesIntervalID = null
|
||||
|
||||
check: ({hidePopups}={}) ->
|
||||
unless hidePopups
|
||||
|
@ -104,6 +104,10 @@ module.exports =
|
||||
description: 'Automatically open an empty editor on startup.'
|
||||
type: 'boolean'
|
||||
default: true
|
||||
automaticallyUpdate:
|
||||
description: 'Automatically update Atom when a new release is available.'
|
||||
type: 'boolean'
|
||||
default: true
|
||||
|
||||
editor:
|
||||
type: 'object'
|
||||
|
@ -779,9 +779,14 @@ class Config
|
||||
loadUserConfig: ->
|
||||
return if @shouldNotAccessFileSystem()
|
||||
|
||||
unless fs.existsSync(@configFilePath)
|
||||
fs.makeTreeSync(path.dirname(@configFilePath))
|
||||
CSON.writeFileSync(@configFilePath, {})
|
||||
try
|
||||
unless fs.existsSync(@configFilePath)
|
||||
fs.makeTreeSync(path.dirname(@configFilePath))
|
||||
CSON.writeFileSync(@configFilePath, {})
|
||||
catch error
|
||||
@configFileHasErrors = true
|
||||
@notifyFailure("Failed to initialize `#{path.basename(@configFilePath)}`", error.stack)
|
||||
return
|
||||
|
||||
try
|
||||
unless @savePending
|
||||
@ -820,7 +825,7 @@ class Config
|
||||
@watchSubscription = null
|
||||
|
||||
notifyFailure: (errorMessage, detail) ->
|
||||
@notificationManager.addError(errorMessage, {detail, dismissable: true})
|
||||
@notificationManager?.addError(errorMessage, {detail, dismissable: true})
|
||||
|
||||
save: ->
|
||||
return if @shouldNotAccessFileSystem()
|
||||
|
@ -812,6 +812,7 @@ class DisplayBuffer extends Model
|
||||
decorationsState
|
||||
|
||||
decorateMarker: (marker, decorationParams) ->
|
||||
throw new Error("Cannot decorate a destroyed marker") if marker.isDestroyed()
|
||||
marker = @getMarkerLayer(marker.layer.id).getMarker(marker.id)
|
||||
decoration = new Decoration(marker, this, decorationParams)
|
||||
@decorationsByMarkerId[marker.id] ?= []
|
||||
|
@ -463,8 +463,12 @@ class GitRepository
|
||||
refreshStatus: ->
|
||||
@handlerPath ?= require.resolve('./repository-status-handler')
|
||||
|
||||
relativeProjectPaths = @project?.getPaths()
|
||||
.map (path) => @relativize(path)
|
||||
.filter (path) -> path.length > 0
|
||||
|
||||
@statusTask?.terminate()
|
||||
@statusTask = Task.once @handlerPath, @getPath(), ({statuses, upstream, branch, submodules}) =>
|
||||
@statusTask = Task.once @handlerPath, @getPath(), relativeProjectPaths, ({statuses, upstream, branch, submodules}) =>
|
||||
statusesUnchanged = _.isEqual(statuses, @statuses) and
|
||||
_.isEqual(upstream, @upstream) and
|
||||
_.isEqual(branch, @branch) and
|
||||
|
@ -77,10 +77,7 @@ class LinesYardstick
|
||||
else
|
||||
Point(row, column)
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition, clip=true) ->
|
||||
screenPosition = Point.fromObject(screenPosition)
|
||||
screenPosition = @model.clipScreenPosition(screenPosition) if clip
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition) ->
|
||||
targetRow = screenPosition.row
|
||||
targetColumn = screenPosition.column
|
||||
|
||||
|
@ -199,7 +199,10 @@ class PackageManager
|
||||
# Returns the {Package} that was disabled or null if it isn't loaded.
|
||||
disablePackage: (name) ->
|
||||
pack = @loadPackage(name)
|
||||
pack?.disable()
|
||||
|
||||
unless @isPackageDisabled(name)
|
||||
pack?.disable()
|
||||
|
||||
pack
|
||||
|
||||
# Public: Is the package with the given name disabled?
|
||||
|
@ -337,13 +337,19 @@ class Pane extends Model
|
||||
#
|
||||
# * `index` {Number}
|
||||
activateItemAtIndex: (index) ->
|
||||
@activateItem(@itemAtIndex(index))
|
||||
item = @itemAtIndex(index) or @getActiveItem()
|
||||
@setActiveItem(item)
|
||||
|
||||
# Public: Make the given item *active*, causing it to be displayed by
|
||||
# the pane's view.
|
||||
activateItem: (item) ->
|
||||
if item?
|
||||
@addItem(item, @getActiveItemIndex() + 1, false)
|
||||
if @activeItem?.isPending?()
|
||||
index = @getActiveItemIndex()
|
||||
@destroyActiveItem() unless item is @activeItem
|
||||
else
|
||||
index = @getActiveItemIndex() + 1
|
||||
@addItem(item, index, false)
|
||||
@setActiveItem(item)
|
||||
|
||||
# Public: Add the given item to the pane.
|
||||
@ -574,7 +580,6 @@ class Pane extends Model
|
||||
# Public: Makes this pane the *active* pane, causing it to gain focus.
|
||||
activate: ->
|
||||
throw new Error("Pane has been destroyed") if @isDestroyed()
|
||||
|
||||
@container?.setActivePane(this)
|
||||
@emitter.emit 'did-activate'
|
||||
|
||||
@ -721,30 +726,28 @@ class Pane extends Model
|
||||
message = "#{message} '#{itemPath}'" if itemPath
|
||||
@notificationManager.addWarning(message, options)
|
||||
|
||||
if error.code is 'EISDIR' or error.message?.endsWith?('is a directory')
|
||||
customMessage = @getMessageForErrorCode(error.code)
|
||||
if customMessage?
|
||||
addWarningWithPath("Unable to save file: #{customMessage}")
|
||||
else if error.code is 'EISDIR' or error.message?.endsWith?('is a directory')
|
||||
@notificationManager.addWarning("Unable to save file: #{error.message}")
|
||||
else if error.code is 'EACCES'
|
||||
addWarningWithPath('Unable to save file: Permission denied')
|
||||
else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST', 'ELOOP', 'EAGAIN']
|
||||
addWarningWithPath('Unable to save file', detail: error.message)
|
||||
else if error.code is 'EROFS'
|
||||
addWarningWithPath('Unable to save file: Read-only file system')
|
||||
else if error.code is 'ENOSPC'
|
||||
addWarningWithPath('Unable to save file: No space left on device')
|
||||
else if error.code is 'ENXIO'
|
||||
addWarningWithPath('Unable to save file: No such device or address')
|
||||
else if error.code is 'ENOTSUP'
|
||||
addWarningWithPath('Unable to save file: Operation not supported on socket')
|
||||
else if error.code is 'EIO'
|
||||
addWarningWithPath('Unable to save file: I/O error writing file')
|
||||
else if error.code is 'EINTR'
|
||||
addWarningWithPath('Unable to save file: Interrupted system call')
|
||||
else if error.code is 'ECONNRESET'
|
||||
addWarningWithPath('Unable to save file: Connection reset')
|
||||
else if error.code is 'ESPIPE'
|
||||
addWarningWithPath('Unable to save file: Invalid seek')
|
||||
else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message)
|
||||
fileName = errorMatch[1]
|
||||
@notificationManager.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to")
|
||||
else
|
||||
throw error
|
||||
|
||||
getMessageForErrorCode: (errorCode) ->
|
||||
switch errorCode
|
||||
when 'EACCES' then 'Permission denied'
|
||||
when 'ECONNRESET' then 'Connection reset'
|
||||
when 'EINTR' then 'Interrupted system call'
|
||||
when 'EIO' then 'I/O error writing file'
|
||||
when 'ENOSPC' then 'No space left on device'
|
||||
when 'ENOTSUP' then 'Operation not supported on socket'
|
||||
when 'ENXIO' then 'No such device or address'
|
||||
when 'EROFS' then 'Read-only file system'
|
||||
when 'ESPIPE' then 'Invalid seek'
|
||||
when 'ETIMEDOUT' then 'Connection timed out'
|
||||
|
@ -288,7 +288,7 @@ class Project extends Model
|
||||
'atom.repository-provider',
|
||||
'^0.1.0',
|
||||
(provider) =>
|
||||
@repositoryProviders.push(provider)
|
||||
@repositoryProviders.unshift(provider)
|
||||
@setPaths(@getPaths()) if null in @repositories
|
||||
new Disposable =>
|
||||
@repositoryProviders.splice(@repositoryProviders.indexOf(provider), 1)
|
||||
|
@ -169,7 +169,8 @@ module.exports = ({commandRegistry, commandInstaller, config}) ->
|
||||
'editor:fold-at-indent-level-8': -> @foldAllAtIndentLevel(7)
|
||||
'editor:fold-at-indent-level-9': -> @foldAllAtIndentLevel(8)
|
||||
'editor:log-cursor-scope': -> @logCursorScope()
|
||||
'editor:copy-path': -> @copyPathToClipboard()
|
||||
'editor:copy-path': -> @copyPathToClipboard(false)
|
||||
'editor:copy-project-path': -> @copyPathToClipboard(true)
|
||||
'editor:toggle-indent-guide': -> config.set('editor.showIndentGuide', not config.get('editor.showIndentGuide'))
|
||||
'editor:toggle-line-numbers': -> config.set('editor.showLineNumbers', not config.get('editor.showLineNumbers'))
|
||||
'editor:scroll-to-cursor': -> @scrollToCursorPosition()
|
||||
|
@ -1,7 +1,7 @@
|
||||
Git = require 'git-utils'
|
||||
path = require 'path'
|
||||
|
||||
module.exports = (repoPath) ->
|
||||
module.exports = (repoPath, paths = []) ->
|
||||
repo = Git.open(repoPath)
|
||||
|
||||
upstream = {}
|
||||
@ -12,7 +12,8 @@ module.exports = (repoPath) ->
|
||||
if repo?
|
||||
# Statuses in main repo
|
||||
workingDirectoryPath = repo.getWorkingDirectory()
|
||||
for filePath, status of repo.getStatus()
|
||||
repoStatus = (if paths.length > 0 then repo.getStatusForPaths(paths) else repo.getStatus())
|
||||
for filePath, status of repoStatus
|
||||
statuses[filePath] = status
|
||||
|
||||
# Statuses in submodules
|
||||
|
@ -445,12 +445,17 @@ class TextEditorComponent
|
||||
getVisibleRowRange: ->
|
||||
@presenter.getVisibleRowRange()
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition, clip) ->
|
||||
pixelPositionForScreenPosition: (screenPosition, clip=true) ->
|
||||
screenPosition = Point.fromObject(screenPosition)
|
||||
screenPosition = @editor.clipScreenPosition(screenPosition) if clip
|
||||
|
||||
unless @presenter.isRowVisible(screenPosition.row)
|
||||
@presenter.setScreenRowsToMeasure([screenPosition.row])
|
||||
|
||||
unless @linesComponent.lineNodeForLineIdAndScreenRow(@presenter.lineIdForScreenRow(screenPosition.row), screenPosition.row)?
|
||||
@updateSyncPreMeasurement()
|
||||
|
||||
pixelPosition = @linesYardstick.pixelPositionForScreenPosition(screenPosition, clip)
|
||||
pixelPosition = @linesYardstick.pixelPositionForScreenPosition(screenPosition)
|
||||
@presenter.clearScreenRowsToMeasure()
|
||||
pixelPosition
|
||||
|
||||
|
@ -459,7 +459,7 @@ class TextEditorPresenter
|
||||
else
|
||||
screenPosition = decoration.getMarker().getHeadScreenPosition()
|
||||
|
||||
pixelPosition = @pixelPositionForScreenPosition(screenPosition, true)
|
||||
pixelPosition = @pixelPositionForScreenPosition(screenPosition)
|
||||
|
||||
top = pixelPosition.top + @lineHeight
|
||||
left = pixelPosition.left + @gutterWidth
|
||||
@ -681,8 +681,10 @@ class TextEditorPresenter
|
||||
updateHorizontalDimensions: ->
|
||||
if @baseCharacterWidth?
|
||||
oldContentWidth = @contentWidth
|
||||
clip = @model.tokenizedLineForScreenRow(@model.getLongestScreenRow())?.isSoftWrapped()
|
||||
@contentWidth = @pixelPositionForScreenPosition([@model.getLongestScreenRow(), @model.getMaxScreenLineLength()], clip).left
|
||||
rightmostPosition = Point(@model.getLongestScreenRow(), @model.getMaxScreenLineLength())
|
||||
if @model.tokenizedLineForScreenRow(rightmostPosition.row)?.isSoftWrapped()
|
||||
rightmostPosition = @model.clipScreenPosition(rightmostPosition)
|
||||
@contentWidth = @pixelPositionForScreenPosition(rightmostPosition).left
|
||||
@contentWidth += @scrollLeft
|
||||
@contentWidth += 1 unless @model.isSoftWrapped() # account for cursor width
|
||||
|
||||
@ -1007,9 +1009,9 @@ class TextEditorPresenter
|
||||
hasPixelPositionRequirements: ->
|
||||
@lineHeight? and @baseCharacterWidth?
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition, clip=true) ->
|
||||
pixelPositionForScreenPosition: (screenPosition) ->
|
||||
position =
|
||||
@linesYardstick.pixelPositionForScreenPosition(screenPosition, clip, true)
|
||||
@linesYardstick.pixelPositionForScreenPosition(screenPosition)
|
||||
position.top -= @getScrollTop()
|
||||
position.left -= @getScrollLeft()
|
||||
|
||||
@ -1028,14 +1030,14 @@ class TextEditorPresenter
|
||||
lineHeight = @model.getLineHeightInPixels()
|
||||
|
||||
if screenRange.end.row > screenRange.start.row
|
||||
top = @linesYardstick.pixelPositionForScreenPosition(screenRange.start, true).top
|
||||
top = @linesYardstick.pixelPositionForScreenPosition(screenRange.start).top
|
||||
left = 0
|
||||
height = (screenRange.end.row - screenRange.start.row + 1) * lineHeight
|
||||
width = @getScrollWidth()
|
||||
else
|
||||
{top, left} = @linesYardstick.pixelPositionForScreenPosition(screenRange.start, false)
|
||||
{top, left} = @linesYardstick.pixelPositionForScreenPosition(screenRange.start)
|
||||
height = lineHeight
|
||||
width = @linesYardstick.pixelPositionForScreenPosition(screenRange.end, false).left - left
|
||||
width = @linesYardstick.pixelPositionForScreenPosition(screenRange.end).left - left
|
||||
|
||||
{top, left, width, height}
|
||||
|
||||
@ -1217,8 +1219,8 @@ class TextEditorPresenter
|
||||
|
||||
buildHighlightRegions: (screenRange) ->
|
||||
lineHeightInPixels = @lineHeight
|
||||
startPixelPosition = @pixelPositionForScreenPosition(screenRange.start, false)
|
||||
endPixelPosition = @pixelPositionForScreenPosition(screenRange.end, false)
|
||||
startPixelPosition = @pixelPositionForScreenPosition(screenRange.start)
|
||||
endPixelPosition = @pixelPositionForScreenPosition(screenRange.end)
|
||||
spannedRows = screenRange.end.row - screenRange.start.row + 1
|
||||
|
||||
regions = []
|
||||
@ -1520,3 +1522,6 @@ class TextEditorPresenter
|
||||
|
||||
isRowVisible: (row) ->
|
||||
@startRow <= row < @endRow
|
||||
|
||||
lineIdForScreenRow: (screenRow) ->
|
||||
@model.tokenizedLineForScreenRow(screenRow)?.id
|
||||
|
@ -92,7 +92,7 @@ class TextEditor extends Model
|
||||
softWrapped, @displayBuffer, @selectionsMarkerLayer, buffer, suppressCursorCreation,
|
||||
@mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config,
|
||||
@notificationManager, @packageManager, @clipboard, @viewRegistry, @grammarRegistry,
|
||||
@project, @assert, @applicationDelegate
|
||||
@project, @assert, @applicationDelegate, @pending
|
||||
} = params
|
||||
|
||||
throw new Error("Must pass a config parameter when constructing TextEditors") unless @config?
|
||||
@ -161,6 +161,9 @@ class TextEditor extends Model
|
||||
@disposables.add @buffer.onDidChangeEncoding =>
|
||||
@emitter.emit 'did-change-encoding', @getEncoding()
|
||||
@disposables.add @buffer.onDidDestroy => @destroy()
|
||||
if @pending
|
||||
@disposables.add @buffer.onDidChangeModified =>
|
||||
@terminatePendingState() if @buffer.isModified()
|
||||
|
||||
@preserveCursorPositionOnBufferReload()
|
||||
|
||||
@ -569,6 +572,13 @@ class TextEditor extends Model
|
||||
getEditorWidthInChars: ->
|
||||
@displayBuffer.getEditorWidthInChars()
|
||||
|
||||
onDidTerminatePendingState: (callback) ->
|
||||
@emitter.on 'did-terminate-pending-state', callback
|
||||
|
||||
terminatePendingState: ->
|
||||
@pending = false
|
||||
@emitter.emit 'did-terminate-pending-state', this
|
||||
|
||||
###
|
||||
Section: File Details
|
||||
###
|
||||
@ -652,9 +662,13 @@ class TextEditor extends Model
|
||||
# Essential: Returns {Boolean} `true` if this editor has no content.
|
||||
isEmpty: -> @buffer.isEmpty()
|
||||
|
||||
# Returns {Boolean} `true` if this editor is pending and `false` if it is permanent.
|
||||
isPending: -> Boolean(@pending)
|
||||
|
||||
# Copies the current file path to the native clipboard.
|
||||
copyPathToClipboard: ->
|
||||
copyPathToClipboard: (relative = false) ->
|
||||
if filePath = @getPath()
|
||||
filePath = atom.project.relativize(filePath) if relative
|
||||
@clipboard.write(filePath)
|
||||
|
||||
###
|
||||
@ -3043,7 +3057,7 @@ class TextEditor extends Model
|
||||
|
||||
# Essential: Scrolls the editor to the given screen position.
|
||||
#
|
||||
# * `screenPosition` An object that represents a buffer position. It can be either
|
||||
# * `screenPosition` An object that represents a screen position. It can be either
|
||||
# an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
|
||||
# * `options` (optional) {Object}
|
||||
# * `center` Center the editor around the position if possible. (default: false)
|
||||
|
@ -475,7 +475,7 @@ class Workspace extends Model
|
||||
when 'EACCES'
|
||||
@notificationManager.addWarning("Permission denied '#{error.path}'")
|
||||
return Promise.resolve()
|
||||
when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL', 'EMFILE', 'ENOTDIR'
|
||||
when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL', 'EMFILE', 'ENOTDIR', 'EAGAIN'
|
||||
@notificationManager.addWarning("Unable to open '#{error.path ? uri}'", detail: error.message)
|
||||
return Promise.resolve()
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user