Comparar commits
193 Commits
v0.147.0
...
bo-messages
| Autor | SHA1 | Data | |
|---|---|---|---|
| aaee54bd08 | |||
| 1ae8862a9c | |||
| f3dd757537 | |||
| 68693e3ca0 | |||
| e24a562387 | |||
| 9c6a5fb4fa | |||
| 25caaa92f1 | |||
| 78ee02f0c6 | |||
| e462fdc4ce | |||
| 96d8721c9e | |||
| 568151b1a5 | |||
| 3d6c9ee554 | |||
| d5d6422d28 | |||
| 5727865b94 | |||
| b95b86396e | |||
| d75c35285c | |||
| a7bc7c198d | |||
| d2f24615c1 | |||
| e4b942e991 | |||
| c9f8ffc749 | |||
| c2086eee0e | |||
| d5a66c590a | |||
| b374c1a11a | |||
| 35f8e6a5a7 | |||
| 36a9ad7d90 | |||
| 6ff304094f | |||
| 0e51def6be | |||
| f366a67fee | |||
| f30f0de45e | |||
| 9e36cd705e | |||
| 2a5081f0e0 | |||
| 2c93b1459e | |||
| bf83fb7b10 | |||
| f4cc8c31b3 | |||
| e62ecbab6b | |||
| 4cef3bfef5 | |||
| 85fae83195 | |||
| f79b78054c | |||
| e803c06b28 | |||
| 1963a7f437 | |||
| 48eb5307e6 | |||
| 95d6ab1d4f | |||
| 9224c86452 | |||
| 0fa2b4426a | |||
| 1e4e59ad1c | |||
| 97a56574e0 | |||
| c06fefce14 | |||
| 00027e892c | |||
| d4dee07b41 | |||
| f475552673 | |||
| 6e33f10050 | |||
| 61651db0b0 | |||
| 982346b142 | |||
| 92ba107c89 | |||
| 7b4a9aa2e4 | |||
| 446398ad01 | |||
| 8afbab311f | |||
| 32f2a95f07 | |||
| d53d01d95b | |||
| 131522f93d | |||
| 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 | |||
| fc90a3c2ba | |||
| 382a06028c |
@@ -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)
|
||||
|
||||
|
||||
@@ -11,32 +11,34 @@ value of a namespaced config key with `atom.config.get`:
|
||||
@showInvisibles() if atom.config.get "editor.showInvisibles"
|
||||
```
|
||||
|
||||
Or you can use the `::subscribe` with `atom.config.observe` to track changes
|
||||
from any view object.
|
||||
Or you can subscribe via `atom.config.observe` to track changes from any view
|
||||
object.
|
||||
|
||||
```coffeescript
|
||||
{View} = require 'space-pen'
|
||||
|
||||
class MyView extends View
|
||||
initialize: ->
|
||||
@subscribe atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
|
||||
@adjustFontSize()
|
||||
attached: ->
|
||||
@fontSizeObserveSubscription =
|
||||
atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
|
||||
@adjustFontSize()
|
||||
|
||||
detached: ->
|
||||
@fontSizeObserveSubscription.dispose()
|
||||
```
|
||||
|
||||
The `atom.config.observe` method will call the given callback immediately with
|
||||
the current value for the specified key path, and it will also call it in the
|
||||
future whenever the value of that key path changes.
|
||||
future whenever the value of that key path changes. If you only want to invoke
|
||||
the callback when the next time the value changes, use `atom.config.onDidChange`
|
||||
instead.
|
||||
|
||||
Subscriptions made with `::subscribe` are automatically canceled when the
|
||||
view is removed. You can cancel config subscriptions manually via the
|
||||
`off` method on the subscription object that `atom.config.observe` returns.
|
||||
|
||||
```coffeescript
|
||||
fontSizeSubscription = atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
|
||||
@adjustFontSize()
|
||||
|
||||
# ... later on
|
||||
|
||||
fontSizeSubscription.off() # Stop observing
|
||||
```
|
||||
Subscription methods return *disposable* subscription objects. Note in the
|
||||
example above how we save the subscription to the `@fontSizeObserveSubscription`
|
||||
instance variable and dispose of it when the view is detached. To group multiple
|
||||
subscriptions together, you can add them all to a
|
||||
[`CompositeDisposable`][composite-disposable] that you dispose when the view is
|
||||
detached.
|
||||
|
||||
### Writing Config Settings
|
||||
|
||||
@@ -48,10 +50,9 @@ but you can programmatically write to it with `atom.config.set`:
|
||||
atom.config.set("core.showInvisibles", true)
|
||||
```
|
||||
|
||||
You can also use `setDefaults`, which will assign default values for keys that
|
||||
are always overridden by values assigned with `set`. Defaults are not written
|
||||
out to the the `config.json` file to prevent it from becoming cluttered.
|
||||
If you're exposing package configuration via specific key paths, you'll want to
|
||||
associate them with a schema in your package's main module. Read more about
|
||||
schemas in the [config API docs][config-api].
|
||||
|
||||
```coffeescript
|
||||
atom.config.setDefaults("editor", fontSize: 18, showInvisibles: true)
|
||||
```
|
||||
[composite-disposable]: https://atom.io/docs/api/latest/CompositeDisposable
|
||||
[config-api]: https://atom.io/docs/api/latest/Config
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# Globals
|
||||
|
||||
Atom exposes several services through singleton objects accessible via the
|
||||
`atom` global:
|
||||
|
||||
* atom
|
||||
* 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
|
||||
types.
|
||||
* config:
|
||||
Read, write, and observe user configuration settings.
|
||||
* keymap:
|
||||
Add and query the currently active keybindings.
|
||||
* deserializers:
|
||||
Deserialize instances from their state objects and register deserializers.
|
||||
* packages:
|
||||
Activate, deactivate, and query user packages.
|
||||
* themes:
|
||||
Activate, deactivate, and query user themes.
|
||||
* contextMenu:
|
||||
Register context menus.
|
||||
* menu:
|
||||
Register application menus.
|
||||
* pasteboard:
|
||||
Read from and write to the system pasteboard.
|
||||
* syntax:
|
||||
Assign and query syntactically-scoped properties.
|
||||
@@ -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
|
||||
@@ -30,6 +30,8 @@ All requests that take parameters require `application/json`.
|
||||
Parameters:
|
||||
|
||||
- **page** (optional)
|
||||
- **sort** (optional, values: `created_at`, `updated_at`, `downloads`)
|
||||
- **direction** (optional, values: `asc`, `desc`)
|
||||
|
||||
Returns a list of all packages in the following format:
|
||||
```json
|
||||
@@ -57,6 +59,20 @@ Link: <https://www.atom.io/api/packages?page=1>; rel="self",
|
||||
<https://www.atom.io/api/packages?page=2>; rel="next"
|
||||
```
|
||||
|
||||
By default, results are sorted by download count, descending.
|
||||
|
||||
#### GET /api/packages/search
|
||||
|
||||
Parameters:
|
||||
|
||||
- **q** String query to search
|
||||
- **sort** (optional, values: `created_at`, `updated_at`, `downloads`)
|
||||
- **direction** (optional, values: `asc`, `desc`)
|
||||
|
||||
Returns a list of all packages in the same format as `/api/packages`.
|
||||
|
||||
By default, results sorted by relevance to search query.
|
||||
|
||||
### Showing package details
|
||||
|
||||
#### GET /api/packages/:package_name
|
||||
|
||||
@@ -40,7 +40,7 @@ package.json files have their own additions.
|
||||
- `main` (**Required**): the path to the CoffeeScript file that's the entry point
|
||||
to your package
|
||||
- `stylesheets` (**Optional**): an Array of Strings identifying the order of the
|
||||
stylesheets your package needs to load. If not specified, stylesheets in the
|
||||
style sheets your package needs to load. If not specified, style sheets in the
|
||||
_stylesheets_ directory are added alphabetically.
|
||||
- `keymaps`(**Optional**): an Array of Strings identifying the order of the
|
||||
key mappings your package needs to load. If not specified, mappings in the
|
||||
@@ -119,27 +119,27 @@ Also, please collaborate with us if you need an API that doesn't exist. Our goal
|
||||
is to build out Atom's API organically based on the needs of package authors
|
||||
like you.
|
||||
|
||||
## Stylesheets
|
||||
## Style Sheets
|
||||
|
||||
Stylesheets for your package should be placed in the _stylesheets_ directory.
|
||||
Any stylesheets in this directory will be loaded and attached to the DOM when
|
||||
your package is activated. Stylesheets can be written as CSS or [LESS] (but LESS
|
||||
is recommended).
|
||||
Style sheets for your package should be placed in the _stylesheets_ directory.
|
||||
Any style sheets in this directory will be loaded and attached to the DOM when
|
||||
your package is activated. Style sheets can be written as CSS or [LESS] (but
|
||||
LESS is recommended).
|
||||
|
||||
Ideally, you won't need much in the way of styling. We've provided a standard
|
||||
set of components which define both the colors and UI elements for any package
|
||||
that fits into Atom seamlessly. You can view all of Atom's UI components by opening
|
||||
the styleguide: open the command palette (`cmd-shift-P`) and search for _styleguide_,
|
||||
or just type `cmd-ctrl-shift-G`.
|
||||
that fits into Atom seamlessly. You can view all of Atom's UI components by
|
||||
opening the styleguide: open the command palette (`cmd-shift-P`) and search for
|
||||
_styleguide_, or just type `cmd-ctrl-shift-G`.
|
||||
|
||||
If you _do_ need special styling, try to keep only structural styles in the package
|
||||
stylesheets. If you _must_ specify colors and sizing, these should be taken from
|
||||
the active theme's [ui-variables.less][ui-variables]. For more information, see the
|
||||
[theme variables docs][theme-variables]. If you follow this guideline, your package
|
||||
will look good out of the box with any theme!
|
||||
If you _do_ need special styling, try to keep only structural styles in the
|
||||
package style sheets. If you _must_ specify colors and sizing, these should be
|
||||
taken from the active theme's [ui-variables.less][ui-variables]. For more
|
||||
information, see the [theme variables docs][theme-variables]. If you follow this
|
||||
guideline, your package will look good out of the box with any theme!
|
||||
|
||||
An optional `stylesheets` array in your _package.json_ can list the stylesheets
|
||||
by name to specify a loading order; otherwise, stylesheets are loaded
|
||||
An optional `stylesheets` array in your _package.json_ can list the style sheets
|
||||
by name to specify a loading order; otherwise, style sheets are loaded
|
||||
alphabetically.
|
||||
|
||||
## Keymaps
|
||||
@@ -157,9 +157,9 @@ loaded in alphabetical order. An optional `keymaps` array in your _package.json_
|
||||
can specify which keymaps to load and in what order.
|
||||
|
||||
|
||||
Keybindings are executed by determining which element the keypress occurred on. In
|
||||
the example above, `changer:magic` command is executed when pressing `ctrl-V` on
|
||||
the `.tree-view-scroller` element.
|
||||
Keybindings are executed by determining which element the keypress occurred on.
|
||||
In the example above, `changer:magic` command is executed when pressing `ctrl-V`
|
||||
on the `.tree-view-scroller` element.
|
||||
|
||||
See the [main keymaps documentation][keymaps] for more detailed information on
|
||||
how keymaps work.
|
||||
@@ -195,7 +195,8 @@ with your package that aren't tied to a specific element:
|
||||
```
|
||||
|
||||
To add your own item to the application menu, simply create a top level `menu`
|
||||
key in any menu configuration file in _menus_. This can be a JSON or [CSON] file.
|
||||
key in any menu configuration file in _menus_. This can be a JSON or [CSON]
|
||||
file.
|
||||
|
||||
The menu templates you specify are merged with all other templates provided
|
||||
by other packages in the order which they were loaded.
|
||||
|
||||
@@ -118,7 +118,6 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu.
|
||||
- `cr`: Carriage return (for Microsoft-style line endings)
|
||||
- `eol`: `\n` characters
|
||||
- `space`: Leading and trailing space characters
|
||||
- `normalizeIndentOnPaste`: Enable/disable conversion of pasted tabs to spaces
|
||||
- `preferredLineLength`: Identifies the length of a line (defaults to `80`)
|
||||
- `showInvisibles`: Whether to render placeholders for invisible characters (defaults to `false`)
|
||||
- `showIndentGuide`: Show/hide indent indicators within the editor
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -6,6 +6,7 @@ module.exports =
|
||||
BufferedNodeProcess: require '../src/buffered-node-process'
|
||||
BufferedProcess: require '../src/buffered-process'
|
||||
GitRepository: require '../src/git-repository'
|
||||
Notification: require '../src/notification'
|
||||
Point: Point
|
||||
Range: Range
|
||||
Emitter: Emitter
|
||||
@@ -43,7 +44,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
`{$} = require 'space-pen'`
|
||||
or
|
||||
`$ = require 'jquery'`
|
||||
Add `"space-pen": "^3"` to your package dependencies.
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
Or add `"jquery": "^2"` to your package dependencies.
|
||||
"""
|
||||
$
|
||||
@@ -53,7 +54,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Requiring `$$` from `atom` is no longer supported.
|
||||
Please require `space-pen` instead:
|
||||
`{$$} = require 'space-pen'`
|
||||
Add `"space-pen": "^3"` to your package dependencies.
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
"""
|
||||
$$
|
||||
|
||||
@@ -62,7 +63,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Requiring `$$$` from `atom` is no longer supported.
|
||||
Please require `space-pen` instead:
|
||||
`{$$$} = require 'space-pen'`
|
||||
Add `"space-pen": "^3"` to your package dependencies.
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
"""
|
||||
$$$
|
||||
|
||||
@@ -71,7 +72,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Requiring `View` from `atom` is no longer supported.
|
||||
Please require `space-pen` instead:
|
||||
`{View} = require 'space-pen'`
|
||||
Add `"space-pen": "^3"` to your package dependencies.
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
"""
|
||||
View
|
||||
|
||||
|
||||
+25
-24
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.147.0",
|
||||
"version": "0.152.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,7 +17,7 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.19.2",
|
||||
"atomShellVersion": "0.19.4",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.2.2",
|
||||
@@ -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,18 +58,18 @@
|
||||
"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",
|
||||
"text-buffer": "^3.7.2",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.1",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.22.0",
|
||||
"atom-dark-ui": "0.39.0",
|
||||
"atom-dark-syntax": "0.23.0",
|
||||
"atom-dark-ui": "0.41.0",
|
||||
"atom-light-syntax": "0.22.0",
|
||||
"atom-light-ui": "0.33.0",
|
||||
"atom-light-ui": "0.35.0",
|
||||
"base16-tomorrow-dark-theme": "0.22.0",
|
||||
"base16-tomorrow-light-theme": "0.5.0",
|
||||
"solarized-dark-syntax": "0.23.0",
|
||||
@@ -80,48 +81,48 @@
|
||||
"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.18.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",
|
||||
"git-diff": "0.43.0",
|
||||
"go-to-line": "0.26.0",
|
||||
"grammar-selector": "0.37.0",
|
||||
"image-view": "0.40.0",
|
||||
"image-view": "0.42.0",
|
||||
"incompatible-packages": "0.10.0",
|
||||
"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",
|
||||
"status-bar": "0.46.0",
|
||||
"spell-check": "0.44.0",
|
||||
"status-bar": "0.47.0",
|
||||
"styleguide": "0.30.0",
|
||||
"symbols-view": "0.68.0",
|
||||
"tabs": "0.56.0",
|
||||
"timecop": "0.23.0",
|
||||
"tree-view": "0.132.0",
|
||||
"tree-view": "0.134.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.19.0",
|
||||
"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-gfm": "0.54.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.19.0",
|
||||
"language-html": "0.26.0",
|
||||
"language-hyperlink": "0.12.0",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.43.0",
|
||||
"language-javascript": "0.45.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.18.0",
|
||||
"language-make": "0.12.0",
|
||||
@@ -130,18 +131,18 @@
|
||||
"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",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.13.0",
|
||||
"language-toml": "0.14.0",
|
||||
"language-xml": "0.24.0",
|
||||
"language-yaml": "0.19.0"
|
||||
"language-xml": "0.25.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++
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
NotificationManager = require '../src/notification-manager'
|
||||
|
||||
describe "NotificationManager", ->
|
||||
[manager] = []
|
||||
|
||||
beforeEach ->
|
||||
manager = new NotificationManager
|
||||
|
||||
describe "the atom global", ->
|
||||
it "has a notifications instance", ->
|
||||
expect(atom.notifications instanceof NotificationManager).toBe true
|
||||
|
||||
describe "adding events", ->
|
||||
addSpy = null
|
||||
|
||||
beforeEach ->
|
||||
addSpy = jasmine.createSpy()
|
||||
manager.onDidAddNotification(addSpy)
|
||||
|
||||
it "emits an event when a notification has been added", ->
|
||||
manager.add('error', 'Some error!', icon: 'someIcon')
|
||||
expect(addSpy).toHaveBeenCalled()
|
||||
|
||||
notification = addSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'error'
|
||||
expect(notification.getMessage()).toBe 'Some error!'
|
||||
expect(notification.getIcon()).toBe 'someIcon'
|
||||
|
||||
it "emits a fatal error ::addFatalError has been called", ->
|
||||
manager.addFatalError('Some error!', icon: 'someIcon')
|
||||
expect(addSpy).toHaveBeenCalled()
|
||||
notification = addSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'fatal'
|
||||
|
||||
it "emits an error ::addError has been called", ->
|
||||
manager.addError('Some error!', icon: 'someIcon')
|
||||
expect(addSpy).toHaveBeenCalled()
|
||||
notification = addSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'error'
|
||||
|
||||
it "emits a warning notification ::addWarning has been called", ->
|
||||
manager.addWarning('Something!', icon: 'someIcon')
|
||||
expect(addSpy).toHaveBeenCalled()
|
||||
notification = addSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'warning'
|
||||
|
||||
it "emits an info notification ::addInfo has been called", ->
|
||||
manager.addInfo('Something!', icon: 'someIcon')
|
||||
expect(addSpy).toHaveBeenCalled()
|
||||
notification = addSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'info'
|
||||
|
||||
it "emits a success notification ::addSuccess has been called", ->
|
||||
manager.addSuccess('Something!', icon: 'someIcon')
|
||||
expect(addSpy).toHaveBeenCalled()
|
||||
notification = addSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'success'
|
||||
@@ -0,0 +1,18 @@
|
||||
Notification = require '../src/notification'
|
||||
|
||||
describe "Notification", ->
|
||||
[notification] = []
|
||||
|
||||
describe "::getTimestamp()", ->
|
||||
it "returns a Date object", ->
|
||||
notification = new Notification('error', 'message!')
|
||||
expect(notification.getTimestamp() instanceof Date).toBe true
|
||||
|
||||
describe "::getIcon()", ->
|
||||
it "returns a default when no icon specified", ->
|
||||
notification = new Notification('error', 'message!')
|
||||
expect(notification.getIcon()).toBe 'flame'
|
||||
|
||||
it "returns the icon specified", ->
|
||||
notification = new Notification('error', 'message!', icon: 'my-icon')
|
||||
expect(notification.getIcon()).toBe 'my-icon'
|
||||
@@ -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
|
||||
@@ -349,8 +350,8 @@ describe "PackageManager", ->
|
||||
atom.packages.activatePackage('package-with-grammars')
|
||||
|
||||
runs ->
|
||||
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Alot'
|
||||
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Alittle'
|
||||
expect(atom.grammars.selectGrammar('a.alot').name).toBe 'Alot'
|
||||
expect(atom.grammars.selectGrammar('a.alittle').name).toBe 'Alittle'
|
||||
|
||||
describe "scoped-property loading", ->
|
||||
it "loads the scoped properties", ->
|
||||
@@ -362,13 +363,13 @@ describe "PackageManager", ->
|
||||
|
||||
describe "converted textmate packages", ->
|
||||
it "loads the package's grammars", ->
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-ruby')
|
||||
|
||||
runs ->
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
|
||||
it "loads the translated scoped properties", ->
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
@@ -454,8 +455,8 @@ describe "PackageManager", ->
|
||||
|
||||
runs ->
|
||||
atom.packages.deactivatePackage('package-with-grammars')
|
||||
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Null Grammar'
|
||||
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Null Grammar'
|
||||
expect(atom.grammars.selectGrammar('a.alot').name).toBe 'Null Grammar'
|
||||
expect(atom.grammars.selectGrammar('a.alittle').name).toBe 'Null Grammar'
|
||||
|
||||
it "removes the package's keymaps", ->
|
||||
waitsForPromise ->
|
||||
@@ -490,15 +491,15 @@ describe "PackageManager", ->
|
||||
|
||||
describe "textmate packages", ->
|
||||
it "removes the package's grammars", ->
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-ruby')
|
||||
|
||||
runs ->
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
atom.packages.deactivatePackage('language-ruby')
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
|
||||
it "removes the package's scoped properties", ->
|
||||
waitsForPromise ->
|
||||
@@ -526,8 +527,8 @@ describe "PackageManager", ->
|
||||
atom.packages.deactivatePackages()
|
||||
atom.packages.unloadPackages()
|
||||
|
||||
Syntax = require '../src/syntax'
|
||||
atom.syntax = window.syntax = new Syntax()
|
||||
GrammarRegistry = require '../src/grammar-registry'
|
||||
atom.grammars = window.syntax = new GrammarRegistry()
|
||||
|
||||
it "activates all the packages, and none of the themes", ->
|
||||
atom.packages.activate()
|
||||
|
||||
@@ -82,7 +82,7 @@ beforeEach ->
|
||||
serializedWindowState = null
|
||||
|
||||
spyOn(atom, 'saveSync')
|
||||
atom.syntax.clearGrammarOverrides()
|
||||
atom.grammars.clearGrammarOverrides()
|
||||
|
||||
spy = spyOn(atom.packages, 'resolvePackagePath').andCallFake (packageName) ->
|
||||
if specPackageName and packageName is specPackageName
|
||||
@@ -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()
|
||||
@@ -150,7 +151,7 @@ afterEach ->
|
||||
|
||||
jasmine.unspy(atom, 'saveSync')
|
||||
ensureNoPathSubscriptions()
|
||||
atom.syntax.clearObservers()
|
||||
atom.grammars.clearObservers()
|
||||
waits(0) # yield to ui thread to make screen update more frequently
|
||||
|
||||
ensureNoPathSubscriptions = ->
|
||||
@@ -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) ->
|
||||
|
||||
+45
-45
@@ -23,10 +23,10 @@ describe "the `syntax` global", ->
|
||||
describe "serialization", ->
|
||||
it "remembers grammar overrides by path", ->
|
||||
filePath = '/foo/bar/file.js'
|
||||
expect(atom.syntax.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
atom.syntax.setGrammarOverrideForPath(filePath, 'source.ruby')
|
||||
syntax2 = atom.deserializers.deserialize(atom.syntax.serialize())
|
||||
syntax2.addGrammar(grammar) for grammar in atom.syntax.grammars when grammar isnt atom.syntax.nullGrammar
|
||||
expect(atom.grammars.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
atom.grammars.setGrammarOverrideForPath(filePath, 'source.ruby')
|
||||
syntax2 = atom.deserializers.deserialize(atom.grammars.serialize())
|
||||
syntax2.addGrammar(grammar) for grammar in atom.grammars.grammars when grammar isnt atom.grammars.nullGrammar
|
||||
expect(syntax2.selectGrammar(filePath).name).toBe 'Ruby'
|
||||
|
||||
describe ".selectGrammar(filePath)", ->
|
||||
@@ -35,15 +35,15 @@ describe "the `syntax` global", ->
|
||||
atom.packages.activatePackage('language-git')
|
||||
|
||||
runs ->
|
||||
expect(atom.syntax.selectGrammar("file.js").name).toBe "JavaScript" # based on extension (.js)
|
||||
expect(atom.syntax.selectGrammar(path.join(temp.dir, '.git', 'config')).name).toBe "Git Config" # based on end of the path (.git/config)
|
||||
expect(atom.syntax.selectGrammar("Rakefile").name).toBe "Ruby" # based on the file's basename (Rakefile)
|
||||
expect(atom.syntax.selectGrammar("curb").name).toBe "Null Grammar"
|
||||
expect(atom.syntax.selectGrammar("/hu.git/config").name).toBe "Null Grammar"
|
||||
expect(atom.grammars.selectGrammar("file.js").name).toBe "JavaScript" # based on extension (.js)
|
||||
expect(atom.grammars.selectGrammar(path.join(temp.dir, '.git', 'config')).name).toBe "Git Config" # based on end of the path (.git/config)
|
||||
expect(atom.grammars.selectGrammar("Rakefile").name).toBe "Ruby" # based on the file's basename (Rakefile)
|
||||
expect(atom.grammars.selectGrammar("curb").name).toBe "Null Grammar"
|
||||
expect(atom.grammars.selectGrammar("/hu.git/config").name).toBe "Null Grammar"
|
||||
|
||||
it "uses the filePath's shebang line if the grammar cannot be determined by the extension or basename", ->
|
||||
filePath = require.resolve("./fixtures/shebang")
|
||||
expect(atom.syntax.selectGrammar(filePath).name).toBe "Ruby"
|
||||
expect(atom.grammars.selectGrammar(filePath).name).toBe "Ruby"
|
||||
|
||||
it "uses the number of newlines in the first line regex to determine the number of lines to test against", ->
|
||||
waitsForPromise ->
|
||||
@@ -51,28 +51,28 @@ describe "the `syntax` global", ->
|
||||
|
||||
runs ->
|
||||
fileContent = "first-line\n<html>"
|
||||
expect(atom.syntax.selectGrammar("dummy.coffee", fileContent).name).toBe "CoffeeScript"
|
||||
expect(atom.grammars.selectGrammar("dummy.coffee", fileContent).name).toBe "CoffeeScript"
|
||||
|
||||
fileContent = '<?xml version="1.0" encoding="UTF-8"?>'
|
||||
expect(atom.syntax.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Null Grammar"
|
||||
expect(atom.grammars.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Null Grammar"
|
||||
|
||||
fileContent += '\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
|
||||
expect(atom.syntax.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Property List (XML)"
|
||||
expect(atom.grammars.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Property List (XML)"
|
||||
|
||||
it "doesn't read the file when the file contents are specified", ->
|
||||
filePath = require.resolve("./fixtures/shebang")
|
||||
filePathContents = fs.readFileSync(filePath, 'utf8')
|
||||
spyOn(fs, 'read').andCallThrough()
|
||||
expect(atom.syntax.selectGrammar(filePath, filePathContents).name).toBe "Ruby"
|
||||
expect(atom.grammars.selectGrammar(filePath, filePathContents).name).toBe "Ruby"
|
||||
expect(fs.read).not.toHaveBeenCalled()
|
||||
|
||||
it "allows the default grammar to be overridden for a path", ->
|
||||
filePath = '/foo/bar/file.js'
|
||||
expect(atom.syntax.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
atom.syntax.setGrammarOverrideForPath(filePath, 'source.ruby')
|
||||
expect(atom.syntax.selectGrammar(filePath).name).toBe 'Ruby'
|
||||
atom.syntax.clearGrammarOverrideForPath(filePath)
|
||||
expect(atom.syntax.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
expect(atom.grammars.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
atom.grammars.setGrammarOverrideForPath(filePath, 'source.ruby')
|
||||
expect(atom.grammars.selectGrammar(filePath).name).toBe 'Ruby'
|
||||
atom.grammars.clearGrammarOverrideForPath(filePath)
|
||||
expect(atom.grammars.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
|
||||
describe "when multiple grammars have matching fileTypes", ->
|
||||
it "selects the grammar with the longest fileType match", ->
|
||||
@@ -82,8 +82,8 @@ describe "the `syntax` global", ->
|
||||
scopeName: 'source1'
|
||||
fileTypes: ['test']
|
||||
)
|
||||
grammar1 = atom.syntax.loadGrammarSync(grammarPath1)
|
||||
expect(atom.syntax.selectGrammar('more.test', '')).toBe grammar1
|
||||
grammar1 = atom.grammars.loadGrammarSync(grammarPath1)
|
||||
expect(atom.grammars.selectGrammar('more.test', '')).toBe grammar1
|
||||
|
||||
grammarPath2 = temp.path(suffix: '.json')
|
||||
fs.writeFileSync grammarPath2, JSON.stringify(
|
||||
@@ -91,44 +91,44 @@ describe "the `syntax` global", ->
|
||||
scopeName: 'source2'
|
||||
fileTypes: ['test', 'more.test']
|
||||
)
|
||||
grammar2 = atom.syntax.loadGrammarSync(grammarPath2)
|
||||
expect(atom.syntax.selectGrammar('more.test', '')).toBe grammar2
|
||||
grammar2 = atom.grammars.loadGrammarSync(grammarPath2)
|
||||
expect(atom.grammars.selectGrammar('more.test', '')).toBe grammar2
|
||||
|
||||
describe "when there is no file path", ->
|
||||
it "does not throw an exception (regression)", ->
|
||||
expect(-> atom.syntax.selectGrammar(null, '#!/usr/bin/ruby')).not.toThrow()
|
||||
expect(-> atom.syntax.selectGrammar(null, '')).not.toThrow()
|
||||
expect(-> atom.syntax.selectGrammar(null, null)).not.toThrow()
|
||||
expect(-> atom.grammars.selectGrammar(null, '#!/usr/bin/ruby')).not.toThrow()
|
||||
expect(-> atom.grammars.selectGrammar(null, '')).not.toThrow()
|
||||
expect(-> atom.grammars.selectGrammar(null, null)).not.toThrow()
|
||||
|
||||
describe ".removeGrammar(grammar)", ->
|
||||
it "removes the grammar, so it won't be returned by selectGrammar", ->
|
||||
grammar = atom.syntax.selectGrammar('foo.js')
|
||||
atom.syntax.removeGrammar(grammar)
|
||||
expect(atom.syntax.selectGrammar('foo.js').name).not.toBe grammar.name
|
||||
grammar = atom.grammars.selectGrammar('foo.js')
|
||||
atom.grammars.removeGrammar(grammar)
|
||||
expect(atom.grammars.selectGrammar('foo.js').name).not.toBe grammar.name
|
||||
|
||||
describe ".getProperty(scopeDescriptor)", ->
|
||||
it "returns the property with the most specific scope selector", ->
|
||||
atom.syntax.addProperties(".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
|
||||
atom.syntax.addProperties(".source .string.quoted.double", foo: bar: baz: 22)
|
||||
atom.syntax.addProperties(".source", foo: bar: baz: 11)
|
||||
atom.grammars.addProperties(".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
|
||||
atom.grammars.addProperties(".source .string.quoted.double", foo: bar: baz: 22)
|
||||
atom.grammars.addProperties(".source", foo: bar: baz: 11)
|
||||
|
||||
expect(atom.syntax.getProperty([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42
|
||||
expect(atom.syntax.getProperty([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBe 22
|
||||
expect(atom.syntax.getProperty([".source.js", ".variable.assignment.js"], "foo.bar.baz")).toBe 11
|
||||
expect(atom.syntax.getProperty([".text"], "foo.bar.baz")).toBeUndefined()
|
||||
expect(atom.grammars.getProperty([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42
|
||||
expect(atom.grammars.getProperty([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBe 22
|
||||
expect(atom.grammars.getProperty([".source.js", ".variable.assignment.js"], "foo.bar.baz")).toBe 11
|
||||
expect(atom.grammars.getProperty([".text"], "foo.bar.baz")).toBeUndefined()
|
||||
|
||||
it "favors the most recently added properties in the event of a specificity tie", ->
|
||||
atom.syntax.addProperties(".source.coffee .string.quoted.single", foo: bar: baz: 42)
|
||||
atom.syntax.addProperties(".source.coffee .string.quoted.double", foo: bar: baz: 22)
|
||||
atom.grammars.addProperties(".source.coffee .string.quoted.single", foo: bar: baz: 42)
|
||||
atom.grammars.addProperties(".source.coffee .string.quoted.double", foo: bar: baz: 22)
|
||||
|
||||
expect(atom.syntax.getProperty([".source.coffee", ".string.quoted.single"], "foo.bar.baz")).toBe 42
|
||||
expect(atom.syntax.getProperty([".source.coffee", ".string.quoted.single.double"], "foo.bar.baz")).toBe 22
|
||||
expect(atom.grammars.getProperty([".source.coffee", ".string.quoted.single"], "foo.bar.baz")).toBe 42
|
||||
expect(atom.grammars.getProperty([".source.coffee", ".string.quoted.single.double"], "foo.bar.baz")).toBe 22
|
||||
|
||||
describe ".removeProperties(name)", ->
|
||||
it "allows properties to be removed by name", ->
|
||||
atom.syntax.addProperties("a", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
|
||||
atom.syntax.addProperties("b", ".source .string.quoted.double", foo: bar: baz: 22)
|
||||
atom.grammars.addProperties("a", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
|
||||
atom.grammars.addProperties("b", ".source .string.quoted.double", foo: bar: baz: 22)
|
||||
|
||||
atom.syntax.removeProperties("b")
|
||||
expect(atom.syntax.getProperty([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBeUndefined()
|
||||
expect(atom.syntax.getProperty([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42
|
||||
atom.grammars.removeProperties("b")
|
||||
expect(atom.grammars.getProperty([".source.js", ".string.quoted.double.js"], "foo.bar.baz")).toBeUndefined()
|
||||
expect(atom.grammars.getProperty([".source.coffee", ".string.quoted.double.coffee"], "foo.bar.baz")).toBe 42
|
||||
|
||||
@@ -2532,7 +2532,7 @@ describe "TextEditorComponent", ->
|
||||
describe "grammar data attributes", ->
|
||||
it "adds and updates the grammar data attribute based on the current grammar", ->
|
||||
expect(wrapperNode.dataset.grammar).toBe 'source js'
|
||||
editor.setGrammar(atom.syntax.nullGrammar)
|
||||
editor.setGrammar(atom.grammars.nullGrammar)
|
||||
expect(wrapperNode.dataset.grammar).toBe 'text plain null-grammar'
|
||||
|
||||
describe "encoding data attributes", ->
|
||||
@@ -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()
|
||||
|
||||
|
||||
+73
-108
@@ -2607,122 +2607,44 @@ describe "TextEditor", ->
|
||||
atom.clipboard.write(" z();")
|
||||
editor.setCursorBufferPosition([1, Infinity])
|
||||
editor.pasteText()
|
||||
|
||||
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", ->
|
||||
editor.setCursorBufferPosition([5, 2])
|
||||
editor.insertText("foo", indentBasis: 5)
|
||||
expect(editor.lineTextForBufferRow(5)).toBe " foo current = items.shift();"
|
||||
describe "when the cursor is indented further than the original copied text", ->
|
||||
it "increases the indentation of the copied lines to match", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 0]])
|
||||
editor.copySelectedText()
|
||||
|
||||
it "does not adjust the whitespace if there are preceding characters", ->
|
||||
copyText(" foo")
|
||||
editor.setCursorBufferPosition([5, 30])
|
||||
editor.setCursorBufferPosition([5, 6])
|
||||
editor.pasteText()
|
||||
|
||||
expect(editor.lineTextForBufferRow(5)).toBe " current = items.shift(); foo"
|
||||
expect(editor.lineTextForBufferRow(5)).toBe " var sort = function(items) {"
|
||||
expect(editor.lineTextForBufferRow(6)).toBe " if (items.length <= 1) return items;"
|
||||
|
||||
describe "when the inserted text contains newlines", ->
|
||||
describe "when the cursor is preceded only by whitespace characters", ->
|
||||
it "normalizes indented lines to each cursor's current indentation level", ->
|
||||
editor.setSelectedBufferRanges([
|
||||
[[1,2], [3,0]],
|
||||
[[4,4], [6,0]]
|
||||
])
|
||||
editor.copySelectedText()
|
||||
expect(atom.clipboard.read()).toEqual """
|
||||
var sort = function(items) {
|
||||
if (items.length <= 1) return items;
|
||||
describe "when the cursor is indented less far than the original copied text", ->
|
||||
it "decreases the indentation of the copied lines to match", ->
|
||||
editor.setSelectedBufferRange([[6, 6], [8, 0]])
|
||||
editor.copySelectedText()
|
||||
|
||||
while(items.length > 0) {
|
||||
current = items.shift();
|
||||
|
||||
"""
|
||||
|
||||
editor.setCursorBufferPosition([0,0])
|
||||
editor.insertNewlineAbove()
|
||||
editor.setSelectedBufferRanges([
|
||||
[[0,0], [0,0]],
|
||||
[[1,0], [1,0]]
|
||||
])
|
||||
editor.pasteText()
|
||||
|
||||
expect(editor.lineTextForBufferRow(0)).toBe "var sort = function(items) {"
|
||||
console.log JSON.stringify(editor.lineTextForBufferRow(1))
|
||||
expect(editor.lineTextForBufferRow(1)).toBe " if (items.length <= 1) return items;"
|
||||
expect(editor.lineTextForBufferRow(2)).toBe ""
|
||||
expect(editor.lineTextForBufferRow(3)).toBe "while(items.length > 0) {"
|
||||
expect(editor.lineTextForBufferRow(4)).toBe " current = items.shift();"
|
||||
|
||||
describe "when the cursor is preceded by non-whitespace characters", ->
|
||||
it "normalizes the indentation level of all lines based on the level of the existing first line", ->
|
||||
copyText(" while (true) {\n foo();\n }\n", {startColumn: 0})
|
||||
editor.setCursorBufferPosition([1, Infinity])
|
||||
editor.pasteText()
|
||||
|
||||
expect(editor.lineTextForBufferRow(1)).toBe " var sort = function(items) {while (true) {"
|
||||
expect(editor.lineTextForBufferRow(2)).toBe " foo();"
|
||||
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.setCursorBufferPosition([1, 2])
|
||||
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)
|
||||
expect(editor.lineTextForBufferRow(1)).toBe " current < pivot ? left.push(current) : right.push(current);"
|
||||
expect(editor.lineTextForBufferRow(2)).toBe "}"
|
||||
|
||||
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);")
|
||||
describe "when the first copied line has leading whitespace", ->
|
||||
it "preserves the line's leading whitespace", ->
|
||||
editor.setSelectedBufferRange([[4, 0], [6, 0]])
|
||||
editor.copySelectedText()
|
||||
|
||||
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 " }"
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.pasteText()
|
||||
|
||||
expect(editor.lineTextForBufferRow(0)).toBe " while(items.length > 0) {"
|
||||
expect(editor.lineTextForBufferRow(1)).toBe " current = items.shift();"
|
||||
|
||||
describe 'when the clipboard has many selections', ->
|
||||
beforeEach ->
|
||||
@@ -2747,6 +2669,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", ->
|
||||
@@ -3377,17 +3332,17 @@ describe "TextEditor", ->
|
||||
it "switches to the better-matched grammar and re-tokenizes the buffer", ->
|
||||
editor.destroy()
|
||||
|
||||
jsGrammar = atom.syntax.selectGrammar('a.js')
|
||||
atom.syntax.removeGrammar(jsGrammar)
|
||||
jsGrammar = atom.grammars.selectGrammar('a.js')
|
||||
atom.grammars.removeGrammar(jsGrammar)
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js', autoIndent: false).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.getGrammar()).toBe atom.syntax.nullGrammar
|
||||
expect(editor.getGrammar()).toBe atom.grammars.nullGrammar
|
||||
expect(editor.tokenizedLineForScreenRow(0).tokens.length).toBe 1
|
||||
|
||||
atom.syntax.addGrammar(jsGrammar)
|
||||
atom.grammars.addGrammar(jsGrammar)
|
||||
expect(editor.getGrammar()).toBe jsGrammar
|
||||
expect(editor.tokenizedLineForScreenRow(0).tokens.length).toBeGreaterThan 1
|
||||
|
||||
@@ -3438,6 +3393,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')
|
||||
@@ -3797,7 +3762,7 @@ describe "TextEditor", ->
|
||||
|
||||
it "updates the grammar based on grammar overrides", ->
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
atom.syntax.setGrammarOverrideForPath(editor.getPath(), 'source.coffee')
|
||||
atom.grammars.setGrammarOverrideForPath(editor.getPath(), 'source.coffee')
|
||||
editor.reloadGrammar()
|
||||
expect(editor.getGrammar().name).toBe 'CoffeeScript'
|
||||
|
||||
@@ -3815,7 +3780,7 @@ describe "TextEditor", ->
|
||||
atom.packages.activatePackage('language-hyperlink')
|
||||
|
||||
runs ->
|
||||
grammar = atom.syntax.selectGrammar("text.js")
|
||||
grammar = atom.grammars.selectGrammar("text.js")
|
||||
{tokens} = grammar.tokenizeLine("var i; // http://github.com")
|
||||
|
||||
expect(tokens[0].value).toBe "var"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -522,7 +522,7 @@ describe "TokenizedBuffer", ->
|
||||
buffer = atom.project.bufferForPathSync()
|
||||
buffer.setText "<div class='name'><%= User.find(2).full_name %></div>"
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
tokenizedBuffer.setGrammar(atom.syntax.selectGrammar('test.erb'))
|
||||
tokenizedBuffer.setGrammar(atom.grammars.selectGrammar('test.erb'))
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
{tokens} = tokenizedBuffer.tokenizedLineForRow(0)
|
||||
|
||||
@@ -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()
|
||||
@@ -95,13 +95,13 @@ describe "Window", ->
|
||||
describe ".unloadEditorWindow()", ->
|
||||
it "saves the serialized state of the window so it can be deserialized after reload", ->
|
||||
workspaceState = atom.workspace.serialize()
|
||||
syntaxState = atom.syntax.serialize()
|
||||
syntaxState = atom.grammars.serialize()
|
||||
projectState = atom.project.serialize()
|
||||
|
||||
atom.unloadEditorWindow()
|
||||
|
||||
expect(atom.state.workspace).toEqual workspaceState
|
||||
expect(atom.state.syntax).toEqual syntaxState
|
||||
expect(atom.state.grammars).toEqual syntaxState
|
||||
expect(atom.state.project).toEqual projectState
|
||||
expect(atom.saveSync).toHaveBeenCalled()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
+85
-20
@@ -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,11 +143,17 @@ class Atom extends Model
|
||||
# Public: A {KeymapManager} instance
|
||||
keymaps: null
|
||||
|
||||
# Public: A {TooltipManager} instance
|
||||
tooltips: null
|
||||
|
||||
# Experimental: A {NotificationManager} instance
|
||||
notifications: null
|
||||
|
||||
# Public: A {Project} instance
|
||||
project: null
|
||||
|
||||
# Public: A {Syntax} instance
|
||||
syntax: null
|
||||
# Public: A {GrammarRegistry} instance
|
||||
grammars: null
|
||||
|
||||
# Public: A {PackageManager} instance
|
||||
packages: null
|
||||
@@ -137,6 +161,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 +173,6 @@ class Atom extends Model
|
||||
# Public: A {Workspace} instance
|
||||
workspace: null
|
||||
|
||||
# Public: A {WorkspaceView} instance
|
||||
workspaceView: null
|
||||
|
||||
###
|
||||
Section: Construction and Destruction
|
||||
###
|
||||
@@ -173,11 +197,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,9 +222,11 @@ class Atom extends Model
|
||||
KeymapManager = require './keymap-extensions'
|
||||
ViewRegistry = require './view-registry'
|
||||
CommandRegistry = require './command-registry'
|
||||
TooltipManager = require './tooltip-manager'
|
||||
NotificationManager = require './notification-manager'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
Syntax = require './syntax'
|
||||
GrammarRegistry = require './grammar-registry'
|
||||
ThemeManager = require './theme-manager'
|
||||
StyleManager = require './style-manager'
|
||||
ContextMenuManager = require './context-menu-manager'
|
||||
@@ -213,6 +249,8 @@ class Atom extends Model
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@tooltips = new TooltipManager
|
||||
@notifications = new NotificationManager
|
||||
@commands = new CommandRegistry
|
||||
@views = new ViewRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@@ -223,7 +261,11 @@ class Atom extends Model
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@clipboard = new Clipboard()
|
||||
|
||||
@syntax = @deserializers.deserialize(@state.syntax) ? new Syntax()
|
||||
@grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry()
|
||||
|
||||
Object.defineProperty this, 'syntax', get: ->
|
||||
deprecate "The atom.syntax global is deprecated. Use atom.grammars instead."
|
||||
@grammars
|
||||
|
||||
@subscribe @packages.onDidActivateAll => @watchThemes()
|
||||
|
||||
@@ -248,10 +290,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,9 +576,9 @@ class Atom extends Model
|
||||
@displayWindow({maximize})
|
||||
|
||||
unloadEditorWindow: ->
|
||||
return if not @project and not @workspaceView
|
||||
return if not @project
|
||||
|
||||
@state.syntax = @syntax.serialize()
|
||||
@state.grammars = @grammars.serialize()
|
||||
@state.project = @project.serialize()
|
||||
@state.workspace = @workspace.serialize()
|
||||
@packages.deactivatePackages()
|
||||
@@ -524,10 +587,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 +603,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 +679,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()
|
||||
|
||||
@@ -119,9 +119,6 @@ module.exports =
|
||||
autoIndentOnPaste:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
normalizeIndentOnPaste:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
nonWordCharacters:
|
||||
type: 'string'
|
||||
default: "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
|
||||
|
||||
+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) ->
|
||||
|
||||
@@ -2,7 +2,8 @@ _ = require 'underscore-plus'
|
||||
{deprecate} = require 'grim'
|
||||
{specificity} = require 'clear-cut'
|
||||
{Subscriber} = require 'emissary'
|
||||
{GrammarRegistry, ScopeSelector} = require 'first-mate'
|
||||
FirstMate = require 'first-mate'
|
||||
{ScopeSelector} = FirstMate
|
||||
ScopedPropertyStore = require 'scoped-property-store'
|
||||
PropertyAccessors = require 'property-accessors'
|
||||
|
||||
@@ -11,20 +12,22 @@ Token = require './token'
|
||||
|
||||
# Extended: Syntax class holding the grammars used for tokenizing.
|
||||
#
|
||||
# An instance of this class is always available as the `atom.syntax` global.
|
||||
# An instance of this class is always available as the `atom.grammars` global.
|
||||
#
|
||||
# The Syntax class also contains properties for things such as the
|
||||
# language-specific comment regexes. See {::getProperty} for more details.
|
||||
module.exports =
|
||||
class Syntax extends GrammarRegistry
|
||||
class GrammarRegistry extends FirstMate.GrammarRegistry
|
||||
PropertyAccessors.includeInto(this)
|
||||
Subscriber.includeInto(this)
|
||||
atom.deserializers.add(this)
|
||||
|
||||
@deserialize: ({grammarOverridesByPath}) ->
|
||||
syntax = new Syntax()
|
||||
syntax.grammarOverridesByPath = grammarOverridesByPath
|
||||
syntax
|
||||
grammarRegistry = new GrammarRegistry()
|
||||
grammarRegistry.grammarOverridesByPath = grammarOverridesByPath
|
||||
grammarRegistry
|
||||
|
||||
atom.deserializers.add(this)
|
||||
atom.deserializers.add(name: 'Syntax', deserialize: @deserialize) # Support old serialization
|
||||
|
||||
constructor: ->
|
||||
super(maxTokensPerLine: 100)
|
||||
@@ -34,6 +37,17 @@ class Syntax extends GrammarRegistry
|
||||
|
||||
createToken: (value, scopes) -> new Token({value, scopes})
|
||||
|
||||
# Extended: Select a grammar for the given file path and file contents.
|
||||
#
|
||||
# This picks the best match by checking the file path and contents against
|
||||
# each grammar.
|
||||
#
|
||||
# * `filePath` A {String} file path.
|
||||
# * `fileContents` A {String} of text for the file path.
|
||||
#
|
||||
# Returns a {Grammar}, never null.
|
||||
selectGrammar: (filePath, fileContents) -> super
|
||||
|
||||
# Deprecated: Used by settings-view to display snippets for packages
|
||||
@::accessor 'propertyStore', ->
|
||||
deprecate("Do not use this. Use a public method on Config")
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
{Emitter, Disposable} = require 'event-kit'
|
||||
Notification = require '../src/notification'
|
||||
|
||||
# Experimental: Allows messaging the user. This will likely change, dont use
|
||||
# quite yet!
|
||||
module.exports =
|
||||
class NotificationManager
|
||||
constructor: ->
|
||||
@notifications = []
|
||||
@emitter = new Emitter
|
||||
|
||||
###
|
||||
Section: Events
|
||||
###
|
||||
|
||||
onDidAddNotification: (callback) ->
|
||||
@emitter.on 'did-add-notification', callback
|
||||
|
||||
###
|
||||
Section: Adding Notifications
|
||||
###
|
||||
|
||||
addSuccess: (message, options) ->
|
||||
@addNotification(new Notification('success', message, options))
|
||||
|
||||
addInfo: (message, options) ->
|
||||
@addNotification(new Notification('info', message, options))
|
||||
|
||||
addWarning: (message, options) ->
|
||||
@addNotification(new Notification('warning', message, options))
|
||||
|
||||
addError: (message, options) ->
|
||||
@addNotification(new Notification('error', message, options))
|
||||
|
||||
addFatalError: (message, options) ->
|
||||
@addNotification(new Notification('fatal', message, options))
|
||||
|
||||
add: (type, message, options) ->
|
||||
@addNotification(new Notification(type, message, options))
|
||||
|
||||
addNotification: (notification) ->
|
||||
@notifications.push(notification)
|
||||
@emitter.emit('did-add-notification', notification)
|
||||
notification
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
# Experimental: This will likely change, do not use.
|
||||
module.exports =
|
||||
class Notification
|
||||
constructor: (@type, @message, @options={}) ->
|
||||
@timestamp = new Date()
|
||||
|
||||
getOptions: -> @options
|
||||
|
||||
getType: -> @type
|
||||
|
||||
getMessage: -> @message
|
||||
|
||||
getTimestamp: -> @timestamp
|
||||
|
||||
getDetail: -> @optons.detail
|
||||
|
||||
isClosable: ->
|
||||
!!@options.closable
|
||||
|
||||
getIcon: ->
|
||||
return @options.icon if @options.icon?
|
||||
switch @type
|
||||
when 'fatal' then 'bug'
|
||||
when 'error' then 'flame'
|
||||
when 'warning' then 'alert'
|
||||
when 'info' then 'info'
|
||||
when 'success' then 'check'
|
||||
@@ -254,7 +254,7 @@ class Package
|
||||
grammarPaths = fs.listSync(grammarsDirPath, ['json', 'cson'])
|
||||
for grammarPath in grammarPaths
|
||||
try
|
||||
grammar = atom.syntax.readGrammarSync(grammarPath)
|
||||
grammar = atom.grammars.readGrammarSync(grammarPath)
|
||||
grammar.packageName = @name
|
||||
@grammars.push(grammar)
|
||||
grammar.activate()
|
||||
@@ -268,7 +268,7 @@ class Package
|
||||
return Q() if @grammarsLoaded
|
||||
|
||||
loadGrammar = (grammarPath, callback) =>
|
||||
atom.syntax.readGrammar grammarPath, (error, grammar) =>
|
||||
atom.grammars.readGrammar grammarPath, (error, grammar) =>
|
||||
if error?
|
||||
console.warn("Failed to load grammar: #{grammarPath}", error.stack ? error)
|
||||
else
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
+38
-38
@@ -359,8 +359,11 @@ class Selection extends Model
|
||||
@clear()
|
||||
@cursor.needsAutoscroll = @cursor.isLastCursor()
|
||||
|
||||
precedingText = @editor.getTextInRange([[oldBufferRange.start.row, 0], oldBufferRange.start])
|
||||
startLevel = @editor.indentLevelForLine(precedingText)
|
||||
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
text = @normalizeIndents(text, options.indentBasis)
|
||||
text = @adjustIndent(text, startLevel - options.indentBasis)
|
||||
|
||||
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo', 'normalizeLineEndings'))
|
||||
|
||||
@@ -376,7 +379,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 +549,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,10 +560,15 @@ 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)
|
||||
{start, end} = @getBufferRange()
|
||||
selectionText = @editor.getTextInRange([start, end])
|
||||
precedingText = @editor.getTextInRange([[start.row, 0], start])
|
||||
startLevel = @editor.indentLevelForLine(precedingText)
|
||||
|
||||
if maintainClipboard
|
||||
{text: clipboardText, metadata} = atom.clipboard.readWithMetadata()
|
||||
@@ -568,11 +577,19 @@ class Selection extends Model
|
||||
metadata.selections = [{
|
||||
text: clipboardText,
|
||||
indentBasis: metadata.indentBasis,
|
||||
fullLine: metadata.fullLine,
|
||||
}]
|
||||
metadata.selections.push(text: selectionText, indentBasis: selectionIndentation)
|
||||
metadata.selections.push({
|
||||
text: selectionText,
|
||||
indentBasis: startLevel,
|
||||
fullLine: fullLine
|
||||
})
|
||||
atom.clipboard.write([clipboardText, selectionText].join("\n"), metadata)
|
||||
else
|
||||
atom.clipboard.write(selectionText, {indentBasis: selectionIndentation})
|
||||
atom.clipboard.write(selectionText, {
|
||||
indentBasis: startLevel,
|
||||
fullLine: fullLine
|
||||
})
|
||||
|
||||
# Public: Creates a fold containing the current selection.
|
||||
fold: ->
|
||||
@@ -580,34 +597,22 @@ class Selection extends Model
|
||||
@editor.createFold(range.start.row, range.end.row)
|
||||
@cursor.setBufferPosition([range.end.row + 1, 0])
|
||||
|
||||
# Public: Indents the given text to the suggested level based on the grammar.
|
||||
# Public: Increases the indentation level of
|
||||
#
|
||||
# * `text` The {String} to indent within the selection.
|
||||
# * `indentBasis` The beginning indent level.
|
||||
normalizeIndents: (text, indentBasis) ->
|
||||
textPrecedingCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferColumn()]
|
||||
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
|
||||
|
||||
# * `indentIncrease` The beginning indent level.
|
||||
adjustIndent: (text, indentIncrease) ->
|
||||
lines = text.split('\n')
|
||||
firstLineIndentLevel = @editor.indentLevelForLine(lines[0])
|
||||
if isCursorInsideExistingLine
|
||||
minimumIndentLevel = @editor.indentationForBufferRow(@cursor.getBufferRow())
|
||||
else
|
||||
minimumIndentLevel = @cursor.getIndentLevel()
|
||||
|
||||
normalizedLines = []
|
||||
for line, i in lines
|
||||
if i == 0
|
||||
indentLevel = 0
|
||||
else if line == '' # remove all indentation from empty lines
|
||||
indentLevel = 0
|
||||
for line, i in lines when i > 0
|
||||
if indentIncrease == 0
|
||||
continue
|
||||
else if indentIncrease > 0
|
||||
lines[i] = @editor.buildIndentString(indentIncrease) + line
|
||||
else
|
||||
lineIndentLevel = @editor.indentLevelForLine(lines[i])
|
||||
indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis)
|
||||
|
||||
normalizedLines.push(@setIndentationForLine(line, indentLevel))
|
||||
|
||||
normalizedLines.join('\n')
|
||||
currentIndentLevel = @editor.indentLevelForLine(lines[i])
|
||||
indentLevel = Math.max(0, currentIndentLevel + indentIncrease)
|
||||
lines[i] = line.replace(/^[\t ]+/, @editor.buildIndentString(indentLevel))
|
||||
lines.join('\n')
|
||||
|
||||
# Indent the current line(s).
|
||||
#
|
||||
@@ -640,11 +645,6 @@ class Selection extends Model
|
||||
for row in [start..end]
|
||||
@editor.buffer.insert([row, 0], @editor.getTabText()) unless @editor.buffer.lineLengthForRow(row) == 0
|
||||
|
||||
setIndentationForLine: (line, indentLevel) ->
|
||||
desiredIndentLevel = Math.max(0, indentLevel)
|
||||
desiredIndentString = @editor.buildIndentString(desiredIndentLevel)
|
||||
line.replace(/^[\t ]*/, desiredIndentString)
|
||||
|
||||
###
|
||||
Section: Managing multiple selections
|
||||
###
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -103,7 +103,9 @@ class TextEditorElement extends HTMLElement
|
||||
)
|
||||
@component = React.renderComponent(@componentDescriptor, @rootElement)
|
||||
|
||||
unless @useShadowDOM
|
||||
if @useShadowDOM
|
||||
@shadowRoot.addEventListener('blur', @shadowRootBlurred.bind(this), true)
|
||||
else
|
||||
inputNode = @component.refs.input.getDOMNode()
|
||||
inputNode.addEventListener 'focus', @focused.bind(this)
|
||||
inputNode.addEventListener 'blur', => @dispatchEvent(new FocusEvent('blur', bubbles: false))
|
||||
@@ -128,6 +130,16 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
@component?.blurred()
|
||||
|
||||
# Work around what seems to be a bug in Chromium. Focus can be stolen from the
|
||||
# hidden input when clicking on the gutter and transferred to the
|
||||
# already-focused host element. The host element never gets a 'focus' event
|
||||
# however, which leaves us in a limbo state where the text editor element is
|
||||
# focused but the hidden input isn't focused. This always refocuses the hidden
|
||||
# input if a blur event occurs in the shadow DOM that is transferring focus
|
||||
# back to the host element.
|
||||
shadowRootBlurred: (event) ->
|
||||
@component.focused() if event.relatedTarget is this
|
||||
|
||||
addGrammarScopeAttribute: ->
|
||||
grammarScope = @model.getGrammar()?.scopeName?.replace(/\./g, ' ')
|
||||
@dataset.grammar = grammarScope
|
||||
|
||||
@@ -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) ->
|
||||
|
||||
+52
-25
@@ -1098,34 +1098,49 @@ class TextEditor extends Model
|
||||
# abort the transaction, call {::abortTransaction} to terminate the function's
|
||||
# execution and revert any changes performed up to the abortion.
|
||||
#
|
||||
# * `groupingInterval` (optional) This is the sames as the `groupingInterval`
|
||||
# parameter in {::beginTransaction}
|
||||
# * `fn` A {Function} to call inside the transaction.
|
||||
transact: (groupingInterval, fn) -> @buffer.transact(groupingInterval, fn)
|
||||
|
||||
# Extended: Start an open-ended transaction.
|
||||
#
|
||||
# Call {::commitTransaction} or {::abortTransaction} to terminate the
|
||||
# transaction. If you nest calls to transactions, only the outermost
|
||||
# transaction is considered. You must match every begin with a matching
|
||||
# commit, but a single call to abort will cancel all nested transactions.
|
||||
#
|
||||
# * `groupingInterval` (optional) The {Number} of milliseconds for which this
|
||||
# transaction should be considered 'groupable' after it begins. If a transaction
|
||||
# with a positive `groupingInterval` is committed while the previous transaction is
|
||||
# still 'groupable', the two transactions are merged with respect to undo and redo.
|
||||
# * `fn` A {Function} to call inside the transaction.
|
||||
transact: (groupingInterval, fn) -> @buffer.transact(groupingInterval, fn)
|
||||
|
||||
# Deprecated: Start an open-ended transaction.
|
||||
beginTransaction: (groupingInterval) -> @buffer.beginTransaction(groupingInterval)
|
||||
|
||||
# Extended: Commit an open-ended transaction started with {::beginTransaction}
|
||||
# and push it to the undo stack.
|
||||
#
|
||||
# If transactions are nested, only the outermost commit takes effect.
|
||||
# Deprecated: Commit an open-ended transaction started with {::beginTransaction}.
|
||||
commitTransaction: -> @buffer.commitTransaction()
|
||||
|
||||
# Extended: Abort an open transaction, undoing any operations performed so far
|
||||
# within the transaction.
|
||||
abortTransaction: -> @buffer.abortTransaction()
|
||||
|
||||
# Extended: Create a pointer to the current state of the buffer for use
|
||||
# with {::revertToCheckpoint} and {::groupChangesSinceCheckpoint}.
|
||||
#
|
||||
# Returns a checkpoint value.
|
||||
createCheckpoint: -> @buffer.createCheckpoint()
|
||||
|
||||
# Extended: Revert the buffer to the state it was in when the given
|
||||
# checkpoint was created.
|
||||
#
|
||||
# The redo stack will be empty following this operation, so changes since the
|
||||
# checkpoint will be lost. If the given checkpoint is no longer present in the
|
||||
# undo history, no changes will be made to the buffer and this method will
|
||||
# return `false`.
|
||||
#
|
||||
# Returns a {Boolean} indicating whether the operation succeeded.
|
||||
revertToCheckpoint: (checkpoint) -> @buffer.revertToCheckpoint(checkpoint)
|
||||
|
||||
# Extended: Group all changes since the given checkpoint into a single
|
||||
# transaction for purposes of undo/redo.
|
||||
#
|
||||
# If the given checkpoint is no longer present in the undo history, no
|
||||
# grouping will be performed and this method will return `false`.
|
||||
#
|
||||
# Returns a {Boolean} indicating whether the operation succeeded.
|
||||
groupChangesSinceCheckpoint: (checkpoint) -> @buffer.groupChangesSinceCheckpoint(checkpoint)
|
||||
|
||||
###
|
||||
Section: TextEditor Coordinates
|
||||
###
|
||||
@@ -2448,7 +2463,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 +2487,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 +2519,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: ->
|
||||
|
||||
@@ -26,8 +26,8 @@ class TokenizedBuffer extends Model
|
||||
constructor: ({@buffer, @tabLength, @invisibles}) ->
|
||||
@emitter = new Emitter
|
||||
|
||||
@subscribe atom.syntax.onDidAddGrammar(@grammarAddedOrUpdated)
|
||||
@subscribe atom.syntax.onDidUpdateGrammar(@grammarAddedOrUpdated)
|
||||
@subscribe atom.grammars.onDidAddGrammar(@grammarAddedOrUpdated)
|
||||
@subscribe atom.grammars.onDidUpdateGrammar(@grammarAddedOrUpdated)
|
||||
|
||||
@subscribe @buffer.preemptDidChange (e) => @handleBufferChange(e)
|
||||
@subscribe @buffer.onDidChangePath (@bufferPath) => @reloadGrammar()
|
||||
@@ -98,7 +98,7 @@ class TokenizedBuffer extends Model
|
||||
@emitter.emit 'did-change-grammar', grammar
|
||||
|
||||
reloadGrammar: ->
|
||||
if grammar = atom.syntax.selectGrammar(@buffer.getPath(), @buffer.getText())
|
||||
if grammar = atom.grammars.selectGrammar(@buffer.getPath(), @buffer.getText())
|
||||
@setGrammar(grammar)
|
||||
else
|
||||
throw new Error("No grammar found for path: #{path}")
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
_ = 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:
|
||||
# * `title` {String} Text in the tip.
|
||||
# * `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'
|
||||
@@ -105,13 +105,13 @@ class Workspace extends Model
|
||||
|
||||
packageNames.push(packageName)
|
||||
for scopeName in includedGrammarScopes ? []
|
||||
addGrammar(atom.syntax.grammarForScopeName(scopeName))
|
||||
addGrammar(atom.grammars.grammarForScopeName(scopeName))
|
||||
|
||||
editors = @getTextEditors()
|
||||
addGrammar(editor.getGrammar()) for editor in editors
|
||||
|
||||
if editors.length > 0
|
||||
for grammar in atom.syntax.getGrammars() when grammar.injectionSelector
|
||||
for grammar in atom.grammars.getGrammars() when grammar.injectionSelector
|
||||
addGrammar(grammar)
|
||||
|
||||
_.uniq(packageNames)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -64,13 +64,3 @@ div > .inline-block-tight:last-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
-webkit-animation: flash-error 0.3s ease-in;
|
||||
}
|
||||
|
||||
@-webkit-keyframes flash-error {
|
||||
0% { background: @background-color-error; }
|
||||
|
||||
100% { background: auto; }
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário