Comparar commits
534 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| eabad3dcef | |||
| 6ad099260e | |||
| ebfd921807 | |||
| 83c77b6e4b | |||
| 654a4392a4 | |||
| 8457c74f2f | |||
| 88366cb5d4 | |||
| c70c819aa2 | |||
| 4ac8aba31f | |||
| 776e431cc5 | |||
| 5a966240b9 | |||
| 27f0c525ac | |||
| 00170804e5 | |||
| d7e5f05f83 | |||
| 3ce641f53b | |||
| 27ca957629 | |||
| 84d0abc52c | |||
| 41c62e8628 | |||
| 1515690302 | |||
| 2be658b894 | |||
| d3e1c004fb | |||
| 62924dfcd1 | |||
| 770e97efff | |||
| 2704d2f15a | |||
| 957e45944a | |||
| 16fd14d295 | |||
| 20daed176b | |||
| 8c11c4a4c6 | |||
| 7cb44b69ef | |||
| d37cfb9042 | |||
| 986753981d | |||
| 970bde9361 | |||
| 7b55946abf | |||
| c74f6bb615 | |||
| 63f2ab3088 | |||
| 742ec6df0d | |||
| 864f9bc2b4 | |||
| 73896d100e | |||
| 193001d793 | |||
| 052f9580f2 | |||
| 2daf70f0e5 | |||
| fca9ed07e6 | |||
| c6fc0d050d | |||
| 6e913c47ef | |||
| a245624211 | |||
| 8af8caca55 | |||
| bbeb4be5b1 | |||
| 449da91216 | |||
| 521647e8ac | |||
| d863638c24 | |||
| 651df12f9b | |||
| 83706647d1 | |||
| 59fb4a839e | |||
| 04e23f581a | |||
| 4574a9e35d | |||
| a2eb4d9303 | |||
| c0a845bc56 | |||
| 1ace5a313c | |||
| 161eb3c3d2 | |||
| 6632a1c63d | |||
| ce5eff100c | |||
| 1bf9e14f9f | |||
| 94f40f0ed9 | |||
| 640881a15e | |||
| ee6c4d7b65 | |||
| a37aeba909 | |||
| 2449fda01d | |||
| b572594f92 | |||
| fbde059748 | |||
| 6084ef52e7 | |||
| a9f4dfc6b7 | |||
| 8032d6dab2 | |||
| 01ec449fce | |||
| e79d66497c | |||
| a205c6d190 | |||
| 2911b395ee | |||
| 64c25f17df | |||
| 9d3082ec95 | |||
| 034a377c5e | |||
| f0fbdc9842 | |||
| 96804096e9 | |||
| e2c41136f3 | |||
| 8b20e2e031 | |||
| 722d8cb48b | |||
| a73e6e5bd0 | |||
| 4cf68ef017 | |||
| b037395551 | |||
| 7a26a16511 | |||
| 30fc3d9e66 | |||
| 7de2ad34aa | |||
| 1bba631ab7 | |||
| cbf4087a3a | |||
| a3d72f5e6a | |||
| aeaa2fad06 | |||
| a219b90eea | |||
| 7086c60e6b | |||
| 0af4c82f36 | |||
| acf5ab816e | |||
| 6aa8c8bab9 | |||
| b5c939dee1 | |||
| 90d9315d45 | |||
| 7de2f57088 | |||
| 1488867063 | |||
| 59d62d48db | |||
| 97c2fc09f0 | |||
| 16d2e41309 | |||
| 13f66fb2ae | |||
| d6a8217e94 | |||
| 8e649e3008 | |||
| 8dffb45fd7 | |||
| c34ce0d2d0 | |||
| 61daf1cc36 | |||
| 1201fb6a5d | |||
| 7a5a329393 | |||
| f447781e01 | |||
| 070d9d0b46 | |||
| 49b4671076 | |||
| 28a0e94bb9 | |||
| ab2c5bfc35 | |||
| 80c64deb21 | |||
| 69af432965 | |||
| e788612ef4 | |||
| 62803efde0 | |||
| 01696b4d11 | |||
| 2c2dc61fa0 | |||
| 66ce001961 | |||
| 3aa6cc827c | |||
| c2304e1124 | |||
| 07f8f0915c | |||
| 7725c78c5e | |||
| 0624720634 | |||
| 64731bff46 | |||
| 878c393e8e | |||
| 84064a811c | |||
| 3c932d6d91 | |||
| a24d1d1af7 | |||
| edb5b43d64 | |||
| ac496e1fa4 | |||
| 103f3f8597 | |||
| 9842baedce | |||
| aaa916f78d | |||
| b463d9d876 | |||
| 7f6a4cccaf | |||
| d5e30e83f6 | |||
| d16c0e9e41 | |||
| bd8ac3bb32 | |||
| 87edff1e42 | |||
| 96f35d3cde | |||
| 7e45ffa4c3 | |||
| 6af69b0fc7 | |||
| 99e02570d1 | |||
| e1f4b7415a | |||
| 823cfcac57 | |||
| de6ccd8c08 | |||
| 2135d3be83 | |||
| 1c3720c160 | |||
| 6c72b13adc | |||
| 1404904d24 | |||
| db243936b4 | |||
| 6e72627e9e | |||
| 3d36ba7ecc | |||
| a7c0d6073f | |||
| f25b468272 | |||
| 2d0fb8ee6b | |||
| d875becc7a | |||
| cb72af63fd | |||
| f7187f1d5a | |||
| 700acdc5a2 | |||
| 18016ae9df | |||
| a30faa5bea | |||
| 05a113bb7a | |||
| f5d4ece9cd | |||
| 3bda37c56c | |||
| 62b52cb70a | |||
| a4fe594441 | |||
| 9d0e46126b | |||
| cb1bb4a691 | |||
| d3a24c3749 | |||
| 092849835e | |||
| b24ade4de5 | |||
| 0f77a2eef9 | |||
| 662c2fc9d3 | |||
| 510b1a7068 | |||
| c4f9914df6 | |||
| 2140ce3beb | |||
| a597bca75e | |||
| 2895aae121 | |||
| 4e20d93f03 | |||
| 1cc4e2e045 | |||
| 9fb427c468 | |||
| a9bd061144 | |||
| 0736b28abf | |||
| 9ac5b67b6e | |||
| 25601d691d | |||
| 0d1c11764b | |||
| 729ff461f1 | |||
| 0360a1918c | |||
| 23f21bcda2 | |||
| 800d65e3de | |||
| 5ce9b3ac55 | |||
| f86191dff8 | |||
| 412793697f | |||
| 3274ef9fb9 | |||
| f8e2231dfc | |||
| 837eaccd16 | |||
| 4f3570b56b | |||
| 8918a42b3b | |||
| bd77a02207 | |||
| eebbb99fc8 | |||
| 2b27c0b440 | |||
| 8e69b0c4a0 | |||
| 532744b4eb | |||
| ddd89ed6d1 | |||
| 5a53e5b96a | |||
| 69f84f7e6d | |||
| e2c65345ab | |||
| f47bcddf10 | |||
| 5e19230809 | |||
| f8961fbd53 | |||
| bef750cb1f | |||
| 4e2f06aec7 | |||
| 02c47ba1ea | |||
| f6cb59be47 | |||
| 397871a012 | |||
| 10239e0466 | |||
| 69ef99481b | |||
| fc20de82ce | |||
| 0232da27f5 | |||
| ba452e2400 | |||
| 9b5b8e7528 | |||
| 6e65947d54 | |||
| 93c5e241f3 | |||
| e0c61136a6 | |||
| c5cc13ddb3 | |||
| fd47c89f9d | |||
| 34ad902cb3 | |||
| 9678418e56 | |||
| 691d6c3b5f | |||
| 431555195a | |||
| b0aa5e6c88 | |||
| b3c2417578 | |||
| 7f882b00f5 | |||
| 3a9aa80914 | |||
| 3af3a0d27e | |||
| 7e415ffdb7 | |||
| e70c696fef | |||
| b2258d9b8a | |||
| 40eab806c4 | |||
| 319455f2da | |||
| 63867ba803 | |||
| 65ffd21574 | |||
| 393552a4b6 | |||
| 444c18be34 | |||
| dca096b8e3 | |||
| 57a03e7884 | |||
| fe1819f587 | |||
| aa157af93e | |||
| 0e58e03de7 | |||
| e011c80b07 | |||
| 9ae007a6d7 | |||
| 9dc59b9807 | |||
| 15689ebfb5 | |||
| 6250419fcb | |||
| 70621afe62 | |||
| 6f29710d88 | |||
| 7b07d7116b | |||
| f175086865 | |||
| c6071a9802 | |||
| ac138c1dc8 | |||
| 85b7261d31 | |||
| d47348e8f9 | |||
| 56df7bdbe3 | |||
| 1ea909d4db | |||
| c748fc49bb | |||
| 3bd1ec08e1 | |||
| caa6f9b06e | |||
| 32045a3f22 | |||
| 736952d0a2 | |||
| 684f15ab89 | |||
| 4238e031da | |||
| a457d8a849 | |||
| 0b3c0fc622 | |||
| a3d82e9414 | |||
| 37165f3293 | |||
| f2507fc9d4 | |||
| 7515fd94ba | |||
| 8cc1029bbf | |||
| 85363f8eaa | |||
| c5b3f18783 | |||
| 7738eeeacc | |||
| c6116468e4 | |||
| 2a2d0b60f7 | |||
| 9a5fddbcbb | |||
| 25c737de56 | |||
| 8ad8be2583 | |||
| f29f8e37d1 | |||
| b922f01257 | |||
| c1ec87c41b | |||
| c8aea97f16 | |||
| c9587a8638 | |||
| 15fc7a8bc5 | |||
| 76eb3b4c72 | |||
| c03d34f535 | |||
| 7cfdcf0c1b | |||
| d3a46b6bc9 | |||
| cc27f2dbb6 | |||
| 54ce852be4 | |||
| 83ad1fe8af | |||
| dcbf730129 | |||
| 39868a2330 | |||
| 5d00ca8bb6 | |||
| 772726ca96 | |||
| 00275d95ec | |||
| 242df788e6 | |||
| 3295b9b0dd | |||
| 2a9c78ef92 | |||
| a896d71948 | |||
| e3e0df7728 | |||
| 0acd3ebd4b | |||
| 82f0a68419 | |||
| 9a95c3acef | |||
| 22eb16352c | |||
| 5355310cc7 | |||
| 9f9ca0a2cf | |||
| 29970acaa9 | |||
| 8c0b9017c2 | |||
| e9890810d3 | |||
| 0e201d539a | |||
| 6a0e7cfb24 | |||
| e13defc0f7 | |||
| 3326cf357f | |||
| 9c78b9832b | |||
| 662b8b30a1 | |||
| caa15e42ac | |||
| 75410e07da | |||
| 72727c2a81 | |||
| adaee84933 | |||
| d761684212 | |||
| 307d4984a2 | |||
| 09711d5a88 | |||
| 2e1239345e | |||
| 8d6325b081 | |||
| 8a8144defa | |||
| ed867666ed | |||
| 84ff28ee69 | |||
| 97f032c66f | |||
| 18ea3bcb99 | |||
| 8da4ed147b | |||
| edd1f46ad2 | |||
| cfb1501720 | |||
| 17ceb34140 | |||
| c551b58490 | |||
| 6c736ace1a | |||
| 4ff2429f71 | |||
| 01499fe674 | |||
| c4d26f6405 | |||
| bd93f243dc | |||
| 1663315323 | |||
| ffb041a160 | |||
| f5f9de1bf8 | |||
| 2f47e8a462 | |||
| 119b446c3b | |||
| c2042ad74a | |||
| 361f8ec770 | |||
| 48a5123202 | |||
| 0f1d155685 | |||
| d3a6e79428 | |||
| 5f7f5b5367 | |||
| 2fe647c950 | |||
| 683f8e06f8 | |||
| bc4173f856 | |||
| 8443f0e2b9 | |||
| b9e2c47321 | |||
| 8099c46c8e | |||
| a3f046b948 | |||
| 911ca0d846 | |||
| 88d1ba2271 | |||
| bbfd9b8178 | |||
| 3818dee175 | |||
| 6d34de68ac | |||
| 10fb929a1b | |||
| d1a610dcb6 | |||
| 17364cd528 | |||
| c67f8493e0 | |||
| 1a90588752 | |||
| 4f4b840f67 | |||
| 77158738e6 | |||
| 27d0743edc | |||
| 9aca6a4489 | |||
| 866fd69008 | |||
| d9a942d6c6 | |||
| 6f0920c04b | |||
| 2e4893c786 | |||
| 5871bee791 | |||
| adea792b78 | |||
| 36f1ebfb6f | |||
| a45e38cd8a | |||
| 46b95318a1 | |||
| 50086df804 | |||
| 52e049bedc | |||
| a6640f6da7 | |||
| 2f82fb2ceb | |||
| c50c25b2d4 | |||
| 89733300a5 | |||
| b9658e23f4 | |||
| 1757ff18f2 | |||
| a26cb6023e | |||
| ccd631a934 | |||
| ab980d78d2 | |||
| f5951425c3 | |||
| 74992b1397 | |||
| 4b07b803b3 | |||
| 94f871e37e | |||
| 4a8a741ef0 | |||
| 162d5a0e0d | |||
| a22cf44b49 | |||
| 10bad42e7a | |||
| 8a6753905c | |||
| 73354f56f4 | |||
| 43c9e21f1d | |||
| ba21f0b0d8 | |||
| 0ee953fe26 | |||
| a68b9a793f | |||
| fb4361e976 | |||
| f9d866fa32 | |||
| 0c4da92d6b | |||
| 6377c7ebf4 | |||
| 08ecba72e6 | |||
| 38b286f989 | |||
| df7f816c88 | |||
| ca1220a682 | |||
| 9bb6c3cc3d | |||
| 4a8ac85ffb | |||
| c4177aba3e | |||
| 3206fdce9e | |||
| 0346e5809a | |||
| 99704517bb | |||
| 783ef730e2 | |||
| e81db5d706 | |||
| a0f75f1639 | |||
| d0893ccdaf | |||
| a9c7842a50 | |||
| 544c759fd1 | |||
| 759dbc061d | |||
| 56c9f75e8c | |||
| 635f288050 | |||
| cc8b7b13b3 | |||
| 4020ed1535 | |||
| e999ef00e7 | |||
| f16ea63a95 | |||
| 754f995c91 | |||
| ac8a67822e | |||
| 1c7926dea6 | |||
| 2bd8015a9d | |||
| 09e8aa0571 | |||
| 364e06483c | |||
| 2d07d6662c | |||
| 3d53749771 | |||
| eeadd823e6 | |||
| 8a5bd357cd | |||
| 79ee887c9a | |||
| 37d0a7f7e5 | |||
| ed4324dedc | |||
| d2da914151 | |||
| ca39e7f7de | |||
| 7bf2b7237e | |||
| c264855f87 | |||
| a5f2a44a45 | |||
| 4960a63bd8 | |||
| 42621805a7 | |||
| fed55b8896 | |||
| 73daa4bb74 | |||
| 92546c60b3 | |||
| 2fa91e5dfb | |||
| aac0913b8b | |||
| acc75ca859 | |||
| 8eb4e13df8 | |||
| 087d9c1da6 | |||
| 18336076a8 | |||
| 7fee5f5f25 | |||
| c2f04a00d2 | |||
| cc927123f9 | |||
| 97b426429b | |||
| 3686530943 | |||
| 621ef450da | |||
| 1e08bcd634 | |||
| ede468d4c9 | |||
| 1278f88dd9 | |||
| 6faf3bd827 | |||
| 92a2b52f53 | |||
| 8135458670 | |||
| 160a1cd690 | |||
| 2d3a133790 | |||
| af5384cd51 | |||
| 27423fcc15 | |||
| cdb5fe15d2 | |||
| 608c2b5354 | |||
| 121350f8e5 | |||
| 7bcc91e7d2 | |||
| b192622ad8 | |||
| 778e6f4492 | |||
| 8614777af4 | |||
| cce49da18c | |||
| 66bfefc09d | |||
| 29e883cf36 | |||
| 381d5b91b2 | |||
| b744997201 | |||
| 0357872558 | |||
| 844186f5fc | |||
| 0a818cfdd7 | |||
| cd1a17fb0a | |||
| 9abab27ba7 | |||
| 0faff626d1 | |||
| c355ade477 | |||
| 18818c9ba5 | |||
| b4ca3e46e6 | |||
| 262ba6be20 | |||
| 50c5d12ced | |||
| d6d51155ac | |||
| b100310764 | |||
| 7ac3e6d9a5 | |||
| 2742995541 | |||
| b8c0c125a2 | |||
| d78eb3d142 | |||
| 36769c35fc | |||
| e6c0c38894 | |||
| 1f77450f7e | |||
| c4204eb9e9 | |||
| 9a393a6ec9 | |||
| bbe02fc6b0 | |||
| 9fbc6d4f02 | |||
| e620121953 | |||
| 41c8878769 | |||
| d2834fa651 |
@@ -13,5 +13,3 @@ debug.log
|
||||
docs/output
|
||||
docs/includes
|
||||
spec/fixtures/evil-files/
|
||||
resources/linux/Atom.desktop
|
||||
resources/linux/debian/control
|
||||
|
||||
@@ -21,6 +21,10 @@ Install the [Atom chocolatey package](https://chocolatey.org/packages/Atom).
|
||||
3. Run `cinst Atom`
|
||||
4. In the future run `cup Atom` to upgrade to the latest release.
|
||||
|
||||
You can also download a `.zip` file from the [releases page](https://github.com/atom/atom/releases/latest).
|
||||
The Windows version does not currently automatically update so you will need to
|
||||
manually upgrade to future releases by re-downloading the `.zip` file.
|
||||
|
||||
## Building
|
||||
|
||||
* [Linux](docs/build-instructions/linux.md)
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.77.0"
|
||||
"atom-package-manager": "0.91.0"
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -69,6 +69,11 @@ 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"
|
||||
|
||||
if [ ! -d "$DOT_ATOM_DIR" ]; then
|
||||
mkdir -p "$DOT_ATOM_DIR"
|
||||
fi
|
||||
|
||||
: ${TMPDIR:=/tmp}
|
||||
|
||||
@@ -79,9 +84,9 @@ elif [ $OS == 'Linux' ]; then
|
||||
exit $?
|
||||
else
|
||||
(
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$TMPDIR/atom-nohup.out" 2>&1
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$DOT_ATOM_DIR/nohup.out" 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
cat "$TMPDIR/atom-nohup.out"
|
||||
cat "$DOT_ATOM_DIR/nohup.out"
|
||||
exit $?
|
||||
fi
|
||||
) &
|
||||
|
||||
@@ -40,7 +40,10 @@ module.exports = (grunt) ->
|
||||
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
installDir = grunt.option('install-dir')
|
||||
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
|
||||
|
||||
home = if process.platform is 'win32' then process.env.USERPROFILE else process.env.HOME
|
||||
atomShellDownloadDir = path.join(home, '.atom', 'atom-shell')
|
||||
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
if process.platform is 'win32'
|
||||
@@ -93,6 +96,8 @@ module.exports = (grunt) ->
|
||||
csonConfig =
|
||||
options:
|
||||
rootObject: true
|
||||
cachePath: path.join(home, '.atom', 'compile-cache', 'grunt-cson')
|
||||
|
||||
glob_to_multiple:
|
||||
expand: true
|
||||
src: [
|
||||
@@ -139,12 +144,7 @@ module.exports = (grunt) ->
|
||||
|
||||
coffeelint:
|
||||
options:
|
||||
no_empty_param_list:
|
||||
level: 'error'
|
||||
max_line_length:
|
||||
level: 'ignore'
|
||||
indentation:
|
||||
level: 'ignore'
|
||||
configFile: 'coffeelint.json'
|
||||
src: [
|
||||
'dot-atom/**/*.coffee'
|
||||
'exports/**/*.coffee'
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git",
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git#cfb99aa99811d52687969532bd5a98011ed95bfe",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"grunt-cson": "0.8.0",
|
||||
"grunt-cson": "0.10.0",
|
||||
"grunt-download-atom-shell": "~0.8.0",
|
||||
"grunt-lesslint": "0.13.0",
|
||||
"grunt-markdown": "~0.4.0",
|
||||
@@ -27,15 +27,15 @@
|
||||
"json-front-matter": "~0.1.3",
|
||||
"legal-eagle": "~0.4.0",
|
||||
"minidump": "~0.7",
|
||||
"read-package-json": "1.1.8",
|
||||
"normalize-package-data": "0.2.12",
|
||||
"npm": "~1.4.5",
|
||||
"rcedit": "~0.1.2",
|
||||
"read-package-json": "1.1.8",
|
||||
"request": "~2.27.0",
|
||||
"rimraf": "~2.2.2",
|
||||
"runas": "0.5.x",
|
||||
"runas": "~1.0.1",
|
||||
"underscore-plus": "1.x",
|
||||
"unzip": "~0.1.9",
|
||||
"vm-compatibility-layer": "~0.1.0",
|
||||
"npm": "~1.4.5"
|
||||
"vm-compatibility-layer": "~0.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ module.exports = (grunt) ->
|
||||
mkdir path.dirname(buildDir)
|
||||
|
||||
if process.platform is 'darwin'
|
||||
cp 'atom-shell/Atom.app', shellAppDir
|
||||
cp 'atom-shell/Atom.app', shellAppDir, filter: /default_app/
|
||||
else
|
||||
cp 'atom-shell', shellAppDir
|
||||
cp 'atom-shell', shellAppDir, filter: /default_app/
|
||||
|
||||
mkdir appDir
|
||||
|
||||
@@ -45,29 +45,45 @@ module.exports = (grunt) ->
|
||||
path.join('git-utils', 'deps')
|
||||
path.join('oniguruma', 'deps')
|
||||
path.join('less', 'dist')
|
||||
path.join('less', 'test')
|
||||
path.join('bootstrap', 'docs')
|
||||
path.join('bootstrap', 'examples')
|
||||
path.join('bootstrap', '_config.yml')
|
||||
path.join('bootstrap', '_includes')
|
||||
path.join('bootstrap', '_layouts')
|
||||
path.join('npm', 'doc')
|
||||
path.join('npm', 'html')
|
||||
path.join('npm', 'man')
|
||||
path.join('npm', 'node_modules', '.bin', 'beep')
|
||||
path.join('npm', 'node_modules', '.bin', 'clear')
|
||||
path.join('npm', 'node_modules', '.bin', 'starwars')
|
||||
path.join('pegjs', 'examples')
|
||||
path.join('plist', 'tests')
|
||||
path.join('xmldom', 'test')
|
||||
path.join('combined-stream', 'test')
|
||||
path.join('delayed-stream', 'test')
|
||||
path.join('domhandler', 'test')
|
||||
path.join('fstream-ignore', 'test')
|
||||
path.join('harmony-collections', 'test')
|
||||
path.join('lru-cache', 'test')
|
||||
path.join('minimatch', 'test')
|
||||
path.join('normalize-package-data', 'test')
|
||||
path.join('npm', 'test')
|
||||
path.join('jasmine-reporters', 'ext')
|
||||
path.join('jasmine-node', 'node_modules', 'gaze')
|
||||
path.join('jasmine-node', 'spec')
|
||||
path.join('node_modules', 'nan')
|
||||
path.join('build', 'binding.Makefile')
|
||||
path.join('build', 'config.gypi')
|
||||
path.join('build', 'gyp-mac-tool')
|
||||
path.join('build', 'Makefile')
|
||||
path.join('build', 'Release', 'obj.target')
|
||||
path.join('build', 'Release', 'obj')
|
||||
path.join('build', 'Release', '.deps')
|
||||
path.join('vendor', 'apm')
|
||||
path.join('resources', 'mac')
|
||||
path.join('resources', 'win')
|
||||
|
||||
# These are only require in dev mode when the grammar isn't precompiled
|
||||
path.join('atom-keymap', 'node_modules', 'loophole')
|
||||
path.join('atom-keymap', 'node_modules', 'pegjs')
|
||||
path.join('atom-keymap', 'node_modules', '.bin', 'pegjs')
|
||||
path.join('snippets', 'node_modules', 'loophole')
|
||||
path.join('snippets', 'node_modules', 'pegjs')
|
||||
path.join('snippets', 'node_modules', '.bin', 'pegjs')
|
||||
|
||||
'.DS_Store'
|
||||
'.jshintrc'
|
||||
'.npmignore'
|
||||
'.pairs'
|
||||
'.travis.yml'
|
||||
]
|
||||
ignoredPaths = ignoredPaths.map (ignoredPath) -> _.escapeRegExp(ignoredPath)
|
||||
|
||||
@@ -75,21 +91,56 @@ module.exports = (grunt) ->
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('spellchecker', 'vendor', 'hunspell') + path.sep)}.*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('build', 'Release') + path.sep)}.*\\.pdb"
|
||||
|
||||
# Ignore *.cc and *.h files from native modules
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('ctags', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('git-utils', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('keytar', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('nslog', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('oniguruma', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('pathwatcher', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('runas', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('scrollbar-style', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('spellchecker', 'src') + path.sep)}.*\\.(cc|h)*"
|
||||
|
||||
# Ignore build files
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.sep)}binding\\.gyp$"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.sep)}.+\\.target.mk$"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.sep)}linker\\.lock$"
|
||||
ignoredPaths.push "#{_.escapeRegExp(path.join('build', 'Release') + path.sep)}.+\\.node\\.dSYM"
|
||||
|
||||
# Hunspell dictionaries are only not needed on OS X.
|
||||
if process.platform is 'darwin'
|
||||
ignoredPaths.push path.join('spellchecker', 'vendor', 'hunspell_dictionaries')
|
||||
ignoredPaths = ignoredPaths.map (ignoredPath) -> "(#{ignoredPath})"
|
||||
|
||||
testFolderPattern = new RegExp("#{_.escapeRegExp(path.sep)}te?sts?#{_.escapeRegExp(path.sep)}")
|
||||
exampleFolderPattern = new RegExp("#{_.escapeRegExp(path.sep)}examples?#{_.escapeRegExp(path.sep)}")
|
||||
benchmarkFolderPattern = new RegExp("#{_.escapeRegExp(path.sep)}benchmarks?#{_.escapeRegExp(path.sep)}")
|
||||
|
||||
nodeModulesFilter = new RegExp(ignoredPaths.join('|'))
|
||||
filterNodeModule = (pathToCopy) ->
|
||||
return true if benchmarkFolderPattern.test(pathToCopy)
|
||||
|
||||
pathToCopy = path.resolve(pathToCopy)
|
||||
nodeModulesFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy)
|
||||
|
||||
packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(cson|coffee)$)")
|
||||
filterPackage = (pathToCopy) ->
|
||||
return true if benchmarkFolderPattern.test(pathToCopy)
|
||||
|
||||
pathToCopy = path.resolve(pathToCopy)
|
||||
packageFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy)
|
||||
|
||||
for directory in nonPackageDirectories
|
||||
cp directory, path.join(appDir, directory), filter: nodeModulesFilter
|
||||
cp directory, path.join(appDir, directory), filter: filterNodeModule
|
||||
|
||||
for directory in packageDirectories
|
||||
cp directory, path.join(appDir, directory), filter: packageFilter
|
||||
cp directory, path.join(appDir, directory), filter: filterPackage
|
||||
|
||||
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: nodeModulesFilter
|
||||
cp 'apm', path.join(appDir, 'apm'), filter: filterNodeModule
|
||||
|
||||
if process.platform is 'darwin'
|
||||
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
|
||||
@@ -97,9 +148,6 @@ module.exports = (grunt) ->
|
||||
grunt.file.copy(sourcePath, path.resolve(appDir, '..', subDirectory, filename))
|
||||
|
||||
if process.platform is 'win32'
|
||||
cp path.join('resources', 'win', 'msvcp100.dll'), path.join(shellAppDir, 'msvcp100.dll')
|
||||
cp path.join('resources', 'win', 'msvcr100.dll'), path.join(shellAppDir, 'msvcr100.dll')
|
||||
|
||||
# Set up chocolatey ignore and gui files
|
||||
fs.writeFileSync path.join(appDir, 'apm', 'node_modules', 'atom-package-manager', 'bin', 'node.exe.ignore'), ''
|
||||
fs.writeFileSync path.join(appDir, 'node_modules', 'symbols-view', 'vendor', 'ctags-win32.exe.ignore'), ''
|
||||
|
||||
@@ -4,17 +4,13 @@ _ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
runas = null
|
||||
|
||||
fillTemplate = (filePath, data) ->
|
||||
template = _.template(String(fs.readFileSync(filePath + '.in')))
|
||||
filled = template(data)
|
||||
fs.writeFileSync(filePath, filled)
|
||||
|
||||
module.exports = (grunt) ->
|
||||
{cp, mkdir, rm} = require('./task-helpers')(grunt)
|
||||
|
||||
grunt.registerTask 'install', 'Install the built application', ->
|
||||
installDir = grunt.config.get('atom.installDir')
|
||||
shellAppDir = grunt.config.get('atom.shellAppDir')
|
||||
|
||||
if process.platform is 'win32'
|
||||
runas ?= require 'runas'
|
||||
copyFolder = path.resolve 'script', 'copy-folder.cmd'
|
||||
@@ -32,7 +28,6 @@ module.exports = (grunt) ->
|
||||
shareDir = path.join(installDir, 'share', 'atom')
|
||||
|
||||
iconName = path.join(shareDir,'resources','app','resources','atom.png')
|
||||
desktopFile = path.join('resources', 'linux', 'Atom.desktop')
|
||||
|
||||
mkdir binDir
|
||||
cp 'atom.sh', path.join(binDir, 'atom')
|
||||
@@ -42,13 +37,17 @@ module.exports = (grunt) ->
|
||||
|
||||
# Create Atom.desktop if installation not in temporary folder
|
||||
tmpDir = if process.env.TMPDIR? then process.env.TMPDIR else '/tmp'
|
||||
desktopInstallFile = path.join(installDir,'share','applications','Atom.desktop')
|
||||
if installDir.indexOf(tmpDir) isnt 0
|
||||
mkdir path.dirname(desktopInstallFile)
|
||||
desktopFile = path.join('resources', 'linux', 'Atom.desktop.in')
|
||||
desktopInstallFile = path.join(installDir, 'share', 'applications', 'Atom.desktop')
|
||||
|
||||
{description} = grunt.file.readJSON('package.json')
|
||||
installDir = path.join(installDir,'.') # To prevent "Exec=/usr/local//share/atom/atom"
|
||||
fillTemplate(desktopFile, {description, installDir, iconName})
|
||||
cp desktopFile, desktopInstallFile
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'atom.png')
|
||||
installDir = path.join(installDir, '.') # To prevent "Exec=/usr/local//share/atom/atom"
|
||||
template = _.template(String(fs.readFileSync(desktopFile)))
|
||||
filled = template({description, installDir, iconName})
|
||||
|
||||
grunt.file.write(desktopInstallFile, filled)
|
||||
|
||||
# Create relative symbol link for apm.
|
||||
process.chdir(binDir)
|
||||
|
||||
@@ -2,14 +2,17 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
fillTemplate = (filePath, data) ->
|
||||
template = _.template(String(fs.readFileSync(filePath + '.in')))
|
||||
filled = template(data)
|
||||
fs.writeFileSync(filePath, filled)
|
||||
|
||||
module.exports = (grunt) ->
|
||||
{spawn} = require('./task-helpers')(grunt)
|
||||
|
||||
fillTemplate = (filePath, data) ->
|
||||
template = _.template(String(fs.readFileSync("#{filePath}.in")))
|
||||
filled = template(data)
|
||||
|
||||
outputPath = path.join(grunt.config.get('atom.buildDir'), path.basename(filePath))
|
||||
grunt.file.write(outputPath, filled)
|
||||
outputPath
|
||||
|
||||
grunt.registerTask 'mkdeb', 'Create debian package', ->
|
||||
done = @async()
|
||||
|
||||
@@ -27,13 +30,11 @@ module.exports = (grunt) ->
|
||||
iconName = 'atom'
|
||||
data = {name, version, description, section, arch, maintainer, installDir, iconName}
|
||||
|
||||
control = path.join('resources', 'linux', 'debian', 'control')
|
||||
fillTemplate(control, data)
|
||||
desktop = path.join('resources', 'linux', 'Atom.desktop')
|
||||
fillTemplate(desktop, data)
|
||||
controlFilePath = fillTemplate(path.join('resources', 'linux', 'debian', 'control'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'Atom.desktop'), data)
|
||||
icon = path.join('resources', 'atom.png')
|
||||
buildDir = grunt.config.get('atom.buildDir')
|
||||
|
||||
cmd = path.join('script', 'mkdeb')
|
||||
args = [version, arch, control, desktop, icon, buildDir]
|
||||
args = [version, arch, controlFilePath, desktopFilePath, icon, buildDir]
|
||||
spawn({cmd, args}, done)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
path = require 'path'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
grunt.registerTask 'output-build-filetypes', 'Log counts for each filetype in the built application', ->
|
||||
shellAppDir = grunt.config.get('atom.shellAppDir')
|
||||
|
||||
types = {}
|
||||
grunt.file.recurse shellAppDir, (absolutePath, rootPath, relativePath, fileName) ->
|
||||
extension = path.extname(fileName) or fileName
|
||||
types[extension] ?= 0
|
||||
types[extension]++
|
||||
|
||||
extensions = Object.keys(types).sort (extension1, extension2) ->
|
||||
diff = types[extension2] - types[extension1]
|
||||
if diff is 0
|
||||
extension1.toLowerCase().localeCompare(extension2.toLowerCase())
|
||||
else
|
||||
diff
|
||||
|
||||
extensions.forEach (extension) ->
|
||||
grunt.log.error "#{extension}: #{types[extension]}"
|
||||
@@ -9,10 +9,12 @@ module.exports = (grunt) ->
|
||||
['atom-dark-ui', 'atom-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', 'solarized-dark-syntax']
|
||||
['atom-light-ui', 'base16-tomorrow-dark-theme']
|
||||
['atom-light-ui', 'base16-tomorrow-light-theme']
|
||||
]
|
||||
|
||||
directory = path.join(grunt.config.get('atom.appDir'), 'less-compile-cache')
|
||||
|
||||
@@ -45,8 +45,8 @@ module.exports = (grunt) ->
|
||||
|
||||
strings =
|
||||
CompanyName: 'GitHub, Inc.'
|
||||
FileDescription: 'The hackable editor'
|
||||
LegalCopyright: 'Copyright (C) 2013 GitHub, Inc. All rights reserved'
|
||||
FileDescription: 'Atom'
|
||||
LegalCopyright: 'Copyright (C) 2014 GitHub, Inc. All rights reserved'
|
||||
ProductName: 'Atom'
|
||||
ProductVersion: version
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ module.exports = (grunt) ->
|
||||
grunt.fatal("Cannot copy non-existent #{source.cyan} to #{destination.cyan}")
|
||||
|
||||
copyFile = (sourcePath, destinationPath) ->
|
||||
return if filter?.test(sourcePath)
|
||||
return if filter?(sourcePath) or filter?.test?(sourcePath)
|
||||
|
||||
stats = fs.lstatSync(sourcePath)
|
||||
if stats.isSymbolicLink()
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"indentation": {
|
||||
"level": "ignore"
|
||||
},
|
||||
"max_line_length": {
|
||||
"level": "ignore"
|
||||
},
|
||||
"no_empty_param_list": {
|
||||
"level": "error"
|
||||
},
|
||||
"no_unnecessary_fat_arrows": {
|
||||
"level": "ignore"
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,10 @@ All requests that take parameters require `application/json`.
|
||||
|
||||
#### GET /api/packages
|
||||
|
||||
Parameters:
|
||||
|
||||
- **page** (optional)
|
||||
|
||||
Returns a list of all packages in the following format:
|
||||
```json
|
||||
[
|
||||
@@ -44,6 +48,15 @@ Returns a list of all packages in the following format:
|
||||
]
|
||||
```
|
||||
|
||||
Results are paginated 30 at a time, and links to the next and last pages are
|
||||
provided in the `Link` header:
|
||||
|
||||
```
|
||||
Link: <https://www.atom.io/api/packages?page=1>; rel="self",
|
||||
<https://www.atom.io/api/packages?page=41>; rel="last",
|
||||
<https://www.atom.io/api/packages?page=2>; rel="next"
|
||||
```
|
||||
|
||||
### Showing package details
|
||||
|
||||
#### GET /api/packages/:package_name
|
||||
|
||||
@@ -6,38 +6,70 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
|
||||
|
||||
* OS with 64-bit or 32-bit architecture
|
||||
* C++ toolchain
|
||||
* on Ubuntu/Debian: `sudo apt-get install build-essential`
|
||||
* on Fedora: `sudo yum --assumeyes install make gcc gcc-c++ glibc-devel`
|
||||
* [node.js](http://nodejs.org/download/) v0.10.x
|
||||
* [Ubuntu/Debian/Mint instructions](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os)
|
||||
* [Fedora instructions](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#fedora)
|
||||
* [npm](http://www.npmjs.org/) v1.4.x
|
||||
* `npm` comes with node.js so no explicit installation is needed here.
|
||||
* You can check `npm` 1.4 or above is installed by running `npm -v`.
|
||||
* libgnome-keyring-dev
|
||||
* on Ubuntu/Debian: `sudo apt-get install libgnome-keyring-dev`
|
||||
* on Fedora: `sudo yum --assumeyes install libgnome-keyring-devel`
|
||||
* on other distributions refer to the manual on how to install packages
|
||||
* `npm config set python /usr/bin/python2 -g` to ensure that gyp uses Python 2
|
||||
* This command may require `sudo` depending on how you have
|
||||
[configured npm](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
|
||||
* Git
|
||||
* on Ubuntu/Debian: `sudo apt-get install git`
|
||||
* on Fedora: `sudo yum install git-core`
|
||||
* [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 -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).
|
||||
* development headers for [GNOME Keyring](https://wiki.gnome.org/Projects/GnomeKeyring)
|
||||
|
||||
### Ubuntu / Debian
|
||||
|
||||
* `sudo apt-get install build-essential git libgnome-keyring-dev`
|
||||
* Instructions for [Node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
|
||||
|
||||
### Fedora
|
||||
|
||||
* `sudo yum --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel`
|
||||
* Instructions for [Node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#fedora).
|
||||
|
||||
### Arch
|
||||
|
||||
* `sudo pacman -S base-devel git nodejs libgnome-keyring`
|
||||
* `export PYTHON=/usr/bin/python2` before building Atom.
|
||||
|
||||
## Instructions
|
||||
|
||||
```sh
|
||||
git clone https://github.com/atom/atom
|
||||
cd atom
|
||||
script/build # Creates application at $TMPDIR/atom-build/Atom
|
||||
sudo script/grunt install # Installs command to /usr/local/bin/atom
|
||||
script/grunt mkdeb # Generates a .deb package at $TMPDIR/atom-build
|
||||
```
|
||||
If you have problems with permissions don't forget to prefix with `sudo`
|
||||
|
||||
From the cloned repository directory:
|
||||
|
||||
1. Build:
|
||||
|
||||
```sh
|
||||
$ script/build
|
||||
```
|
||||
This will create the atom application at `$TMPDIR/atom-build/Atom`.
|
||||
2. Install the `atom` and `apm` commands to `/usr/local/bin` by executing:
|
||||
|
||||
```sh
|
||||
$ sudo script/grunt install
|
||||
```
|
||||
3. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`:
|
||||
|
||||
```sh
|
||||
$ script/grunt mkdeb
|
||||
```
|
||||
|
||||
Use the newly installed atom by restarting any running atom instances.
|
||||
|
||||
## Advanced Options
|
||||
|
||||
### Custom install directory
|
||||
|
||||
```sh
|
||||
sudo script/grunt install --install-dir /install/atom/here
|
||||
```
|
||||
|
||||
### Custom build directory
|
||||
|
||||
```sh
|
||||
script/build --build-dir /build/atom/here
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
### Exception: "TypeError: Unable to watch path"
|
||||
|
||||
If you get following error with a big traceback right after Atom starts:
|
||||
@@ -64,7 +96,7 @@ See also https://github.com/atom/atom/issues/2082.
|
||||
### /usr/bin/env: node: No such file or directory
|
||||
|
||||
If you get this notice when attempting to `script/build`, you either do not
|
||||
have nodejs installed, or node isn't identified as nodejs on your machine.
|
||||
have Node.js installed, or node isn't identified as Node.js on your machine.
|
||||
If it's the latter, entering `sudo ln -s /usr/bin/nodejs /usr/bin/node` into
|
||||
your terminal may fix the issue.
|
||||
|
||||
|
||||
@@ -35,10 +35,14 @@
|
||||
|
||||
## Why do I have to use GitHub for Windows?
|
||||
|
||||
You don't, You can use your existing Git! GitHub for Windows's Git Shell is just
|
||||
easier to set up. You need to have Posix tools in your `%PATH%` (i.e. `grep`,
|
||||
`sed`, et al.), which isn't the default configuration when you install Git. To
|
||||
fix this, you probably need to fiddle with your system PATH.
|
||||
You don't. You can use your existing Git! GitHub for Windows's Git Shell is just
|
||||
easier to set up.
|
||||
|
||||
If you _prefer_ using your existing Git installation, make sure git's cmd directory is in your PATH env variable (e.g. `C:\Program Files (x86)\Git\cmd`) before you open your powershell or command window.
|
||||
Note that you may have to open your command window as administrator. For powershell that doesn't seem to always be the case, though.
|
||||
|
||||
If none of this works, do install Github for Windows and use its Git shell. Makes life easier.
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -62,5 +66,24 @@ fix this, you probably need to fiddle with your system PATH.
|
||||
* https://github.com/TooTallNate/node-gyp/issues/297
|
||||
* https://code.google.com/p/gyp/issues/detail?id=393
|
||||
|
||||
* `script/build` stops at installing runas with 'Failed at the runas@0.5.4 install script.'
|
||||
|
||||
See the next item.
|
||||
|
||||
* `error MSB8020: The build tools for Visual Studio 2010 (Platform Toolset = 'v100') cannot be found.`
|
||||
|
||||
* If you're building atom with Visual Studio 2013 try executing the following
|
||||
command in your Git shell and then re-run `script/build`:
|
||||
|
||||
```
|
||||
$env:GYP_MSVS_VERSION=2013
|
||||
```
|
||||
|
||||
* Other `node-gyp` errors on first build attempt, even though the right node and python versions are installed.
|
||||
* Do try the build command one more time, as experience shows it often works on second try in many of these cases.
|
||||
|
||||
|
||||
### Windows build error reports in atom/atom
|
||||
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Awindows&type=Issues) to get a list of reports about build errors on Windows.
|
||||
* If all fails, use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Awindows&type=Issues) to get a list of reports about build errors on Windows, and see if yours has already been reported.
|
||||
|
||||
* If it hasn't, please open a new issue with your Windows version 32/64bit and a print/screenshot of your build output, incl. the node and python versions.
|
||||
|
||||
@@ -227,15 +227,16 @@ or one of its parents has the `tree-view` class applied to it.
|
||||
|
||||
You can also add separators and submenus to your context menus. To add a
|
||||
submenu, pass in another object instead of a command. To add a separator, use
|
||||
`-` for the name and command of the item.
|
||||
`-` for the command of the item.
|
||||
|
||||
```coffeescript
|
||||
'context-menu':
|
||||
'.workspace':
|
||||
'Inspect Element': 'core:inspect'
|
||||
'-': '-'
|
||||
'Separator': '-'
|
||||
'Text':
|
||||
'Select All': 'core:select-all'
|
||||
'Another Separator': '-'
|
||||
'Deleted Selected Text': 'core:delete'
|
||||
```
|
||||
|
||||
|
||||
@@ -15,10 +15,15 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
module.exports.$ = $
|
||||
module.exports.$$ = $$
|
||||
module.exports.$$$ = $$$
|
||||
module.exports.EditorView = require '../src/editor-view'
|
||||
if atom.config.get('core.useReactMiniEditors')
|
||||
module.exports.EditorView = require '../src/react-editor-view'
|
||||
else
|
||||
module.exports.EditorView = require '../src/editor-view'
|
||||
module.exports.ScrollView = require '../src/scroll-view'
|
||||
module.exports.SelectListView = require '../src/select-list-view'
|
||||
module.exports.Task = require '../src/task'
|
||||
module.exports.View = View
|
||||
module.exports.WorkspaceView = require '../src/workspace-view'
|
||||
module.exports.Workspace = require '../src/workspace'
|
||||
module.exports.React = require 'react-atom-fork'
|
||||
module.exports.Reactionary = require 'reactionary-atom-fork'
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
# Sublime Parity
|
||||
'tab': 'editor:indent'
|
||||
'enter': 'editor:newline'
|
||||
'num-enter': 'editor:newline'
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'ctrl-K': 'editor:delete-line'
|
||||
|
||||
@@ -27,7 +26,6 @@
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
'enter': 'native!'
|
||||
'num-enter': 'native!'
|
||||
'backspace': 'native!'
|
||||
'shift-backspace': 'native!'
|
||||
'delete': 'native!'
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
'cmd-O': 'application:open-dev'
|
||||
'cmd-alt-ctrl-s': 'application:run-all-specs'
|
||||
'enter': 'core:confirm'
|
||||
'num-enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'body':
|
||||
# Atom Specific
|
||||
'enter': 'core:confirm'
|
||||
'num-enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
@@ -26,6 +25,7 @@
|
||||
'ctrl-w': 'core:close'
|
||||
'ctrl-z': 'core:undo'
|
||||
'ctrl-y': 'core:redo'
|
||||
'ctrl-shift-z': 'core:redo'
|
||||
'ctrl-x': 'core:cut'
|
||||
'ctrl-c': 'core:copy'
|
||||
'ctrl-v': 'core:paste'
|
||||
@@ -95,6 +95,7 @@
|
||||
'ctrl-alt-shift-p': 'editor:log-cursor-scope'
|
||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||
'ctrl-l': 'editor:select-line'
|
||||
|
||||
'.workspace .editor:not(.mini)':
|
||||
# Atom specific
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
# Atom Specific
|
||||
'enter': 'core:confirm'
|
||||
'num-enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
@@ -18,6 +17,7 @@
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-,': 'application:show-settings'
|
||||
'ctrl-N': 'application:new-window'
|
||||
'ctrl-W': 'window:close'
|
||||
'ctrl-o': 'application:open-file'
|
||||
@@ -28,6 +28,7 @@
|
||||
'ctrl-w': 'core:close'
|
||||
'ctrl-f4': 'core:close'
|
||||
'ctrl-z': 'core:undo'
|
||||
'ctrl-shift-z': 'core:redo'
|
||||
'ctrl-y': 'core:redo'
|
||||
'ctrl-x': 'core:cut'
|
||||
'ctrl-c': 'core:copy'
|
||||
@@ -83,12 +84,15 @@
|
||||
'ctrl-delete': 'editor:delete-to-end-of-word'
|
||||
'ctrl-home': 'core:move-to-top'
|
||||
'ctrl-end': 'core:move-to-bottom'
|
||||
'ctrl-shift-home': 'core:select-to-top'
|
||||
'ctrl-shift-end': 'core:select-to-bottom'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-a': 'core:select-all'
|
||||
'ctrl-alt-shift-p': 'editor:log-cursor-scope'
|
||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||
'ctrl-l': 'editor:select-line'
|
||||
|
||||
'.workspace .editor:not(.mini)':
|
||||
# Atom specific
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@
|
||||
{ label: 'Save As...', command: 'core:save-as' }
|
||||
{ label: 'Save All', command: 'window:save-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Close Buffer', command: 'core:close' }
|
||||
{ label: 'Close Tab', command: 'core:close' }
|
||||
{ label: 'Close Pane', command: 'pane:close' }
|
||||
{ label: 'Close Window', command: 'window:close' }
|
||||
]
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@
|
||||
{ label: 'Save &As...', command: 'core:save-as' }
|
||||
{ label: 'Save A&ll', command: 'window:save-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Close Buffer', command: 'core:close' }
|
||||
{ label: 'Close All &Buffers', command: 'pane:close' }
|
||||
{ label: '&Close Tab', command: 'core:close' }
|
||||
{ label: 'Close &Pane', command: 'pane:close' }
|
||||
{ label: 'Clos&e Window', command: 'window:close' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Quit', command: 'application:quit' }
|
||||
|
||||
+7
-2
@@ -9,13 +9,18 @@
|
||||
{ label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Se&ttings', command: 'application:show-settings' }
|
||||
{ label: 'Open Your Config', command: 'application:open-your-config' }
|
||||
{ label: 'Open Your Init Script', command: 'application:open-your-init-script' }
|
||||
{ label: 'Open Your Keymap', command: 'application:open-your-keymap' }
|
||||
{ label: 'Open Your Snippets', command: 'application:open-your-snippets' }
|
||||
{ label: 'Open Your Stylesheet', command: 'application:open-your-stylesheet' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Save', command: 'core:save' }
|
||||
{ label: 'Save &As...', command: 'core:save-as' }
|
||||
{ label: 'Save A&ll', command: 'window:save-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Close Buffer', command: 'core:close' }
|
||||
{ label: 'Close All &Buffers', command: 'pane:close' }
|
||||
{ label: '&Close Tab', command: 'core:close' }
|
||||
{ label: 'Close &Pane', command: 'pane:close' }
|
||||
{ label: 'Clos&e Window', command: 'window:close' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'E&xit', command: 'application:quit' }
|
||||
|
||||
+62
-60
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.115.0",
|
||||
"version": "0.122.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,126 +17,128 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.13.3",
|
||||
"atomShellVersion": "0.15.6",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^0.27.0",
|
||||
"atom-keymap": "^2.0.1",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.7.0",
|
||||
"coffeestack": "0.7.0",
|
||||
"delegato": "^1",
|
||||
"emissary": "^1.2.1",
|
||||
"first-mate": "^1.7.1",
|
||||
"fs-plus": "^2.2.3",
|
||||
"emissary": "^1.2.2",
|
||||
"first-mate": "^2.0.1",
|
||||
"fs-plus": "^2.2.6",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^1.1",
|
||||
"git-utils": "^1.3",
|
||||
"grim": "0.11.0",
|
||||
"git-utils": "^2.1.4",
|
||||
"grim": "0.12.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"less-cache": "0.12.0",
|
||||
"less-cache": "0.13.0",
|
||||
"mixto": "^1",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "0.5.0",
|
||||
"oniguruma": "^1.0.6",
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.3",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^1.3.2",
|
||||
"pathwatcher": "^2.0.6",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
"react-atom-fork": "^0.10.0",
|
||||
"reactionary-atom-fork": "^0.9.0",
|
||||
"runas": "0.5.4",
|
||||
"scandal": "0.16.0",
|
||||
"react-atom-fork": "^0.11.1",
|
||||
"reactionary-atom-fork": "^1.0.0",
|
||||
"runas": "1.0.1",
|
||||
"scandal": "1.0.0",
|
||||
"scoped-property-store": "^0.9.0",
|
||||
"scrollbar-style": "^0.4.0",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^1.0.2",
|
||||
"semver": "1.1.4",
|
||||
"serializable": "^1",
|
||||
"space-pen": "3.2.0",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^2.4.2",
|
||||
"text-buffer": "^3.0.1",
|
||||
"theorist": "^1",
|
||||
"underscore-plus": "^1.5.0",
|
||||
"underscore-plus": "^1.5.1",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.19.0",
|
||||
"atom-dark-ui": "0.32.0",
|
||||
"atom-dark-ui": "0.33.0",
|
||||
"atom-light-syntax": "0.20.0",
|
||||
"atom-light-ui": "0.28.0",
|
||||
"base16-tomorrow-dark-theme": "0.19.0",
|
||||
"solarized-dark-syntax": "0.20.0",
|
||||
"solarized-light-syntax": "0.11.0",
|
||||
"archive-view": "0.33.0",
|
||||
"autocomplete": "0.28.0",
|
||||
"atom-light-ui": "0.29.0",
|
||||
"base16-tomorrow-dark-theme": "0.21.0",
|
||||
"base16-tomorrow-light-theme": "0.4.0",
|
||||
"solarized-dark-syntax": "0.22.0",
|
||||
"solarized-light-syntax": "0.12.0",
|
||||
"archive-view": "0.36.0",
|
||||
"autocomplete": "0.31.0",
|
||||
"autoflow": "0.17.0",
|
||||
"autosave": "0.14.0",
|
||||
"autosave": "0.15.0",
|
||||
"background-tips": "0.15.0",
|
||||
"bookmarks": "0.27.0",
|
||||
"bracket-matcher": "0.48.0",
|
||||
"bracket-matcher": "0.54.0",
|
||||
"command-palette": "0.24.0",
|
||||
"deprecation-cop": "0.7.0",
|
||||
"dev-live-reload": "0.31.0",
|
||||
"exception-reporting": "0.18.0",
|
||||
"deprecation-cop": "0.9.0",
|
||||
"dev-live-reload": "0.34.0",
|
||||
"exception-reporting": "0.20.0",
|
||||
"feedback": "0.33.0",
|
||||
"find-and-replace": "0.126.0",
|
||||
"find-and-replace": "0.128.0",
|
||||
"fuzzy-finder": "0.57.0",
|
||||
"git-diff": "0.36.0",
|
||||
"go-to-line": "0.23.0",
|
||||
"git-diff": "0.37.0",
|
||||
"go-to-line": "0.24.0",
|
||||
"grammar-selector": "0.27.0",
|
||||
"image-view": "0.36.0",
|
||||
"keybinding-resolver": "0.18.0",
|
||||
"link": "0.24.0",
|
||||
"markdown-preview": "0.93.0",
|
||||
"incompatible-packages": "0.8.0",
|
||||
"keybinding-resolver": "0.19.0",
|
||||
"link": "0.25.0",
|
||||
"markdown-preview": "0.99.0",
|
||||
"metrics": "0.33.0",
|
||||
"open-on-github": "0.29.0",
|
||||
"package-generator": "0.31.0",
|
||||
"release-notes": "0.35.0",
|
||||
"settings-view": "0.133.0",
|
||||
"snippets": "0.47.0",
|
||||
"spell-check": "0.38.0",
|
||||
"status-bar": "0.41.0",
|
||||
"release-notes": "0.36.0",
|
||||
"settings-view": "0.139.0",
|
||||
"snippets": "0.51.0",
|
||||
"spell-check": "0.41.0",
|
||||
"status-bar": "0.42.0",
|
||||
"styleguide": "0.29.0",
|
||||
"symbols-view": "0.59.0",
|
||||
"tabs": "0.44.0",
|
||||
"timecop": "0.21.0",
|
||||
"tree-view": "0.109.0",
|
||||
"symbols-view": "0.63.0",
|
||||
"tabs": "0.49.0",
|
||||
"timecop": "0.22.0",
|
||||
"tree-view": "0.112.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.17.0",
|
||||
"whitespace": "0.24.0",
|
||||
"whitespace": "0.25.0",
|
||||
"wrap-guide": "0.21.0",
|
||||
|
||||
"language-c": "0.21.0",
|
||||
"language-coffee-script": "0.25.0",
|
||||
"language-c": "0.27.0",
|
||||
"language-coffee-script": "0.29.0",
|
||||
"language-css": "0.17.0",
|
||||
"language-gfm": "0.42.0",
|
||||
"language-gfm": "0.46.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.13.0",
|
||||
"language-html": "0.22.0",
|
||||
"language-go": "0.16.0",
|
||||
"language-html": "0.24.0",
|
||||
"language-hyperlink": "0.10.0",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.35.0",
|
||||
"language-javascript": "0.39.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.12.0",
|
||||
"language-less": "0.13.0",
|
||||
"language-make": "0.10.0",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.15.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.18.0",
|
||||
"language-ruby": "0.32.0",
|
||||
"language-ruby": "0.34.0",
|
||||
"language-ruby-on-rails": "0.15.0",
|
||||
"language-sass": "0.13.0",
|
||||
"language-sass": "0.16.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.7.0",
|
||||
"language-sql": "0.9.0",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.10.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.10.0",
|
||||
"language-toml": "0.12.0",
|
||||
"language-xml": "0.15.0",
|
||||
"language-yaml": "0.11.0"
|
||||
"language-xml": "0.18.0",
|
||||
"language-yaml": "0.15.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
Arquivo binário não exibido.
Arquivo binário não exibido.
+1
-1
@@ -77,7 +77,7 @@ function bootstrap() {
|
||||
moduleInstallCommand,
|
||||
dedupeApmCommand + ' ' + packagesToDedupe.join(' '),
|
||||
{
|
||||
command: dedupeNpmCommand + ' request',
|
||||
command: dedupeNpmCommand + ' request semver',
|
||||
options: {
|
||||
cwd: path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager')
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ var commands = [
|
||||
[home, '.atom', 'storage'],
|
||||
[home, '.atom', '.npm'],
|
||||
[home, '.atom', 'compile-cache'],
|
||||
[home, '.atom', 'atom-shell'],
|
||||
[tmpdir, 'atom-build'],
|
||||
[tmpdir, 'atom-cached-atom-shells'],
|
||||
];
|
||||
|
||||
@@ -531,7 +531,7 @@ describe "the `atom` global", ->
|
||||
describe ".isReleasedVersion()", ->
|
||||
it "returns false if the version is a SHA and true otherwise", ->
|
||||
version = '0.1.0'
|
||||
spyOn(atom.constructor, 'getVersion').andCallFake -> version
|
||||
spyOn(atom, 'getVersion').andCallFake -> version
|
||||
expect(atom.isReleasedVersion()).toBe true
|
||||
version = '36b5518'
|
||||
expect(atom.isReleasedVersion()).toBe false
|
||||
|
||||
@@ -23,6 +23,18 @@ describe "Config", ->
|
||||
retrievedValue.array[1].b = 2.1
|
||||
expect(atom.config.get('value')).toEqual(array: [1, b: 2, 3])
|
||||
|
||||
it "merges defaults into the returned value if both the assigned value and the default value are objects", ->
|
||||
atom.config.setDefaults("foo", a: 1, b: 2)
|
||||
atom.config.set("foo", a: 3)
|
||||
expect(atom.config.get("foo")).toEqual {a: 3, b: 2}
|
||||
|
||||
atom.config.set("foo", 7)
|
||||
expect(atom.config.get("foo")).toBe 7
|
||||
|
||||
atom.config.set("bar.baz", a: 3)
|
||||
atom.config.setDefaults("bar", baz: 7)
|
||||
expect(atom.config.get("bar.baz")).toEqual {a: 3}
|
||||
|
||||
describe ".set(keyPath, value)", ->
|
||||
it "allows a key path's value to be written", ->
|
||||
expect(atom.config.set("foo.bar.baz", 42)).toBe 42
|
||||
|
||||
@@ -30,6 +30,16 @@ describe "ContextMenuManager", ->
|
||||
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
|
||||
expect(contextMenu.definitions['.selector'].length).toBe 1
|
||||
|
||||
it 'allows multiple separators', ->
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
'separator1': '-'
|
||||
'separator2': '-'
|
||||
|
||||
expect(contextMenu.definitions['.selector'].length).toBe 2
|
||||
expect(contextMenu.definitions['.selector'][0].type).toEqual 'separator'
|
||||
expect(contextMenu.definitions['.selector'][1].type).toEqual 'separator'
|
||||
|
||||
it 'allows duplicate commands with different labels', ->
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
|
||||
+613
-440
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -499,6 +499,15 @@ describe "Editor", ->
|
||||
cursor = editor.getCursor()
|
||||
expect(cursor.getBufferPosition()).toEqual [1,0]
|
||||
|
||||
describe "when invisible characters are enabled", ->
|
||||
it "moves to the first character of the current line without being confused by the invisible characters", ->
|
||||
atom.config.set('editor.showInvisibles', true)
|
||||
editor.setCursorScreenPosition [1,7]
|
||||
editor.moveCursorToFirstCharacterOfLine()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1,2]
|
||||
editor.moveCursorToFirstCharacterOfLine()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1,0]
|
||||
|
||||
describe ".moveCursorToBeginningOfWord()", ->
|
||||
it "moves the cursor to the beginning of the word", ->
|
||||
editor.setCursorBufferPosition [0, 8]
|
||||
@@ -1470,6 +1479,15 @@ describe "Editor", ->
|
||||
|
||||
describe "buffer manipulation", ->
|
||||
describe ".insertText(text)", ->
|
||||
describe "when there is a single selection", ->
|
||||
beforeEach ->
|
||||
editor.setSelectedBufferRange([[1, 0], [1, 2]])
|
||||
|
||||
it "will-insert-text and did-insert-text events are emitted when inserting text", ->
|
||||
range = editor.insertText('xxx')
|
||||
expect(range).toEqual [ [[1, 0], [1, 3]] ]
|
||||
expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {'
|
||||
|
||||
describe "when there are multiple empty selections", ->
|
||||
describe "when the cursors are on the same line", ->
|
||||
it "inserts the given text at the location of each cursor and moves the cursors to the end of each cursor's inserted text", ->
|
||||
@@ -1547,6 +1565,48 @@ describe "Editor", ->
|
||||
editor.insertText('holy cow')
|
||||
expect(editor.lineForScreenRow(2).fold).toBeUndefined()
|
||||
|
||||
describe "when will-insert-text and did-insert-text events are used", ->
|
||||
beforeEach ->
|
||||
editor.setSelectedBufferRange([[1, 0], [1, 2]])
|
||||
|
||||
it "will-insert-text and did-insert-text events are emitted when inserting text", ->
|
||||
willInsertSpy = jasmine.createSpy().andCallFake ->
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(items) {'
|
||||
|
||||
didInsertSpy = jasmine.createSpy().andCallFake ->
|
||||
expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {'
|
||||
|
||||
editor.on('will-insert-text', willInsertSpy)
|
||||
editor.on('did-insert-text', didInsertSpy)
|
||||
|
||||
expect(editor.insertText('xxx')).toBeTruthy()
|
||||
expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {'
|
||||
|
||||
expect(willInsertSpy).toHaveBeenCalled()
|
||||
expect(didInsertSpy).toHaveBeenCalled()
|
||||
|
||||
options = willInsertSpy.mostRecentCall.args[0]
|
||||
expect(options.text).toBe 'xxx'
|
||||
expect(options.cancel).toBeDefined()
|
||||
|
||||
options = didInsertSpy.mostRecentCall.args[0]
|
||||
expect(options.text).toBe 'xxx'
|
||||
|
||||
it "text insertion is prevented when cancel is called from a will-insert-text handler", ->
|
||||
willInsertSpy = jasmine.createSpy().andCallFake ({cancel}) ->
|
||||
cancel()
|
||||
|
||||
didInsertSpy = jasmine.createSpy()
|
||||
|
||||
editor.on('will-insert-text', willInsertSpy)
|
||||
editor.on('did-insert-text', didInsertSpy)
|
||||
|
||||
expect(editor.insertText('xxx')).toBe false
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(items) {'
|
||||
|
||||
expect(willInsertSpy).toHaveBeenCalled()
|
||||
expect(didInsertSpy).not.toHaveBeenCalled()
|
||||
|
||||
describe ".insertNewline()", ->
|
||||
describe "when there is a single cursor", ->
|
||||
describe "when the cursor is at the beginning of a line", ->
|
||||
@@ -2081,6 +2141,20 @@ describe "Editor", ->
|
||||
editor.indent()
|
||||
expect(buffer.lineForRow(0)).toMatch(tabRegex)
|
||||
|
||||
it "respects the tab stops when cursor is in the middle of a tab", ->
|
||||
editor.setTabLength(4)
|
||||
buffer.insert([12, 2], "\n ")
|
||||
editor.setCursorBufferPosition [13, 1]
|
||||
editor.indent()
|
||||
expect(buffer.lineForRow(13)).toMatch /^\s+$/
|
||||
expect(buffer.lineForRow(13).length).toBe 4
|
||||
expect(editor.getCursorBufferPosition()).toEqual [13, 4]
|
||||
|
||||
buffer.insert([13, 0], " ")
|
||||
editor.setCursorBufferPosition [13, 6]
|
||||
editor.indent()
|
||||
expect(buffer.lineForRow(13).length).toBe 8
|
||||
|
||||
describe "if 'softTabs' is false", ->
|
||||
it "insert a \t into the buffer", ->
|
||||
editor.setSoftTabs(false)
|
||||
@@ -2099,6 +2173,20 @@ describe "Editor", ->
|
||||
expect(buffer.lineForRow(5).length).toBe 6
|
||||
expect(editor.getCursorBufferPosition()).toEqual [5, 6]
|
||||
|
||||
it "respects the tab stops when cursor is in the middle of a tab", ->
|
||||
editor.setTabLength(4)
|
||||
buffer.insert([12, 2], "\n ")
|
||||
editor.setCursorBufferPosition [13, 1]
|
||||
editor.indent(autoIndent: true)
|
||||
expect(buffer.lineForRow(13)).toMatch /^\s+$/
|
||||
expect(buffer.lineForRow(13).length).toBe 4
|
||||
expect(editor.getCursorBufferPosition()).toEqual [13, 4]
|
||||
|
||||
buffer.insert([13, 0], " ")
|
||||
editor.setCursorBufferPosition [13, 6]
|
||||
editor.indent(autoIndent: true)
|
||||
expect(buffer.lineForRow(13).length).toBe 8
|
||||
|
||||
describe "when 'softTabs' is false", ->
|
||||
it "moves the cursor to the end of the leading whitespace and inserts enough tabs to bring the line to the suggested level of indentaion", ->
|
||||
convertToHardTabs(buffer)
|
||||
@@ -2829,7 +2917,7 @@ describe "Editor", ->
|
||||
|
||||
atom.config.set("editor.autoIndent", false)
|
||||
editor.indent()
|
||||
expect(editor.lineForBufferRow(2)).toBe " "
|
||||
expect(editor.lineForBufferRow(2)).toBe " "
|
||||
|
||||
describe "when editor.autoIndent is true", ->
|
||||
beforeEach ->
|
||||
@@ -3273,20 +3361,25 @@ describe "Editor", ->
|
||||
expect(editor.getText()).toBe ' '
|
||||
|
||||
describe ".scrollToCursorPosition()", ->
|
||||
it "scrolls the last cursor into view", ->
|
||||
it "scrolls the last cursor into view, centering around the cursor if possible and the 'center' option isn't false", ->
|
||||
editor.setCursorScreenPosition([8, 8])
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setDefaultCharWidth(10)
|
||||
editor.setHeight(50)
|
||||
editor.setHeight(60)
|
||||
editor.setWidth(50)
|
||||
editor.setHorizontalScrollbarHeight(0)
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
expect(editor.getScrollLeft()).toBe 0
|
||||
|
||||
editor.scrollToCursorPosition()
|
||||
expect(editor.getScrollBottom()).toBe (9 + editor.getVerticalScrollMargin()) * 10
|
||||
expect(editor.getScrollTop()).toBe (8.5 * 10) - 30
|
||||
expect(editor.getScrollBottom()).toBe (8.5 * 10) + 30
|
||||
expect(editor.getScrollRight()).toBe (9 + editor.getHorizontalScrollMargin()) * 10
|
||||
|
||||
editor.setScrollTop(0)
|
||||
editor.scrollToCursorPosition(center: false)
|
||||
expect(editor.getScrollBottom()).toBe (9 + editor.getVerticalScrollMargin()) * 10
|
||||
|
||||
describe ".pageUp/Down()", ->
|
||||
it "scrolls one screen height up or down and moves the cursor one page length", ->
|
||||
editor.manageScrollPosition = true
|
||||
|
||||
@@ -2414,37 +2414,6 @@ describe "EditorView", ->
|
||||
expect(editor.getCursor().getScreenPosition().row).toBe(0)
|
||||
expect(editorView.getFirstVisibleScreenRow()).toBe(0)
|
||||
|
||||
describe ".checkoutHead()", ->
|
||||
[filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
workingDirPath = temp.mkdirSync('atom-working-dir')
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'git', 'working-dir'), workingDirPath)
|
||||
fs.renameSync(path.join(workingDirPath, 'git.git'), path.join(workingDirPath, '.git'))
|
||||
atom.project.setPath(workingDirPath)
|
||||
filePath = atom.project.resolve('file.txt')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editorView.edit(editor)
|
||||
|
||||
it "restores the contents of the editor view to the HEAD revision", ->
|
||||
editor.setText('')
|
||||
editor.save()
|
||||
|
||||
fileChangeHandler = jasmine.createSpy('fileChange')
|
||||
editor.getBuffer().file.on 'contents-changed', fileChangeHandler
|
||||
|
||||
editorView.checkoutHead()
|
||||
|
||||
waitsFor "file to trigger contents-changed event", ->
|
||||
fileChangeHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(editor.getText()).toBe('undefined')
|
||||
|
||||
describe ".pixelPositionForBufferPosition(position)", ->
|
||||
describe "when the editor view is detached", ->
|
||||
it "returns top and left values of 0", ->
|
||||
@@ -2652,7 +2621,6 @@ describe "EditorView", ->
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
|
||||
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {'
|
||||
expect(buffer.lineForRow(13)).toBe 'var a = function() {'
|
||||
editor.logScreenLines()
|
||||
expect(editor.isFoldedAtBufferRow(0)).toBe true
|
||||
expect(editor.isFoldedAtBufferRow(13)).toBe true
|
||||
|
||||
@@ -2999,8 +2967,8 @@ describe "EditorView", ->
|
||||
expect(editorView.lineElementForScreenRow(rowNumber).text()).toBe buffer.lineForRow(rowNumber)
|
||||
|
||||
it "correctly calculates the position left for non-monospaced invisibles", ->
|
||||
editorView.setShowInvisibles(true)
|
||||
editorView.setInvisibles tab: '♘'
|
||||
atom.config.set('editor.showInvisibles', true)
|
||||
atom.config.set('editor.invisibles', tab: '♘')
|
||||
editor.setText('\tx')
|
||||
|
||||
editorView.setFontFamily('serif')
|
||||
|
||||
externo
BIN
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 392 B |
externo
-1
@@ -1 +0,0 @@
|
||||
this tests files with no extensions
|
||||
gerado
externo
gerado
externo
+1
@@ -0,0 +1 @@
|
||||
throw new Error("this simulates a native module's failure to load")
|
||||
gerado
externo
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "native-module",
|
||||
"main": "./main.js"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "package-with-incompatible-native-module",
|
||||
"version": "1.0",
|
||||
"main": "./main.js"
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
'fileTypes': ['package-with-infinite-loop-grammar']
|
||||
'name': 'package-with-infinite-loop-grammar'
|
||||
'scopeName': 'source.package-with-infinite-loop-grammar'
|
||||
|
||||
# This grammar should loop forever if the line contains an `a`
|
||||
'patterns': [
|
||||
{
|
||||
'name': 'start'
|
||||
'begin': '^'
|
||||
'end': '$'
|
||||
'patterns': [
|
||||
{
|
||||
name: 'negative-look-ahead'
|
||||
match: "(?!a)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1 +0,0 @@
|
||||
This is a hidden file. Don't even try to load it as a snippet
|
||||
@@ -1 +0,0 @@
|
||||
This file isn't CSON, but shouldn't be a big deal
|
||||
@@ -1,4 +0,0 @@
|
||||
".test":
|
||||
"Test Snippet":
|
||||
prefix: "test"
|
||||
body: "testing 123"
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"theme": "ui",
|
||||
"stylesheets": ["editor.less"]
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
@import "ui-variables";
|
||||
|
||||
.editor {
|
||||
padding-top: @component-padding;
|
||||
padding-right: @component-padding;
|
||||
padding-bottom: @component-padding;
|
||||
|
||||
color: @input-background-color;
|
||||
background-color: @background-color-info; // From the fallback variables, not overridden
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// This does not contain all of the ui-variables available.
|
||||
@app-background-color: #00f; // Changed
|
||||
@input-background-color: #f00; // Changed
|
||||
@@ -1,3 +0,0 @@
|
||||
@import "stylesheets/first";
|
||||
@import "stylesheets/second";
|
||||
@import "stylesheets/last";
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"theme": "ui"
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
.editor {
|
||||
padding-top: 101px;
|
||||
padding-right: 101px;
|
||||
padding-bottom: 101px;
|
||||
|
||||
color: red;
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
.editor {
|
||||
/* padding-top: 103px;
|
||||
padding-right: 103px;*/
|
||||
padding-bottom: 103px;
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
@import "ui-variables";
|
||||
|
||||
@number: 102px;
|
||||
|
||||
.editor {
|
||||
/* padding-top: 102px;*/
|
||||
padding-right: @number;
|
||||
padding-bottom: @number;
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
// Variables different from the original are marked 'Changed'
|
||||
|
||||
@text-color: #333;
|
||||
@text-color-subtle: #777;
|
||||
@text-color-highlight: #111;
|
||||
@text-color-selected: @text-color-highlight;
|
||||
|
||||
@text-color-info: #5293d8;
|
||||
@text-color-success: #1fe977;
|
||||
@text-color-warning: #f78a46;
|
||||
@text-color-error: #c00;
|
||||
|
||||
@background-color-info: #0098ff;
|
||||
@background-color-success: #17ca65;
|
||||
@background-color-warning: #ff4800;
|
||||
@background-color-error: #c00;
|
||||
@background-color-highlight: rgba(255, 255, 255, 0.10);
|
||||
@background-color-selected: @background-color-highlight;
|
||||
|
||||
@app-background-color: #00f; // Changed
|
||||
|
||||
@base-background-color: #fff;
|
||||
@base-border-color: #eee;
|
||||
|
||||
@pane-item-background-color: @base-background-color;
|
||||
@pane-item-border-color: @base-border-color;
|
||||
|
||||
@input-background-color: #f00; // Changed
|
||||
@input-border-color: @base-border-color;
|
||||
|
||||
@tool-panel-background-color: #f4f4f4;
|
||||
@tool-panel-border-color: @base-border-color;
|
||||
|
||||
@inset-panel-background-color: #eee;
|
||||
@inset-panel-border-color: @base-border-color;
|
||||
|
||||
@panel-heading-background-color: #ddd;
|
||||
@panel-heading-border-color: transparent;
|
||||
|
||||
@overlay-background-color: #f4f4f4;
|
||||
@overlay-border-color: @base-border-color;
|
||||
|
||||
@button-background-color: #ccc;
|
||||
@button-background-color-hover: lighten(@button-background-color, 5%);
|
||||
@button-background-color-selected: @button-background-color-hover;
|
||||
@button-border-color: #aaa;
|
||||
|
||||
@tab-bar-background-color: #fff;
|
||||
@tab-bar-border-color: darken(@tab-background-color-active, 10%);
|
||||
@tab-background-color: #f4f4f4;
|
||||
@tab-background-color-active: #fff;
|
||||
@tab-border-color: @base-border-color;
|
||||
|
||||
@tree-view-background-color: @tool-panel-background-color;
|
||||
@tree-view-border-color: @tool-panel-border-color;
|
||||
|
||||
@ui-site-color-1: @background-color-success; // green
|
||||
@ui-site-color-2: @background-color-info; // blue
|
||||
@ui-site-color-3: @background-color-warning; // orange
|
||||
@ui-site-color-4: #db2ff4; // purple
|
||||
@ui-site-color-5: #f5e11d; // yellow
|
||||
|
||||
@font-size: 12px;
|
||||
|
||||
@disclosure-arrow-size: 12px;
|
||||
|
||||
@component-padding: 150px;
|
||||
@component-icon-padding: 5px;
|
||||
@component-icon-size: 16px;
|
||||
@component-line-height: 25px;
|
||||
@component-border-radius: 2px;
|
||||
|
||||
@tab-height: 30px;
|
||||
|
||||
@font-family: Arial;
|
||||
@@ -1 +0,0 @@
|
||||
Hello World!
|
||||
@@ -1 +0,0 @@
|
||||
Goodbye World!
|
||||
@@ -1 +0,0 @@
|
||||
Hello World!
|
||||
@@ -1 +0,0 @@
|
||||
Goodbye World!
|
||||
-1
@@ -1 +0,0 @@
|
||||
#header {
|
||||
externo
-71
@@ -1,71 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>txt</string>
|
||||
</array>
|
||||
<key>keyEquivalent</key>
|
||||
<string>^~P</string>
|
||||
<key>name</key>
|
||||
<string>Plain Text</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.item.text</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>^\s*(•).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>meta.bullet-point.strong.text</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.item.text</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>^\s*(·).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>meta.bullet-point.light.text</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.item.text</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>^\s*(\*).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>meta.bullet-point.star.text</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>^([ \t]*)(?=\S)</string>
|
||||
<key>contentName</key>
|
||||
<string>meta.paragraph.text</string>
|
||||
<key>end</key>
|
||||
<string>^(?!\1(?=\S))</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>text.plain</string>
|
||||
<key>uuid</key>
|
||||
<string>3130E4FA-B10E-11D9-9F75-000D93589AF6</string>
|
||||
</dict>
|
||||
</plist>
|
||||
externo
-1
@@ -1 +0,0 @@
|
||||
dir
|
||||
externo
-1
@@ -1 +0,0 @@
|
||||
sample.js
|
||||
externo
-1
@@ -1 +0,0 @@
|
||||
a
|
||||
@@ -119,6 +119,38 @@ describe "Git", ->
|
||||
repo.checkoutHead(filePath)
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
describe ".checkoutHeadForEditor(editor)", ->
|
||||
[filePath, editor] = []
|
||||
|
||||
beforeEach ->
|
||||
workingDirPath = copyRepository()
|
||||
repo = new Git(workingDirPath)
|
||||
filePath = path.join(workingDirPath, 'a.txt')
|
||||
fs.writeFileSync(filePath, 'ch ch changes')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath)
|
||||
|
||||
runs ->
|
||||
editor = atom.workspace.getActiveEditor()
|
||||
|
||||
it "displays a confirmation dialog by default", ->
|
||||
spyOn(atom, 'confirm').andCallFake ({buttons}) -> buttons.OK()
|
||||
atom.config.set('editor.confirmCheckoutHeadRevision', true)
|
||||
|
||||
repo.checkoutHeadForEditor(editor)
|
||||
|
||||
expect(fs.readFileSync(filePath, 'utf8')).toBe ''
|
||||
|
||||
it "does not display a dialog when confirmation is disabled", ->
|
||||
spyOn(atom, 'confirm')
|
||||
atom.config.set('editor.confirmCheckoutHeadRevision', false)
|
||||
|
||||
repo.checkoutHeadForEditor(editor)
|
||||
|
||||
expect(fs.readFileSync(filePath, 'utf8')).toBe ''
|
||||
expect(atom.confirm).not.toHaveBeenCalled()
|
||||
|
||||
describe ".destroy()", ->
|
||||
it "throws an exception when any method is called after it is called", ->
|
||||
repo = new Git(require.resolve('./fixtures/git/master.git/HEAD'))
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
fs = require 'fs'
|
||||
|
||||
module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
|
||||
{$, $$} = require 'atom'
|
||||
{$, $$} = require '../src/space-pen-extensions'
|
||||
|
||||
window[key] = value for key, value of require '../vendor/jasmine'
|
||||
|
||||
{TerminalReporter} = require 'jasmine-tagged'
|
||||
|
||||
@@ -1,8 +1,39 @@
|
||||
{$} = require 'atom'
|
||||
path = require 'path'
|
||||
Package = require '../src/package'
|
||||
ThemePackage = require '../src/theme-package'
|
||||
|
||||
describe "Package", ->
|
||||
describe "when the package contains incompatible native modules", ->
|
||||
beforeEach ->
|
||||
spyOn(atom, 'inDevMode').andReturn(false)
|
||||
|
||||
it "does not activate it", ->
|
||||
packagePath = atom.project.resolve('packages/package-with-incompatible-native-module')
|
||||
pack = new Package(packagePath)
|
||||
expect(pack.isCompatible()).toBe false
|
||||
expect(pack.incompatibleModules[0].name).toBe 'native-module'
|
||||
expect(pack.incompatibleModules[0].path).toBe path.join(packagePath, 'node_modules', 'native-module')
|
||||
|
||||
it "caches the incompatible native modules in local storage", ->
|
||||
packagePath = atom.project.resolve('packages/package-with-incompatible-native-module')
|
||||
cacheKey = null
|
||||
cacheItem = null
|
||||
|
||||
spyOn(global.localStorage, 'setItem').andCallFake (key, item) ->
|
||||
cacheKey = key
|
||||
cacheItem = item
|
||||
spyOn(global.localStorage, 'getItem').andCallFake (key) ->
|
||||
return cacheItem if cacheKey is key
|
||||
|
||||
expect(new Package(packagePath).isCompatible()).toBe false
|
||||
expect(global.localStorage.getItem.callCount).toBe 1
|
||||
expect(global.localStorage.setItem.callCount).toBe 1
|
||||
|
||||
expect(new Package(packagePath).isCompatible()).toBe false
|
||||
expect(global.localStorage.getItem.callCount).toBe 2
|
||||
expect(global.localStorage.setItem.callCount).toBe 1
|
||||
|
||||
describe "theme", ->
|
||||
theme = null
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ atom.keymaps.loadBundledKeymaps()
|
||||
keyBindingsToRestore = atom.keymaps.getKeyBindings()
|
||||
|
||||
$(window).on 'core:close', -> window.close()
|
||||
$(window).on 'unload', ->
|
||||
$(window).on 'beforeunload', ->
|
||||
atom.storeWindowDimensions()
|
||||
atom.saveSync()
|
||||
$('html,body').css('overflow', 'auto')
|
||||
@@ -130,6 +130,8 @@ afterEach ->
|
||||
atom.project?.destroy()
|
||||
atom.project = null
|
||||
|
||||
atom.themes.removeStylesheet('global-editor-styles')
|
||||
|
||||
delete atom.state.packageStates
|
||||
|
||||
$('#jasmine-content').empty() unless window.debugContent
|
||||
@@ -209,6 +211,13 @@ addCustomMatchers = (spec) ->
|
||||
element = element.get(0) if element.jquery
|
||||
element.webkitMatchesSelector(":focus") or element.querySelector(":focus")
|
||||
|
||||
toShow: ->
|
||||
notText = if @isNot then " not" else ""
|
||||
element = @actual
|
||||
element = element.get(0) if element.jquery
|
||||
@message = -> return "Expected element '#{element}' or its descendants #{notText} to show."
|
||||
element.style.display in ['block', 'inline-block', 'static', 'fixed']
|
||||
|
||||
window.keyIdentifierForKey = (key) ->
|
||||
if key.length > 1 # named key
|
||||
key
|
||||
@@ -318,9 +327,13 @@ window.setEditorWidthInChars = (editorView, widthInChars, charWidth=editorView.c
|
||||
editorView.width(charWidth * widthInChars + editorView.gutter.outerWidth())
|
||||
$(window).trigger 'resize' # update width of editor view's on-screen lines
|
||||
|
||||
window.setEditorHeightInLines = (editorView, heightInChars, charHeight=editorView.lineHeight) ->
|
||||
editorView.height(charHeight * heightInChars + editorView.renderedLines.position().top)
|
||||
$(window).trigger 'resize' # update editor view's on-screen lines
|
||||
window.setEditorHeightInLines = (editorView, heightInLines, lineHeight=editorView.lineHeight) ->
|
||||
if editorView.hasClass('react')
|
||||
editorView.height(editorView.getEditor().getLineHeightInPixels() * heightInLines)
|
||||
editorView.component?.measureHeightAndWidth()
|
||||
else
|
||||
editorView.height(lineHeight * heightInLines + editorView.renderedLines.position().top)
|
||||
$(window).trigger 'resize' # update editor view's on-screen lines
|
||||
|
||||
$.fn.resultOfTrigger = (type) ->
|
||||
event = $.Event(type)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
{Git} = require 'atom'
|
||||
path = require 'path'
|
||||
require './spec-helper'
|
||||
|
||||
|
||||
@@ -232,6 +232,21 @@ describe "ThemeManager", ->
|
||||
expect($(".editor").css("padding-right")).toBe "150px"
|
||||
expect($(".editor").css("padding-bottom")).toBe "150px"
|
||||
|
||||
describe "when there is a theme with incomplete variables", ->
|
||||
it "loads the correct values from the fallback ui-variables", ->
|
||||
themeManager.on 'reloaded', reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-incomplete-ui-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
# an override loaded in the base css
|
||||
expect(atom.workspaceView.css("background-color")).toBe "rgb(0, 0, 255)"
|
||||
|
||||
# from within the theme itself
|
||||
expect($(".editor").css("background-color")).toBe "rgb(0, 152, 255)"
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
it "reloads it", ->
|
||||
[stylesheetRemovedHandler, stylesheetAddedHandler, stylesheetsChangedHandler] = []
|
||||
@@ -295,3 +310,59 @@ describe "ThemeManager", ->
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
|
||||
|
||||
describe "when in safe mode", ->
|
||||
beforeEach ->
|
||||
themeManager = new ThemeManager({packageManager: atom.packages, resourcePath, configDirPath, safeMode: true})
|
||||
|
||||
describe 'when the enabled UI and syntax themes are bundled with Atom', ->
|
||||
beforeEach ->
|
||||
atom.config.set('core.themes', ['atom-light-ui', 'atom-dark-syntax'])
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
it 'uses the enabled themes', ->
|
||||
activeThemeNames = themeManager.getActiveNames()
|
||||
expect(activeThemeNames.length).toBe(2)
|
||||
expect(activeThemeNames).toContain('atom-light-ui')
|
||||
expect(activeThemeNames).toContain('atom-dark-syntax')
|
||||
|
||||
describe 'when the enabled UI and syntax themes are not bundled with Atom', ->
|
||||
beforeEach ->
|
||||
atom.config.set('core.themes', ['installed-dark-ui', 'installed-dark-syntax'])
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
it 'uses the default dark UI and syntax themes', ->
|
||||
activeThemeNames = themeManager.getActiveNames()
|
||||
expect(activeThemeNames.length).toBe(2)
|
||||
expect(activeThemeNames).toContain('atom-dark-ui')
|
||||
expect(activeThemeNames).toContain('atom-dark-syntax')
|
||||
|
||||
describe 'when the enabled UI theme is not bundled with Atom', ->
|
||||
beforeEach ->
|
||||
atom.config.set('core.themes', ['installed-dark-ui', 'atom-light-syntax'])
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
it 'uses the default dark UI theme', ->
|
||||
activeThemeNames = themeManager.getActiveNames()
|
||||
expect(activeThemeNames.length).toBe(2)
|
||||
expect(activeThemeNames).toContain('atom-dark-ui')
|
||||
expect(activeThemeNames).toContain('atom-light-syntax')
|
||||
|
||||
describe 'when the enabled syntax theme is not bundled with Atom', ->
|
||||
beforeEach ->
|
||||
atom.config.set('core.themes', ['atom-light-ui', 'installed-dark-syntax'])
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
it 'uses the default dark syntax theme', ->
|
||||
activeThemeNames = themeManager.getActiveNames()
|
||||
expect(activeThemeNames.length).toBe(2)
|
||||
expect(activeThemeNames).toContain('atom-light-ui')
|
||||
expect(activeThemeNames).toContain('atom-dark-syntax')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
TokenizedBuffer = require '../src/tokenized-buffer'
|
||||
TextBuffer = require 'text-buffer'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
describe "TokenizedBuffer", ->
|
||||
@@ -12,6 +13,9 @@ describe "TokenizedBuffer", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
|
||||
afterEach ->
|
||||
tokenizedBuffer?.destroy()
|
||||
|
||||
startTokenizing = (tokenizedBuffer) ->
|
||||
tokenizedBuffer.setVisible(true)
|
||||
|
||||
@@ -584,42 +588,95 @@ describe "TokenizedBuffer", ->
|
||||
atom.config.set('editor.tabLength', 0)
|
||||
expect(tokenizedBuffer.tokenForPosition([0,0]).value).toBe ' '
|
||||
|
||||
describe "when the invisibles value changes", ->
|
||||
beforeEach ->
|
||||
|
||||
it "updates the tokens with the appropriate invisible characters", ->
|
||||
buffer = new TextBuffer(text: " \t a line with tabs\tand \tspaces \t ")
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
tokenizedBuffer.setInvisibles(space: 'S', tab: 'T')
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "SST Sa line with tabsTand T spacesSTS"
|
||||
# Also needs to work for copies
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).copy().text).toBe "SST Sa line with tabsTand T spacesSTS"
|
||||
|
||||
it "assigns endOfLineInvisibles to tokenized lines", ->
|
||||
buffer = new TextBuffer(text: "a line that ends in a carriage-return-line-feed \r\na line that ends in just a line-feed\na line with no ending")
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
|
||||
atom.config.set('editor.showInvisibles', true)
|
||||
tokenizedBuffer.setInvisibles(cr: 'R', eol: 'N')
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).endOfLineInvisibles).toEqual ['R', 'N']
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).endOfLineInvisibles).toEqual ['N']
|
||||
|
||||
# Lines ending in soft wraps get no invisibles
|
||||
[left, right] = tokenizedBuffer.lineForScreenRow(0).softWrapAt(20)
|
||||
expect(left.endOfLineInvisibles).toBe null
|
||||
expect(right.endOfLineInvisibles).toEqual ['R', 'N']
|
||||
|
||||
tokenizedBuffer.setInvisibles(cr: 'R', eol: false)
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).endOfLineInvisibles).toEqual ['R']
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).endOfLineInvisibles).toEqual []
|
||||
|
||||
describe "leading and trailing whitespace", ->
|
||||
beforeEach ->
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
it "sets ::hasLeadingWhitespace to true on tokens that have leading whitespace", ->
|
||||
it "sets ::hasLeadingWhitespace to true and assigns ::firstNonWhitespaceIndex on tokens that have leading whitespace", ->
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[0].hasLeadingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[0].firstNonWhitespaceIndex).toBe null
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).tokens[0].hasLeadingWhitespace).toBe true
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].hasLeadingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].firstNonWhitespaceIndex).toBe null
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[0].hasLeadingWhitespace).toBe true
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].hasLeadingWhitespace).toBe true
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].firstNonWhitespaceIndex).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[2].hasLeadingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[2].firstNonWhitespaceIndex).toBe null
|
||||
|
||||
# The 4th token *has* leading whitespace, but isn't entirely whitespace
|
||||
buffer.insert([5, 0], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).tokens[3].hasLeadingWhitespace).toBe true
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).tokens[3].firstNonWhitespaceIndex).toBe 1
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).tokens[4].hasLeadingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).tokens[4].firstNonWhitespaceIndex).toBe null
|
||||
|
||||
# Lines that are *only* whitespace are not considered to have leading whitespace
|
||||
buffer.insert([10, 0], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(10).tokens[0].hasLeadingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(10).tokens[0].firstNonWhitespaceIndex).toBe null
|
||||
|
||||
it "sets ::hasTrailingWhitespace to true on tokens that have trailing whitespace", ->
|
||||
it "sets ::hasTrailingWhitespace to true and assigns ::firstTrailingWhitespaceIndex on tokens that have trailing whitespace", ->
|
||||
buffer.insert([0, Infinity], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[11].hasTrailingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[11].firstTrailingWhitespaceIndex).toBe null
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[12].hasTrailingWhitespace).toBe true
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[12].firstTrailingWhitespaceIndex).toBe 0
|
||||
|
||||
# The last token *has* trailing whitespace, but isn't entirely whitespace
|
||||
buffer.setTextInRange([[2, 39], [2, 40]], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[14].hasTrailingWhitespace).toBe false
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[14].firstTrailingWhitespaceIndex).toBe null
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[15].hasTrailingWhitespace).toBe true
|
||||
console.log tokenizedBuffer.lineForScreenRow(2).tokens[15]
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[15].firstTrailingWhitespaceIndex).toBe 6
|
||||
|
||||
# Lines that are *only* whitespace are considered to have trailing whitespace
|
||||
buffer.insert([10, 0], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(10).tokens[0].hasTrailingWhitespace).toBe true
|
||||
expect(tokenizedBuffer.lineForScreenRow(10).tokens[0].firstTrailingWhitespaceIndex).toBe 0
|
||||
|
||||
it "only marks trailing whitespace on the last segment of a soft-wrapped line", ->
|
||||
buffer.insert([0, Infinity], ' ')
|
||||
@@ -627,8 +684,20 @@ describe "TokenizedBuffer", ->
|
||||
[segment1, segment2] = tokenizedLine.softWrapAt(16)
|
||||
expect(segment1.tokens[5].value).toBe ' '
|
||||
expect(segment1.tokens[5].hasTrailingWhitespace).toBe false
|
||||
expect(segment1.tokens[5].firstTrailingWhitespaceIndex).toBe null
|
||||
expect(segment2.tokens[6].value).toBe ' '
|
||||
expect(segment2.tokens[6].hasTrailingWhitespace).toBe true
|
||||
expect(segment2.tokens[6].firstTrailingWhitespaceIndex).toBe 0
|
||||
|
||||
it "sets leading and trailing whitespace correctly on a line with invisible characters that is copied", ->
|
||||
buffer.setText(" \t a line with tabs\tand \tspaces \t ")
|
||||
|
||||
tokenizedBuffer.setInvisibles(space: 'S', tab: 'T')
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
line = tokenizedBuffer.lineForScreenRow(0).copy()
|
||||
expect(line.tokens[0].hasLeadingWhitespace).toBe true
|
||||
expect(line.tokens[line.tokens.length - 1].hasTrailingWhitespace).toBe true
|
||||
|
||||
describe "indent level", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -113,6 +113,7 @@ describe "Window", ->
|
||||
expect(atom.state.project).toEqual projectState
|
||||
expect(atom.saveSync).toHaveBeenCalled()
|
||||
|
||||
describe ".removeEditorWindow()", ->
|
||||
it "unsubscribes from all buffers", ->
|
||||
waitsForPromise ->
|
||||
atom.workspace.open("sample.js")
|
||||
@@ -123,7 +124,7 @@ describe "Window", ->
|
||||
pane.splitRight(pane.copyActiveItem())
|
||||
expect(atom.workspaceView.find('.editor').length).toBe 2
|
||||
|
||||
atom.unloadEditorWindow()
|
||||
atom.removeEditorWindow()
|
||||
|
||||
expect(buffer.getSubscriptionCount()).toBe 0
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ describe "WorkspaceView", ->
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(pathToOpen)
|
||||
|
||||
|
||||
describe "@deserialize()", ->
|
||||
viewState = null
|
||||
|
||||
@@ -196,13 +195,12 @@ describe "WorkspaceView", ->
|
||||
atom.workspaceView.height(200)
|
||||
atom.workspaceView.attachToDom()
|
||||
rightEditorView = atom.workspaceView.getActiveView()
|
||||
rightEditorView.getEditor().setText("\t ")
|
||||
rightEditorView.getEditor().setText("\t \n")
|
||||
leftEditorView = rightEditorView.splitLeft()
|
||||
expect(rightEditorView.find(".line:first").text()).toBe " "
|
||||
expect(leftEditorView.find(".line:first").text()).toBe " "
|
||||
|
||||
{invisibles} = rightEditorView.component.state
|
||||
{space, tab, eol} = invisibles
|
||||
{space, tab, eol} = atom.config.get('editor.invisibles')
|
||||
withInvisiblesShowing = "#{tab} #{space}#{space}#{eol}"
|
||||
|
||||
atom.workspaceView.trigger "window:toggle-invisibles"
|
||||
@@ -294,3 +292,31 @@ describe "WorkspaceView", ->
|
||||
expect(atom.workspaceView).toHaveClass 'scrollbars-visible-always'
|
||||
scrollbarStyle.emitValue 'overlay'
|
||||
expect(atom.workspaceView).toHaveClass 'scrollbars-visible-when-scrolling'
|
||||
|
||||
describe "editor font styling", ->
|
||||
[editorNode, editor] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.workspaceView.attachToDom()
|
||||
editorNode = atom.workspaceView.find('.editor')[0]
|
||||
editor = atom.workspaceView.find('.editor').view().getEditor()
|
||||
|
||||
it "updates the font-size based on the 'editor.fontSize' config value", ->
|
||||
initialCharWidth = editor.getDefaultCharWidth()
|
||||
expect(getComputedStyle(editorNode).fontSize).toBe atom.config.get('editor.fontSize') + 'px'
|
||||
atom.config.set('editor.fontSize', atom.config.get('editor.fontSize') + 5)
|
||||
expect(getComputedStyle(editorNode).fontSize).toBe atom.config.get('editor.fontSize') + 'px'
|
||||
expect(editor.getDefaultCharWidth()).toBeGreaterThan initialCharWidth
|
||||
|
||||
it "updates the font-family based on the 'editor.fontFamily' config value", ->
|
||||
initialCharWidth = editor.getDefaultCharWidth()
|
||||
expect(getComputedStyle(editorNode).fontFamily).toBe atom.config.get('editor.fontFamily')
|
||||
atom.config.set('editor.fontFamily', 'sans-serif')
|
||||
expect(getComputedStyle(editorNode).fontFamily).toBe atom.config.get('editor.fontFamily')
|
||||
expect(editor.getDefaultCharWidth()).not.toBe initialCharWidth
|
||||
|
||||
it "updates the line-height based on the 'editor.lineHeight' config value", ->
|
||||
initialLineHeight = editor.getLineHeightInPixels()
|
||||
atom.config.set('editor.lineHeight', '30px')
|
||||
expect(getComputedStyle(editorNode).lineHeight).toBe atom.config.get('editor.lineHeight')
|
||||
expect(editor.getLineHeightInPixels()).not.toBe initialLineHeight
|
||||
|
||||
+22
-23
@@ -110,14 +110,6 @@ class Atom extends Model
|
||||
@getCurrentWindow: ->
|
||||
remote.getCurrentWindow()
|
||||
|
||||
# Get the version of the Atom application.
|
||||
@getVersion: ->
|
||||
@appVersion ?= @getLoadSettings().appVersion
|
||||
|
||||
# Determine whether the current version is an official release.
|
||||
@isReleasedVersion: ->
|
||||
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
|
||||
|
||||
workspaceViewParentSelector: 'body'
|
||||
|
||||
# Call .loadOrCreate instead
|
||||
@@ -158,13 +150,13 @@ class Atom extends Model
|
||||
process.env.NODE_PATH = exportsPath
|
||||
|
||||
# Make react.js faster
|
||||
process.env.NODE_ENV ?= 'production'
|
||||
process.env.NODE_ENV ?= 'production' unless devMode
|
||||
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath})
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode})
|
||||
@contextMenu = new ContextMenuManager(devMode)
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@clipboard = new Clipboard()
|
||||
@@ -319,11 +311,6 @@ class Atom extends Model
|
||||
@requireUserInitScript()
|
||||
@menu.update()
|
||||
|
||||
$(window).on 'unload', =>
|
||||
$(document.body).css('visibility', 'hidden')
|
||||
@unloadEditorWindow()
|
||||
false
|
||||
|
||||
@displayWindow()
|
||||
|
||||
unloadEditorWindow: ->
|
||||
@@ -335,13 +322,18 @@ class Atom extends Model
|
||||
@packages.deactivatePackages()
|
||||
@state.packageStates = @packages.packageStates
|
||||
@saveSync()
|
||||
@workspaceView.remove()
|
||||
@workspaceView = null
|
||||
@project.destroy()
|
||||
@windowEventHandler?.unsubscribe()
|
||||
@keymaps.destroy()
|
||||
@windowState = null
|
||||
|
||||
removeEditorWindow: ->
|
||||
return if not @project and not @workspaceView
|
||||
|
||||
@workspaceView?.remove()
|
||||
@workspaceView = null
|
||||
@project?.destroy()
|
||||
@project = null
|
||||
|
||||
@windowEventHandler?.unsubscribe()
|
||||
|
||||
loadThemes: ->
|
||||
@themes.load()
|
||||
|
||||
@@ -446,7 +438,7 @@ class Atom extends Model
|
||||
# width - The {Number} of pixels.
|
||||
# height - The {Number} of pixels.
|
||||
setSize: (width, height) ->
|
||||
ipc.send('call-window-method', 'setSize', width, height)
|
||||
@getCurrentWindow().setSize(width, height)
|
||||
|
||||
# Public: Set the position of current window.
|
||||
#
|
||||
@@ -459,6 +451,7 @@ class Atom extends Model
|
||||
center: ->
|
||||
ipc.send('call-window-method', 'center')
|
||||
|
||||
|
||||
# Schedule the window to be shown and focused on the next tick.
|
||||
#
|
||||
# This is done in a next tick to prevent a white flicker from occurring
|
||||
@@ -478,6 +471,12 @@ class Atom extends Model
|
||||
app.emit('will-exit')
|
||||
remote.process.exit(status)
|
||||
|
||||
setDocumentEdited: (edited) ->
|
||||
ipc.send('call-window-method', 'setDocumentEdited', edited)
|
||||
|
||||
setRepresentedFilename: (filename) ->
|
||||
ipc.send('call-window-method', 'setRepresentedFilename', filename)
|
||||
|
||||
# Public: Is the current window in development mode?
|
||||
inDevMode: ->
|
||||
@getLoadSettings().devMode
|
||||
@@ -503,11 +502,11 @@ class Atom extends Model
|
||||
#
|
||||
# Returns the version text {String}.
|
||||
getVersion: ->
|
||||
@constructor.getVersion()
|
||||
@appVersion ?= @getLoadSettings().appVersion
|
||||
|
||||
# Public: Determine whether the current version is an official release.
|
||||
isReleasedVersion: ->
|
||||
@constructor.isReleasedVersion()
|
||||
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
|
||||
|
||||
# Public: Get the directory path to Atom's configuration area.
|
||||
#
|
||||
|
||||
@@ -135,7 +135,7 @@ class AtomApplication
|
||||
|
||||
# Registers basic application commands, non-idempotent.
|
||||
handleEvents: ->
|
||||
@on 'application:run-all-specs', -> @runSpecs(exitWhenDone: false, resourcePath: global.devResourcePath)
|
||||
@on 'application:run-all-specs', -> @runSpecs(exitWhenDone: false, resourcePath: global.devResourcePath, safeMode: @focusedWindow()?.safeMode)
|
||||
@on 'application:run-benchmarks', -> @runBenchmarks()
|
||||
@on 'application:quit', -> app.quit()
|
||||
@on 'application:new-window', -> @openPath(windowDimensions: @focusedWindow()?.getDimensions())
|
||||
@@ -387,11 +387,13 @@ class AtomApplication
|
||||
# Opens up a new {AtomWindow} to run specs within.
|
||||
#
|
||||
# options -
|
||||
# :exitWhenDone - A Boolean that if true, will close the window upon
|
||||
# :exitWhenDone - A Boolean that, if true, will close the window upon
|
||||
# completion.
|
||||
# :resourcePath - The path to include specs from.
|
||||
# :specPath - The directory to load specs from.
|
||||
runSpecs: ({exitWhenDone, resourcePath, specDirectory, logFile}) ->
|
||||
# :safeMode - A Boolean that, if true, won't run specs from ~/.atom/packages
|
||||
# and ~/.atom/dev/packages, defaults to false.
|
||||
runSpecs: ({exitWhenDone, resourcePath, specDirectory, logFile, safeMode}) ->
|
||||
if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath)
|
||||
resourcePath = @resourcePath
|
||||
|
||||
@@ -402,7 +404,8 @@ class AtomApplication
|
||||
|
||||
isSpec = true
|
||||
devMode = true
|
||||
new AtomWindow({bootstrapScript, resourcePath, exitWhenDone, isSpec, devMode, specDirectory, logFile})
|
||||
safeMode ?= false
|
||||
new AtomWindow({bootstrapScript, resourcePath, exitWhenDone, isSpec, devMode, specDirectory, logFile, safeMode})
|
||||
|
||||
runBenchmarks: ->
|
||||
try
|
||||
|
||||
@@ -20,7 +20,7 @@ class AtomWindow
|
||||
isSpec: null
|
||||
|
||||
constructor: (settings={}) ->
|
||||
{@resourcePath, pathToOpen, initialLine, initialColumn, @isSpec, @exitWhenDone} = settings
|
||||
{@resourcePath, pathToOpen, initialLine, initialColumn, @isSpec, @exitWhenDone, @safeMode} = settings
|
||||
|
||||
# Normalize to make sure drive letter case is consistent on Windows
|
||||
@resourcePath = path.normalize(@resourcePath) if @resourcePath
|
||||
@@ -105,7 +105,7 @@ class AtomWindow
|
||||
type: 'warning'
|
||||
buttons: ['Close Window', 'Reload', 'Keep It Open']
|
||||
message: 'The editor has crashed'
|
||||
detail: 'Please report this issue to atom@github.com'
|
||||
detail: 'Please report this issue to https://github.com/atom/atom'
|
||||
switch chosen
|
||||
when 0 then @browserWindow.destroy()
|
||||
when 1 then @browserWindow.restart()
|
||||
|
||||
@@ -27,10 +27,6 @@ start = ->
|
||||
event.preventDefault()
|
||||
args.urlsToOpen.push(urlToOpen)
|
||||
|
||||
app.on 'open-url', (event, urlToOpen) ->
|
||||
event.preventDefault()
|
||||
args.urlsToOpen.push(urlToOpen)
|
||||
|
||||
app.on 'open-file', addPathToOpen
|
||||
app.on 'open-url', addUrlToOpen
|
||||
|
||||
|
||||
@@ -40,16 +40,23 @@ class BufferedProcess
|
||||
# containing the exit status (optional).
|
||||
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
|
||||
options ?= {}
|
||||
# Quick hack. Killing @process will only kill cmd.exe, and not the child
|
||||
# process and will just orphan it. Does not escape ^ (cmd's escape symbol).
|
||||
# Related to joyent/node#2318
|
||||
if process.platform is "win32"
|
||||
# Quote all arguments and escapes inner quotes
|
||||
if args?
|
||||
cmdArgs = args.map (arg) -> "\"#{arg.replace(/"/g, '\\"')}\""
|
||||
cmdArgs = args.map (arg) ->
|
||||
if command in ['explorer.exe', 'explorer'] and /^\/[a-zA-Z]+,.*$/.test(arg)
|
||||
# Don't wrap /root,C:\folder style arguments to explorer calls in
|
||||
# quotes since they will not be interpreted correctly if they are
|
||||
arg
|
||||
else
|
||||
"\"#{arg.replace(/"/g, '\\"')}\""
|
||||
else
|
||||
cmdArgs = []
|
||||
cmdArgs.unshift("\"#{command}\"")
|
||||
if /\s/.test(command)
|
||||
cmdArgs.unshift("\"#{command}\"")
|
||||
else
|
||||
cmdArgs.unshift(command)
|
||||
cmdArgs = ['/s', '/c', "\"#{cmdArgs.join(' ')}\""]
|
||||
cmdOptions = _.clone(options)
|
||||
cmdOptions.windowsVerbatimArguments = true
|
||||
@@ -108,8 +115,48 @@ class BufferedProcess
|
||||
onLines(buffered) if buffered.length > 0
|
||||
onDone()
|
||||
|
||||
# Kill all child processes of the spawned cmd.exe process on Windows.
|
||||
#
|
||||
# This is required since killing the cmd.exe does not terminate child
|
||||
# processes.
|
||||
killOnWindows: ->
|
||||
parentPid = @process.pid
|
||||
cmd = 'wmic'
|
||||
args = [
|
||||
'process'
|
||||
'where'
|
||||
"(ParentProcessId=#{parentPid})"
|
||||
'get'
|
||||
'processid'
|
||||
]
|
||||
|
||||
wmicProcess = ChildProcess.spawn(cmd, args)
|
||||
wmicProcess.on 'error', -> # ignore errors
|
||||
output = ''
|
||||
wmicProcess.stdout.on 'data', (data) -> output += data
|
||||
wmicProcess.stdout.on 'close', =>
|
||||
pidsToKill = output.split(/\s+/)
|
||||
.filter (pid) -> /^\d+$/.test(pid)
|
||||
.map (pid) -> parseInt(pid)
|
||||
.filter (pid) -> pid isnt parentPid and 0 < pid < Infinity
|
||||
|
||||
for pid in pidsToKill
|
||||
try
|
||||
process.kill(pid)
|
||||
@killProcess()
|
||||
|
||||
killProcess: ->
|
||||
@process?.kill()
|
||||
@process = null
|
||||
|
||||
# Public: Terminate the process.
|
||||
kill: ->
|
||||
return if @killed
|
||||
|
||||
@killed = true
|
||||
@process.kill()
|
||||
@process = null
|
||||
if process.platform is 'win32'
|
||||
@killOnWindows()
|
||||
else
|
||||
@killProcess()
|
||||
|
||||
undefined
|
||||
|
||||
@@ -18,11 +18,16 @@ getCachedJavaScript = (cachePath) ->
|
||||
try
|
||||
fs.readFileSync(cachePath, 'utf8')
|
||||
|
||||
convertFilePath = (filePath) ->
|
||||
if process.platform is 'win32'
|
||||
filePath = "/#{path.resolve(filePath).replace(/\\/g, '/')}"
|
||||
encodeURI(filePath)
|
||||
|
||||
compileCoffeeScript = (coffee, filePath, cachePath) ->
|
||||
{js, v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
|
||||
# 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=#{filePath}"
|
||||
js = "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=#{convertFilePath(filePath)}"
|
||||
try
|
||||
fs.writeFileSync(cachePath, js)
|
||||
js
|
||||
|
||||
+13
-2
@@ -103,8 +103,19 @@ class Config
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
# file, or `null` if the key doesn't exist in either.
|
||||
get: (keyPath) ->
|
||||
value = _.valueForKeyPath(@settings, keyPath) ? _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
_.deepClone(value)
|
||||
value = _.valueForKeyPath(@settings, keyPath)
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
|
||||
if value?
|
||||
value = _.deepClone(value)
|
||||
valueIsObject = _.isObject(value) and not _.isArray(value)
|
||||
defaultValueIsObject = _.isObject(defaultValue) and not _.isArray(defaultValue)
|
||||
if valueIsObject and defaultValueIsObject
|
||||
_.defaults(value, defaultValue)
|
||||
else
|
||||
value = _.deepClone(defaultValue)
|
||||
|
||||
value
|
||||
|
||||
# Public: Retrieves the setting for the given key as an integer.
|
||||
#
|
||||
|
||||
@@ -44,7 +44,7 @@ class ContextMenuManager
|
||||
@addBySelector(selector, menuItem, {devMode})
|
||||
|
||||
buildMenuItem: (label, command) ->
|
||||
if label is command is '-'
|
||||
if command is '-'
|
||||
{type: 'separator'}
|
||||
else
|
||||
{label, command}
|
||||
@@ -60,7 +60,7 @@ class ContextMenuManager
|
||||
# editor is in dev mode.
|
||||
addBySelector: (selector, definition, {devMode}={}) ->
|
||||
definitions = if devMode then @devModeDefinitions else @definitions
|
||||
unless _.findWhere(definitions[selector], definition)
|
||||
if not _.findWhere(definitions[selector], definition) or _.isEqual(definition, {type: 'separator'})
|
||||
(definitions[selector] ?= []).push(definition)
|
||||
|
||||
# Returns definitions which match the element and devMode.
|
||||
|
||||
@@ -8,22 +8,11 @@ CursorComponent = React.createClass
|
||||
|
||||
render: ->
|
||||
{pixelRect, defaultCharWidth} = @props
|
||||
{height, width} = pixelRect
|
||||
{top, left, height, width} = pixelRect
|
||||
width = defaultCharWidth if width is 0
|
||||
WebkitTransform = @getTransform()
|
||||
WebkitTransform = "translate(#{left}px, #{top}px)"
|
||||
|
||||
div className: 'cursor', style: {height, width, WebkitTransform}
|
||||
|
||||
getTransform: ->
|
||||
{pixelRect, scrollTop, scrollLeft, useHardwareAcceleration} = @props
|
||||
{top, left} = pixelRect
|
||||
top -= scrollTop
|
||||
left -= scrollLeft
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(#{left}px, #{top}px, 0px)"
|
||||
else
|
||||
"translate(#{left}px, #{top}px)"
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
not isEqualForProperties(newProps, @props, 'pixelRect', 'scrollTop', 'scrollLeft', 'defaultCharWidth')
|
||||
not isEqualForProperties(newProps, @props, 'pixelRect', 'defaultCharWidth')
|
||||
|
||||
+5
-4
@@ -95,8 +95,8 @@ class Cursor extends Model
|
||||
getBufferPosition: ->
|
||||
@marker.getHeadBufferPosition()
|
||||
|
||||
autoscroll: ->
|
||||
@editor.scrollToScreenRange(@getScreenRange())
|
||||
autoscroll: (options) ->
|
||||
@editor.scrollToScreenRange(@getScreenRange(), options)
|
||||
|
||||
# Public: If the marker range is empty, the cursor is marked as being visible.
|
||||
updateVisibility: ->
|
||||
@@ -273,9 +273,10 @@ class Cursor extends Model
|
||||
# line.
|
||||
moveToFirstCharacterOfLine: ->
|
||||
{row, column} = @getScreenPosition()
|
||||
screenline = @editor.lineForScreenRow(row)
|
||||
|
||||
goalColumn = screenline.text.search(/\S/)
|
||||
bufferRange = @editor.bufferRangeForScreenRange([[row, 0], [row, Infinity]])
|
||||
screenLineText = @editor.getTextInBufferRange(bufferRange)
|
||||
goalColumn = screenLineText.search(/\S/)
|
||||
goalColumn = 0 if goalColumn == column or goalColumn == -1
|
||||
@setScreenPosition([row, goalColumn])
|
||||
|
||||
|
||||
@@ -12,16 +12,16 @@ CursorsComponent = React.createClass
|
||||
cursorBlinkIntervalHandle: null
|
||||
|
||||
render: ->
|
||||
{cursorPixelRects, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration} = @props
|
||||
{performedInitialMeasurement, cursorPixelRects, defaultCharWidth} = @props
|
||||
{blinkOff} = @state
|
||||
|
||||
className = 'cursors'
|
||||
className += ' blink-off' if blinkOff
|
||||
|
||||
div {className},
|
||||
if @isMounted()
|
||||
if performedInitialMeasurement
|
||||
for key, pixelRect of cursorPixelRects
|
||||
CursorComponent({key, pixelRect, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration})
|
||||
CursorComponent({key, pixelRect, defaultCharWidth})
|
||||
|
||||
getInitialState: ->
|
||||
blinkOff: false
|
||||
|
||||
@@ -55,13 +55,13 @@ class Decoration
|
||||
|
||||
# Public: Destroy this marker.
|
||||
#
|
||||
# If you own the marker, you should use {Marker:destroy} which will destroy
|
||||
# If you own the marker, you should use {Marker::destroy} which will destroy
|
||||
# this decoration.
|
||||
destroy: ->
|
||||
return if @isDestroyed
|
||||
@isDestroyed = true
|
||||
@displayBuffer.removeDecoration(this)
|
||||
@emit 'destoryed'
|
||||
@emit 'destroyed'
|
||||
|
||||
# Public: Update the marker with new params. Allows you to change the decoration's class.
|
||||
#
|
||||
|
||||
@@ -38,10 +38,10 @@ class DisplayBuffer extends Model
|
||||
verticalScrollbarWidth: 15
|
||||
scopedCharacterWidthsChangeCount: 0
|
||||
|
||||
constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer}={}) ->
|
||||
constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, @invisibles}={}) ->
|
||||
super
|
||||
@softWrap ?= atom.config.get('editor.softWrap') ? false
|
||||
@tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer})
|
||||
@tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, @invisibles})
|
||||
@buffer = @tokenizedBuffer.buffer
|
||||
@charWidthsByScope = {}
|
||||
@markers = {}
|
||||
@@ -81,7 +81,7 @@ class DisplayBuffer extends Model
|
||||
params
|
||||
|
||||
copy: ->
|
||||
newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength()})
|
||||
newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength(), @invisibles})
|
||||
newDisplayBuffer.setScrollTop(@getScrollTop())
|
||||
newDisplayBuffer.setScrollLeft(@getScrollLeft())
|
||||
|
||||
@@ -340,6 +340,9 @@ class DisplayBuffer extends Model
|
||||
setTabLength: (tabLength) ->
|
||||
@tokenizedBuffer.setTabLength(tabLength)
|
||||
|
||||
setInvisibles: (@invisibles) ->
|
||||
@tokenizedBuffer.setInvisibles(@invisibles)
|
||||
|
||||
# Deprecated: Use the softWrap property directly
|
||||
setSoftWrap: (@softWrap) -> @softWrap
|
||||
|
||||
@@ -356,8 +359,10 @@ class DisplayBuffer extends Model
|
||||
if editorWidthInChars isnt previousWidthInChars and @softWrap
|
||||
@updateWrappedScreenLines()
|
||||
|
||||
# Returns the editor width in characters for soft wrap.
|
||||
getEditorWidthInChars: ->
|
||||
width = @getWidth()
|
||||
width = @width ? @getScrollWidth()
|
||||
width -= @getVerticalScrollbarWidth()
|
||||
if width? and @defaultCharWidth > 0
|
||||
Math.floor(width / @defaultCharWidth)
|
||||
else
|
||||
|
||||
+216
-162
@@ -3,17 +3,15 @@ React = require 'react-atom-fork'
|
||||
{debounce, defaults, isEqualForProperties} = require 'underscore-plus'
|
||||
scrollbarStyle = require 'scrollbar-style'
|
||||
{Range, Point} = require 'text-buffer'
|
||||
grim = require 'grim'
|
||||
|
||||
GutterComponent = require './gutter-component'
|
||||
InputComponent = require './input-component'
|
||||
CursorsComponent = require './cursors-component'
|
||||
LinesComponent = require './lines-component'
|
||||
ScrollbarComponent = require './scrollbar-component'
|
||||
ScrollbarCornerComponent = require './scrollbar-corner-component'
|
||||
SubscriberMixin = require './subscriber-mixin'
|
||||
|
||||
DummyHighlightDecoration = {id: 'dummy', startPixelPosition: {top: 0, left: 0}, endPixelPosition: {top: 0, left: 0}, decorations: [{class: 'dummy'}]}
|
||||
|
||||
module.exports =
|
||||
EditorComponent = React.createClass
|
||||
displayName: 'EditorComponent'
|
||||
@@ -22,6 +20,10 @@ EditorComponent = React.createClass
|
||||
statics:
|
||||
performSyncUpdates: false
|
||||
|
||||
visible: false
|
||||
autoHeight: false
|
||||
backgroundColor: null
|
||||
gutterBackgroundColor: null
|
||||
pendingScrollTop: null
|
||||
pendingScrollLeft: null
|
||||
selectOnMouseMove: false
|
||||
@@ -32,30 +34,28 @@ EditorComponent = React.createClass
|
||||
selectionChanged: false
|
||||
selectionAdded: false
|
||||
scrollingVertically: false
|
||||
gutterWidth: 0
|
||||
refreshingScrollbars: false
|
||||
measuringScrollbars: true
|
||||
pendingVerticalScrollDelta: 0
|
||||
pendingHorizontalScrollDelta: 0
|
||||
mouseWheelScreenRow: null
|
||||
mouseWheelScreenRowClearDelay: 150
|
||||
scrollSensitivity: 0.4
|
||||
scrollViewMeasurementRequested: false
|
||||
heightAndWidthMeasurementRequested: false
|
||||
measureLineHeightAndDefaultCharWidthWhenShown: false
|
||||
remeasureCharacterWidthsIfVisibleAfterNextUpdate: false
|
||||
remeasureCharacterWidthsWhenShown: false
|
||||
inputEnabled: true
|
||||
scrollViewMeasurementInterval: 100
|
||||
scopedCharacterWidthsChangeCount: null
|
||||
scrollViewMeasurementPaused: false
|
||||
domPollingInterval: 100
|
||||
domPollingIntervalId: null
|
||||
domPollingPaused: false
|
||||
|
||||
render: ->
|
||||
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, showLineNumbers, visible} = @state
|
||||
{editor, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
|
||||
{focused, showIndentGuide, showLineNumbers, visible} = @state
|
||||
{editor, mini, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
|
||||
maxLineNumberDigits = editor.getLineCount().toString().length
|
||||
invisibles = if showInvisibles then @state.invisibles else {}
|
||||
hasSelection = editor.getSelection()? and !editor.getSelection().isEmpty()
|
||||
style = {}
|
||||
|
||||
if @isMounted()
|
||||
if @performedInitialMeasurement
|
||||
renderedRowRange = @getRenderedRowRange()
|
||||
[renderedStartRow, renderedEndRow] = renderedRowRange
|
||||
cursorPixelRects = @getCursorPixelRects(renderedRowRange)
|
||||
@@ -63,6 +63,7 @@ EditorComponent = React.createClass
|
||||
decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
|
||||
highlightDecorations = @getHighlightDecorations(decorations)
|
||||
lineDecorations = @getLineDecorations(decorations)
|
||||
placeholderText = @props.placeholderText if @props.placeholderText? and editor.isEmpty()
|
||||
|
||||
scrollHeight = editor.getScrollHeight()
|
||||
scrollWidth = editor.getScrollWidth()
|
||||
@@ -81,16 +82,19 @@ EditorComponent = React.createClass
|
||||
if @mouseWheelScreenRow? and not (renderedStartRow <= @mouseWheelScreenRow < renderedEndRow)
|
||||
mouseWheelScreenRow = @mouseWheelScreenRow
|
||||
|
||||
className = 'editor-contents editor-colors'
|
||||
style.height = scrollViewHeight if @autoHeight
|
||||
|
||||
className = 'editor-contents'
|
||||
className += ' is-focused' if focused
|
||||
className += ' has-selection' if hasSelection
|
||||
|
||||
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1,
|
||||
if showLineNumbers
|
||||
div {className, style, tabIndex: -1},
|
||||
if @shouldRenderGutter()
|
||||
GutterComponent {
|
||||
ref: 'gutter', onMouseDown: @onGutterMouseDown, onWidthChanged: @onGutterWidthChanged,
|
||||
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
|
||||
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow, @useHardwareAcceleration
|
||||
ref: 'gutter', onMouseDown: @onGutterMouseDown, lineDecorations,
|
||||
defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
|
||||
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow,
|
||||
@useHardwareAcceleration, @performedInitialMeasurement, @backgroundColor, @gutterBackgroundColor
|
||||
}
|
||||
|
||||
div ref: 'scrollView', className: 'scroll-view', onMouseDown: @onMouseDown,
|
||||
@@ -101,18 +105,28 @@ EditorComponent = React.createClass
|
||||
onFocus: @onInputFocused
|
||||
onBlur: @onInputBlurred
|
||||
|
||||
CursorsComponent {
|
||||
scrollTop, scrollLeft, cursorPixelRects, cursorBlinkPeriod, cursorBlinkResumeDelay,
|
||||
lineHeightInPixels, defaultCharWidth, @scopedCharacterWidthsChangeCount, @useHardwareAcceleration
|
||||
}
|
||||
LinesComponent {
|
||||
ref: 'lines',
|
||||
editor, lineHeightInPixels, defaultCharWidth, lineDecorations, highlightDecorations,
|
||||
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
|
||||
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
|
||||
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration
|
||||
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow,
|
||||
@visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration,
|
||||
placeholderText, @performedInitialMeasurement, @backgroundColor, cursorPixelRects,
|
||||
cursorBlinkPeriod, cursorBlinkResumeDelay, mini
|
||||
}
|
||||
|
||||
ScrollbarComponent
|
||||
ref: 'horizontalScrollbar'
|
||||
className: 'horizontal-scrollbar'
|
||||
orientation: 'horizontal'
|
||||
onScroll: @onHorizontalScroll
|
||||
scrollLeft: scrollLeft
|
||||
scrollWidth: scrollWidth
|
||||
visible: horizontallyScrollable and not @refreshingScrollbars and not @measuringScrollbars
|
||||
scrollableInOppositeDirection: verticallyScrollable
|
||||
verticalScrollbarWidth: verticalScrollbarWidth
|
||||
horizontalScrollbarHeight: horizontalScrollbarHeight
|
||||
|
||||
ScrollbarComponent
|
||||
ref: 'verticalScrollbar'
|
||||
className: 'vertical-scrollbar'
|
||||
@@ -125,18 +139,6 @@ EditorComponent = React.createClass
|
||||
verticalScrollbarWidth: verticalScrollbarWidth
|
||||
horizontalScrollbarHeight: horizontalScrollbarHeight
|
||||
|
||||
ScrollbarComponent
|
||||
ref: 'horizontalScrollbar'
|
||||
className: 'horizontal-scrollbar'
|
||||
orientation: 'horizontal'
|
||||
onScroll: @onHorizontalScroll
|
||||
scrollLeft: scrollLeft
|
||||
scrollWidth: scrollWidth + @gutterWidth
|
||||
visible: horizontallyScrollable and not @refreshingScrollbars and not @measuringScrollbars
|
||||
scrollableInOppositeDirection: verticallyScrollable
|
||||
verticalScrollbarWidth: verticalScrollbarWidth
|
||||
horizontalScrollbarHeight: horizontalScrollbarHeight
|
||||
|
||||
# Also used to measure the height/width of scrollbars after the initial render
|
||||
ScrollbarCornerComponent
|
||||
ref: 'scrollbarCorner'
|
||||
@@ -149,13 +151,15 @@ EditorComponent = React.createClass
|
||||
{editor} = @props
|
||||
Math.max(1, Math.ceil(editor.getHeight() / editor.getLineHeightInPixels()))
|
||||
|
||||
getInitialState: ->
|
||||
visible: true
|
||||
shouldRenderGutter: ->
|
||||
not @props.mini and @state.showLineNumbers
|
||||
|
||||
getInitialState: -> {}
|
||||
|
||||
getDefaultProps: ->
|
||||
cursorBlinkPeriod: 800
|
||||
cursorBlinkResumeDelay: 100
|
||||
lineOverdrawMargin: 8
|
||||
lineOverdrawMargin: 15
|
||||
|
||||
componentWillMount: ->
|
||||
@pendingChanges = []
|
||||
@@ -166,26 +170,34 @@ EditorComponent = React.createClass
|
||||
componentDidMount: ->
|
||||
{editor} = @props
|
||||
|
||||
@scrollViewMeasurementIntervalId = setInterval(@measureScrollView, @scrollViewMeasurementInterval)
|
||||
@domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval)
|
||||
|
||||
@observeEditor()
|
||||
@listenForDOMEvents()
|
||||
@listenForCommands()
|
||||
|
||||
@subscribe atom.themes, 'stylesheet-added stylsheet-removed', @onStylesheetsChanged
|
||||
@subscribe atom.themes, 'stylesheet-added stylesheet-removed stylesheet-updated', @onStylesheetsChanged
|
||||
@subscribe scrollbarStyle.changes, @refreshScrollbars
|
||||
|
||||
editor.setVisible(true)
|
||||
|
||||
@measureLineHeightAndDefaultCharWidth()
|
||||
@measureScrollView()
|
||||
@measureScrollbars()
|
||||
if @visible = @isVisible()
|
||||
@performInitialMeasurement()
|
||||
@forceUpdate()
|
||||
|
||||
componentWillUnmount: ->
|
||||
@props.parentView.trigger 'editor:will-be-removed', [@props.parentView]
|
||||
@unsubscribe()
|
||||
clearInterval(@scrollViewMeasurementIntervalId)
|
||||
@scrollViewMeasurementIntervalId = null
|
||||
window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
clearInterval(@domPollingIntervalId)
|
||||
@domPollingIntervalId = null
|
||||
@props.editor.destroy()
|
||||
|
||||
componentWillReceiveProps: (newProps) ->
|
||||
@props.editor.setMini(newProps.mini)
|
||||
|
||||
componentWillUpdate: ->
|
||||
wasVisible = @visible
|
||||
@visible = @isVisible()
|
||||
@performInitialMeasurement() if @visible and not wasVisible
|
||||
|
||||
componentDidUpdate: (prevProps, prevState) ->
|
||||
cursorsMoved = @cursorsMoved
|
||||
@@ -197,15 +209,29 @@ EditorComponent = React.createClass
|
||||
|
||||
if @props.editor.isAlive()
|
||||
@updateParentViewFocusedClassIfNeeded(prevState)
|
||||
@updateParentViewMiniClassIfNeeded(prevState)
|
||||
@props.parentView.trigger 'cursor:moved' if cursorsMoved
|
||||
@props.parentView.trigger 'selection:changed' if selectionChanged
|
||||
@props.parentView.trigger 'editor:display-updated'
|
||||
|
||||
@measureScrollbars() if @measuringScrollbars
|
||||
@measureLineHeightAndCharWidthsIfNeeded(prevState)
|
||||
@remeasureCharacterWidthsIfNeeded(prevState)
|
||||
if @performedInitialMeasurement
|
||||
@measureScrollbars() if @measuringScrollbars
|
||||
|
||||
performInitialMeasurement: ->
|
||||
@updatesPaused = true
|
||||
@measureHeightAndWidth()
|
||||
@sampleFontStyling()
|
||||
@sampleBackgroundColors()
|
||||
@measureScrollbars()
|
||||
@measureLineHeightAndDefaultCharWidth() if @measureLineHeightAndDefaultCharWidthWhenShown
|
||||
@remeasureCharacterWidths() if @remeasureCharacterWidthsWhenShown
|
||||
@props.editor.setVisible(true)
|
||||
@updatesPaused = false
|
||||
@performedInitialMeasurement = true
|
||||
|
||||
requestUpdate: ->
|
||||
return unless @isMounted()
|
||||
|
||||
if @updatesPaused
|
||||
@updateRequestedWhilePaused = true
|
||||
return
|
||||
@@ -214,13 +240,13 @@ EditorComponent = React.createClass
|
||||
@forceUpdate()
|
||||
else unless @updateRequested
|
||||
@updateRequested = true
|
||||
setImmediate =>
|
||||
requestAnimationFrame =>
|
||||
@updateRequested = false
|
||||
@forceUpdate() if @isMounted()
|
||||
|
||||
requestAnimationFrame: (fn) ->
|
||||
@updatesPaused = true
|
||||
@pauseScrollViewMeasurement()
|
||||
@pauseDOMPolling()
|
||||
requestAnimationFrame =>
|
||||
fn()
|
||||
@updatesPaused = false
|
||||
@@ -228,6 +254,9 @@ EditorComponent = React.createClass
|
||||
@updateRequestedWhilePaused = false
|
||||
@forceUpdate()
|
||||
|
||||
getTopmostDOMNode: ->
|
||||
@props.parentView.element
|
||||
|
||||
getRenderedRowRange: ->
|
||||
{editor, lineOverdrawMargin} = @props
|
||||
[visibleStartRow, visibleEndRow] = editor.getVisibleRowRange()
|
||||
@@ -273,7 +302,9 @@ EditorComponent = React.createClass
|
||||
cursorPixelRects
|
||||
|
||||
getLineDecorations: (decorationsByMarkerId) ->
|
||||
{editor} = @props
|
||||
{editor, mini} = @props
|
||||
return {} if mini
|
||||
|
||||
decorationsByScreenRow = {}
|
||||
for markerId, decorations of decorationsByMarkerId
|
||||
marker = editor.getMarker(markerId)
|
||||
@@ -317,11 +348,6 @@ EditorComponent = React.createClass
|
||||
decorations: []
|
||||
filteredDecorations[markerId].decorations.push decorationParams
|
||||
|
||||
# At least in Chromium 31, removing the last highlight causes a rendering
|
||||
# artifact where chunks of the lines disappear, so we always leave this
|
||||
# dummy highlight in place to prevent that.
|
||||
filteredDecorations['dummy'] = DummyHighlightDecoration
|
||||
|
||||
filteredDecorations
|
||||
|
||||
observeEditor: ->
|
||||
@@ -350,7 +376,7 @@ EditorComponent = React.createClass
|
||||
|
||||
scrollViewNode = @refs.scrollView.getDOMNode()
|
||||
scrollViewNode.addEventListener 'scroll', @onScrollViewScroll
|
||||
window.addEventListener 'resize', @requestScrollViewMeasurement
|
||||
window.addEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
|
||||
@listenForIMEEvents()
|
||||
|
||||
@@ -474,7 +500,7 @@ EditorComponent = React.createClass
|
||||
'editor:fold-at-indent-level-9': => editor.foldAllAtIndentLevel(8)
|
||||
'editor:toggle-line-comments': => editor.toggleLineCommentsInSelection()
|
||||
'editor:log-cursor-scope': => editor.logCursorScope()
|
||||
'editor:checkout-head-revision': => editor.checkoutHead()
|
||||
'editor:checkout-head-revision': => atom.project.getRepo()?.checkoutHeadForEditor(editor)
|
||||
'editor:copy-path': => editor.copyPathToClipboard()
|
||||
'editor:move-line-up': => editor.moveLineUp()
|
||||
'editor:move-line-down': => editor.moveLineDown()
|
||||
@@ -488,24 +514,31 @@ EditorComponent = React.createClass
|
||||
addCommandListeners: (listenersByCommandName) ->
|
||||
{parentView} = @props
|
||||
|
||||
for command, listener of listenersByCommandName
|
||||
parentView.command command, listener
|
||||
addListener = (command, listener) ->
|
||||
parentView.command command, (event) ->
|
||||
event.stopPropagation()
|
||||
listener(event)
|
||||
|
||||
addListener(command, listener) for command, listener of listenersByCommandName
|
||||
|
||||
return
|
||||
|
||||
observeConfig: ->
|
||||
@subscribe atom.config.observe 'editor.fontFamily', @setFontFamily
|
||||
@subscribe atom.config.observe 'editor.fontSize', @setFontSize
|
||||
@subscribe atom.config.observe 'editor.lineHeight', @setLineHeight
|
||||
@subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide
|
||||
@subscribe atom.config.observe 'editor.invisibles', @setInvisibles
|
||||
@subscribe atom.config.observe 'editor.showInvisibles', @setShowInvisibles
|
||||
@subscribe atom.config.observe 'editor.showLineNumbers', @setShowLineNumbers
|
||||
@subscribe atom.config.observe 'editor.scrollSensitivity', @setScrollSensitivity
|
||||
@subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration
|
||||
|
||||
onFocus: ->
|
||||
@refs.input.focus()
|
||||
@refs.input.focus() if @isMounted()
|
||||
|
||||
onTextInput: (event) ->
|
||||
event.stopPropagation()
|
||||
|
||||
# If we prevent the insertion of a space character, then the browser
|
||||
# interprets the spacebar keypress as a page-down command.
|
||||
event.preventDefault() unless event.data is ' '
|
||||
|
||||
return unless @isInputEnabled()
|
||||
|
||||
{editor} = @props
|
||||
@@ -518,12 +551,8 @@ EditorComponent = React.createClass
|
||||
selectedLength = inputNode.selectionEnd - inputNode.selectionStart
|
||||
editor.selectLeft() if selectedLength is 1
|
||||
|
||||
editor.insertText(event.data)
|
||||
inputNode.value = event.data
|
||||
inputNode.value = event.data if editor.insertText(event.data)
|
||||
|
||||
# If we prevent the insertion of a space character, then the browser
|
||||
# interprets the spacebar keypress as a page-down command.
|
||||
event.preventDefault() unless event.data is ' '
|
||||
|
||||
onInputFocused: ->
|
||||
@setState(focused: true)
|
||||
@@ -557,28 +586,23 @@ EditorComponent = React.createClass
|
||||
@pendingScrollLeft = null
|
||||
|
||||
onMouseWheel: (event) ->
|
||||
event.preventDefault()
|
||||
animationFramePending = @pendingHorizontalScrollDelta isnt 0 or @pendingVerticalScrollDelta isnt 0
|
||||
{editor} = @props
|
||||
|
||||
# Only scroll in one direction at a time
|
||||
{wheelDeltaX, wheelDeltaY} = event
|
||||
if Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY)
|
||||
# Scrolling horizontally
|
||||
@pendingHorizontalScrollDelta -= Math.round(wheelDeltaX * @scrollSensitivity)
|
||||
previousScrollLeft = editor.getScrollLeft()
|
||||
editor.setScrollLeft(previousScrollLeft - Math.round(wheelDeltaX * @scrollSensitivity))
|
||||
event.preventDefault() unless previousScrollLeft is editor.getScrollLeft()
|
||||
else
|
||||
# Scrolling vertically
|
||||
@pendingVerticalScrollDelta -= Math.round(wheelDeltaY * @scrollSensitivity)
|
||||
@mouseWheelScreenRow = @screenRowForNode(event.target)
|
||||
@clearMouseWheelScreenRowAfterDelay ?= debounce(@clearMouseWheelScreenRow, @mouseWheelScreenRowClearDelay)
|
||||
@clearMouseWheelScreenRowAfterDelay()
|
||||
|
||||
unless animationFramePending
|
||||
@requestAnimationFrame =>
|
||||
{editor} = @props
|
||||
editor.setScrollTop(editor.getScrollTop() + @pendingVerticalScrollDelta)
|
||||
editor.setScrollLeft(editor.getScrollLeft() + @pendingHorizontalScrollDelta)
|
||||
@pendingVerticalScrollDelta = 0
|
||||
@pendingHorizontalScrollDelta = 0
|
||||
previousScrollTop = editor.getScrollTop()
|
||||
editor.setScrollTop(previousScrollTop - Math.round(wheelDeltaY * @scrollSensitivity))
|
||||
event.preventDefault() unless previousScrollTop is editor.getScrollTop()
|
||||
|
||||
onScrollViewScroll: ->
|
||||
if @isMounted()
|
||||
@@ -654,9 +678,12 @@ EditorComponent = React.createClass
|
||||
editor.setSelectedScreenRange([tailPosition, [dragRow + 1, 0]])
|
||||
|
||||
onStylesheetsChanged: (stylesheet) ->
|
||||
return unless @performedInitialMeasurement
|
||||
|
||||
@refreshScrollbars() if @containsScrollbarSelector(stylesheet)
|
||||
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = true
|
||||
@requestUpdate() if @state.visible
|
||||
@sampleFontStyling()
|
||||
@sampleBackgroundColors()
|
||||
@remeasureCharacterWidths()
|
||||
|
||||
onScreenLinesChanged: (change) ->
|
||||
{editor} = @props
|
||||
@@ -733,78 +760,114 @@ EditorComponent = React.createClass
|
||||
window.addEventListener('mousemove', onMouseMove)
|
||||
window.addEventListener('mouseup', onMouseUp)
|
||||
|
||||
pauseScrollViewMeasurement: ->
|
||||
@scrollViewMeasurementPaused = true
|
||||
@resumeScrollViewMeasurementAfterDelay ?= debounce(@resumeScrollViewMeasurement, 100)
|
||||
@resumeScrollViewMeasurementAfterDelay()
|
||||
isVisible: ->
|
||||
node = @getDOMNode()
|
||||
node.offsetHeight > 0 or node.offsetWidth > 0
|
||||
|
||||
resumeScrollViewMeasurement: ->
|
||||
@scrollViewMeasurementPaused = false
|
||||
pauseDOMPolling: ->
|
||||
@domPollingPaused = true
|
||||
@resumeDOMPollingAfterDelay ?= debounce(@resumeDOMPolling, 100)
|
||||
@resumeDOMPollingAfterDelay()
|
||||
|
||||
resumeScrollViewMeasurementAfterDelay: null # created lazily
|
||||
resumeDOMPolling: ->
|
||||
@domPollingPaused = false
|
||||
|
||||
requestScrollViewMeasurement: ->
|
||||
return if @scrollViewMeasurementRequested
|
||||
resumeDOMPollingAfterDelay: null # created lazily
|
||||
|
||||
@scrollViewMeasurementRequested = true
|
||||
pollDOM: ->
|
||||
return if @domPollingPaused or @updateRequested or not @isMounted()
|
||||
|
||||
wasVisible = @visible
|
||||
if @visible = @isVisible()
|
||||
if wasVisible
|
||||
@measureHeightAndWidth()
|
||||
@sampleFontStyling()
|
||||
@sampleBackgroundColors()
|
||||
else
|
||||
@performInitialMeasurement()
|
||||
@forceUpdate()
|
||||
|
||||
requestHeightAndWidthMeasurement: ->
|
||||
return if @heightAndWidthMeasurementRequested
|
||||
|
||||
@heightAndWidthMeasurementRequested = true
|
||||
requestAnimationFrame =>
|
||||
@scrollViewMeasurementRequested = false
|
||||
@measureScrollView()
|
||||
@heightAndWidthMeasurementRequested = false
|
||||
@measureHeightAndWidth()
|
||||
|
||||
# Measure explicitly-styled height and width and relay them to the model. If
|
||||
# these values aren't explicitly styled, we assume the editor is unconstrained
|
||||
# and use the scrollHeight / scrollWidth as its height and width in
|
||||
# calculations.
|
||||
measureScrollView: ->
|
||||
return if @scrollViewMeasurementPaused
|
||||
measureHeightAndWidth: ->
|
||||
return unless @isMounted()
|
||||
|
||||
{editor} = @props
|
||||
editorNode = @getDOMNode()
|
||||
{editor, parentView} = @props
|
||||
parentNode = parentView.element
|
||||
scrollViewNode = @refs.scrollView.getDOMNode()
|
||||
{position} = getComputedStyle(editorNode)
|
||||
{width, height} = editorNode.style
|
||||
{position} = getComputedStyle(parentNode)
|
||||
{height} = parentNode.style
|
||||
|
||||
if position is 'absolute' or height
|
||||
if @autoHeight
|
||||
@autoHeight = false
|
||||
@forceUpdate()
|
||||
|
||||
clientHeight = scrollViewNode.clientHeight
|
||||
editor.setHeight(clientHeight) if clientHeight > 0
|
||||
else
|
||||
editor.setHeight(null)
|
||||
@autoHeight = true
|
||||
|
||||
if position is 'absolute' or width
|
||||
clientWidth = scrollViewNode.clientWidth
|
||||
paddingLeft = parseInt(getComputedStyle(scrollViewNode).paddingLeft)
|
||||
clientWidth -= paddingLeft
|
||||
editor.setWidth(clientWidth) if clientWidth > 0
|
||||
clientWidth = scrollViewNode.clientWidth
|
||||
paddingLeft = parseInt(getComputedStyle(scrollViewNode).paddingLeft)
|
||||
clientWidth -= paddingLeft
|
||||
editor.setWidth(clientWidth) if clientWidth > 0
|
||||
|
||||
measureLineHeightAndCharWidthsIfNeeded: (prevState) ->
|
||||
if not isEqualForProperties(prevState, @state, 'lineHeight', 'fontSize', 'fontFamily')
|
||||
if @state.visible
|
||||
@measureLineHeightAndDefaultCharWidth()
|
||||
else
|
||||
@measureLineHeightAndDefaultCharWidthWhenShown = true
|
||||
else if @measureLineHeightAndDefaultCharWidthWhenShown and @state.visible and not prevState.visible
|
||||
sampleFontStyling: ->
|
||||
oldFontSize = @fontSize
|
||||
oldFontFamily = @fontFamily
|
||||
oldLineHeight = @lineHeight
|
||||
|
||||
{@fontSize, @fontFamily, @lineHeight} = getComputedStyle(@getTopmostDOMNode())
|
||||
|
||||
if @fontSize isnt oldFontSize or @fontFamily isnt oldFontFamily or @lineHeight isnt oldLineHeight
|
||||
@measureLineHeightAndDefaultCharWidth()
|
||||
|
||||
measureLineHeightAndDefaultCharWidth: ->
|
||||
@measureLineHeightAndDefaultCharWidthWhenShown = false
|
||||
@refs.lines.measureLineHeightAndDefaultCharWidth()
|
||||
|
||||
remeasureCharacterWidthsIfNeeded: (prevState) ->
|
||||
if not isEqualForProperties(prevState, @state, 'fontSize', 'fontFamily')
|
||||
if @state.visible
|
||||
@remeasureCharacterWidths()
|
||||
else
|
||||
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = true
|
||||
else if @remeasureCharacterWidthsIfVisibleAfterNextUpdate and @state.visible
|
||||
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = false
|
||||
if (@fontSize isnt oldFontSize or @fontFamily isnt oldFontFamily) and @performedInitialMeasurement
|
||||
@remeasureCharacterWidths()
|
||||
|
||||
remeasureCharacterWidths: ->
|
||||
@refs.lines.remeasureCharacterWidths()
|
||||
sampleBackgroundColors: (suppressUpdate) ->
|
||||
{parentView} = @props
|
||||
{showLineNumbers} = @state
|
||||
{backgroundColor} = getComputedStyle(parentView.element)
|
||||
|
||||
onGutterWidthChanged: (@gutterWidth) ->
|
||||
@requestUpdate()
|
||||
if backgroundColor isnt @backgroundColor
|
||||
@backgroundColor = backgroundColor
|
||||
@requestUpdate() unless suppressUpdate
|
||||
|
||||
if @shouldRenderGutter()
|
||||
gutterBackgroundColor = getComputedStyle(@refs.gutter.getDOMNode()).backgroundColor
|
||||
if gutterBackgroundColor isnt @gutterBackgroundColor
|
||||
@gutterBackgroundColor = gutterBackgroundColor
|
||||
@requestUpdate() unless suppressUpdate
|
||||
|
||||
measureLineHeightAndDefaultCharWidth: ->
|
||||
if @visible
|
||||
@measureLineHeightAndDefaultCharWidthWhenShown = false
|
||||
@refs.lines.measureLineHeightAndDefaultCharWidth()
|
||||
else
|
||||
@measureLineHeightAndDefaultCharWidthWhenShown = true
|
||||
|
||||
remeasureCharacterWidths: ->
|
||||
if @visible
|
||||
@remeasureCharacterWidthsWhenShown = false
|
||||
@refs.lines.remeasureCharacterWidths()
|
||||
else
|
||||
@remeasureCharacterWidthsWhenShown = true
|
||||
|
||||
measureScrollbars: ->
|
||||
return unless @visible
|
||||
@measuringScrollbars = false
|
||||
|
||||
{editor} = @props
|
||||
@@ -861,48 +924,35 @@ EditorComponent = React.createClass
|
||||
node = node.parentNode
|
||||
null
|
||||
|
||||
hide: ->
|
||||
@setState(visible: false)
|
||||
|
||||
show: ->
|
||||
@setState(visible: true)
|
||||
|
||||
getFontSize: ->
|
||||
@state.fontSize
|
||||
parseInt(getComputedStyle(@getTopmostDOMNode()).fontSize)
|
||||
|
||||
setFontSize: (fontSize) ->
|
||||
@setState({fontSize})
|
||||
@getTopmostDOMNode().style.fontSize = fontSize + 'px'
|
||||
@sampleFontStyling()
|
||||
|
||||
getFontFamily: ->
|
||||
@state.fontFamily
|
||||
getComputedStyle(@getTopmostDOMNode()).fontFamily
|
||||
|
||||
setFontFamily: (fontFamily) ->
|
||||
@setState({fontFamily})
|
||||
@getTopmostDOMNode().style.fontFamily = fontFamily
|
||||
@sampleFontStyling()
|
||||
|
||||
setLineHeight: (lineHeight) ->
|
||||
@setState({lineHeight})
|
||||
@getTopmostDOMNode().style.lineHeight = lineHeight
|
||||
@sampleFontStyling()
|
||||
|
||||
setShowIndentGuide: (showIndentGuide) ->
|
||||
@setState({showIndentGuide})
|
||||
|
||||
# Public: Defines which characters are invisible.
|
||||
#
|
||||
# invisibles - An {Object} defining the invisible characters:
|
||||
# :eol - The end of line invisible {String} (default: `\u00ac`).
|
||||
# :space - The space invisible {String} (default: `\u00b7`).
|
||||
# :tab - The tab invisible {String} (default: `\u00bb`).
|
||||
# :cr - The carriage return invisible {String} (default: `\u00a4`).
|
||||
# Deprecated
|
||||
setInvisibles: (invisibles={}) ->
|
||||
defaults invisibles,
|
||||
eol: '\u00ac'
|
||||
space: '\u00b7'
|
||||
tab: '\u00bb'
|
||||
cr: '\u00a4'
|
||||
|
||||
@setState({invisibles})
|
||||
grim.deprecate "Use config.set('editor.invisibles', invisibles) instead"
|
||||
atom.config.set('editor.invisibles', invisibles)
|
||||
|
||||
# Deprecated
|
||||
setShowInvisibles: (showInvisibles) ->
|
||||
@setState({showInvisibles})
|
||||
atom.config.set('editor.showInvisibles', showInvisibles)
|
||||
|
||||
setShowLineNumbers: (showLineNumbers) ->
|
||||
@setState({showLineNumbers})
|
||||
@@ -940,6 +990,10 @@ EditorComponent = React.createClass
|
||||
if prevState.focused isnt @state.focused
|
||||
@props.parentView.toggleClass('is-focused', @props.focused)
|
||||
|
||||
updateParentViewMiniClassIfNeeded: (prevProps) ->
|
||||
if prevProps.mini isnt @props.mini
|
||||
@props.parentView.toggleClass('mini', @props.mini)
|
||||
|
||||
runScrollBenchmark: ->
|
||||
unless process.env.NODE_ENV is 'production'
|
||||
ReactPerf = require 'react-atom-fork/lib/ReactDefaultPerf'
|
||||
|
||||
@@ -58,6 +58,12 @@ class EditorView extends View
|
||||
softWrapAtPreferredLineLength: false
|
||||
scrollSensitivity: 40
|
||||
useHardwareAcceleration: true
|
||||
confirmCheckoutHeadRevision: true
|
||||
invisibles:
|
||||
eol: '\u00ac'
|
||||
space: '\u00b7'
|
||||
tab: '\u00bb'
|
||||
cr: '\u00a4'
|
||||
|
||||
@nextEditorId: 1
|
||||
|
||||
@@ -231,7 +237,7 @@ class EditorView extends View
|
||||
'editor:fold-at-indent-level-9': => @editor.foldAllAtIndentLevel(8)
|
||||
'editor:toggle-line-comments': => @toggleLineCommentsInSelection()
|
||||
'editor:log-cursor-scope': => @logCursorScope()
|
||||
'editor:checkout-head-revision': => @checkoutHead()
|
||||
'editor:checkout-head-revision': => atom.project.getRepo()?.checkoutHeadForEditor(@editor)
|
||||
'editor:copy-path': => @copyPathToClipboard()
|
||||
'editor:move-line-up': => @editor.moveLineUp()
|
||||
'editor:move-line-down': => @editor.moveLineDown()
|
||||
@@ -338,11 +344,6 @@ class EditorView extends View
|
||||
getPlaceholderText: ->
|
||||
@placeholderText
|
||||
|
||||
# Checkout the HEAD revision of this editor's file.
|
||||
checkoutHead: ->
|
||||
if path = @editor.getPath()
|
||||
atom.project.getRepo()?.checkoutHead(path)
|
||||
|
||||
configure: ->
|
||||
@subscribe atom.config.observe 'editor.showLineNumbers', (showLineNumbers) => @gutter.setShowLineNumbers(showLineNumbers)
|
||||
@subscribe atom.config.observe 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles)
|
||||
@@ -641,9 +642,9 @@ class EditorView extends View
|
||||
@scrollBottom(@editor.getScreenLineCount() * @lineHeight)
|
||||
|
||||
# Public: Scrolls the editor to the position of the most recently added
|
||||
# cursor.
|
||||
# cursor if it isn't current on screen.
|
||||
#
|
||||
# The editor is also centered.
|
||||
# The editor is centered around the cursor's position if possible.
|
||||
scrollToCursorPosition: ->
|
||||
@scrollToBufferPosition(@editor.getCursorBufferPosition(), center: true)
|
||||
|
||||
|
||||
+61
-17
@@ -159,13 +159,16 @@ class Editor extends Model
|
||||
@delegatesProperties '$lineHeightInPixels', '$defaultCharWidth', '$height', '$width',
|
||||
'$scrollTop', '$scrollLeft', 'manageScrollPosition', toProperty: 'displayBuffer'
|
||||
|
||||
constructor: ({@softTabs, initialLine, initialColumn, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation}) ->
|
||||
constructor: ({@softTabs, initialLine, initialColumn, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation, @mini}) ->
|
||||
super
|
||||
|
||||
@cursors = []
|
||||
@selections = []
|
||||
|
||||
@displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrap})
|
||||
if @shouldShowInvisibles()
|
||||
invisibles = atom.config.get('editor.invisibles')
|
||||
|
||||
@displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrap, invisibles})
|
||||
@buffer = @displayBuffer.buffer
|
||||
@softTabs = @usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true
|
||||
|
||||
@@ -186,6 +189,9 @@ class Editor extends Model
|
||||
@subscribe @$scrollTop, (scrollTop) => @emit 'scroll-top-changed', scrollTop
|
||||
@subscribe @$scrollLeft, (scrollLeft) => @emit 'scroll-left-changed', scrollLeft
|
||||
|
||||
@subscribe atom.config.observe 'editor.showInvisibles', callNow: false, (show) => @updateInvisibles()
|
||||
@subscribe atom.config.observe 'editor.invisibles', callNow: false, => @updateInvisibles()
|
||||
|
||||
atom.workspace?.editorAdded(this) if registerEditor
|
||||
|
||||
serializeParams: ->
|
||||
@@ -281,6 +287,11 @@ class Editor extends Model
|
||||
# Controls visibility based on the given {Boolean}.
|
||||
setVisible: (visible) -> @displayBuffer.setVisible(visible)
|
||||
|
||||
setMini: (mini) ->
|
||||
if mini isnt @mini
|
||||
@mini = mini
|
||||
@updateInvisibles()
|
||||
|
||||
# Set the number of characters that can be displayed horizontally in the
|
||||
# editor.
|
||||
#
|
||||
@@ -416,9 +427,10 @@ class Editor extends Model
|
||||
@displayBuffer.indentLevelForLine(line)
|
||||
|
||||
# Constructs the string used for tabs.
|
||||
buildIndentString: (number) ->
|
||||
buildIndentString: (number, column=0) ->
|
||||
if @getSoftTabs()
|
||||
_.multiplyString(" ", Math.floor(number * @getTabLength()))
|
||||
tabStopViolation = column % @getTabLength()
|
||||
_.multiplyString(" ", Math.floor(number * @getTabLength()) - tabStopViolation)
|
||||
else
|
||||
_.multiplyString("\t", Math.floor(number))
|
||||
|
||||
@@ -434,10 +446,6 @@ class Editor extends Model
|
||||
# filePath - A {String} path.
|
||||
saveAs: (filePath) -> @buffer.saveAs(filePath)
|
||||
|
||||
checkoutHead: ->
|
||||
if filePath = @getPath()
|
||||
atom.project.getRepo()?.checkoutHead(filePath)
|
||||
|
||||
# Copies the current file path to the native clipboard.
|
||||
copyPathToClipboard: ->
|
||||
if filePath = @getPath()
|
||||
@@ -517,6 +525,8 @@ class Editor extends Model
|
||||
# {Delegates to: TextBuffer.isModified}
|
||||
isModified: -> @buffer.isModified()
|
||||
|
||||
isEmpty: -> @buffer.isEmpty()
|
||||
|
||||
# Public: Determine whether the user should be prompted to save before closing
|
||||
# this editor.
|
||||
shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors()
|
||||
@@ -626,12 +636,29 @@ class Editor extends Model
|
||||
|
||||
# Public: For each selection, replace the selected text with the given text.
|
||||
#
|
||||
# Emits: `will-insert-text -> ({text, cancel})` before the text has
|
||||
# been inserted. Calling `cancel` will prevent the text from being
|
||||
# inserted.
|
||||
# Emits: `did-insert-text -> ({text})` after the text has been inserted.
|
||||
#
|
||||
# text - A {String} representing the text to insert.
|
||||
# options - See {Selection::insertText}.
|
||||
#
|
||||
# Returns a {Bool} indicating whether or not the text was inserted.
|
||||
insertText: (text, options={}) ->
|
||||
options.autoIndentNewline ?= @shouldAutoIndent()
|
||||
options.autoDecreaseIndent ?= @shouldAutoIndent()
|
||||
@mutateSelectedText (selection) -> selection.insertText(text, options)
|
||||
willInsert = true
|
||||
cancel = -> willInsert = false
|
||||
@emit('will-insert-text', {cancel, text})
|
||||
|
||||
if willInsert
|
||||
options.autoIndentNewline ?= @shouldAutoIndent()
|
||||
options.autoDecreaseIndent ?= @shouldAutoIndent()
|
||||
@mutateSelectedText (selection) =>
|
||||
range = selection.insertText(text, options)
|
||||
@emit('did-insert-text', {text, range})
|
||||
range
|
||||
else
|
||||
false
|
||||
|
||||
# Public: For each selection, replace the selected text with a newline.
|
||||
insertNewline: ->
|
||||
@@ -1064,9 +1091,11 @@ class Editor extends Model
|
||||
# All the changes made inside the given {Function} can be reverted with a
|
||||
# single call to {::undo}.
|
||||
#
|
||||
# fn - A {Function} that will be called with each {Selection}.
|
||||
# fn - A {Function} that will be called once for each {Selection}. The first
|
||||
# argument will be a {Selection} and the second argument will be the
|
||||
# {Number} index of that selection.
|
||||
mutateSelectedText: (fn) ->
|
||||
@transact => fn(selection,index) for selection,index in @getSelections()
|
||||
@transact => fn(selection, index) for selection, index in @getSelections()
|
||||
|
||||
replaceSelectedText: (options={}, fn) ->
|
||||
{selectWordIfEmpty} = options
|
||||
@@ -1583,8 +1612,14 @@ class Editor extends Model
|
||||
moveCursorToBeginningOfPreviousParagraph: ->
|
||||
@moveCursors (cursor) -> cursor.moveToBeginningOfPreviousParagraph()
|
||||
|
||||
scrollToCursorPosition: ->
|
||||
@getCursor().autoscroll()
|
||||
# Public: Scroll the editor to reveal the most recently added cursor if it is
|
||||
# off-screen.
|
||||
#
|
||||
# options - An optional hash of options.
|
||||
# :center - Center the editor around the cursor if possible. Defauls to
|
||||
# true.
|
||||
scrollToCursorPosition: (options) ->
|
||||
@getCursor().autoscroll(center: options?.center ? true)
|
||||
|
||||
pageUp: ->
|
||||
newScrollTop = @getScrollTop() - @getHeight()
|
||||
@@ -1757,7 +1792,7 @@ class Editor extends Model
|
||||
{row} = start
|
||||
while ++row < end.row
|
||||
@addSelectionForBufferRange([[row, 0], [row, Infinity]])
|
||||
@addSelectionForBufferRange([[end.row, 0], [end.row, end.column]])
|
||||
@addSelectionForBufferRange([[end.row, 0], [end.row, end.column]]) unless end.column is 0
|
||||
|
||||
# Public: For each selection, transpose the selected text.
|
||||
#
|
||||
@@ -1923,6 +1958,15 @@ class Editor extends Model
|
||||
shouldAutoIndent: ->
|
||||
atom.config.get("editor.autoIndent")
|
||||
|
||||
shouldShowInvisibles: ->
|
||||
not @mini and atom.config.get('editor.showInvisibles')
|
||||
|
||||
updateInvisibles: ->
|
||||
if @shouldShowInvisibles()
|
||||
@displayBuffer.setInvisibles(atom.config.get('editor.invisibles'))
|
||||
else
|
||||
@displayBuffer.setInvisibles(null)
|
||||
|
||||
# Public: Batch multiple operations as a single undo/redo step.
|
||||
#
|
||||
# Any group of operations that are logically grouped from the perspective of
|
||||
@@ -2012,7 +2056,7 @@ class Editor extends Model
|
||||
setScrollRight: (scrollRight) -> @displayBuffer.setScrollRight(scrollRight)
|
||||
|
||||
getScrollHeight: -> @displayBuffer.getScrollHeight()
|
||||
getScrollWidth: (scrollWidth) -> @displayBuffer.getScrollWidth(scrollWidth)
|
||||
getScrollWidth: -> @displayBuffer.getScrollWidth()
|
||||
|
||||
getVisibleRowRange: -> @displayBuffer.getVisibleRowRange()
|
||||
|
||||
|
||||
+22
-1
@@ -1,4 +1,4 @@
|
||||
{join} = require 'path'
|
||||
{basename, join} = require 'path'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{Emitter, Subscriber} = require 'emissary'
|
||||
@@ -93,6 +93,27 @@ class Git
|
||||
@getPathStatus(path)
|
||||
@subscribe buffer, 'destroyed', => @unsubscribe(buffer)
|
||||
|
||||
# Subscribes to editor view event.
|
||||
checkoutHeadForEditor: (editor) ->
|
||||
filePath = editor.getPath()
|
||||
return unless filePath
|
||||
|
||||
fileName = basename(filePath)
|
||||
|
||||
checkoutHead = =>
|
||||
editor.buffer.reload() if editor.buffer.isModified()
|
||||
@checkoutHead(filePath)
|
||||
|
||||
if atom.config.get('editor.confirmCheckoutHeadRevision')
|
||||
atom.confirm
|
||||
message: 'Confirm Checkout HEAD Revision'
|
||||
detailedMessage: "Are you sure you want to discard all changes to \"#{fileName}\" since the last Git commit?"
|
||||
buttons:
|
||||
OK: checkoutHead
|
||||
Cancel: null
|
||||
else
|
||||
checkoutHead()
|
||||
|
||||
# Public: Destroy this `Git` object. This destroys any tasks and subscriptions
|
||||
# and releases the underlying libgit2 repository handle.
|
||||
destroy: ->
|
||||
|
||||
@@ -16,14 +16,16 @@ GutterComponent = React.createClass
|
||||
measuredWidth: null
|
||||
|
||||
render: ->
|
||||
{scrollHeight, scrollViewHeight, onMouseDown} = @props
|
||||
{scrollHeight, scrollViewHeight, onMouseDown, backgroundColor, gutterBackgroundColor} = @props
|
||||
|
||||
if gutterBackgroundColor isnt 'rbga(0, 0, 0, 0)'
|
||||
backgroundColor = gutterBackgroundColor
|
||||
|
||||
div className: 'gutter', onClick: @onClick, onMouseDown: onMouseDown,
|
||||
# The line-numbers div must have the 'editor-colors' class so it has an
|
||||
# opaque background to avoid sub-pixel anti-aliasing problems on the GPU
|
||||
div className: 'gutter line-numbers editor-colors', ref: 'lineNumbers', style:
|
||||
div className: 'line-numbers', ref: 'lineNumbers', style:
|
||||
height: Math.max(scrollHeight, scrollViewHeight)
|
||||
WebkitTransform: @getTransform()
|
||||
backgroundColor: backgroundColor
|
||||
|
||||
getTransform: ->
|
||||
{scrollTop, useHardwareAcceleration} = @props
|
||||
@@ -41,7 +43,7 @@ GutterComponent = React.createClass
|
||||
|
||||
componentDidMount: ->
|
||||
@appendDummyLineNumber()
|
||||
@updateLineNumbers() if @props.renderedRowRange?
|
||||
@updateLineNumbers() if @props.performedInitialMeasurement
|
||||
|
||||
# Only update the gutter if the visible row range has changed or if a
|
||||
# non-zero-delta change to the screen lines has occurred within the current
|
||||
@@ -49,23 +51,24 @@ GutterComponent = React.createClass
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
return true unless isEqualForProperties(newProps, @props,
|
||||
'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'mouseWheelScreenRow', 'lineDecorations',
|
||||
'scrollViewHeight', 'useHardwareAcceleration'
|
||||
'scrollViewHeight', 'useHardwareAcceleration', 'backgroundColor', 'gutterBackgroundColor'
|
||||
)
|
||||
|
||||
{renderedRowRange, pendingChanges, lineDecorations} = newProps
|
||||
return false unless renderedRowRange?
|
||||
|
||||
for change in pendingChanges when Math.abs(change.screenDelta) > 0 or Math.abs(change.bufferDelta) > 0
|
||||
return true unless change.end <= renderedRowRange.start or renderedRowRange.end <= change.start
|
||||
|
||||
false
|
||||
|
||||
componentDidUpdate: (oldProps) ->
|
||||
return unless @props.performedInitialMeasurement
|
||||
|
||||
unless isEqualForProperties(oldProps, @props, 'maxLineNumberDigits')
|
||||
@updateDummyLineNumber()
|
||||
@removeLineNumberNodes()
|
||||
|
||||
unless isEqualForProperties(oldProps, @props, 'maxLineNumberDigits', 'defaultCharWidth')
|
||||
@measureWidth()
|
||||
|
||||
@clearScreenRowCaches() unless oldProps.lineHeightInPixels is @props.lineHeightInPixels
|
||||
@updateLineNumbers()
|
||||
|
||||
@@ -223,9 +226,3 @@ GutterComponent = React.createClass
|
||||
editor.unfoldBufferRow(bufferRow)
|
||||
else
|
||||
editor.foldBufferRow(bufferRow)
|
||||
|
||||
measureWidth: ->
|
||||
width = @getDOMNode().offsetWidth
|
||||
unless width is @measuredWidth
|
||||
@measuredWidth = width
|
||||
@props.onWidthChanged?(width)
|
||||
|
||||
@@ -9,7 +9,7 @@ HighlightsComponent = React.createClass
|
||||
|
||||
render: ->
|
||||
div className: 'highlights',
|
||||
@renderHighlights() if @isMounted()
|
||||
@renderHighlights() if @props.performedInitialMeasurement
|
||||
|
||||
renderHighlights: ->
|
||||
{editor, highlightDecorations, lineHeightInPixels} = @props
|
||||
|
||||
+10
-10
@@ -43,12 +43,12 @@ class LanguageMode
|
||||
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
|
||||
|
||||
if commentEndString
|
||||
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
|
||||
shouldUncomment = commentStartRegex.testSync(buffer.lineForRow(start))
|
||||
if shouldUncomment
|
||||
commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '(?:$1)?')
|
||||
commentEndRegex = new OnigRegExp("(#{commentEndRegexString})(\\s*)$")
|
||||
startMatch = commentStartRegex.search(buffer.lineForRow(start))
|
||||
endMatch = commentEndRegex.search(buffer.lineForRow(end))
|
||||
startMatch = commentStartRegex.searchSync(buffer.lineForRow(start))
|
||||
endMatch = commentEndRegex.searchSync(buffer.lineForRow(end))
|
||||
if startMatch and endMatch
|
||||
buffer.transact ->
|
||||
columnStart = startMatch[1].length
|
||||
@@ -72,13 +72,13 @@ class LanguageMode
|
||||
blank = line?.match(/^\s*$/)
|
||||
|
||||
allBlank = false unless blank
|
||||
allBlankOrCommented = false unless blank or commentStartRegex.test(line)
|
||||
allBlankOrCommented = false unless blank or commentStartRegex.testSync(line)
|
||||
|
||||
shouldUncomment = allBlankOrCommented and not allBlank
|
||||
|
||||
if shouldUncomment
|
||||
for row in [start..end]
|
||||
if match = commentStartRegex.search(buffer.lineForRow(row))
|
||||
if match = commentStartRegex.searchSync(buffer.lineForRow(row))
|
||||
columnStart = match[1].length
|
||||
columnEnd = columnStart + match[2].length
|
||||
buffer.setTextInRange([[row, columnStart], [row, columnEnd]], "")
|
||||
@@ -168,7 +168,7 @@ class LanguageMode
|
||||
continue if @editor.isBufferRowBlank(row)
|
||||
indentation = @editor.indentationForBufferRow(row)
|
||||
if indentation <= startIndentLevel
|
||||
includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editor.lineForBufferRow(row))
|
||||
includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.searchSync(@editor.lineForBufferRow(row))
|
||||
foldEndRow = row if includeRowInFold
|
||||
break
|
||||
|
||||
@@ -250,10 +250,10 @@ class LanguageMode
|
||||
|
||||
precedingLine = @buffer.lineForRow(precedingRow)
|
||||
desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
|
||||
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editor.isBufferRowCommented(precedingRow)
|
||||
desiredIndentLevel += 1 if increaseIndentRegex.testSync(precedingLine) and not @editor.isBufferRowCommented(precedingRow)
|
||||
|
||||
return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
|
||||
desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine)
|
||||
desiredIndentLevel -= 1 if decreaseIndentRegex.testSync(currentLine)
|
||||
|
||||
Math.max(desiredIndentLevel, 0)
|
||||
|
||||
@@ -293,7 +293,7 @@ class LanguageMode
|
||||
return unless increaseIndentRegex and decreaseIndentRegex
|
||||
|
||||
line = @buffer.lineForRow(bufferRow)
|
||||
return unless decreaseIndentRegex.test(line)
|
||||
return unless decreaseIndentRegex.testSync(line)
|
||||
|
||||
currentIndentLevel = @editor.indentationForBufferRow(bufferRow)
|
||||
return if currentIndentLevel is 0
|
||||
@@ -302,7 +302,7 @@ class LanguageMode
|
||||
precedingLine = @buffer.lineForRow(precedingRow)
|
||||
|
||||
desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
|
||||
desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine)
|
||||
desiredIndentLevel -= 1 unless increaseIndentRegex.testSync(precedingLine)
|
||||
if desiredIndentLevel >= 0 and desiredIndentLevel < currentIndentLevel
|
||||
@editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ class LessCompileCache
|
||||
setImportPaths: (importPaths=[]) ->
|
||||
@cache.setImportPaths(importPaths.concat(@lessSearchPaths))
|
||||
|
||||
read: (stylesheetPath) -> @cache.readFileSync(stylesheetPath)
|
||||
read: (stylesheetPath) ->
|
||||
@cache.readFileSync(stylesheetPath)
|
||||
|
||||
cssForFile: (stylesheetPath, lessContent) ->
|
||||
@cache.cssForFile(stylesheetPath, lessContent)
|
||||
|
||||
destroy: -> @unsubscribe()
|
||||
|
||||
@@ -5,6 +5,7 @@ React = require 'react-atom-fork'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
Decoration = require './decoration'
|
||||
CursorsComponent = require './cursors-component'
|
||||
HighlightsComponent = require './highlights-component'
|
||||
|
||||
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
|
||||
@@ -16,18 +17,30 @@ LinesComponent = React.createClass
|
||||
displayName: 'LinesComponent'
|
||||
|
||||
render: ->
|
||||
if @isMounted()
|
||||
{editor, highlightDecorations, scrollHeight, scrollWidth} = @props
|
||||
{performedInitialMeasurement, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
|
||||
|
||||
if performedInitialMeasurement
|
||||
{editor, highlightDecorations, scrollHeight, scrollWidth, placeholderText, backgroundColor} = @props
|
||||
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
|
||||
{scrollTop, scrollLeft, cursorPixelRects, mini} = @props
|
||||
style =
|
||||
height: Math.max(scrollHeight, scrollViewHeight)
|
||||
width: scrollWidth
|
||||
WebkitTransform: @getTransform()
|
||||
backgroundColor: if mini then null else backgroundColor
|
||||
|
||||
# The lines div must have the 'editor-colors' class so it has an opaque
|
||||
# background to avoid sub-pixel anti-aliasing problems on the GPU
|
||||
div {className: 'lines editor-colors', style},
|
||||
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount})
|
||||
div {className: 'lines', style},
|
||||
div className: 'placeholder-text', placeholderText if placeholderText?
|
||||
|
||||
CursorsComponent {
|
||||
cursorPixelRects, cursorBlinkPeriod, cursorBlinkResumeDelay, lineHeightInPixels,
|
||||
defaultCharWidth, scopedCharacterWidthsChangeCount, performedInitialMeasurement
|
||||
}
|
||||
|
||||
HighlightsComponent {
|
||||
editor, highlightDecorations, lineHeightInPixels, defaultCharWidth,
|
||||
scopedCharacterWidthsChangeCount, performedInitialMeasurement
|
||||
}
|
||||
|
||||
getTransform: ->
|
||||
{scrollTop, scrollLeft, useHardwareAcceleration} = @props
|
||||
@@ -47,11 +60,14 @@ LinesComponent = React.createClass
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
return true unless isEqualForProperties(newProps, @props,
|
||||
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
|
||||
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
|
||||
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration'
|
||||
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'visible',
|
||||
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration',
|
||||
'placeholderText', 'performedInitialMeasurement', 'backgroundColor', 'cursorPixelRects'
|
||||
)
|
||||
|
||||
{renderedRowRange, pendingChanges} = newProps
|
||||
return false unless renderedRowRange?
|
||||
|
||||
[renderedStartRow, renderedEndRow] = renderedRowRange
|
||||
for change in pendingChanges
|
||||
if change.screenDelta is 0
|
||||
@@ -62,10 +78,11 @@ LinesComponent = React.createClass
|
||||
false
|
||||
|
||||
componentDidUpdate: (prevProps) ->
|
||||
{visible, scrollingVertically} = @props
|
||||
{visible, scrollingVertically, performedInitialMeasurement} = @props
|
||||
return unless performedInitialMeasurement
|
||||
|
||||
@clearScreenRowCaches() unless prevProps.lineHeightInPixels is @props.lineHeightInPixels
|
||||
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide', 'invisibles')
|
||||
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide')
|
||||
@updateLines(@props.lineWidth isnt prevProps.lineWidth)
|
||||
@measureCharactersInNewLines() if visible and not scrollingVertically
|
||||
|
||||
@@ -153,34 +170,30 @@ LinesComponent = React.createClass
|
||||
lineHTML
|
||||
|
||||
buildEmptyLineInnerHTML: (line) ->
|
||||
{showIndentGuide, invisibles} = @props
|
||||
{cr, eol} = invisibles
|
||||
{indentLevel, tabLength} = line
|
||||
{showIndentGuide} = @props
|
||||
{indentLevel, tabLength, endOfLineInvisibles} = line
|
||||
|
||||
if showIndentGuide and indentLevel > 0
|
||||
invisiblesToRender = []
|
||||
invisiblesToRender.push(cr) if cr? and line.lineEnding is '\r\n'
|
||||
invisiblesToRender.push(eol) if eol?
|
||||
|
||||
invisibleIndex = 0
|
||||
lineHTML = ''
|
||||
for i in [0...indentLevel]
|
||||
lineHTML += "<span class='indent-guide'>"
|
||||
for j in [0...tabLength]
|
||||
if invisible = invisiblesToRender.shift()
|
||||
if invisible = endOfLineInvisibles?[invisibleIndex++]
|
||||
lineHTML += "<span class='invisible-character'>#{invisible}</span>"
|
||||
else
|
||||
lineHTML += ' '
|
||||
lineHTML += "</span>"
|
||||
|
||||
while invisiblesToRender.length
|
||||
lineHTML += "<span class='invisible-character'>#{invisiblesToRender.shift()}</span>"
|
||||
while invisibleIndex < endOfLineInvisibles?.length
|
||||
lineHTML += "<span class='invisible-character'>#{line.endOfLineInvisibles[invisibleIndex++]}</span>"
|
||||
|
||||
lineHTML
|
||||
else
|
||||
@buildEndOfLineHTML(line, @props.invisibles)
|
||||
@buildEndOfLineHTML(line) or ' '
|
||||
|
||||
buildLineInnerHTML: (line) ->
|
||||
{invisibles, mini, showIndentGuide, invisibles} = @props
|
||||
{mini, showIndentGuide} = @props
|
||||
{tokens, text} = line
|
||||
innerHTML = ""
|
||||
|
||||
@@ -189,22 +202,20 @@ LinesComponent = React.createClass
|
||||
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
|
||||
for token in tokens
|
||||
innerHTML += @updateScopeStack(scopeStack, token.scopes)
|
||||
hasIndentGuide = not mini and showIndentGuide and token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly)
|
||||
innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide})
|
||||
hasIndentGuide = not mini and showIndentGuide and (token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly))
|
||||
innerHTML += token.getValueAsHtml({hasIndentGuide})
|
||||
|
||||
innerHTML += @popScope(scopeStack) while scopeStack.length > 0
|
||||
innerHTML += @buildEndOfLineHTML(line, invisibles)
|
||||
innerHTML += @buildEndOfLineHTML(line)
|
||||
innerHTML
|
||||
|
||||
buildEndOfLineHTML: (line, invisibles) ->
|
||||
return '' if @props.mini or line.isSoftWrapped()
|
||||
buildEndOfLineHTML: (line) ->
|
||||
{endOfLineInvisibles} = line
|
||||
|
||||
html = ''
|
||||
if invisibles.cr? and line.lineEnding is '\r\n'
|
||||
html += "<span class='invisible-character'>#{invisibles.cr}</span>"
|
||||
if invisibles.eol?
|
||||
html += "<span class='invisible-character'>#{invisibles.eol}</span>"
|
||||
|
||||
if endOfLineInvisibles?
|
||||
for invisible in endOfLineInvisibles
|
||||
html += "<span class='invisible-character'>#{invisible}</span>"
|
||||
html
|
||||
|
||||
updateScopeStack: (scopeStack, desiredScopes) ->
|
||||
@@ -212,7 +223,7 @@ LinesComponent = React.createClass
|
||||
|
||||
# Find a common prefix
|
||||
for scope, i in desiredScopes
|
||||
break unless scopeStack[i]?.scope is desiredScopes[i]
|
||||
break unless scopeStack[i] is desiredScopes[i]
|
||||
|
||||
# Pop scopes until we're at the common prefx
|
||||
until scopeStack.length is i
|
||||
|
||||
@@ -15,6 +15,7 @@ class MenuManager
|
||||
@pendingUpdateOperation = null
|
||||
@template = []
|
||||
atom.keymaps.on 'bundled-keymaps-loaded', => @loadPlatformItems()
|
||||
atom.packages.on 'activated', => @sortPackagesMenu()
|
||||
|
||||
# Public: Adds the given item definition to the existing template.
|
||||
#
|
||||
@@ -130,3 +131,14 @@ class MenuManager
|
||||
# Get an {Array} of {String} classes for the given element.
|
||||
classesForElement: (element) ->
|
||||
element?.classList.toString().split(' ') ? []
|
||||
|
||||
sortPackagesMenu: ->
|
||||
packagesMenu = @template.find ({label}) => @normalizeLabel(label) is 'Packages'
|
||||
return unless packagesMenu?.submenu?
|
||||
|
||||
packagesMenu.submenu.sort (item1, item2) =>
|
||||
if item1.label and item2.label
|
||||
@normalizeLabel(item1.label).localeCompare(@normalizeLabel(item2.label))
|
||||
else
|
||||
0
|
||||
@update()
|
||||
|
||||
+71
-1
@@ -158,7 +158,7 @@ class Package
|
||||
|
||||
loadStylesheets: ->
|
||||
@stylesheets = @getStylesheetPaths().map (stylesheetPath) ->
|
||||
[stylesheetPath, atom.themes.loadStylesheet(stylesheetPath)]
|
||||
[stylesheetPath, atom.themes.loadStylesheet(stylesheetPath, true)]
|
||||
|
||||
getStylesheetsPath: ->
|
||||
path.join(@path, @constructor.stylesheetsDir)
|
||||
@@ -269,6 +269,7 @@ class Package
|
||||
|
||||
requireMainModule: ->
|
||||
return @mainModule if @mainModule?
|
||||
return unless @isCompatible()
|
||||
mainModulePath = @getMainModulePath()
|
||||
@mainModule = require(mainModulePath) if fs.isFileSync(mainModulePath)
|
||||
|
||||
@@ -340,3 +341,72 @@ class Package
|
||||
for eventHandler in eventHandlers
|
||||
eventHandler.handler = eventHandler.disabledHandler
|
||||
delete eventHandler.disabledHandler
|
||||
|
||||
# Does the given module path contain native code?
|
||||
isNativeModule: (modulePath) ->
|
||||
try
|
||||
fs.listSync(path.join(modulePath, 'build', 'Release'), ['.node']).length > 0
|
||||
catch error
|
||||
false
|
||||
|
||||
# Get an array of all the native modules that this package depends on.
|
||||
# This will recurse through all dependencies.
|
||||
getNativeModuleDependencyPaths: ->
|
||||
nativeModulePaths = []
|
||||
|
||||
traversePath = (nodeModulesPath) =>
|
||||
try
|
||||
for modulePath in fs.listSync(nodeModulesPath)
|
||||
nativeModulePaths.push(modulePath) if @isNativeModule(modulePath)
|
||||
traversePath(path.join(modulePath, 'node_modules'))
|
||||
|
||||
traversePath(path.join(@path, 'node_modules'))
|
||||
nativeModulePaths
|
||||
|
||||
# Get the incompatible native modules that this package depends on.
|
||||
# This recurses through all dependencies and requires all modules that
|
||||
# contain a `.node` file.
|
||||
#
|
||||
# This information is cached in local storage on a per package/version basis
|
||||
# to minimize the impact on startup time.
|
||||
getIncompatibleNativeModules: ->
|
||||
localStorageKey = "installed-packages:#{@name}:#{@metadata.version}"
|
||||
unless atom.inDevMode()
|
||||
try
|
||||
{incompatibleNativeModules} = JSON.parse(global.localStorage.getItem(localStorageKey)) ? {}
|
||||
return incompatibleNativeModules if incompatibleNativeModules?
|
||||
|
||||
incompatibleNativeModules = []
|
||||
for nativeModulePath in @getNativeModuleDependencyPaths()
|
||||
try
|
||||
require(nativeModulePath)
|
||||
catch error
|
||||
try
|
||||
version = require("#{nativeModulePath}/package.json").version
|
||||
incompatibleNativeModules.push
|
||||
path: nativeModulePath
|
||||
name: path.basename(nativeModulePath)
|
||||
version: version
|
||||
error: error.message
|
||||
|
||||
global.localStorage.setItem(localStorageKey, JSON.stringify({incompatibleNativeModules}))
|
||||
incompatibleNativeModules
|
||||
|
||||
# Public: Is this package compatible with this version of Atom?
|
||||
#
|
||||
# Incompatible packages cannot be activated. This will include packages
|
||||
# installed to ~/.atom/packages that were built against node 0.11.10 but
|
||||
# now need to be upgrade to node 0.11.13.
|
||||
#
|
||||
# Returns a {Boolean}, true if compatible, false if incompatible.
|
||||
isCompatible: ->
|
||||
return @compatible if @compatible?
|
||||
|
||||
if @path.indexOf(path.join(atom.packages.resourcePath, 'node_modules') + path.sep) is 0
|
||||
# Bundled packages are always considered compatible
|
||||
@compatible = true
|
||||
else if packageMain = @getMainModulePath()
|
||||
@incompatibleModules = @getIncompatibleNativeModules()
|
||||
@compatible = @incompatibleModules.length is 0
|
||||
else
|
||||
@compatible = true
|
||||
|
||||
@@ -141,13 +141,17 @@ class PaneView extends View
|
||||
@activeItem
|
||||
|
||||
onActiveItemChanged: (item) =>
|
||||
@previousActiveItem?.off? 'title-changed', @activeItemTitleChanged
|
||||
if @previousActiveItem?.off?
|
||||
@previousActiveItem.off 'title-changed', @activeItemTitleChanged
|
||||
@previousActiveItem.off 'modified-status-changed', @activeItemModifiedChanged
|
||||
@previousActiveItem = item
|
||||
|
||||
return unless item?
|
||||
|
||||
hasFocus = @hasFocus()
|
||||
item.on? 'title-changed', @activeItemTitleChanged
|
||||
if item.on?
|
||||
item.on 'title-changed', @activeItemTitleChanged
|
||||
item.on 'modified-status-changed', @activeItemModifiedChanged
|
||||
view = @viewForItem(item)
|
||||
otherView.hide() for otherView in @itemViews.children().not(view).views()
|
||||
@itemViews.append(view) unless view.parent().is(@itemViews)
|
||||
@@ -183,6 +187,9 @@ class PaneView extends View
|
||||
activeItemTitleChanged: =>
|
||||
@trigger 'pane:active-item-title-changed'
|
||||
|
||||
activeItemModifiedChanged: =>
|
||||
@trigger 'pane:active-item-modified-status-changed'
|
||||
|
||||
viewForItem: (item) ->
|
||||
return unless item?
|
||||
if item instanceof $
|
||||
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário