Comparar commits
185 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| a6e59bbbe0 | |||
| d61c015de7 | |||
| 78b4efe1dd | |||
| df79038bcc | |||
| 5a1c6bdf4a | |||
| ba6abea216 | |||
| 1e740d95ab | |||
| 6f5b296471 | |||
| 9a5be7e70c | |||
| 4edb856848 | |||
| 74358f3e79 | |||
| 0ecb46504c | |||
| 474be40154 | |||
| 06f496cd13 | |||
| 27835013fe | |||
| fd593e94be | |||
| 6df60cb29e | |||
| 920ffd91a5 | |||
| 7e194541a0 | |||
| ccf0e6168a | |||
| 8258ec6d45 | |||
| db2e6dd97c | |||
| ce29060d2d | |||
| 7d1c23b561 | |||
| 9e2799db27 | |||
| 040f6deb1e | |||
| 33d2debf5f | |||
| 6de40e21c7 | |||
| 6169caa1fb | |||
| b4e25137a2 | |||
| 05aaace387 | |||
| a32daecf5f | |||
| 6db43d85c4 | |||
| 53e06b8680 | |||
| 9ab2500970 | |||
| 697e70d47c | |||
| ffd1f8520c | |||
| 9132859757 | |||
| 6af2e1649c | |||
| 0962918a82 | |||
| 6b963a562f | |||
| db41b022c2 | |||
| d4084b305b | |||
| b81c1f408f | |||
| 97bdb84122 | |||
| 87e8720269 | |||
| 160c32384c | |||
| 33299ec774 | |||
| d4cc549a01 | |||
| 76a5da8be8 | |||
| 0b0cbe11dc | |||
| 86d730a3a9 | |||
| 99ff482afe | |||
| 84be87324e | |||
| d1ecafc69f | |||
| 235f602002 | |||
| 1ee4240b7e | |||
| a46c4ed30e | |||
| 023b9d18e1 | |||
| 5b992d1397 | |||
| 1ad25f4a56 | |||
| 4baea35c23 | |||
| 63335f6b60 | |||
| f691c20d68 | |||
| 45ca1c6762 | |||
| 528267b7d7 | |||
| 5cdeb7bc18 | |||
| 36d28235fa | |||
| f7ecc3e2a3 | |||
| 89a5469151 | |||
| 77e8f5c9ac | |||
| 1fc597ca22 | |||
| 5c62eb0253 | |||
| c378ef0649 | |||
| 12982027f2 | |||
| 36a9e3f76e | |||
| a9d215970f | |||
| 0daee2c2c2 | |||
| f9fe317298 | |||
| ce46991600 | |||
| e1d9838a28 | |||
| 0c057dbbd5 | |||
| aad393618e | |||
| ccaffb1c28 | |||
| 47b1d3e90f | |||
| 9df7ea91db | |||
| 5bf0e53c01 | |||
| c052b03793 | |||
| 22cf142473 | |||
| 1d6db875ff | |||
| b2a71ecd36 | |||
| 432b531c07 | |||
| 3190f7578f | |||
| db49d4da31 | |||
| 9fb1edbc54 | |||
| 5a2365cead | |||
| 3619e6acaf | |||
| 936ab1c898 | |||
| b961ed416e | |||
| 867f920329 | |||
| 6f4107fe5d | |||
| 323ce940f9 | |||
| 1fe452776d | |||
| d263205a9a | |||
| 60970d6cec | |||
| 32f6ab717e | |||
| 4f871f1331 | |||
| c2107fa9b3 | |||
| 96d4c1c41b | |||
| bac10d60c4 | |||
| 828b841f17 | |||
| 11bda1b47a | |||
| 2577843e51 | |||
| e0e821e7a4 | |||
| 93f109fbba | |||
| 97a55ba8c0 | |||
| 0a59d13d56 | |||
| 20dbc4cfd3 | |||
| 6efaf91ff9 | |||
| b6b90c0270 | |||
| d736ebff38 | |||
| 0cf180804c | |||
| c0c5f46097 | |||
| 16cc9f76c4 | |||
| 6ad8aa7e5c | |||
| 67fc2b9af5 | |||
| b8b58b25da | |||
| 696c795b50 | |||
| 97d697f195 | |||
| 57d020ff65 | |||
| 3e56822968 | |||
| d46d797f87 | |||
| fa6a826a37 | |||
| e598856db5 | |||
| 380fee33ef | |||
| d524d25a43 | |||
| 2f765974f8 | |||
| 28868fdb8c | |||
| 4ce785d12c | |||
| 7f8f5203bc | |||
| 77fb8ba15b | |||
| c538857cfa | |||
| 6716e544f0 | |||
| 2f3a9c9e35 | |||
| 3d1baaf3f3 | |||
| b819f681aa | |||
| e30b2f1c73 | |||
| ab9cc75f8b | |||
| 9fcac1ab1c | |||
| c172882c15 | |||
| bb6446f7d0 | |||
| e2609ddd06 | |||
| 7f3e0287eb | |||
| 1bba80c2b2 | |||
| 0845610595 | |||
| 2c09321315 | |||
| f2d495eab2 | |||
| 67c193c5ce | |||
| e62485195a | |||
| 1eba8cff39 | |||
| 40b465b0b6 | |||
| 909ec375b1 | |||
| a17b504bdb | |||
| 75857bec01 | |||
| b8fa3a2127 | |||
| 979fad966d | |||
| d523f9e1ec | |||
| f10453ed04 | |||
| 2743c0ab6f | |||
| 2cf5df858f | |||
| dfbb50385d | |||
| e0f6642a9b | |||
| 87c217c3f6 | |||
| 77aa539e70 | |||
| 13fa424ed5 | |||
| 0ea2a9dc9c | |||
| e3eadc310d | |||
| 6520587ba8 | |||
| 3bb62b6651 | |||
| e8ab37c207 | |||
| 612e972ac6 | |||
| 14a20147c6 | |||
| ed9c62f883 | |||
| 0239c7d386 | |||
| 7a0b8c31d4 |
+1
-1
@@ -74,7 +74,7 @@ For more information on how to work with Atom's official packages, see
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :lipstick: `:lipstick:` when improving the format/structure of the code
|
||||
* :art: `:art:` when improving the format/structure of the code
|
||||
* :racehorse: `:racehorse:` when improving performance
|
||||
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
|
||||
* :memo: `:memo:` when writing docs
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.120.0"
|
||||
"atom-package-manager": "0.128"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"fs-plus": "2.x",
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-atom-shell-installer": "^0.19.0",
|
||||
"grunt-atom-shell-installer": "^0.20.0",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git#cfb99aa99811d52687969532bd5a98011ed95bfe",
|
||||
"grunt-contrib-coffee": "~0.12.0",
|
||||
@@ -24,7 +24,7 @@
|
||||
"grunt-peg": "~1.1.0",
|
||||
"grunt-shell": "~0.3.1",
|
||||
"harmony-collections": "~0.3.8",
|
||||
"legal-eagle": "~0.8.0",
|
||||
"legal-eagle": "~0.9.0",
|
||||
"minidump": "~0.8",
|
||||
"npm": "~1.4.5",
|
||||
"rcedit": "~0.3.0",
|
||||
|
||||
@@ -144,7 +144,10 @@ module.exports = (grunt) ->
|
||||
cp 'spec', path.join(appDir, 'spec')
|
||||
cp 'src', path.join(appDir, 'src'), filter: /.+\.(cson|coffee)$/
|
||||
cp 'static', path.join(appDir, 'static')
|
||||
cp 'apm', path.join(appDir, 'apm'), filter: filterNodeModule
|
||||
|
||||
cp path.join('apm', 'node_modules', 'atom-package-manager'), path.join(appDir, 'apm'), filter: filterNodeModule
|
||||
if process.platform isnt 'win32'
|
||||
fs.symlinkSync(path.join('..', '..', 'bin', 'apm'), path.join(appDir, 'apm', 'node_modules', '.bin', 'apm'))
|
||||
|
||||
if process.platform is 'darwin'
|
||||
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
|
||||
|
||||
@@ -35,6 +35,10 @@ module.exports =
|
||||
|
||||
MIT/X11
|
||||
"""
|
||||
'cheerio@0.15.0':
|
||||
repository: "https://github.com/cheeriojs/cheerio"
|
||||
license: 'MIT'
|
||||
source: 'https://github.com/cheeriojs/cheerio/blob/master/package.json'
|
||||
'specificity@0.1.3':
|
||||
repository: 'https://github.com/keeganstreet/specificity'
|
||||
license: 'MIT'
|
||||
|
||||
@@ -8,14 +8,35 @@ module.exports = (grunt) ->
|
||||
prebuiltConfigurations = [
|
||||
['atom-dark-ui', 'atom-dark-syntax']
|
||||
['atom-dark-ui', 'atom-light-syntax']
|
||||
['atom-dark-ui', 'one-dark-syntax']
|
||||
['atom-dark-ui', 'one-light-syntax']
|
||||
['atom-dark-ui', 'solarized-dark-syntax']
|
||||
['atom-dark-ui', 'base16-tomorrow-dark-theme']
|
||||
['atom-dark-ui', 'base16-tomorrow-light-theme']
|
||||
|
||||
['atom-light-ui', 'atom-light-syntax']
|
||||
['atom-light-ui', 'atom-dark-syntax']
|
||||
['atom-light-ui', 'one-dark-syntax']
|
||||
['atom-light-ui', 'one-light-syntax']
|
||||
['atom-light-ui', 'solarized-dark-syntax']
|
||||
['atom-light-ui', 'base16-tomorrow-dark-theme']
|
||||
['atom-light-ui', 'base16-tomorrow-light-theme']
|
||||
|
||||
['one-dark-ui', 'one-dark-syntax']
|
||||
['one-dark-ui', 'one-light-syntax']
|
||||
['one-dark-ui', 'atom-dark-syntax']
|
||||
['one-dark-ui', 'atom-light-syntax']
|
||||
['one-dark-ui', 'solarized-dark-syntax']
|
||||
['one-dark-ui', 'base16-tomorrow-dark-theme']
|
||||
['one-dark-ui', 'base16-tomorrow-light-theme']
|
||||
|
||||
['one-light-ui', 'one-light-syntax']
|
||||
['one-light-ui', 'one-dark-syntax']
|
||||
['one-light-ui', 'atom-light-syntax']
|
||||
['one-light-ui', 'atom-dark-syntax']
|
||||
['one-light-ui', 'solarized-dark-syntax']
|
||||
['one-light-ui', 'base16-tomorrow-dark-theme']
|
||||
['one-light-ui', 'base16-tomorrow-light-theme']
|
||||
]
|
||||
|
||||
directory = path.join(grunt.config.get('atom.appDir'), 'less-compile-cache')
|
||||
@@ -42,10 +63,18 @@ module.exports = (grunt) ->
|
||||
resourcePath: path.resolve('.')
|
||||
importPaths: importPaths
|
||||
|
||||
cssForFile = (file) ->
|
||||
baseVarImports = """
|
||||
@import "variables/ui-variables";
|
||||
@import "variables/syntax-variables";
|
||||
"""
|
||||
less = fs.readFileSync(file, 'utf8')
|
||||
lessCache.cssForFile(file, [baseVarImports, less].join('\n'))
|
||||
|
||||
for file in @filesSrc
|
||||
grunt.verbose.writeln("File #{file.cyan} created in cache.")
|
||||
lessCache.readFileSync(file)
|
||||
cssForFile(file)
|
||||
|
||||
for file in themeMains
|
||||
grunt.verbose.writeln("File #{file.cyan} created in cache.")
|
||||
lessCache.readFileSync(file)
|
||||
cssForFile(file)
|
||||
|
||||
@@ -45,7 +45,7 @@ the editor to see it in action!
|
||||
|
||||
[atomio]: https://atom.io
|
||||
[CSS]: http://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[LESS]: http://lesscss.org
|
||||
[Less]: http://lesscss.org
|
||||
[plist]: http://en.wikipedia.org/wiki/Property_list
|
||||
[R]: http://en.wikipedia.org/wiki/R_(programming_language)
|
||||
[TextMate]: http://macromates.com
|
||||
|
||||
@@ -6,7 +6,7 @@ theme.
|
||||
### Differences
|
||||
|
||||
TextMate themes use [plist][plist] files while Atom themes use [CSS][CSS] or
|
||||
[LESS][LESS] to style the UI and syntax in the editor.
|
||||
[Less][Less] to style the UI and syntax in the editor.
|
||||
|
||||
The utility that converts the theme first parses the theme's plist file and
|
||||
then creates comparable CSS rules and properties that will style Atom similarly.
|
||||
@@ -62,7 +62,7 @@ __Syntax Theme__ dropdown menu to enable your new theme.
|
||||
|
||||
[atomio]: https://atom.io
|
||||
[CSS]: http://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[LESS]: http://lesscss.org
|
||||
[Less]: http://lesscss.org
|
||||
[plist]: http://en.wikipedia.org/wiki/Property_list
|
||||
[TextMate]: http://macromates.com
|
||||
[TextMateThemes]: http://wiki.macromates.com/Themes/UserSubmittedThemes
|
||||
|
||||
@@ -123,8 +123,8 @@ like you.
|
||||
|
||||
Style sheets for your package should be placed in the _styles_ 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.
|
||||
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
|
||||
@@ -418,7 +418,7 @@ all the other available commands.
|
||||
[underscore]: http://underscorejs.org/
|
||||
[jasmine]: http://jasmine.github.io
|
||||
[cson]: https://github.com/atom/season
|
||||
[LESS]: http://lesscss.org
|
||||
[Less]: http://lesscss.org
|
||||
[ui-variables]: https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less
|
||||
[first-package]: your-first-package.html
|
||||
[convert-bundle]: converting-a-text-mate-bundle.html
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Creating a Theme
|
||||
|
||||
Atom's interface is rendered using HTML, and it's styled via [LESS] which is a
|
||||
superset of CSS. Don't worry if you haven't heard of LESS before; it's just like
|
||||
Atom's interface is rendered using HTML, and it's styled via [Less] which is a
|
||||
superset of CSS. Don't worry if you haven't heard of Less before; it's just like
|
||||
CSS, but with a few handy extensions.
|
||||
|
||||
Atom supports two types of themes: _UI_ and _syntax_. UI themes style
|
||||
@@ -17,7 +17,7 @@ section on the left hand side.
|
||||
Themes are pretty straightforward but it's still helpful to be familiar with
|
||||
a few things before starting:
|
||||
|
||||
* LESS is a superset of CSS, but it has some really handy features like
|
||||
* Less is a superset of CSS, but it has some really handy features like
|
||||
variables. If you aren't familiar with its syntax, take a few minutes
|
||||
to [familiarize yourself][less-tutorial].
|
||||
* You may also want to review the concept of a _[package.json]_, too. This file
|
||||
@@ -131,7 +131,7 @@ _styleguide_, or use the shortcut `cmd-ctrl-shift-g`.
|
||||
![styleguide-img]
|
||||
|
||||
[atomio]: http://atom.io/packages
|
||||
[LESS]: http://lesscss.org/
|
||||
[Less]: http://lesscss.org/
|
||||
[git]: http://git-scm.com/
|
||||
[atom]: https://atom.io/
|
||||
[package.json]: ./creating-a-package.html#package-json
|
||||
|
||||
@@ -174,12 +174,12 @@ atom-text-editor.is-focused .cursor {
|
||||
}
|
||||
```
|
||||
|
||||
Unfamiliar with LESS? Read more about it [here][LESS].
|
||||
Unfamiliar with Less? Read more about it [here][Less].
|
||||
|
||||
This file can also be named _styles.css_ and contain CSS.
|
||||
|
||||
[creating-a-package]: creating-a-package.md
|
||||
[create-theme]: creating-a-theme.md
|
||||
[LESS]: http://www.lesscss.org
|
||||
[Less]: http://www.lesscss.org
|
||||
[CSON]: https://github.com/atom/season
|
||||
[CoffeeScript]: http://coffeescript.org/
|
||||
|
||||
@@ -100,6 +100,21 @@ When an error is thrown in Atom, the developer tools are automatically shown wit
|
||||
|
||||
If you can reproduce the error, use this approach to get the full stack trace. The stack trace might point to a problem in your [Init script][init script or stylesheet] or a specific package you installed, which you can then disable and report an issue on its GitHub repository.
|
||||
|
||||
## Check that you have a build toolchain installed
|
||||
|
||||
If you are having issues installing a package using `apm install`, this could be
|
||||
because the package has dependencies on libraries that contain native code
|
||||
and so you will need to have a C++ compiler and Python installed to be able to
|
||||
install it.
|
||||
|
||||
You can run `apm install --check` to see if [apm][apm] can build native code on
|
||||
your machine.
|
||||
|
||||
Check out the pre-requisites in the [build instructions][build-instructions] for
|
||||
your platform for more details.
|
||||
|
||||
[apm]: https://github.com/atom/apm
|
||||
[build-instructions]: https://github.com/atom/atom/tree/master/docs/build-instructions
|
||||
[submitting issues]: https://github.com/atom/atom/blob/master/CONTRIBUTING.md#submitting-issues
|
||||
[building atom]: https://github.com/atom/atom#building
|
||||
[atom releases]: https://github.com/atom/atom/releases
|
||||
|
||||
@@ -34,7 +34,7 @@ files. If you are using Git you can use `cmd-shift-b` to search the list of
|
||||
files modified and untracked in your project's repository.
|
||||
|
||||
You can also use the tree view to navigate to a file. To open and focus the
|
||||
the tree view, press `ctrl-0`. The tree view can be toggled open and closed with
|
||||
tree view, press `ctrl-0`. The tree view can be toggled open and closed with
|
||||
`cmd-\`.
|
||||
|
||||
#### Adding, Moving, Deleting Files
|
||||
|
||||
@@ -0,0 +1,625 @@
|
||||
# Upgrading your package to 1.0 APIs
|
||||
|
||||
Atom is rapidly approaching 1.0. Much of the effort leading up to the 1.0 has been cleaning up APIs in an attempt to future proof, and make a more pleasant experience developing packages.
|
||||
|
||||
This document will guide you through the large bits of upgrading your package to work with 1.0 APIs.
|
||||
|
||||
## TL;DR
|
||||
|
||||
We've set deprecation messages and errors in strategic places to help make sure you don't miss anything. You should be able to get 95% of the way to an updated package just by fixing errors and deprecations. There are a couple of things you can do to get the full effect of all the errors and deprecations.
|
||||
|
||||
### Use atom-space-pen-views
|
||||
|
||||
If you use any class from `require 'atom'` with a `$` or `View` in the name, add the `atom-space-pen-views` module to your package's `package.json` file's dependencies:
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"atom-space-pen-views": "^2.0.3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then run `apm install` in your package directory.
|
||||
|
||||
### Require views from atom-space-pen-views
|
||||
|
||||
Anywhere you are requiring one of the following from `atom` you need to require them from `atom-space-pen-views` instead.
|
||||
|
||||
```coffee
|
||||
# require these from 'atom-space-pen-views' rather than 'atom'
|
||||
$
|
||||
$$
|
||||
$$$
|
||||
View
|
||||
TextEditorView
|
||||
ScrollView
|
||||
SelectListView
|
||||
```
|
||||
|
||||
So this:
|
||||
|
||||
```coffee
|
||||
# Old way
|
||||
{$, TextEditorView, View, GitRepository} = require 'atom'
|
||||
```
|
||||
|
||||
Would be replaced by this:
|
||||
|
||||
```coffee
|
||||
# New way
|
||||
{GitRepository} = require 'atom'
|
||||
{$, TextEditorView, View} = require 'atom-space-pen-views'
|
||||
```
|
||||
|
||||
### Run specs and test your package
|
||||
|
||||
You wrote specs, right!? Here's where they shine. Run them with `cmd-shift-P`, and search for `run package specs`. It will show all the deprecation messages and errors.
|
||||
|
||||
### Update the engines field in package.json
|
||||
|
||||
When you are deprecation free and all done converting, upgrade the `engines` field in your package.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"engines": {
|
||||
"atom": ">=0.174.0, <2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
We have upgraded all the core packages. Please see [this issue](https://github.com/atom/atom/issues/4011) for a link to all the upgrade PRs.
|
||||
|
||||
## Deprecations
|
||||
|
||||
All of the methods in Atom core that have changes will emit deprecation messages when called. These messages are shown in two places: your **package specs**, and in **Deprecation Cop**.
|
||||
|
||||
### Specs
|
||||
|
||||
Just run your specs, and all the deprecations will be displayed in yellow.
|
||||
|
||||

|
||||
|
||||
### Deprecation Cop
|
||||
|
||||
Run an atom window in dev mode (`atom -d`) with your package loaded, and open Deprecation Cop (search for `deprecation` in the command palette). Deprecated methods will be appear in Deprecation Cop only after they have been called.
|
||||
|
||||

|
||||
|
||||
When deprecation cop is open, and deprecated methods are called, a `Refresh` button will appear in the top right of the Deprecation Cop interface. So exercise your package, then come back to Deprecation Cop and click the `Refresh` button.
|
||||
|
||||
## Upgrading your Views
|
||||
|
||||
Previous to 1.0, views were baked into Atom core. These views were based on jQuery and `space-pen`. They looked something like this:
|
||||
|
||||
```coffee
|
||||
# The old way: getting views from atom
|
||||
{$, TextEditorView, View} = require 'atom'
|
||||
|
||||
module.exports =
|
||||
class SomeView extends View
|
||||
@content: ->
|
||||
@div class: 'find-and-replace', =>
|
||||
@div class: 'block', =>
|
||||
@subview 'myEditor', new TextEditorView(mini: true)
|
||||
#...
|
||||
```
|
||||
|
||||
### The New
|
||||
|
||||
`require 'atom'` no longer provides view helpers or jQuery. Atom core is now 'view agnostic'. The preexisting view system is available from a new npm package: `atom-space-pen-views`.
|
||||
|
||||
`atom-space-pen-views` now provides jQuery, `space-pen` views, and Atom specific views:
|
||||
|
||||
|
||||
```coffee
|
||||
# These are now provided by atom-space-pen-views
|
||||
$
|
||||
$$
|
||||
$$$
|
||||
View
|
||||
TextEditorView
|
||||
ScrollView
|
||||
SelectListView
|
||||
```
|
||||
|
||||
### Adding the module dependencies
|
||||
|
||||
To use the new views, you need to specify the `atom-space-pen-views` module in your package's `package.json` file's dependencies:
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"atom-space-pen-views": "^2.0.3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`space-pen` bundles jQuery. If you do not need `space-pen` or any of the views, you can require jQuery directly.
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"jquery": "^2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Converting your views
|
||||
|
||||
Sometimes it is as simple as converting the requires at the top of each view page. I assume you read the 'TL;DR' section and have updated all of your requires.
|
||||
|
||||
### Upgrading classes extending any space-pen View
|
||||
|
||||
#### `afterAttach` and `beforeRemove` updated
|
||||
|
||||
The `afterAttach` and `beforeRemove` hooks have been replaced with
|
||||
`attached` and `detached` and the semantics have changed.
|
||||
|
||||
`afterAttach` was called whenever the node was attached to another DOM node, even if that parent node wasn't present in the DOM. `afterAttach` also was called with a boolean indicating whether or not the element and its parents were on the DOM. Now the `attached` hook is _only_ called when the node and all of its parents are actually on the DOM, and is not called with a boolean.
|
||||
|
||||
`beforeRemove` was only called when `$.fn.remove` was called, which was typically used when the node was completely removed from the DOM. The new `detached` hook is called whenever the DOM node is _detached_, which could happen if the node is being detached for reattachment later. In short, if `beforeRemove` is called the node is never coming back. With `detached` it might be attached again later.
|
||||
|
||||
```coffee
|
||||
# Old way
|
||||
{View} = require 'atom'
|
||||
class MyView extends View
|
||||
afterAttach: (onDom) ->
|
||||
#...
|
||||
|
||||
beforeRemove: ->
|
||||
#...
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New way
|
||||
{View} = require 'atom-space-pen-views'
|
||||
class MyView extends View
|
||||
attached: ->
|
||||
# Always called with the equivalent of @afterAttach(true)!
|
||||
#...
|
||||
|
||||
detached: ->
|
||||
#...
|
||||
```
|
||||
|
||||
#### `subscribe` and `subscribeToCommand` methods removed
|
||||
|
||||
The `subscribe` and `subscribeToCommand` methods have been removed. See the Eventing and Disposables section for more info.
|
||||
|
||||
### Upgrading to the new TextEditorView
|
||||
|
||||
All of the atom-specific methods available on the `TextEditorView` have been moved to the `TextEditor`, available via `TextEditorView::getModel`. See the [`TextEditorView` docs][TextEditorView] and [`TextEditor` docs][TextEditor] for more info.
|
||||
|
||||
### Upgrading classes extending ScrollView
|
||||
|
||||
The `ScrollView` has very minor changes.
|
||||
|
||||
You can no longer use `@off` to remove default behavior for `core:move-up`, `core:move-down`, etc.
|
||||
|
||||
```coffee
|
||||
# Old way to turn off default behavior
|
||||
class ResultsView extends ScrollView
|
||||
initialize: (@model) ->
|
||||
super()
|
||||
# turn off default scrolling behavior from ScrollView
|
||||
@off 'core:move-up'
|
||||
@off 'core:move-down'
|
||||
@off 'core:move-left'
|
||||
@off 'core:move-right'
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New way to turn off default behavior
|
||||
class ResultsView extends ScrollView
|
||||
initialize: (@model) ->
|
||||
disposable = super()
|
||||
# turn off default scrolling behavior from ScrollView
|
||||
disposable.dispose()
|
||||
```
|
||||
|
||||
* Check out [an example](https://github.com/atom/find-and-replace/pull/311/files#diff-9) from find-and-replace.
|
||||
* See the [docs][ScrollView] for all the options.
|
||||
|
||||
### Upgrading classes extending SelectListView
|
||||
|
||||
Your SelectListView might look something like this:
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
class CommandPaletteView extends SelectListView
|
||||
initialize: ->
|
||||
super()
|
||||
@addClass('command-palette overlay from-top')
|
||||
atom.workspaceView.command 'command-palette:toggle', => @toggle()
|
||||
|
||||
confirmed: ({name, jQuery}) ->
|
||||
@cancel()
|
||||
# do something with the result
|
||||
|
||||
toggle: ->
|
||||
if @hasParent()
|
||||
@cancel()
|
||||
else
|
||||
@attach()
|
||||
|
||||
attach: ->
|
||||
@storeFocusedElement()
|
||||
|
||||
items = [] # TODO: build items
|
||||
@setItems(items)
|
||||
|
||||
atom.workspaceView.append(this)
|
||||
@focusFilterEditor()
|
||||
|
||||
confirmed: ({name, jQuery}) ->
|
||||
@cancel()
|
||||
```
|
||||
|
||||
This attaches and detaches itself from the dom when toggled, canceling magically detaches it from the DOM, and it uses the classes `overlay` and `from-top`.
|
||||
|
||||
The new SelectListView no longer automatically detaches itself from the DOM when cancelled. It's up to you to implement whatever cancel beahavior you want. Using the new APIs to mimic the sematics of the old class, it should look like this:
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
class CommandPaletteView extends SelectListView
|
||||
initialize: ->
|
||||
super()
|
||||
# no more need for the `overlay` and `from-top` classes
|
||||
@addClass('command-palette')
|
||||
atom.commands.add 'atom-workspace', 'command-palette:toggle', => @toggle()
|
||||
|
||||
# You need to implement the `cancelled` method and hide.
|
||||
cancelled: ->
|
||||
@hide()
|
||||
|
||||
confirmed: ({name, jQuery}) ->
|
||||
@cancel()
|
||||
# do something with the result
|
||||
|
||||
toggle: ->
|
||||
# Toggling now checks panel visibility,
|
||||
# and hides / shows rather than attaching to / detaching from the DOM.
|
||||
if @panel?.isVisible()
|
||||
@cancel()
|
||||
else
|
||||
@show()
|
||||
|
||||
show: ->
|
||||
# Now you will add your select list as a modal panel to the workspace
|
||||
@panel ?= atom.workspace.addModalPanel(item: this)
|
||||
@panel.show()
|
||||
|
||||
@storeFocusedElement()
|
||||
|
||||
items = [] # TODO: build items
|
||||
@setItems(items)
|
||||
|
||||
@focusFilterEditor()
|
||||
|
||||
hide: ->
|
||||
@panel?.hide()
|
||||
```
|
||||
|
||||
* And check out the [conversion of CommandPaletteView][selectlistview-example] as a real-world example.
|
||||
* See the [SelectListView docs][SelectListView] for all options.
|
||||
|
||||
## Using the model layer rather than the view layer
|
||||
|
||||
The API no longer exposes any specialized view objects or view classes. `atom.workspaceView`, and all the view classes: `WorkspaceView`, `EditorView`, `PaneView`, etc. have been globally deprecated.
|
||||
|
||||
Nearly all of the atom-specific actions performed by the old view objects can now be managed via the model layer. For example, here's adding a panel to the interface using the `atom.workspace` model instead of the `workspaceView`:
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
div = document.createElement('div')
|
||||
atom.workspaceView.appendToTop(div)
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
div = document.createElement('div')
|
||||
atom.workspace.addTopPanel(item: div)
|
||||
```
|
||||
|
||||
For actions that still require the view, such as dispatching commands or munging css classes, you'll access the view via the `atom.views.getView()` method. This will return a subclass of `HTMLElement` rather than a jQuery object or an instance of a deprecated view class (e.g. `WorkspaceView`).
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
workspaceView = atom.workspaceView
|
||||
editorView = workspaceView.getActiveEditorView()
|
||||
paneView = editorView.getPaneView()
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
# Generally, just use the models
|
||||
workspace = atom.workspace
|
||||
editor = workspace.getActiveTextEditor()
|
||||
pane = editor.getPane()
|
||||
|
||||
# If you need views, get them with `getView`
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
editorElement = atom.views.getView(editor)
|
||||
paneElement = atom.views.getView(pane)
|
||||
```
|
||||
|
||||
## Updating Specs
|
||||
|
||||
`atom.workspaceView`, the `WorkspaceView` class and the `EditorView` class have been deprecated. These two objects are used heavily throughout specs, mostly to dispatch events and commands. This section will explain how to remove them while still retaining the ability to dispatch events and commands.
|
||||
|
||||
### Removing WorkspaceView references
|
||||
|
||||
`WorkspaceView` has been deprecated. Everything you could do on the view, you can now do on the `Workspace` model.
|
||||
|
||||
Requiring `WorkspaceView` from `atom` and accessing any methods on it will throw a deprecation warning. Many specs lean heavily on `WorkspaceView` to trigger commands and fetch `EditorView` objects.
|
||||
|
||||
Your specs might contain something like this:
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
{WorkspaceView} = require 'atom'
|
||||
describe 'FindView', ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = new WorkspaceView()
|
||||
```
|
||||
|
||||
Instead, we will use the `atom.views.getView()` method. This will return a plain `HTMLElement`, not a `WorkspaceView` or jQuery object.
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
describe 'FindView', ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
```
|
||||
|
||||
### Attaching the workspace to the DOM
|
||||
|
||||
The workspace needs to be attached to the DOM in some cases. For example, view hooks only work (`attached()` on `View`, `attachedCallback()` on custom elements) when there is a descendant attached to the DOM.
|
||||
|
||||
You might see this in your specs:
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
atom.workspaceView.attachToDom()
|
||||
```
|
||||
|
||||
Change it to:
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
```
|
||||
|
||||
### Removing EditorView references
|
||||
|
||||
Like `WorkspaceView`, `EditorView` has been deprecated. Everything you needed to do on the view you are now able to do on the `TextEditor` model.
|
||||
|
||||
In many cases, you will not even need to get the editor's view anymore. Any of those instances should be updated to use the `TextEditor` instance instead. You should really only need the editor's view when you plan on triggering a command on the view in a spec.
|
||||
|
||||
Your specs might contain something like this:
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
describe 'Something', ->
|
||||
[editorView] = []
|
||||
beforeEach ->
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
```
|
||||
|
||||
We're going to use `atom.views.getView()` again to get the editor element. As in the case of the `workspaceElement`, `getView` will return a subclass of `HTMLElement` rather than an `EditorView` or jQuery object.
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
describe 'Something', ->
|
||||
[editor, editorElement] = []
|
||||
beforeEach ->
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
editorElement = atom.views.getView(editor)
|
||||
```
|
||||
|
||||
### Dispatching commands
|
||||
|
||||
Since the `editorElement` objects are no longer `jQuery` objects, they no longer support `trigger()`. Additionally, Atom has a new command dispatcher, `atom.commands`, that we use rather than commandeering jQuery's `trigger` method.
|
||||
|
||||
From this:
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
workspaceView.trigger 'a-package:toggle'
|
||||
editorView.trigger 'find-and-replace:show'
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
atom.commands.dispatch workspaceElement, 'a-package:toggle'
|
||||
atom.commands.dispatch editorElement, 'find-and-replace:show'
|
||||
```
|
||||
|
||||
## Eventing and Disposables
|
||||
|
||||
A couple large things changed with respect to events:
|
||||
|
||||
1. All model events are now exposed as event subscription methods that return [`Disposable`][disposable] objects
|
||||
1. The `subscribe()` method is no longer available on `space-pen` `View` objects
|
||||
1. An Emitter is now provided from `require 'atom'`
|
||||
|
||||
### Consuming Events
|
||||
|
||||
All events from the Atom API are now methods that return a [`Disposable`][disposable] object, on which you can call `dispose()` to unsubscribe.
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
editor.on 'changed', ->
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
disposable = editor.onDidChange ->
|
||||
|
||||
# You can unsubscribe at some point in the future via `dispose()`
|
||||
disposable.dispose()
|
||||
```
|
||||
|
||||
Deprecation warnings will guide you toward the correct methods.
|
||||
|
||||
#### Using a CompositeDisposable
|
||||
|
||||
You can group multiple disposables into a single disposable with a `CompositeDisposable`.
|
||||
|
||||
```coffee
|
||||
{CompositeDisposable} = require 'atom'
|
||||
|
||||
class Something
|
||||
constructor: ->
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
@disposables = new CompositeDisposable
|
||||
@disposables.add editor.onDidChange ->
|
||||
@disposables.add editor.onDidChangePath ->
|
||||
|
||||
destroy: ->
|
||||
@disposables.dispose()
|
||||
```
|
||||
|
||||
### Removing View::subscribe and Subscriber::subscribe calls
|
||||
|
||||
There were a couple permutations of `subscribe()`. In these examples, a `CompositeDisposable` is used as it will commonly be useful where conversion is necessary.
|
||||
|
||||
#### subscribe(unsubscribable)
|
||||
|
||||
This one is very straight forward.
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
@subscribe editor.on 'changed', ->
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
disposables = new CompositeDisposable
|
||||
disposables.add editor.onDidChange ->
|
||||
```
|
||||
|
||||
#### subscribe(modelObject, event, method)
|
||||
|
||||
When the modelObject is an Atom model object, the change is very simple. Just use the correct event method, and add it to your CompositeDisposable.
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
@subscribe editor, 'changed', ->
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
disposables = new CompositeDisposable
|
||||
disposables.add editor.onDidChange ->
|
||||
```
|
||||
|
||||
#### subscribe(jQueryObject, selector(optional), event, method)
|
||||
|
||||
Things are a little more complicated when subscribing to a DOM or jQuery element. Atom no longer provides helpers for subscribing to elements. You can use jQuery or the native DOM APIs, whichever you prefer.
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
@subscribe $(window), 'focus', ->
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
{Disposable, CompositeDisposable} = require 'atom'
|
||||
disposables = new CompositeDisposable
|
||||
|
||||
# New with jQuery
|
||||
focusCallback = ->
|
||||
$(window).on 'focus', focusCallback
|
||||
disposables.add new Disposable ->
|
||||
$(window).off 'focus', focusCallback
|
||||
|
||||
# New with native APIs
|
||||
focusCallback = ->
|
||||
window.addEventListener 'focus', focusCallback
|
||||
disposables.add new Disposable ->
|
||||
window.removeEventListener 'focus', focusCallback
|
||||
```
|
||||
|
||||
### Providing Events: Using the Emitter
|
||||
|
||||
You no longer need to require `emissary` to get an emitter. We now provide an `Emitter` class from `require 'atom'`. We have a specific pattern for use of the `Emitter`. Rather than mixing it in, we instantiate a member variable, and create explicit subscription methods. For more information see the [`Emitter` docs][emitter].
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
{Emitter} = require 'atom'
|
||||
|
||||
class Something
|
||||
constructor: ->
|
||||
@emitter = new Emitter
|
||||
|
||||
destroy: ->
|
||||
@emitter.dispose()
|
||||
|
||||
onDidChange: (callback) ->
|
||||
@emitter.on 'did-change', callback
|
||||
|
||||
methodThatFiresAChange: ->
|
||||
@emitter.emit 'did-change', {data: 2}
|
||||
|
||||
# Using the evented class
|
||||
something = new Something
|
||||
something.onDidChange (eventObject) ->
|
||||
console.log eventObject.data # => 2
|
||||
something.methodThatFiresAChange()
|
||||
```
|
||||
|
||||
## Subscribing To Commands
|
||||
|
||||
`$.fn.command` and `View::subscribeToCommand` are no longer available. Now we use `atom.commands.add`, and collect the results in a `CompositeDisposable`. See [the docs][commands-add] for more info.
|
||||
|
||||
```coffee
|
||||
# Old!
|
||||
atom.workspaceView.command 'core:close core:cancel', ->
|
||||
|
||||
# When inside a View class, you might see this
|
||||
@subscribeToCommand 'core:close core:cancel', ->
|
||||
```
|
||||
|
||||
```coffee
|
||||
# New!
|
||||
@disposables.add atom.commands.add 'atom-workspace',
|
||||
'core:close': ->
|
||||
'core:cancel': ->
|
||||
|
||||
# You can register commands directly on individual DOM elements in addition to
|
||||
# using selectors. When in a View class, you should have a `@element` object
|
||||
# available. `@element` is a plain HTMLElement object
|
||||
@disposables.add atom.commands.add @element,
|
||||
'core:close': ->
|
||||
'core:cancel': ->
|
||||
```
|
||||
|
||||
## Upgrading your stylesheet's selectors
|
||||
|
||||
Many selectors have changed, and we have introduced the [Shadow DOM][shadowdom] to the editor. See [Upgrading Your Package Selectors guide][upgrading-selectors] for more information in upgrading your package stylesheets.
|
||||
|
||||
## Help us improve this guide!
|
||||
|
||||
Did you hit something painful that wasn't in here? Want to reword some bit of it? Find something incorrect? Please edit [this file][guide], and send a pull request. Contributions are greatly appreciated.
|
||||
|
||||
|
||||
|
||||
|
||||
[texteditorview]:https://github.com/atom/atom-space-pen-views#texteditorview
|
||||
[scrollview]:https://github.com/atom/atom-space-pen-views#scrollview
|
||||
[selectlistview]:https://github.com/atom/atom-space-pen-views#selectlistview
|
||||
[selectlistview-example]:https://github.com/atom/command-palette/pull/19/files
|
||||
[emitter]:https://atom.io/docs/api/latest/Emitter
|
||||
[texteditor]:https://atom.io/docs/api/latest/TextEditor
|
||||
[disposable]:https://atom.io/docs/api/latest/Disposable
|
||||
[commands-add]:https://atom.io/docs/api/latest/CommandRegistry#instance-add
|
||||
[upgrading-selectors]:upgrading-your-ui-theme
|
||||
[shadowdom]:http://blog.atom.io/2014/11/18/avoiding-style-pollution-with-the-shadow-dom.html
|
||||
[guide]:https://github.com/atom/atom/blob/master/docs/upgrading/upgrading-your-package.md
|
||||
@@ -6,19 +6,16 @@ Syntax themes are specifically intended to style only text editor content, so th
|
||||
|
||||
When theme style sheets are loaded into the text editor's shadow DOM, selectors intended to target the editor from the *outside* no longer make sense. Styles targeting the `.editor` and `.editor-colors` classes instead need to target the `:host` pseudo-element, which matches against the containing `atom-text-editor` node. Check out the [Shadow DOM 201][host-pseudo-element] article for more information about the `:host` pseudo-element.
|
||||
|
||||
Here's an example from Atom's light syntax theme. Note that the previous selectors intended to target the editor from the outside have been retained to allow the theme to keep working during the transition phase when it is possible to disable the shadow DOM.
|
||||
Here's an example from Atom's light syntax theme. Note that the `atom-text-editor` selector intended to target the editor from the outside has been retained to allow the theme to keep working during the transition phase when it is possible to disable the shadow DOM.
|
||||
|
||||
```css
|
||||
.editor-colors, :host { /* :host added */
|
||||
atom-text-editor, :host { /* :host added */
|
||||
background-color: @syntax-background-color;
|
||||
color: @syntax-text-color;
|
||||
}
|
||||
|
||||
.editor, :host { /* :host added */
|
||||
.invisible-character {
|
||||
color: @syntax-invisible-character-color;
|
||||
}
|
||||
|
||||
/* more nested selectors... */
|
||||
}
|
||||
```
|
||||
|
||||
@@ -88,17 +88,17 @@ run the `ascii-art:convert` command it will output 'Hello, World!'
|
||||
Now let's add a key binding to trigger the `ascii-art:convert` command. Open
|
||||
_keymaps/ascii-art.cson_ and add a key binding linking `ctrl-alt-a` to the
|
||||
`ascii-art:convert` command. You can delete the pre-existing key binding since
|
||||
you don't need it anymore. When finished, the file will look like this:
|
||||
you don't need it anymore. When finished, the file will have this:
|
||||
|
||||
```coffeescript
|
||||
'atom-text-editor':
|
||||
'cmd-alt-a': 'ascii-art:convert'
|
||||
'ctrl-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
|
||||
the Tree View has focus, pressing `ctrl-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.
|
||||
@@ -142,7 +142,7 @@ convert: ->
|
||||
selection.insertText("\n#{asciiArt}\n")
|
||||
```
|
||||
|
||||
Select some text in an editor window and hit `cmd-alt-a`. :tada: You're now an
|
||||
Select some text in an editor window and hit `ctrl-alt-a`. :tada: You're now an
|
||||
ASCII art professional!
|
||||
|
||||
## Further reading
|
||||
|
||||
+34
-30
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.173.0",
|
||||
"version": "0.177.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.20.5",
|
||||
"atomShellVersion": "0.20.7",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.5.2",
|
||||
@@ -29,7 +29,7 @@
|
||||
"delegato": "^1",
|
||||
"emissary": "^1.3.1",
|
||||
"event-kit": "^1.0.1",
|
||||
"first-mate": "^2.2.4",
|
||||
"first-mate": "^2.2.5",
|
||||
"fs-plus": "^2.3.2",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^2.1",
|
||||
@@ -39,14 +39,14 @@
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"jquery": "^2.1.1",
|
||||
"less-cache": "0.19.0",
|
||||
"less-cache": "git+https://github.com/atom/less-cache.git#018b1739ae03ee35aae9827d7d7b16d0799c5d42",
|
||||
"marked": "^0.3",
|
||||
"mixto": "^1",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.4",
|
||||
"oniguruma": "^3.0.6",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^2.6.0",
|
||||
"pathwatcher": "^2.6.1",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
@@ -56,14 +56,14 @@
|
||||
"scandal": "1.0.3",
|
||||
"scoped-property-store": "^0.16.2",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^5.0.5",
|
||||
"season": "^5.1.1",
|
||||
"semver": "2.2.1",
|
||||
"serializable": "^1",
|
||||
"service-hub": "^0.1.0",
|
||||
"service-hub": "^0.2.0",
|
||||
"space-pen": "3.8.2",
|
||||
"stacktrace-parser": "0.1.1",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.10.0",
|
||||
"text-buffer": "^3.10.1",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.6",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
@@ -75,6 +75,10 @@
|
||||
"atom-light-ui": "0.40.0",
|
||||
"base16-tomorrow-dark-theme": "0.25.0",
|
||||
"base16-tomorrow-light-theme": "0.8.0",
|
||||
"one-dark-ui": "0.2.0",
|
||||
"one-dark-syntax": "0.2.0",
|
||||
"one-light-syntax": "0.2.0",
|
||||
"one-light-ui": "0.1.0",
|
||||
"solarized-dark-syntax": "0.32.0",
|
||||
"solarized-light-syntax": "0.19.0",
|
||||
"archive-view": "0.44.0",
|
||||
@@ -82,52 +86,52 @@
|
||||
"autoflow": "0.21.0",
|
||||
"autosave": "0.20.0",
|
||||
"background-tips": "0.21.0",
|
||||
"bookmarks": "0.34.0",
|
||||
"bookmarks": "0.35.0",
|
||||
"bracket-matcher": "0.69.0",
|
||||
"command-palette": "0.34.0",
|
||||
"deprecation-cop": "0.31.0",
|
||||
"dev-live-reload": "0.38.0",
|
||||
"encoding-selector": "0.15.0",
|
||||
"deprecation-cop": "0.33.0",
|
||||
"dev-live-reload": "0.39.0",
|
||||
"encoding-selector": "0.17.0",
|
||||
"exception-reporting": "0.21.0",
|
||||
"find-and-replace": "0.156.0",
|
||||
"fuzzy-finder": "0.65.0",
|
||||
"git-diff": "0.48.0",
|
||||
"git-diff": "0.50.0",
|
||||
"go-to-line": "0.30.0",
|
||||
"grammar-selector": "0.43.0",
|
||||
"grammar-selector": "0.44.0",
|
||||
"image-view": "0.47.0",
|
||||
"incompatible-packages": "0.20.0",
|
||||
"keybinding-resolver": "0.26.0",
|
||||
"incompatible-packages": "0.21.0",
|
||||
"keybinding-resolver": "0.27.0",
|
||||
"link": "0.29.0",
|
||||
"markdown-preview": "0.120.0",
|
||||
"metrics": "0.40.0",
|
||||
"notifications": "0.25.0",
|
||||
"markdown-preview": "0.126.0",
|
||||
"metrics": "0.41.0",
|
||||
"notifications": "0.26.0",
|
||||
"open-on-github": "0.32.0",
|
||||
"package-generator": "0.37.0",
|
||||
"release-notes": "0.46.0",
|
||||
"settings-view": "0.173.0",
|
||||
"snippets": "0.69.0",
|
||||
"release-notes": "0.47.0",
|
||||
"settings-view": "0.174.0",
|
||||
"snippets": "0.70.0",
|
||||
"spell-check": "0.51.0",
|
||||
"status-bar": "0.57.0",
|
||||
"status-bar": "0.58.0",
|
||||
"styleguide": "0.42.0",
|
||||
"symbols-view": "0.79.0",
|
||||
"tabs": "0.64.0",
|
||||
"timecop": "0.27.0",
|
||||
"tree-view": "0.148.0",
|
||||
"timecop": "0.28.0",
|
||||
"tree-view": "0.149.0",
|
||||
"update-package-dependencies": "0.7.0",
|
||||
"welcome": "0.21.0",
|
||||
"whitespace": "0.28.0",
|
||||
"wrap-guide": "0.30.0",
|
||||
"wrap-guide": "0.31.0",
|
||||
"language-c": "0.37.0",
|
||||
"language-clojure": "0.10.0",
|
||||
"language-coffee-script": "0.39.0",
|
||||
"language-css": "0.26.0",
|
||||
"language-gfm": "0.62.0",
|
||||
"language-gfm": "0.63.0",
|
||||
"language-git": "0.10.0",
|
||||
"language-go": "0.21.0",
|
||||
"language-html": "0.28.0",
|
||||
"language-hyperlink": "0.12.2",
|
||||
"language-java": "0.14.0",
|
||||
"language-javascript": "0.54.0",
|
||||
"language-javascript": "0.55.0",
|
||||
"language-json": "0.11.0",
|
||||
"language-less": "0.24.0",
|
||||
"language-make": "0.13.0",
|
||||
@@ -142,7 +146,7 @@
|
||||
"language-sass": "0.31.0",
|
||||
"language-shellscript": "0.12.0",
|
||||
"language-source": "0.9.0",
|
||||
"language-sql": "0.13.0",
|
||||
"language-sql": "0.14.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.15.0",
|
||||
"language-toml": "0.15.0",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
"$0/../../app/apm/node_modules/atom-package-manager/bin/node.exe" "$0/../../app/apm/node_modules/atom-package-manager/lib/cli.js" "$@"
|
||||
"$0/../../app/apm/bin/node.exe" "$0/../../app/apm/lib/cli.js" "$@"
|
||||
|
||||
@@ -18,5 +18,5 @@ FOR %%a IN (%*) DO (
|
||||
IF "%EXPECT_OUTPUT%"=="YES" (
|
||||
"%~dp0\..\..\atom.exe" %*
|
||||
) ELSE (
|
||||
"%~dp0\..\app\apm\node_modules\atom-package-manager\bin\node.exe" "%~dp0\atom.js" %*
|
||||
"%~dp0\..\app\apm\bin\node.exe" "%~dp0\atom.js" %*
|
||||
)
|
||||
|
||||
@@ -18,5 +18,5 @@ done
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
"$0/../../../atom.exe" "$@"
|
||||
else
|
||||
"$0/../../app/apm/node_modules/atom-package-manager/bin/node.exe" "$0/../atom.js" "$@"
|
||||
"$0/../../app/apm/bin/node.exe" "$0/../atom.js" "$@"
|
||||
fi
|
||||
|
||||
+3
-3
@@ -48,9 +48,9 @@ function bootstrap() {
|
||||
var dedupeNpmCommand = npmPath + npmFlags + 'dedupe';
|
||||
|
||||
if (process.argv.indexOf('--no-quiet') === -1) {
|
||||
buildInstallCommand += ' --quiet';
|
||||
apmInstallCommand += ' --quiet';
|
||||
moduleInstallCommand += ' --quiet';
|
||||
buildInstallCommand += ' --loglevel error';
|
||||
apmInstallCommand += ' --loglevel error';
|
||||
moduleInstallCommand += ' --loglevel error';
|
||||
dedupeApmCommand += ' --quiet';
|
||||
dedupeNpmCommand += ' --quiet';
|
||||
buildInstallOptions.ignoreStdout = true;
|
||||
|
||||
@@ -226,14 +226,44 @@ describe "Config", ->
|
||||
advanceClock(500)
|
||||
expect(atom.config.save.callCount).toBe 1
|
||||
|
||||
describe "when a 'source' and no 'scopeSelector' is given", ->
|
||||
it "removes all scoped settings with the given source", ->
|
||||
atom.config.set("foo.bar.baz", 1, scopeSelector: ".a", source: "source-a")
|
||||
atom.config.set("foo.bar.quux", 2, scopeSelector: ".b", source: "source-a")
|
||||
expect(atom.config.get("foo.bar", scope: [".a.b"])).toEqual(baz: 1, quux: 2)
|
||||
describe "when no 'scopeSelector' is given", ->
|
||||
describe "when a 'source' but no key-path is given", ->
|
||||
it "removes all scoped settings with the given source", ->
|
||||
atom.config.set("foo.bar.baz", 1, scopeSelector: ".a", source: "source-a")
|
||||
atom.config.set("foo.bar.quux", 2, scopeSelector: ".b", source: "source-a")
|
||||
expect(atom.config.get("foo.bar", scope: [".a.b"])).toEqual(baz: 1, quux: 2)
|
||||
|
||||
atom.config.unset(null, source: "source-a")
|
||||
expect(atom.config.get("foo.bar", scope: [".a"])).toEqual(baz: 0, ok: 0)
|
||||
atom.config.unset(null, source: "source-a")
|
||||
expect(atom.config.get("foo.bar", scope: [".a"])).toEqual(baz: 0, ok: 0)
|
||||
|
||||
describe "when a 'source' and a key-path is given", ->
|
||||
it "removes all scoped settings with the given source and key-path", ->
|
||||
atom.config.set("foo.bar.baz", 1)
|
||||
atom.config.set("foo.bar.baz", 2, scopeSelector: ".a", source: "source-a")
|
||||
atom.config.set("foo.bar.baz", 3, scopeSelector: ".a.b", source: "source-b")
|
||||
expect(atom.config.get("foo.bar.baz", scope: [".a.b"])).toEqual(3)
|
||||
|
||||
atom.config.unset("foo.bar.baz", source: "source-b")
|
||||
expect(atom.config.get("foo.bar.baz", scope: [".a.b"])).toEqual(2)
|
||||
expect(atom.config.get("foo.bar.baz")).toEqual(1)
|
||||
|
||||
describe "when no 'source' is given", ->
|
||||
it "removes all scoped and unscoped properties for that key-path", ->
|
||||
atom.config.setDefaults("foo.bar", baz: 100)
|
||||
|
||||
atom.config.set("foo.bar", { baz: 1, ok: 2 }, scopeSelector: ".a")
|
||||
atom.config.set("foo.bar", { baz: 11, ok: 12 }, scopeSelector: ".b")
|
||||
atom.config.set("foo.bar", { baz: 21, ok: 22 })
|
||||
|
||||
atom.config.unset("foo.bar.baz")
|
||||
|
||||
expect(atom.config.get("foo.bar.baz", scope: [".a"])).toBe 100
|
||||
expect(atom.config.get("foo.bar.baz", scope: [".b"])).toBe 100
|
||||
expect(atom.config.get("foo.bar.baz")).toBe 100
|
||||
|
||||
expect(atom.config.get("foo.bar.ok", scope: [".a"])).toBe 2
|
||||
expect(atom.config.get("foo.bar.ok", scope: [".b"])).toBe 12
|
||||
expect(atom.config.get("foo.bar.ok")).toBe 22
|
||||
|
||||
describe "when a 'scopeSelector' is given", ->
|
||||
it "restores the global default when no scoped default set", ->
|
||||
@@ -1363,6 +1393,14 @@ describe "Config", ->
|
||||
atom.config.set('foo.bar.aColor', false)
|
||||
expect(atom.config.get('foo.bar.aColor')).toEqual {red: 255, green: 255, blue: 255, alpha: 1}
|
||||
|
||||
it "returns a clone of the Color when returned in a parent object", ->
|
||||
color1 = atom.config.get('foo.bar').aColor
|
||||
color2 = atom.config.get('foo.bar').aColor
|
||||
expect(color1.toRGBAString()).toBe 'rgba(255, 255, 255, 1)'
|
||||
expect(color2.toRGBAString()).toBe 'rgba(255, 255, 255, 1)'
|
||||
expect(color1).not.toBe color2
|
||||
expect(color1).toEqual color2
|
||||
|
||||
describe 'when the `enum` key is used', ->
|
||||
beforeEach ->
|
||||
schema =
|
||||
|
||||
@@ -9,5 +9,3 @@ module.exports =
|
||||
two:
|
||||
type: 'integer'
|
||||
default: 2
|
||||
|
||||
activate: -> # no-op
|
||||
|
||||
@@ -37,6 +37,32 @@ describe "Project", ->
|
||||
deserializedProject.getBuffers()[0].destroy()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
|
||||
|
||||
it "does not deserialize buffers when their path is a directory that exists", ->
|
||||
pathToOpen = path.join(temp.mkdirSync(), 'file.txt')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(pathToOpen)
|
||||
|
||||
runs ->
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
fs.mkdirSync(pathToOpen)
|
||||
deserializedProject = atom.project.testSerialization()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
|
||||
it "does not deserialize buffers when their path is inaccessible", ->
|
||||
pathToOpen = path.join(temp.mkdirSync(), 'file.txt')
|
||||
fs.writeFileSync(pathToOpen, '')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(pathToOpen)
|
||||
|
||||
runs ->
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
fs.chmodSync(pathToOpen, '000')
|
||||
deserializedProject = atom.project.testSerialization()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
|
||||
describe "when an editor is saved and the project has no path", ->
|
||||
it "sets the project's path to the saved file's parent directory", ->
|
||||
tempFile = temp.openSync().path
|
||||
|
||||
@@ -213,6 +213,11 @@ jasmine.snapshotDeprecations = ->
|
||||
jasmine.restoreDeprecationsSnapshot = ->
|
||||
Grim.deprecations = deprecationsSnapshot
|
||||
|
||||
jasmine.useRealClock = ->
|
||||
jasmine.unspy(window, 'setTimeout')
|
||||
jasmine.unspy(window, 'clearTimeout')
|
||||
jasmine.unspy(_._, 'now')
|
||||
|
||||
addCustomMatchers = (spec) ->
|
||||
spec.addMatchers
|
||||
toBeInstanceOf: (expected) ->
|
||||
@@ -298,13 +303,13 @@ window.waitsForPromise = (args...) ->
|
||||
window.waitsFor timeout, (moveOn) ->
|
||||
promise = fn()
|
||||
if shouldReject
|
||||
promise.fail(moveOn)
|
||||
promise.done ->
|
||||
promise.catch(moveOn)
|
||||
promise.then ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be rejected, but it was resolved")
|
||||
moveOn()
|
||||
else
|
||||
promise.done(moveOn)
|
||||
promise.fail (error) ->
|
||||
promise.then(moveOn)
|
||||
promise.catch (error) ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with #{jasmine.pp(error)}")
|
||||
moveOn()
|
||||
|
||||
|
||||
@@ -155,6 +155,25 @@ describe "TextEditor", ->
|
||||
expect(editor2.getSoftTabs()).toBe true
|
||||
expect(editor2.getEncoding()).toBe 'macroman'
|
||||
|
||||
it "uses scoped `core.fileEncoding` values", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
|
||||
atom.config.set('core.fileEncoding', 'utf16le')
|
||||
atom.config.set('core.fileEncoding', 'macroman', scopeSelector: '.js')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('a').then (o) -> editor1 = o
|
||||
|
||||
runs ->
|
||||
expect(editor1.getEncoding()).toBe 'utf16le'
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('test.js').then (o) -> editor2 = o
|
||||
|
||||
runs ->
|
||||
expect(editor2.getEncoding()).toBe 'macroman'
|
||||
|
||||
describe "title", ->
|
||||
describe ".getTitle()", ->
|
||||
it "uses the basename of the buffer's path as its title, or 'untitled' if the path is undefined", ->
|
||||
@@ -2630,12 +2649,20 @@ describe "TextEditor", ->
|
||||
atom.config.set("editor.autoIndentOnPaste", true)
|
||||
|
||||
describe "when only whitespace precedes the cursor", ->
|
||||
it "auto-indents the lines spanned by the pasted text", ->
|
||||
atom.clipboard.write("console.log(x);\nconsole.log(y);\n")
|
||||
editor.setCursorBufferPosition([5, 2])
|
||||
it "auto-indents the lines spanned by the pasted text, based on the first pasted line", ->
|
||||
expect(editor.indentationForBufferRow(5)).toBe(3)
|
||||
|
||||
atom.clipboard.write("a(x);\n b(x);\n c(x);\n", indentBasis: 0)
|
||||
editor.setCursorBufferPosition([5, 0])
|
||||
editor.pasteText()
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(" console.log(x);")
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(" console.log(y);")
|
||||
|
||||
# Adjust the indentation of the pasted block
|
||||
expect(editor.indentationForBufferRow(5)).toBe(3)
|
||||
expect(editor.indentationForBufferRow(6)).toBe(4)
|
||||
expect(editor.indentationForBufferRow(7)).toBe(5)
|
||||
|
||||
# Preserve the indentation of the next row
|
||||
expect(editor.indentationForBufferRow(8)).toBe(3)
|
||||
|
||||
describe "when non-whitespace characters precede the cursor", ->
|
||||
it "does not auto-indent the first line being pasted", ->
|
||||
@@ -2732,9 +2759,9 @@ describe "TextEditor", ->
|
||||
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(2)).toBe("")
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(" if (items.length <= 1) return items;")
|
||||
expect(editor.getCursorBufferPosition()).toEqual([2, 2])
|
||||
expect(editor.getCursorBufferPosition()).toEqual([2, 0])
|
||||
|
||||
describe "when there is no selection", ->
|
||||
it "pastes the line above the cursor and retains the cursor's column", ->
|
||||
|
||||
@@ -315,6 +315,44 @@ describe "Workspace", ->
|
||||
expect(notification.getMessage()).toContain 'Permission denied'
|
||||
expect(notification.getMessage()).toContain 'file1'
|
||||
|
||||
describe "when the the operation is not permitted", ->
|
||||
beforeEach ->
|
||||
spyOn(fs, 'openSync').andCallFake (path) ->
|
||||
error = new Error("EPERM, operation not permitted '#{path}'")
|
||||
error.path = path
|
||||
error.code = 'EPERM'
|
||||
throw error
|
||||
|
||||
it "creates a notification", ->
|
||||
waitsForPromise ->
|
||||
workspace.open('file1')
|
||||
|
||||
runs ->
|
||||
expect(notificationSpy).toHaveBeenCalled()
|
||||
notification = notificationSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'warning'
|
||||
expect(notification.getMessage()).toContain 'Unable to open'
|
||||
expect(notification.getMessage()).toContain 'file1'
|
||||
|
||||
describe "when the the file is already open in windows", ->
|
||||
beforeEach ->
|
||||
spyOn(fs, 'openSync').andCallFake (path) ->
|
||||
error = new Error("EBUSY, resource busy or locked '#{path}'")
|
||||
error.path = path
|
||||
error.code = 'EBUSY'
|
||||
throw error
|
||||
|
||||
it "creates a notification", ->
|
||||
waitsForPromise ->
|
||||
workspace.open('file1')
|
||||
|
||||
runs ->
|
||||
expect(notificationSpy).toHaveBeenCalled()
|
||||
notification = notificationSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'warning'
|
||||
expect(notification.getMessage()).toContain 'Unable to open'
|
||||
expect(notification.getMessage()).toContain 'file1'
|
||||
|
||||
describe "when there is an unhandled error", ->
|
||||
beforeEach ->
|
||||
spyOn(fs, 'openSync').andCallFake (path) ->
|
||||
@@ -948,6 +986,43 @@ describe "Workspace", ->
|
||||
expect(addedSpy).toHaveBeenCalled()
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the operation is not permitted", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
error = new Error("EPERM, operation not permitted '/Some/dir/and-a-file.js'")
|
||||
error.code = 'EPERM'
|
||||
error.path = '/Some/dir/and-a-file.js'
|
||||
throw error
|
||||
|
||||
it "emits a warning notification when the file is already open by another app", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
error = new Error("EBUSY, resource busy or locked '/Some/dir/and-a-file.js'")
|
||||
error.code = 'EBUSY'
|
||||
error.path = '/Some/dir/and-a-file.js'
|
||||
throw error
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
atom.workspace.saveActivePaneItem()
|
||||
expect(addedSpy).toHaveBeenCalled()
|
||||
|
||||
notificaiton = addedSpy.mostRecentCall.args[0]
|
||||
expect(notificaiton.getType()).toBe 'warning'
|
||||
expect(notificaiton.getMessage()).toContain 'Unable to save'
|
||||
|
||||
it "emits a warning notification when the file system is read-only", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
error = new Error("EROFS, read-only file system '/Some/dir/and-a-file.js'")
|
||||
error.code = 'EROFS'
|
||||
error.path = '/Some/dir/and-a-file.js'
|
||||
throw error
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
atom.workspace.saveActivePaneItem()
|
||||
expect(addedSpy).toHaveBeenCalled()
|
||||
|
||||
notification = addedSpy.mostRecentCall.args[0]
|
||||
expect(notification.getType()).toBe 'warning'
|
||||
expect(notification.getMessage()).toContain 'Unable to save'
|
||||
|
||||
it "emits a warning notification when the file cannot be saved", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("no one knows")
|
||||
|
||||
+5
-14
@@ -3,7 +3,6 @@ ipc = require 'ipc'
|
||||
os = require 'os'
|
||||
path = require 'path'
|
||||
remote = require 'remote'
|
||||
screen = require 'screen'
|
||||
shell = require 'shell'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
@@ -280,8 +279,6 @@ class Atom extends Model
|
||||
deprecate "The atom.syntax global is deprecated. Use atom.grammars instead."
|
||||
@grammars
|
||||
|
||||
@subscribe @packages.onDidActivateInitialPackages => @watchThemes()
|
||||
|
||||
Project = require './project'
|
||||
TextBuffer = require 'text-buffer'
|
||||
@deserializers.add(TextBuffer)
|
||||
@@ -547,6 +544,7 @@ class Atom extends Model
|
||||
if @isValidDimensions(dimensions)
|
||||
dimensions
|
||||
else
|
||||
screen = remote.require 'screen'
|
||||
{width, height} = screen.getPrimaryDisplay().workAreaSize
|
||||
{x: 0, y: 0, width: Math.min(1024, width), height}
|
||||
|
||||
@@ -580,7 +578,10 @@ class Atom extends Model
|
||||
|
||||
@watchProjectPath()
|
||||
|
||||
@packages.activate()
|
||||
@packages.activate().then =>
|
||||
maximize = dimensions?.maximized and process.platform isnt 'darwin'
|
||||
@displayWindow({maximize})
|
||||
|
||||
@keymaps.loadUserKeymap()
|
||||
@requireUserInitScript() unless safeMode
|
||||
|
||||
@@ -589,9 +590,6 @@ class Atom extends Model
|
||||
@setAutoHideMenuBar(newValue)
|
||||
@setAutoHideMenuBar(true) if @config.get('core.autoHideMenuBar')
|
||||
|
||||
maximize = dimensions?.maximized and process.platform isnt 'darwin'
|
||||
@displayWindow({maximize})
|
||||
|
||||
unloadEditorWindow: ->
|
||||
return if not @project
|
||||
|
||||
@@ -720,13 +718,6 @@ class Atom extends Model
|
||||
loadThemes: ->
|
||||
@themes.load()
|
||||
|
||||
watchThemes: ->
|
||||
@themes.onDidChangeActiveThemes =>
|
||||
# Only reload stylesheets from non-theme packages
|
||||
for pack in @packages.getActivePackages() when pack.getType() isnt 'theme'
|
||||
pack.reloadStylesheets?()
|
||||
null
|
||||
|
||||
# Notify the browser project of the window's current project path
|
||||
watchProjectPath: ->
|
||||
onProjectPathChanged = =>
|
||||
|
||||
@@ -10,7 +10,6 @@ module.exports =
|
||||
class AtomWindow
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
|
||||
@iconPath: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
@includeShellLoadTime: true
|
||||
|
||||
browserWindow: null
|
||||
@@ -26,7 +25,6 @@ class AtomWindow
|
||||
@browserWindow = new BrowserWindow
|
||||
show: false
|
||||
title: 'Atom'
|
||||
icon: @constructor.iconPath
|
||||
'web-preferences':
|
||||
'direct-write': false
|
||||
'subpixel-font-scaling': false
|
||||
|
||||
@@ -13,16 +13,6 @@ 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'
|
||||
@@ -50,8 +40,12 @@ start = ->
|
||||
app.removeListener 'open-file', addPathToOpen
|
||||
app.removeListener 'open-url', addUrlToOpen
|
||||
|
||||
cwd = args.executedFrom?.toString() or process.cwd()
|
||||
args.pathsToOpen = args.pathsToOpen.map (pathToOpen) ->
|
||||
path.resolve(args.executedFrom ? process.cwd(), pathToOpen.toString())
|
||||
if cwd
|
||||
path.resolve(cwd, pathToOpen.toString())
|
||||
else
|
||||
path.resolve(pathToOpen.toString())
|
||||
|
||||
setupCoffeeScript()
|
||||
if args.devMode
|
||||
|
||||
@@ -125,7 +125,7 @@ addCommandsToPath = (callback) ->
|
||||
atomShCommand = "#!/bin/sh\r\n\"$0/../#{relativeAtomShPath.replace(/\\/g, '/')}\" \"$@\""
|
||||
|
||||
apmCommandPath = path.join(binFolder, 'apm.cmd')
|
||||
relativeApmPath = path.relative(binFolder, path.join(process.resourcesPath, 'app', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm.cmd'))
|
||||
relativeApmPath = path.relative(binFolder, path.join(process.resourcesPath, 'app', 'apm', 'bin', 'apm.cmd'))
|
||||
apmCommand = "@echo off\r\n\"%~dp0\\#{relativeApmPath}\" %*"
|
||||
|
||||
apmShCommandPath = path.join(binFolder, 'apm')
|
||||
|
||||
@@ -28,22 +28,23 @@ class BufferedProcess
|
||||
# * `options` An {Object} with the following keys:
|
||||
# * `command` The {String} command to execute.
|
||||
# * `args` The {Array} of arguments to pass to the command (optional).
|
||||
# * `options` The options {Object} to pass to Node's `ChildProcess.spawn`
|
||||
# method (optional).
|
||||
# * `stdout` The callback {Function} that receives a single argument which
|
||||
# contains the standard output from the command. The callback is
|
||||
# called as data is received but it's buffered to ensure only
|
||||
# complete lines are passed until the source stream closes. After
|
||||
# the source stream has closed all remaining data is sent in a
|
||||
# final call (optional).
|
||||
# * `stderr` The callback {Function} that receives a single argument which
|
||||
# contains the standard error output from the command. The
|
||||
# callback is called as data is received but it's buffered to
|
||||
# ensure only complete lines are passed until the source stream
|
||||
# closes. After the source stream has closed all remaining data
|
||||
# is sent in a final call (optional).
|
||||
# * `exit` The callback {Function} which receives a single argument
|
||||
# containing the exit status (optional).
|
||||
# * `options` {Object} (optional) The options {Object} to pass to Node's
|
||||
# `ChildProcess.spawn` method.
|
||||
# * `stdout` {Function} (optional) The callback that receives a single
|
||||
# argument which contains the standard output from the command. The
|
||||
# callback is called as data is received but it's buffered to ensure only
|
||||
# complete lines are passed until the source stream closes. After the
|
||||
# source stream has closed all remaining data is sent in a final call.
|
||||
# * `data` {String}
|
||||
# * `stderr` {Function} (optional) The callback that receives a single
|
||||
# argument which contains the standard error output from the command. The
|
||||
# callback is called as data is received but it's buffered to ensure only
|
||||
# complete lines are passed until the source stream closes. After the
|
||||
# source stream has closed all remaining data is sent in a final call.
|
||||
# * `data` {String}
|
||||
# * `exit` {Function} (optional) The callback which receives a single
|
||||
# argument containing the exit status.
|
||||
# * `code` {Number}
|
||||
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
|
||||
@emitter = new Emitter
|
||||
options ?= {}
|
||||
|
||||
@@ -7,6 +7,10 @@ fs = require 'fs-plus'
|
||||
|
||||
cacheDir = path.join(fs.absolute('~/.atom'), 'compile-cache')
|
||||
|
||||
stats =
|
||||
hits: 0
|
||||
misses: 0
|
||||
|
||||
# Use separate compile cache when sudo'ing as root to avoid permission issues
|
||||
if process.env.USER is 'root' and process.env.SUDO_USER and process.env.SUDO_USER isnt process.env.USER
|
||||
cacheDir = path.join(cacheDir, 'root')
|
||||
@@ -21,7 +25,10 @@ getCachePath = (coffee) ->
|
||||
getCachedJavaScript = (cachePath) ->
|
||||
if fs.isFileSync(cachePath)
|
||||
try
|
||||
fs.readFileSync(cachePath, 'utf8')
|
||||
cachedJavaScript = fs.readFileSync(cachePath, 'utf8')
|
||||
stats.hits++
|
||||
return cachedJavaScript
|
||||
return
|
||||
|
||||
convertFilePath = (filePath) ->
|
||||
if process.platform is 'win32'
|
||||
@@ -30,6 +37,7 @@ convertFilePath = (filePath) ->
|
||||
|
||||
compileCoffeeScript = (coffee, filePath, cachePath) ->
|
||||
{js, v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
|
||||
stats.misses++
|
||||
# Include source map in the web page environment.
|
||||
if btoa? and JSON? and unescape? and encodeURIComponent?
|
||||
js = "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=#{convertFilePath(filePath)}"
|
||||
@@ -60,3 +68,7 @@ module.exports =
|
||||
compileCoffeeScript(coffee, filePath, cachePath)
|
||||
else if extension is '.cson'
|
||||
CSON.readFileSync(filePath)
|
||||
|
||||
getCacheMisses: -> stats.misses
|
||||
|
||||
getCacheHits: -> stats.hits
|
||||
|
||||
+18
-12
@@ -583,6 +583,7 @@ class Config
|
||||
Pass a `scopeSelector` in an options hash as the final argument instead.
|
||||
"""
|
||||
[scopeSelector, keyPath, value] = arguments
|
||||
shouldSave = true
|
||||
else
|
||||
[keyPath, value, options] = arguments
|
||||
scopeSelector = options?.scopeSelector
|
||||
@@ -640,8 +641,9 @@ class Config
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector(source, scopeSelector)
|
||||
@emitChangeEvent()
|
||||
else
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
if keyPath?
|
||||
for scopeSelector of @scopedSettingsStore.propertiesForSource(source)
|
||||
@unset(keyPath, {scopeSelector, source})
|
||||
if keyPath? and source is @getUserConfigPath()
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
|
||||
# Extended: Get an {Array} of all of the `source` {String}s with which
|
||||
@@ -898,16 +900,10 @@ class Config
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
|
||||
if value?
|
||||
if value instanceof Color
|
||||
value = value.clone()
|
||||
else
|
||||
value = _.deepClone(value)
|
||||
_.defaults(value, defaultValue) if isPlainObject(value) and isPlainObject(defaultValue)
|
||||
value = @deepClone(value)
|
||||
_.defaults(value, defaultValue) if isPlainObject(value) and isPlainObject(defaultValue)
|
||||
else
|
||||
if defaultValue instanceof Color
|
||||
value = defaultValue.clone()
|
||||
else
|
||||
value = _.deepClone(defaultValue)
|
||||
value = @deepClone(defaultValue)
|
||||
|
||||
value
|
||||
|
||||
@@ -957,6 +953,16 @@ class Config
|
||||
catch e
|
||||
console.warn("'#{keyPath}' could not set the default. Attempted default: #{JSON.stringify(defaults)}; Schema: #{JSON.stringify(@getSchema(keyPath))}")
|
||||
|
||||
deepClone: (object) ->
|
||||
if object instanceof Color
|
||||
object.clone()
|
||||
else if _.isArray(object)
|
||||
object.map (value) => @deepClone(value)
|
||||
else if isPlainObject(object)
|
||||
_.mapObject object, (key, value) => [key, @deepClone(value)]
|
||||
else
|
||||
object
|
||||
|
||||
# `schema` will look something like this
|
||||
#
|
||||
# ```coffee
|
||||
@@ -1162,7 +1168,7 @@ Config.addSchemaEnforcers
|
||||
throw new Error("Validation failed at #{keyPath}, #{JSON.stringify(value)} is not one of #{JSON.stringify(possibleValues)}")
|
||||
|
||||
isPlainObject = (value) ->
|
||||
_.isObject(value) and not _.isArray(value) and not _.isFunction(value) and not _.isString(value)
|
||||
_.isObject(value) and not _.isArray(value) and not _.isFunction(value) and not _.isString(value) and not (value instanceof Color)
|
||||
|
||||
splitKeyPath = (keyPath) ->
|
||||
return [] unless keyPath?
|
||||
|
||||
@@ -30,6 +30,10 @@ class LessCompileCache
|
||||
setImportPaths: (importPaths=[]) ->
|
||||
@cache.setImportPaths(importPaths.concat(@lessSearchPaths))
|
||||
|
||||
clearFooters: -> @cache.clearFooters()
|
||||
|
||||
setFooter: (filePath, footer) -> @cache.setFooter(filePath, footer)
|
||||
|
||||
read: (stylesheetPath) ->
|
||||
@cache.readFileSync(stylesheetPath)
|
||||
|
||||
|
||||
@@ -128,9 +128,15 @@ class PackageManager
|
||||
#
|
||||
# Return a {String} file path to apm.
|
||||
getApmPath: ->
|
||||
return @apmPath if @apmPath?
|
||||
|
||||
commandName = 'apm'
|
||||
commandName += '.cmd' if process.platform is 'win32'
|
||||
@apmPath ?= path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', commandName)
|
||||
apmRoot = path.resolve(__dirname, '..', 'apm')
|
||||
@apmPath = path.join(apmRoot, 'bin', commandName)
|
||||
unless fs.isFileSync(@apmPath)
|
||||
@apmPath = path.join(apmRoot, 'node_modules', 'atom-package-manager', 'bin', commandName)
|
||||
@apmPath
|
||||
|
||||
# Public: Get the paths being used to look for packages.
|
||||
#
|
||||
@@ -148,7 +154,7 @@ class PackageManager
|
||||
#
|
||||
# Return a {String} folder path or undefined if it could not be resolved.
|
||||
resolvePackagePath: (name) ->
|
||||
return name if fs.isDirectorySync(name)
|
||||
return fs.absolute(name) if fs.isDirectorySync(name)
|
||||
|
||||
packagePath = fs.resolve(@packageDirPaths..., name)
|
||||
return packagePath if fs.isDirectorySync(packagePath)
|
||||
@@ -370,6 +376,7 @@ class PackageManager
|
||||
packages = @getLoadedPackagesForTypes(types)
|
||||
promises = promises.concat(activator.activatePackages(packages))
|
||||
Q.all(promises).then =>
|
||||
@initialPackageActivationComplete = true
|
||||
@emit 'activated'
|
||||
@emitter.emit 'did-activate-initial-packages'
|
||||
|
||||
|
||||
+21
-7
@@ -9,6 +9,7 @@ EmitterMixin = require('emissary').Emitter
|
||||
Q = require 'q'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
Color = require './color'
|
||||
ModuleCache = require './module-cache'
|
||||
ScopedProperties = require './scoped-properties'
|
||||
|
||||
@@ -123,7 +124,6 @@ class Package
|
||||
try
|
||||
@loadKeymaps()
|
||||
@loadMenus()
|
||||
@loadStylesheets()
|
||||
@settingsPromise = @loadSettings()
|
||||
@requireMainModule() unless @hasActivationCommands()
|
||||
|
||||
@@ -155,9 +155,8 @@ class Package
|
||||
activateNow: ->
|
||||
try
|
||||
@activateConfig()
|
||||
@activateStylesheets()
|
||||
if @requireMainModule()
|
||||
@mainModule.activate(atom.packages.getPackageState(@name) ? {})
|
||||
@mainModule.activate?(atom.packages.getPackageState(@name) ? {})
|
||||
@mainActivated = true
|
||||
catch e
|
||||
console.warn "Failed to activate package named '#{@name}'", e.stack
|
||||
@@ -185,6 +184,7 @@ class Package
|
||||
@stylesheetDisposables = new CompositeDisposable
|
||||
|
||||
priority = @getStyleSheetPriority()
|
||||
@loadStylesheets()
|
||||
for [sourcePath, source] in @stylesheets
|
||||
if match = path.basename(sourcePath).match(/[^.]*\.([^.]*)\./)
|
||||
context = match[1]
|
||||
@@ -236,8 +236,9 @@ class Package
|
||||
fs.listSync(menusDirPath, ['cson', 'json'])
|
||||
|
||||
loadStylesheets: ->
|
||||
@stylesheets = @getStylesheetPaths().map (stylesheetPath) ->
|
||||
[stylesheetPath, atom.themes.loadStylesheet(stylesheetPath, true)]
|
||||
@stylesheets = @getStylesheetPaths().map (stylesheetPath) =>
|
||||
stylesheet = atom.themes.loadStylesheet(stylesheetPath, {importFallbackVariables: true})
|
||||
[stylesheetPath, stylesheet]
|
||||
|
||||
getStylesheetsPath: ->
|
||||
if fs.isDirectorySync(path.join(@path, 'stylesheets'))
|
||||
@@ -257,6 +258,21 @@ class Package
|
||||
else
|
||||
fs.listSync(stylesheetDirPath, ['css', 'less'])
|
||||
|
||||
getStylesheetFooter: ->
|
||||
return unless @isTheme()
|
||||
|
||||
footer = ''
|
||||
for key, value of atom.config.get(@name)
|
||||
if typeof value is 'object' and not (value instanceof Color)
|
||||
value = Color.parse(value)
|
||||
value = value?.toRGBAString?() ? value
|
||||
switch typeof value
|
||||
when 'string'
|
||||
footer += "\n@#{key}: #{value};" if value
|
||||
when 'number'
|
||||
footer += "\n@#{key}: #{value};" if isFinite(value)
|
||||
footer
|
||||
|
||||
loadGrammarsSync: ->
|
||||
return if @grammarsLoaded
|
||||
|
||||
@@ -352,8 +368,6 @@ class Package
|
||||
@settingsActivated = false
|
||||
|
||||
reloadStylesheets: ->
|
||||
oldSheets = _.clone(@stylesheets)
|
||||
@loadStylesheets()
|
||||
@stylesheetDisposables?.dispose()
|
||||
@stylesheetDisposables = new CompositeDisposable
|
||||
@stylesheetsActivated = false
|
||||
|
||||
+11
-6
@@ -66,9 +66,17 @@ class Project extends Model
|
||||
buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained())
|
||||
|
||||
deserializeParams: (params) ->
|
||||
params.buffers = params.buffers.map (bufferState) -> atom.deserializers.deserialize(bufferState)
|
||||
params
|
||||
params.buffers = _.compact params.buffers.map (bufferState) ->
|
||||
# Check that buffer's file path is accessible
|
||||
return if fs.isDirectorySync(bufferState.filePath)
|
||||
if bufferState.filePath
|
||||
try
|
||||
fs.closeSync(fs.openSync(bufferState.filePath, 'r'))
|
||||
catch error
|
||||
return unless error.code is 'ENOENT'
|
||||
|
||||
atom.deserializers.deserialize(bufferState)
|
||||
params
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
@@ -219,8 +227,7 @@ class Project extends Model
|
||||
|
||||
if filePath?
|
||||
try
|
||||
fileDescriptor = fs.openSync(filePath, 'r+')
|
||||
fs.closeSync(fileDescriptor)
|
||||
fs.closeSync(fs.openSync(filePath, 'r'))
|
||||
catch error
|
||||
# allow ENOENT errors to create an editor for paths that dont exist
|
||||
throw error unless error.code is 'ENOENT'
|
||||
@@ -273,7 +280,6 @@ class Project extends Model
|
||||
# Still needed when deserializing a tokenized buffer
|
||||
buildBufferSync: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({filePath: absoluteFilePath})
|
||||
buffer.setEncoding(atom.config.get('core.fileEncoding'))
|
||||
@addBuffer(buffer)
|
||||
buffer.loadSync()
|
||||
buffer
|
||||
@@ -291,7 +297,6 @@ class Project extends Model
|
||||
throw error
|
||||
|
||||
buffer = new TextBuffer({filePath: absoluteFilePath})
|
||||
buffer.setEncoding(atom.config.get('core.fileEncoding'))
|
||||
@addBuffer(buffer)
|
||||
buffer.load()
|
||||
.then((buffer) -> buffer)
|
||||
|
||||
+14
-8
@@ -362,7 +362,7 @@ class Selection extends Model
|
||||
precedingText = @editor.getTextInRange([[oldBufferRange.start.row, 0], oldBufferRange.start])
|
||||
startLevel = @editor.indentLevelForLine(precedingText)
|
||||
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
if options.indentBasis?
|
||||
text = @adjustIndent(text, startLevel - options.indentBasis)
|
||||
|
||||
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo', 'normalizeLineEndings'))
|
||||
@@ -375,8 +375,16 @@ class Selection extends Model
|
||||
if options.autoIndent
|
||||
precedingText = @editor.getTextInBufferRange([[newBufferRange.start.row, 0], newBufferRange.start])
|
||||
unless NonWhitespaceRegExp.test(precedingText)
|
||||
@editor.autoIndentBufferRow(newBufferRange.getRows()[0])
|
||||
@editor.autoIndentBufferRow(row) for row, i in newBufferRange.getRows() when i > 0
|
||||
rowsToIndent = newBufferRange.getRows()
|
||||
firstRow = rowsToIndent.shift()
|
||||
rowsToIndent.pop() if text.endsWith("\n")
|
||||
suggestedIndent = @editor.suggestedIndentForBufferRow(firstRow)
|
||||
actualIndent = @editor.indentationForBufferRow(firstRow)
|
||||
@editor.setIndentationForBufferRow(firstRow, suggestedIndent)
|
||||
indentChange = suggestedIndent - actualIndent
|
||||
for row in rowsToIndent
|
||||
newIndent = @editor.indentationForBufferRow(row) + indentChange
|
||||
@editor.setIndentationForBufferRow(row, newIndent)
|
||||
else if options.autoIndentNewline and text == '\n'
|
||||
currentIndentation = @editor.indentationForBufferRow(newBufferRange.start.row)
|
||||
@editor.autoIndentBufferRow(newBufferRange.end.row, preserveLeadingWhitespace: true, skipBlankLines: false)
|
||||
@@ -595,14 +603,12 @@ class Selection extends Model
|
||||
@editor.createFold(range.start.row, range.end.row)
|
||||
@cursor.setBufferPosition([range.end.row + 1, 0])
|
||||
|
||||
# Public: Increases the indentation level of
|
||||
#
|
||||
|
||||
# * `indentIncrease` The beginning indent level.
|
||||
# Private: Increase the indentation level of the given text by given number
|
||||
# of levels. Leaves the first line unchanged.
|
||||
adjustIndent: (text, indentIncrease) ->
|
||||
lines = text.split('\n')
|
||||
for line, i in lines when i > 0
|
||||
if indentIncrease == 0
|
||||
if indentIncrease == 0 or line is ''
|
||||
continue
|
||||
else if indentIncrease > 0
|
||||
lines[i] = @editor.buildIndentString(indentIncrease) + line
|
||||
|
||||
@@ -224,7 +224,7 @@ TextEditorComponent = React.createClass
|
||||
@props.editor.setVisible(true)
|
||||
@performedInitialMeasurement = true
|
||||
@updatesPaused = false
|
||||
@forceUpdate() if @updateRequestedWhilePaused and @canUpdate()
|
||||
@forceUpdate() if @canUpdate()
|
||||
|
||||
requestUpdate: ->
|
||||
return unless @canUpdate()
|
||||
|
||||
@@ -105,6 +105,8 @@ class TextEditor extends Model
|
||||
|
||||
@languageMode = new LanguageMode(this)
|
||||
|
||||
@setEncoding(atom.config.get('core.fileEncoding', scope: @getRootScopeDescriptor()))
|
||||
|
||||
@subscribe @$scrollTop, (scrollTop) =>
|
||||
@emit 'scroll-top-changed', scrollTop
|
||||
@emitter.emit 'did-change-scroll-top', scrollTop
|
||||
|
||||
+68
-28
@@ -197,7 +197,7 @@ class ThemeManager
|
||||
]
|
||||
themeNames = _.intersection(themeNames, builtInThemeNames)
|
||||
if themeNames.length is 0
|
||||
themeNames = ['atom-dark-syntax', 'atom-dark-ui']
|
||||
themeNames = ['atom-dark-ui', 'atom-dark-syntax']
|
||||
else if themeNames.length is 1
|
||||
if _.endsWith(themeNames[0], '-ui')
|
||||
themeNames.unshift('atom-dark-syntax')
|
||||
@@ -266,7 +266,7 @@ class ThemeManager
|
||||
"""
|
||||
atom.notifications.addError(message, dismissable: true)
|
||||
|
||||
userStylesheetContents = @loadStylesheet(userStylesheetPath, true)
|
||||
userStylesheetContents = @loadStylesheet(userStylesheetPath, importFallbackVariables: true)
|
||||
@userStyleSheetDisposable = atom.styles.addStyleSheet(userStylesheetContents, sourcePath: userStylesheetPath, priority: 2)
|
||||
|
||||
loadBaseStylesheets: ->
|
||||
@@ -287,16 +287,14 @@ class ThemeManager
|
||||
else
|
||||
fs.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
|
||||
|
||||
loadStylesheet: (stylesheetPath, importFallbackVariables) ->
|
||||
loadStylesheet: (stylesheetPath, options) ->
|
||||
if path.extname(stylesheetPath) is '.less'
|
||||
@loadLessStylesheet(stylesheetPath, importFallbackVariables)
|
||||
@loadLessStylesheet(stylesheetPath, options)
|
||||
else
|
||||
fs.readFileSync(stylesheetPath, 'utf8')
|
||||
|
||||
loadLessStylesheet: (lessStylesheetPath, importFallbackVariables=false) ->
|
||||
unless @lessCache?
|
||||
LessCompileCache = require './less-compile-cache'
|
||||
@lessCache = new LessCompileCache({@resourcePath, importPaths: @getImportPaths()})
|
||||
loadLessStylesheet: (lessStylesheetPath, {variables, importFallbackVariables}={}) ->
|
||||
@createLessCache()
|
||||
|
||||
try
|
||||
if importFallbackVariables
|
||||
@@ -335,26 +333,7 @@ class ThemeManager
|
||||
|
||||
# atom.config.observe runs the callback once, then on subsequent changes.
|
||||
atom.config.observe 'core.themes', =>
|
||||
@deactivateThemes()
|
||||
|
||||
@refreshLessCache() # Update cache for packages in core.themes config
|
||||
|
||||
promises = []
|
||||
for themeName in @getEnabledThemeNames()
|
||||
if @packageManager.resolvePackagePath(themeName)
|
||||
promises.push(@packageManager.activatePackage(themeName))
|
||||
else
|
||||
console.warn("Failed to activate theme '#{themeName}' because it isn't installed.")
|
||||
|
||||
Q.all(promises).then =>
|
||||
@addActiveThemeClasses()
|
||||
@refreshLessCache() # Update cache again now that @getActiveThemes() is populated
|
||||
@loadUserStylesheet()
|
||||
@reloadBaseStylesheets()
|
||||
@initialLoadComplete = true
|
||||
@emit 'reloaded'
|
||||
@emitter.emit 'did-change-active-themes'
|
||||
deferred.resolve()
|
||||
@reloadStylesheets -> deferred.resolve()
|
||||
|
||||
deferred.promise
|
||||
|
||||
@@ -364,6 +343,44 @@ class ThemeManager
|
||||
@packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes()
|
||||
null
|
||||
|
||||
reloadPackageStylesheets: ->
|
||||
for pack in @packageManager.getActivePackages()
|
||||
pack.reloadStylesheets() if pack.getType() isnt 'theme'
|
||||
|
||||
reloadStylesheets: (callback) ->
|
||||
@deactivateThemes()
|
||||
|
||||
@refreshLessCache() # Update cache for packages in core.themes config
|
||||
@lessCache?.clearFooters()
|
||||
|
||||
loadedThemes = []
|
||||
for themeName in @getEnabledThemeNames()
|
||||
unless @packageManager.resolvePackagePath(themeName)
|
||||
console.warn("Failed to activate theme '#{themeName}' because it isn't installed.")
|
||||
continue
|
||||
|
||||
if theme = @packageManager.loadPackage(themeName)
|
||||
@setFooterForTheme(theme)
|
||||
loadedThemes.push(theme)
|
||||
|
||||
promises = []
|
||||
for theme in loadedThemes
|
||||
promises.push(@packageManager.activatePackage(theme.name))
|
||||
|
||||
Q.all(promises).then =>
|
||||
@addActiveThemeClasses()
|
||||
@refreshLessCache() # Update cache again now that @getActiveThemes() is populated
|
||||
@loadUserStylesheet()
|
||||
@reloadBaseStylesheets()
|
||||
if @packageManager.initialPackageActivationComplete
|
||||
@reloadPackageStylesheets()
|
||||
else
|
||||
@packageManager.onDidActivateInitialPackages => @reloadPackageStylesheets()
|
||||
@initialLoadComplete = true
|
||||
@emit 'reloaded'
|
||||
@emitter.emit 'did-change-active-themes'
|
||||
callback?()
|
||||
|
||||
isInitialLoadComplete: -> @initialLoadComplete
|
||||
|
||||
addActiveThemeClasses: ->
|
||||
@@ -378,9 +395,32 @@ class ThemeManager
|
||||
workspaceElement.classList.remove("theme-#{pack.name}")
|
||||
return
|
||||
|
||||
createLessCache: ->
|
||||
unless @lessCache?
|
||||
LessCompileCache = require './less-compile-cache'
|
||||
@lessCache = new LessCompileCache({@resourcePath, importPaths: @getImportPaths()})
|
||||
@lessCache
|
||||
|
||||
refreshLessCache: ->
|
||||
@lessCache?.setImportPaths(@getImportPaths())
|
||||
|
||||
setFooterForTheme: (theme) ->
|
||||
footer = theme.getStylesheetFooter()
|
||||
return unless footer
|
||||
|
||||
stylesheetPaths = []
|
||||
try
|
||||
stylesheetPaths = theme.getStylesheetPaths()
|
||||
|
||||
try
|
||||
stylesPath = path.join(theme.path, 'styles')
|
||||
stylesheetPaths = stylesheetPaths.concat(fs.listSync(stylesPath, ['less']))
|
||||
|
||||
for stylesheetPath in stylesheetPaths
|
||||
@createLessCache().setFooter(stylesheetPath, footer)
|
||||
|
||||
return
|
||||
|
||||
getImportPaths: ->
|
||||
activeThemes = @getActiveThemes()
|
||||
if activeThemes.length > 0
|
||||
|
||||
@@ -21,12 +21,21 @@ class ThemePackage extends Package
|
||||
console.warn "Failed to load theme named '#{@name}'", error.stack ? error
|
||||
this
|
||||
|
||||
watchThemeConfig: ->
|
||||
@configDisposable = atom.config.onDidChange @name, =>
|
||||
atom.themes.reloadStylesheets()
|
||||
|
||||
activate: ->
|
||||
return @activationDeferred.promise if @activationDeferred?
|
||||
|
||||
@activationDeferred = Q.defer()
|
||||
@measure 'activateTime', =>
|
||||
@loadStylesheets()
|
||||
@activateNow()
|
||||
@reloadStylesheets()
|
||||
@watchThemeConfig()
|
||||
|
||||
@activationDeferred.promise
|
||||
|
||||
deactivate: ->
|
||||
@configDisposable?.dispose()
|
||||
super
|
||||
|
||||
@@ -456,6 +456,8 @@ class Workspace extends Model
|
||||
atom.notifications.addWarning("#{error.message} Large file support is being tracked at [atom/atom#307](https://github.com/atom/atom/issues/307).")
|
||||
when 'EACCES'
|
||||
atom.notifications.addWarning("Permission denied '#{error.path}'")
|
||||
when 'EPERM', 'EBUSY'
|
||||
atom.notifications.addWarning("Unable to open '#{error.path}'", detail: error.message)
|
||||
else
|
||||
throw error
|
||||
return Q()
|
||||
@@ -498,7 +500,7 @@ class Workspace extends Model
|
||||
# ## Examples
|
||||
#
|
||||
# ```coffee
|
||||
# atom.project.addOpener (uri) ->
|
||||
# atom.workspace.addOpener (uri) ->
|
||||
# if path.extname(uri) is '.toml'
|
||||
# return new TomlEditor(uri)
|
||||
# ```
|
||||
@@ -625,6 +627,12 @@ class Workspace extends Model
|
||||
atom.notifications.addWarning("Unable to save file: #{error.message}")
|
||||
else if error.code is 'EACCES' and error.path?
|
||||
atom.notifications.addWarning("Unable to save file: Permission denied '#{error.path}'")
|
||||
else if error.code is 'EPERM' and error.path?
|
||||
atom.notifications.addWarning("Unable to save file '#{error.path}'", detail: error.message)
|
||||
else if error.code is 'EBUSY' and error.path?
|
||||
atom.notifications.addWarning("Unable to save file '#{error.path}'", detail: error.message)
|
||||
else if error.code is 'EROFS' and error.path?
|
||||
atom.notifications.addWarning("Unable to save file: Read-only file system '#{error.path}'")
|
||||
else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message)
|
||||
fileName = errorMatch[1]
|
||||
atom.notifications.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to")
|
||||
|
||||
@@ -5,23 +5,6 @@ window.onload = function() {
|
||||
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 rawLoadSettings = decodeURIComponent(location.search.substr(14));
|
||||
var loadSettings;
|
||||
|
||||
@@ -12,6 +12,7 @@ atom-text-editor[mini] {
|
||||
font-size: @input-font-size;
|
||||
line-height: @component-line-height;
|
||||
max-height: @component-line-height + 2; // +2 for borders
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
atom-overlay {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário