Comparar commits
139 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 00027e892c | |||
| 6e33f10050 | |||
| 61651db0b0 | |||
| 982346b142 | |||
| 92ba107c89 | |||
| 7b4a9aa2e4 | |||
| 446398ad01 | |||
| 8afbab311f | |||
| 1601a1fbfa | |||
| 2c89a5c82a | |||
| e4ec932513 | |||
| a834920fb7 | |||
| b5edefcae8 | |||
| 616a94a10e | |||
| 7034fe3b36 | |||
| 5f68af27f5 | |||
| ea207f0938 | |||
| 732f053d4a | |||
| 78e61c3ff9 | |||
| 22c9a222c9 | |||
| cc4ab0d36b | |||
| 7bdf3b1719 | |||
| 175d7811b4 | |||
| 3f3fca872b | |||
| 421c64347e | |||
| 557d277e9f | |||
| 3fc514659a | |||
| 747398f2a5 | |||
| 1f51317a10 | |||
| f592a5d11f | |||
| fb223db958 | |||
| 1d73c57f9e | |||
| 016f32d62e | |||
| 9ee4d334b2 | |||
| ddb16dcc6f | |||
| 8403e6583f | |||
| 6bdbabecbd | |||
| 2cda86efda | |||
| 46ff794c8b | |||
| 1406fbfe03 | |||
| dde13a5d4e | |||
| bfc7995aee | |||
| 7fd9c75d24 | |||
| 677be2df82 | |||
| b3bf47dd69 | |||
| a25920da72 | |||
| 9b28e7a47c | |||
| db811cfa9e | |||
| 6d0be70dbc | |||
| 74966bd547 | |||
| 488abc8c24 | |||
| 362d7712ad | |||
| 6ed3626133 | |||
| fc87c98261 | |||
| 46a7ea5936 | |||
| f412d88edd | |||
| 49471070a3 | |||
| 0ca9d7b97e | |||
| d42878164a | |||
| 9adad17e27 | |||
| be420b042c | |||
| 270642b2ea | |||
| 9a080bfd1b | |||
| 7c43ea7a0f | |||
| 28c5bd7814 | |||
| 8c3bae4275 | |||
| 71e3ab9d2b | |||
| a1634b2f9b | |||
| fb6351d9d7 | |||
| 90041b7115 | |||
| d6ba6067b8 | |||
| aface45084 | |||
| 16fc52b351 | |||
| 56184be6fe | |||
| 8f623db092 | |||
| 081c2efc98 | |||
| 3296674605 | |||
| 1e18e2b4e5 | |||
| 13b28c26f0 | |||
| 760f6d280a | |||
| f39ca3ea48 | |||
| d379582248 | |||
| 84f160f88e | |||
| c3d1dd82f0 | |||
| 32ff599a61 | |||
| cbdf93b075 | |||
| c721300be4 | |||
| 6630147b69 | |||
| 08076a4af1 | |||
| b9897d8b34 | |||
| 68fbff59d8 | |||
| 0b2bd468b5 | |||
| a36eae8e4d | |||
| ed23058af0 | |||
| c3d8f4843a | |||
| 085933c55e | |||
| 01987cb762 | |||
| 75a6c51ac7 | |||
| 1575ee9037 | |||
| 64612d4734 | |||
| 3aac342c21 | |||
| 69d3b3cfa2 | |||
| 84232d76de | |||
| dc69b07045 | |||
| 971539c438 | |||
| c36be85dd6 | |||
| 4bbc498d1d | |||
| 3ac992d5d5 | |||
| ddbedcee3e | |||
| ba8cc9e1c0 | |||
| ec4a2a468e | |||
| f09423e020 | |||
| 7e34e8c4ed | |||
| cc785de974 | |||
| a8c4d2e4ca | |||
| d918eb6fa7 | |||
| 69efdc2292 | |||
| fc891f8706 | |||
| 9fc96ba7d4 | |||
| b8a263c570 | |||
| c9a9b51238 | |||
| 13d16b4723 | |||
| ddacfd7d5f | |||
| 932207b106 | |||
| 2c39f3515b | |||
| 8e53b2d507 | |||
| 9bd7141359 | |||
| e534997bf9 | |||
| db9de34993 | |||
| 6f95f51da2 | |||
| a67743b5cd | |||
| 2a56e70110 | |||
| eaedb14942 | |||
| c7cd084e24 | |||
| 685a2c088b | |||
| be7111f007 | |||
| 59c28c0f76 | |||
| 27331cb379 | |||
| d3f2798472 |
@@ -202,9 +202,9 @@ module.exports = (grunt) ->
|
||||
'create-windows-installer':
|
||||
appDirectory: shellAppDir
|
||||
outputDirectory: path.join(buildDir, 'installer')
|
||||
authors: 'The Atom Team & Community'
|
||||
authors: 'GitHub Inc.'
|
||||
loadingGif: path.resolve(__dirname, '..', 'resources', 'win', 'loading.gif')
|
||||
iconUrl: 'https://raw.githubusercontent.com/atom/atom/master/resources/atom.png'
|
||||
iconUrl: 'https://raw.githubusercontent.com/atom/atom/master/resources/win/atom.ico'
|
||||
|
||||
shell:
|
||||
'kill-atom':
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"fs-plus": "2.x",
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-atom-shell-installer": "^0.7.0",
|
||||
"grunt-atom-shell-installer": "^0.10.0",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git#cfb99aa99811d52687969532bd5a98011ed95bfe",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
|
||||
@@ -6,12 +6,17 @@ _ = require 'underscore-plus'
|
||||
donna = require 'donna'
|
||||
tello = require 'tello'
|
||||
|
||||
moduleBlacklist = [
|
||||
'space-pen'
|
||||
]
|
||||
|
||||
module.exports = (grunt) ->
|
||||
getClassesToInclude = ->
|
||||
modulesPath = path.resolve(__dirname, '..', '..', 'node_modules')
|
||||
classes = {}
|
||||
fs.traverseTreeSync modulesPath, (modulePath) ->
|
||||
return false if modulePath.match(/node_modules/g).length > 1 # dont need the dependencies of the dependencies
|
||||
return false if path.basename(modulePath) in moduleBlacklist
|
||||
return true unless path.basename(modulePath) is 'package.json'
|
||||
return true unless fs.isFileSync(modulePath)
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ Atom exposes several services through singleton objects accessible via the
|
||||
* workspace:
|
||||
Manipulate and query the state of the user interface for the current
|
||||
window. Open editors, manipulate panes.
|
||||
* workspaceView:
|
||||
Similar to workspace, but provides access to the root of all views in the
|
||||
current window.
|
||||
* project:
|
||||
Access the directory associated with the current window. Load editors,
|
||||
perform project-wide searches, register custom openers for special file
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
## Atom's View System
|
||||
|
||||
### SpacePen Basics
|
||||
|
||||
Atom's view system is built around the [SpacePen] view framework. SpacePen
|
||||
view objects inherit from the jQuery prototype, and wrap DOM nodes
|
||||
|
||||
View objects are actually jQuery wrappers around DOM fragments, supporting all
|
||||
the typical jQuery traversal and manipulation methods. In addition, view objects
|
||||
have methods that are view-specific. For example, you could call both general
|
||||
and view-specific on the global `atom.workspaceView` instance:
|
||||
|
||||
```coffeescript
|
||||
atom.workspaceView.find('atom-text-editor.active') # standard jQuery method
|
||||
atom.workspaceView.getActiveEditor() # view-specific method
|
||||
```
|
||||
|
||||
If you retrieve a jQuery wrapper for an element associated with a view, use the
|
||||
`.view()` method to retrieve the element's view object:
|
||||
|
||||
```coffeescript
|
||||
# this is a plain jQuery object; you can't call view-specific methods
|
||||
editorElement = atom.workspaceView.find('atom-text-editor.active')
|
||||
|
||||
# get the view object by calling `.view()` to call view-specific methods
|
||||
editorView = editorElement.view()
|
||||
editorView.setCursorBufferPosition([1, 2])
|
||||
```
|
||||
|
||||
Refer to the [SpacePen] documentation for more details.
|
||||
|
||||
### WorkspaceView
|
||||
|
||||
The root of Atom's view hierarchy is a global called `atom.workspaceView`, which is a
|
||||
singleton instance of the `WorkspaceView` view class. The root view fills the entire
|
||||
window, and contains every other view. If you open Atom's inspector with
|
||||
`alt-cmd-i`, you can see the internal structure of `WorkspaceView`:
|
||||
|
||||
![WorkspaceView in the inspector][workspaceview-inspector]
|
||||
|
||||
#### Panes
|
||||
|
||||
The `WorkspaceView` contains `prependToBottom/Top/Left/Right` and
|
||||
`appendToBottom/Top/Left/Right` methods, which are used to add Tool Panels. Tool
|
||||
panels are elements that take up screen real estate not devoted to text editing.
|
||||
In the example above, the `TreeView` is appended to the left, and the
|
||||
`CommandPanel` is appended to the top.
|
||||
|
||||
```coffeescript
|
||||
# place a view to the left of the panes
|
||||
atom.workspaceView.appendToLeft(new MyView)
|
||||
|
||||
# place a view below the panes
|
||||
atom.workspaceView.appendToBottom(new MyOtherView)
|
||||
```
|
||||
|
||||
[spacepen]: http://github.com/nathansobo/space-pen
|
||||
[workspaceView-inspector]: https://f.cloud.github.com/assets/1424/1091631/1932c2d6-166b-11e3-8adf-9690fe82d3b8.png
|
||||
@@ -18,7 +18,6 @@
|
||||
* [Developing Node Modules](advanced/node-modules.md)
|
||||
* [Keymaps](advanced/keymaps.md)
|
||||
* [Serialization](advanced/serialization.md)
|
||||
* [View System](advanced/view-system.md)
|
||||
* [Scopes and Scope Descriptors](advanced/scopes-and-scope-descriptors.md)
|
||||
|
||||
### Upgrading to 1.0 APIs
|
||||
|
||||
@@ -49,7 +49,7 @@ Register the command in _lib/ascii-art.coffee_:
|
||||
```coffeescript
|
||||
module.exports =
|
||||
activate: ->
|
||||
atom.workspaceView.command "ascii-art:convert", => @convert()
|
||||
atom.commands.add 'atom-workspace', "ascii-art:convert", => @convert()
|
||||
|
||||
convert: ->
|
||||
# This assumes the active pane item is an editor
|
||||
@@ -57,10 +57,10 @@ module.exports =
|
||||
editor.insertText('Hello, World!')
|
||||
```
|
||||
|
||||
The `atom.workspaceView.command` method takes a command name and a callback. The
|
||||
callback executes when the command is triggered. In this case, when the command
|
||||
is triggered the callback will call the `convert` method and insert 'Hello,
|
||||
World!'.
|
||||
The `atom.commands.add` method takes a selector, command name, and a callback.
|
||||
The callback executes when the command is triggered on an element matching the
|
||||
selector. In this case, when the command is triggered the callback will call the
|
||||
`convert` method and insert 'Hello, World!'.
|
||||
|
||||
## Reload the Package
|
||||
|
||||
@@ -95,13 +95,13 @@ you don't need it anymore. When finished, the file will look like this:
|
||||
'cmd-alt-a': 'ascii-art:convert'
|
||||
```
|
||||
|
||||
Notice `atom-text-editor` on the first line. Just like CSS, keymap selectors *scope* key
|
||||
bindings so they only apply to specific elements. In this case, our binding is
|
||||
only active for elements matching the `atom-text-editor` selector. If the Tree View has
|
||||
focus, pressing `cmd-alt-a` won't trigger the `ascii-art:convert` command. But
|
||||
if the editor has focus, the `ascii-art:convert` method *will* be triggered.
|
||||
More information on key bindings can be found in the
|
||||
[keymaps](advanced/keymaps.html) documentation.
|
||||
Notice `atom-text-editor` on the first line. Just like CSS, keymap selectors
|
||||
*scope* key bindings so they only apply to specific elements. In this case, our
|
||||
binding is only active for elements matching the `atom-text-editor` selector. If
|
||||
the Tree View has focus, pressing `cmd-alt-a` won't trigger the
|
||||
`ascii-art:convert` command. But if the editor has focus, the
|
||||
`ascii-art:convert` method *will* be triggered. More information on key bindings
|
||||
can be found in the [keymaps](advanced/keymaps.html) documentation.
|
||||
|
||||
Now reload the window and verify that the key binding works! You can also verify
|
||||
that it **doesn't** work when the Tree View is focused.
|
||||
|
||||
+17
-16
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.147.0",
|
||||
"version": "0.150.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -29,7 +29,7 @@
|
||||
"emissary": "^1.3.1",
|
||||
"event-kit": "0.7.2",
|
||||
"first-mate": "^2.2.0",
|
||||
"fs-plus": "^2.3.1",
|
||||
"fs-plus": "^2.3.2",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"git-utils": "^2.1.5",
|
||||
@@ -39,6 +39,7 @@
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"jquery": "^2.1.1",
|
||||
"less-cache": "0.19.0",
|
||||
"marked": "^0.3",
|
||||
"mixto": "^1",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "^1.0.1",
|
||||
@@ -57,7 +58,7 @@
|
||||
"season": "^1.0.2",
|
||||
"semver": "2.2.1",
|
||||
"serializable": "^1",
|
||||
"space-pen": "3.8.1",
|
||||
"space-pen": "3.8.2",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.6.1",
|
||||
"theorist": "^1.0.2",
|
||||
@@ -66,9 +67,9 @@
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.22.0",
|
||||
"atom-dark-ui": "0.39.0",
|
||||
"atom-dark-ui": "0.40.0",
|
||||
"atom-light-syntax": "0.22.0",
|
||||
"atom-light-ui": "0.33.0",
|
||||
"atom-light-ui": "0.34.0",
|
||||
"base16-tomorrow-dark-theme": "0.22.0",
|
||||
"base16-tomorrow-light-theme": "0.5.0",
|
||||
"solarized-dark-syntax": "0.23.0",
|
||||
@@ -80,10 +81,10 @@
|
||||
"background-tips": "0.17.0",
|
||||
"bookmarks": "0.30.0",
|
||||
"bracket-matcher": "0.62.0",
|
||||
"command-palette": "0.27.0",
|
||||
"deprecation-cop": "0.13.0",
|
||||
"command-palette": "0.28.0",
|
||||
"deprecation-cop": "0.15.0",
|
||||
"dev-live-reload": "0.35.0",
|
||||
"encoding-selector": "0.7.0",
|
||||
"encoding-selector": "0.8.0",
|
||||
"exception-reporting": "0.20.0",
|
||||
"find-and-replace": "0.147.0",
|
||||
"fuzzy-finder": "0.60.0",
|
||||
@@ -95,13 +96,13 @@
|
||||
"keybinding-resolver": "0.20.0",
|
||||
"link": "0.26.0",
|
||||
"markdown-preview": "0.110.0",
|
||||
"metrics": "0.38.0",
|
||||
"metrics": "0.39.0",
|
||||
"open-on-github": "0.30.0",
|
||||
"package-generator": "0.32.0",
|
||||
"release-notes": "0.36.0",
|
||||
"settings-view": "0.160.0",
|
||||
"settings-view": "0.161.0",
|
||||
"snippets": "0.56.0",
|
||||
"spell-check": "0.43.0",
|
||||
"spell-check": "0.44.0",
|
||||
"status-bar": "0.46.0",
|
||||
"styleguide": "0.30.0",
|
||||
"symbols-view": "0.68.0",
|
||||
@@ -113,7 +114,7 @@
|
||||
"whitespace": "0.26.0",
|
||||
"wrap-guide": "0.24.0",
|
||||
"language-c": "0.31.0",
|
||||
"language-coffee-script": "0.37.0",
|
||||
"language-coffee-script": "0.38.0",
|
||||
"language-css": "0.23.0",
|
||||
"language-gfm": "0.53.0",
|
||||
"language-git": "0.9.0",
|
||||
@@ -121,7 +122,7 @@
|
||||
"language-html": "0.26.0",
|
||||
"language-hyperlink": "0.12.0",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.43.0",
|
||||
"language-javascript": "0.44.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.18.0",
|
||||
"language-make": "0.12.0",
|
||||
@@ -130,10 +131,10 @@
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.18.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.23.0",
|
||||
"language-python": "0.24.0",
|
||||
"language-ruby": "0.41.0",
|
||||
"language-ruby-on-rails": "0.18.0",
|
||||
"language-sass": "0.25.0",
|
||||
"language-sass": "0.26.0",
|
||||
"language-shellscript": "0.10.0",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.11.0",
|
||||
@@ -141,7 +142,7 @@
|
||||
"language-todo": "0.13.0",
|
||||
"language-toml": "0.14.0",
|
||||
"language-xml": "0.24.0",
|
||||
"language-yaml": "0.19.0"
|
||||
"language-yaml": "0.20.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -3,6 +3,7 @@ _ = require 'underscore-plus'
|
||||
{convertStackTrace} = require 'coffeestack'
|
||||
{View, $, $$} = require '../src/space-pen-extensions'
|
||||
grim = require 'grim'
|
||||
marked = require 'marked'
|
||||
|
||||
sourceMaps = {}
|
||||
formatStackTrace = (spec, message='', stackTrace) ->
|
||||
@@ -110,7 +111,8 @@ class AtomReporter extends View
|
||||
for deprecation in deprecations
|
||||
@deprecationList.append $$ ->
|
||||
@div class: 'padded', =>
|
||||
@div class: 'result-message fail deprecation-message', deprecation.message
|
||||
@div class: 'result-message fail deprecation-message', =>
|
||||
@raw marked(deprecation.message)
|
||||
|
||||
for stack in deprecation.stacks
|
||||
fullStack = stack.map ({functionName, location}) ->
|
||||
|
||||
+72
-3
@@ -5,9 +5,6 @@ Package = require '../src/package'
|
||||
ThemeManager = require '../src/theme-manager'
|
||||
|
||||
describe "the `atom` global", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
|
||||
describe 'window sizing methods', ->
|
||||
describe '::getPosition and ::setPosition', ->
|
||||
it 'sets the position of the window, and can retrieve the position just set', ->
|
||||
@@ -35,6 +32,9 @@ describe "the `atom` global", ->
|
||||
|
||||
describe "window:update-available", ->
|
||||
it "is triggered when the auto-updater sends the update-downloaded event", ->
|
||||
# FIXME: We need to figure out a way minus workspaceView to handle update-available events.
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
|
||||
updateAvailableHandler = jasmine.createSpy("update-available-handler")
|
||||
atom.workspaceView.on 'window:update-available', updateAvailableHandler
|
||||
autoUpdater = require('remote').require('auto-updater')
|
||||
@@ -52,3 +52,72 @@ describe "the `atom` global", ->
|
||||
it 'loads the default core config', ->
|
||||
expect(atom.config.get('core.excludeVcsIgnoredPaths')).toBe true
|
||||
expect(atom.config.get('editor.showInvisibles')).toBe false
|
||||
|
||||
describe "window onerror handler", ->
|
||||
beforeEach ->
|
||||
spyOn atom, 'openDevTools'
|
||||
spyOn atom, 'executeJavaScriptInDevTools'
|
||||
|
||||
it "will open the dev tools when an error is triggered", ->
|
||||
try
|
||||
a + 1
|
||||
catch e
|
||||
window.onerror.call(window, e.toString(), 'abc', 2, 3, e)
|
||||
|
||||
expect(atom.openDevTools).toHaveBeenCalled()
|
||||
expect(atom.executeJavaScriptInDevTools).toHaveBeenCalled()
|
||||
|
||||
describe "::onWillThrowError", ->
|
||||
willThrowSpy = null
|
||||
beforeEach ->
|
||||
willThrowSpy = jasmine.createSpy()
|
||||
|
||||
it "is called when there is an error", ->
|
||||
error = null
|
||||
atom.onWillThrowError(willThrowSpy)
|
||||
try
|
||||
a + 1
|
||||
catch e
|
||||
error = e
|
||||
window.onerror.call(window, e.toString(), 'abc', 2, 3, e)
|
||||
|
||||
delete willThrowSpy.mostRecentCall.args[0].preventDefault
|
||||
expect(willThrowSpy).toHaveBeenCalledWith
|
||||
message: error.toString()
|
||||
url: 'abc'
|
||||
line: 2
|
||||
column: 3
|
||||
originalError: error
|
||||
|
||||
it "will not show the devtools when preventDefault() is called", ->
|
||||
willThrowSpy.andCallFake (errorObject) -> errorObject.preventDefault()
|
||||
atom.onWillThrowError(willThrowSpy)
|
||||
|
||||
try
|
||||
a + 1
|
||||
catch e
|
||||
window.onerror.call(window, e.toString(), 'abc', 2, 3, e)
|
||||
|
||||
expect(willThrowSpy).toHaveBeenCalled()
|
||||
expect(atom.openDevTools).not.toHaveBeenCalled()
|
||||
expect(atom.executeJavaScriptInDevTools).not.toHaveBeenCalled()
|
||||
|
||||
describe "::onDidThrowError", ->
|
||||
didThrowSpy = null
|
||||
beforeEach ->
|
||||
didThrowSpy = jasmine.createSpy()
|
||||
|
||||
it "is called when there is an error", ->
|
||||
error = null
|
||||
atom.onDidThrowError(didThrowSpy)
|
||||
try
|
||||
a + 1
|
||||
catch e
|
||||
error = e
|
||||
window.onerror.call(window, e.toString(), 'abc', 2, 3, e)
|
||||
expect(didThrowSpy).toHaveBeenCalledWith
|
||||
message: error.toString()
|
||||
url: 'abc'
|
||||
line: 2
|
||||
column: 3
|
||||
originalError: error
|
||||
|
||||
@@ -9,5 +9,6 @@ module.exports =
|
||||
atom.commands.add 'atom-workspace', 'activation-command', =>
|
||||
@activationCommandCallCount++
|
||||
|
||||
atom.workspaceView.getActiveView()?.command 'activation-command', =>
|
||||
editorView = atom.views.getView(atom.workspace.getActiveEditor())?.__spacePenView
|
||||
editorView?.command 'activation-command', =>
|
||||
@legacyActivationCommandCallCount++
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
Package = require '../src/package'
|
||||
|
||||
describe "PackageManager", ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
|
||||
describe "::loadPackage(name)", ->
|
||||
it "continues if the package has an invalid package.json", ->
|
||||
@@ -111,7 +112,7 @@ describe "PackageManager", ->
|
||||
[mainModule, promise, workspaceCommandListener] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.workspaceView.attachToDom()
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
mainModule = require './fixtures/packages/package-with-activation-commands/index'
|
||||
mainModule.legacyActivationCommandCallCount = 0
|
||||
mainModule.activationCommandCallCount = 0
|
||||
@@ -125,29 +126,29 @@ describe "PackageManager", ->
|
||||
|
||||
it "defers requiring/activating the main module until an activation event bubbles to the root view", ->
|
||||
expect(promise.isFulfilled()).not.toBeTruthy()
|
||||
atom.workspaceView[0].dispatchEvent(new CustomEvent('activation-command', bubbles: true))
|
||||
workspaceElement.dispatchEvent(new CustomEvent('activation-command', bubbles: true))
|
||||
|
||||
waitsForPromise ->
|
||||
promise
|
||||
|
||||
it "triggers the activation event on all handlers registered during activation", ->
|
||||
waitsForPromise ->
|
||||
atom.workspaceView.open()
|
||||
atom.workspace.open()
|
||||
|
||||
runs ->
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
editorView = atom.views.getView(atom.workspace.getActiveEditor()).__spacePenView
|
||||
legacyCommandListener = jasmine.createSpy("legacyCommandListener")
|
||||
editorView.command 'activation-command', legacyCommandListener
|
||||
editorCommandListener = jasmine.createSpy("editorCommandListener")
|
||||
atom.commands.add 'atom-text-editor', 'activation-command', editorCommandListener
|
||||
editorView[0].dispatchEvent(new CustomEvent('activation-command', bubbles: true))
|
||||
atom.commands.dispatch(editorView[0], 'activation-command')
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
expect(mainModule.legacyActivationCommandCallCount).toBe 1
|
||||
expect(mainModule.activationCommandCallCount).toBe 1
|
||||
expect(legacyCommandListener.callCount).toBe 1
|
||||
expect(editorCommandListener.callCount).toBe 1
|
||||
expect(workspaceCommandListener.callCount).toBe 1
|
||||
editorView[0].dispatchEvent(new CustomEvent('activation-command', bubbles: true))
|
||||
atom.commands.dispatch(editorView[0], 'activation-command')
|
||||
expect(mainModule.legacyActivationCommandCallCount).toBe 2
|
||||
expect(mainModule.activationCommandCallCount).toBe 2
|
||||
expect(legacyCommandListener.callCount).toBe 2
|
||||
|
||||
@@ -135,8 +135,9 @@ afterEach ->
|
||||
atom.menu.template = []
|
||||
atom.contextMenu.clear()
|
||||
|
||||
atom.workspaceView?.remove?()
|
||||
atom.workspaceView = null
|
||||
atom.workspace?.destroy()
|
||||
atom.workspace = null
|
||||
atom.__workspaceView = null
|
||||
delete atom.state.workspace
|
||||
|
||||
atom.project?.destroy()
|
||||
@@ -191,6 +192,10 @@ jasmine.unspy = (object, methodName) ->
|
||||
throw new Error("Not a spy") unless object[methodName].hasOwnProperty('originalValue')
|
||||
object[methodName] = object[methodName].originalValue
|
||||
|
||||
jasmine.attachToDOM = (element) ->
|
||||
jasmineContent = document.querySelector('#jasmine-content')
|
||||
jasmineContent.appendChild(element) unless jasmineContent.contains(element)
|
||||
|
||||
addCustomMatchers = (spec) ->
|
||||
spec.addMatchers
|
||||
toBeInstanceOf: (expected) ->
|
||||
|
||||
@@ -2686,6 +2686,10 @@ describe "TextEditorComponent", ->
|
||||
|
||||
describe "middle mouse paste on Linux", ->
|
||||
it "pastes the previously selected text", ->
|
||||
spyOn(require('ipc'), 'send').andCallFake (eventName, selectedText) ->
|
||||
if eventName is 'write-text-to-selection-clipboard'
|
||||
require('clipboard').writeText(selectedText, 'selection')
|
||||
|
||||
atom.clipboard.write('')
|
||||
component.listenForMiddleMousePaste()
|
||||
|
||||
|
||||
@@ -2611,10 +2611,9 @@ describe "TextEditor", ->
|
||||
console.log JSON.stringify(editor.lineTextForBufferRow(1))
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(" y(); z();")
|
||||
|
||||
describe "when `autoIndentOnPaste` is false and `normalizeIndentOnPaste` is true", ->
|
||||
describe "when `autoIndentOnPaste` is false", ->
|
||||
beforeEach ->
|
||||
atom.config.set('editor.autoIndentOnPaste', false)
|
||||
atom.config.set('editor.normalizeIndentOnPaste', true)
|
||||
|
||||
describe "when the inserted text contains no newlines", ->
|
||||
it "does not adjust the indentation level of the text", ->
|
||||
@@ -2672,58 +2671,6 @@ describe "TextEditor", ->
|
||||
expect(editor.lineTextForBufferRow(3)).toBe " }"
|
||||
expect(editor.lineTextForBufferRow(4)).toBe ""
|
||||
|
||||
describe 'when scoped settings are used', ->
|
||||
coffeeEditor = null
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-coffee-script')
|
||||
waitsForPromise ->
|
||||
atom.project.open('coffee.coffee', autoIndent: false).then (o) ->
|
||||
coffeeEditor = o
|
||||
|
||||
runs ->
|
||||
atom.config.set('.source.js', 'editor.normalizeIndentOnPaste', true)
|
||||
atom.config.set('.source.coffee', 'editor.normalizeIndentOnPaste', false)
|
||||
|
||||
afterEach: ->
|
||||
atom.packages.deactivatePackages()
|
||||
atom.packages.unloadPackages()
|
||||
|
||||
it "normalizes the indentation level based on scoped settings", ->
|
||||
copyText(" while (true) {\n foo();\n }\n", {startColumn: 2, textEditor: coffeeEditor})
|
||||
coffeeEditor.setCursorBufferPosition([4, 4])
|
||||
coffeeEditor.pasteText()
|
||||
expect(coffeeEditor.lineTextForBufferRow(4)).toBe " while (true) {"
|
||||
expect(coffeeEditor.lineTextForBufferRow(5)).toBe " foo();"
|
||||
expect(coffeeEditor.lineTextForBufferRow(6)).toBe " }"
|
||||
|
||||
copyText(" while (true) {\n foo();\n }\n", {startColumn: 2})
|
||||
editor.setCursorBufferPosition([3, 4])
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(3)).toBe " while (true) {"
|
||||
expect(editor.lineTextForBufferRow(4)).toBe " foo();"
|
||||
expect(editor.lineTextForBufferRow(5)).toBe " }"
|
||||
|
||||
describe "when `autoIndentOnPaste` and `normalizeIndentOnPaste` are both false", ->
|
||||
beforeEach ->
|
||||
atom.config.set('editor.normalizeIndentOnPaste', false)
|
||||
atom.config.set("editor.autoIndentOnPaste", false)
|
||||
|
||||
it "does not auto-indent the pasted text", ->
|
||||
atom.clipboard.write("console.log(x);\nconsole.log(y);\n")
|
||||
editor.setCursorBufferPosition([5, 0])
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(5)).toBe("console.log(x);")
|
||||
expect(editor.lineTextForBufferRow(6)).toBe("console.log(y);")
|
||||
|
||||
it "does not normalize the indentation level of the text", ->
|
||||
copyText(" function() {\nvar cool = 1;\n }\n")
|
||||
editor.setCursorBufferPosition([5, 2])
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(5)).toBe " function() {"
|
||||
expect(editor.lineTextForBufferRow(6)).toBe "var cool = 1;"
|
||||
expect(editor.lineTextForBufferRow(7)).toBe " }"
|
||||
|
||||
describe 'when the clipboard has many selections', ->
|
||||
beforeEach ->
|
||||
atom.config.set("editor.autoIndentOnPaste", false)
|
||||
@@ -2747,6 +2694,39 @@ describe "TextEditor", ->
|
||||
expect(editor.lineTextForBufferRow(0)).toBe "var quicksort"
|
||||
expect(editor.lineTextForBufferRow(1)).toBe "sort = function () {"
|
||||
|
||||
describe "when a full line was cut", ->
|
||||
beforeEach ->
|
||||
editor.setCursorBufferPosition([2, 13])
|
||||
editor.cutSelectedText()
|
||||
editor.setCursorBufferPosition([2, 13])
|
||||
|
||||
it "pastes the line above the cursor and retains the cursor's column", ->
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(" if (items.length <= 1) return items;")
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(" var pivot = items.shift(), current, left = [], right = [];")
|
||||
expect(editor.getCursorBufferPosition()).toEqual([3, 13])
|
||||
|
||||
describe "when a full line was copied", ->
|
||||
beforeEach ->
|
||||
editor.setCursorBufferPosition([2, 13])
|
||||
editor.copySelectedText()
|
||||
|
||||
describe "when there is a selection", ->
|
||||
it "overwrites the selection as with any copied text", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [1, Infinity]])
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(" if (items.length <= 1) return items;")
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(" ")
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(" if (items.length <= 1) return items;")
|
||||
expect(editor.getCursorBufferPosition()).toEqual([2, 2])
|
||||
|
||||
describe "when there is no selection", ->
|
||||
it "pastes the line above the cursor and retains the cursor's column", ->
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(" if (items.length <= 1) return items;")
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(" if (items.length <= 1) return items;")
|
||||
expect(editor.getCursorBufferPosition()).toEqual([3, 13])
|
||||
|
||||
describe ".indentSelectedRows()", ->
|
||||
describe "when nothing is selected", ->
|
||||
describe "when softTabs is enabled", ->
|
||||
@@ -3438,6 +3418,16 @@ describe "TextEditor", ->
|
||||
editor.insertText('\n')
|
||||
expect(editor.indentationForBufferRow(1)).toBe 2
|
||||
|
||||
describe "when the line preceding the newline contains only whitespace", ->
|
||||
it "bases the new line's indentation on only the preceding line", ->
|
||||
editor.setCursorBufferPosition([6, Infinity])
|
||||
editor.insertText("\n ")
|
||||
expect(editor.getCursorBufferPosition()).toEqual([7, 2])
|
||||
|
||||
editor.insertNewline()
|
||||
editor.logScreenLines()
|
||||
expect(editor.lineTextForBufferRow(8)).toBe(" ")
|
||||
|
||||
it "does not indent the line preceding the newline", ->
|
||||
editor.setCursorBufferPosition([2, 0])
|
||||
editor.insertText(' var this-line-should-be-indented-more\n')
|
||||
|
||||
@@ -70,7 +70,7 @@ describe "ThemeManager", ->
|
||||
describe "when the core.themes config value changes", ->
|
||||
it "add/removes stylesheets to reflect the new config value", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null
|
||||
spyOn(atom.styles, 'getUserStyleSheetPath').andCallFake -> null
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
@@ -207,10 +207,11 @@ describe "ThemeManager", ->
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.append $('<atom-text-editor>')
|
||||
atom.workspaceView.attachToDom()
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
workspaceElement.appendChild document.createElement('atom-text-editor')
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
@@ -224,7 +225,7 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
# an override loaded in the base css
|
||||
expect(atom.workspaceView.css("background-color")).toBe "rgb(0, 0, 255)"
|
||||
expect(getComputedStyle(workspaceElement)["background-color"]).toBe "rgb(0, 0, 255)"
|
||||
|
||||
# from within the theme itself
|
||||
expect($("atom-text-editor").css("padding-top")).toBe "150px"
|
||||
@@ -241,14 +242,14 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
# an override loaded in the base css
|
||||
expect(atom.workspaceView.css("background-color")).toBe "rgb(0, 0, 255)"
|
||||
expect(getComputedStyle(workspaceElement)["background-color"]).toBe "rgb(0, 0, 255)"
|
||||
|
||||
# from within the theme itself
|
||||
expect($("atom-text-editor").css("background-color")).toBe "rgb(0, 152, 255)"
|
||||
|
||||
describe "theme classes on the workspace", ->
|
||||
it 'adds theme-* classes to the workspace for each active theme', ->
|
||||
expect(atom.workspaceView).toHaveClass 'theme-atom-dark-ui'
|
||||
expect(workspaceElement).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
@@ -258,17 +259,17 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(atom.workspaceView).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(atom.workspaceView).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(atom.workspaceView).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(atom.workspaceView).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
it "reloads it", ->
|
||||
[stylesheetRemovedHandler, stylesheetAddedHandler, stylesheetsChangedHandler] = []
|
||||
userStylesheetPath = path.join(temp.mkdirSync("atom"), 'styles.less')
|
||||
fs.writeFileSync(userStylesheetPath, 'body {border-style: dotted !important;}')
|
||||
spyOn(themeManager, 'getUserStylesheetPath').andReturn userStylesheetPath
|
||||
spyOn(atom.styles, 'getUserStyleSheetPath').andReturn userStylesheetPath
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
TooltipManager = require '../src/tooltip-manager'
|
||||
{$} = require '../src/space-pen-extensions'
|
||||
|
||||
describe "TooltipManager", ->
|
||||
[manager, element] = []
|
||||
|
||||
beforeEach ->
|
||||
manager = new TooltipManager
|
||||
element = document.createElement('div')
|
||||
element.classList.add('foo')
|
||||
jasmine.attachToDOM(element)
|
||||
|
||||
hover = (element, fn) ->
|
||||
$(element).trigger 'mouseenter'
|
||||
advanceClock(manager.defaults.delay.show)
|
||||
fn()
|
||||
$(element).trigger 'mouseleave'
|
||||
advanceClock(manager.defaults.delay.hide)
|
||||
|
||||
describe "::add(target, options)", ->
|
||||
describe "when the target is an element", ->
|
||||
it "creates a tooltip based on the given options when hovering over the target element", ->
|
||||
manager.add element, title: "Title"
|
||||
hover element, ->
|
||||
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
|
||||
|
||||
describe "when a keyBindingCommand is specified", ->
|
||||
describe "when a title is specified", ->
|
||||
it "appends the key binding corresponding to the command to the title", ->
|
||||
atom.keymaps.add 'test',
|
||||
'.foo': 'ctrl-x ctrl-y': 'test-command'
|
||||
'.bar': 'ctrl-x ctrl-z': 'test-command'
|
||||
|
||||
manager.add element, title: "Title", keyBindingCommand: 'test-command'
|
||||
|
||||
hover element, ->
|
||||
tooltipElement = document.body.querySelector(".tooltip")
|
||||
expect(tooltipElement).toHaveText "Title ⌃X ⌃Y"
|
||||
|
||||
describe "when no title is specified", ->
|
||||
it "shows the key binding corresponding to the command alone", ->
|
||||
atom.keymaps.add 'test', '.foo': 'ctrl-x ctrl-y': 'test-command'
|
||||
|
||||
manager.add element, keyBindingCommand: 'test-command'
|
||||
|
||||
hover element, ->
|
||||
tooltipElement = document.body.querySelector(".tooltip")
|
||||
expect(tooltipElement).toHaveText "⌃X ⌃Y"
|
||||
|
||||
describe "when a keyBindingTarget is specified", ->
|
||||
it "looks up the key binding relative to the target", ->
|
||||
atom.keymaps.add 'test',
|
||||
'.bar': 'ctrl-x ctrl-z': 'test-command'
|
||||
'.foo': 'ctrl-x ctrl-y': 'test-command'
|
||||
|
||||
manager.add element, keyBindingCommand: 'test-command', keyBindingTarget: element
|
||||
|
||||
hover element, ->
|
||||
tooltipElement = document.body.querySelector(".tooltip")
|
||||
expect(tooltipElement).toHaveText "⌃X ⌃Y"
|
||||
|
||||
describe "when .dispose() is called on the returned disposable", ->
|
||||
it "no longer displays the tooltip on hover", ->
|
||||
disposable = manager.add element, title: "Title"
|
||||
|
||||
hover element, ->
|
||||
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
|
||||
|
||||
disposable.dispose()
|
||||
|
||||
hover element, ->
|
||||
expect(document.body.querySelector(".tooltip")).toBeNull()
|
||||
@@ -112,9 +112,9 @@ describe "Window", ->
|
||||
|
||||
runs ->
|
||||
buffer = atom.workspace.getActivePaneItem().buffer
|
||||
pane = atom.workspaceView.getActivePaneView()
|
||||
pane.splitRight(pane.copyActiveItem())
|
||||
expect(atom.workspaceView.find('atom-text-editor').length).toBe 2
|
||||
pane = atom.workspace.getActivePane()
|
||||
pane.splitRight(copyActiveItem: true)
|
||||
expect(atom.workspace.getTextEditors().length).toBe 2
|
||||
|
||||
atom.removeEditorWindow()
|
||||
|
||||
|
||||
+71
-15
@@ -5,6 +5,7 @@ path = require 'path'
|
||||
remote = require 'remote'
|
||||
screen = require 'screen'
|
||||
shell = require 'shell'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{deprecate} = require 'grim'
|
||||
@@ -33,6 +34,23 @@ class Atom extends Model
|
||||
startTime = Date.now()
|
||||
atom = @deserialize(@loadState(mode)) ? new this({mode, @version})
|
||||
atom.deserializeTimings.atom = Date.now() - startTime
|
||||
|
||||
workspaceViewDeprecationMessage = """
|
||||
atom.workspaceView is no longer available.
|
||||
In most cases you will not need the view. See the Workspace docs for
|
||||
alternatives: https://atom.io/docs/api/latest/Workspace.
|
||||
If you do need the view, please use `atom.views.getView(atom.workspace)`,
|
||||
which returns an HTMLElement.
|
||||
"""
|
||||
|
||||
Object.defineProperty atom, 'workspaceView',
|
||||
get: ->
|
||||
deprecate(workspaceViewDeprecationMessage)
|
||||
atom.__workspaceView
|
||||
set: (newValue) ->
|
||||
deprecate(workspaceViewDeprecationMessage)
|
||||
atom.__workspaceView = newValue
|
||||
|
||||
atom
|
||||
|
||||
# Deserializes the Atom environment from a state object
|
||||
@@ -125,6 +143,9 @@ class Atom extends Model
|
||||
# Public: A {KeymapManager} instance
|
||||
keymaps: null
|
||||
|
||||
# Public: A {TooltipManager} instance
|
||||
tooltips: null
|
||||
|
||||
# Public: A {Project} instance
|
||||
project: null
|
||||
|
||||
@@ -137,6 +158,9 @@ class Atom extends Model
|
||||
# Public: A {ThemeManager} instance
|
||||
themes: null
|
||||
|
||||
# Public: A {StyleManager} instance
|
||||
styles: null
|
||||
|
||||
# Public: A {DeserializerManager} instance
|
||||
deserializers: null
|
||||
|
||||
@@ -146,9 +170,6 @@ class Atom extends Model
|
||||
# Public: A {Workspace} instance
|
||||
workspace: null
|
||||
|
||||
# Public: A {WorkspaceView} instance
|
||||
workspaceView: null
|
||||
|
||||
###
|
||||
Section: Construction and Destruction
|
||||
###
|
||||
@@ -173,11 +194,21 @@ class Atom extends Model
|
||||
require('grim').deprecate = ->
|
||||
|
||||
window.onerror = =>
|
||||
@openDevTools()
|
||||
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
|
||||
@lastUncaughtError = Array::slice.call(arguments)
|
||||
[message, url, line, column, originalError] = @lastUncaughtError
|
||||
eventObject = {message, url, line, column, originalError}
|
||||
|
||||
openDevTools = true
|
||||
eventObject.preventDefault = -> openDevTools = false
|
||||
|
||||
@emitter.emit 'will-throw-error', eventObject
|
||||
|
||||
if openDevTools
|
||||
@openDevTools()
|
||||
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
|
||||
|
||||
@emit 'uncaught-error', arguments...
|
||||
@emitter.emit 'did-throw-error', arguments...
|
||||
@emitter.emit 'did-throw-error', {message, url, line, column, originalError}
|
||||
|
||||
@unsubscribe()
|
||||
@setBodyPlatformClass()
|
||||
@@ -188,6 +219,7 @@ class Atom extends Model
|
||||
KeymapManager = require './keymap-extensions'
|
||||
ViewRegistry = require './view-registry'
|
||||
CommandRegistry = require './command-registry'
|
||||
TooltipManager = require './tooltip-manager'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
Syntax = require './syntax'
|
||||
@@ -213,6 +245,7 @@ class Atom extends Model
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@tooltips = new TooltipManager
|
||||
@commands = new CommandRegistry
|
||||
@views = new ViewRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@@ -248,10 +281,31 @@ class Atom extends Model
|
||||
onDidBeep: (callback) ->
|
||||
@emitter.on 'did-beep', callback
|
||||
|
||||
# Extended: Invoke the given callback when there is an unhandled error, but
|
||||
# before the devtools pop open
|
||||
#
|
||||
# * `callback` {Function} to be called whenever there is an unhandled error
|
||||
# * `event` {Object}
|
||||
# * `originalError` {Object} the original error object
|
||||
# * `message` {String} the original error object
|
||||
# * `url` {String} Url to the file where the error originated.
|
||||
# * `line` {Number}
|
||||
# * `column` {Number}
|
||||
# * `preventDefault` {Function} call this to avoid popping up the dev tools.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onWillThrowError: (callback) ->
|
||||
@emitter.on 'will-throw-error', callback
|
||||
|
||||
# Extended: Invoke the given callback whenever there is an unhandled error.
|
||||
#
|
||||
# * `callback` {Function} to be called whenever there is an unhandled error
|
||||
# * `errorMessage` {String}
|
||||
# * `event` {Object}
|
||||
# * `originalError` {Object} the original error object
|
||||
# * `message` {String} the original error object
|
||||
# * `url` {String} Url to the file where the error originated.
|
||||
# * `line` {Number}
|
||||
# * `column` {Number}
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidThrowError: (callback) ->
|
||||
@@ -513,7 +567,7 @@ class Atom extends Model
|
||||
@displayWindow({maximize})
|
||||
|
||||
unloadEditorWindow: ->
|
||||
return if not @project and not @workspaceView
|
||||
return if not @project
|
||||
|
||||
@state.syntax = @syntax.serialize()
|
||||
@state.project = @project.serialize()
|
||||
@@ -524,10 +578,10 @@ class Atom extends Model
|
||||
@windowState = null
|
||||
|
||||
removeEditorWindow: ->
|
||||
return if not @project and not @workspaceView
|
||||
return if not @project
|
||||
|
||||
@workspaceView?.remove()
|
||||
@workspaceView = null
|
||||
@workspace?.destroy()
|
||||
@workspace = null
|
||||
@project?.destroy()
|
||||
@project = null
|
||||
|
||||
@@ -540,7 +594,7 @@ class Atom extends Model
|
||||
# Essential: Visually and audibly trigger a beep.
|
||||
beep: ->
|
||||
shell.beep() if @config.get('core.audioBeep')
|
||||
@workspaceView.trigger 'beep'
|
||||
@__workspaceView.trigger 'beep'
|
||||
@emitter.emit 'did-beep'
|
||||
|
||||
# Essential: A flexible way to open a dialog akin to an alert dialog.
|
||||
@@ -616,11 +670,13 @@ class Atom extends Model
|
||||
|
||||
startTime = Date.now()
|
||||
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
|
||||
@workspaceView = @views.getView(@workspace).__spacePenView
|
||||
|
||||
workspaceElement = @views.getView(@workspace)
|
||||
@__workspaceView = workspaceElement.__spacePenView
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
|
||||
@keymaps.defaultTarget = @workspaceView[0]
|
||||
$(@workspaceViewParentSelector).append(@workspaceView)
|
||||
@keymaps.defaultTarget = workspaceElement
|
||||
document.querySelector(@workspaceViewParentSelector).appendChild(workspaceElement)
|
||||
|
||||
deserializePackageStates: ->
|
||||
@packages.packageStates = @state.packageStates ? {}
|
||||
|
||||
@@ -238,6 +238,11 @@ class AtomApplication
|
||||
win = BrowserWindow.fromWebContents(event.sender)
|
||||
win[method](args...)
|
||||
|
||||
clipboard = null
|
||||
ipc.on 'write-text-to-selection-clipboard', (event, selectedText) ->
|
||||
clipboard ?= require 'clipboard'
|
||||
clipboard.writeText(selectedText, 'selection')
|
||||
|
||||
# Public: Executes the given command.
|
||||
#
|
||||
# If it isn't handled globally, delegate to the currently focused window.
|
||||
|
||||
@@ -15,7 +15,12 @@ class AutoUpdateManager
|
||||
|
||||
constructor: (@version) ->
|
||||
@state = IdleState
|
||||
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
|
||||
if process.platform is 'win32'
|
||||
# Squirrel for Windows can't handle query params
|
||||
# https://github.com/Squirrel/Squirrel.Windows/issues/132
|
||||
@feedUrl = 'https://atom.io/api/updates'
|
||||
else
|
||||
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
|
||||
|
||||
process.nextTick => @setupAutoUpdater()
|
||||
|
||||
|
||||
@@ -13,6 +13,16 @@ process.on 'uncaughtException', (error={}) ->
|
||||
nslog(error.message) if error.message?
|
||||
nslog(error.stack) if error.stack?
|
||||
|
||||
# Patch fs.statSyncNoException/fs.lstatSyncNoException to fail for non-strings
|
||||
# https://github.com/atom/atom-shell/issues/843
|
||||
{lstatSyncNoException, statSyncNoException} = fs
|
||||
fs.statSyncNoException = (pathToStat) ->
|
||||
return false unless pathToStat and typeof pathToStat is 'string'
|
||||
statSyncNoException(pathToStat)
|
||||
fs.lstatSyncNoException = (pathToStat) ->
|
||||
return false unless pathToStat and typeof pathToStat is 'string'
|
||||
lstatSyncNoException(pathToStat)
|
||||
|
||||
start = ->
|
||||
if process.platform is 'win32'
|
||||
SquirrelUpdate = require './squirrel-update'
|
||||
|
||||
@@ -1,28 +1,176 @@
|
||||
app = require 'app'
|
||||
ChildProcess = require 'child_process'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
|
||||
updateDotExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe')
|
||||
rootAtomFolder = path.resolve(process.execPath, '..', '..')
|
||||
binFolder = path.join(rootAtomFolder, 'bin')
|
||||
updateDotExe = path.join(rootAtomFolder, 'Update.exe')
|
||||
exeName = path.basename(process.execPath)
|
||||
|
||||
# Spawn the Update.exe with the given arguments and invoke the callback when
|
||||
# the command completes.
|
||||
exports.spawn = (args, callback) ->
|
||||
updateProcess = ChildProcess.spawn(updateDotExe, args)
|
||||
if process.env.SystemRoot
|
||||
system32Path = path.join(process.env.SystemRoot, 'System32')
|
||||
regPath = path.join(system32Path, 'reg.exe')
|
||||
setxPath = path.join(system32Path, 'setx.exe')
|
||||
else
|
||||
regPath = 'reg.exe'
|
||||
setxPath = 'setx.exe'
|
||||
|
||||
# Registry keys used for context menu
|
||||
fileKeyPath = 'HKCU\\Software\\Classes\\*\\shell\\Atom'
|
||||
directoryKeyPath = 'HKCU\\Software\\Classes\\directory\\shell\\Atom'
|
||||
backgroundKeyPath = 'HKCU\\Software\\Classes\\directory\\background\\shell\\Atom'
|
||||
environmentKeyPath = 'HKCU\\Environment'
|
||||
|
||||
# Spawn a command and invoke the callback when it completes with an error
|
||||
# and the output from standard out.
|
||||
spawn = (command, args, callback) ->
|
||||
spawnedProcess = ChildProcess.spawn(command, args)
|
||||
|
||||
stdout = ''
|
||||
updateProcess.stdout.on 'data', (data) -> stdout += data
|
||||
spawnedProcess.stdout.on 'data', (data) -> stdout += data
|
||||
|
||||
error = null
|
||||
updateProcess.on 'error', (processError) -> error ?= processError
|
||||
updateProcess.on 'close', (code, signal) ->
|
||||
error ?= new Error("Command failed: #{signal}") if code isnt 0
|
||||
spawnedProcess.on 'error', (processError) -> error ?= processError
|
||||
spawnedProcess.on 'close', (code, signal) ->
|
||||
error ?= new Error("Command failed: #{signal ? code}") if code isnt 0
|
||||
error?.code ?= code
|
||||
error?.stdout ?= stdout
|
||||
callback(error, stdout)
|
||||
|
||||
undefined
|
||||
# Spawn reg.exe and callback when it completes
|
||||
spawnReg = (args, callback) ->
|
||||
spawn(regPath, args, callback)
|
||||
|
||||
# Spawn setx.exe and callback when it completes
|
||||
spawnSetx = (args, callback) ->
|
||||
spawn(setxPath, args, callback)
|
||||
|
||||
# Spawn the Update.exe with the given arguments and invoke the callback when
|
||||
# the command completes.
|
||||
spawnUpdate = (args, callback) ->
|
||||
spawn(updateDotExe, args, callback)
|
||||
|
||||
# Install the Open with Atom explorer context menu items via the registry.
|
||||
installContextMenu = (callback) ->
|
||||
addToRegistry = (args, callback) ->
|
||||
args.unshift('add')
|
||||
args.push('/f')
|
||||
spawnReg(args, callback)
|
||||
|
||||
installMenu = (keyPath, arg, callback) ->
|
||||
args = [keyPath, '/ve', '/d', 'Open with Atom']
|
||||
addToRegistry args, ->
|
||||
args = [keyPath, '/v', 'Icon', '/d', process.execPath]
|
||||
addToRegistry args, ->
|
||||
args = ["#{keyPath}\\command", '/ve', '/d', "#{process.execPath} \"#{arg}\""]
|
||||
addToRegistry(args, callback)
|
||||
|
||||
installMenu fileKeyPath, '%1', ->
|
||||
installMenu directoryKeyPath, '%1', ->
|
||||
installMenu(backgroundKeyPath, '%V', callback)
|
||||
|
||||
# Get the user's PATH environment variable registry value.
|
||||
getPath = (callback) ->
|
||||
spawnReg ['query', environmentKeyPath, '/v', 'Path'], (error, stdout) ->
|
||||
if error?
|
||||
if error.code is 1
|
||||
# The query failed so the Path does not exist yet in the registry
|
||||
return callback(null, '')
|
||||
else
|
||||
return callback(error)
|
||||
|
||||
# Registry query output is in the form:
|
||||
#
|
||||
# HKEY_CURRENT_USER\Environment
|
||||
# Path REG_SZ C:\a\folder\on\the\path;C\another\folder
|
||||
#
|
||||
|
||||
lines = stdout.split(/[\r\n]+/).filter (line) -> line
|
||||
segments = lines[lines.length - 1]?.split(' ')
|
||||
if segments[1] is 'Path' and segments.length >= 3
|
||||
pathEnv = segments?[3..].join(' ')
|
||||
callback(null, pathEnv)
|
||||
else
|
||||
callback(new Error('Registry query for PATH failed'))
|
||||
|
||||
# Uninstall the Open with Atom explorer context menu items via the registry.
|
||||
uninstallContextMenu = (callback) ->
|
||||
deleteFromRegistry = (keyPath, callback) ->
|
||||
spawnReg(['delete', keyPath, '/f'], callback)
|
||||
|
||||
deleteFromRegistry fileKeyPath, ->
|
||||
deleteFromRegistry directoryKeyPath, ->
|
||||
deleteFromRegistry(backgroundKeyPath, callback)
|
||||
|
||||
# Add atom and apm to the PATH
|
||||
#
|
||||
# This is done by adding .cmd shims to the root bin folder in the Atom
|
||||
# install directory that point to the newly installed versions inside
|
||||
# the versioned app directories.
|
||||
addCommandsToPath = (callback) ->
|
||||
installCommands = (callback) ->
|
||||
atomCommandPath = path.join(binFolder, 'atom.cmd')
|
||||
relativeExePath = path.relative(binFolder, process.execPath)
|
||||
atomCommand = """
|
||||
@echo off
|
||||
"%~dp0\\#{relativeExePath}" %*
|
||||
"""
|
||||
|
||||
apmCommandPath = path.join(binFolder, 'apm.cmd')
|
||||
relativeApmPath = path.relative(binFolder, path.join(process.resourcesPath, 'app', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm.cmd'))
|
||||
apmCommand = """
|
||||
@echo off
|
||||
"%~dp0\\#{relativeApmPath}" %*
|
||||
"""
|
||||
|
||||
fs.writeFile atomCommandPath, atomCommand, ->
|
||||
fs.writeFile apmCommandPath, apmCommand, ->
|
||||
callback()
|
||||
|
||||
addBinToPath = (pathSegments, callback) ->
|
||||
pathSegments.push(binFolder)
|
||||
newPathEnv = pathSegments.join(';')
|
||||
spawnSetx(['Path', newPathEnv], callback)
|
||||
|
||||
installCommands (error) ->
|
||||
return callback(error) if error?
|
||||
|
||||
getPath (error, pathEnv) ->
|
||||
return callback(error) if error?
|
||||
|
||||
pathSegments = pathEnv.split(/;+/).filter (pathSegment) -> pathSegment
|
||||
if pathSegments.indexOf(binFolder) is -1
|
||||
addBinToPath(pathSegments, callback)
|
||||
else
|
||||
callback()
|
||||
|
||||
# Remove atom and apm from the PATH
|
||||
removeCommandsFromPath = (callback) ->
|
||||
getPath (error, pathEnv) ->
|
||||
return callback(error) if error?
|
||||
|
||||
pathSegments = pathEnv.split(/;+/).filter (pathSegment) ->
|
||||
pathSegment and pathSegment isnt binFolder
|
||||
newPathEnv = pathSegments.join(';')
|
||||
|
||||
if pathEnv isnt newPathEnv
|
||||
spawnSetx(['Path', newPathEnv], callback)
|
||||
else
|
||||
callback()
|
||||
|
||||
|
||||
# Create a desktop and start menu shortcut by using the command line API
|
||||
# provided by Squirrel's Update.exe
|
||||
createShortcut = (callback) ->
|
||||
spawnUpdate(['--createShortcut', exeName], callback)
|
||||
|
||||
# Remove the desktop and start menu shortcuts by using the command line API
|
||||
# provided by Squirrel's Update.exe
|
||||
removeShortcut = (callback) ->
|
||||
spawnUpdate(['--removeShortcut', exeName], callback)
|
||||
|
||||
exports.spawn = spawnUpdate
|
||||
|
||||
# Is the Update.exe installed with Atom?
|
||||
exports.existsSync = ->
|
||||
@@ -32,10 +180,16 @@ exports.existsSync = ->
|
||||
exports.handleStartupEvent = ->
|
||||
switch process.argv[1]
|
||||
when '--squirrel-install', '--squirrel-updated'
|
||||
exports.spawn ['--createShortcut', exeName], -> app.quit()
|
||||
createShortcut ->
|
||||
installContextMenu ->
|
||||
addCommandsToPath ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-uninstall'
|
||||
exports.spawn ['--removeShortcut', exeName], -> app.quit()
|
||||
removeShortcut ->
|
||||
uninstallContextMenu ->
|
||||
removeCommandsFromPath ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-obsolete'
|
||||
app.quit()
|
||||
|
||||
+16
-11
@@ -1,9 +1,8 @@
|
||||
{basename, join} = require 'path'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{Subscriber} = require 'emissary'
|
||||
EmitterMixin = require('emissary').Emitter
|
||||
{Emitter} = require 'event-kit'
|
||||
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
|
||||
fs = require 'fs-plus'
|
||||
GitUtils = require 'git-utils'
|
||||
{deprecate} = require 'grim'
|
||||
@@ -45,7 +44,6 @@ Task = require './task'
|
||||
module.exports =
|
||||
class GitRepository
|
||||
EmitterMixin.includeInto(this)
|
||||
Subscriber.includeInto(this)
|
||||
|
||||
@exists: (path) ->
|
||||
if git = @open(path)
|
||||
@@ -75,6 +73,8 @@ class GitRepository
|
||||
|
||||
constructor: (path, options={}) ->
|
||||
@emitter = new Emitter
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
@repo = GitUtils.open(path)
|
||||
unless @repo?
|
||||
throw new Error("No Git repository found searching path: #{path}")
|
||||
@@ -88,13 +88,15 @@ class GitRepository
|
||||
|
||||
refreshOnWindowFocus ?= true
|
||||
if refreshOnWindowFocus
|
||||
{$} = require './space-pen-extensions'
|
||||
@subscribe $(window), 'focus', =>
|
||||
onWindowFocus = =>
|
||||
@refreshIndex()
|
||||
@refreshStatus()
|
||||
|
||||
window.addEventListener 'focus', onWindowFocus
|
||||
@subscriptions.add new Disposable(-> window.removeEventListener 'focus', onWindowFocus)
|
||||
|
||||
if @project?
|
||||
@subscribe @project.eachBuffer (buffer) => @subscribeToBuffer(buffer)
|
||||
@subscriptions.add @project.eachBuffer (buffer) => @subscribeToBuffer(buffer)
|
||||
|
||||
# Public: Destroy this {GitRepository} object.
|
||||
#
|
||||
@@ -109,7 +111,7 @@ class GitRepository
|
||||
@repo.release()
|
||||
@repo = null
|
||||
|
||||
@unsubscribe()
|
||||
@subscriptions.dispose()
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
@@ -403,10 +405,13 @@ class GitRepository
|
||||
if path = buffer.getPath()
|
||||
@getPathStatus(path)
|
||||
|
||||
@subscribe buffer.onDidSave(getBufferPathStatus)
|
||||
@subscribe buffer.onDidReload(getBufferPathStatus)
|
||||
@subscribe buffer.onDidChangePath(getBufferPathStatus)
|
||||
@subscribe buffer.onDidDestroy => @unsubscribe(buffer)
|
||||
bufferSubscriptions = new CompositeDisposable
|
||||
bufferSubscriptions.add buffer.onDidSave(getBufferPathStatus)
|
||||
bufferSubscriptions.add buffer.onDidReload(getBufferPathStatus)
|
||||
bufferSubscriptions.add buffer.onDidChangePath(getBufferPathStatus)
|
||||
bufferSubscriptions.add buffer.onDidDestroy =>
|
||||
bufferSubscriptions.dispose()
|
||||
@subscriptions.remove(bufferSubscriptions)
|
||||
|
||||
# Subscribes to editor view event.
|
||||
checkoutHeadForEditor: (editor) ->
|
||||
|
||||
@@ -244,14 +244,18 @@ class LanguageMode
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
#
|
||||
# Returns a {Number}.
|
||||
suggestedIndentForBufferRow: (bufferRow) ->
|
||||
suggestedIndentForBufferRow: (bufferRow, options) ->
|
||||
currentIndentLevel = @editor.indentationForBufferRow(bufferRow)
|
||||
scopeDescriptor = @editor.scopeDescriptorForBufferPosition([bufferRow, 0])
|
||||
return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopeDescriptor(scopeDescriptor)
|
||||
|
||||
currentLine = @buffer.lineForRow(bufferRow)
|
||||
precedingRow = @buffer.previousNonBlankRow(bufferRow)
|
||||
return 0 unless precedingRow?
|
||||
if options?.skipBlankLines ? true
|
||||
precedingRow = @buffer.previousNonBlankRow(bufferRow)
|
||||
return 0 unless precedingRow?
|
||||
else
|
||||
precedingRow = bufferRow - 1
|
||||
return currentIndentLevel if precedingRow < 0
|
||||
|
||||
precedingLine = @buffer.lineForRow(precedingRow)
|
||||
desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
|
||||
@@ -285,7 +289,7 @@ class LanguageMode
|
||||
# bufferRow - The row {Number}.
|
||||
# options - An options {Object} to pass through to {TextEditor::setIndentationForBufferRow}.
|
||||
autoIndentBufferRow: (bufferRow, options) ->
|
||||
indentLevel = @suggestedIndentForBufferRow(bufferRow)
|
||||
indentLevel = @suggestedIndentForBufferRow(bufferRow, options)
|
||||
@editor.setIndentationForBufferRow(bufferRow, indentLevel, options)
|
||||
|
||||
# Given a buffer row, this decreases the indentation.
|
||||
|
||||
@@ -95,7 +95,7 @@ class PaneElement extends HTMLElement
|
||||
|
||||
itemRemoved: ({item, index, destroyed}) ->
|
||||
if viewToRemove = @model.getView(item)
|
||||
callRemoveHooks(viewToRemove)
|
||||
callRemoveHooks(viewToRemove) if destroyed
|
||||
viewToRemove.remove()
|
||||
|
||||
paneDestroyed: ->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{View} = require './space-pen-extensions'
|
||||
|
||||
# Extended: Represents a view that scrolls.
|
||||
# Deprecated: Represents a view that scrolls.
|
||||
#
|
||||
# Handles several core events to update scroll position:
|
||||
#
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
TextEditorView = require './text-editor-view'
|
||||
fuzzyFilter = require('fuzzaldrin').filter
|
||||
|
||||
# Essential: Provides a view that renders a list of items with an editor that
|
||||
# Deprecated: Provides a view that renders a list of items with an editor that
|
||||
# filters the items. Used by many packages such as the fuzzy-finder,
|
||||
# command-palette, symbols-view and autocomplete.
|
||||
#
|
||||
|
||||
+17
-6
@@ -376,7 +376,7 @@ class Selection extends Model
|
||||
@editor.autoIndentBufferRow(row) for row, i in newBufferRange.getRows() when i > 0
|
||||
else if options.autoIndentNewline and text == '\n'
|
||||
currentIndentation = @editor.indentationForBufferRow(newBufferRange.start.row)
|
||||
@editor.autoIndentBufferRow(newBufferRange.end.row, preserveLeadingWhitespace: true)
|
||||
@editor.autoIndentBufferRow(newBufferRange.end.row, preserveLeadingWhitespace: true, skipBlankLines: false)
|
||||
if @editor.indentationForBufferRow(newBufferRange.end.row) < currentIndentation
|
||||
@editor.setIndentationForBufferRow(newBufferRange.end.row, currentIndentation)
|
||||
else if options.autoDecreaseIndent and NonWhitespaceRegExp.test(text)
|
||||
@@ -546,8 +546,9 @@ class Selection extends Model
|
||||
# Public: Copies the selection to the clipboard and then deletes it.
|
||||
#
|
||||
# * `maintainClipboard` {Boolean} (default: false) See {::copy}
|
||||
cut: (maintainClipboard=false) ->
|
||||
@copy(maintainClipboard)
|
||||
# * `fullLine` {Boolean} (default: false) See {::copy}
|
||||
cut: (maintainClipboard=false, fullLine=false) ->
|
||||
@copy(maintainClipboard, fullLine)
|
||||
@delete()
|
||||
|
||||
# Public: Copies the current selection to the clipboard.
|
||||
@@ -556,7 +557,10 @@ class Selection extends Model
|
||||
# is created to store each content copied to the clipboard. The clipboard
|
||||
# `text` still contains the concatenation of the clipboard with the
|
||||
# current selection. (default: false)
|
||||
copy: (maintainClipboard=false) ->
|
||||
# * `fullLine` {Boolean} if `true`, the copied text will always be pasted
|
||||
# at the beginning of the line containing the cursor, regardless of the
|
||||
# cursor's horizontal position. (default: false)
|
||||
copy: (maintainClipboard=false, fullLine=false) ->
|
||||
return if @isEmpty()
|
||||
selectionText = @editor.buffer.getTextInRange(@getBufferRange())
|
||||
selectionIndentation = @editor.indentationForBufferRow(@getBufferRange().start.row)
|
||||
@@ -569,10 +573,17 @@ class Selection extends Model
|
||||
text: clipboardText,
|
||||
indentBasis: metadata.indentBasis,
|
||||
}]
|
||||
metadata.selections.push(text: selectionText, indentBasis: selectionIndentation)
|
||||
metadata.selections.push({
|
||||
text: selectionText,
|
||||
indentBasis: selectionIndentation,
|
||||
fullLine: fullLine
|
||||
})
|
||||
atom.clipboard.write([clipboardText, selectionText].join("\n"), metadata)
|
||||
else
|
||||
atom.clipboard.write(selectionText, {indentBasis: selectionIndentation})
|
||||
atom.clipboard.write(selectionText, {
|
||||
indentBasis: selectionIndentation,
|
||||
fullLine: fullLine
|
||||
})
|
||||
|
||||
# Public: Creates a fold containing the current selection.
|
||||
fold: ->
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
{Emitter, Disposable} = require 'event-kit'
|
||||
|
||||
# Extended: A singleton instance of this class available via `atom.styles`,
|
||||
# which you can use to globally query and observe the set of active style
|
||||
# sheets. The `StyleManager` doesn't add any style elements to the DOM on its
|
||||
# own, but is instead subscribed to by individual `<atom-styles>` elements,
|
||||
# which clone and attach style elements in different contexts.
|
||||
module.exports =
|
||||
class StyleManager
|
||||
constructor: ->
|
||||
@@ -7,19 +14,78 @@ class StyleManager
|
||||
@styleElements = []
|
||||
@styleElementsBySourcePath = {}
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
# Extended: Invoke `callback` for all current and future style elements.
|
||||
#
|
||||
# * `callback` {Function} that is called with style elements.
|
||||
# * `styleElement` An `HTMLStyleElement` instance. The `.sheet` property
|
||||
# will be null because this element isn't attached to the DOM. If you want
|
||||
# to attach this element to the DOM, be sure to clone it first by calling
|
||||
# `.cloneNode(true)` on it. The style element will also have the following
|
||||
# non-standard properties:
|
||||
# * `sourcePath` A {String} containing the path from which the style
|
||||
# element was loaded.
|
||||
# * `context` A {String} indicating the target context of the style
|
||||
# element.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to cancel the
|
||||
# subscription.
|
||||
observeStyleElements: (callback) ->
|
||||
callback(styleElement) for styleElement in @getStyleElements()
|
||||
@onDidAddStyleElement(callback)
|
||||
|
||||
# Extended: Invoke `callback` when a style element is added.
|
||||
#
|
||||
# * `callback` {Function} that is called with style elements.
|
||||
# * `styleElement` An `HTMLStyleElement` instance. The `.sheet` property
|
||||
# will be null because this element isn't attached to the DOM. If you want
|
||||
# to attach this element to the DOM, be sure to clone it first by calling
|
||||
# `.cloneNode(true)` on it. The style element will also have the following
|
||||
# non-standard properties:
|
||||
# * `sourcePath` A {String} containing the path from which the style
|
||||
# element was loaded.
|
||||
# * `context` A {String} indicating the target context of the style
|
||||
# element.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to cancel the
|
||||
# subscription.
|
||||
onDidAddStyleElement: (callback) ->
|
||||
@emitter.on 'did-add-style-element', callback
|
||||
|
||||
# Extended: Invoke `callback` when a style element is removed.
|
||||
#
|
||||
# * `callback` {Function} that is called with style elements.
|
||||
# * `styleElement` An `HTMLStyleElement` instance.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to cancel the
|
||||
# subscription.
|
||||
onDidRemoveStyleElement: (callback) ->
|
||||
@emitter.on 'did-remove-style-element', callback
|
||||
|
||||
# Extended: Invoke `callback` when an existing style element is updated.
|
||||
#
|
||||
# * `callback` {Function} that is called with style elements.
|
||||
# * `styleElement` An `HTMLStyleElement` instance. The `.sheet` property
|
||||
# will be null because this element isn't attached to the DOM. The style
|
||||
# element will also have the following non-standard properties:
|
||||
# * `sourcePath` A {String} containing the path from which the style
|
||||
# element was loaded.
|
||||
# * `context` A {String} indicating the target context of the style
|
||||
# element.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to cancel the
|
||||
# subscription.
|
||||
onDidUpdateStyleElement: (callback) ->
|
||||
@emitter.on 'did-update-style-element', callback
|
||||
|
||||
###
|
||||
Section: Reading Style Elements
|
||||
###
|
||||
|
||||
# Extended: Get all loaded style elements.
|
||||
getStyleElements: ->
|
||||
@styleElements.slice()
|
||||
|
||||
@@ -85,3 +151,17 @@ class StyleManager
|
||||
existingStyleElements = @getStyleElements()
|
||||
for styleElement in styleElementsToRestore
|
||||
@addStyleElement(styleElement) unless styleElement in existingStyleElements
|
||||
|
||||
###
|
||||
Section: Paths
|
||||
###
|
||||
|
||||
# Extended: Get the path of the user style sheet in `~/.atom`.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getUserStyleSheetPath: ->
|
||||
stylesheetPath = fs.resolve(path.join(atom.getConfigDirPath(), 'styles'), ['css', 'less'])
|
||||
if fs.isFileSync(stylesheetPath)
|
||||
stylesheetPath
|
||||
else
|
||||
path.join(atom.getConfigDirPath(), 'styles.less')
|
||||
|
||||
@@ -6,6 +6,7 @@ scrollbarStyle = require 'scrollbar-style'
|
||||
{Range, Point} = require 'text-buffer'
|
||||
grim = require 'grim'
|
||||
{CompositeDisposable} = require 'event-kit'
|
||||
ipc = require 'ipc'
|
||||
|
||||
GutterComponent = require './gutter-component'
|
||||
InputComponent = require './input-component'
|
||||
@@ -198,7 +199,6 @@ TextEditorComponent = React.createClass
|
||||
componentWillUnmount: ->
|
||||
{editor, hostElement} = @props
|
||||
|
||||
hostElement.__spacePenView.trigger 'editor:will-be-removed', [hostElement.__spacePenView]
|
||||
@unsubscribe()
|
||||
@scopedConfigSubscriptions.dispose()
|
||||
window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
@@ -444,7 +444,10 @@ TextEditorComponent = React.createClass
|
||||
|
||||
@subscribe @props.editor.onDidChangeSelectionRange =>
|
||||
if selectedText = @props.editor.getSelectedText()
|
||||
clipboard.writeText(selectedText, 'selection')
|
||||
# This uses ipc.send instead of clipboard.writeText because
|
||||
# clipboard.writeText is a sync ipc call on Linux and that
|
||||
# will slow down selections.
|
||||
ipc.send('write-text-to-selection-clipboard', selectedText)
|
||||
|
||||
observeConfig: ->
|
||||
@subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration
|
||||
|
||||
@@ -7,7 +7,7 @@ TextEditorElement = require './text-editor-element'
|
||||
TextEditorComponent = require './text-editor-component'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
# Public: Represents the entire visual pane in Atom.
|
||||
# Deprecated: Represents the entire visual pane in Atom.
|
||||
#
|
||||
# The TextEditorView manages the {TextEditor}, which manages the file buffers.
|
||||
# `TextEditorView` is intentionally sparse. Most of the things you'll want
|
||||
@@ -138,6 +138,7 @@ class TextEditorView extends View
|
||||
|
||||
beforeRemove: ->
|
||||
@trigger 'editor:detached', [this]
|
||||
@trigger 'editor:will-be-removed', [this]
|
||||
@attached = false
|
||||
|
||||
remove: (selector, keepData) ->
|
||||
|
||||
@@ -2448,7 +2448,8 @@ class TextEditor extends Model
|
||||
@commentScopeSelector.matches(scopeDescriptor)
|
||||
|
||||
logCursorScope: ->
|
||||
console.log @getLastCursor().getScopeDescriptor()
|
||||
scopeDescriptor = @getLastCursor().getScopeDescriptor()
|
||||
console.log scopeDescriptor.scopes, scopeDescriptor
|
||||
|
||||
# {Delegates to: DisplayBuffer.tokenForBufferPosition}
|
||||
tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition)
|
||||
@@ -2471,18 +2472,21 @@ class TextEditor extends Model
|
||||
if selection.isEmpty()
|
||||
previousRange = selection.getBufferRange()
|
||||
selection.selectLine()
|
||||
selection.copy(maintainClipboard)
|
||||
selection.copy(maintainClipboard, true)
|
||||
selection.setBufferRange(previousRange)
|
||||
else
|
||||
selection.copy(maintainClipboard)
|
||||
selection.copy(maintainClipboard, false)
|
||||
maintainClipboard = true
|
||||
|
||||
# Essential: For each selection, cut the selected text.
|
||||
cutSelectedText: ->
|
||||
maintainClipboard = false
|
||||
@mutateSelectedText (selection) ->
|
||||
selection.selectLine() if selection.isEmpty()
|
||||
selection.cut(maintainClipboard)
|
||||
if selection.isEmpty()
|
||||
selection.selectLine()
|
||||
selection.cut(maintainClipboard, true)
|
||||
else
|
||||
selection.cut(maintainClipboard, false)
|
||||
maintainClipboard = true
|
||||
|
||||
# Essential: For each selection, replace the selected text with the contents of
|
||||
@@ -2500,18 +2504,26 @@ class TextEditor extends Model
|
||||
|
||||
@mutateSelectedText (selection, index) =>
|
||||
if metadata.selections?.length is @getSelections().length
|
||||
{text, indentBasis} = metadata.selections[index]
|
||||
{text, indentBasis, fullLine} = metadata.selections[index]
|
||||
else
|
||||
[text, indentBasis] = [clipboardText, metadata.indentBasis]
|
||||
{indentBasis, fullLine} = metadata
|
||||
text = clipboardText
|
||||
|
||||
delete options.indentBasis
|
||||
{cursor} = selection
|
||||
if indentBasis? and atom.config.get(cursor.getScopeDescriptor(), "editor.normalizeIndentOnPaste")
|
||||
if indentBasis?
|
||||
containsNewlines = text.indexOf('\n') isnt -1
|
||||
if containsNewlines or !cursor.hasPrecedingCharactersOnLine()
|
||||
options.indentBasis ?= indentBasis
|
||||
|
||||
selection.insertText(text, options)
|
||||
if fullLine and selection.isEmpty()
|
||||
oldPosition = selection.getBufferRange().start
|
||||
selection.setBufferRange([[oldPosition.row, 0], [oldPosition.row, 0]])
|
||||
selection.insertText(text, options)
|
||||
newPosition = oldPosition.translate([1, 0])
|
||||
selection.setBufferRange([newPosition, newPosition])
|
||||
else
|
||||
selection.insertText(text, options)
|
||||
|
||||
# Public: For each selection, if the selection is empty, cut all characters
|
||||
# of the containing line following the cursor. Otherwise cut the selected
|
||||
|
||||
+27
-27
@@ -6,7 +6,7 @@ EmitterMixin = require('emissary').Emitter
|
||||
{File} = require 'pathwatcher'
|
||||
fs = require 'fs-plus'
|
||||
Q = require 'q'
|
||||
{deprecate} = require 'grim'
|
||||
Grim = require 'grim'
|
||||
|
||||
Package = require './package'
|
||||
|
||||
@@ -57,61 +57,66 @@ class ThemeManager
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
# Essential: Invoke `callback` when all styles have been reloaded.
|
||||
# Essential: Invoke `callback` when style sheet changes associated with
|
||||
# updating the list of active themes have completed.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
onDidReloadAll: (callback) ->
|
||||
@emitter.on 'did-reload-all', callback
|
||||
|
||||
# Essential: Invoke `callback` when a stylesheet has been added to the dom.
|
||||
# Deprecated: Invoke `callback` when a stylesheet has been added to the dom.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
# * `stylesheet` {StyleSheet} the style node
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidAddStylesheet: (callback) ->
|
||||
Grim.deprecate("Use atom.styles.onDidAddStyleElement instead")
|
||||
@emitter.on 'did-add-stylesheet', callback
|
||||
|
||||
# Essential: Invoke `callback` when a stylesheet has been removed from the dom.
|
||||
# Deprecated: Invoke `callback` when a stylesheet has been removed from the dom.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
# * `stylesheet` {StyleSheet} the style node
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidRemoveStylesheet: (callback) ->
|
||||
Grim.deprecate("Use atom.styles.onDidRemoveStyleElement instead")
|
||||
@emitter.on 'did-remove-stylesheet', callback
|
||||
|
||||
# Essential: Invoke `callback` when a stylesheet has been updated.
|
||||
# Deprecated: Invoke `callback` when a stylesheet has been updated.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
# * `stylesheet` {StyleSheet} the style node
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidUpdateStylesheet: (callback) ->
|
||||
Grim.deprecate("Use atom.styles.onDidUpdateStyleElement instead")
|
||||
@emitter.on 'did-update-stylesheet', callback
|
||||
|
||||
# Essential: Invoke `callback` when any stylesheet has been updated, added, or removed.
|
||||
# Deprecated: Invoke `callback` when any stylesheet has been updated, added, or removed.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidChangeStylesheets: (callback) ->
|
||||
Grim.deprecate("Use atom.styles.onDidAdd/RemoveStyleElement instead")
|
||||
@emitter.on 'did-change-stylesheets', callback
|
||||
|
||||
on: (eventName) ->
|
||||
switch eventName
|
||||
when 'reloaded'
|
||||
deprecate 'Use ThemeManager::onDidReloadAll instead'
|
||||
Grim.deprecate 'Use ThemeManager::onDidReloadAll instead'
|
||||
when 'stylesheet-added'
|
||||
deprecate 'Use ThemeManager::onDidAddStylesheet instead'
|
||||
Grim.deprecate 'Use ThemeManager::onDidAddStylesheet instead'
|
||||
when 'stylesheet-removed'
|
||||
deprecate 'Use ThemeManager::onDidRemoveStylesheet instead'
|
||||
Grim.deprecate 'Use ThemeManager::onDidRemoveStylesheet instead'
|
||||
when 'stylesheet-updated'
|
||||
deprecate 'Use ThemeManager::onDidUpdateStylesheet instead'
|
||||
Grim.deprecate 'Use ThemeManager::onDidUpdateStylesheet instead'
|
||||
when 'stylesheets-changed'
|
||||
deprecate 'Use ThemeManager::onDidChangeStylesheets instead'
|
||||
Grim.deprecate 'Use ThemeManager::onDidChangeStylesheets instead'
|
||||
else
|
||||
deprecate 'ThemeManager::on is deprecated. Use event subscription methods instead.'
|
||||
Grim.deprecate 'ThemeManager::on is deprecated. Use event subscription methods instead.'
|
||||
EmitterMixin::on.apply(this, arguments)
|
||||
|
||||
###
|
||||
@@ -197,18 +202,15 @@ class ThemeManager
|
||||
atom.config.set('core.themes', enabledThemeNames)
|
||||
|
||||
###
|
||||
Section: Managing Stylesheets
|
||||
Section: Private
|
||||
###
|
||||
|
||||
# Public: Returns the {String} path to the user's stylesheet under ~/.atom
|
||||
# Returns the {String} path to the user's stylesheet under ~/.atom
|
||||
getUserStylesheetPath: ->
|
||||
stylesheetPath = fs.resolve(path.join(@configDirPath, 'styles'), ['css', 'less'])
|
||||
if fs.isFileSync(stylesheetPath)
|
||||
stylesheetPath
|
||||
else
|
||||
path.join(@configDirPath, 'styles.less')
|
||||
Grim.deprecate("Call atom.styles.getUserStyleSheetPath() instead")
|
||||
atom.styles.getUserStyleSheetPath()
|
||||
|
||||
# Public: Resolve and apply the stylesheet specified by the path.
|
||||
# Resolve and apply the stylesheet specified by the path.
|
||||
#
|
||||
# This supports both CSS and Less stylsheets.
|
||||
#
|
||||
@@ -231,7 +233,7 @@ class ThemeManager
|
||||
|
||||
loadUserStylesheet: ->
|
||||
@unwatchUserStylesheet()
|
||||
userStylesheetPath = @getUserStylesheetPath()
|
||||
userStylesheetPath = atom.styles.getUserStyleSheetPath()
|
||||
return unless fs.isFileSync(userStylesheetPath)
|
||||
|
||||
@userStylesheetPath = userStylesheetPath
|
||||
@@ -292,10 +294,6 @@ class ThemeManager
|
||||
applyStylesheet: (path, text, type='bundled') ->
|
||||
@styleSheetDisposablesBySourcePath[path] = atom.styles.addStyleSheet(text, sourcePath: path, group: type)
|
||||
|
||||
###
|
||||
Section: Private
|
||||
###
|
||||
|
||||
stringToId: (string) ->
|
||||
string.replace(/\\/g, '/')
|
||||
|
||||
@@ -336,13 +334,15 @@ class ThemeManager
|
||||
isInitialLoadComplete: -> @initialLoadComplete
|
||||
|
||||
addActiveThemeClasses: ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
for pack in @getActiveThemes()
|
||||
atom.workspaceView?[0]?.classList.add("theme-#{pack.name}")
|
||||
workspaceElement.classList.add("theme-#{pack.name}")
|
||||
return
|
||||
|
||||
removeActiveThemeClasses: ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
for pack in @getActiveThemes()
|
||||
atom.workspaceView?[0]?.classList.remove("theme-#{pack.name}")
|
||||
workspaceElement.classList.remove("theme-#{pack.name}")
|
||||
return
|
||||
|
||||
refreshLessCache: ->
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
_ = require 'underscore-plus'
|
||||
{Disposable} = require 'event-kit'
|
||||
{$} = require './space-pen-extensions'
|
||||
|
||||
# Essential: Associates tooltips with HTML elements or selectors.
|
||||
module.exports =
|
||||
class TooltipManager
|
||||
defaults:
|
||||
delay:
|
||||
show: 1000
|
||||
hide: 100
|
||||
container: 'body'
|
||||
html: true
|
||||
placement: 'auto top'
|
||||
viewportPadding: 2
|
||||
|
||||
# Essential: Add a tooltip to the given element.
|
||||
#
|
||||
# * `target` An `HTMLElement`
|
||||
# * `options` See http://getbootstrap.com/javascript/#tooltips for a full list
|
||||
# of options. You can also supply the following additional options:
|
||||
# * `keyBindingCommand` A {String} containing a command name. If you specify
|
||||
# this option and a key binding exists that matches the command, it will
|
||||
# be appended to the title or rendered alone if no title is specified.
|
||||
# * `keyBindingTarget` An `HTMLElement` on which to look up the key binding.
|
||||
# If this option is not supplied, the first of all matching key bindings
|
||||
# for the given command will be rendered.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# tooltip.
|
||||
add: (target, options) ->
|
||||
requireBootstrapTooltip()
|
||||
|
||||
{keyBindingCommand, keyBindingTarget} = options
|
||||
|
||||
if keyBindingCommand?
|
||||
bindings = atom.keymaps.findKeyBindings(command: keyBindingCommand, target: keyBindingTarget)
|
||||
if options.title?
|
||||
options.title += " " + getKeystroke(bindings)
|
||||
else
|
||||
options.title = getKeystroke(bindings)
|
||||
|
||||
$target = $(target)
|
||||
$target.tooltip(_.defaults(options, @defaults))
|
||||
|
||||
new Disposable -> $target.tooltip('destroy')
|
||||
|
||||
humanizeKeystrokes = (keystroke) ->
|
||||
keystrokes = keystroke.split(' ')
|
||||
keystrokes = (_.humanizeKeystroke(stroke) for stroke in keystrokes)
|
||||
keystrokes.join(' ')
|
||||
|
||||
getKeystroke = (bindings) ->
|
||||
if bindings?.length
|
||||
"<span class=\"keystroke\">#{humanizeKeystrokes(bindings[0].keystrokes)}</span>"
|
||||
else
|
||||
|
||||
requireBootstrapTooltip = _.once ->
|
||||
atom.requireWithGlobals('bootstrap/js/tooltip', {jQuery: $})
|
||||
@@ -89,22 +89,22 @@ class ViewRegistry
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting An Editor View
|
||||
# ### Getting An Editor Element
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorView = atom.views.getView(textEditor)
|
||||
# textEditorElement = atom.views.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane View
|
||||
# ### Getting A Pane Element
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneView = atom.views.getView(pane)
|
||||
# paneElement = atom.views.getView(pane)
|
||||
# ```
|
||||
#
|
||||
# ### Getting The Workspace View
|
||||
# ### Getting The Workspace Element
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceView = atom.views.getView(atom.workspace)
|
||||
# workspaceElement = atom.views.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# * `object` The object for which you want to retrieve a view. This can be a
|
||||
|
||||
@@ -15,11 +15,13 @@ class WindowEventHandler
|
||||
@reloadRequested = false
|
||||
|
||||
@subscribe ipc, 'command', (command, args...) ->
|
||||
|
||||
activeElement = document.activeElement
|
||||
# Use root view if body has focus
|
||||
if activeElement is document.body and atom.workspaceView?
|
||||
activeElement = atom.workspaceView
|
||||
$(activeElement).trigger(command, args...)
|
||||
# Use the workspace element view if body has focus
|
||||
if activeElement is document.body and workspaceElement = atom.views.getView(atom.workspace)
|
||||
activeElement = workspaceElement
|
||||
|
||||
atom.commands.dispatch(activeElement, command, args[0])
|
||||
|
||||
@subscribe ipc, 'context-command', (command, args...) ->
|
||||
$(atom.contextMenu.activeElement).trigger(command, args...)
|
||||
|
||||
@@ -12,7 +12,7 @@ PaneView = require './pane-view'
|
||||
PaneContainerView = require './pane-container-view'
|
||||
TextEditor = require './text-editor'
|
||||
|
||||
# Extended: The top-level view for the entire window. An instance of this class is
|
||||
# Deprecated: The top-level view for the entire window. An instance of this class is
|
||||
# available via the `atom.workspaceView` global.
|
||||
#
|
||||
# It is backed by a model object, an instance of {Workspace}, which is available
|
||||
|
||||
@@ -61,7 +61,7 @@ class Workspace extends Model
|
||||
@addOpener (filePath) =>
|
||||
switch filePath
|
||||
when 'atom://.atom/stylesheet'
|
||||
@open(atom.themes.getUserStylesheetPath())
|
||||
@open(atom.styles.getUserStyleSheetPath())
|
||||
when 'atom://.atom/keymap'
|
||||
@open(atom.keymaps.getUserKeymapPath())
|
||||
when 'atom://.atom/config'
|
||||
|
||||
@@ -2,8 +2,26 @@ window.onload = function() {
|
||||
try {
|
||||
var startTime = Date.now();
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Patch fs.statSyncNoException/fs.lstatSyncNoException to fail for non-strings
|
||||
// https://github.com/atom/atom-shell/issues/843
|
||||
var statSyncNoException = fs.statSyncNoException;
|
||||
var lstatSyncNoException = fs.lstatSyncNoException;
|
||||
fs.statSyncNoException = function(pathToStat) {
|
||||
if (pathToStat && typeof pathToStat === 'string')
|
||||
return statSyncNoException(pathToStat);
|
||||
else
|
||||
return false;
|
||||
};
|
||||
fs.lstatSyncNoException = function(pathToStat) {
|
||||
if (pathToStat && typeof pathToStat === 'string')
|
||||
return lstatSyncNoException(pathToStat);
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
// Skip "?loadSettings=".
|
||||
var loadSettings = JSON.parse(decodeURIComponent(location.search.substr(14)));
|
||||
|
||||
|
||||
@@ -136,7 +136,14 @@ body {
|
||||
}
|
||||
|
||||
.result-message.deprecation-message {
|
||||
color: #f0ad4e;
|
||||
font-weight: normal;
|
||||
color: darken(#f0ad4e, 20%);
|
||||
line-height: 1.4;
|
||||
|
||||
code {
|
||||
color: darken(#f0ad4e, 20%);
|
||||
background: lighten(#f0ad4e, 35%);
|
||||
}
|
||||
}
|
||||
|
||||
.stack-trace {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário