Comparar commits
334 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 6430bbb460 | |||
| 362ff963fd | |||
| 61ca2e14dc | |||
| 56677e71e4 | |||
| c927101bb2 | |||
| 28f280183e | |||
| f1df254a66 | |||
| af28083a6f | |||
| 495caa7316 | |||
| d0757c87c8 | |||
| c19d99e9e2 | |||
| ab43b08739 | |||
| 01bf346d0f | |||
| c3bd501b84 | |||
| 556bb5b65e | |||
| de1c6d1a5d | |||
| a985942b16 | |||
| 9ba106192d | |||
| 83568a1d85 | |||
| 71333bbc93 | |||
| 4e10ea0b10 | |||
| 888d6dfab5 | |||
| 622b396111 | |||
| 0f2943989f | |||
| 63e618cf74 | |||
| 76f37277d9 | |||
| 745e9c8284 | |||
| 456e511031 | |||
| 390be558e2 | |||
| 4acd5951f5 | |||
| 8cd7d7dc0c | |||
| a127240f4f | |||
| c0ab2c4ac8 | |||
| 4c534606c2 | |||
| f330e207b4 | |||
| d05a3f370e | |||
| 08edcf23c9 | |||
| dc4640eee0 | |||
| 33073ea270 | |||
| 449acc7ced | |||
| dde253160c | |||
| c547039f1d | |||
| afb795d8cc | |||
| ef8a493b9a | |||
| c738145dc7 | |||
| 86991bbec2 | |||
| 973d7ebf13 | |||
| 93c67b670a | |||
| c7315e2be6 | |||
| a4976c32ae | |||
| 37a85bcdd0 | |||
| 47bd093d68 | |||
| a788a7e9b7 | |||
| 9101da11ce | |||
| f7159181ac | |||
| 1784a7f726 | |||
| a28a8447a7 | |||
| 197e74f18d | |||
| 5cae6f20c4 | |||
| 6ad704c1e4 | |||
| 2b0cb11df3 | |||
| 9aee7d4b38 | |||
| b6c86ea217 | |||
| 0d169f0516 | |||
| 740e6de5f3 | |||
| 5dea6e7d12 | |||
| 312e4e0e8a | |||
| 853ad9cee3 | |||
| a5ccfa6299 | |||
| 800ca5a37a | |||
| 23b8b15261 | |||
| 959aa08d62 | |||
| 6eed4e461f | |||
| 00b79e69f1 | |||
| 3739995ddb | |||
| f942bafe54 | |||
| 5fa230e71a | |||
| 9858916c31 | |||
| 18ed76f111 | |||
| feb35e710c | |||
| 2e989b502a | |||
| 434c9e60a8 | |||
| 84453d5441 | |||
| 9e11914b8b | |||
| f9f7cf6d34 | |||
| c7b206f5ca | |||
| 3b8b569d0c | |||
| 8365ccb064 | |||
| fee8e4a75a | |||
| edd8714bbf | |||
| 56adf8cc32 | |||
| d3956da8e5 | |||
| b24b338b2c | |||
| 14969c0522 | |||
| 65f2ffa55e | |||
| 5638c7fb6a | |||
| cb8b254502 | |||
| 027ebc78c4 | |||
| d9fb54ad6f | |||
| 2e72790e72 | |||
| 8fcd71f207 | |||
| 776eedd473 | |||
| 62c515e4e7 | |||
| 223334181b | |||
| a7e18b05d3 | |||
| b92e6f5a2d | |||
| 2170e917bd | |||
| 7add4af585 | |||
| 5076e2c8b3 | |||
| b56d73cd74 | |||
| 6c5a0e3670 | |||
| 791f89216b | |||
| f6067cb629 | |||
| 22158031bf | |||
| 8ac3fada4e | |||
| a03d5bc288 | |||
| cc489e5663 | |||
| cd3f7f73a0 | |||
| 9cb67a6def | |||
| 786e8c558a | |||
| bfeeddea4d | |||
| 1589b8b192 | |||
| b02d0e3df3 | |||
| d3f29c4580 | |||
| 7263ca8faa | |||
| cd812e7a65 | |||
| 4e6e636b8b | |||
| 083bafdb33 | |||
| adbe151c5d | |||
| 26b450fe49 | |||
| 5d273d0ee6 | |||
| b9b2b4bca2 | |||
| 79094ee889 | |||
| 52f2c0ec69 | |||
| d2f485a1ab | |||
| c12002a0ba | |||
| fed2bd6ab8 | |||
| d29b5b20cd | |||
| a0bb9d88e0 | |||
| 32b3c4076f | |||
| acd1d31480 | |||
| 242fce3d79 | |||
| e0bac77fa5 | |||
| c4c13375e4 | |||
| 83f0104c46 | |||
| a0a3c93b1d | |||
| 98a874808e | |||
| e7b790c5b9 | |||
| 4988293400 | |||
| 0d51c3b871 | |||
| 8316183fa0 | |||
| 8e617ff4e2 | |||
| 3ca5495690 | |||
| 5c47ae0cbc | |||
| 6a86a00c66 | |||
| 1abe64e73e | |||
| bb9150340d | |||
| c3f5c43694 | |||
| 1678016ae4 | |||
| f50e402de3 | |||
| e6363150dd | |||
| 5f024bfd69 | |||
| 76adb58fea | |||
| 53d5e61b23 | |||
| 499c09fc25 | |||
| 7891595fed | |||
| 604f2a951f | |||
| c1b6b716b1 | |||
| 4d861a68d1 | |||
| a831688ce1 | |||
| 1cbac24cee | |||
| afa5f73094 | |||
| a142e23f49 | |||
| f1b7536d06 | |||
| 397e61a0d8 | |||
| af22e45f70 | |||
| e6a12530a1 | |||
| 896c98b7a0 | |||
| 3201a05672 | |||
| 93181d8a54 | |||
| 661f1f822a | |||
| 678306317d | |||
| 8dd5f17609 | |||
| 13e069b45d | |||
| e61cc5eb13 | |||
| 9e92952ad0 | |||
| a8d778781c | |||
| da17679ec7 | |||
| 1cf663714e | |||
| 05963c4e57 | |||
| 965a18f7e2 | |||
| 58c45f87e6 | |||
| 21e609ffac | |||
| 93befc986f | |||
| 3321d77264 | |||
| 84761563f0 | |||
| 014cf19723 | |||
| 2a42ed4aaa | |||
| 34b1615782 | |||
| 87db2760b8 | |||
| b4dd0f4f73 | |||
| 9d655fd642 | |||
| 4700edf439 | |||
| 87c2f4496f | |||
| 2741445d95 | |||
| ed90c5e6c2 | |||
| 0bf2a3f480 | |||
| a743e8d058 | |||
| ddc607c760 | |||
| cbc8ad1467 | |||
| 1a1eb4380a | |||
| 535b49f60c | |||
| b5e60f7aa0 | |||
| 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 | |||
| 3b13e4f502 | |||
| 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 | |||
| c538857cfa | |||
| 6716e544f0 | |||
| 2f3a9c9e35 | |||
| 3d1baaf3f3 | |||
| b819f681aa | |||
| e30b2f1c73 |
@@ -36,7 +36,7 @@ many packages and themes that are stored in other repos under the
|
||||
[tabs](https://github.com/atom/tabs),
|
||||
[find-and-replace](https://github.com/atom/find-and-replace),
|
||||
[language-javascript](https://github.com/atom/language-javascript), and
|
||||
[atom-light-ui](http://github.com/atom/atom-light-ui).
|
||||
[atom-light-ui](https://github.com/atom/atom-light-ui).
|
||||
|
||||
For more information on how to work with Atom's official packages, see
|
||||
[Contributing to Atom Packages](https://atom.io/docs/latest/contributing-to-packages.html)
|
||||
@@ -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,6 +1,6 @@
|
||||

|
||||
|
||||
Atom is a hackable text editor for the 21st century, built on [atom-shell](http://github.com/atom/atom-shell), and based on everything we love about our favorite editors. We designed it to be deeply customizable, but still approachable using the default configuration.
|
||||
Atom is a hackable text editor for the 21st century, built on [atom-shell](https://github.com/atom/atom-shell), and based on everything we love about our favorite editors. We designed it to be deeply customizable, but still approachable using the default configuration.
|
||||
|
||||
Visit [atom.io](https://atom.io) to learn more or visit the [Atom forum](https://discuss.atom.io).
|
||||
|
||||
@@ -9,7 +9,7 @@ about the Atom 1.0 roadmap.
|
||||
|
||||
## Installing
|
||||
|
||||
### Mac OS X
|
||||
### OS X
|
||||
|
||||
Download the latest [Atom release](https://github.com/atom/atom/releases/latest).
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.120.0"
|
||||
"atom-package-manager": "0.135.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,18 +45,24 @@ if [ $REDIRECT_STDERR ]; then
|
||||
fi
|
||||
|
||||
if [ $OS == 'Mac' ]; then
|
||||
ATOM_PATH="${ATOM_PATH:-/Applications}" # Set ATOM_PATH unless it is already set
|
||||
ATOM_APP_NAME=Atom.app
|
||||
|
||||
# If ATOM_PATH isn't a executable file, use spotlight to search for Atom
|
||||
if [ ! -x "$ATOM_PATH/$ATOM_APP_NAME" ]; then
|
||||
ATOM_PATH="$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | grep -v ShipIt | head -1 | xargs -0 dirname)"
|
||||
fi
|
||||
if [ -z "${ATOM_PATH}" ]; then
|
||||
# If ATOM_PATH isnt set, check /Applications and then ~/Applications for Atom.app
|
||||
if [ -x "/Applications/$ATOM_APP_NAME" ]; then
|
||||
ATOM_PATH="/Applications"
|
||||
elif [ -x "$HOME/Applications/$ATOM_APP_NAME" ]; then
|
||||
ATOM_PATH="$HOME/Applications"
|
||||
else
|
||||
# We havent found an Atom.app, use spotlight to search for Atom
|
||||
ATOM_PATH="$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | grep -v ShipIt | head -1 | xargs -0 dirname)"
|
||||
|
||||
# Exit if Atom can't be found
|
||||
if [ -z "$ATOM_PATH" ]; then
|
||||
echo "Cannot locate Atom.app, it is usually located in /Applications. Set the ATOM_PATH environment variable to the directory containing Atom.app."
|
||||
exit 1
|
||||
# Exit if Atom can't be found
|
||||
if [ ! -x "$ATOM_PATH/$ATOM_APP_NAME" ]; then
|
||||
echo "Cannot locate Atom.app, it is usually located in /Applications. Set the ATOM_PATH environment variable to the directory containing Atom.app."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
@@ -69,9 +75,9 @@ elif [ $OS == 'Linux' ]; then
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
USR_DIRECTORY=$(readlink -f $(dirname $SCRIPT)/..)
|
||||
ATOM_PATH="$USR_DIRECTORY/share/atom/atom"
|
||||
DOT_ATOM_DIR="$HOME/.atom"
|
||||
ATOM_HOME="${ATOM_HOME:-$HOME/.atom}"
|
||||
|
||||
mkdir -p "$DOT_ATOM_DIR"
|
||||
mkdir -p "$ATOM_HOME"
|
||||
|
||||
: ${TMPDIR:=/tmp}
|
||||
|
||||
@@ -82,9 +88,9 @@ elif [ $OS == 'Linux' ]; then
|
||||
exit $?
|
||||
else
|
||||
(
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$DOT_ATOM_DIR/nohup.out" 2>&1
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$ATOM_HOME/nohup.out" 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
cat "$DOT_ATOM_DIR/nohup.out"
|
||||
cat "$ATOM_HOME/nohup.out"
|
||||
exit $?
|
||||
fi
|
||||
) &
|
||||
|
||||
@@ -207,6 +207,7 @@ module.exports = (grunt) ->
|
||||
loadingGif: path.resolve(__dirname, '..', 'resources', 'win', 'loading.gif')
|
||||
iconUrl: 'https://raw.githubusercontent.com/atom/atom/master/resources/win/atom.ico'
|
||||
setupIcon: path.resolve(__dirname, '..', 'resources', 'win', 'atom.ico')
|
||||
remoteReleases: 'https://atom.io/api/updates'
|
||||
|
||||
shell:
|
||||
'kill-atom':
|
||||
@@ -221,7 +222,7 @@ module.exports = (grunt) ->
|
||||
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
|
||||
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
|
||||
|
||||
ciTasks = ['output-disk-space', 'download-atom-shell', 'build']
|
||||
ciTasks = ['output-disk-space', 'download-atom-shell', 'download-atom-shell-chromedriver', 'build']
|
||||
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
|
||||
ciTasks.push('set-version', 'check-licenses', 'lint')
|
||||
ciTasks.push('mkdeb') if process.platform is 'linux'
|
||||
@@ -231,6 +232,6 @@ module.exports = (grunt) ->
|
||||
ciTasks.push('publish-build')
|
||||
grunt.registerTask('ci', ciTasks)
|
||||
|
||||
defaultTasks = ['download-atom-shell', 'build', 'set-version']
|
||||
defaultTasks = ['download-atom-shell', 'download-atom-shell-chromedriver', 'build', 'set-version']
|
||||
defaultTasks.push 'install' unless process.platform is 'linux'
|
||||
grunt.registerTask('default', defaultTasks)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# VERSION: 0.1
|
||||
# DESCRIPTION: Create the atom editor in a container
|
||||
# DESCRIPTION: Create the atom editor in a container
|
||||
# AUTHOR: Jessica Frazelle <jessie@docker.com>
|
||||
# COMMENTS:
|
||||
# This file describes how to build the atom editor
|
||||
# This file describes how to build the atom editor
|
||||
# in a container with all dependencies installed.
|
||||
# Tested on Debian Jessie.
|
||||
# USAGE:
|
||||
# # Download atom Dockerfile
|
||||
# wget http://raw.githubusercontent.com/atom/atom/master/Dockerfile
|
||||
# wget https://raw.githubusercontent.com/atom/atom/master/Dockerfile
|
||||
#
|
||||
# # Build atom image
|
||||
# docker build -t atom .
|
||||
|
||||
@@ -12,25 +12,26 @@
|
||||
"fs-plus": "2.x",
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-atom-shell-installer": "^0.20.0",
|
||||
"grunt-atom-shell-installer": "^0.21.0",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git#cfb99aa99811d52687969532bd5a98011ed95bfe",
|
||||
"grunt-contrib-coffee": "~0.12.0",
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"grunt-cson": "0.14.0",
|
||||
"grunt-download-atom-shell": "~0.11.0",
|
||||
"grunt-download-atom-shell": "~0.12.0",
|
||||
"grunt-lesslint": "0.13.0",
|
||||
"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",
|
||||
"request": "~2.27.0",
|
||||
"rimraf": "~2.2.2",
|
||||
"runas": "~1.0.1",
|
||||
"selenium-webdriver": "^2.44.0",
|
||||
"tello": "1.0.4",
|
||||
"temp": "~0.8.1",
|
||||
"underscore-plus": "1.x",
|
||||
|
||||
@@ -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'
|
||||
@@ -75,3 +79,6 @@ module.exports =
|
||||
|
||||
LGPL
|
||||
"""
|
||||
'core-js@0.4.10':
|
||||
license: 'MIT'
|
||||
source: 'http://rock.mit-license.org linked in source files and bower.json says MIT'
|
||||
|
||||
@@ -36,8 +36,9 @@ module.exports = (grunt) ->
|
||||
maintainer = 'GitHub <atom@github.com>'
|
||||
installDir = '/usr'
|
||||
iconName = 'atom'
|
||||
executable = path.join(installDir, 'share', 'atom', 'atom')
|
||||
getInstalledSize buildDir, (error, installedSize) ->
|
||||
data = {name, version, description, section, arch, maintainer, installDir, iconName, installedSize}
|
||||
data = {name, version, description, section, arch, maintainer, installDir, iconName, installedSize, executable}
|
||||
controlFilePath = fillTemplate(path.join('resources', 'linux', 'debian', 'control'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'atom.desktop'), data)
|
||||
icon = path.join('resources', 'atom.png')
|
||||
|
||||
@@ -33,8 +33,9 @@ module.exports = (grunt) ->
|
||||
installDir = grunt.config.get('atom.installDir')
|
||||
shareDir = path.join(installDir, 'share', 'atom')
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'atom.png')
|
||||
executable = 'atom'
|
||||
|
||||
data = {name, version, description, installDir, iconName}
|
||||
data = {name, version, description, installDir, iconName, executable}
|
||||
specFilePath = fillTemplate(path.join('resources', 'linux', 'redhat', 'atom.spec'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'atom.desktop'), data)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ module.exports = (grunt) ->
|
||||
fullPath = path.join(relativePath, fileName)
|
||||
else
|
||||
fullPath = fileName
|
||||
longPaths.push(fullPath) if fullPath.length >= 200
|
||||
longPaths.push(fullPath) if fullPath.length >= 175
|
||||
|
||||
longPaths.sort (longPath1, longPath2) -> longPath2.length - longPath1.length
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -68,7 +68,7 @@ getAssets = ->
|
||||
]
|
||||
when 'win32'
|
||||
assets = [{assetName: 'atom-windows.zip', sourcePath: 'Atom'}]
|
||||
for squirrelAsset in ['AtomSetup.exe', 'RELEASES', "atom-#{version}-full.nupkg"]
|
||||
for squirrelAsset in ['AtomSetup.exe', 'RELEASES', "atom-#{version}-full.nupkg", "atom-#{version}-delta.nupkg"]
|
||||
cp path.join(buildDir, 'installer', squirrelAsset), path.join(buildDir, squirrelAsset)
|
||||
assets.push({assetName: squirrelAsset, sourcePath: assetName})
|
||||
assets
|
||||
|
||||
@@ -85,15 +85,27 @@ module.exports = (grunt) ->
|
||||
appPath = getAppPath()
|
||||
resourcePath = process.cwd()
|
||||
coreSpecsPath = path.resolve('spec')
|
||||
chromedriverPath = path.join(resourcePath, "atom-shell", "chromedriver")
|
||||
|
||||
if process.platform in ['darwin', 'linux']
|
||||
options =
|
||||
cmd: appPath
|
||||
args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}"]
|
||||
opts:
|
||||
env: _.extend({}, process.env,
|
||||
ATOM_INTEGRATION_TESTS_ENABLED: true
|
||||
PATH: [process.env.path, chromedriverPath].join(":")
|
||||
)
|
||||
|
||||
else if process.platform is 'win32'
|
||||
options =
|
||||
cmd: process.env.comspec
|
||||
args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}", "--log-file=ci.log"]
|
||||
opts:
|
||||
env: _.extend({}, process.env,
|
||||
ATOM_INTEGRATION_TESTS_ENABLED: true
|
||||
PATH: [process.env.path, chromedriverPath].join(";")
|
||||
)
|
||||
|
||||
spawn options, (error, results, code) ->
|
||||
if process.platform is 'win32'
|
||||
|
||||
@@ -49,19 +49,17 @@ can be expressed as keystroke patterns separated by spaces.
|
||||
Commands are custom DOM events that are triggered when a keystroke matches a
|
||||
binding. This allows user interface code to listen for named commands without
|
||||
specifying the specific keybinding that triggers it. For example, the following
|
||||
code sets up {EditorView} to listen for commands to move the cursor to the first
|
||||
character of the current line:
|
||||
code creates a command to insert the current date in an editor:
|
||||
|
||||
```coffee
|
||||
class EditorView
|
||||
listenForEvents: ->
|
||||
@command 'editor:move-to-first-character-of-line', =>
|
||||
@editor.moveToFirstCharacterOfLine()
|
||||
atom.commands.add 'atom-text-editor',
|
||||
'user:insert-date': (event) ->
|
||||
editor = @getModel()
|
||||
editor.insertText(new Date().toLocaleString())
|
||||
```
|
||||
|
||||
The `::command` method is basically an enhanced version of jQuery's `::on`
|
||||
method that listens for a custom DOM event and adds some metadata to the DOM,
|
||||
which is read by the command palette.
|
||||
`atom.commands` refers to the global {CommandRegistry} instance where all commands
|
||||
are set and consequently picked up by the command palette.
|
||||
|
||||
When you are looking to bind new keys, it is often useful to use the command
|
||||
palette (`ctrl-shift-p`) to discover what commands are being listened for in a
|
||||
@@ -69,6 +67,30 @@ given focus context. Commands are "humanized" following a simple algorithm, so a
|
||||
command like `editor:fold-current-row` would appear as "Editor: Fold Current
|
||||
Row".
|
||||
|
||||
### "Composed" Commands
|
||||
|
||||
A common question is, "How do I make a single keybinding execute two or more
|
||||
commands?" There isn't any direct support for this in Atom, but it can be
|
||||
achieved by creating a custom command that performs the multiple actions
|
||||
you desire and then creating a keybinding for that command. For example, let's
|
||||
say I want to create a "composed" command that performs a Select Line followed
|
||||
by Cut. You could add the following to your `init.coffee`:
|
||||
|
||||
```coffee
|
||||
atom.commands.add 'atom-text-editor', 'custom:cut-line', ->
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
editor.selectLinesContainingCursors()
|
||||
editor.cutSelectedText()
|
||||
```
|
||||
|
||||
Then let's say we want to map this custom command to `alt-ctrl-z`, you could
|
||||
add the following to your keymap:
|
||||
|
||||
```coffee
|
||||
'atom-text-editor':
|
||||
'alt-ctrl-z': 'custom:cut-line'
|
||||
```
|
||||
|
||||
### Specificity and Cascade Order
|
||||
|
||||
As is the case with CSS applying styles, when multiple bindings match for a
|
||||
|
||||
@@ -8,7 +8,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
|
||||
* C++ toolchain
|
||||
* [Git](http://git-scm.com/)
|
||||
* [Node.js](http://nodejs.org/download/) v0.10.x
|
||||
* [npm](http://www.npmjs.org/) v1.4.x (bundled with Node.js)
|
||||
* [npm](https://www.npmjs.com/) v1.4.x (bundled with Node.js)
|
||||
* `npm -v` to check the version.
|
||||
* `npm config set python /usr/bin/python2 -g` to ensure that gyp uses python2.
|
||||
* You might need to run this command as `sudo`, depending on how you have set up [npm](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* For 64-bit builds of node and native modules you **must** have the
|
||||
[Windows 7 64-bit SDK](http://www.microsoft.com/en-us/download/details.aspx?id=8279).
|
||||
You may also need the [compiler update for the Windows SDK 7.1](http://www.microsoft.com/en-us/download/details.aspx?id=4422)
|
||||
* [Python](http://www.python.org/download/) v2.7.
|
||||
* [Python](https://www.python.org/downloads/) v2.7.
|
||||
* The python.exe must be available at `%SystemDrive%\Python27\python.exe`.
|
||||
If it is installed elsewhere, you can create a symbolic link to the
|
||||
directory containing the python.exe using:
|
||||
@@ -19,7 +19,7 @@
|
||||
### On Windows 8
|
||||
* [Visual Studio Express 2013 for Windows Desktop](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_2)
|
||||
* [node.js](http://nodejs.org/download/) v0.10.x
|
||||
* [Python](http://www.python.org/download/) v2.7.x (required by [node-gyp](https://github.com/TooTallNate/node-gyp))
|
||||
* [Python](https://www.python.org/downloads/) v2.7.x (required by [node-gyp](https://github.com/TooTallNate/node-gyp))
|
||||
* [GitHub for Windows](http://windows.github.com/)
|
||||
|
||||
## Instructions
|
||||
|
||||
@@ -44,9 +44,9 @@ the editor to see it in action!
|
||||
on publishing the package you just created to [atom.io][atomio].
|
||||
|
||||
[atomio]: https://atom.io
|
||||
[CSS]: http://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[LESS]: http://lesscss.org
|
||||
[plist]: http://en.wikipedia.org/wiki/Property_list
|
||||
[R]: http://en.wikipedia.org/wiki/R_(programming_language)
|
||||
[CSS]: https://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[Less]: http://lesscss.org
|
||||
[plist]: https://en.wikipedia.org/wiki/Property_list
|
||||
[R]: https://en.wikipedia.org/wiki/R_(programming_language)
|
||||
[TextMate]: http://macromates.com
|
||||
[TextMateOrg]: https://github.com/textmate
|
||||
|
||||
@@ -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.
|
||||
@@ -61,8 +61,8 @@ __Syntax Theme__ dropdown menu to enable your new theme.
|
||||
on publishing the theme you just created to [atom.io][atomio].
|
||||
|
||||
[atomio]: https://atom.io
|
||||
[CSS]: http://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[LESS]: http://lesscss.org
|
||||
[plist]: http://en.wikipedia.org/wiki/Property_list
|
||||
[CSS]: https://en.wikipedia.org/wiki/Cascading_Style_Sheets
|
||||
[Less]: http://lesscss.org
|
||||
[plist]: https://en.wikipedia.org/wiki/Property_list
|
||||
[TextMate]: http://macromates.com
|
||||
[TextMateThemes]: http://wiki.macromates.com/Themes/UserSubmittedThemes
|
||||
|
||||
@@ -51,9 +51,24 @@ in the _menus_ directory are added alphabetically.
|
||||
- `snippets` (**Optional**): an Array of Strings identifying the order of the
|
||||
snippets your package needs to load. If not specified, snippets in the
|
||||
_snippets_ directory are added alphabetically.
|
||||
- `activationEvents` (**Optional**): an Array of Strings identifying events that
|
||||
- `activationCommands` (**Optional**): an Array of Strings identifying commands that
|
||||
trigger your package's activation. You can delay the loading of your package
|
||||
until one of these events is triggered.
|
||||
- `providedServices` (**Optional**): an Object describing the services that your
|
||||
package provides, which can be used by other packages. The keys of this object
|
||||
are the names of the services, and the values are Objects with the following
|
||||
keys:
|
||||
- `description` (**Optional**) a String describing the service
|
||||
- `versions` (**Required**) an Object whose keys are Semver version strings,
|
||||
and whose values are names of methods in your package's top-level module
|
||||
that return a value implementing the service.
|
||||
- `consumedServices` (**Optional**): an Object describing the services that your
|
||||
package uses, which can be provided by other packages. The keys of this object
|
||||
are the names of the services, and the values are Objects with the following
|
||||
keys:
|
||||
- `versions` (**Required**) an Object whose keys are Semver version ranges
|
||||
and whose values are names of methods in your package's top-level module
|
||||
that are called with values implementing the service.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -83,9 +98,9 @@ module's `activate` method so you can restore your view to where the user left
|
||||
off.
|
||||
|
||||
- `deactivate()`: This **optional** method is called when the window is shutting
|
||||
down. If your package is watching any files or holding external resources in any
|
||||
other way, release them here. If you're just subscribing to things on window,
|
||||
you don't need to worry because that's getting torn down anyway.
|
||||
down, or when your package is being updated or disabled. If your package is
|
||||
watching any files, holding external resources, providing commands or subscribing
|
||||
to events, release them here.
|
||||
|
||||
### Simple Package Code
|
||||
|
||||
@@ -112,19 +127,18 @@ module.exports =
|
||||
serialize: -> # ...
|
||||
```
|
||||
|
||||
Beyond this simple contract, your package has access to Atom's API. Be aware
|
||||
that since we are early in development, APIs are subject to change and we have
|
||||
not yet established clear boundaries between what is public and what is private.
|
||||
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.
|
||||
Beyond this simple contract, your package has access to [Atom's API][api]. Be aware
|
||||
that the Atom 1.0 API is mostly frozen. Refer to the API documentation for what
|
||||
is public. That said, 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.
|
||||
|
||||
## Style Sheets
|
||||
|
||||
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
|
||||
@@ -352,6 +366,79 @@ to indicate the type your value should be, its default, etc.
|
||||
See the [Config API Docs](https://atom.io/docs/api/latest/Config) for more
|
||||
details specifying your configuration.
|
||||
|
||||
## Interacting With Other Packages Via Services
|
||||
|
||||
Atom packages can interact with each other through versioned APIs called
|
||||
*services*. To provide a service, in your `package.json`, specify one or more
|
||||
version numbers, each paired with the name of a method on your package's main module:
|
||||
|
||||
```json
|
||||
{
|
||||
"providedServices": {
|
||||
"my-service": {
|
||||
"description": "Does a useful thing",
|
||||
"versions": {
|
||||
"1.2.3": "provideMyServiceV1",
|
||||
"2.3.4": "provideMyServiceV2",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In your package's main module, implement the methods named above. These methods
|
||||
will be called any time a package is activated that consumes their corresponding
|
||||
service. They should return a value that implements the service's API.
|
||||
|
||||
|
||||
```coffeescript
|
||||
module.exports =
|
||||
activate: -> # ...
|
||||
|
||||
provideMyServiceV1: ->
|
||||
adaptToLegacyAPI(myService)
|
||||
|
||||
provideMyServiceV2: ->
|
||||
myService
|
||||
```
|
||||
|
||||
Similarly, to consume a service, specify one or more [version *ranges*][version-ranges],
|
||||
each paired with the name of a method on the package's main module:
|
||||
|
||||
```json
|
||||
{
|
||||
"consumedServices": {
|
||||
"another-service": {
|
||||
"versions": {
|
||||
"^1.2.3": "consumeAnotherServiceV1",
|
||||
">=2.3.4 <2.5": "consumeAnotherServiceV2",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These methods will be called any time a package is activated that *provides* their
|
||||
corresponding service. They will receive the service object as an argument. You
|
||||
will usually need to perform some kind of cleanup in the event that the package
|
||||
providing the service is deactivated. To do this, return a `Disposable` from
|
||||
your service-consuming method:
|
||||
|
||||
```coffeescript
|
||||
{Disposable} = require 'atom'
|
||||
|
||||
module.exports =
|
||||
activate: -> # ...
|
||||
|
||||
consumeAnotherServiceV1: (service) ->
|
||||
useService(adaptServiceFromLegacyAPI(service))
|
||||
new Disposable -> stopUsingService(service)
|
||||
|
||||
consumeAnotherServiceV2: (service) ->
|
||||
useService(service)
|
||||
new Disposable -> stopUsingService(service)
|
||||
```
|
||||
|
||||
## Bundle External Resources
|
||||
|
||||
It's common to ship external resources like images and fonts in the package, to
|
||||
@@ -402,11 +489,12 @@ registry.
|
||||
Run `apm help publish` to see all the available options and `apm help` to see
|
||||
all the other available commands.
|
||||
|
||||
[api]: https://atom.io/docs/api/latest
|
||||
[file-tree]: https://github.com/atom/tree-view
|
||||
[status-bar]: https://github.com/atom/status-bar
|
||||
[cs-syntax]: https://github.com/atom/language-coffee-script
|
||||
[npm]: http://en.wikipedia.org/wiki/Npm_(software)
|
||||
[npm-keys]: https://npmjs.org/doc/json.html
|
||||
[npm]: https://en.wikipedia.org/wiki/Npm_(software)
|
||||
[npm-keys]: https://docs.npmjs.com/files/package.json
|
||||
[git-tag]: http://git-scm.com/book/en/Git-Basics-Tagging
|
||||
[wrap-guide]: https://github.com/atom/wrap-guide/
|
||||
[keymaps]: advanced/keymaps.md
|
||||
@@ -418,9 +506,10 @@ 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
|
||||
[convert-theme]: converting-a-text-mate-theme.html
|
||||
[json-schema]: http://json-schema.org/
|
||||
[version-ranges]: https://docs.npmjs.com/misc/semver#ranges
|
||||
|
||||
@@ -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
|
||||
@@ -9,22 +9,23 @@ elements such as the tree view, the tabs, drop-down lists, and the status bar.
|
||||
Syntax themes style the code inside the editor.
|
||||
|
||||
Themes can be installed and changed from the settings view which you can open
|
||||
by selecting the _Atom > Preferences..._ menu and navigating to the _Themes_
|
||||
section on the left hand side.
|
||||
by selecting the _Atom > Preferences..._ menu and navigating to the _Install_
|
||||
section and the _Themes_ section on the left hand side.
|
||||
|
||||
## Getting Started
|
||||
|
||||
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
|
||||
is used to help distribute your theme to Atom users.
|
||||
* Your theme's _package.json_ must contain a `"theme"` key with a value
|
||||
of `"ui"` or `"syntax"` for Atom to recognize and load it as a theme.
|
||||
* You can find existing themes to install or fork on [atom.io](atomio).
|
||||
* You can find existing themes to install or fork on
|
||||
[atom.io][atomio-themes].
|
||||
|
||||
## Creating a Syntax Theme
|
||||
|
||||
@@ -130,13 +131,13 @@ _styleguide_, or use the shortcut `cmd-ctrl-shift-g`.
|
||||
|
||||
![styleguide-img]
|
||||
|
||||
[atomio]: http://atom.io/packages
|
||||
[LESS]: http://lesscss.org/
|
||||
[atomio-themes]: https://atom.io/themes
|
||||
[Less]: http://lesscss.org/
|
||||
[git]: http://git-scm.com/
|
||||
[atom]: https://atom.io/
|
||||
[package.json]: ./creating-a-package.html#package-json
|
||||
[less-tutorial]: https://speakerdeck.com/danmatthews/less-css
|
||||
[devtools-tutorial]: https://developers.google.com/chrome-developer-tools/docs/elements
|
||||
[devtools-tutorial]: https://developer.chrome.com/devtools/docs/dom-and-styles
|
||||
[ui-variables]: ./theme-variables.html
|
||||
[livereload]: https://github.com/atom/dev-live-reload
|
||||
[styleguide]: https://github.com/atom/styleguide
|
||||
|
||||
@@ -100,6 +100,14 @@ namespaces: `core` and `editor`.
|
||||
|
||||
You can open this file in an editor from the _Atom > Open Your Config_ menu.
|
||||
|
||||
### Custom Configuration Location
|
||||
|
||||
You can override the location that Atom stores configuration files and folders
|
||||
in by setting the `ATOM_HOME` environment variable. The `ATOM_HOME` path will be
|
||||
used instead of `~/.atom` when it is set.
|
||||
|
||||
This option can be useful when you want to make Atom portable across machines.
|
||||
|
||||
### Configuration Key Reference
|
||||
|
||||
- `core`
|
||||
@@ -169,17 +177,17 @@ For example, to change the color of the cursor, you could add the following
|
||||
rule to your _~/.atom/styles.less_ file:
|
||||
|
||||
```less
|
||||
atom-text-editor.is-focused .cursor {
|
||||
atom-text-editor::shadow .cursor {
|
||||
border-color: pink;
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* [Contributing](contributing.md)
|
||||
* [Contributing to Core Packages](contributing-to-packages.md)
|
||||
* [Debugging](debugging.md)
|
||||
* [Your First Package](your-first-package.md)
|
||||
|
||||
### Advanced Topics
|
||||
|
||||
@@ -19,6 +20,8 @@
|
||||
* [Keymaps](advanced/keymaps.md)
|
||||
* [Serialization](advanced/serialization.md)
|
||||
* [Scopes and Scope Descriptors](advanced/scopes-and-scope-descriptors.md)
|
||||
* [Theme Variables](theme-variables.md)
|
||||
* [apm REST API](apm-rest-api.md)
|
||||
|
||||
### Upgrading to 1.0 APIs
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ If not, there are a few things you should check before publishing:
|
||||
|
||||
Before you publish a package it is a good idea to check ahead of time if
|
||||
a package with the same name has already been published to atom.io. You can do
|
||||
that by visiting `http://atom.io/packages/my-package` to see if the package
|
||||
that by visiting `https://atom.io/packages/my-package` to see if the package
|
||||
already exists. If it does, update your package's name to something that is
|
||||
available before proceeding.
|
||||
|
||||
@@ -73,7 +73,7 @@ and you only need to enter this information the first time you publish. The
|
||||
credentials are stored securely in your [keychain][keychain] once you login.
|
||||
|
||||
:tada: Your package is now published and available on atom.io. Head on over to
|
||||
`http://atom.io/packages/my-package` to see your package's page.
|
||||
`https://atom.io/packages/my-package` to see your package's page.
|
||||
|
||||
With `apm publish`, you can bump the version and publish by using
|
||||
```sh
|
||||
@@ -107,7 +107,7 @@ Use `patch` when you make a small change like a bug fix that does not add or rem
|
||||
[atomio]: https://atom.io
|
||||
[github]: https://github.com
|
||||
[git-tag]: http://git-scm.com/book/en/Git-Basics-Tagging
|
||||
[keychain]: http://en.wikipedia.org/wiki/Keychain_(Apple)
|
||||
[keychain]: https://en.wikipedia.org/wiki/Keychain_(Apple)
|
||||
[repo-guide]: http://guides.github.com/overviews/desktop
|
||||
[semver]: http://semver.org
|
||||
[your-first-package]: your-first-package.html
|
||||
|
||||
@@ -24,7 +24,7 @@ Here's an example `.less` file that a package can define using theme variables:
|
||||
```css
|
||||
@import "ui-variables";
|
||||
|
||||
.my-selector{
|
||||
.my-selector {
|
||||
background-color: @base-background-color;
|
||||
padding: @component-padding;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ When you are deprecation free and all done converting, upgrade the `engines` fie
|
||||
```json
|
||||
{
|
||||
"engines": {
|
||||
"atom": ">=0.x.0, <2.0.0"
|
||||
"atom": ">=0.174.0, <2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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... */
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Writing specs
|
||||
|
||||
Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec framework. Any new functionality should have specs to guard against regressions.
|
||||
Atom uses [Jasmine](http://jasmine.github.io/1.3/introduction.html) as its spec framework. Any new functionality should have specs to guard against regressions.
|
||||
|
||||
## Create a new spec
|
||||
|
||||
@@ -12,7 +12,7 @@ Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec
|
||||
|
||||
0. Add one or more `describe` methods
|
||||
|
||||
The `describe` method takes two arguments, a description and a function. If the description explains a behavior it typically begins with `when` if it is more like a unit test it begins with the method name.
|
||||
The `describe` method takes two arguments, a description and a function. If the description explains a behavior it typically begins with `when`; if it is more like a unit test it begins with the method name.
|
||||
|
||||
```coffee
|
||||
describe "when a test is written", ->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Create Your First Package
|
||||
|
||||
This tutorial will guide you though creating a simple command that replaces the
|
||||
selected text with [ascii art](http://en.wikipedia.org/wiki/ASCII_art). When you
|
||||
selected text with [ascii art](https://en.wikipedia.org/wiki/ASCII_art). When you
|
||||
run our new command with the word "cool" selected, it will be replaced with:
|
||||
|
||||
```
|
||||
@@ -72,12 +72,12 @@ command palette or by pressing `ctrl-alt-cmd-l`.
|
||||
|
||||
Now open the command panel and search for the `ascii-art:convert` command. But
|
||||
it's not there! To fix this, open _package.json_ and find the property called
|
||||
`activationEvents`. Activation Events speed up load time by allowing Atom to
|
||||
`activationCommands`. Activation Events speed up load time by allowing Atom to
|
||||
delay a package's activation until it's needed. So remove the existing command
|
||||
and add `ascii-art:convert` to the `activationEvents` array:
|
||||
and add `ascii-art:convert` to the `activationCommands` array:
|
||||
|
||||
```json
|
||||
"activationEvents": ["ascii-art:convert"],
|
||||
"activationCommands": ["ascii-art:convert"],
|
||||
```
|
||||
|
||||
First, reload the window by running the command `window:reload`. Now when you
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.174.0",
|
||||
"version": "0.178.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,10 +17,11 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.20.5",
|
||||
"atomShellVersion": "0.21.0",
|
||||
"dependencies": {
|
||||
"6to5-core": "^3.0.14",
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.5.2",
|
||||
"atom-keymap": "^3.1.0",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.8.0",
|
||||
@@ -28,42 +29,42 @@
|
||||
"color": "^0.7.3",
|
||||
"delegato": "^1",
|
||||
"emissary": "^1.3.1",
|
||||
"event-kit": "^1.0.1",
|
||||
"first-mate": "^2.2.4",
|
||||
"event-kit": "^1.0.2",
|
||||
"first-mate": "^3.0.0",
|
||||
"fs-plus": "^2.3.2",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"git-utils": "^2.2",
|
||||
"git-utils": "^3.0.0",
|
||||
"grim": "1.1.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"jquery": "^2.1.1",
|
||||
"less-cache": "0.19.0",
|
||||
"less-cache": "0.21",
|
||||
"marked": "^0.3",
|
||||
"mixto": "^1",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.4",
|
||||
"nslog": "^2.0.0",
|
||||
"oniguruma": "^4.0.0",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^2.6.0",
|
||||
"pathwatcher": "^3.1.0",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
"react-atom-fork": "^0.11.4",
|
||||
"react-atom-fork": "^0.11.5",
|
||||
"reactionary-atom-fork": "^1.0.0",
|
||||
"runas": "1.0.1",
|
||||
"scandal": "1.0.3",
|
||||
"runas": "2.0.0",
|
||||
"scandal": "2.0.0",
|
||||
"scoped-property-store": "^0.16.2",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^5.0.5",
|
||||
"scrollbar-style": "^2.0.0",
|
||||
"season": "^5.1.2",
|
||||
"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": "^4.0.0",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.6",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
@@ -75,60 +76,64 @@
|
||||
"atom-light-ui": "0.40.0",
|
||||
"base16-tomorrow-dark-theme": "0.25.0",
|
||||
"base16-tomorrow-light-theme": "0.8.0",
|
||||
"one-dark-ui": "0.3.0",
|
||||
"one-dark-syntax": "0.3.0",
|
||||
"one-light-syntax": "0.3.0",
|
||||
"one-light-ui": "0.2.0",
|
||||
"solarized-dark-syntax": "0.32.0",
|
||||
"solarized-light-syntax": "0.19.0",
|
||||
"archive-view": "0.44.0",
|
||||
"autocomplete": "0.43.0",
|
||||
"archive-view": "0.46.0",
|
||||
"autocomplete": "0.44.0",
|
||||
"autoflow": "0.21.0",
|
||||
"autosave": "0.20.0",
|
||||
"background-tips": "0.21.0",
|
||||
"background-tips": "0.22.0",
|
||||
"bookmarks": "0.35.0",
|
||||
"bracket-matcher": "0.69.0",
|
||||
"bracket-matcher": "0.71.0",
|
||||
"command-palette": "0.34.0",
|
||||
"deprecation-cop": "0.32.0",
|
||||
"dev-live-reload": "0.38.0",
|
||||
"encoding-selector": "0.15.0",
|
||||
"deprecation-cop": "0.34.0",
|
||||
"dev-live-reload": "0.41.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.49.0",
|
||||
"git-diff": "0.50.0",
|
||||
"go-to-line": "0.30.0",
|
||||
"grammar-selector": "0.43.0",
|
||||
"image-view": "0.47.0",
|
||||
"incompatible-packages": "0.20.0",
|
||||
"keybinding-resolver": "0.26.0",
|
||||
"link": "0.29.0",
|
||||
"markdown-preview": "0.120.0",
|
||||
"metrics": "0.40.0",
|
||||
"notifications": "0.25.0",
|
||||
"grammar-selector": "0.44.0",
|
||||
"image-view": "0.48.0",
|
||||
"incompatible-packages": "0.21.0",
|
||||
"keybinding-resolver": "0.27.0",
|
||||
"link": "0.30.0",
|
||||
"markdown-preview": "0.133.0",
|
||||
"metrics": "0.42.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",
|
||||
"spell-check": "0.51.0",
|
||||
"release-notes": "0.47.0",
|
||||
"settings-view": "0.174.0",
|
||||
"snippets": "0.72.0",
|
||||
"spell-check": "0.54.0",
|
||||
"status-bar": "0.57.0",
|
||||
"styleguide": "0.42.0",
|
||||
"symbols-view": "0.79.0",
|
||||
"styleguide": "0.43.0",
|
||||
"symbols-view": "0.81.0",
|
||||
"tabs": "0.64.0",
|
||||
"timecop": "0.27.0",
|
||||
"tree-view": "0.148.0",
|
||||
"update-package-dependencies": "0.7.0",
|
||||
"timecop": "0.28.0",
|
||||
"tree-view": "0.154.0",
|
||||
"update-package-dependencies": "0.8.0",
|
||||
"welcome": "0.21.0",
|
||||
"whitespace": "0.28.0",
|
||||
"wrap-guide": "0.30.0",
|
||||
"language-c": "0.37.0",
|
||||
"wrap-guide": "0.31.0",
|
||||
"language-c": "0.38.0",
|
||||
"language-clojure": "0.10.0",
|
||||
"language-coffee-script": "0.39.0",
|
||||
"language-css": "0.26.0",
|
||||
"language-gfm": "0.62.0",
|
||||
"language-css": "0.27.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-json": "0.11.0",
|
||||
"language-javascript": "0.56.0",
|
||||
"language-json": "0.12.0",
|
||||
"language-less": "0.24.0",
|
||||
"language-make": "0.13.0",
|
||||
"language-mustache": "0.11.0",
|
||||
@@ -142,11 +147,11 @@
|
||||
"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-todo": "0.16.0",
|
||||
"language-toml": "0.15.0",
|
||||
"language-xml": "0.27.0",
|
||||
"language-xml": "0.28.0",
|
||||
"language-yaml": "0.22.0"
|
||||
},
|
||||
"private": true,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Name=Atom
|
||||
Comment=<%= description %>
|
||||
GenericName=Text Editor
|
||||
Exec=<%= installDir %>/share/atom/atom %U
|
||||
Exec=<%= executable %> %U
|
||||
Icon=<%= iconName %>
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
|
||||
|
Depois Largura: | Altura: | Tamanho: 628 KiB |
|
Depois Largura: | Altura: | Tamanho: 20 KiB |
|
Depois Largura: | Altura: | Tamanho: 944 B |
|
Depois Largura: | Altura: | Tamanho: 1.6 KiB |
|
Depois Largura: | Altura: | Tamanho: 61 KiB |
|
Depois Largura: | Altura: | Tamanho: 2.4 KiB |
|
Depois Largura: | Altura: | Tamanho: 4.5 KiB |
|
Depois Largura: | Altura: | Tamanho: 192 KiB |
|
Depois Largura: | Altura: | Tamanho: 7.0 KiB |
@@ -1,26 +1,27 @@
|
||||
Name: <%= name %>
|
||||
Version: <%= version %>
|
||||
Release: 0.1%{?dist}
|
||||
Summary: Atom is a hackable text editor for the 21st century
|
||||
Summary: <%= description %>
|
||||
License: MIT
|
||||
URL: https://atom.io/
|
||||
AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
|
||||
Prefix: <%= installDir %>
|
||||
|
||||
%description
|
||||
<%= description %>
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/local/share/atom
|
||||
cp -r /tmp/atom-build/Atom/* %{buildroot}/usr/local/share/atom
|
||||
mkdir -p %{buildroot}/usr/local/bin/
|
||||
ln -sf /usr/local/share/atom/resources/app/apm/node_modules/.bin/apm %{buildroot}/usr/local/bin/apm
|
||||
cp atom.sh %{buildroot}/usr/local/bin/atom
|
||||
chmod 755 atom.sh
|
||||
mkdir -p %{buildroot}/usr/local/share/applications/
|
||||
mv atom.desktop %{buildroot}/usr/local/share/applications/
|
||||
mkdir -p %{buildroot}/<%= installDir %>/share/atom/
|
||||
cp -r Atom/* %{buildroot}/<%= installDir %>/share/atom/
|
||||
mkdir -p %{buildroot}/<%= installDir %>/bin/
|
||||
ln -sf ../share/atom/resources/app/apm/node_modules/.bin/apm %{buildroot}/<%= installDir %>/bin/apm
|
||||
cp atom.sh %{buildroot}/<%= installDir %>/bin/atom
|
||||
chmod 755 %{buildroot}/<%= installDir %>/bin/atom
|
||||
mkdir -p %{buildroot}/<%= installDir %>/share/applications/
|
||||
cp atom.desktop %{buildroot}/<%= installDir %>/share/applications/
|
||||
|
||||
%files
|
||||
/usr/local/bin/atom
|
||||
/usr/local/bin/apm
|
||||
/usr/local/share/atom/
|
||||
/usr/local/share/applications/atom.desktop
|
||||
<%= installDir %>/bin/atom
|
||||
<%= installDir %>/bin/apm
|
||||
<%= installDir %>/share/atom/
|
||||
<%= installDir %>/share/applications/atom.desktop
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -11,7 +11,7 @@ ARCH=`uname -m`
|
||||
|
||||
rpmdev-setuptree
|
||||
|
||||
cp -r $BUILD_DIRECTORY/Atom/* $RPM_BUILD_ROOT/BUILD
|
||||
cp -r $BUILD_DIRECTORY/Atom $RPM_BUILD_ROOT/BUILD
|
||||
cp $SPEC_FILE $RPM_BUILD_ROOT/SPECS
|
||||
cp ./atom.sh $RPM_BUILD_ROOT/BUILD
|
||||
cp $DESKTOP_FILE $RPM_BUILD_ROOT/BUILD
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
set -e
|
||||
|
||||
script/build
|
||||
script/grunt mkrpm publish-build --stack
|
||||
script/grunt mkrpm publish-build --stack --install-dir /usr
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
to5 = require '../src/6to5'
|
||||
crypto = require 'crypto'
|
||||
|
||||
describe "6to5 transpiler support", ->
|
||||
describe "::create6to5VersionAndOptionsDigest", ->
|
||||
it "returns a digest for the library version and specified options", ->
|
||||
defaultOptions =
|
||||
blacklist: [
|
||||
'useStrict'
|
||||
]
|
||||
experimental: true
|
||||
optional: [
|
||||
'asyncToGenerator'
|
||||
]
|
||||
reactCompat: true
|
||||
sourceMap: 'inline'
|
||||
version = '3.0.14'
|
||||
shasum = crypto.createHash('sha1')
|
||||
shasum.update('6to5-core', 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(version, 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update('{"blacklist": ["useStrict",],"experimental": true,"optional": ["asyncToGenerator",],"reactCompat": true,"sourceMap": "inline",}')
|
||||
expectedDigest = shasum.digest('hex')
|
||||
|
||||
observedDigest = to5.create6to5VersionAndOptionsDigest(version, defaultOptions)
|
||||
expect(observedDigest).toEqual expectedDigest
|
||||
|
||||
describe "when a .js file starts with 'use 6to5';", ->
|
||||
it "transpiles it using 6to5", ->
|
||||
transpiled = require('./fixtures/6to5/single-quotes.js')
|
||||
expect(transpiled(3)).toBe 4
|
||||
|
||||
describe 'when a .js file starts with "use 6to5";', ->
|
||||
it "transpiles it using 6to5", ->
|
||||
transpiled = require('./fixtures/6to5/double-quotes.js')
|
||||
expect(transpiled(3)).toBe 4
|
||||
|
||||
describe "when a .js file does not start with 'use 6to6';", ->
|
||||
it "does not transpile it using 6to5", ->
|
||||
expect(-> require('./fixtures/6to5/invalid.js')).toThrow()
|
||||
@@ -47,9 +47,8 @@ describe "the `atom` global", ->
|
||||
updateAvailableHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
{releaseVersion, releaseNotes} = updateAvailableHandler.mostRecentCall.args[0]
|
||||
{releaseVersion} = updateAvailableHandler.mostRecentCall.args[0]
|
||||
expect(releaseVersion).toBe 'version'
|
||||
expect(releaseNotes).toBe 'notes'
|
||||
|
||||
describe "loading default config", ->
|
||||
it 'loads the default core config', ->
|
||||
|
||||
@@ -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", ->
|
||||
@@ -669,6 +699,26 @@ describe "Config", ->
|
||||
expect(atom.config.get("foo.bar")).toBe 'baz'
|
||||
expect(atom.config.get("foo.bar", scope: ['.source.ruby'])).toBe 'more-specific'
|
||||
|
||||
describe "when the config file does not conform to the schema", ->
|
||||
beforeEach ->
|
||||
fs.writeFileSync atom.config.configFilePath, """
|
||||
'*':
|
||||
foo:
|
||||
bar: 'omg'
|
||||
int: 'baz'
|
||||
'.source.ruby':
|
||||
foo:
|
||||
bar: 'scoped'
|
||||
int: 'nope'
|
||||
"""
|
||||
|
||||
it "validates and does not load the incorrect values", ->
|
||||
atom.config.loadUserConfig()
|
||||
expect(atom.config.get("foo.int")).toBe 12
|
||||
expect(atom.config.get("foo.bar")).toBe 'omg'
|
||||
expect(atom.config.get("foo.int", scope: ['.source.ruby'])).toBe 12
|
||||
expect(atom.config.get("foo.bar", scope: ['.source.ruby'])).toBe 'scoped'
|
||||
|
||||
describe "when the config file contains valid cson", ->
|
||||
beforeEach ->
|
||||
fs.writeFileSync(atom.config.configFilePath, "foo: bar: 'baz'")
|
||||
@@ -1076,6 +1126,62 @@ describe "Config", ->
|
||||
expect(atom.config.get('foo.bar.str', scope: ['.source.js'])).toBe 'omg'
|
||||
expect(atom.config.get('foo.bar.str', scope: ['.source.coffee'])).toBe 'ok'
|
||||
|
||||
describe 'when a schema is added after config values have been set', ->
|
||||
schema = null
|
||||
beforeEach ->
|
||||
schema =
|
||||
type: 'object'
|
||||
properties:
|
||||
int:
|
||||
type: 'integer'
|
||||
default: 2
|
||||
str:
|
||||
type: 'string'
|
||||
default: 'def'
|
||||
|
||||
it "respects the new schema when values are set", ->
|
||||
expect(atom.config.set('foo.bar.str', 'global')).toBe true
|
||||
expect(atom.config.set('foo.bar.str', 'scoped', scopeSelector: '.source.js')).toBe true
|
||||
expect(atom.config.get('foo.bar.str')).toBe 'global'
|
||||
expect(atom.config.get('foo.bar.str', scope: ['.source.js'])).toBe 'scoped'
|
||||
|
||||
expect(atom.config.set('foo.bar.noschema', 'nsGlobal')).toBe true
|
||||
expect(atom.config.set('foo.bar.noschema', 'nsScoped', scopeSelector: '.source.js')).toBe true
|
||||
expect(atom.config.get('foo.bar.noschema')).toBe 'nsGlobal'
|
||||
expect(atom.config.get('foo.bar.noschema', scope: ['.source.js'])).toBe 'nsScoped'
|
||||
|
||||
expect(atom.config.set('foo.bar.int', 'nope')).toBe true
|
||||
expect(atom.config.set('foo.bar.int', 'notanint', scopeSelector: '.source.js')).toBe true
|
||||
expect(atom.config.set('foo.bar.int', 23, scopeSelector: '.source.coffee')).toBe true
|
||||
expect(atom.config.get('foo.bar.int')).toBe 'nope'
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.js'])).toBe 'notanint'
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.coffee'])).toBe 23
|
||||
|
||||
atom.config.setSchema('foo.bar', schema)
|
||||
|
||||
expect(atom.config.get('foo.bar.str')).toBe 'global'
|
||||
expect(atom.config.get('foo.bar.str', scope: ['.source.js'])).toBe 'scoped'
|
||||
expect(atom.config.get('foo.bar.noschema')).toBe 'nsGlobal'
|
||||
expect(atom.config.get('foo.bar.noschema', scope: ['.source.js'])).toBe 'nsScoped'
|
||||
|
||||
expect(atom.config.get('foo.bar.int')).toBe 2
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.js'])).toBe 2
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.coffee'])).toBe 23
|
||||
|
||||
it "sets all values that adhere to the schema", ->
|
||||
expect(atom.config.set('foo.bar.int', 10)).toBe true
|
||||
expect(atom.config.set('foo.bar.int', 15, scopeSelector: '.source.js')).toBe true
|
||||
expect(atom.config.set('foo.bar.int', 23, scopeSelector: '.source.coffee')).toBe true
|
||||
expect(atom.config.get('foo.bar.int')).toBe 10
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.js'])).toBe 15
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.coffee'])).toBe 23
|
||||
|
||||
atom.config.setSchema('foo.bar', schema)
|
||||
|
||||
expect(atom.config.get('foo.bar.int')).toBe 10
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.js'])).toBe 15
|
||||
expect(atom.config.get('foo.bar.int', scope: ['.source.coffee'])).toBe 23
|
||||
|
||||
describe 'when the value has an "integer" type', ->
|
||||
beforeEach ->
|
||||
schema =
|
||||
@@ -1363,6 +1469,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 =
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"use 6to5";
|
||||
|
||||
module.exports = v => v + 1
|
||||
@@ -0,0 +1,3 @@
|
||||
'use 6to6';
|
||||
|
||||
module.exports = v => v + 1
|
||||
@@ -0,0 +1,3 @@
|
||||
'use 6to5';
|
||||
|
||||
module.exports = v => v + 1
|
||||
@@ -0,0 +1,10 @@
|
||||
module.exports =
|
||||
activate: ->
|
||||
|
||||
deactivate: ->
|
||||
|
||||
consumeFirstServiceV3: ->
|
||||
|
||||
consumeFirstServiceV4: ->
|
||||
|
||||
consumeSecondService: ->
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "package-with-consumed-services",
|
||||
|
||||
"consumedServices": {
|
||||
"service-1": {
|
||||
"versions": {
|
||||
">=0.2 <=0.3.6": "consumeFirstServiceV3",
|
||||
"^0.4.1": "consumeFirstServiceV4"
|
||||
}
|
||||
},
|
||||
"service-2": {
|
||||
"versions": {
|
||||
"0.2.1 || 0.2.2": "consumeSecondService"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "package-with-invalid-styles",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{
|
||||
@@ -0,0 +1,13 @@
|
||||
module.exports =
|
||||
activate: ->
|
||||
|
||||
deactivate: ->
|
||||
|
||||
provideFirstServiceV3: ->
|
||||
'first-service-v3'
|
||||
|
||||
provideFirstServiceV4: ->
|
||||
'first-service-v4'
|
||||
|
||||
provideSecondService: ->
|
||||
'second-service'
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "package-with-provided-services",
|
||||
|
||||
"providedServices": {
|
||||
"service-1": {
|
||||
"description": "The first service",
|
||||
"versions": {
|
||||
"0.3.1": "provideFirstServiceV3",
|
||||
"0.4.1": "provideFirstServiceV4"
|
||||
}
|
||||
},
|
||||
"service-2": {
|
||||
"description": "The second service",
|
||||
"versions": {
|
||||
"0.2.1": "provideSecondService"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script wraps the `Atom` binary, allowing the `chromedriver` server to
|
||||
# execute it with positional arguments. `chromedriver` only allows 'switches'
|
||||
# to be specified when starting a browser, not positional arguments, so this
|
||||
# script accepts two special switches:
|
||||
#
|
||||
# * `atom-path` The path to the `Atom` binary
|
||||
# * `atom-args` A space-separated list of positional arguments to pass to Atom.
|
||||
#
|
||||
# Any other switches will be passed through to `Atom`.
|
||||
|
||||
atom_path=""
|
||||
atom_switches=()
|
||||
atom_args=()
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--atom-path=*)
|
||||
atom_path="${arg#*=}"
|
||||
;;
|
||||
|
||||
--atom-args=*)
|
||||
atom_args_string="${arg#*=}"
|
||||
for atom_arg in $atom_args_string; do
|
||||
atom_args+=($atom_arg)
|
||||
done
|
||||
;;
|
||||
|
||||
*)
|
||||
atom_switches+=($arg)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
exec $atom_path "${atom_switches[@]}" "${atom_args[@]}"
|
||||
@@ -0,0 +1,107 @@
|
||||
# These tests are excluded by default. To run them from the command line:
|
||||
#
|
||||
# ATOM_INTEGRATION_TESTS_ENABLED=true apm test
|
||||
return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED
|
||||
|
||||
os = require "os"
|
||||
fs = require "fs"
|
||||
path = require "path"
|
||||
remote = require "remote"
|
||||
temp = require("temp").track()
|
||||
{spawn, spawnSync} = require "child_process"
|
||||
{Builder, By} = require "../../build/node_modules/selenium-webdriver"
|
||||
|
||||
AtomPath = remote.process.argv[0]
|
||||
AtomLauncherPath = path.join(__dirname, "helpers", "atom-launcher.sh")
|
||||
SocketPath = path.join(os.tmpdir(), "atom-integration-test.sock")
|
||||
ChromeDriverPort = 9515
|
||||
|
||||
describe "Starting Atom", ->
|
||||
[chromeDriver, driver, tempDirPath] = []
|
||||
|
||||
beforeEach ->
|
||||
tempDirPath = temp.mkdirSync("empty-dir")
|
||||
|
||||
waitsFor "chromedriver to start", (done) ->
|
||||
chromeDriver = spawn "chromedriver", ["--verbose", "--port=#{ChromeDriverPort}"]
|
||||
chromeDriver.on "error", (error) ->
|
||||
throw new Error("chromedriver failed to start: #{error.message}")
|
||||
chromeDriver.stdout.on "data", -> done()
|
||||
|
||||
afterEach ->
|
||||
waitsForPromise -> driver.quit().thenFinally(-> chromeDriver.kill())
|
||||
|
||||
startAtom = (args...) ->
|
||||
driver = new Builder()
|
||||
.usingServer("http://localhost:#{ChromeDriverPort}")
|
||||
.withCapabilities(
|
||||
chromeOptions:
|
||||
binary: AtomLauncherPath
|
||||
args: [
|
||||
"atom-path=#{AtomPath}"
|
||||
"atom-args=#{args.join(" ")}"
|
||||
"dev"
|
||||
"safe"
|
||||
"user-data-dir=#{temp.mkdirSync('integration-spec-')}"
|
||||
"socket-path=#{SocketPath}"
|
||||
]
|
||||
)
|
||||
.forBrowser('atom')
|
||||
.build()
|
||||
|
||||
waitsForPromise ->
|
||||
driver.wait ->
|
||||
driver.getTitle().then (title) -> title.indexOf("Atom") >= 0
|
||||
|
||||
startAnotherAtom = (args...) ->
|
||||
spawnSync(AtomPath, args.concat([
|
||||
"--dev",
|
||||
"--safe",
|
||||
"--socket-path=#{SocketPath}"
|
||||
]))
|
||||
|
||||
describe "when given the name of a file that doesn't exist", ->
|
||||
tempFilePath = null
|
||||
|
||||
beforeEach ->
|
||||
tempFilePath = path.join(tempDirPath, "an-existing-file")
|
||||
fs.writeFileSync(tempFilePath, "This was already here.")
|
||||
startAtom(path.join(tempDirPath, "new-file"))
|
||||
|
||||
it "opens a new window with an empty text editor", ->
|
||||
waitsForPromise ->
|
||||
driver.getAllWindowHandles().then (handles) ->
|
||||
expect(handles.length).toBe 1
|
||||
driver.executeScript(-> atom.workspace.getActivePane().getItems().length).then (length) ->
|
||||
expect(length).toBe 1
|
||||
driver.executeScript(-> atom.workspace.getActiveTextEditor().getText()).then (text) ->
|
||||
expect(text).toBe("")
|
||||
driver.findElement(By.tagName("atom-text-editor")).sendKeys("Hello world!")
|
||||
driver.executeScript(-> atom.workspace.getActiveTextEditor().getText()).then (text) ->
|
||||
expect(text).toBe "Hello world!"
|
||||
|
||||
# Opening another existing file in the same directory reuses the window,
|
||||
# and opens a new tab for the file.
|
||||
waitsForPromise ->
|
||||
startAnotherAtom(tempFilePath)
|
||||
driver.wait ->
|
||||
driver.executeScript(-> atom.workspace.getActivePane().getItems().length).then (length) ->
|
||||
length is 2
|
||||
driver.executeScript(-> atom.workspace.getActiveTextEditor().getText()).then (text) ->
|
||||
expect(text).toBe "This was already here."
|
||||
|
||||
# Opening a different directory creates a new window.
|
||||
waitsForPromise ->
|
||||
startAnotherAtom(temp.mkdirSync("another-empty-dir"))
|
||||
driver.wait ->
|
||||
driver.getAllWindowHandles().then (handles) ->
|
||||
handles.length is 2
|
||||
|
||||
describe "when given the name of a directory that exists", ->
|
||||
beforeEach ->
|
||||
startAtom(tempDirPath)
|
||||
|
||||
it "opens a new window no text editors open", ->
|
||||
waitsForPromise ->
|
||||
driver.executeScript(-> atom.workspace.getActiveTextEditor()).then (editor) ->
|
||||
expect(editor).toBeNull()
|
||||
@@ -1,5 +1,6 @@
|
||||
{$, $$} = require '../src/space-pen-extensions'
|
||||
Package = require '../src/package'
|
||||
{Disposable} = require 'atom'
|
||||
|
||||
describe "PackageManager", ->
|
||||
workspaceElement = null
|
||||
@@ -22,6 +23,12 @@ describe "PackageManager", ->
|
||||
expect(pack instanceof Package).toBe true
|
||||
expect(pack.metadata.name).toBe "package-with-broken-keymap"
|
||||
|
||||
it "returns the package if it has an invalid stylesheet", ->
|
||||
pack = atom.packages.loadPackage("package-with-invalid-styles")
|
||||
expect(pack instanceof Package).toBe true
|
||||
expect(pack.metadata.name).toBe "package-with-invalid-styles"
|
||||
expect(pack.stylesheets.length).toBe 0
|
||||
|
||||
it "returns null if the package has an invalid package.json", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.loadPackage("package-with-broken-package-json")).toBeNull()
|
||||
@@ -445,6 +452,47 @@ describe "PackageManager", ->
|
||||
runs ->
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBe '^a'
|
||||
|
||||
describe "service registration", ->
|
||||
it "registers the package's provided and consumed services", ->
|
||||
consumerModule = require "./fixtures/packages/package-with-consumed-services"
|
||||
firstServiceV3Disposed = false
|
||||
firstServiceV4Disposed = false
|
||||
secondServiceDisposed = false
|
||||
spyOn(consumerModule, 'consumeFirstServiceV3').andReturn(new Disposable -> firstServiceV3Disposed = true)
|
||||
spyOn(consumerModule, 'consumeFirstServiceV4').andReturn(new Disposable -> firstServiceV4Disposed = true)
|
||||
spyOn(consumerModule, 'consumeSecondService').andReturn(new Disposable -> secondServiceDisposed = true)
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-consumed-services")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-provided-services")
|
||||
|
||||
runs ->
|
||||
expect(consumerModule.consumeFirstServiceV3).toHaveBeenCalledWith('first-service-v3')
|
||||
expect(consumerModule.consumeFirstServiceV4).toHaveBeenCalledWith('first-service-v4')
|
||||
expect(consumerModule.consumeSecondService).toHaveBeenCalledWith('second-service')
|
||||
|
||||
consumerModule.consumeFirstServiceV3.reset()
|
||||
consumerModule.consumeFirstServiceV4.reset()
|
||||
consumerModule.consumeSecondService.reset()
|
||||
|
||||
atom.packages.deactivatePackage("package-with-provided-services")
|
||||
|
||||
expect(firstServiceV3Disposed).toBe true
|
||||
expect(firstServiceV4Disposed).toBe true
|
||||
expect(secondServiceDisposed).toBe true
|
||||
|
||||
atom.packages.deactivatePackage("package-with-consumed-services")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-provided-services")
|
||||
|
||||
runs ->
|
||||
expect(consumerModule.consumeFirstServiceV3).not.toHaveBeenCalled()
|
||||
expect(consumerModule.consumeFirstServiceV4).not.toHaveBeenCalled()
|
||||
expect(consumerModule.consumeSecondService).not.toHaveBeenCalled()
|
||||
|
||||
describe "::deactivatePackage(id)", ->
|
||||
afterEach ->
|
||||
atom.packages.unloadPackages()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,6 +17,7 @@ Config = require '../src/config'
|
||||
{Point} = require 'text-buffer'
|
||||
Project = require '../src/project'
|
||||
Workspace = require '../src/workspace'
|
||||
ServiceHub = require 'service-hub'
|
||||
TextEditor = require '../src/text-editor'
|
||||
TextEditorView = require '../src/text-editor-view'
|
||||
TextEditorElement = require '../src/text-editor-element'
|
||||
@@ -77,6 +78,7 @@ beforeEach ->
|
||||
projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures')
|
||||
atom.project = new Project(paths: [projectPath])
|
||||
atom.workspace = new Workspace()
|
||||
atom.packages.serviceHub = new ServiceHub
|
||||
atom.keymaps.keyBindings = _.clone(keyBindingsToRestore)
|
||||
atom.commands.restoreSnapshot(commandsToRestore)
|
||||
atom.styles.restoreSnapshot(styleElementsToRestore)
|
||||
@@ -213,6 +215,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 +305,13 @@ window.waitsForPromise = (args...) ->
|
||||
window.waitsFor timeout, (moveOn) ->
|
||||
promise = fn()
|
||||
if shouldReject
|
||||
promise.fail(moveOn)
|
||||
promise.done ->
|
||||
(promise.catch ? promise.thenCatch).call(promise, 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 ? promise.thenCatch).call promise, (error) ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with #{jasmine.pp(error)}")
|
||||
moveOn()
|
||||
|
||||
|
||||
@@ -374,6 +374,22 @@ describe "TextEditorComponent", ->
|
||||
expect(line2LeafNodes[2].textContent).toBe ' '
|
||||
expect(line2LeafNodes[2].classList.contains('indent-guide')).toBe true
|
||||
|
||||
it "renders indent guides correctly on lines containing only whitespace when invisibles are enabled", ->
|
||||
atom.config.set 'editor.showInvisibles', true
|
||||
atom.config.set 'editor.invisibles', space: '-', eol: 'x'
|
||||
editor.getBuffer().insert([1, Infinity], '\n ')
|
||||
nextAnimationFrame()
|
||||
|
||||
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
|
||||
expect(line2LeafNodes.length).toBe 4
|
||||
expect(line2LeafNodes[0].textContent).toBe '--'
|
||||
expect(line2LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
expect(line2LeafNodes[1].textContent).toBe '--'
|
||||
expect(line2LeafNodes[1].classList.contains('indent-guide')).toBe true
|
||||
expect(line2LeafNodes[2].textContent).toBe '--'
|
||||
expect(line2LeafNodes[2].classList.contains('indent-guide')).toBe true
|
||||
expect(line2LeafNodes[3].textContent).toBe 'x'
|
||||
|
||||
it "does not render indent guides in trailing whitespace for lines containing non whitespace characters", ->
|
||||
editor.getBuffer().setText " hi "
|
||||
nextAnimationFrame()
|
||||
|
||||
@@ -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", ->
|
||||
|
||||
@@ -364,12 +364,13 @@ describe "ThemeManager", ->
|
||||
throw new Error('EACCES permission denied "styles.less"')
|
||||
atom.notifications.onDidAddNotification addErrorHandler = jasmine.createSpy()
|
||||
|
||||
it "creates an error notification", ->
|
||||
it "creates an error notification and does not add the stylesheet", ->
|
||||
themeManager.loadUserStylesheet()
|
||||
expect(addErrorHandler).toHaveBeenCalled()
|
||||
note = addErrorHandler.mostRecentCall.args[0]
|
||||
expect(note.getType()).toBe 'error'
|
||||
expect(note.getMessage()).toContain 'Error loading'
|
||||
expect(atom.styles.styleElementsBySourcePath[atom.styles.getUserStyleSheetPath()]).toBeUndefined()
|
||||
|
||||
describe "when there is an error watching the user stylesheet", ->
|
||||
addErrorHandler = null
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
###
|
||||
Cache for source code transpiled by 6to5.
|
||||
|
||||
Inspired by https://github.com/atom/atom/blob/6b963a562f8d495fbebe6abdbafbc7caf705f2c3/src/coffee-cache.coffee.
|
||||
###
|
||||
|
||||
crypto = require 'crypto'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
to5 = null # Defer until used
|
||||
|
||||
stats =
|
||||
hits: 0
|
||||
misses: 0
|
||||
|
||||
defaultOptions =
|
||||
# The Chrome dev tools will show the original version of the file
|
||||
# when the source map is inlined.
|
||||
sourceMap: 'inline'
|
||||
|
||||
# Because Atom is currently packaged with a fork of React v0.11,
|
||||
# it makes sense to use the --react-compat option so the React
|
||||
# JSX transformer produces pre-v0.12 code.
|
||||
reactCompat: true
|
||||
|
||||
# Blacklisted features do not get transpiled. Features that are
|
||||
# natively supported in the target environment should be listed
|
||||
# here. Because Atom uses a bleeding edge version of Node/io.js,
|
||||
# I think this can include es6.arrowFunctions, es6.classes, and
|
||||
# possibly others, but I want to be conservative.
|
||||
blacklist: [
|
||||
'useStrict'
|
||||
]
|
||||
|
||||
# Includes support for es7 features listed at:
|
||||
# http://6to5.org/docs/usage/transformers/#es7-experimental-.
|
||||
experimental: true
|
||||
|
||||
optional: [
|
||||
# Target a version of the regenerator runtime that
|
||||
# supports yield so the transpiled code is cleaner/smaller.
|
||||
'asyncToGenerator'
|
||||
]
|
||||
|
||||
###
|
||||
shasum - Hash with an update() method.
|
||||
value - Must be a value that could be returned by JSON.parse().
|
||||
###
|
||||
updateDigestForJsonValue = (shasum, value) ->
|
||||
# Implmentation is similar to that of pretty-printing a JSON object, except:
|
||||
# * Strings are not escaped.
|
||||
# * No effort is made to avoid trailing commas.
|
||||
# These shortcuts should not affect the correctness of this function.
|
||||
type = typeof value
|
||||
if type is 'string'
|
||||
shasum.update('"', 'utf8')
|
||||
shasum.update(value, 'utf8')
|
||||
shasum.update('"', 'utf8')
|
||||
else if type in ['boolean', 'number']
|
||||
shasum.update(value.toString(), 'utf8')
|
||||
else if value is null
|
||||
shasum.update('null', 'utf8')
|
||||
else if Array.isArray value
|
||||
shasum.update('[', 'utf8')
|
||||
for item in value
|
||||
updateDigestForJsonValue(shasum, item)
|
||||
shasum.update(',', 'utf8')
|
||||
shasum.update(']', 'utf8')
|
||||
else
|
||||
# value must be an object: be sure to sort the keys.
|
||||
keys = Object.keys value
|
||||
keys.sort()
|
||||
|
||||
shasum.update('{', 'utf8')
|
||||
for key in keys
|
||||
updateDigestForJsonValue(shasum, key)
|
||||
shasum.update(': ', 'utf8')
|
||||
updateDigestForJsonValue(shasum, value[key])
|
||||
shasum.update(',', 'utf8')
|
||||
shasum.update('}', 'utf8')
|
||||
|
||||
create6to5VersionAndOptionsDigest = (version, options) ->
|
||||
shasum = crypto.createHash('sha1')
|
||||
# Include the version of 6to5 in the hash.
|
||||
shasum.update('6to5-core', 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(version, 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
updateDigestForJsonValue(shasum, options)
|
||||
shasum.digest('hex')
|
||||
|
||||
jsCacheDir = null
|
||||
|
||||
getCachePath = (sourceCode) ->
|
||||
digest = crypto.createHash('sha1').update(sourceCode, 'utf8').digest('hex')
|
||||
|
||||
unless jsCacheDir?
|
||||
to5Version = require('6to5-core/package.json').version
|
||||
cacheDir = path.join(process.env.ATOM_HOME, 'compile-cache')
|
||||
jsCacheDir = path.join(cacheDir, 'js', '6to5', create6to5VersionAndOptionsDigest(to5Version, defaultOptions))
|
||||
|
||||
path.join(jsCacheDir, "#{digest}.js")
|
||||
|
||||
getCachedJavaScript = (cachePath) ->
|
||||
if fs.isFileSync(cachePath)
|
||||
try
|
||||
cachedJavaScript = fs.readFileSync(cachePath, 'utf8')
|
||||
stats.hits++
|
||||
return cachedJavaScript
|
||||
null
|
||||
|
||||
# Returns the 6to5 options that should be used to transpile filePath.
|
||||
createOptions = (filePath) ->
|
||||
options = filename: filePath
|
||||
for key, value of defaultOptions
|
||||
options[key] = value
|
||||
options
|
||||
|
||||
transpile = (sourceCode, filePath, cachePath) ->
|
||||
options = createOptions(filePath)
|
||||
to5 ?= require '6to5-core'
|
||||
js = to5.transform(sourceCode, options).code
|
||||
stats.misses++
|
||||
|
||||
try
|
||||
fs.writeFileSync(cachePath, js)
|
||||
|
||||
js
|
||||
|
||||
# Function that obeys the contract of an entry in the require.extensions map.
|
||||
# Returns the transpiled version of the JavaScript code at filePath, which is
|
||||
# either generated on the fly or pulled from cache.
|
||||
loadFile = (module, filePath) ->
|
||||
sourceCode = fs.readFileSync(filePath, 'utf8')
|
||||
unless sourceCode.startsWith('"use 6to5"') or sourceCode.startsWith("'use 6to5'")
|
||||
return module._compile(sourceCode, filePath)
|
||||
|
||||
cachePath = getCachePath(sourceCode)
|
||||
js = getCachedJavaScript(cachePath) ? transpile(sourceCode, filePath, cachePath)
|
||||
module._compile(js, filePath)
|
||||
|
||||
register = ->
|
||||
Object.defineProperty(require.extensions, '.js', {
|
||||
writable: false
|
||||
value: loadFile
|
||||
})
|
||||
|
||||
module.exports =
|
||||
register: register
|
||||
getCacheMisses: -> stats.misses
|
||||
getCacheHits: -> stats.hits
|
||||
|
||||
# Visible for testing.
|
||||
create6to5VersionAndOptionsDigest: create6to5VersionAndOptionsDigest
|
||||
|
||||
addPathToCache: (filePath) ->
|
||||
return if path.extname(filePath) isnt '.js'
|
||||
|
||||
sourceCode = fs.readFileSync(filePath, 'utf8')
|
||||
cachePath = getCachePath(sourceCode)
|
||||
transpile(sourceCode, filePath, cachePath)
|
||||
@@ -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'
|
||||
@@ -43,6 +42,12 @@ class Atom extends Model
|
||||
which returns an HTMLElement.
|
||||
"""
|
||||
|
||||
serviceHubDeprecationMessage = """
|
||||
atom.services is no longer available. To register service providers and
|
||||
consumers, use the `providedServices` and `consumedServices` fields in
|
||||
your package's package.json.
|
||||
"""
|
||||
|
||||
Object.defineProperty atom, 'workspaceView',
|
||||
get: ->
|
||||
deprecate(workspaceViewDeprecationMessage)
|
||||
@@ -51,6 +56,14 @@ class Atom extends Model
|
||||
deprecate(workspaceViewDeprecationMessage)
|
||||
atom.__workspaceView = newValue
|
||||
|
||||
Object.defineProperty atom, 'services',
|
||||
get: ->
|
||||
deprecate(serviceHubDeprecationMessage)
|
||||
atom.packages.serviceHub
|
||||
set: (newValue) ->
|
||||
deprecate(serviceHubDeprecationMessage)
|
||||
atom.packages.serviceHub = newValue
|
||||
|
||||
atom
|
||||
|
||||
# Deserializes the Atom environment from a state object
|
||||
@@ -96,7 +109,7 @@ class Atom extends Model
|
||||
#
|
||||
# Returns the absolute path to ~/.atom
|
||||
@getConfigDirPath: ->
|
||||
@configDirPath ?= fs.absolute('~/.atom')
|
||||
@configDirPath ?= process.env.ATOM_HOME
|
||||
|
||||
# Get the path to Atom's storage directory.
|
||||
#
|
||||
@@ -134,9 +147,6 @@ class Atom extends Model
|
||||
# Public: A {Clipboard} instance
|
||||
clipboard: null
|
||||
|
||||
# A {ServiceHub} instance
|
||||
services: null
|
||||
|
||||
# Public: A {ContextMenuManager} instance
|
||||
contextMenu: null
|
||||
|
||||
@@ -236,7 +246,6 @@ class Atom extends Model
|
||||
NotificationManager = require './notification-manager'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
ServiceHub = require './service-hub'
|
||||
GrammarRegistry = require './grammar-registry'
|
||||
ThemeManager = require './theme-manager'
|
||||
StyleManager = require './style-manager'
|
||||
@@ -254,9 +263,6 @@ class Atom extends Model
|
||||
# Make react.js faster
|
||||
process.env.NODE_ENV ?= 'production' unless devMode
|
||||
|
||||
# Set Atom's home so packages don't have to guess it
|
||||
process.env.ATOM_HOME = configDirPath
|
||||
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@@ -272,7 +278,6 @@ class Atom extends Model
|
||||
@contextMenu = new ContextMenuManager({resourcePath, devMode})
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@clipboard = new Clipboard()
|
||||
@services = new ServiceHub
|
||||
|
||||
@grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry()
|
||||
|
||||
@@ -547,6 +552,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}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ url = require 'url'
|
||||
{EventEmitter} = require 'events'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
socketPath =
|
||||
DefaultSocketPath =
|
||||
if process.platform is 'win32'
|
||||
'\\\\.\\pipe\\atom-sock'
|
||||
else
|
||||
@@ -31,17 +31,20 @@ class AtomApplication
|
||||
|
||||
# Public: The entry point into the Atom application.
|
||||
@open: (options) ->
|
||||
options.socketPath ?= DefaultSocketPath
|
||||
|
||||
createAtomApplication = -> new AtomApplication(options)
|
||||
|
||||
# FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely
|
||||
# take a few seconds to trigger 'error' event, it could be a bug of node
|
||||
# or atom-shell, before it's fixed we check the existence of socketPath to
|
||||
# speedup startup.
|
||||
if (process.platform isnt 'win32' and not fs.existsSync socketPath) or options.test
|
||||
if (process.platform isnt 'win32' and not fs.existsSync options.socketPath) or options.test
|
||||
createAtomApplication()
|
||||
return
|
||||
|
||||
client = net.connect {path: socketPath}, ->
|
||||
|
||||
client = net.connect {path: options.socketPath}, ->
|
||||
client.write JSON.stringify(options), ->
|
||||
client.end()
|
||||
app.terminate()
|
||||
@@ -57,7 +60,7 @@ class AtomApplication
|
||||
exit: (status) -> app.exit(status)
|
||||
|
||||
constructor: (options) ->
|
||||
{@resourcePath, @version, @devMode, @safeMode} = options
|
||||
{@resourcePath, @version, @devMode, @safeMode, @socketPath} = options
|
||||
|
||||
# Normalize to make sure drive letter case is consistent on Windows
|
||||
@resourcePath = path.normalize(@resourcePath) if @resourcePath
|
||||
@@ -119,15 +122,15 @@ class AtomApplication
|
||||
connection.on 'data', (data) =>
|
||||
@openWithOptions(JSON.parse(data))
|
||||
|
||||
server.listen socketPath
|
||||
server.listen @socketPath
|
||||
server.on 'error', (error) -> console.error 'Application server failed', error
|
||||
|
||||
deleteSocketFile: ->
|
||||
return if process.platform is 'win32'
|
||||
|
||||
if fs.existsSync(socketPath)
|
||||
if fs.existsSync(@socketPath)
|
||||
try
|
||||
fs.unlinkSync(socketPath)
|
||||
fs.unlinkSync(@socketPath)
|
||||
catch error
|
||||
# Ignore ENOENT errors in case the file was deleted between the exists
|
||||
# check and the call to unlink sync. This occurred occasionally on CI
|
||||
@@ -216,6 +219,8 @@ class AtomApplication
|
||||
ipc.on 'open', (event, options) =>
|
||||
window = @windowForEvent(event)
|
||||
if options?
|
||||
if typeof options.pathsToOpen is 'string'
|
||||
options.pathsToOpen = [options.pathsToOpen]
|
||||
if options.pathsToOpen?.length > 0
|
||||
options.window = window
|
||||
@openPaths(options)
|
||||
@@ -414,7 +419,7 @@ class AtomApplication
|
||||
PackageManager = require '../package-manager'
|
||||
fs = require 'fs-plus'
|
||||
@packages = new PackageManager
|
||||
configDirPath: fs.absolute('~/.atom')
|
||||
configDirPath: process.env.ATOM_HOME
|
||||
devMode: devMode
|
||||
resourcePath: @resourcePath
|
||||
|
||||
|
||||
@@ -23,13 +23,18 @@ class AtomWindow
|
||||
# Normalize to make sure drive letter case is consistent on Windows
|
||||
@resourcePath = path.normalize(@resourcePath) if @resourcePath
|
||||
|
||||
@browserWindow = new BrowserWindow
|
||||
options =
|
||||
show: false
|
||||
title: 'Atom'
|
||||
icon: @constructor.iconPath
|
||||
'web-preferences':
|
||||
'direct-write': false
|
||||
'direct-write': true
|
||||
'subpixel-font-scaling': false
|
||||
# Don't set icon on Windows so the exe's ico will be used as window and
|
||||
# taskbar's icon. See https://github.com/atom/atom/issues/4811 for more.
|
||||
if process.platform is 'linux'
|
||||
options.icon = @constructor.iconPath
|
||||
|
||||
@browserWindow = new BrowserWindow options
|
||||
global.atomApplication.addWindow(this)
|
||||
|
||||
@handleEvents()
|
||||
|
||||
@@ -47,7 +47,7 @@ class AutoUpdateManager
|
||||
@setState(ErrorState)
|
||||
console.error "Error Downloading Update: #{message}"
|
||||
|
||||
autoUpdater.on 'update-downloaded', (event, @releaseNotes, @releaseVersion) =>
|
||||
autoUpdater.on 'update-downloaded', (event, releaseNotes, @releaseVersion) =>
|
||||
@setState(UpdateAvailableState)
|
||||
@emitUpdateAvailableEvent(@getWindows()...)
|
||||
|
||||
@@ -61,9 +61,9 @@ class AutoUpdateManager
|
||||
@setState(UnsupportedState)
|
||||
|
||||
emitUpdateAvailableEvent: (windows...) ->
|
||||
return unless @releaseVersion? and @releaseNotes
|
||||
return unless @releaseVersion?
|
||||
for atomWindow in windows
|
||||
atomWindow.sendMessage('update-available', {@releaseVersion, @releaseNotes})
|
||||
atomWindow.sendMessage('update-available', {@releaseVersion})
|
||||
|
||||
setState: (state) ->
|
||||
return if @state is state
|
||||
|
||||
@@ -13,17 +13,8 @@ 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 = ->
|
||||
setupAtomHome()
|
||||
if process.platform is 'win32'
|
||||
SquirrelUpdate = require './squirrel-update'
|
||||
squirrelCommand = process.argv[1]
|
||||
@@ -50,8 +41,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
|
||||
@@ -79,6 +74,18 @@ setupCoffeeScript = ->
|
||||
js = CoffeeScript.compile(coffee, filename: filePath)
|
||||
module._compile(js, filePath)
|
||||
|
||||
setupAtomHome = ->
|
||||
return if process.env.ATOM_HOME
|
||||
|
||||
if process.platform is 'win32'
|
||||
home = process.env.USERPROFILE
|
||||
else
|
||||
home = process.env.HOME
|
||||
atomHome = path.join(home, '.atom')
|
||||
try
|
||||
atomHome = fs.realpathSync(atomHome)
|
||||
process.env.ATOM_HOME = atomHome
|
||||
|
||||
parseCommandLine = ->
|
||||
version = app.getVersion()
|
||||
options = optimist(process.argv[1..])
|
||||
@@ -95,8 +102,12 @@ parseCommandLine = ->
|
||||
opened or a new window if it hasn't.
|
||||
|
||||
Environment Variables:
|
||||
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
|
||||
Defaults to `~/github/atom`.
|
||||
|
||||
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
|
||||
Defaults to `~/github/atom`.
|
||||
|
||||
ATOM_HOME The root path for all configuration files and folders.
|
||||
Defaults to `~/.atom`.
|
||||
"""
|
||||
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
|
||||
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the browser process in the foreground.')
|
||||
@@ -109,6 +120,7 @@ parseCommandLine = ->
|
||||
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
|
||||
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
|
||||
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
|
||||
options.string('socket-path')
|
||||
args = options.argv
|
||||
|
||||
if args.help
|
||||
@@ -129,6 +141,7 @@ parseCommandLine = ->
|
||||
newWindow = args['new-window']
|
||||
pidToKillWhenClosed = args['pid'] if args['wait']
|
||||
logFile = args['log-file']
|
||||
socketPath = args['socket-path']
|
||||
|
||||
if args['resource-path']
|
||||
devMode = true
|
||||
@@ -153,6 +166,6 @@ parseCommandLine = ->
|
||||
# explicitly pass it by command line, see http://git.io/YC8_Ew.
|
||||
process.env.PATH = args['path-environment'] if args['path-environment']
|
||||
|
||||
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile}
|
||||
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile, socketPath}
|
||||
|
||||
start()
|
||||
|
||||
@@ -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 ?= {}
|
||||
|
||||
@@ -5,7 +5,11 @@ CoffeeScript = require 'coffee-script'
|
||||
CSON = require 'season'
|
||||
fs = require 'fs-plus'
|
||||
|
||||
cacheDir = path.join(fs.absolute('~/.atom'), 'compile-cache')
|
||||
cacheDir = path.join(process.env.ATOM_HOME, '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
|
||||
@@ -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)}"
|
||||
@@ -53,10 +61,16 @@ module.exports =
|
||||
})
|
||||
|
||||
addPathToCache: (filePath) ->
|
||||
extension = path.extname(filePath)
|
||||
if extension is '.coffee'
|
||||
content = fs.readFileSync(filePath, 'utf8')
|
||||
cachePath = getCachePath(coffee)
|
||||
compileCoffeeScript(coffee, filePath, cachePath)
|
||||
else if extension is '.cson'
|
||||
CSON.readFileSync(filePath)
|
||||
switch path.extname(filePath)
|
||||
when '.coffee'
|
||||
content = fs.readFileSync(filePath, 'utf8')
|
||||
cachePath = getCachePath(coffee)
|
||||
compileCoffeeScript(coffee, filePath, cachePath)
|
||||
when '.cson'
|
||||
CSON.readFileSync(filePath)
|
||||
when '.js'
|
||||
require('./6to5').addPathToCache(filePath)
|
||||
|
||||
getCacheMisses: -> stats.misses
|
||||
|
||||
getCacheHits: -> stats.hits
|
||||
|
||||
@@ -83,7 +83,7 @@ ScopeDescriptor = require './scope-descriptor'
|
||||
#
|
||||
# ## Config Schemas
|
||||
#
|
||||
# We use [json schema](json-schema.org) which allows you to define your value's
|
||||
# We use [json schema](http://json-schema.org) which allows you to define your value's
|
||||
# default, the type it should be, etc. A simple example:
|
||||
#
|
||||
# ```coffee
|
||||
@@ -519,7 +519,7 @@ class Config
|
||||
# * `options` (optional) {Object} see the `options` argument to {::get}
|
||||
#
|
||||
# Returns an {Array} of {Object}s with the following keys:
|
||||
# * `scopeSelector` The scope-selector {String} with which the value is associated
|
||||
# * `scopeDescriptor` The {ScopeDescriptor} with which the value is associated
|
||||
# * `value` The value for the key-path
|
||||
getAll: (keyPath, options) ->
|
||||
{scope, sources} = options if options?
|
||||
@@ -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
|
||||
@@ -601,7 +602,7 @@ class Config
|
||||
return false
|
||||
|
||||
if scopeSelector?
|
||||
@setRawScopedValue(source, scopeSelector, keyPath, value)
|
||||
@setRawScopedValue(keyPath, value, source, scopeSelector)
|
||||
else
|
||||
@setRawValue(keyPath, value)
|
||||
|
||||
@@ -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
|
||||
@@ -795,6 +797,7 @@ class Config
|
||||
_.extend rootSchema, schema
|
||||
@setDefaults(keyPath, @extractDefaultsFromSchema(schema))
|
||||
@setScopedDefaultsFromSchema(keyPath, schema)
|
||||
@resetSettingsForSchemaChange()
|
||||
|
||||
load: ->
|
||||
@initializeConfigDirectory()
|
||||
@@ -898,16 +901,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 +954,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
|
||||
@@ -992,9 +999,28 @@ class Config
|
||||
defaults[key] = @extractDefaultsFromSchema(value) for key, value of properties
|
||||
defaults
|
||||
|
||||
makeValueConformToSchema: (keyPath, value) ->
|
||||
value = @constructor.executeSchemaEnforcers(keyPath, value, schema) if schema = @getSchema(keyPath)
|
||||
value
|
||||
makeValueConformToSchema: (keyPath, value, options) ->
|
||||
if options?.suppressException
|
||||
try
|
||||
@makeValueConformToSchema(keyPath, value)
|
||||
catch e
|
||||
undefined
|
||||
else
|
||||
value = @constructor.executeSchemaEnforcers(keyPath, value, schema) if schema = @getSchema(keyPath)
|
||||
value
|
||||
|
||||
# When the schema is changed / added, there may be values set in the config
|
||||
# that do not conform to the schema. This will reset make them conform.
|
||||
resetSettingsForSchemaChange: (source=@getUserConfigPath()) ->
|
||||
@transact =>
|
||||
@settings = @makeValueConformToSchema(null, @settings, suppressException: true)
|
||||
priority = @priorityForSource(source)
|
||||
selectorsAndSettings = @scopedSettingsStore.propertiesForSource(source)
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
for scopeSelector, settings of selectorsAndSettings
|
||||
settings = @makeValueConformToSchema(null, settings, suppressException: true)
|
||||
@setRawScopedValue(null, settings, source, scopeSelector)
|
||||
return
|
||||
|
||||
###
|
||||
Section: Private Scoped Settings
|
||||
@@ -1011,8 +1037,15 @@ class Config
|
||||
|
||||
resetUserScopedSettings: (newScopedSettings) ->
|
||||
source = @getUserConfigPath()
|
||||
priority = @priorityForSource(source)
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
@scopedSettingsStore.addProperties(source, newScopedSettings, priority: @priorityForSource(source))
|
||||
|
||||
for scopeSelector, settings of newScopedSettings
|
||||
settings = @makeValueConformToSchema(null, settings, suppressException: true)
|
||||
validatedSettings = {}
|
||||
validatedSettings[scopeSelector] = withoutEmptyObjects(settings)
|
||||
@scopedSettingsStore.addProperties(source, validatedSettings, {priority}) if validatedSettings[scopeSelector]?
|
||||
|
||||
@emitChangeEvent()
|
||||
|
||||
addScopedSettings: (source, selector, value, options) ->
|
||||
@@ -1025,7 +1058,7 @@ class Config
|
||||
disposable.dispose()
|
||||
@emitChangeEvent()
|
||||
|
||||
setRawScopedValue: (source, selector, keyPath, value) ->
|
||||
setRawScopedValue: (keyPath, value, source, selector, options) ->
|
||||
if keyPath?
|
||||
newValue = {}
|
||||
_.setValueForKeyPath(newValue, keyPath, value)
|
||||
@@ -1112,12 +1145,17 @@ Config.addSchemaEnforcers
|
||||
return value unless schema.properties?
|
||||
|
||||
newValue = {}
|
||||
for prop, childSchema of schema.properties
|
||||
continue unless value.hasOwnProperty(prop)
|
||||
try
|
||||
newValue[prop] = @executeSchemaEnforcers("#{keyPath}.#{prop}", value[prop], childSchema)
|
||||
catch error
|
||||
console.warn "Error setting item in object: #{error.message}"
|
||||
for prop, propValue of value
|
||||
childSchema = schema.properties[prop]
|
||||
if childSchema?
|
||||
try
|
||||
newValue[prop] = @executeSchemaEnforcers("#{keyPath}.#{prop}", propValue, childSchema)
|
||||
catch error
|
||||
console.warn "Error setting item in object: #{error.message}"
|
||||
else
|
||||
# Just pass through un-schema'd values
|
||||
newValue[prop] = propValue
|
||||
|
||||
newValue
|
||||
|
||||
'array':
|
||||
@@ -1162,7 +1200,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?
|
||||
|
||||
@@ -32,7 +32,7 @@ class LanguageMode
|
||||
|
||||
return unless commentStartEntry?
|
||||
|
||||
commentEndEntry = atom.config.getAll('editor.commentEnd', {scope}).find (entry) ->
|
||||
commentEndEntry = _.find atom.config.getAll('editor.commentEnd', {scope}), (entry) ->
|
||||
entry.scopeSelector is commentStartEntry.scopeSelector
|
||||
commentStartString = commentStartEntry?.value
|
||||
commentEndString = commentEndEntry?.value
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
path = require 'path'
|
||||
fs = require 'fs-plus'
|
||||
LessCache = require 'less-cache'
|
||||
{Subscriber} = require 'emissary'
|
||||
|
||||
# {LessCache} wrapper used by {ThemeManager} to read stylesheets.
|
||||
module.exports =
|
||||
class LessCompileCache
|
||||
Subscriber.includeInto(this)
|
||||
|
||||
@cacheDir: path.join(require('./coffee-cache').cacheDir, 'less')
|
||||
@cacheDir: path.join(process.env.ATOM_HOME, 'compile-cache', 'less')
|
||||
|
||||
constructor: ({resourcePath, importPaths}) ->
|
||||
@lessSearchPaths = [
|
||||
@@ -35,5 +31,3 @@ class LessCompileCache
|
||||
|
||||
cssForFile: (stylesheetPath, lessContent) ->
|
||||
@cache.cssForFile(stylesheetPath, lessContent)
|
||||
|
||||
destroy: -> @unsubscribe()
|
||||
|
||||
@@ -213,8 +213,7 @@ LinesComponent = React.createClass
|
||||
innerHTML = ""
|
||||
|
||||
scopeStack = []
|
||||
firstTrailingWhitespacePosition = text.search(/\s*$/)
|
||||
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
|
||||
lineIsWhitespaceOnly = line.isOnlyWhitespace()
|
||||
for token in tokens
|
||||
innerHTML += @updateScopeStack(scopeStack, token.scopes)
|
||||
hasIndentGuide = not editor.isMini() and showIndentGuide and (token.hasLeadingWhitespace() or (token.hasTrailingWhitespace() and lineIsWhitespaceOnly))
|
||||
|
||||
@@ -176,7 +176,7 @@ class MenuManager
|
||||
element?.classList.toString().split(' ') ? []
|
||||
|
||||
sortPackagesMenu: ->
|
||||
packagesMenu = @template.find ({label}) -> MenuHelpers.normalizeLabel(label) is 'Packages'
|
||||
packagesMenu = _.find @template, ({label}) -> MenuHelpers.normalizeLabel(label) is 'Packages'
|
||||
return unless packagesMenu?.submenu?
|
||||
|
||||
packagesMenu.submenu.sort (item1, item2) ->
|
||||
|
||||
@@ -7,6 +7,7 @@ fs = require 'fs-plus'
|
||||
Q = require 'q'
|
||||
Grim = require 'grim'
|
||||
|
||||
ServiceHub = require 'service-hub'
|
||||
Package = require './package'
|
||||
ThemePackage = require './theme-package'
|
||||
|
||||
@@ -40,6 +41,7 @@ class PackageManager
|
||||
@loadedPackages = {}
|
||||
@activePackages = {}
|
||||
@packageStates = {}
|
||||
@serviceHub = new ServiceHub
|
||||
|
||||
@packageActivators = []
|
||||
@registerPackageActivator(this, ['atom', 'textmate'])
|
||||
@@ -128,9 +130,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.
|
||||
#
|
||||
|
||||
@@ -159,6 +159,7 @@ class Package
|
||||
if @requireMainModule()
|
||||
@mainModule.activate(atom.packages.getPackageState(@name) ? {})
|
||||
@mainActivated = true
|
||||
@activateServices()
|
||||
catch e
|
||||
console.warn "Failed to activate package named '#{@name}'", e.stack
|
||||
|
||||
@@ -209,6 +210,15 @@ class Package
|
||||
settings.activate() for settings in @settings
|
||||
@settingsActivated = true
|
||||
|
||||
activateServices: ->
|
||||
for name, {versions} of @metadata.providedServices
|
||||
for version, methodName of versions
|
||||
@activationDisposables.add atom.packages.serviceHub.provide(name, version, @mainModule[methodName]())
|
||||
|
||||
for name, {versions} of @metadata.consumedServices
|
||||
for version, methodName of versions
|
||||
@activationDisposables.add atom.packages.serviceHub.consume(name, version, @mainModule[methodName].bind(@mainModule))
|
||||
|
||||
loadKeymaps: ->
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
@keymaps = (["#{atom.packages.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of packagesCache[@name].keymaps)
|
||||
|
||||
@@ -48,7 +48,7 @@ class PaneContainer extends Model
|
||||
deserializeParams: (params) ->
|
||||
params.root = atom.deserializers.deserialize(params.root, container: this)
|
||||
params.destroyEmptyPanes = atom.config.get('core.destroyEmptyPanes')
|
||||
params.activePane = params.root.getPanes().find (pane) -> pane.id is params.activePaneId
|
||||
params.activePane = find params.root.getPanes(), (pane) -> pane.id is params.activePaneId
|
||||
params
|
||||
|
||||
serializeParams: (params) ->
|
||||
@@ -147,7 +147,7 @@ class PaneContainer extends Model
|
||||
find @getPanes(), (pane) -> pane.itemForURI(uri)?
|
||||
|
||||
paneForItem: (item) ->
|
||||
@getPanes().find (pane) -> item in pane.getItems()
|
||||
find @getPanes(), (pane) -> item in pane.getItems()
|
||||
|
||||
saveAll: ->
|
||||
pane.saveItems() for pane in @getPanes()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
_ServiceHub = require('service-hub')
|
||||
|
||||
# Experimental: This class facilitates communication between Atom packages
|
||||
# through semantically-versioned services. If you want your package to provide
|
||||
# an API for other packages to interact with, provide or consume a service via
|
||||
# the global instance of this class available as `atom.services`.
|
||||
#
|
||||
# If you're providing an API for other packages, the most straightforward is to
|
||||
# `provide` a module namespaced under your package's name as follows.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.services.provide "status-bar", "1.0.0",
|
||||
# addRightItem: (item) -> # ...
|
||||
# addLeftItem: (item) -> # ...
|
||||
# ```
|
||||
#
|
||||
# Then other packages can interact with your package by consuming the provided
|
||||
# service. Note that a service consumer can provide an npm-style version range
|
||||
# string to express the required API version of the consumed service. The
|
||||
# callback will be invoked with the service immediately or when the service
|
||||
# becomes available. If multiple services match the provided key-path and
|
||||
# version range, the callback will be invoked multiple times.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.services.consume "status-bar", "^1.0.0", (statusBar) ->
|
||||
# statusBar.addLeftItem(new GrammarChanger)
|
||||
# ```
|
||||
#
|
||||
# You can also provide multiple services end-points under the same namespace by
|
||||
# passing a dot-separated key path. In this example, we also provide a global
|
||||
# reference to the status bar's DOM element so other packages can modify it
|
||||
# directly. Doing this via `atom.services` is superior to querying from the DOM
|
||||
# manually because you can use semantic versioning to indicate when the DOM
|
||||
# structure changes in a breaking way.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.services.provide "status-bar.view", "1.0.0", statusBarElement
|
||||
# ```
|
||||
#
|
||||
# By convention, every package owns its package name in the services namespace.
|
||||
# Your package can provide a service under another package's namespace, but you
|
||||
# should always conform to that package's API. If you want to make additions to
|
||||
# the API, add them under your own namespace.
|
||||
#
|
||||
# When upgrading your package's API, consider retaining previous versions with
|
||||
# shims if at all possible to minimize breakage and to give the ecosystem time
|
||||
# to catch up with your changes.
|
||||
#
|
||||
# You can also apply an inverted pattern, where your package consumes services
|
||||
# under its own namespace. In this pattern, you would define a contract for
|
||||
# services that other packages provide and your package consumes. For example,
|
||||
# say we were adding the ability to add custom completion providers to
|
||||
# autocomplete:
|
||||
#
|
||||
# ```coffee
|
||||
# atom.services.consume "autocomplete", "1.0.0", (provider) ->
|
||||
# addCompletionProvider(provider)
|
||||
# ```
|
||||
#
|
||||
# In this use case, you would want to consume a specific version number rather
|
||||
# than a range. You could consume multiple version numbers to provide backward
|
||||
# compatibility.
|
||||
module.exports =
|
||||
class ServiceHub extends _ServiceHub
|
||||
# Experimental: Provide a service by invoking the callback of all current and
|
||||
# future consumers matching the given key path and version range.
|
||||
#
|
||||
# * `keyPath` A {String} of `.` separated keys indicating the services's
|
||||
# location in the namespace of all services.
|
||||
# * `version` A {String} containing a [semantic version](http://semver.org/)
|
||||
# for the service's API.
|
||||
# * `service` An object exposing the service API.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# provided service.
|
||||
provide: (keyPath, version, service) ->
|
||||
super
|
||||
|
||||
# Experimental: Consume a service by invoking the given callback for all
|
||||
# current and future provided services matching the given key path and version
|
||||
# range.
|
||||
#
|
||||
# * `keyPath` A {String} of `.` separated keys indicating the services's
|
||||
# location in the namespace of all services.
|
||||
# * `versionRange` A {String} containing a [semantic version range](https://www.npmjs.org/doc/misc/semver.html)
|
||||
# that any provided services for the given key path must satisfy.
|
||||
# * `callback` A {Function} to be called with current and future matching
|
||||
# service objects.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# consumer.
|
||||
consume: (keyPath, versionRange, callback) ->
|
||||
super
|
||||
@@ -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
|
||||
|
||||
@@ -266,7 +266,11 @@ class ThemeManager
|
||||
"""
|
||||
atom.notifications.addError(message, dismissable: true)
|
||||
|
||||
userStylesheetContents = @loadStylesheet(userStylesheetPath, true)
|
||||
try
|
||||
userStylesheetContents = @loadStylesheet(userStylesheetPath, true)
|
||||
catch
|
||||
return
|
||||
|
||||
@userStyleSheetDisposable = atom.styles.addStyleSheet(userStylesheetContents, sourcePath: userStylesheetPath, priority: 2)
|
||||
|
||||
loadBaseStylesheets: ->
|
||||
@@ -320,6 +324,7 @@ class ThemeManager
|
||||
detail = error.message
|
||||
|
||||
atom.notifications.addError(message, {detail, dismissable: true})
|
||||
throw error
|
||||
|
||||
removeStylesheet: (stylesheetPath) ->
|
||||
@styleSheetDisposablesBySourcePath[stylesheetPath]?.dispose()
|
||||
|
||||
@@ -9,6 +9,7 @@ idCounter = 1
|
||||
module.exports =
|
||||
class TokenizedLine
|
||||
endOfLineInvisibles: null
|
||||
lineIsWhitespaceOnly: false
|
||||
|
||||
constructor: ({tokens, @lineEnding, @ruleStack, @startBufferColumn, @fold, @tabLength, @indentLevel, @invisibles}) ->
|
||||
@startBufferColumn ?= 0
|
||||
@@ -146,7 +147,7 @@ class TokenizedLine
|
||||
markLeadingAndTrailingWhitespaceTokens: ->
|
||||
firstNonWhitespaceIndex = @text.search(NonWhitespaceRegex)
|
||||
firstTrailingWhitespaceIndex = @text.search(TrailingWhitespaceRegex)
|
||||
lineIsWhitespaceOnly = firstTrailingWhitespaceIndex is 0
|
||||
@lineIsWhitespaceOnly = firstTrailingWhitespaceIndex is 0
|
||||
index = 0
|
||||
for token in @tokens
|
||||
if index < firstNonWhitespaceIndex
|
||||
@@ -202,12 +203,7 @@ class TokenizedLine
|
||||
false
|
||||
|
||||
isOnlyWhitespace: ->
|
||||
if @text == ''
|
||||
true
|
||||
else
|
||||
for token in @tokens
|
||||
return false unless token.isOnlyWhitespace()
|
||||
true
|
||||
@lineIsWhitespaceOnly
|
||||
|
||||
tokenAtIndex: (index) ->
|
||||
@tokens[index]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{find} = require 'underscore-plus'
|
||||
Grim = require 'grim'
|
||||
{Disposable} = require 'event-kit'
|
||||
|
||||
@@ -148,4 +149,4 @@ class ViewRegistry
|
||||
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
|
||||
|
||||
findProvider: (object) ->
|
||||
@providers.find ({modelConstructor}) -> object instanceof modelConstructor
|
||||
find @providers, ({modelConstructor}) -> object instanceof modelConstructor
|
||||
|
||||
@@ -31,8 +31,8 @@ class WindowEventHandler
|
||||
atom.updateAvailable(detail)
|
||||
|
||||
# FIXME: Remove this when deprecations are removed
|
||||
{releaseVersion, releaseNotes} = detail
|
||||
detail = [releaseVersion, releaseNotes]
|
||||
{releaseVersion} = detail
|
||||
detail = [releaseVersion]
|
||||
if workspaceElement = atom.views.getView(atom.workspace)
|
||||
atom.commands.dispatch workspaceElement, "window:update-available", detail
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
function registerRuntimeTranspilers() {
|
||||
// This sets require.extensions['.coffee'].
|
||||
require('coffee-script').register();
|
||||
|
||||
// This redefines require.extensions['.js'].
|
||||
require('../src/6to5').register();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
try {
|
||||
var startTime = Date.now();
|
||||
@@ -5,23 +13,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;
|
||||
@@ -39,7 +30,7 @@ window.onload = function() {
|
||||
|
||||
// Require before the module cache in dev mode
|
||||
if (devMode) {
|
||||
require('coffee-script').register();
|
||||
registerRuntimeTranspilers();
|
||||
}
|
||||
|
||||
ModuleCache = require('../src/module-cache');
|
||||
@@ -58,7 +49,7 @@ window.onload = function() {
|
||||
require('vm-compatibility-layer');
|
||||
|
||||
if (!devMode) {
|
||||
require('coffee-script').register();
|
||||
registerRuntimeTranspilers();
|
||||
}
|
||||
|
||||
require('../src/coffee-cache').register();
|
||||
|
||||
@@ -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 {
|
||||
|
||||