Comparar commits
605 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 8fa6fdb90c | |||
| a57df59cb8 | |||
| 99d01b5d0e | |||
| c806fcf9e7 | |||
| 1bc9c2eb4b | |||
| bd08e36d2d | |||
| 76a2b8c54a | |||
| 131d2ab3ad | |||
| 0e0c508756 | |||
| 325d95ed35 | |||
| 081fc0e1ae | |||
| a6cc6afb16 | |||
| f330e58b4f | |||
| a406322748 | |||
| 8ee428f9dc | |||
| 437873411e | |||
| 00eecd4802 | |||
| 2cb13e1a66 | |||
| 8f7f1cef23 | |||
| 34d41efd9a | |||
| 82527c24f2 | |||
| ccfe787e4f | |||
| 4a5b43553b | |||
| da1ceb0e51 | |||
| 97e0ddf15d | |||
| fb3cc5554c | |||
| 184aecb4a4 | |||
| 181cecaf2f | |||
| ced66d920d | |||
| 6fe7eb086f | |||
| 462af79d21 | |||
| 771a60b1bc | |||
| 3e34e426bf | |||
| f77f48102c | |||
| 7dd67caf57 | |||
| 8081595523 | |||
| 47cd2359c8 | |||
| 13cf51f835 | |||
| 571d146ec0 | |||
| dc06173f2f | |||
| 358799285e | |||
| 8f4555b970 | |||
| e0bc7948ae | |||
| a606fc516b | |||
| 2c1f8ce733 | |||
| 62adc98b17 | |||
| 94e12ee886 | |||
| 4c74b07b22 | |||
| 8eb53696a6 | |||
| f9e28af59b | |||
| 3b5bb1501c | |||
| 8c4c15c17a | |||
| ae61ecf602 | |||
| 9a7582fd0b | |||
| f7f2f4497b | |||
| d4c4ab58b1 | |||
| a01e6e543e | |||
| d931b3ed5c | |||
| b95a7f47a8 | |||
| 06cbbe4b67 | |||
| 7d44026a92 | |||
| 11b0a80d3d | |||
| 92a8701c70 | |||
| 08e1d550c8 | |||
| c9eb84f2a4 | |||
| 74afcc58ac | |||
| 180725799a | |||
| 03468e405a | |||
| 1fd4e945ee | |||
| 0b48150b71 | |||
| bed8abea22 | |||
| 893bdda47d | |||
| 0b98093370 | |||
| 6abe05b1ab | |||
| 0f45937adf | |||
| c8726c991f | |||
| 60205aaabe | |||
| 6a16c8a59c | |||
| a055f09a6c | |||
| c19b42a49c | |||
| 2632e9aa10 | |||
| a9753d430e | |||
| 796eefd012 | |||
| 0f9eea34a5 | |||
| a84e19c9bd | |||
| 6d276d39d3 | |||
| ab203e5f81 | |||
| 61512b9e19 | |||
| c29c4652b0 | |||
| a9c0553e31 | |||
| 6d6e5baa9a | |||
| 1de76c7d73 | |||
| f6b7450dea | |||
| 71e1928f74 | |||
| 1a709065f8 | |||
| dca99cb34e | |||
| 3e79f54860 | |||
| a8b5960bc0 | |||
| 70e3484a16 | |||
| 5ac3f58cdb | |||
| 692f6947f2 | |||
| 08fad809d2 | |||
| ba63239928 | |||
| d90c8c0fb7 | |||
| 35e782f05d | |||
| 00af9a93d7 | |||
| 018e22ad8d | |||
| f73d3df233 | |||
| 25b44ceb1a | |||
| c28ecf1a7d | |||
| 478e80e585 | |||
| 08be377004 | |||
| 4db3e47377 | |||
| 76857b4486 | |||
| e743d93d6d | |||
| f443c375d4 | |||
| b9b488bee2 | |||
| e192922f0e | |||
| d1c41fbf68 | |||
| aa8b97a039 | |||
| 5276cb716a | |||
| 03f8a32f86 | |||
| eabb498af7 | |||
| a1e4c0bb05 | |||
| 6a285b695f | |||
| 7f66a2fca4 | |||
| 6565f6d608 | |||
| 493035fe4e | |||
| 6e30998ef5 | |||
| 825c4f6098 | |||
| b4756aa9b7 | |||
| 651fa1aa42 | |||
| db17fe2daa | |||
| 1e0c839257 | |||
| 18481789b0 | |||
| 304f63532e | |||
| 6e7364c7c6 | |||
| 339f331776 | |||
| 6b34a18bd9 | |||
| 32275b27a3 | |||
| 5c730415b7 | |||
| 637b2b0aba | |||
| b4246a2f07 | |||
| 31170dcfae | |||
| f784b51f12 | |||
| 3c6dab22d8 | |||
| e80f5acd50 | |||
| 90aca1c6ad | |||
| c7771ffde9 | |||
| bdfc862dac | |||
| 2c7aa170e9 | |||
| 6c8d624e73 | |||
| 57a876e677 | |||
| 20adc96e4c | |||
| d508d1eedf | |||
| 2949ebfe86 | |||
| dbaef8e593 | |||
| 3edd2f9590 | |||
| f2652bcb40 | |||
| d6c8ec83d4 | |||
| b4b492a321 | |||
| ba6a976013 | |||
| d0486cc923 | |||
| fb09f28c4c | |||
| 883c48b490 | |||
| ceefc15b15 | |||
| a0cc63273c | |||
| c328092463 | |||
| b1a3d89af3 | |||
| bd92acba7e | |||
| d90daf07f8 | |||
| 388428b074 | |||
| f439d0d996 | |||
| 4142845632 | |||
| 60c5293b5e | |||
| a1b4820c04 | |||
| 1cf8479831 | |||
| a14d57ceac | |||
| c1d5d96aca | |||
| b5632b6988 | |||
| fe02442b23 | |||
| 04ceaf36bf | |||
| 08d183dff1 | |||
| 134daa1fe2 | |||
| 360fbe2a3f | |||
| 8148446a86 | |||
| 16f56a068b | |||
| 11112cb374 | |||
| 5c7177746c | |||
| ab947ba87a | |||
| 8a4db34cb8 | |||
| 669088612c | |||
| 0a14d232d2 | |||
| 651fe5d71c | |||
| 7d49d50b34 | |||
| aab51d15ab | |||
| 1926156eee | |||
| b12a6abc90 | |||
| 46762c293f | |||
| 6b8ef25c8e | |||
| 03a769b516 | |||
| 229e7e03b2 | |||
| 45ee6df36e | |||
| 9422a8047a | |||
| 85456ad920 | |||
| 2f3d54db8a | |||
| bae903a772 | |||
| aabf4dfbab | |||
| 44327724a8 | |||
| 3c3e72e36d | |||
| e0741d2073 | |||
| d973ce9832 | |||
| 25cb56a936 | |||
| 9640678c29 | |||
| 2ce1677aa5 | |||
| d5c8956d38 | |||
| d532f506fe | |||
| 32b414328a | |||
| b1697399dc | |||
| 27eccfaf81 | |||
| ebbd8101ba | |||
| 20504fc7a8 | |||
| 0db1971825 | |||
| 80c828d001 | |||
| e688df57f2 | |||
| 0790d33e9d | |||
| 05820a3044 | |||
| c4ac602644 | |||
| 12d4fae91c | |||
| 2f334979d5 | |||
| d9e414af27 | |||
| 335c1e215a | |||
| b9b7646d4b | |||
| d885fb2d13 | |||
| f5ae96820a | |||
| 435fee1433 | |||
| c96f976162 | |||
| 5115540f8e | |||
| d642553351 | |||
| fa090345a8 | |||
| 55d291ffde | |||
| a0038b6f56 | |||
| 48f63926ab | |||
| b0501c9cb2 | |||
| 355ab1eb2f | |||
| 28ac51d140 | |||
| d6210b24d9 | |||
| b0731afd4c | |||
| 1c81aa90c0 | |||
| bbf6930061 | |||
| 3d149eb9d1 | |||
| 5a8b96b180 | |||
| 5add777291 | |||
| f866e69704 | |||
| b27b4387fc | |||
| 1f850f0af1 | |||
| 9f1bbc54de | |||
| e7d34d4b83 | |||
| c5a15fb50e | |||
| 7a251f5432 | |||
| dc2a453986 | |||
| fdd55dfd27 | |||
| 5147fb6a8b | |||
| 9bbbb58084 | |||
| 9ad080cd31 | |||
| 509976fa18 | |||
| aad5700418 | |||
| 09a0773043 | |||
| 0829da53b0 | |||
| 2ea92cf0e5 | |||
| 9a2cc36c6b | |||
| 965a6243e1 | |||
| 503fa30c28 | |||
| b8f239cd39 | |||
| 231da60e13 | |||
| a47719eb53 | |||
| 9f851e55d1 | |||
| ab89776f01 | |||
| 2cea51b50e | |||
| 4e4794f3fd | |||
| ac6fbf100d | |||
| 8c8e866a97 | |||
| f859ad5fc5 | |||
| d30cf35a16 | |||
| c35fb90653 | |||
| 73df017d83 | |||
| 0e1ef201c1 | |||
| be4d23aa13 | |||
| c58606907a | |||
| c489a4662b | |||
| 44fceaae20 | |||
| 1b393e4f48 | |||
| e84bd28c64 | |||
| bbf199fb60 | |||
| 367a4c4bd3 | |||
| 7d74f8179b | |||
| bcafef385f | |||
| 83d5890962 | |||
| 7ee3ccb43d | |||
| 9126f2e45c | |||
| 89ed95e2ae | |||
| 27174b2880 | |||
| ed1fbcc8e7 | |||
| 307ce4dc54 | |||
| 0833be4c27 | |||
| af116b2b8a | |||
| 59d582722b | |||
| 9239b95241 | |||
| ab8b5959d3 | |||
| 5ff7a286fc | |||
| f199c71fa8 | |||
| 265601cbdb | |||
| 67b39845c8 | |||
| a42505b6ae | |||
| f026d30426 | |||
| b4db61a7e7 | |||
| fad93b8d7e | |||
| feb72b38f8 | |||
| 23ce2cd1ac | |||
| ee2509e90f | |||
| ca5e66bbd1 | |||
| 3389555d71 | |||
| 202426a85b | |||
| a6d68f8683 | |||
| 6674bfbf97 | |||
| cd5309e494 | |||
| 11b2f4a18d | |||
| 88442ccb78 | |||
| c4768cb266 | |||
| cf772295fb | |||
| dabedeb065 | |||
| 224e6cb5d4 | |||
| 3f745e3d67 | |||
| d9a5e3c7e1 | |||
| d272606408 | |||
| 263567649d | |||
| c345532864 | |||
| c0c4e65b5d | |||
| b441b3cd6f | |||
| 3a51228899 | |||
| 42d5d0ba87 | |||
| a1d0635d98 | |||
| b66e931a99 | |||
| 0a7ea419a0 | |||
| 91770f2885 | |||
| d4c7fe4b47 | |||
| 8b848c1853 | |||
| eef6532b8c | |||
| 43de383b14 | |||
| 9d3aaad394 | |||
| 3cf104444c | |||
| f91741eec1 | |||
| 8f77d65aab | |||
| 3dced04aab | |||
| bac9eac1fc | |||
| d3e53c5ada | |||
| cad8afe78b | |||
| a7f30c63cb | |||
| 1d0dd86041 | |||
| 690ece3a9e | |||
| 100a1f5764 | |||
| 35f49be82a | |||
| 4225c25ad7 | |||
| 330592e2bd | |||
| d306876229 | |||
| 47aa269de5 | |||
| 2a80762d5b | |||
| 42ab14c2cb | |||
| e83784e141 | |||
| cedb41f4b0 | |||
| d873f3d255 | |||
| 2781c24fce | |||
| 2a45bd7f69 | |||
| f4fab84869 | |||
| 204e5a6b46 | |||
| 9459bd15a2 | |||
| 6cd96c8284 | |||
| 2ceced2b84 | |||
| be78572d78 | |||
| 61abda5166 | |||
| 93f98ec14e | |||
| d581c41c0e | |||
| 252bef63bf | |||
| 9c63a4f517 | |||
| e7b0c3e519 | |||
| 697ccedbd3 | |||
| 87efc7e1df | |||
| 6a0a694a7b | |||
| be1f28b3d8 | |||
| 32f7c72d28 | |||
| d51a86e804 | |||
| 93e3a5af2a | |||
| 278a507653 | |||
| 7422f4378e | |||
| f2ab14656b | |||
| 453abf8b90 | |||
| 7866f0819d | |||
| 921e3c581d | |||
| 58aa87438d | |||
| ad73902382 | |||
| bf63a9715c | |||
| 06c52c6873 | |||
| 9ac27bc2f8 | |||
| 98caaf0d70 | |||
| a102d1e134 | |||
| 6caa86fb04 | |||
| b1e0c8132d | |||
| f3947dd6e0 | |||
| 27dbbabe09 | |||
| 5950110860 | |||
| ab5d71e6b5 | |||
| 1ee2839245 | |||
| a6f31ed791 | |||
| e04b5a74d7 | |||
| 4acf143f45 | |||
| 5ad5ce0841 | |||
| 31d1ca12c1 | |||
| ace3325db8 | |||
| b718114fc4 | |||
| 1df8c77f41 | |||
| 26e867d65e | |||
| 2688761c29 | |||
| b64d9db198 | |||
| bc5b786bb2 | |||
| 13025c17f1 | |||
| 8b4b5230ab | |||
| 7d6d634ceb | |||
| b386b00bc0 | |||
| 2028045254 | |||
| ca60dae630 | |||
| a5605bd408 | |||
| caf6fdd5ac | |||
| 19872959bc | |||
| 299ea18c58 | |||
| 966360e022 | |||
| 70a2be849a | |||
| 1c7843d9b2 | |||
| 5291f1c62c | |||
| c9e7cfc02c | |||
| e93ca3c901 | |||
| 48bd330a5e | |||
| 6240bc1fc9 | |||
| 6ccc60342f | |||
| 03750d0b6c | |||
| 03e31ad918 | |||
| 610c07870a | |||
| 5c37d208f5 | |||
| 88c119f4ad | |||
| d03cfda6c4 | |||
| 8f02b21d08 | |||
| 953f2c61f7 | |||
| 15e95d0d21 | |||
| 391a71fed0 | |||
| 67ed490618 | |||
| c812dfef9b | |||
| 631bca6c89 | |||
| 095c1b74a7 | |||
| 7e408ad268 | |||
| 4945fd7aae | |||
| 0db5549b64 | |||
| 96095f9c30 | |||
| e2b4fcad65 | |||
| 3ea1c80fe7 | |||
| 525b4ac3eb | |||
| 6ffc750e18 | |||
| 66716db4d1 | |||
| 95d03fc5fa | |||
| b816fca75e | |||
| 6f148f681d | |||
| a489358f55 | |||
| 1cd0caeb2d | |||
| 310939338c | |||
| e39d50972d | |||
| 9a5f3ab000 | |||
| 9285f2605f | |||
| b654209adb | |||
| 0c07166a8e | |||
| de36ceb00c | |||
| aa292874ec | |||
| 736b6f37e4 | |||
| 8d9098464c | |||
| eb6ce74a12 | |||
| 33ee1cb0de | |||
| 11a07f41ac | |||
| 5cf97db07c | |||
| f095d38978 | |||
| 218f6ab629 | |||
| 26edd40f14 | |||
| 8241351143 | |||
| 286361bf2b | |||
| 3d5437c1e9 | |||
| 95b9140dcf | |||
| fc82e5ffd6 | |||
| 20521ad487 | |||
| 99f91fac48 | |||
| d4b0b33d86 | |||
| 790c125e0b | |||
| 4afe133f85 | |||
| 763e83584d | |||
| 62a671aae6 | |||
| c0eb5d0ebe | |||
| d1e9ad3ed1 | |||
| 396b53b8dc | |||
| d87d98278e | |||
| 682a4be285 | |||
| 14c68a4280 | |||
| ddfbc6c335 | |||
| 779642b3da | |||
| 705c78bf18 | |||
| 07a21a15a1 | |||
| 287895c78c | |||
| fcf7b6747b | |||
| 1af25ea401 | |||
| aecd689593 | |||
| 8ad8a61aab | |||
| 6a83246838 | |||
| a7fc1c4138 | |||
| c19aee5472 | |||
| e9d49b1df3 | |||
| 5a456c8552 | |||
| 1179ced85c | |||
| 7738472eb8 | |||
| 45274eaad3 | |||
| 24f7638e8b | |||
| 6ec7b7b38d | |||
| 094a7e9a5f | |||
| 97181121c9 | |||
| 3e4c7a8ab7 | |||
| f4b08649a0 | |||
| c1a93395f5 | |||
| 53b538311e | |||
| 19ae78e062 | |||
| 5a93f14199 | |||
| d7dd0f3224 | |||
| 37e6f03346 | |||
| 0aa3cd58c1 | |||
| ac23717f8c | |||
| 491561db4a | |||
| edfd67b093 | |||
| dd63d47c11 | |||
| 067f5ea7e8 | |||
| eb223c4f21 | |||
| f632b6fe79 | |||
| 5bdc8af850 | |||
| b03931371a | |||
| c02755f59a | |||
| e178b25f17 | |||
| 96efb232ee | |||
| 714cbc9f4b | |||
| 64e4053a19 | |||
| a7f1f90c1d | |||
| cacaba936b | |||
| b20589fbb6 | |||
| d3f14d8939 | |||
| 094ba81758 | |||
| 8a40be8345 | |||
| 2d8d330df7 | |||
| fbc9c05096 | |||
| 1eab423a1c | |||
| cfca6ecc86 | |||
| fb96b01f30 | |||
| 625b95a6d9 | |||
| 0fe9dc6aa9 | |||
| 38e6aee46d | |||
| 01f87d9678 | |||
| 93bf9357b0 | |||
| ed42a275ab | |||
| 6998337144 | |||
| 8b92aef3ff | |||
| 66d6af54bf | |||
| 2a06ece3df | |||
| 1c0c8db042 | |||
| 9293ef766b | |||
| a7a9b3707f | |||
| 7e16e42b3f | |||
| 179fb2d274 | |||
| f804006d6c | |||
| 9a9347e3a5 | |||
| e4bcb96dcc | |||
| 8a0992d689 | |||
| db17a6cba4 | |||
| 5449fc2e15 | |||
| 0a84ad5307 | |||
| 485c402661 | |||
| 4591f00a65 | |||
| b635fa0c97 | |||
| 004103d579 | |||
| 2c952fad95 | |||
| adc983e8da | |||
| 7dc9d0c8ce | |||
| 3d3521962c | |||
| 46a1f69ab1 | |||
| 298d3e5fb6 | |||
| 27291980cb | |||
| 64ae4bf6c3 | |||
| 90a71d1171 | |||
| a5b7d15bcc | |||
| be2d49a410 | |||
| 8a9805cc6d | |||
| 196694e352 | |||
| 5da4846fff | |||
| 67f4d51774 | |||
| 1bf4db15b2 | |||
| aff1aa5112 | |||
| 3b6d55dbbb |
+1
-1
@@ -1 +1 @@
|
||||
v0.10.21
|
||||
v0.10.33
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
2.7.6
|
||||
@@ -87,6 +87,7 @@ For more information on how to work with Atom's official packages, see
|
||||
* :white_check_mark: `:white_check_mark:` when adding tests
|
||||
* :lock: `:lock:` when dealing with security
|
||||
* :arrow_up: `:arrow_up:` when upgrading dependencies
|
||||
* :arrow_down: `:arrow_down:` when downgrading dependencies
|
||||
|
||||
## CoffeeScript Styleguide
|
||||
|
||||
|
||||
+18
-9
@@ -2,7 +2,7 @@
|
||||
|
||||
Atom is a hackable text editor for the 21st century, built on [atom-shell](http://github.com/atom/atom-shell), and based on everything we love about our favorite editors. We designed it to be deeply customizable, but still approachable using the default configuration.
|
||||
|
||||
Visit [atom.io](https://atom.io) to learn more.
|
||||
Visit [atom.io](https://atom.io) to learn more or visit the [Atom forum](https://discuss.atom.io).
|
||||
|
||||
Visit [issue #3684](https://github.com/atom/atom/issues/3684) to learn more
|
||||
about the Atom 1.0 roadmap.
|
||||
@@ -17,16 +17,25 @@ Atom will automatically update when a new release is available.
|
||||
|
||||
### Windows
|
||||
|
||||
Install the [Atom chocolatey package](https://chocolatey.org/packages/Atom).
|
||||
Download the latest [AtomSetup.exe installer](https://github.com/atom/atom/releases/latest).
|
||||
|
||||
1. Install [chocolatey](https://chocolatey.org).
|
||||
2. Close and reopen your command prompt or PowerShell window.
|
||||
3. Run `cinst Atom`
|
||||
4. In the future run `cup Atom` to upgrade to the latest release.
|
||||
Atom will automatically update when a new release is available.
|
||||
|
||||
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.
|
||||
You can also download an `atom-windows.zip` file from the [releases page](https://github.com/atom/atom/releases/latest).
|
||||
The `.zip` version will not automatically update.
|
||||
|
||||
#### Uninstalling Chocolatey Version
|
||||
|
||||
The recommended installation of Atom on Windows used to be using [Chocolatey](https://chocolatey.org/packages/Atom/).
|
||||
This is no longer recommended now that the Atom Windows installer & auto-updater
|
||||
exists.
|
||||
|
||||
To switch from Chocolatey to the new installer:
|
||||
* Upgrade to Atom 0.155 or above by running `cup Atom`
|
||||
* Run `cuninst Atom` to uninstall the Chocolatey version of Atom
|
||||
* This will not delete any of your installed packages or Atom config files.
|
||||
* Download the latest [AtomSetup.exe installer](https://github.com/atom/atom/releases/latest).
|
||||
* Double-click the downloaded file to install Atom
|
||||
|
||||
### Debian Linux (Ubuntu)
|
||||
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.111.0"
|
||||
"atom-package-manager": "0.117.0"
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -45,12 +45,12 @@ if [ $REDIRECT_STDERR ]; then
|
||||
fi
|
||||
|
||||
if [ $OS == 'Mac' ]; then
|
||||
ATOM_PATH=${ATOM_PATH:-/Applications} # Set ATOM_PATH unless it is already set
|
||||
ATOM_PATH="${ATOM_PATH:-/Applications}" # Set ATOM_PATH unless it is already set
|
||||
ATOM_APP_NAME=Atom.app
|
||||
|
||||
# If ATOM_PATH isn't a executable file, use spotlight to search for Atom
|
||||
if [ ! -x "$ATOM_PATH/$ATOM_APP_NAME" ]; then
|
||||
ATOM_PATH=$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | grep -v ShipIt | head -1 | xargs dirname)
|
||||
ATOM_PATH="$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | grep -v ShipIt | head -1 | xargs -0 dirname)"
|
||||
fi
|
||||
|
||||
# Exit if Atom can't be found
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"fs-plus": "2.x",
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-atom-shell-installer": "^0.10.0",
|
||||
"grunt-atom-shell-installer": "^0.16.0",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git#cfb99aa99811d52687969532bd5a98011ed95bfe",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
@@ -31,7 +31,7 @@
|
||||
"request": "~2.27.0",
|
||||
"rimraf": "~2.2.2",
|
||||
"runas": "~1.0.1",
|
||||
"tello": "1.0.3",
|
||||
"tello": "1.0.4",
|
||||
"temp": "~0.8.1",
|
||||
"underscore-plus": "1.x",
|
||||
"unzip": "~0.1.9",
|
||||
|
||||
@@ -21,7 +21,9 @@ module.exports = (grunt) ->
|
||||
|
||||
mkdir appDir
|
||||
|
||||
cp 'atom.sh', path.join(appDir, 'atom.sh')
|
||||
if process.platform isnt 'win32'
|
||||
cp 'atom.sh', path.join(appDir, 'atom.sh')
|
||||
|
||||
cp 'package.json', path.join(appDir, 'package.json')
|
||||
|
||||
packageDirectories = []
|
||||
@@ -69,6 +71,7 @@ module.exports = (grunt) ->
|
||||
path.join('build', 'Release', 'obj')
|
||||
path.join('build', 'Release', '.deps')
|
||||
path.join('vendor', 'apm')
|
||||
path.join('resources', 'linux')
|
||||
path.join('resources', 'mac')
|
||||
path.join('resources', 'win')
|
||||
|
||||
@@ -149,10 +152,10 @@ module.exports = (grunt) ->
|
||||
grunt.file.copy(sourcePath, path.resolve(appDir, '..', subDirectory, filename))
|
||||
|
||||
if process.platform is 'win32'
|
||||
# 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'), ''
|
||||
fs.writeFileSync path.join(shellAppDir, 'atom.exe.gui'), ''
|
||||
cp path.join('resources', 'win', 'atom.cmd'), path.join(shellAppDir, 'resources', 'cli', 'atom.cmd')
|
||||
cp path.join('resources', 'win', 'atom.sh'), path.join(shellAppDir, 'resources', 'cli', 'atom.sh')
|
||||
cp path.join('resources', 'win', 'atom.js'), path.join(shellAppDir, 'resources', 'cli', 'atom.js')
|
||||
cp path.join('resources', 'win', 'apm.sh'), path.join(shellAppDir, 'resources', 'cli', 'apm.sh')
|
||||
|
||||
dependencies = ['compile', 'generate-license:save', 'generate-module-cache', 'compile-packages-slug']
|
||||
dependencies.push('copy-info-plist') if process.platform is 'darwin'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
|
||||
@@ -101,7 +101,7 @@ getAssets = ->
|
||||
logError = (message, error, details) ->
|
||||
grunt.log.error(message)
|
||||
grunt.log.error(error.message ? error) if error?
|
||||
grunt.log.error(details) if details
|
||||
grunt.log.error(require('util').inspect(details)) if details
|
||||
|
||||
zipAssets = (buildDir, assets, callback) ->
|
||||
zip = (directory, sourcePath, assetName, callback) ->
|
||||
@@ -142,7 +142,30 @@ getAtomDraftRelease = (callback) ->
|
||||
firstDraft.assets = assets
|
||||
callback(null, firstDraft)
|
||||
else
|
||||
callback(new Error('No draft release in atom/atom repo'))
|
||||
createAtomDraftRelease(callback)
|
||||
|
||||
createAtomDraftRelease = (callback) ->
|
||||
{version} = require('../../package.json')
|
||||
options =
|
||||
uri: 'https://api.github.com/repos/atom/atom/releases'
|
||||
method: 'POST'
|
||||
headers: defaultHeaders
|
||||
json:
|
||||
tag_name: "v#{version}"
|
||||
name: version
|
||||
draft: true
|
||||
body: """
|
||||
### Notable Changes
|
||||
|
||||
* Something new
|
||||
"""
|
||||
|
||||
request options, (error, response, body='') ->
|
||||
if error? or response.statusCode isnt 201
|
||||
logError("Creating atom/atom draft release failed", error, body)
|
||||
callback(error ? new Error(response.statusCode))
|
||||
else
|
||||
callback(null, body)
|
||||
|
||||
deleteRelease = (release) ->
|
||||
options =
|
||||
|
||||
@@ -11,6 +11,20 @@ module.exports = (grunt) ->
|
||||
|
||||
packageSpecQueue = null
|
||||
|
||||
logDeprecations = (label, {stderr}={}) ->
|
||||
return unless process.env.JANKY_SHA1
|
||||
stderr ?= ''
|
||||
deprecatedStart = stderr.indexOf('Calls to deprecated functions')
|
||||
return if deprecatedStart.length is -1
|
||||
|
||||
grunt.log.error(label)
|
||||
stderr = stderr.substring(deprecatedStart)
|
||||
stderr = stderr.replace(/^\s*\[[^\]]+\]\s+/gm, '')
|
||||
stderr = stderr.replace(/source: .*$/gm, '')
|
||||
stderr = stderr.replace(/^"/gm, '')
|
||||
stderr = stderr.replace(/",\s*$/gm, '')
|
||||
grunt.log.error(stderr)
|
||||
|
||||
getAppPath = ->
|
||||
contentsDir = grunt.config.get('atom.contentsDir')
|
||||
switch process.platform
|
||||
@@ -54,6 +68,7 @@ module.exports = (grunt) ->
|
||||
fs.unlinkSync(path.join(packagePath, 'ci.log'))
|
||||
|
||||
failedPackages.push path.basename(packagePath) if error
|
||||
logDeprecations("#{path.basename(packagePath)} Specs", results)
|
||||
callback()
|
||||
|
||||
modulesDirectory = path.resolve('node_modules')
|
||||
@@ -87,6 +102,7 @@ module.exports = (grunt) ->
|
||||
else
|
||||
# TODO: Restore concurrency on Windows
|
||||
packageSpecQueue.concurrency = concurrency
|
||||
logDeprecations('Core Specs', results)
|
||||
|
||||
callback(null, error)
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
path = require 'path'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
grunt.registerTask 'update-octicons', 'Update octicon font and LESS variables', ->
|
||||
pathToOcticons = path.resolve('..', 'octicons')
|
||||
if grunt.file.isDir(pathToOcticons)
|
||||
# Copy font-file
|
||||
fontSrc = path.join(pathToOcticons, 'octicons', 'octicons.woff')
|
||||
fontDest = path.resolve('static', 'octicons.woff')
|
||||
grunt.file.copy(fontSrc, fontDest)
|
||||
|
||||
# Update Octicon UTF codes
|
||||
glyphsSrc = path.join(pathToOcticons, 'data', 'glyphs.yml')
|
||||
output = []
|
||||
for {css, code} in grunt.file.readYAML(glyphsSrc)
|
||||
output.push "@#{css}: \"\\#{code}\";"
|
||||
|
||||
octiconUtfDest = path.resolve('static', 'variables', 'octicon-utf-codes.less')
|
||||
grunt.file.write(octiconUtfDest, "#{output.join('\n')}\n")
|
||||
else
|
||||
grunt.log.error("octicons repo must be cloned to #{pathToOcticons}")
|
||||
false
|
||||
@@ -30,8 +30,8 @@ All requests that take parameters require `application/json`.
|
||||
Parameters:
|
||||
|
||||
- **page** (optional)
|
||||
- **sort** (optional, values: `created_at`, `updated_at`, `downloads`)
|
||||
- **direction** (optional, values: `asc`, `desc`)
|
||||
- **sort** (optional) - One of `downloads`, `created_at`, `updated_at`, `stars`. Defaults to `downloads`
|
||||
- **direction** (optional) - `asc` or `desc`. Defaults to `desc`. `stars` can only be ordered `desc`
|
||||
|
||||
Returns a list of all packages in the following format:
|
||||
```json
|
||||
@@ -61,17 +61,18 @@ Link: <https://www.atom.io/api/packages?page=1>; rel="self",
|
||||
|
||||
By default, results are sorted by download count, descending.
|
||||
|
||||
### Searching packages
|
||||
|
||||
#### GET /api/packages/search
|
||||
|
||||
Parameters:
|
||||
|
||||
- **q** String query to search
|
||||
- **sort** (optional, values: `created_at`, `updated_at`, `downloads`)
|
||||
- **direction** (optional, values: `asc`, `desc`)
|
||||
- **q** (required) - Search query
|
||||
- **page** (optional)
|
||||
- **sort** (optional) - One of `downloads`, `created_at`, `updated_at`, `stars`. Defaults to the relevance of the search query.
|
||||
- **direction** (optional) - `asc` or `desc`. Defaults to `desc`.
|
||||
|
||||
Returns a list of all packages in the same format as `/api/packages`.
|
||||
|
||||
By default, results sorted by relevance to search query.
|
||||
Returns results in the same format as [listing packages](#listing-packages).
|
||||
|
||||
### Showing package details
|
||||
|
||||
|
||||
@@ -26,9 +26,17 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
|
||||
|
||||
### Arch
|
||||
|
||||
* `sudo pacman -S base-devel git nodejs libgnome-keyring python2`
|
||||
* `sudo pacman -S gconf base-devel git nodejs libgnome-keyring python2`
|
||||
* `export PYTHON=/usr/bin/python2` before building Atom.
|
||||
|
||||
### Slackware
|
||||
|
||||
* `sbopkg -k -i node -i atom`
|
||||
|
||||
### openSUSE
|
||||
|
||||
* `sudo zypper install nodejs make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools`
|
||||
|
||||
## Instructions
|
||||
|
||||
If you have problems with permissions don't forget to prefix with `sudo`
|
||||
@@ -121,6 +129,15 @@ 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.
|
||||
|
||||
#### You can also use Alternatives
|
||||
|
||||
On some variants (mostly Debian based distros) it's preferable for you to use
|
||||
Alternatives so that changes to the binary paths can be fixed or altered easily:
|
||||
|
||||
```sh
|
||||
sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 1 --slave /usr/bin/js js /usr/bin/nodejs
|
||||
```
|
||||
|
||||
### AttributeError: 'module' object has no attribute 'script_main'
|
||||
|
||||
If you get following error with a big traceback while building Atom:
|
||||
@@ -137,15 +154,6 @@ On Fedora you would do the following:
|
||||
sudo yum remove gyp
|
||||
```
|
||||
|
||||
#### You can also use Alternatives
|
||||
|
||||
On some variants (mostly Debian based distros) it's preferable for you to use
|
||||
Alternatives so that changes to the binary paths can be fixed or altered easily:
|
||||
|
||||
```sh
|
||||
sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 1 --slave /usr/bin/js js /usr/bin/nodejs
|
||||
```
|
||||
|
||||
### Linux build error reports in atom/atom
|
||||
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Alinux&type=Issues)
|
||||
to get a list of reports about build errors on Linux.
|
||||
|
||||
@@ -123,8 +123,8 @@ like you.
|
||||
|
||||
Style sheets for your package should be placed in the _stylesheets_ directory.
|
||||
Any style sheets in this directory will be loaded and attached to the DOM when
|
||||
your package is activated. Style sheets can be written as CSS or [LESS] (but
|
||||
LESS is recommended).
|
||||
your package is activated. Style sheets can be written as CSS or [LESS], but
|
||||
LESS is recommended.
|
||||
|
||||
Ideally, you won't need much in the way of styling. We've provided a standard
|
||||
set of components which define both the colors and UI elements for any package
|
||||
@@ -418,7 +418,7 @@ all the other available commands.
|
||||
[underscore]: http://underscorejs.org/
|
||||
[jasmine]: http://jasmine.github.io
|
||||
[cson]: https://github.com/atom/season
|
||||
[less]: http://lesscss.org
|
||||
[LESS]: http://lesscss.org
|
||||
[ui-variables]: https://github.com/atom/atom-dark-ui/blob/master/stylesheets/ui-variables.less
|
||||
[first-package]: your-first-package.html
|
||||
[convert-bundle]: converting-a-text-mate-bundle.html
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Creating a Theme
|
||||
|
||||
Atom's interface is rendered using HTML, and it's styled via [LESS] (a superset
|
||||
of CSS). Don't worry if you haven't heard of LESS before; it's just like CSS,
|
||||
but with a few handy extensions.
|
||||
Atom's interface is rendered using HTML, and it's styled via [LESS] which is a
|
||||
superset of CSS. Don't worry if you haven't heard of LESS before; it's just like
|
||||
CSS, but with a few handy extensions.
|
||||
|
||||
Atom supports two types of themes: _UI_ and _syntax_. UI themes style
|
||||
elements such as the tree view, the tabs, drop-down lists, and the status bar.
|
||||
@@ -59,6 +59,8 @@ window in dev mode. To open a Dev Mode Atom window run `atom --dev .` in the
|
||||
terminal, use `cmd-shift-o` or use the _View > Developer > Open in Dev Mode_
|
||||
menu. When you edit your theme, changes will instantly be reflected!
|
||||
|
||||
> Note: It's advised to _not_ specify a `font-family` in your syntax theme because it will override the Font Family field in Atom's settings. If you still like to recommend a font that goes well with your theme, we recommend you do so in your README.
|
||||
|
||||
## Creating an Interface Theme
|
||||
|
||||
Interface themes **must** provide a `ui-variables.less` file which contains all
|
||||
@@ -129,7 +131,7 @@ _styleguide_, or use the shortcut `cmd-ctrl-shift-g`.
|
||||
![styleguide-img]
|
||||
|
||||
[atomio]: http://atom.io/packages
|
||||
[less]: http://lesscss.org/
|
||||
[LESS]: http://lesscss.org/
|
||||
[git]: http://git-scm.com/
|
||||
[atom]: https://atom.io/
|
||||
[package.json]: ./creating-a-package.html#package-json
|
||||
|
||||
@@ -105,6 +105,7 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu.
|
||||
- `core`
|
||||
- `disabledPackages`: An array of package names to disable
|
||||
- `excludeVcsIgnoredPaths`: Don't search within files specified by _.gitignore_
|
||||
- `followSymlinks`: Follow symlinks when searching and scanning root directory
|
||||
- `ignoredNames`: File names to ignore across all of Atom
|
||||
- `projectHome`: The directory where projects are assumed to be located
|
||||
- `themes`: An array of theme names to load, in cascading order
|
||||
|
||||
+12
-1
@@ -3,7 +3,8 @@
|
||||
Atom provides several tools to help you understand unexpected behavior and debug problems. This guide describes some of those tools and a few approaches to help you debug and provide more helpful information when [submitting issues]:
|
||||
|
||||
* [Update to the latest version](#update-to-the-latest-version)
|
||||
* [Check Atom and package settings](#check-atom-and-package-settings)
|
||||
* [Check for linked packages](#check-for-linked-packages)
|
||||
* [Check Atom and package settings](#check-atom-and-package-settings)
|
||||
* [Check the keybindings](#check-the-keybindings)
|
||||
* [Check if the problem shows up in safe mode](#check-if-the-problem-shows-up-in-safe-mode)
|
||||
* [Check your config files](#check-your-config-files)
|
||||
@@ -24,6 +25,16 @@ $ atom --version
|
||||
|
||||
Head on over to the [list of releases][atom releases] and see if there's a more recent release. You can update to the most recent release by downloading Atom from the releases page, or with the in-app auto-updater. The in-app auto-updater checks for and downloads a new version after you restart Atom, or if you use the Atom > Check for Update menu option.
|
||||
|
||||
## Check for linked packages
|
||||
|
||||
If you develop or contribute to Atom packages, there may be left-over packages linked to your `~/.atom/packages` or `~/.atom/dev/packages` directories. You can use:
|
||||
|
||||
```shell
|
||||
$ apm links
|
||||
```
|
||||
|
||||
to list all linked development packages. You can remove the links using the `apm unlink` command. See `apm unlink --help` for details.
|
||||
|
||||
## Check Atom and package settings
|
||||
|
||||
In some cases, unexpected behavior might be caused by misconfigured or unconfigured settings in Atom or in one of the packages.
|
||||
|
||||
@@ -72,7 +72,7 @@ Writing Asynchronous specs can be tricky at first. Some examples.
|
||||
atom.workspace.open 'c.coffee'
|
||||
|
||||
it "should be opened in an editor", ->
|
||||
expect(atom.workspace.getActiveEditor().getPath()).toContain 'c.coffee'
|
||||
expect(atom.workspace.getActiveTextEditor().getPath()).toContain 'c.coffee'
|
||||
|
||||
```
|
||||
|
||||
|
||||
+16
-16
@@ -40,11 +40,11 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Object.defineProperty module.exports, '$', get: ->
|
||||
deprecate """
|
||||
Requiring `$` from `atom` is no longer supported.
|
||||
If you are using `space-pen`, please require `$` from `space-pen`. Otherwise require `jquery` instead:
|
||||
`{$} = require 'space-pen'`
|
||||
If you are using `space-pen`, please require `$` from `atom-space-pen-views`. Otherwise require `jquery` instead:
|
||||
`{$} = require 'atom-space-pen-views'`
|
||||
or
|
||||
`$ = require 'jquery'`
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
Or add `"jquery": "^2"` to your package dependencies.
|
||||
"""
|
||||
$
|
||||
@@ -52,27 +52,27 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Object.defineProperty module.exports, '$$', get: ->
|
||||
deprecate """
|
||||
Requiring `$$` from `atom` is no longer supported.
|
||||
Please require `space-pen` instead:
|
||||
`{$$} = require 'space-pen'`
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
Please require `atom-space-pen-views` instead:
|
||||
`{$$} = require 'atom-space-pen-views'`
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
$$
|
||||
|
||||
Object.defineProperty module.exports, '$$$', get: ->
|
||||
deprecate """
|
||||
Requiring `$$$` from `atom` is no longer supported.
|
||||
Please require `space-pen` instead:
|
||||
`{$$$} = require 'space-pen'`
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
Please require `atom-space-pen-views` instead:
|
||||
`{$$$} = require 'atom-space-pen-views'`
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
$$$
|
||||
|
||||
Object.defineProperty module.exports, 'View', get: ->
|
||||
deprecate """
|
||||
Requiring `View` from `atom` is no longer supported.
|
||||
Please require `space-pen` instead:
|
||||
`{View} = require 'space-pen'`
|
||||
Add `"space-pen": "^4"` to your package dependencies.
|
||||
Please require `atom-space-pen-views` instead:
|
||||
`{View} = require 'atom-space-pen-views'`
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
View
|
||||
|
||||
@@ -81,7 +81,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Requiring `EditorView` from `atom` is no longer supported.
|
||||
Please require `TextEditorView` from `atom-space-pen-view` instead:
|
||||
`{TextEditorView} = require 'atom-space-pen-views'`
|
||||
Add `"atom-space-pen-views": "^0"` to your package dependencies.
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
require '../src/text-editor-view'
|
||||
|
||||
@@ -90,7 +90,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Requiring `TextEditorView` from `atom` is no longer supported.
|
||||
Please require `TextEditorView` from `atom-space-pen-view` instead:
|
||||
`{TextEditorView} = require 'atom-space-pen-views'`
|
||||
Add `"atom-space-pen-views": "^0"` to your package dependencies.
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
require '../src/text-editor-view'
|
||||
|
||||
@@ -100,7 +100,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Please require `ScrollView` from `atom-space-pen-view` instead:
|
||||
`{ScrollView} = require 'atom-space-pen-views'`
|
||||
Note that the API has changed slightly! Please read the docs at https://github.com/atom/atom-space-pen-views
|
||||
Add `"atom-space-pen-views": "^0"` to your package dependencies.
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
require '../src/scroll-view'
|
||||
|
||||
@@ -110,7 +110,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
Please require `SelectListView` from `atom-space-pen-view` instead:
|
||||
`{SelectListView} = require 'atom-space-pen-views'`
|
||||
Note that the API has changed slightly! Please read the docs at https://github.com/atom/atom-space-pen-views
|
||||
Add `"atom-space-pen-views": "^0"` to your package dependencies.
|
||||
Add `"atom-space-pen-views": "^2.0.3"` to your package dependencies.
|
||||
"""
|
||||
require '../src/select-list-view'
|
||||
|
||||
|
||||
+1
-1
@@ -202,7 +202,7 @@
|
||||
]
|
||||
|
||||
'context-menu':
|
||||
'.overlayer': [
|
||||
'atom-text-editor, .overlayer': [
|
||||
{label: 'Undo', command: 'core:undo'}
|
||||
{label: 'Redo', command: 'core:redo'}
|
||||
{type: 'separator'}
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@
|
||||
]
|
||||
|
||||
'context-menu':
|
||||
'.overlayer': [
|
||||
'atom-text-editor, .overlayer': [
|
||||
{label: 'Undo', command: 'core:undo'}
|
||||
{label: 'Redo', command: 'core:redo'}
|
||||
{type: 'separator'}
|
||||
|
||||
+4
-1
@@ -164,6 +164,9 @@
|
||||
{ label: 'View &Terms of Use', command: 'application:open-terms-of-use' }
|
||||
{ label: 'View &License', command: 'application:open-license' }
|
||||
{ label: 'VERSION', enabled: false }
|
||||
{ label: 'Restart and Install Update', command: 'application:install-update', visible: false}
|
||||
{ label: 'Check for Update', command: 'application:check-for-update', visible: false}
|
||||
{ label: 'Downloading Update', enabled: false, visible: false}
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
@@ -178,7 +181,7 @@
|
||||
]
|
||||
|
||||
'context-menu':
|
||||
'.overlayer': [
|
||||
'atom-text-editor, .overlayer': [
|
||||
{label: 'Undo', command: 'core:undo'}
|
||||
{label: 'Redo', command: 'core:redo'}
|
||||
{type: 'separator'}
|
||||
|
||||
+85
-83
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.153.0",
|
||||
"version": "0.169.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,23 +17,23 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.19.4",
|
||||
"atomShellVersion": "0.20.5",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.3.0",
|
||||
"atom-keymap": "^2.3.3",
|
||||
"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.3.1",
|
||||
"event-kit": "0.7.2",
|
||||
"first-mate": "^2.2.0",
|
||||
"event-kit": "^1.0.1",
|
||||
"first-mate": "^2.2.3",
|
||||
"fs-plus": "^2.3.2",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"git-utils": "^2.1.5",
|
||||
"grim": "0.12.0",
|
||||
"git-utils": "^2.2",
|
||||
"grim": "1.0.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
@@ -45,7 +45,7 @@
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.4",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^2.3.5",
|
||||
"pathwatcher": "^2.3.7",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
@@ -53,97 +53,99 @@
|
||||
"reactionary-atom-fork": "^1.0.0",
|
||||
"runas": "1.0.1",
|
||||
"scandal": "1.0.3",
|
||||
"scoped-property-store": "^0.15.0",
|
||||
"scoped-property-store": "^0.16.2",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^1.0.2",
|
||||
"semver": "2.2.1",
|
||||
"serializable": "^1",
|
||||
"service-hub": "^0.1.0",
|
||||
"space-pen": "3.8.2",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.8.0",
|
||||
"text-buffer": "^3.8.4",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.1",
|
||||
"underscore-plus": "^1.6.6",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.23.0",
|
||||
"atom-dark-ui": "0.42.0",
|
||||
"atom-light-syntax": "0.22.0",
|
||||
"atom-light-syntax": "0.24.0",
|
||||
"atom-light-ui": "0.36.0",
|
||||
"base16-tomorrow-dark-theme": "0.22.0",
|
||||
"base16-tomorrow-light-theme": "0.5.0",
|
||||
"solarized-dark-syntax": "0.24.0",
|
||||
"solarized-light-syntax": "0.13.0",
|
||||
"archive-view": "0.37.0",
|
||||
"autocomplete": "0.33.1",
|
||||
"autoflow": "0.18.0",
|
||||
"autosave": "0.18.0",
|
||||
"background-tips": "0.17.0",
|
||||
"bookmarks": "0.30.0",
|
||||
"bracket-matcher": "0.62.0",
|
||||
"command-palette": "0.29.0",
|
||||
"deprecation-cop": "0.18.0",
|
||||
"dev-live-reload": "0.35.0",
|
||||
"encoding-selector": "0.8.0",
|
||||
"exception-reporting": "0.20.0",
|
||||
"find-and-replace": "0.147.0",
|
||||
"fuzzy-finder": "0.60.0",
|
||||
"git-diff": "0.43.0",
|
||||
"go-to-line": "0.26.0",
|
||||
"grammar-selector": "0.37.0",
|
||||
"image-view": "0.42.0",
|
||||
"incompatible-packages": "0.10.0",
|
||||
"keybinding-resolver": "0.20.0",
|
||||
"link": "0.26.0",
|
||||
"markdown-preview": "0.110.0",
|
||||
"metrics": "0.39.0",
|
||||
"notifications": "0.4.0",
|
||||
"open-on-github": "0.30.0",
|
||||
"package-generator": "0.32.0",
|
||||
"release-notes": "0.36.0",
|
||||
"settings-view": "0.161.0",
|
||||
"snippets": "0.57.0",
|
||||
"spell-check": "0.44.0",
|
||||
"status-bar": "0.48.0",
|
||||
"styleguide": "0.30.0",
|
||||
"symbols-view": "0.68.0",
|
||||
"tabs": "0.56.0",
|
||||
"timecop": "0.23.0",
|
||||
"tree-view": "0.134.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.19.0",
|
||||
"whitespace": "0.26.0",
|
||||
"wrap-guide": "0.24.0",
|
||||
"language-c": "0.31.0",
|
||||
"language-coffee-script": "0.38.1",
|
||||
"language-css": "0.23.1",
|
||||
"language-gfm": "0.54.1",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.19.1",
|
||||
"language-html": "0.26.1",
|
||||
"base16-tomorrow-dark-theme": "0.23.0",
|
||||
"base16-tomorrow-light-theme": "0.6.0",
|
||||
"solarized-dark-syntax": "0.30.0",
|
||||
"solarized-light-syntax": "0.17.0",
|
||||
"archive-view": "0.43.0",
|
||||
"autocomplete": "0.40.0",
|
||||
"autoflow": "0.20.0",
|
||||
"autosave": "0.19.0",
|
||||
"background-tips": "0.20.0",
|
||||
"bookmarks": "0.33.0",
|
||||
"bracket-matcher": "0.67.0",
|
||||
"command-palette": "0.32.0",
|
||||
"deprecation-cop": "0.22.0",
|
||||
"dev-live-reload": "0.36.0",
|
||||
"encoding-selector": "0.14.0",
|
||||
"exception-reporting": "0.21.0",
|
||||
"find-and-replace": "0.155.0",
|
||||
"fuzzy-finder": "0.64.0",
|
||||
"git-diff": "0.47.0",
|
||||
"go-to-line": "0.30.0",
|
||||
"grammar-selector": "0.42.0",
|
||||
"image-view": "0.46.0",
|
||||
"incompatible-packages": "0.19.0",
|
||||
"keybinding-resolver": "0.25.0",
|
||||
"link": "0.28.0",
|
||||
"markdown-preview": "0.116.0",
|
||||
"metrics": "0.40.0",
|
||||
"notifications": "0.23.0",
|
||||
"open-on-github": "0.31.0",
|
||||
"package-generator": "0.36.0",
|
||||
"release-notes": "0.45.0",
|
||||
"settings-view": "0.166.0",
|
||||
"snippets": "0.66.0",
|
||||
"spell-check": "0.49.0",
|
||||
"status-bar": "0.56.0",
|
||||
"styleguide": "0.39.0",
|
||||
"symbols-view": "0.77.0",
|
||||
"tabs": "0.61.0",
|
||||
"timecop": "0.26.0",
|
||||
"tree-view": "0.147.0",
|
||||
"update-package-dependencies": "0.7.0",
|
||||
"welcome": "0.21.0",
|
||||
"whitespace": "0.28.0",
|
||||
"wrap-guide": "0.29.0",
|
||||
"language-c": "0.37.0",
|
||||
"language-clojure": "0.10.0",
|
||||
"language-coffee-script": "0.39.0",
|
||||
"language-css": "0.26.0",
|
||||
"language-gfm": "0.59.0",
|
||||
"language-git": "0.10.0",
|
||||
"language-go": "0.20.0",
|
||||
"language-html": "0.28.0",
|
||||
"language-hyperlink": "0.12.2",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.45.1",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.18.1",
|
||||
"language-make": "0.12.0",
|
||||
"language-mustache": "0.10.1",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.18.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.24.1",
|
||||
"language-ruby": "0.42.0",
|
||||
"language-java": "0.14.0",
|
||||
"language-javascript": "0.53.0",
|
||||
"language-json": "0.11.0",
|
||||
"language-less": "0.24.0",
|
||||
"language-make": "0.13.0",
|
||||
"language-mustache": "0.11.0",
|
||||
"language-objective-c": "0.15.0",
|
||||
"language-perl": "0.10.0",
|
||||
"language-php": "0.20.0",
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.29.0",
|
||||
"language-ruby": "0.47.0",
|
||||
"language-ruby-on-rails": "0.18.0",
|
||||
"language-sass": "0.26.1",
|
||||
"language-shellscript": "0.10.1",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.11.0",
|
||||
"language-sass": "0.30.0",
|
||||
"language-shellscript": "0.12.0",
|
||||
"language-source": "0.9.0",
|
||||
"language-sql": "0.13.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.13.0",
|
||||
"language-toml": "0.14.1",
|
||||
"language-xml": "0.25.0",
|
||||
"language-yaml": "0.20.1"
|
||||
"language-todo": "0.15.0",
|
||||
"language-toml": "0.15.0",
|
||||
"language-xml": "0.26.0",
|
||||
"language-yaml": "0.22.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 284 KiB Depois Largura: | Altura: | Tamanho: 628 KiB |
@@ -1,6 +1,6 @@
|
||||
Package: <%= name %>
|
||||
Version: <%= version %>
|
||||
Depends: gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11, libnotify4, libxtst6, libnss3, python, gvfs-bin, xdg-utils
|
||||
Depends: git, gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11, libnotify4, libxtst6, libnss3, python, gvfs-bin, xdg-utils
|
||||
Suggests: libgnome-keyring0, gir1.2-gnomekeyring-1.0
|
||||
Section: <%= section %>
|
||||
Priority: optional
|
||||
|
||||
Arquivo binário não exibido.
Arquivo binário não exibido.
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
"$0/../../app/apm/node_modules/atom-package-manager/bin/node.exe" "$0/../../app/apm/node_modules/atom-package-manager/lib/cli.js" "$@"
|
||||
@@ -0,0 +1,22 @@
|
||||
@echo off
|
||||
|
||||
SET EXPECT_OUTPUT=
|
||||
|
||||
FOR %%a IN (%*) DO (
|
||||
IF /I "%%a"=="-f" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="--foreground" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="-h" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="--help" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="-t" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="--test" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="-v" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="--version" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="-w" SET EXPECT_OUTPUT=YES
|
||||
IF /I "%%a"=="--wait" SET EXPECT_OUTPUT=YES
|
||||
)
|
||||
|
||||
IF "%EXPECT_OUTPUT%"=="YES" (
|
||||
"%~dp0\..\..\atom.exe" %*
|
||||
) ELSE (
|
||||
"%~dp0\..\app\apm\node_modules\atom-package-manager\bin\node.exe" "%~dp0\atom.js" %*
|
||||
)
|
||||
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 141 KiB Depois Largura: | Altura: | Tamanho: 182 KiB |
@@ -0,0 +1,9 @@
|
||||
var path = require('path');
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
var atomCommandPath = path.resolve(__dirname, '..', '..', 'atom.exe');
|
||||
var arguments = process.argv.slice(2);
|
||||
arguments.unshift('--executed-from', process.cwd());
|
||||
var options = {detached: true, stdio: 'ignore'};
|
||||
spawn(atomCommandPath, arguments, options);
|
||||
process.exit(0);
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
while getopts ":fhtvw-:" opt; do
|
||||
case "$opt" in
|
||||
-)
|
||||
case "${OPTARG}" in
|
||||
foreground|help|test|version|wait)
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
f|h|t|v|w)
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
"$0/../../../atom.exe" "$@"
|
||||
else
|
||||
"$0/../../app/apm/node_modules/atom-package-manager/bin/node.exe" "$0/../atom.js" "$@"
|
||||
fi
|
||||
@@ -4,7 +4,9 @@ set -e
|
||||
|
||||
docker build -t atom-rpm .
|
||||
docker run \
|
||||
--rm \
|
||||
--env JANKY_SHA1="$JANKY_SHA1" \
|
||||
--env JANKY_BRANCH="$JANKY_BRANCH" \
|
||||
--env ATOM_ACCESS_TOKEN="$BUILD_ATOM_RPM_ACCESS_TOKEN" \
|
||||
atom-rpm /atom/script/rpmbuild
|
||||
docker rmi atom-rpm
|
||||
|
||||
@@ -38,7 +38,8 @@ module.exports =
|
||||
class AtomReporter extends View
|
||||
@content: ->
|
||||
@div class: 'spec-reporter', =>
|
||||
@div outlet: "suites"
|
||||
@div class: 'padded pull-right', =>
|
||||
@button outlet: 'reloadButton', class: 'btn btn-small reload-button', 'Reload Specs'
|
||||
@div outlet: 'coreArea', class: 'symbol-area', =>
|
||||
@div outlet: 'coreHeader', class: 'symbol-header'
|
||||
@ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
|
||||
@@ -80,6 +81,8 @@ class AtomReporter extends View
|
||||
@on 'click', '.stack-trace', ->
|
||||
$(this).toggleClass('expanded')
|
||||
|
||||
@reloadButton.on 'click', -> require('ipc').send('call-window-method', 'restart')
|
||||
|
||||
reportRunnerResults: (runner) ->
|
||||
@updateSpecCounts()
|
||||
@status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
|
||||
@@ -114,7 +117,7 @@ class AtomReporter extends View
|
||||
@div class: 'result-message fail deprecation-message', =>
|
||||
@raw marked(deprecation.message)
|
||||
|
||||
for stack in deprecation.stacks
|
||||
for stack in deprecation.getStacks()
|
||||
fullStack = stack.map ({functionName, location}) ->
|
||||
if functionName is '<unknown>'
|
||||
" at #{location}"
|
||||
|
||||
@@ -54,6 +54,7 @@ describe "the `atom` global", ->
|
||||
describe "loading default config", ->
|
||||
it 'loads the default core config', ->
|
||||
expect(atom.config.get('core.excludeVcsIgnoredPaths')).toBe true
|
||||
expect(atom.config.get('core.followSymlinks')).toBe false
|
||||
expect(atom.config.get('editor.showInvisibles')).toBe false
|
||||
|
||||
describe "window onerror handler", ->
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
ChildProcess = require 'child_process'
|
||||
path = require 'path'
|
||||
BufferedProcess = require '../src/buffered-process'
|
||||
|
||||
describe "BufferedProcess", ->
|
||||
describe "when a bad command is specified", ->
|
||||
[oldOnError] = []
|
||||
beforeEach ->
|
||||
oldOnError = window.onerror
|
||||
window.onerror = jasmine.createSpy()
|
||||
|
||||
afterEach ->
|
||||
window.onerror = oldOnError
|
||||
|
||||
describe "when there is an error handler specified", ->
|
||||
it "calls the error handler and does not throw an exception", ->
|
||||
process = new BufferedProcess
|
||||
command: 'bad-command-nope'
|
||||
args: ['nothing']
|
||||
options: {}
|
||||
|
||||
errorSpy = jasmine.createSpy().andCallFake (error) -> error.handle()
|
||||
process.onWillThrowError(errorSpy)
|
||||
|
||||
waitsFor -> errorSpy.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(window.onerror).not.toHaveBeenCalled()
|
||||
expect(errorSpy).toHaveBeenCalled()
|
||||
expect(errorSpy.mostRecentCall.args[0].error.message).toContain 'spawn bad-command-nope ENOENT'
|
||||
|
||||
describe "when there is not an error handler specified", ->
|
||||
it "calls the error handler and does not throw an exception", ->
|
||||
process = new BufferedProcess
|
||||
command: 'bad-command-nope'
|
||||
args: ['nothing']
|
||||
options: {}
|
||||
|
||||
waitsFor -> window.onerror.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(window.onerror).toHaveBeenCalled()
|
||||
expect(window.onerror.mostRecentCall.args[0]).toContain 'Failed to spawn command `bad-command-nope`'
|
||||
expect(window.onerror.mostRecentCall.args[4].name).toBe 'BufferedProcessError'
|
||||
|
||||
describe "on Windows", ->
|
||||
originalPlatform = null
|
||||
|
||||
beforeEach ->
|
||||
# Prevent any commands from actually running and affecting the host
|
||||
originalSpawn = ChildProcess.spawn
|
||||
spyOn(ChildProcess, 'spawn').andCallFake ->
|
||||
# Just spawn something that won't actually modify the host
|
||||
if originalPlatform is 'win32'
|
||||
originalSpawn('dir')
|
||||
else
|
||||
originalSpawn('ls')
|
||||
|
||||
originalPlatform = process.platform
|
||||
Object.defineProperty process, 'platform', value: 'win32'
|
||||
|
||||
afterEach ->
|
||||
Object.defineProperty process, 'platform', value: originalPlatform
|
||||
|
||||
describe "when the explorer command is spawned on Windows", ->
|
||||
it "doesn't quote arguments of the form /root,C...", ->
|
||||
new BufferedProcess({command: 'explorer.exe', args: ['/root,C:\\foo']})
|
||||
expect(ChildProcess.spawn.argsForCall[0][1][2]).toBe '"explorer.exe /root,C:\\foo"'
|
||||
|
||||
it "spawns the command using a cmd.exe wrapper", ->
|
||||
new BufferedProcess({command: 'dir'})
|
||||
expect(path.basename(ChildProcess.spawn.argsForCall[0][0])).toBe 'cmd.exe'
|
||||
expect(ChildProcess.spawn.argsForCall[0][1][0]).toBe '/s'
|
||||
expect(ChildProcess.spawn.argsForCall[0][1][1]).toBe '/c'
|
||||
expect(ChildProcess.spawn.argsForCall[0][1][2]).toBe '"dir"'
|
||||
+1089
-847
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1085,6 +1085,12 @@ describe "DisplayBuffer", ->
|
||||
expect(oldProperties).toEqual decorationProperties
|
||||
expect(newProperties).toEqual type: 'gutter', class: 'two', id: decoration.id
|
||||
|
||||
describe "::getDecorations(properties)", ->
|
||||
it "returns decorations matching the given optional properties", ->
|
||||
expect(displayBuffer.getDecorations()).toEqual [decoration]
|
||||
expect(displayBuffer.getDecorations(class: 'two').length).toEqual 0
|
||||
expect(displayBuffer.getDecorations(class: 'one').length).toEqual 1
|
||||
|
||||
describe "::setScrollTop", ->
|
||||
beforeEach ->
|
||||
displayBuffer.manageScrollPosition = true
|
||||
|
||||
@@ -9,6 +9,6 @@ module.exports =
|
||||
atom.commands.add 'atom-workspace', 'activation-command', =>
|
||||
@activationCommandCallCount++
|
||||
|
||||
editorView = atom.views.getView(atom.workspace.getActiveEditor())?.__spacePenView
|
||||
editorView = atom.views.getView(atom.workspace.getActiveTextEditor())?.__spacePenView
|
||||
editorView?.command 'activation-command', =>
|
||||
@legacyActivationCommandCallCount++
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "package-with-empty-keymap",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "package-with-empty-menu",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@@ -132,7 +132,7 @@ describe "GitRepository", ->
|
||||
atom.workspace.open(filePath)
|
||||
|
||||
runs ->
|
||||
editor = atom.workspace.getActiveEditor()
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
|
||||
it "displays a confirmation dialog by default", ->
|
||||
spyOn(atom, 'confirm').andCallFake ({buttons}) -> buttons.OK()
|
||||
@@ -259,6 +259,10 @@ describe "GitRepository", ->
|
||||
editor.getBuffer().emitter.emit 'did-change-path'
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
it "stops listening to the buffer when the repository is destroyed (regression)", ->
|
||||
atom.project.getRepositories()[0].destroy()
|
||||
expect(-> editor.save()).not.toThrow()
|
||||
|
||||
describe "when a project is deserialized", ->
|
||||
[buffer, project2] = []
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
|
||||
log(str)
|
||||
onComplete: (runner) ->
|
||||
fs.closeSync(logStream) if logStream?
|
||||
if process.env.JANKY_SHA1
|
||||
grim = require 'grim'
|
||||
grim.logDeprecations() if grim.getDeprecationsLength() > 0
|
||||
atom.exit(runner.results().failedCount > 0 ? 1 : 0)
|
||||
else
|
||||
AtomReporter = require './atom-reporter'
|
||||
|
||||
@@ -381,6 +381,23 @@ describe "LanguageMode", ->
|
||||
expect(languageMode.isFoldableAtBufferRow(3)).toBe false
|
||||
expect(languageMode.isFoldableAtBufferRow(4)).toBe true
|
||||
|
||||
describe ".foldAllAtIndentLevel(indentLevel)", ->
|
||||
it "folds blocks of text at the given indentation level", ->
|
||||
languageMode.foldAllAtIndentLevel(0)
|
||||
expect(editor.lineTextForScreenRow(0)).toBe "var quicksort = function () {"
|
||||
expect(editor.getLastScreenRow()).toBe 0
|
||||
|
||||
languageMode.foldAllAtIndentLevel(1)
|
||||
expect(editor.lineTextForScreenRow(0)).toBe "var quicksort = function () {"
|
||||
expect(editor.lineTextForScreenRow(1)).toBe " var sort = function(items) {"
|
||||
expect(editor.getLastScreenRow()).toBe 4
|
||||
|
||||
languageMode.foldAllAtIndentLevel(2)
|
||||
expect(editor.lineTextForScreenRow(0)).toBe "var quicksort = function () {"
|
||||
expect(editor.lineTextForScreenRow(1)).toBe " var sort = function(items) {"
|
||||
expect(editor.lineTextForScreenRow(2)).toBe " if (items.length <= 1) return items;"
|
||||
expect(editor.getLastScreenRow()).toBe 9
|
||||
|
||||
describe "folding with comments", ->
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
|
||||
@@ -16,3 +16,32 @@ describe "Notification", ->
|
||||
it "returns the icon specified", ->
|
||||
notification = new Notification('error', 'message!', icon: 'my-icon')
|
||||
expect(notification.getIcon()).toBe 'my-icon'
|
||||
|
||||
describe "dismissing notifications", ->
|
||||
describe "when the notfication is dismissable", ->
|
||||
it "calls a callback when the notification is dismissed", ->
|
||||
dismissedSpy = jasmine.createSpy()
|
||||
notification = new Notification('error', 'message', dismissable: true)
|
||||
notification.onDidDismiss dismissedSpy
|
||||
|
||||
expect(notification.isDismissable()).toBe true
|
||||
expect(notification.isDismissed()).toBe false
|
||||
|
||||
notification.dismiss()
|
||||
|
||||
expect(dismissedSpy).toHaveBeenCalled()
|
||||
expect(notification.isDismissed()).toBe true
|
||||
|
||||
describe "when the notfication is not dismissable", ->
|
||||
it "does nothing when ::dismiss() is called", ->
|
||||
dismissedSpy = jasmine.createSpy()
|
||||
notification = new Notification('error', 'message')
|
||||
notification.onDidDismiss dismissedSpy
|
||||
|
||||
expect(notification.isDismissable()).toBe false
|
||||
expect(notification.isDismissed()).toBe true
|
||||
|
||||
notification.dismiss()
|
||||
|
||||
expect(dismissedSpy).not.toHaveBeenCalled()
|
||||
expect(notification.isDismissed()).toBe true
|
||||
|
||||
@@ -3,19 +3,36 @@ Package = require '../src/package'
|
||||
|
||||
describe "PackageManager", ->
|
||||
workspaceElement = null
|
||||
|
||||
beforeEach ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
|
||||
describe "::loadPackage(name)", ->
|
||||
it "continues if the package has an invalid package.json", ->
|
||||
spyOn(console, 'warn')
|
||||
beforeEach ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
expect(-> atom.packages.loadPackage("package-with-broken-package-json")).not.toThrow()
|
||||
|
||||
it "continues if the package has an invalid keymap", ->
|
||||
it "returns the package", ->
|
||||
pack = atom.packages.loadPackage("package-with-index")
|
||||
expect(pack instanceof Package).toBe true
|
||||
expect(pack.metadata.name).toBe "package-with-index"
|
||||
|
||||
it "returns the package if it has an invalid keymap", ->
|
||||
spyOn(console, 'warn')
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
expect(-> atom.packages.loadPackage("package-with-broken-keymap")).not.toThrow()
|
||||
pack = atom.packages.loadPackage("package-with-broken-keymap")
|
||||
expect(pack instanceof Package).toBe true
|
||||
expect(pack.metadata.name).toBe "package-with-broken-keymap"
|
||||
|
||||
it "returns null if the package has an invalid package.json", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.loadPackage("package-with-broken-package-json")).toBeNull()
|
||||
expect(console.warn.callCount).toBe(1)
|
||||
expect(console.warn.argsForCall[0][0]).toContain("Failed to load package.json")
|
||||
|
||||
it "returns null if the package is not found in any package directory", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.loadPackage("this-package-cannot-be-found")).toBeNull()
|
||||
expect(console.warn.callCount).toBe(1)
|
||||
expect(console.warn.argsForCall[0][0]).toContain("Could not resolve")
|
||||
|
||||
describe "::unloadPackage(name)", ->
|
||||
describe "when the package is active", ->
|
||||
@@ -144,7 +161,7 @@ describe "PackageManager", ->
|
||||
atom.workspace.open()
|
||||
|
||||
runs ->
|
||||
editorView = atom.views.getView(atom.workspace.getActiveEditor()).__spacePenView
|
||||
editorView = atom.views.getView(atom.workspace.getActiveTextEditor()).__spacePenView
|
||||
legacyCommandListener = jasmine.createSpy("legacyCommandListener")
|
||||
editorView.command 'activation-command', legacyCommandListener
|
||||
editorCommandListener = jasmine.createSpy("editorCommandListener")
|
||||
@@ -197,11 +214,30 @@ describe "PackageManager", ->
|
||||
runs ->
|
||||
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
|
||||
|
||||
it "logs warning instead of throwing an exception if the package fails to load", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
spyOn(console, "warn")
|
||||
expect(-> atom.packages.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
describe "when the package throws an error while loading", ->
|
||||
it "logs a warning instead of throwing an exception", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
spyOn(console, "warn")
|
||||
expect(-> atom.packages.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
|
||||
describe "when the package is not found", ->
|
||||
it "rejects the promise", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
|
||||
onSuccess = jasmine.createSpy('onSuccess')
|
||||
onFailure = jasmine.createSpy('onFailure')
|
||||
spyOn(console, 'warn')
|
||||
|
||||
atom.packages.activatePackage("this-doesnt-exist").then(onSuccess, onFailure)
|
||||
|
||||
waitsFor "promise to be rejected", ->
|
||||
onFailure.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(onFailure.mostRecentCall.args[0] instanceof Error).toBe true
|
||||
expect(onFailure.mostRecentCall.args[0].message).toContain "Failed to load package 'this-doesnt-exist'"
|
||||
|
||||
describe "keymap loading", ->
|
||||
describe "when the metadata does not contain a 'keymaps' manifest", ->
|
||||
@@ -237,6 +273,14 @@ describe "PackageManager", ->
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-n', target:element1[0])[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-y', target:element3[0])).toHaveLength 0
|
||||
|
||||
describe "when the keymap file is empty", ->
|
||||
it "does not throw an error on activation", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-empty-keymap")
|
||||
|
||||
runs ->
|
||||
expect(atom.packages.isPackageActive("package-with-empty-keymap")).toBe true
|
||||
|
||||
describe "menu loading", ->
|
||||
beforeEach ->
|
||||
atom.contextMenu.definitions = []
|
||||
@@ -275,6 +319,14 @@ describe "PackageManager", ->
|
||||
expect(atom.contextMenu.templateForElement(element)[1].label).toBe "Menu item 1"
|
||||
expect(atom.contextMenu.templateForElement(element)[2]).toBeUndefined()
|
||||
|
||||
describe "when the menu file is empty", ->
|
||||
it "does not throw an error on activation", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-empty-menu")
|
||||
|
||||
runs ->
|
||||
expect(atom.packages.isPackageActive("package-with-empty-menu")).toBe true
|
||||
|
||||
describe "stylesheet loading", ->
|
||||
describe "when the metadata contains a 'stylesheets' manifest", ->
|
||||
it "loads stylesheets from the stylesheets directory as specified by the manifest", ->
|
||||
@@ -364,10 +416,10 @@ describe "PackageManager", ->
|
||||
describe "scoped-property loading", ->
|
||||
it "loads the scoped properties", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-scoped-properties")
|
||||
atom.packages.activatePackage("package-with-settings")
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBe '^a'
|
||||
|
||||
describe "converted textmate packages", ->
|
||||
it "loads the package's grammars", ->
|
||||
@@ -380,13 +432,13 @@ describe "PackageManager", ->
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
|
||||
it "loads the translated scoped properties", ->
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
expect(atom.config.get('editor.commentStart', scope: ['.source.ruby'])).toBeUndefined()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-ruby')
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBe '# '
|
||||
expect(atom.config.get('editor.commentStart', scope: ['.source.ruby'])).toBe '# '
|
||||
|
||||
describe "::deactivatePackage(id)", ->
|
||||
afterEach ->
|
||||
@@ -490,12 +542,12 @@ describe "PackageManager", ->
|
||||
|
||||
it "removes the package's scoped-properties", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-scoped-properties")
|
||||
atom.packages.activatePackage("package-with-settings")
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
|
||||
atom.packages.deactivatePackage("package-with-scoped-properties")
|
||||
expect(atom.config.get ['.source.omg'], 'editor.increaseIndentPattern').toBeUndefined()
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBe '^a'
|
||||
atom.packages.deactivatePackage("package-with-settings")
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBeUndefined()
|
||||
|
||||
describe "textmate packages", ->
|
||||
it "removes the package's grammars", ->
|
||||
@@ -515,7 +567,7 @@ describe "PackageManager", ->
|
||||
|
||||
runs ->
|
||||
atom.packages.deactivatePackage('language-ruby')
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
expect(atom.config.get('editor.commentStart', scope: ['.source.ruby'])).toBeUndefined()
|
||||
|
||||
describe "::activate()", ->
|
||||
packageActivator = null
|
||||
@@ -552,9 +604,9 @@ describe "PackageManager", ->
|
||||
themes = themeActivator.mostRecentCall.args[0]
|
||||
expect(['theme']).toContain(theme.getType()) for theme in themes
|
||||
|
||||
describe "::enablePackage() and ::disablePackage()", ->
|
||||
describe "::enablePackage(id) and ::disablePackage(id)", ->
|
||||
describe "with packages", ->
|
||||
it ".enablePackage() enables a disabled package", ->
|
||||
it "enables a disabled package", ->
|
||||
packageName = 'package-with-main'
|
||||
atom.config.pushAtKeyPath('core.disabledPackages', packageName)
|
||||
atom.packages.observeDisabledPackages()
|
||||
@@ -572,7 +624,7 @@ describe "PackageManager", ->
|
||||
expect(activatedPackages).toContain(pack)
|
||||
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
|
||||
|
||||
it ".disablePackage() disables an enabled package", ->
|
||||
it "disables an enabled package", ->
|
||||
packageName = 'package-with-main'
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage(packageName)
|
||||
@@ -587,6 +639,11 @@ describe "PackageManager", ->
|
||||
expect(activatedPackages).not.toContain(pack)
|
||||
expect(atom.config.get('core.disabledPackages')).toContain packageName
|
||||
|
||||
it "returns null if the package cannot be loaded", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.enablePackage("this-doesnt-exist")).toBeNull()
|
||||
expect(console.warn.callCount).toBe 1
|
||||
|
||||
describe "with themes", ->
|
||||
reloadedHandler = null
|
||||
|
||||
@@ -597,7 +654,7 @@ describe "PackageManager", ->
|
||||
afterEach ->
|
||||
atom.themes.deactivateThemes()
|
||||
|
||||
it ".enablePackage() and .disablePackage() enables and disables a theme", ->
|
||||
it "enables and disables a theme", ->
|
||||
packageName = 'theme-with-package-file'
|
||||
|
||||
expect(atom.config.get('core.themes')).not.toContain packageName
|
||||
|
||||
@@ -148,3 +148,57 @@ describe "PaneContainer", ->
|
||||
saved = container.confirmClose()
|
||||
expect(saved).toBeFalsy()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
describe "::onDidAddPane(callback)", ->
|
||||
it "invokes the given callback when panes are added", ->
|
||||
container = new PaneContainer
|
||||
events = []
|
||||
container.onDidAddPane (event) -> events.push(event)
|
||||
|
||||
pane1 = container.getActivePane()
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitDown()
|
||||
|
||||
expect(events).toEqual [{pane: pane2}, {pane: pane3}]
|
||||
|
||||
describe "::onDidDestroyPane(callback)", ->
|
||||
it "invokes the given callback when panes are destroyed", ->
|
||||
container = new PaneContainer
|
||||
events = []
|
||||
container.onDidDestroyPane (event) -> events.push(event)
|
||||
|
||||
pane1 = container.getActivePane()
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitDown()
|
||||
|
||||
pane2.destroy()
|
||||
pane3.destroy()
|
||||
|
||||
expect(events).toEqual [{pane: pane2}, {pane: pane3}]
|
||||
|
||||
describe "::onWillDestroyPaneItem() and ::onDidDestroyPaneItem", ->
|
||||
it "invokes the given callbacks when an item will be destroyed on any pane", ->
|
||||
container = new PaneContainer
|
||||
pane1 = container.getRoot()
|
||||
item1 = new Object
|
||||
item2 = new Object
|
||||
item3 = new Object
|
||||
|
||||
pane1.addItem(item1)
|
||||
events = []
|
||||
container.onWillDestroyPaneItem (event) -> events.push(['will', event])
|
||||
container.onDidDestroyPaneItem (event) -> events.push(['did', event])
|
||||
pane2 = pane1.splitRight(items: [item2, item3])
|
||||
|
||||
pane1.destroyItem(item1)
|
||||
pane2.destroyItem(item3)
|
||||
pane2.destroyItem(item2)
|
||||
|
||||
expect(events).toEqual [
|
||||
['will', {item: item1, pane: pane1, index: 0}]
|
||||
['did', {item: item1, pane: pane1, index: 0}]
|
||||
['will', {item: item3, pane: pane2, index: 1}]
|
||||
['did', {item: item3, pane: pane2, index: 1}]
|
||||
['will', {item: item2, pane: pane2, index: 0}]
|
||||
['did', {item: item2, pane: pane2, index: 0}]
|
||||
]
|
||||
|
||||
@@ -229,7 +229,7 @@ describe "PaneView", ->
|
||||
|
||||
beforeEach ->
|
||||
pane2Model = paneModel.splitRight() # Can't destroy the last pane, so we add another
|
||||
pane2 = containerModel.getView(pane2Model).__spacePenView
|
||||
pane2 = atom.views.getView(pane2Model).__spacePenView
|
||||
|
||||
it "triggers a 'pane:removed' event with the pane", ->
|
||||
removedHandler = jasmine.createSpy("removedHandler")
|
||||
@@ -262,7 +262,7 @@ describe "PaneView", ->
|
||||
|
||||
beforeEach ->
|
||||
pane2Model = paneModel.splitRight(items: [pane.copyActiveItem()])
|
||||
pane2 = containerModel.getView(pane2Model).__spacePenView
|
||||
pane2 = atom.views.getView(pane2Model).__spacePenView
|
||||
expect(pane2Model.isActive()).toBe true
|
||||
|
||||
it "adds or removes the .active class as appropriate", ->
|
||||
@@ -309,8 +309,8 @@ describe "PaneView", ->
|
||||
pane2Model = pane1Model.splitRight(items: [pane1Model.copyActiveItem()])
|
||||
pane3Model = pane2Model.splitDown(items: [pane2Model.copyActiveItem()])
|
||||
pane2 = pane2Model._view
|
||||
pane2 = containerModel.getView(pane2Model).__spacePenView
|
||||
pane3 = containerModel.getView(pane3Model).__spacePenView
|
||||
pane2 = atom.views.getView(pane2Model).__spacePenView
|
||||
pane3 = atom.views.getView(pane3Model).__spacePenView
|
||||
|
||||
expect(container.find('> atom-pane-axis.horizontal > atom-pane').toArray()).toEqual [pane1[0]]
|
||||
expect(container.find('> atom-pane-axis.horizontal > atom-pane-axis.vertical > atom-pane').toArray()).toEqual [pane2[0], pane3[0]]
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
ViewRegistry = require '../src/view-registry'
|
||||
Panel = require '../src/panel'
|
||||
PanelElement = require '../src/panel-element'
|
||||
PanelContainer = require '../src/panel-container'
|
||||
PanelContainerElement = require '../src/panel-container-element'
|
||||
|
||||
describe "PanelContainerElement", ->
|
||||
[jasmineContent, element, container, viewRegistry] = []
|
||||
[jasmineContent, element, container] = []
|
||||
|
||||
class TestPanelContainerItem
|
||||
constructior: ->
|
||||
@@ -13,25 +12,23 @@ describe "PanelContainerElement", ->
|
||||
class TestPanelContainerItemElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@classList.add('test-root')
|
||||
setModel: (@model) ->
|
||||
initialize: (@model) ->
|
||||
this
|
||||
|
||||
TestPanelContainerItemElement = document.registerElement 'atom-test-container-item-element', prototype: TestPanelContainerItemElement.prototype
|
||||
|
||||
beforeEach ->
|
||||
jasmineContent = document.body.querySelector('#jasmine-content')
|
||||
|
||||
viewRegistry = new ViewRegistry
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: PanelContainer
|
||||
viewConstructor: PanelContainerElement
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: TestPanelContainerItem
|
||||
viewConstructor: TestPanelContainerItemElement
|
||||
atom.views.addViewProvider Panel, (model) ->
|
||||
new PanelElement().initialize(model)
|
||||
atom.views.addViewProvider PanelContainer, (model) ->
|
||||
new PaneContainerElement().initialize(model)
|
||||
atom.views.addViewProvider TestPanelContainerItem, (model) ->
|
||||
new TestPanelContainerItemElement().initialize(model)
|
||||
|
||||
container = new PanelContainer({viewRegistry, location: 'left'})
|
||||
element = container.getView()
|
||||
container = new PanelContainer({location: 'left'})
|
||||
element = atom.views.getView(container)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
it 'has a location class with value from the model', ->
|
||||
@@ -44,9 +41,9 @@ describe "PanelContainerElement", ->
|
||||
|
||||
describe "adding and removing panels", ->
|
||||
it "allows panels to be inserted at any position", ->
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), priority: 10})
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), priority: 5})
|
||||
panel3 = new Panel({viewRegistry, item: new TestPanelContainerItem(), priority: 8})
|
||||
panel1 = new Panel({item: new TestPanelContainerItem(), priority: 10})
|
||||
panel2 = new Panel({item: new TestPanelContainerItem(), priority: 5})
|
||||
panel3 = new Panel({item: new TestPanelContainerItem(), priority: 8})
|
||||
|
||||
container.addPanel(panel1)
|
||||
container.addPanel(panel2)
|
||||
@@ -60,7 +57,7 @@ describe "PanelContainerElement", ->
|
||||
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
panel1 = new Panel({item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel1)
|
||||
expect(element.childNodes.length).toBe 1
|
||||
expect(element.childNodes[0]).toHaveClass 'left'
|
||||
@@ -69,12 +66,12 @@ describe "PanelContainerElement", ->
|
||||
|
||||
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
panel2 = new Panel({item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel2)
|
||||
expect(element.childNodes.length).toBe 2
|
||||
|
||||
expect(panel1.getView().style.display).not.toBe 'none'
|
||||
expect(panel2.getView().style.display).not.toBe 'none'
|
||||
expect(atom.views.getView(panel1).style.display).not.toBe 'none'
|
||||
expect(atom.views.getView(panel2).style.display).not.toBe 'none'
|
||||
|
||||
panel1.destroy()
|
||||
expect(element.childNodes.length).toBe 1
|
||||
@@ -84,26 +81,26 @@ describe "PanelContainerElement", ->
|
||||
|
||||
describe "when the container is at the bottom location", ->
|
||||
beforeEach ->
|
||||
container = new PanelContainer({viewRegistry, location: 'bottom'})
|
||||
element = container.getView()
|
||||
container = new PanelContainer({location: 'bottom'})
|
||||
element = atom.views.getView(container)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), className: 'one'})
|
||||
panel1 = new Panel({item: new TestPanelContainerItem(), className: 'one'})
|
||||
container.addPanel(panel1)
|
||||
expect(element.childNodes.length).toBe 1
|
||||
expect(element.childNodes[0]).toHaveClass 'bottom'
|
||||
expect(element.childNodes[0]).toHaveClass 'tool-panel' # legacy selector support
|
||||
expect(element.childNodes[0]).toHaveClass 'panel-bottom' # legacy selector support
|
||||
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
|
||||
expect(panel1.getView()).toHaveClass 'one'
|
||||
expect(atom.views.getView(panel1)).toHaveClass 'one'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), className: 'two'})
|
||||
panel2 = new Panel({item: new TestPanelContainerItem(), className: 'two'})
|
||||
container.addPanel(panel2)
|
||||
expect(element.childNodes.length).toBe 2
|
||||
expect(panel2.getView()).toHaveClass 'two'
|
||||
expect(atom.views.getView(panel2)).toHaveClass 'two'
|
||||
|
||||
panel1.destroy()
|
||||
expect(element.childNodes.length).toBe 1
|
||||
@@ -113,34 +110,34 @@ describe "PanelContainerElement", ->
|
||||
|
||||
describe "when the container is modal", ->
|
||||
beforeEach ->
|
||||
container = new PanelContainer({viewRegistry, location: 'modal'})
|
||||
element = container.getView()
|
||||
container = new PanelContainer({location: 'modal'})
|
||||
element = atom.views.getView(container)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
it "allows only one panel to be visible at a time", ->
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
panel1 = new Panel({item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel1)
|
||||
|
||||
expect(panel1.getView().style.display).not.toBe 'none'
|
||||
expect(atom.views.getView(panel1).style.display).not.toBe 'none'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
panel2 = new Panel({item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel2)
|
||||
|
||||
expect(panel1.getView().style.display).toBe 'none'
|
||||
expect(panel2.getView().style.display).not.toBe 'none'
|
||||
expect(atom.views.getView(panel1).style.display).toBe 'none'
|
||||
expect(atom.views.getView(panel2).style.display).not.toBe 'none'
|
||||
|
||||
panel1.show()
|
||||
|
||||
expect(panel1.getView().style.display).not.toBe 'none'
|
||||
expect(panel2.getView().style.display).toBe 'none'
|
||||
expect(atom.views.getView(panel1).style.display).not.toBe 'none'
|
||||
expect(atom.views.getView(panel2).style.display).toBe 'none'
|
||||
|
||||
it "adds the 'modal' class to panels", ->
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
panel1 = new Panel({item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel1)
|
||||
|
||||
expect(panel1.getView()).toHaveClass 'modal'
|
||||
expect(atom.views.getView(panel1)).toHaveClass 'modal'
|
||||
|
||||
# legacy selector support
|
||||
expect(panel1.getView()).not.toHaveClass 'tool-panel'
|
||||
expect(panel1.getView()).toHaveClass 'overlay'
|
||||
expect(panel1.getView()).toHaveClass 'from-top'
|
||||
expect(atom.views.getView(panel1)).not.toHaveClass 'tool-panel'
|
||||
expect(atom.views.getView(panel1)).toHaveClass 'overlay'
|
||||
expect(atom.views.getView(panel1)).toHaveClass 'from-top'
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
ViewRegistry = require '../src/view-registry'
|
||||
Panel = require '../src/panel'
|
||||
PanelContainer = require '../src/panel-container'
|
||||
|
||||
describe "PanelContainer", ->
|
||||
[container, viewRegistry] = []
|
||||
[container] = []
|
||||
|
||||
class TestPanelItem
|
||||
constructior: ->
|
||||
|
||||
beforeEach ->
|
||||
viewRegistry = new ViewRegistry
|
||||
container = new PanelContainer({viewRegistry})
|
||||
container = new PanelContainer
|
||||
|
||||
describe "::addPanel(panel)", ->
|
||||
it 'emits an onDidAddPanel event with the index the panel was inserted at', ->
|
||||
@@ -46,7 +44,7 @@ describe "PanelContainer", ->
|
||||
[initialPanel] = []
|
||||
beforeEach ->
|
||||
# 'left' logic is the same as 'top'
|
||||
container = new PanelContainer({viewRegistry, location: 'left'})
|
||||
container = new PanelContainer({location: 'left'})
|
||||
initialPanel = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(initialPanel)
|
||||
|
||||
@@ -75,7 +73,7 @@ describe "PanelContainer", ->
|
||||
[initialPanel] = []
|
||||
beforeEach ->
|
||||
# 'bottom' logic is the same as 'right'
|
||||
container = new PanelContainer({viewRegistry, location: 'right'})
|
||||
container = new PanelContainer({location: 'right'})
|
||||
initialPanel = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(initialPanel)
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
ViewRegistry = require '../src/view-registry'
|
||||
Panel = require '../src/panel'
|
||||
PanelElement = require '../src/panel-element'
|
||||
|
||||
describe "PanelElement", ->
|
||||
[jasmineContent, element, panel, viewRegistry] = []
|
||||
[jasmineContent, element, panel] = []
|
||||
|
||||
class TestPanelItem
|
||||
constructior: ->
|
||||
@@ -11,23 +10,22 @@ describe "PanelElement", ->
|
||||
class TestPanelItemElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@classList.add('test-root')
|
||||
setModel: (@model) ->
|
||||
initialize: (@model) ->
|
||||
this
|
||||
|
||||
TestPanelItemElement = document.registerElement 'atom-test-item-element', prototype: TestPanelItemElement.prototype
|
||||
|
||||
beforeEach ->
|
||||
jasmineContent = document.body.querySelector('#jasmine-content')
|
||||
|
||||
viewRegistry = new ViewRegistry
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: TestPanelItem
|
||||
viewConstructor: TestPanelItemElement
|
||||
atom.views.addViewProvider Panel, (model) ->
|
||||
new PanelElement().initialize(model)
|
||||
atom.views.addViewProvider TestPanelItem, (model) ->
|
||||
new TestPanelItemElement().initialize(model)
|
||||
|
||||
it 'removes the element when the panel is destroyed', ->
|
||||
panel = new Panel({viewRegistry, item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
panel = new Panel({item: new TestPanelItem})
|
||||
element = atom.views.getView(panel)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element.parentNode).toBe jasmineContent
|
||||
@@ -36,15 +34,15 @@ describe "PanelElement", ->
|
||||
|
||||
describe "changing panel visibility", ->
|
||||
it 'initially renders panel created with visibile: false', ->
|
||||
panel = new Panel({viewRegistry, visible: false, item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
panel = new Panel({visible: false, item: new TestPanelItem})
|
||||
element = atom.views.getView(panel)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element.style.display).toBe 'none'
|
||||
|
||||
it 'hides and shows the panel element when Panel::hide() and Panel::show() are called', ->
|
||||
panel = new Panel({viewRegistry, item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
panel = new Panel({item: new TestPanelItem})
|
||||
element = atom.views.getView(panel)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element.style.display).not.toBe 'none'
|
||||
@@ -57,8 +55,8 @@ describe "PanelElement", ->
|
||||
|
||||
describe "when a class name is specified", ->
|
||||
it 'initially renders panel created with visibile: false', ->
|
||||
panel = new Panel({viewRegistry, className: 'some classes', item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
panel = new Panel({className: 'some classes', item: new TestPanelItem})
|
||||
element = atom.views.getView(panel)
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element).toHaveClass 'some'
|
||||
|
||||
@@ -21,3 +21,7 @@ describe "Panel", ->
|
||||
panel.show()
|
||||
expect(panel.isVisible()).toBe true
|
||||
expect(spy).toHaveBeenCalledWith(true)
|
||||
|
||||
panel.destroy()
|
||||
expect(panel.isVisible()).toBe false
|
||||
expect(spy).toHaveBeenCalledWith(false)
|
||||
|
||||
@@ -4,7 +4,6 @@ Project = require '../src/project'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
platform = require './spec-helper-platform'
|
||||
BufferedProcess = require '../src/buffered-process'
|
||||
|
||||
describe "Project", ->
|
||||
@@ -195,290 +194,6 @@ describe "Project", ->
|
||||
expect(atom.project.getPaths()[0]).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
expect(atom.project.getDirectories()[0].path).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
|
||||
describe ".replace()", ->
|
||||
[filePath, commentFilePath, sampleContent, sampleCommentContent] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.project.setPaths([atom.project.resolve('../')])
|
||||
|
||||
filePath = atom.project.resolve('sample.js')
|
||||
commentFilePath = atom.project.resolve('sample-with-comments.js')
|
||||
sampleContent = fs.readFileSync(filePath).toString()
|
||||
sampleCommentContent = fs.readFileSync(commentFilePath).toString()
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, sampleContent)
|
||||
fs.writeFileSync(commentFilePath, sampleCommentContent)
|
||||
|
||||
describe "when a file doesn't exist", ->
|
||||
it "calls back with an error", ->
|
||||
errors = []
|
||||
missingPath = path.resolve('/not-a-file.js')
|
||||
expect(fs.existsSync(missingPath)).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [missingPath], (result, error) ->
|
||||
errors.push(error)
|
||||
|
||||
runs ->
|
||||
expect(errors).toHaveLength 1
|
||||
expect(errors[0].path).toBe missingPath
|
||||
|
||||
describe "when called with unopened files", ->
|
||||
it "replaces properly", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
describe "when a buffer is already open", ->
|
||||
it "replaces properly and saves when not modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
it "does not replace when the path is not specified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample-with-comments.js').then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [commentFilePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe commentFilePath
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'okthen', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
describe ".scan(options, callback)", ->
|
||||
describe "when called with a regex", ->
|
||||
it "calls the callback with all regex results in all files in the project", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /(a)+/, (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results[0].filePath).toBe atom.project.resolve('a')
|
||||
expect(results[0].matches).toHaveLength(3)
|
||||
expect(results[0].matches[0]).toEqual
|
||||
matchText: 'aaa'
|
||||
lineText: 'aaa bbb'
|
||||
lineTextOffset: 0
|
||||
range: [[0, 0], [0, 3]]
|
||||
|
||||
it "works with with escaped literals (like $ and ^)", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /\$\w+/, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results.length).toBe 1
|
||||
|
||||
{filePath, matches} = results[0]
|
||||
expect(filePath).toBe atom.project.resolve('a')
|
||||
expect(matches).toHaveLength 1
|
||||
expect(matches[0]).toEqual
|
||||
matchText: '$bill'
|
||||
lineText: 'dollar$bill'
|
||||
lineTextOffset: 0
|
||||
range: [[2, 6], [2, 11]]
|
||||
|
||||
it "works on evil filenames", ->
|
||||
platform.generateEvilFiles()
|
||||
atom.project.setPaths([path.join(__dirname, 'fixtures', 'evil-files')])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /evil/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
_.each(matches, (m) -> expect(m.matchText).toEqual 'evil')
|
||||
|
||||
if platform.isWindows()
|
||||
expect(paths.length).toBe 3
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(path.basename(paths[2])).toBe "utfa\u0306.md"
|
||||
else
|
||||
expect(paths.length).toBe 5
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(paths[2]).toMatch /goddam\nnewlines$/m
|
||||
expect(paths[3]).toMatch /quote".txt$/m
|
||||
expect(path.basename(paths[4])).toBe "utfa\u0306.md"
|
||||
|
||||
it "ignores case if the regex includes the `i` flag", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /DOLLAR/i, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
|
||||
describe "when the core.excludeVcsIgnoredPaths config is truthy", ->
|
||||
[projectPath, ignoredPath] = []
|
||||
|
||||
beforeEach ->
|
||||
sourceProjectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
projectPath = path.join(temp.mkdirSync("atom"))
|
||||
|
||||
writerStream = fstream.Writer(projectPath)
|
||||
fstream.Reader(sourceProjectPath).pipe(writerStream)
|
||||
|
||||
waitsFor (done) ->
|
||||
writerStream.on 'close', done
|
||||
writerStream.on 'error', done
|
||||
|
||||
runs ->
|
||||
fs.rename(path.join(projectPath, 'git.git'), path.join(projectPath, '.git'))
|
||||
ignoredPath = path.join(projectPath, 'ignored.txt')
|
||||
fs.writeFileSync(ignoredPath, 'this match should not be included')
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(projectPath) if fs.existsSync(projectPath)
|
||||
|
||||
it "excludes ignored files", ->
|
||||
atom.project.setPaths([projectPath])
|
||||
atom.config.set('core.excludeVcsIgnoredPaths', true)
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.project.scan /match/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "includes only files when a directory filter is specified", ->
|
||||
projectPath = path.join(path.join(__dirname, 'fixtures', 'dir'))
|
||||
atom.project.setPaths([projectPath])
|
||||
|
||||
filePath = path.join(projectPath, 'a-dir', 'oh-git')
|
||||
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /aaa/, paths: ["a-dir#{path.sep}"], (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "includes files and folders that begin with a '.'", ->
|
||||
projectPath = temp.mkdirSync()
|
||||
filePath = path.join(projectPath, '.text')
|
||||
fs.writeFileSync(filePath, 'match this')
|
||||
atom.project.setPaths([projectPath])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /match this/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "excludes values in core.ignoredNames", ->
|
||||
projectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
ignoredNames = atom.config.get("core.ignoredNames")
|
||||
ignoredNames.push("a")
|
||||
atom.config.set("core.ignoredNames", ignoredNames)
|
||||
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.project.scan /dollar/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('a').then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.scan /a|Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 3
|
||||
resultForA = _.find results, ({filePath}) -> path.basename(filePath) == 'a'
|
||||
expect(resultForA.matches).toHaveLength 1
|
||||
expect(resultForA.matches[0].matchText).toBe 'Elephant'
|
||||
|
||||
it "ignores buffers outside the project", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(temp.openSync().path).then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.scan /Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 0
|
||||
|
||||
describe ".eachBuffer(callback)", ->
|
||||
beforeEach ->
|
||||
atom.project.bufferForPathSync('a')
|
||||
|
||||
@@ -84,6 +84,10 @@ beforeEach ->
|
||||
atom.workspaceViewParentSelector = '#jasmine-content'
|
||||
|
||||
window.resetTimeouts()
|
||||
spyOn(_._, "now").andCallFake -> window.now
|
||||
spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout
|
||||
spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout
|
||||
|
||||
atom.packages.packageStates = {}
|
||||
|
||||
serializedWindowState = null
|
||||
@@ -102,9 +106,9 @@ beforeEach ->
|
||||
spyOn(atom.menu, 'sendToBrowserProcess')
|
||||
|
||||
# reset config before each spec; don't load or save from/to `config.json`
|
||||
spyOn(Config::, 'load')
|
||||
spyOn(Config::, 'save')
|
||||
config = new Config({resourcePath, configDirPath: atom.getConfigDirPath()})
|
||||
spyOn(config, 'load')
|
||||
spyOn(config, 'save')
|
||||
atom.config = config
|
||||
atom.loadConfig()
|
||||
config.set "core.destroyEmptyPanes", false
|
||||
@@ -114,6 +118,7 @@ beforeEach ->
|
||||
config.set "core.disabledPackages", ["package-that-throws-an-exception",
|
||||
"package-with-broken-package-json", "package-with-broken-keymap"]
|
||||
config.set "editor.useShadowDOM", true
|
||||
advanceClock(1000)
|
||||
config.load.reset()
|
||||
config.save.reset()
|
||||
|
||||
@@ -121,8 +126,6 @@ beforeEach ->
|
||||
TextEditorElement::setUpdatedSynchronously(true)
|
||||
|
||||
spyOn(atom, "setRepresentedFilename")
|
||||
spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout
|
||||
spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout
|
||||
spyOn(pathwatcher.File.prototype, "detectResurrectionAfterDelay").andCallFake -> @detectResurrection()
|
||||
spyOn(TextEditor.prototype, "shouldPromptToSave").andReturn false
|
||||
|
||||
@@ -204,10 +207,10 @@ jasmine.attachToDOM = (element) ->
|
||||
|
||||
deprecationsSnapshot = null
|
||||
jasmine.snapshotDeprecations = ->
|
||||
deprecationsSnapshot = Grim.getDeprecations() # suppress deprecations!!
|
||||
deprecationsSnapshot = _.clone(Grim.deprecations)
|
||||
|
||||
jasmine.restoreDeprecationsSnapshot = ->
|
||||
Grim.grimDeprecations = deprecationsSnapshot
|
||||
Grim.deprecations = deprecationsSnapshot
|
||||
|
||||
addCustomMatchers = (spec) ->
|
||||
spec.addMatchers
|
||||
@@ -304,9 +307,6 @@ window.waitsForPromise = (args...) ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with #{jasmine.pp(error)}")
|
||||
moveOn()
|
||||
|
||||
window.waitsForAnimationFrame = ->
|
||||
waitsFor "next animation frame", (done) -> requestAnimationFrame(done)
|
||||
|
||||
window.resetTimeouts = ->
|
||||
window.now = 0
|
||||
window.timeoutCount = 0
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
ChildProcess = require 'child_process'
|
||||
{EventEmitter} = require 'events'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
SquirrelUpdate = require '../src/browser/squirrel-update'
|
||||
|
||||
describe "Windows squirrel updates", ->
|
||||
tempHomeDirectory = null
|
||||
|
||||
beforeEach ->
|
||||
# Prevent the actually home directory from being manipulated
|
||||
tempHomeDirectory = temp.mkdirSync('atom-temp-home-')
|
||||
spyOn(fs, 'getHomeDirectory').andReturn(tempHomeDirectory)
|
||||
|
||||
# Prevent any commands from actually running and affecting the host
|
||||
originalSpawn = ChildProcess.spawn
|
||||
spyOn(ChildProcess, 'spawn').andCallFake (command, args) ->
|
||||
if path.basename(command) is 'Update.exe' and args?[0] is '--createShortcut'
|
||||
fs.writeFileSync(path.join(tempHomeDirectory, 'Desktop', 'Atom.lnk'), '')
|
||||
|
||||
# Just spawn something that won't actually modify the host
|
||||
if process.platform is 'win32'
|
||||
originalSpawn('dir')
|
||||
else
|
||||
originalSpawn('ls')
|
||||
|
||||
it "ignores errors spawning Squirrel", ->
|
||||
jasmine.unspy(ChildProcess, 'spawn')
|
||||
spyOn(ChildProcess, 'spawn').andCallFake -> throw new Error("EBUSY")
|
||||
|
||||
app = quit: jasmine.createSpy('quit')
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-install')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
it "quits the app on all squirrel events", ->
|
||||
app = quit: jasmine.createSpy('quit')
|
||||
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-install')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
runs ->
|
||||
app.quit.reset()
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-updated')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
runs ->
|
||||
app.quit.reset()
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-uninstall')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
runs ->
|
||||
app.quit.reset()
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-obsolete')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
runs ->
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--not-squirrel')).toBe false
|
||||
|
||||
it "keeps the desktop shortcut deleted on updates if it was previously deleted after install", ->
|
||||
desktopShortcutPath = path.join(tempHomeDirectory, 'Desktop', 'Atom.lnk')
|
||||
expect(fs.existsSync(desktopShortcutPath)).toBe false
|
||||
|
||||
app = quit: jasmine.createSpy('quit')
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-install')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
runs ->
|
||||
app.quit.reset()
|
||||
expect(fs.existsSync(desktopShortcutPath)).toBe true
|
||||
fs.removeSync(desktopShortcutPath)
|
||||
expect(fs.existsSync(desktopShortcutPath)).toBe false
|
||||
expect(SquirrelUpdate.handleStartupEvent(app, '--squirrel-updated')).toBe true
|
||||
|
||||
waitsFor ->
|
||||
app.quit.callCount is 1
|
||||
|
||||
runs ->
|
||||
expect(fs.existsSync(desktopShortcutPath)).toBe false
|
||||
|
||||
describe ".restartAtom", ->
|
||||
it "quits the app and spawns a new one", ->
|
||||
app = new EventEmitter()
|
||||
app.quit = jasmine.createSpy('quit')
|
||||
|
||||
SquirrelUpdate.restartAtom(app)
|
||||
expect(app.quit.callCount).toBe 1
|
||||
|
||||
expect(ChildProcess.spawn.callCount).toBe 0
|
||||
app.emit('will-quit')
|
||||
expect(ChildProcess.spawn.callCount).toBe 1
|
||||
expect(path.basename(ChildProcess.spawn.argsForCall[0][0])).toBe 'atom.cmd'
|
||||
@@ -53,14 +53,16 @@ describe "StyleManager", ->
|
||||
expect(addEvents[0].getAttribute('source-path')).toBe '/foo/bar'
|
||||
expect(addEvents[0].textContent).toBe "a {color: yellow;}"
|
||||
|
||||
describe "when a group parameter is specified", ->
|
||||
it "inserts the stylesheet at the end of any existing stylesheets for the same group", ->
|
||||
manager.addStyleSheet("a {color: red}", group: 'a')
|
||||
manager.addStyleSheet("a {color: blue}", group: 'b')
|
||||
manager.addStyleSheet("a {color: green}", group: 'a')
|
||||
describe "when a priority parameter is specified", ->
|
||||
it "inserts the style sheet based on the priority", ->
|
||||
manager.addStyleSheet("a {color: red}", priority: 1)
|
||||
manager.addStyleSheet("a {color: blue}", priority: 0)
|
||||
manager.addStyleSheet("a {color: green}", priority: 2)
|
||||
manager.addStyleSheet("a {color: yellow}", priority: 1)
|
||||
|
||||
expect(manager.getStyleElements().map (elt) -> elt.textContent).toEqual [
|
||||
"a {color: red}"
|
||||
"a {color: green}"
|
||||
"a {color: blue}"
|
||||
"a {color: red}"
|
||||
"a {color: yellow}"
|
||||
"a {color: green}"
|
||||
]
|
||||
|
||||
@@ -32,16 +32,18 @@ describe "StylesElement", ->
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: blue;}"
|
||||
expect(removedStyleElements).toEqual [addedStyleElements[0]]
|
||||
|
||||
it "orders style elements by group", ->
|
||||
it "orders style elements by priority", ->
|
||||
initialChildCount = element.children.length
|
||||
|
||||
atom.styles.addStyleSheet("a {color: red}", group: 'a')
|
||||
atom.styles.addStyleSheet("a {color: blue}", group: 'b')
|
||||
atom.styles.addStyleSheet("a {color: green}", group: 'a')
|
||||
atom.styles.addStyleSheet("a {color: red}", priority: 1)
|
||||
atom.styles.addStyleSheet("a {color: blue}", priority: 0)
|
||||
atom.styles.addStyleSheet("a {color: green}", priority: 2)
|
||||
atom.styles.addStyleSheet("a {color: yellow}", priority: 1)
|
||||
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: red}"
|
||||
expect(element.children[initialChildCount + 1].textContent).toBe "a {color: green}"
|
||||
expect(element.children[initialChildCount + 2].textContent).toBe "a {color: blue}"
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: blue}"
|
||||
expect(element.children[initialChildCount + 1].textContent).toBe "a {color: red}"
|
||||
expect(element.children[initialChildCount + 2].textContent).toBe "a {color: yellow}"
|
||||
expect(element.children[initialChildCount + 3].textContent).toBe "a {color: green}"
|
||||
|
||||
it "updates existing style nodes when style elements are updated", ->
|
||||
initialChildCount = element.children.length
|
||||
@@ -105,3 +107,8 @@ describe "StylesElement", ->
|
||||
|
||||
document.querySelector('#jasmine-content').appendChild(element)
|
||||
expect(element.firstChild.sheet.cssRules[0].selectorText).toBe ':host'
|
||||
|
||||
it "does not throw exceptions on rules with no selectors", ->
|
||||
atom.styles.addStyleSheet """
|
||||
@media screen {font-size: 10px;}
|
||||
""", context: 'atom-text-editor'
|
||||
|
||||
@@ -755,7 +755,6 @@ describe "TextEditorComponent", ->
|
||||
expect(cursorNode.offsetWidth).toBe charWidth
|
||||
|
||||
it "blinks cursors when they aren't moving", ->
|
||||
spyOn(_._, 'now').andCallFake -> window.now # Ensure _.debounce is based on our fake spec timeline
|
||||
cursorsNode = componentNode.querySelector('.cursors')
|
||||
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe false
|
||||
@@ -1612,6 +1611,22 @@ describe "TextEditorComponent", ->
|
||||
expect(nextAnimationFrame).toBe noAnimationFrame
|
||||
expect(editor.getSelectedScreenRange()).toEqual [[2, 4], [6, 8]]
|
||||
|
||||
describe "when the editor is destroyed while dragging", ->
|
||||
it "cleans up the handlers for window.mouseup and window.mousemove", ->
|
||||
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([2, 4]), which: 1))
|
||||
linesNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenPosition([6, 8]), which: 1))
|
||||
nextAnimationFrame()
|
||||
|
||||
spyOn(window, 'removeEventListener').andCallThrough()
|
||||
|
||||
linesNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenPosition([6, 10]), which: 1))
|
||||
editor.destroy()
|
||||
nextAnimationFrame()
|
||||
|
||||
call.args.pop() for call in window.removeEventListener.calls
|
||||
expect(window.removeEventListener).toHaveBeenCalledWith('mouseup')
|
||||
expect(window.removeEventListener).toHaveBeenCalledWith('mousemove')
|
||||
|
||||
describe "when a line is folded", ->
|
||||
beforeEach ->
|
||||
editor.foldBufferRow 4
|
||||
@@ -1908,7 +1923,8 @@ describe "TextEditorComponent", ->
|
||||
}
|
||||
""", context: 'atom-text-editor'
|
||||
|
||||
nextAnimationFrame()
|
||||
nextAnimationFrame() # handle stylesheet change event
|
||||
nextAnimationFrame() # perform requested update
|
||||
|
||||
scrollbarCornerNode = componentNode.querySelector('.scrollbar-corner')
|
||||
expect(verticalScrollbarNode.offsetWidth).toBe 8
|
||||
@@ -2031,8 +2047,6 @@ describe "TextEditorComponent", ->
|
||||
expect(component.mouseWheelScreenRow).toBe null
|
||||
|
||||
it "clears the mouseWheelScreenRow after a delay even if the event does not cause scrolling", ->
|
||||
spyOn(_._, 'now').andCallFake -> window.now # Ensure _.debounce is based on our fake spec timeline
|
||||
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
|
||||
lineNode = componentNode.querySelector('.line')
|
||||
@@ -2576,9 +2590,9 @@ describe "TextEditorComponent", ->
|
||||
|
||||
describe 'soft wrap settings', ->
|
||||
beforeEach ->
|
||||
atom.config.set '.source.coffee', 'editor.softWrap', true
|
||||
atom.config.set '.source.coffee', 'editor.preferredLineLength', 17
|
||||
atom.config.set '.source.coffee', 'editor.softWrapAtPreferredLineLength', true
|
||||
atom.config.set 'editor.softWrap', true, scopeSelector: '.source.coffee'
|
||||
atom.config.set 'editor.preferredLineLength', 17, scopeSelector: '.source.coffee'
|
||||
atom.config.set 'editor.softWrapAtPreferredLineLength', true, scopeSelector: '.source.coffee'
|
||||
|
||||
editor.setEditorWidthInChars(20)
|
||||
coffeeEditor.setEditorWidthInChars(20)
|
||||
@@ -2588,18 +2602,18 @@ describe "TextEditorComponent", ->
|
||||
expect(coffeeEditor.lineTextForScreenRow(3)).toEqual ' return items '
|
||||
|
||||
it 'updates the wrapped lines when editor.preferredLineLength changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.preferredLineLength', 20
|
||||
atom.config.set 'editor.preferredLineLength', 20, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(2)).toEqual ' return items if '
|
||||
|
||||
it 'updates the wrapped lines when editor.softWrapAtPreferredLineLength changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.softWrapAtPreferredLineLength', false
|
||||
atom.config.set 'editor.softWrapAtPreferredLineLength', false, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(2)).toEqual ' return items if '
|
||||
|
||||
it 'updates the wrapped lines when editor.softWrap changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.softWrap', false
|
||||
atom.config.set 'editor.softWrap', false, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(2)).toEqual ' return items if items.length <= 1'
|
||||
|
||||
atom.config.set '.source.coffee', 'editor.softWrap', true
|
||||
atom.config.set 'editor.softWrap', true, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(3)).toEqual ' return items '
|
||||
|
||||
it 'updates the wrapped lines when the grammar changes', ->
|
||||
@@ -2627,11 +2641,11 @@ describe "TextEditorComponent", ->
|
||||
tab: 'F'
|
||||
cr: 'E'
|
||||
|
||||
atom.config.set '.source.js', 'editor.showInvisibles', true
|
||||
atom.config.set '.source.js', 'editor.invisibles', jsInvisibles
|
||||
atom.config.set 'editor.showInvisibles', true, scopeSelector: '.source.js'
|
||||
atom.config.set 'editor.invisibles', jsInvisibles, scopeSelector: '.source.js'
|
||||
|
||||
atom.config.set '.source.coffee', 'editor.showInvisibles', false
|
||||
atom.config.set '.source.coffee', 'editor.invisibles', coffeeInvisibles
|
||||
atom.config.set 'editor.showInvisibles', false, scopeSelector: '.source.coffee'
|
||||
atom.config.set 'editor.invisibles', coffeeInvisibles, scopeSelector: '.source.coffee'
|
||||
|
||||
editor.setText " a line with tabs\tand spaces \n"
|
||||
nextAnimationFrame()
|
||||
@@ -2647,7 +2661,7 @@ describe "TextEditorComponent", ->
|
||||
it "re-renders the invisibles when the invisible settings change", ->
|
||||
jsGrammar = editor.getGrammar()
|
||||
editor.setGrammar(coffeeEditor.getGrammar())
|
||||
atom.config.set '.source.coffee', 'editor.showInvisibles', true
|
||||
atom.config.set 'editor.showInvisibles', true, scopeSelector: '.source.coffee'
|
||||
nextAnimationFrame()
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{coffeeInvisibles.space}a line with tabs#{coffeeInvisibles.tab}and spaces#{coffeeInvisibles.space}#{coffeeInvisibles.eol}"
|
||||
|
||||
@@ -2656,7 +2670,7 @@ describe "TextEditorComponent", ->
|
||||
space: 'E'
|
||||
tab: 'W'
|
||||
cr: 'I'
|
||||
atom.config.set '.source.coffee', 'editor.invisibles', newInvisibles
|
||||
atom.config.set 'editor.invisibles', newInvisibles, scopeSelector: '.source.coffee'
|
||||
nextAnimationFrame()
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{newInvisibles.space}a line with tabs#{newInvisibles.tab}and spaces#{newInvisibles.space}#{newInvisibles.eol}"
|
||||
|
||||
@@ -2666,8 +2680,8 @@ describe "TextEditorComponent", ->
|
||||
|
||||
describe 'editor.showIndentGuide', ->
|
||||
beforeEach ->
|
||||
atom.config.set '.source.js', 'editor.showIndentGuide', true
|
||||
atom.config.set '.source.coffee', 'editor.showIndentGuide', false
|
||||
atom.config.set 'editor.showIndentGuide', true, scopeSelector: '.source.js'
|
||||
atom.config.set 'editor.showIndentGuide', false, scopeSelector: '.source.coffee'
|
||||
|
||||
it "has an 'indent-guide' class when scoped editor.showIndentGuide is true, but not when scoped editor.showIndentGuide is false", ->
|
||||
line1LeafNodes = getLeafNodes(component.lineNodeForScreenRow(1))
|
||||
@@ -2688,7 +2702,7 @@ describe "TextEditorComponent", ->
|
||||
expect(line1LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false
|
||||
|
||||
atom.config.set '.source.js', 'editor.showIndentGuide', false
|
||||
atom.config.set 'editor.showIndentGuide', false, scopeSelector: '.source.js'
|
||||
|
||||
line1LeafNodes = getLeafNodes(component.lineNodeForScreenRow(1))
|
||||
expect(line1LeafNodes[0].textContent).toBe ' '
|
||||
@@ -2696,26 +2710,35 @@ describe "TextEditorComponent", ->
|
||||
expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false
|
||||
|
||||
describe "middle mouse paste on Linux", ->
|
||||
it "pastes the previously selected text", ->
|
||||
originalPlatform = null
|
||||
|
||||
beforeEach ->
|
||||
originalPlatform = process.platform
|
||||
Object.defineProperty process, 'platform', value: 'linux'
|
||||
|
||||
afterEach ->
|
||||
Object.defineProperty process, 'platform', value: originalPlatform
|
||||
|
||||
it "pastes the previously selected text at the clicked location", ->
|
||||
jasmine.unspy(window, 'setTimeout')
|
||||
clipboardWrittenTo = false
|
||||
spyOn(require('ipc'), 'send').andCallFake (eventName, selectedText) ->
|
||||
if eventName is 'write-text-to-selection-clipboard'
|
||||
require('clipboard').writeText(selectedText, 'selection')
|
||||
clipboardWrittenTo = true
|
||||
|
||||
atom.clipboard.write('')
|
||||
component.listenForMiddleMousePaste()
|
||||
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mouseup', which: 2))
|
||||
|
||||
expect(atom.clipboard.read()).toBe ''
|
||||
expect(editor.lineTextForBufferRow(10)).toBe ''
|
||||
|
||||
component.trackSelectionClipboard()
|
||||
editor.setSelectedBufferRange([[1, 6], [1, 10]])
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mouseup', which: 2))
|
||||
|
||||
expect(atom.clipboard.read()).toBe 'sort'
|
||||
expect(editor.lineTextForBufferRow(10)).toBe 'sort'
|
||||
waitsFor ->
|
||||
clipboardWrittenTo
|
||||
|
||||
runs ->
|
||||
componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([10, 0]), button: 1))
|
||||
componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenPosition([10, 0]), which: 2))
|
||||
expect(atom.clipboard.read()).toBe 'sort'
|
||||
expect(editor.lineTextForBufferRow(10)).toBe 'sort'
|
||||
|
||||
buildMouseEvent = (type, properties...) ->
|
||||
properties = extend({bubbles: true, cancelable: true}, properties...)
|
||||
|
||||
@@ -20,6 +20,11 @@ describe "TextEditorElement", ->
|
||||
element = jasmineContent.firstChild
|
||||
expect(element.getModel().getPlaceholderText()).toBe 'testing'
|
||||
|
||||
it "honors the text content", ->
|
||||
jasmineContent.innerHTML = "<atom-text-editor>testing</atom-text-editor>"
|
||||
element = jasmineContent.firstChild
|
||||
expect(element.getModel().getText()).toBe 'testing'
|
||||
|
||||
describe "when the model is assigned", ->
|
||||
it "adds the 'mini' attribute if .isMini() returns true on the model", ->
|
||||
element = new TextEditorElement
|
||||
@@ -27,6 +32,34 @@ describe "TextEditorElement", ->
|
||||
element.setModel(model)
|
||||
expect(element.hasAttribute('mini')).toBe true
|
||||
|
||||
describe "when the editor is attached to the DOM", ->
|
||||
describe "when the editor.useShadowDOM config option is true", ->
|
||||
it "mounts the react component and unmounts when removed from the dom", ->
|
||||
atom.config.set('editor.useShadowDOM', true)
|
||||
|
||||
element = new TextEditorElement
|
||||
jasmine.attachToDOM(element)
|
||||
|
||||
component = element.component
|
||||
expect(component.isMounted()).toBe true
|
||||
element.remove()
|
||||
expect(component.isMounted()).toBe false
|
||||
|
||||
jasmine.attachToDOM(element)
|
||||
expect(element.component.isMounted()).toBe true
|
||||
|
||||
describe "when the editor.useShadowDOM config option is false", ->
|
||||
it "mounts the react component and unmounts when removed from the dom", ->
|
||||
atom.config.set('editor.useShadowDOM', false)
|
||||
|
||||
element = new TextEditorElement
|
||||
jasmine.attachToDOM(element)
|
||||
|
||||
component = element.component
|
||||
expect(component.isMounted()).toBe true
|
||||
element.getModel().destroy()
|
||||
expect(component.isMounted()).toBe false
|
||||
|
||||
describe "focus and blur handling", ->
|
||||
describe "when the editor.useShadowDOM config option is true", ->
|
||||
it "proxies focus/blur events to/from the hidden input inside the shadow root", ->
|
||||
@@ -99,8 +132,31 @@ describe "TextEditorElement", ->
|
||||
scrollbarWidth = verticalScrollbarNode.offsetWidth - verticalScrollbarNode.clientWidth
|
||||
expect(scrollbarWidth).toEqual(8)
|
||||
|
||||
describe "::onDidAttach and ::onDidDetach", ->
|
||||
it "invokes callbacks when the element is attached and detached", ->
|
||||
element = new TextEditorElement
|
||||
|
||||
attachedCallback = jasmine.createSpy("attachedCallback")
|
||||
detachedCallback = jasmine.createSpy("detachedCallback")
|
||||
|
||||
element.onDidAttach(attachedCallback)
|
||||
element.onDidDetach(detachedCallback)
|
||||
|
||||
jasmine.attachToDOM(element)
|
||||
|
||||
expect(attachedCallback).toHaveBeenCalled()
|
||||
expect(detachedCallback).not.toHaveBeenCalled()
|
||||
|
||||
attachedCallback.reset()
|
||||
element.remove()
|
||||
|
||||
expect(attachedCallback).not.toHaveBeenCalled()
|
||||
expect(detachedCallback).toHaveBeenCalled()
|
||||
|
||||
describe "::setUpdatedSynchronously", ->
|
||||
it "controls whether the text editor is updated synchronously", ->
|
||||
spyOn(window, 'requestAnimationFrame').andCallFake (fn) -> fn()
|
||||
|
||||
element = new TextEditorElement
|
||||
jasmine.attachToDOM(element)
|
||||
|
||||
@@ -108,13 +164,22 @@ describe "TextEditorElement", ->
|
||||
expect(element.isUpdatedSynchronously()).toBe false
|
||||
|
||||
element.getModel().setText("hello")
|
||||
expect(element.shadowRoot.textContent).not.toContain "hello"
|
||||
expect(window.requestAnimationFrame).toHaveBeenCalled()
|
||||
|
||||
waitsForAnimationFrame()
|
||||
expect(element.shadowRoot.textContent).toContain "hello"
|
||||
|
||||
runs ->
|
||||
expect(element.shadowRoot.textContent).toContain "hello"
|
||||
window.requestAnimationFrame.reset()
|
||||
element.setUpdatedSynchronously(true)
|
||||
element.getModel().setText("goodbye")
|
||||
expect(window.requestAnimationFrame).not.toHaveBeenCalled()
|
||||
expect(element.shadowRoot.textContent).toContain "goodbye"
|
||||
|
||||
element.setUpdatedSynchronously(true)
|
||||
element.getModel().setText("goodbye")
|
||||
expect(element.shadowRoot.textContent).toContain "goodbye"
|
||||
describe "::getDefaultCharacterWidth", ->
|
||||
it "returns null before the element is attached", ->
|
||||
element = new TextEditorElement
|
||||
expect(element.getDefaultCharacterWidth()).toBeNull()
|
||||
|
||||
it "returns the width of a character in the root scope", ->
|
||||
element = new TextEditorElement
|
||||
jasmine.attachToDOM(element)
|
||||
expect(element.getDefaultCharacterWidth()).toBeGreaterThan(0)
|
||||
|
||||
@@ -62,7 +62,6 @@ describe "TextEditor", ->
|
||||
atom.workspace.open('sample.less', initialLine: 5).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 5
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 0
|
||||
|
||||
@@ -74,10 +73,37 @@ describe "TextEditor", ->
|
||||
atom.workspace.open('sample.less', initialColumn: 8).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 0
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 8
|
||||
|
||||
describe "when the editor is reopened with an initialLine option", ->
|
||||
it "positions the cursor on the specified line", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialLine: 5).then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialLine: 4).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 4
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 0
|
||||
|
||||
describe "when the editor is reopened with an initialColumn option", ->
|
||||
it "positions the cursor on the specified column", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialColumn: 8).then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialColumn: 7).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 0
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 7
|
||||
|
||||
describe ".copy()", ->
|
||||
it "returns a different edit session with the same initial state", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 4]])
|
||||
@@ -192,12 +218,18 @@ describe "TextEditor", ->
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1, 1]
|
||||
|
||||
it "emits an event with the old position, new position, and the cursor that moved", ->
|
||||
editor.onDidChangeCursorPosition positionChangedHandler = jasmine.createSpy()
|
||||
cursorCallback = jasmine.createSpy('cursor-changed-position')
|
||||
editorCallback = jasmine.createSpy('editor-changed-cursor-position')
|
||||
|
||||
editor.getLastCursor().onDidChangePosition(cursorCallback)
|
||||
editor.onDidChangeCursorPosition(editorCallback)
|
||||
|
||||
editor.setCursorBufferPosition([2, 4])
|
||||
|
||||
expect(positionChangedHandler).toHaveBeenCalled()
|
||||
eventObject = positionChangedHandler.mostRecentCall.args[0]
|
||||
expect(editorCallback).toHaveBeenCalled()
|
||||
expect(cursorCallback).toHaveBeenCalled()
|
||||
eventObject = editorCallback.mostRecentCall.args[0]
|
||||
expect(cursorCallback.mostRecentCall.args[0]).toEqual(eventObject)
|
||||
|
||||
expect(eventObject.oldBufferPosition).toEqual [0, 0]
|
||||
expect(eventObject.oldScreenPosition).toEqual [0, 0]
|
||||
@@ -1321,7 +1353,7 @@ describe "TextEditor", ->
|
||||
coffeeEditor.selectWordsContainingCursors()
|
||||
expect(coffeeEditor.getSelectedBufferRange()).toEqual [[0, 6], [0, 15]]
|
||||
|
||||
atom.config.set '.source.coffee', 'editor.nonWordCharacters', 'qusort'
|
||||
atom.config.set 'editor.nonWordCharacters', 'qusort', scopeSelector: '.source.coffee'
|
||||
|
||||
coffeeEditor.setCursorBufferPosition [0, 9]
|
||||
coffeeEditor.selectWordsContainingCursors()
|
||||
@@ -3270,7 +3302,7 @@ describe "TextEditor", ->
|
||||
atom.packages.unloadPackages()
|
||||
|
||||
it 'returns correct values based on the scope of the set grammars', ->
|
||||
atom.config.set '.source.coffee', 'editor.tabLength', 6
|
||||
atom.config.set 'editor.tabLength', 6, scopeSelector: '.source.coffee'
|
||||
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(coffeeEditor.getTabLength()).toBe 6
|
||||
@@ -3292,12 +3324,12 @@ describe "TextEditor", ->
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
|
||||
atom.config.set '.source.js', 'editor.tabLength', 6
|
||||
atom.config.set 'editor.tabLength', 6, scopeSelector: '.source.js'
|
||||
expect(editor.getTabLength()).toBe 6
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 6
|
||||
|
||||
it 'updates the tab length when the grammar changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.tabLength', 6
|
||||
atom.config.set 'editor.tabLength', 6, scopeSelector: '.source.coffee'
|
||||
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
@@ -3398,7 +3430,6 @@ describe "TextEditor", ->
|
||||
expect(editor.getCursorBufferPosition()).toEqual([7, 2])
|
||||
|
||||
editor.insertNewline()
|
||||
editor.logScreenLines()
|
||||
expect(editor.lineTextForBufferRow(8)).toBe(" ")
|
||||
|
||||
it "does not indent the line preceding the newline", ->
|
||||
@@ -3415,11 +3446,11 @@ describe "TextEditor", ->
|
||||
describe "when the cursor is before whitespace", ->
|
||||
it "retains the whitespace following the cursor on the new line", ->
|
||||
editor.setText(" var sort = function() {}")
|
||||
editor.setCursorScreenPosition([0, 23])
|
||||
editor.setCursorScreenPosition([0, 12])
|
||||
editor.insertNewline()
|
||||
|
||||
expect(buffer.lineForRow(0)).toBe ' var sort = function()'
|
||||
expect(buffer.lineForRow(1)).toBe ' {}'
|
||||
expect(buffer.lineForRow(0)).toBe ' var sort ='
|
||||
expect(buffer.lineForRow(1)).toBe ' function() {}'
|
||||
expect(editor.getCursorScreenPosition()).toEqual [1, 2]
|
||||
|
||||
describe "when inserted text matches a decrease indent pattern", ->
|
||||
@@ -3468,8 +3499,8 @@ describe "TextEditor", ->
|
||||
atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o
|
||||
|
||||
runs ->
|
||||
atom.config.set('.source.js', 'editor.autoIndent', true)
|
||||
atom.config.set('.source.coffee', 'editor.autoIndent', false)
|
||||
atom.config.set('editor.autoIndent', true, scopeSelector: '.source.js')
|
||||
atom.config.set('editor.autoIndent', false, scopeSelector: '.source.coffee')
|
||||
|
||||
afterEach: ->
|
||||
atom.packages.deactivatePackages()
|
||||
@@ -3761,8 +3792,12 @@ describe "TextEditor", ->
|
||||
it "updates the grammar based on grammar overrides", ->
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
atom.grammars.setGrammarOverrideForPath(editor.getPath(), 'source.coffee')
|
||||
callback = jasmine.createSpy('callback')
|
||||
editor.onDidChangeGrammar(callback)
|
||||
editor.reloadGrammar()
|
||||
expect(editor.getGrammar().name).toBe 'CoffeeScript'
|
||||
expect(callback.callCount).toBe 1
|
||||
expect(callback.argsForCall[0][0]).toBe atom.grammars.grammarForScopeName('source.coffee')
|
||||
|
||||
describe "when the editor's grammar has an injection selector", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -96,8 +96,8 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-ui/
|
||||
expect($('style[priority=1]')).toHaveLength 2
|
||||
expect($('style[priority=1]:eq(0)').attr('source-path')).toMatch /atom-dark-ui/
|
||||
atom.config.set('core.themes', ['atom-light-ui', 'atom-dark-ui'])
|
||||
|
||||
waitsFor ->
|
||||
@@ -105,9 +105,9 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-ui/
|
||||
expect($('style[group=theme]:eq(1)').attr('source-path')).toMatch /atom-light-ui/
|
||||
expect($('style[priority=1]')).toHaveLength 2
|
||||
expect($('style[priority=1]:eq(0)').attr('source-path')).toMatch /atom-dark-ui/
|
||||
expect($('style[priority=1]:eq(1)').attr('source-path')).toMatch /atom-light-ui/
|
||||
atom.config.set('core.themes', [])
|
||||
|
||||
waitsFor ->
|
||||
@@ -115,7 +115,7 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[priority=1]')).toHaveLength 2
|
||||
# atom-dark-ui has an directory path, the syntax one doesn't
|
||||
atom.config.set('core.themes', ['theme-with-index-less', 'atom-dark-ui'])
|
||||
|
||||
@@ -123,15 +123,40 @@ describe "ThemeManager", ->
|
||||
reloadHandler.callCount == 1
|
||||
|
||||
runs ->
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[priority=1]')).toHaveLength 2
|
||||
importPaths = themeManager.getImportPaths()
|
||||
expect(importPaths.length).toBe 1
|
||||
expect(importPaths[0]).toContain 'atom-dark-ui'
|
||||
|
||||
it 'adds theme-* classes to the workspace for each active theme', ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
expect(workspaceElement).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when a theme fails to load", ->
|
||||
it "logs a warning", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(-> atom.packages.activatePackage('a-theme-that-will-not-be-found')).toThrow()
|
||||
atom.packages.activatePackage('a-theme-that-will-not-be-found')
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0]).toContain "Could not resolve 'a-theme-that-will-not-be-found'"
|
||||
|
||||
describe "::requireStylesheet(path)", ->
|
||||
beforeEach ->
|
||||
@@ -223,11 +248,9 @@ describe "ThemeManager", ->
|
||||
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
describe "base style sheet loading", ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
jasmine.snapshotDeprecations()
|
||||
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
workspaceElement.appendChild document.createElement('atom-text-editor')
|
||||
@@ -235,9 +258,6 @@ describe "ThemeManager", ->
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
beforeEach ->
|
||||
jasmine.restoreDeprecationsSnapshot()
|
||||
|
||||
it "loads the correct values from the theme's ui-variables file", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
@@ -269,22 +289,6 @@ describe "ThemeManager", ->
|
||||
# from within the theme itself
|
||||
expect($("atom-text-editor").css("background-color")).toBe "rgb(0, 152, 255)"
|
||||
|
||||
describe "theme classes on the workspace", ->
|
||||
it 'adds theme-* classes to the workspace for each active theme', ->
|
||||
expect(workspaceElement).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -59,6 +59,13 @@ describe "TooltipManager", ->
|
||||
tooltipElement = document.body.querySelector(".tooltip")
|
||||
expect(tooltipElement).toHaveText "⌃X ⌃Y"
|
||||
|
||||
it "does not display the keybinding if there is nothing mapped to the specified keyBindingCommand", ->
|
||||
manager.add element, title: 'A Title', keyBindingCommand: 'test-command', keyBindingTarget: element
|
||||
|
||||
hover element, ->
|
||||
tooltipElement = document.body.querySelector(".tooltip")
|
||||
expect(tooltipElement.textContent).toBe "A Title"
|
||||
|
||||
describe "when .dispose() is called on the returned disposable", ->
|
||||
it "no longer displays the tooltip on hover", ->
|
||||
disposable = manager.add element, title: "Title"
|
||||
|
||||
@@ -14,58 +14,38 @@ describe "ViewRegistry", ->
|
||||
expect(registry.getView(node)).toBe node
|
||||
|
||||
describe "when passed a SpacePen view", ->
|
||||
it "returns the root node of the view with a __spacePenView property pointing at the SpacePen view", ->
|
||||
it "returns the root node of the view with a .spacePenView property pointing at the SpacePen view", ->
|
||||
class TestView extends View
|
||||
@content: -> @div "Hello"
|
||||
|
||||
view = new TestView
|
||||
node = registry.getView(view)
|
||||
expect(node.textContent).toBe "Hello"
|
||||
expect(node.__spacePenView).toBe view
|
||||
expect(node.spacePenView).toBe view
|
||||
|
||||
describe "when passed a model object", ->
|
||||
describe "when a view provider is registered matching the object's constructor", ->
|
||||
describe "when the provider has a viewConstructor property", ->
|
||||
it "constructs a view element and assigns the model on it", ->
|
||||
class TestModel
|
||||
it "constructs a view element and assigns the model on it", ->
|
||||
class TestModel
|
||||
|
||||
class TestModelSubclass extends TestModel
|
||||
class TestModelSubclass extends TestModel
|
||||
|
||||
class TestView
|
||||
setModel: (@model) ->
|
||||
class TestView
|
||||
initialize: (@model) -> this
|
||||
|
||||
model = new TestModel
|
||||
model = new TestModel
|
||||
|
||||
registry.addViewProvider
|
||||
modelConstructor: TestModel
|
||||
viewConstructor: TestView
|
||||
registry.addViewProvider TestModel, (model) ->
|
||||
new TestView().initialize(model)
|
||||
|
||||
view = registry.getView(model)
|
||||
expect(view instanceof TestView).toBe true
|
||||
expect(view.model).toBe model
|
||||
view = registry.getView(model)
|
||||
expect(view instanceof TestView).toBe true
|
||||
expect(view.model).toBe model
|
||||
|
||||
subclassModel = new TestModelSubclass
|
||||
view2 = registry.getView(subclassModel)
|
||||
expect(view2 instanceof TestView).toBe true
|
||||
expect(view2.model).toBe subclassModel
|
||||
|
||||
describe "when the provider has a createView method", ->
|
||||
it "constructs a view element by calling the createView method with the model", ->
|
||||
class TestModel
|
||||
class TestView
|
||||
setModel: (@model) ->
|
||||
|
||||
registry.addViewProvider
|
||||
modelConstructor: TestModel
|
||||
createView: (model) ->
|
||||
view = new TestView
|
||||
view.setModel(model)
|
||||
view
|
||||
|
||||
model = new TestModel
|
||||
view = registry.getView(model)
|
||||
expect(view instanceof TestView).toBe true
|
||||
expect(view.model).toBe model
|
||||
subclassModel = new TestModelSubclass
|
||||
view2 = registry.getView(subclassModel)
|
||||
expect(view2 instanceof TestView).toBe true
|
||||
expect(view2.model).toBe subclassModel
|
||||
|
||||
describe "when no view provider is registered for the object's constructor", ->
|
||||
describe "when the object has a .getViewClass() method", ->
|
||||
@@ -82,7 +62,7 @@ describe "ViewRegistry", ->
|
||||
node = registry.getView(model)
|
||||
|
||||
expect(node.textContent).toBe "hello"
|
||||
view = node.__spacePenView
|
||||
view = node.spacePenView
|
||||
expect(view instanceof TestView).toBe true
|
||||
expect(view.model).toBe model
|
||||
|
||||
@@ -97,10 +77,10 @@ describe "ViewRegistry", ->
|
||||
it "returns a disposable that can be used to remove the provider", ->
|
||||
class TestModel
|
||||
class TestView
|
||||
setModel: (@model) ->
|
||||
disposable = registry.addViewProvider
|
||||
modelConstructor: TestModel
|
||||
viewConstructor: TestView
|
||||
initialize: (@model) -> this
|
||||
|
||||
disposable = registry.addViewProvider TestModel, (model) ->
|
||||
new TestView().initialize(model)
|
||||
|
||||
expect(registry.getView(new TestModel) instanceof TestView).toBe true
|
||||
disposable.dispose()
|
||||
|
||||
@@ -128,17 +128,15 @@ describe "Window", ->
|
||||
setData: (key, value) -> @data[key] = value
|
||||
getData: (key) -> @data[key]
|
||||
|
||||
event = $.Event(type)
|
||||
event.originalEvent = { dataTransfer }
|
||||
event.preventDefault = ->
|
||||
event.stopPropagation = ->
|
||||
event = new CustomEvent("drop")
|
||||
event.dataTransfer = dataTransfer
|
||||
event
|
||||
|
||||
describe "when a file is dragged to window", ->
|
||||
it "opens it", ->
|
||||
spyOn(atom, "open")
|
||||
event = buildDragEvent("drop", [ {path: "/fake1"}, {path: "/fake2"} ])
|
||||
$(document).trigger(event)
|
||||
document.dispatchEvent(event)
|
||||
expect(atom.open.callCount).toBe 1
|
||||
expect(atom.open.argsForCall[0][0]).toEqual pathsToOpen: ['/fake1', '/fake2']
|
||||
|
||||
@@ -146,7 +144,7 @@ describe "Window", ->
|
||||
it "does nothing", ->
|
||||
spyOn(atom, "open")
|
||||
event = buildDragEvent("drop", [])
|
||||
$(document).trigger(event)
|
||||
document.dispatchEvent(event)
|
||||
expect(atom.open).not.toHaveBeenCalled()
|
||||
|
||||
describe "when a link is clicked", ->
|
||||
|
||||
+307
-11
@@ -2,6 +2,10 @@ path = require 'path'
|
||||
temp = require 'temp'
|
||||
Workspace = require '../src/workspace'
|
||||
{View} = require '../src/space-pen-extensions'
|
||||
platform = require './spec-helper-platform'
|
||||
_ = require 'underscore-plus'
|
||||
fstream = require 'fstream'
|
||||
fs = require 'fs-plus'
|
||||
|
||||
describe "Workspace", ->
|
||||
workspace = null
|
||||
@@ -356,7 +360,7 @@ describe "Workspace", ->
|
||||
atom.workspace.open('sample.coffee')
|
||||
|
||||
runs ->
|
||||
atom.workspace.getActiveEditor().setText """
|
||||
atom.workspace.getActiveTextEditor().setText """
|
||||
i = /test/; #FIXME
|
||||
"""
|
||||
|
||||
@@ -462,14 +466,12 @@ describe "Workspace", ->
|
||||
|
||||
class TestItemElement extends HTMLElement
|
||||
constructor: ->
|
||||
setModel: (@model) ->
|
||||
initialize: (@model) -> this
|
||||
getModel: -> @model
|
||||
|
||||
beforeEach ->
|
||||
atom.views.addViewProvider(
|
||||
modelConstructor: TestItem
|
||||
viewConstructor: TestItemElement
|
||||
)
|
||||
atom.views.addViewProvider TestItem, (model) ->
|
||||
new TestItemElement().initialize(model)
|
||||
|
||||
describe '::addLeftPanel(model)', ->
|
||||
it 'adds a panel to the correct panel container', ->
|
||||
@@ -482,7 +484,7 @@ describe "Workspace", ->
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
itemView = atom.workspace.getLeftPanels()[0].getItemView()
|
||||
itemView = atom.views.getView(atom.workspace.getLeftPanels()[0].getItem())
|
||||
expect(itemView instanceof TestItemElement).toBe(true)
|
||||
expect(itemView.getModel()).toBe(model)
|
||||
|
||||
@@ -497,7 +499,7 @@ describe "Workspace", ->
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
itemView = atom.workspace.getRightPanels()[0].getItemView()
|
||||
itemView = atom.views.getView(atom.workspace.getRightPanels()[0].getItem())
|
||||
expect(itemView instanceof TestItemElement).toBe(true)
|
||||
expect(itemView.getModel()).toBe(model)
|
||||
|
||||
@@ -512,7 +514,7 @@ describe "Workspace", ->
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
itemView = atom.workspace.getTopPanels()[0].getItemView()
|
||||
itemView = atom.views.getView(atom.workspace.getTopPanels()[0].getItem())
|
||||
expect(itemView instanceof TestItemElement).toBe(true)
|
||||
expect(itemView.getModel()).toBe(model)
|
||||
|
||||
@@ -527,7 +529,7 @@ describe "Workspace", ->
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
itemView = atom.workspace.getBottomPanels()[0].getItemView()
|
||||
itemView = atom.views.getView(atom.workspace.getBottomPanels()[0].getItem())
|
||||
expect(itemView instanceof TestItemElement).toBe(true)
|
||||
expect(itemView.getModel()).toBe(model)
|
||||
|
||||
@@ -542,6 +544,300 @@ describe "Workspace", ->
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
itemView = atom.workspace.getModalPanels()[0].getItemView()
|
||||
itemView = atom.views.getView(atom.workspace.getModalPanels()[0].getItem())
|
||||
expect(itemView instanceof TestItemElement).toBe(true)
|
||||
expect(itemView.getModel()).toBe(model)
|
||||
|
||||
describe "::panelForItem(item)", ->
|
||||
it "returns the panel associated with the item", ->
|
||||
item = new TestItem
|
||||
panel = atom.workspace.addLeftPanel(item: item)
|
||||
|
||||
itemWithNoPanel = new TestItem
|
||||
|
||||
expect(atom.workspace.panelForItem(item)).toBe panel
|
||||
expect(atom.workspace.panelForItem(itemWithNoPanel)).toBe null
|
||||
|
||||
describe "::scan(regex, options, callback)", ->
|
||||
describe "when called with a regex", ->
|
||||
it "calls the callback with all regex results in all files in the project", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /(a)+/, (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results[0].filePath).toBe atom.project.resolve('a')
|
||||
expect(results[0].matches).toHaveLength(3)
|
||||
expect(results[0].matches[0]).toEqual
|
||||
matchText: 'aaa'
|
||||
lineText: 'aaa bbb'
|
||||
lineTextOffset: 0
|
||||
range: [[0, 0], [0, 3]]
|
||||
|
||||
it "works with with escaped literals (like $ and ^)", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /\$\w+/, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results.length).toBe 1
|
||||
|
||||
{filePath, matches} = results[0]
|
||||
expect(filePath).toBe atom.project.resolve('a')
|
||||
expect(matches).toHaveLength 1
|
||||
expect(matches[0]).toEqual
|
||||
matchText: '$bill'
|
||||
lineText: 'dollar$bill'
|
||||
lineTextOffset: 0
|
||||
range: [[2, 6], [2, 11]]
|
||||
|
||||
it "works on evil filenames", ->
|
||||
platform.generateEvilFiles()
|
||||
atom.project.setPaths([path.join(__dirname, 'fixtures', 'evil-files')])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /evil/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
_.each(matches, (m) -> expect(m.matchText).toEqual 'evil')
|
||||
|
||||
if platform.isWindows()
|
||||
expect(paths.length).toBe 3
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(path.basename(paths[2])).toBe "utfa\u0306.md"
|
||||
else
|
||||
expect(paths.length).toBe 5
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(paths[2]).toMatch /goddam\nnewlines$/m
|
||||
expect(paths[3]).toMatch /quote".txt$/m
|
||||
expect(path.basename(paths[4])).toBe "utfa\u0306.md"
|
||||
|
||||
it "ignores case if the regex includes the `i` flag", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /DOLLAR/i, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
|
||||
describe "when the core.excludeVcsIgnoredPaths config is truthy", ->
|
||||
[projectPath, ignoredPath] = []
|
||||
|
||||
beforeEach ->
|
||||
sourceProjectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
projectPath = path.join(temp.mkdirSync("atom"))
|
||||
|
||||
writerStream = fstream.Writer(projectPath)
|
||||
fstream.Reader(sourceProjectPath).pipe(writerStream)
|
||||
|
||||
waitsFor (done) ->
|
||||
writerStream.on 'close', done
|
||||
writerStream.on 'error', done
|
||||
|
||||
runs ->
|
||||
fs.rename(path.join(projectPath, 'git.git'), path.join(projectPath, '.git'))
|
||||
ignoredPath = path.join(projectPath, 'ignored.txt')
|
||||
fs.writeFileSync(ignoredPath, 'this match should not be included')
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(projectPath) if fs.existsSync(projectPath)
|
||||
|
||||
it "excludes ignored files", ->
|
||||
atom.project.setPaths([projectPath])
|
||||
atom.config.set('core.excludeVcsIgnoredPaths', true)
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /match/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "includes only files when a directory filter is specified", ->
|
||||
projectPath = path.join(path.join(__dirname, 'fixtures', 'dir'))
|
||||
atom.project.setPaths([projectPath])
|
||||
|
||||
filePath = path.join(projectPath, 'a-dir', 'oh-git')
|
||||
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /aaa/, paths: ["a-dir#{path.sep}"], (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "includes files and folders that begin with a '.'", ->
|
||||
projectPath = temp.mkdirSync()
|
||||
filePath = path.join(projectPath, '.text')
|
||||
fs.writeFileSync(filePath, 'match this')
|
||||
atom.project.setPaths([projectPath])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /match this/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "excludes values in core.ignoredNames", ->
|
||||
projectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
ignoredNames = atom.config.get("core.ignoredNames")
|
||||
ignoredNames.push("a")
|
||||
atom.config.set("core.ignoredNames", ignoredNames)
|
||||
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /dollar/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('a').then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /a|Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 3
|
||||
resultForA = _.find results, ({filePath}) -> path.basename(filePath) == 'a'
|
||||
expect(resultForA.matches).toHaveLength 1
|
||||
expect(resultForA.matches[0].matchText).toBe 'Elephant'
|
||||
|
||||
it "ignores buffers outside the project", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(temp.openSync().path).then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 0
|
||||
|
||||
describe "::replace(regex, replacementText, paths, iterator)", ->
|
||||
[filePath, commentFilePath, sampleContent, sampleCommentContent] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.project.setPaths([atom.project.resolve('../')])
|
||||
|
||||
filePath = atom.project.resolve('sample.js')
|
||||
commentFilePath = atom.project.resolve('sample-with-comments.js')
|
||||
sampleContent = fs.readFileSync(filePath).toString()
|
||||
sampleCommentContent = fs.readFileSync(commentFilePath).toString()
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, sampleContent)
|
||||
fs.writeFileSync(commentFilePath, sampleCommentContent)
|
||||
|
||||
describe "when a file doesn't exist", ->
|
||||
it "calls back with an error", ->
|
||||
errors = []
|
||||
missingPath = path.resolve('/not-a-file.js')
|
||||
expect(fs.existsSync(missingPath)).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [missingPath], (result, error) ->
|
||||
errors.push(error)
|
||||
|
||||
runs ->
|
||||
expect(errors).toHaveLength 1
|
||||
expect(errors[0].path).toBe missingPath
|
||||
|
||||
describe "when called with unopened files", ->
|
||||
it "replaces properly", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
describe "when a buffer is already open", ->
|
||||
it "replaces properly and saves when not modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
it "does not replace when the path is not specified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample-with-comments.js').then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [commentFilePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe commentFilePath
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'okthen', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
@@ -3,6 +3,7 @@ Q = require 'q'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
TextEditorView = require '../src/text-editor-view'
|
||||
Pane = require '../src/pane'
|
||||
PaneView = require '../src/pane-view'
|
||||
Workspace = require '../src/workspace'
|
||||
|
||||
@@ -294,3 +295,39 @@ describe "WorkspaceView", ->
|
||||
|
||||
modalContainer = workspaceElement.querySelector('atom-panel-container.modal')
|
||||
expect(modalContainer.parentNode).toBe workspaceElement
|
||||
|
||||
describe "::saveActivePaneItem()", ->
|
||||
describe "when there is an error", ->
|
||||
it "emits a warning notification when the file cannot be saved", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("'/some/file' is a directory")
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
atom.workspace.saveActivePaneItem()
|
||||
expect(addedSpy).toHaveBeenCalled()
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the directory cannot be written to", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("ENOTDIR, not a directory '/Some/dir/and-a-file.js'")
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
atom.workspace.saveActivePaneItem()
|
||||
expect(addedSpy).toHaveBeenCalled()
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the user does not have permission", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("EACCES, permission denied '/Some/dir/and-a-file.js'")
|
||||
|
||||
atom.notifications.onDidAddNotification addedSpy = jasmine.createSpy()
|
||||
atom.workspace.saveActivePaneItem()
|
||||
expect(addedSpy).toHaveBeenCalled()
|
||||
expect(addedSpy.mostRecentCall.args[0].getType()).toBe 'warning'
|
||||
|
||||
it "emits a warning notification when the file cannot be saved", ->
|
||||
spyOn(Pane::, 'saveActiveItem').andCallFake ->
|
||||
throw new Error("no one knows")
|
||||
|
||||
save = -> atom.workspace.saveActivePaneItem()
|
||||
expect(save).toThrow()
|
||||
|
||||
+18
-2
@@ -5,13 +5,13 @@ path = require 'path'
|
||||
remote = require 'remote'
|
||||
screen = require 'screen'
|
||||
shell = require 'shell'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{deprecate} = require 'grim'
|
||||
{Emitter} = require 'event-kit'
|
||||
{Model} = require 'theorist'
|
||||
fs = require 'fs-plus'
|
||||
{convertStackTrace, convertLine} = require 'coffeestack'
|
||||
|
||||
{$} = require './space-pen-extensions'
|
||||
WindowEventHandler = require './window-event-handler'
|
||||
@@ -134,6 +134,9 @@ class Atom extends Model
|
||||
# Public: A {Clipboard} instance
|
||||
clipboard: null
|
||||
|
||||
# A {ServiceHub} instance
|
||||
services: null
|
||||
|
||||
# Public: A {ContextMenuManager} instance
|
||||
contextMenu: null
|
||||
|
||||
@@ -196,9 +199,16 @@ class Atom extends Model
|
||||
unless @inDevMode() or @inSpecMode()
|
||||
require('grim').deprecate = ->
|
||||
|
||||
sourceMapCache = {}
|
||||
|
||||
window.onerror = =>
|
||||
@lastUncaughtError = Array::slice.call(arguments)
|
||||
[message, url, line, column, originalError] = @lastUncaughtError
|
||||
|
||||
convertedLine = convertLine(url, line, column, sourceMapCache)
|
||||
{line, column} = convertedLine if convertedLine?
|
||||
originalError.stack = convertStackTrace(originalError.stack, sourceMapCache) if originalError
|
||||
|
||||
eventObject = {message, url, line, column, originalError}
|
||||
|
||||
openDevTools = true
|
||||
@@ -226,6 +236,7 @@ class Atom extends Model
|
||||
NotificationManager = require './notification-manager'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
ServiceHub = require './service-hub'
|
||||
GrammarRegistry = require './grammar-registry'
|
||||
ThemeManager = require './theme-manager'
|
||||
StyleManager = require './style-manager'
|
||||
@@ -261,6 +272,7 @@ class Atom extends Model
|
||||
@contextMenu = new ContextMenuManager({resourcePath, devMode})
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@clipboard = new Clipboard()
|
||||
@services = new ServiceHub
|
||||
|
||||
@grammars = @deserializers.deserialize(@state.grammars ? @state.syntax) ? new GrammarRegistry()
|
||||
|
||||
@@ -329,6 +341,10 @@ class Atom extends Model
|
||||
inDevMode: ->
|
||||
@getLoadSettings().devMode
|
||||
|
||||
# Public: Is the current window in safe mode?
|
||||
inSafeMode: ->
|
||||
@getLoadSettings().safeMode
|
||||
|
||||
# Public: Is the current window running specs?
|
||||
inSpecMode: ->
|
||||
@getLoadSettings().isSpec
|
||||
@@ -604,7 +620,7 @@ class Atom extends Model
|
||||
# Essential: Visually and audibly trigger a beep.
|
||||
beep: ->
|
||||
shell.beep() if @config.get('core.audioBeep')
|
||||
@__workspaceView.trigger 'beep'
|
||||
@__workspaceView?.trigger 'beep'
|
||||
@emitter.emit 'did-beep'
|
||||
|
||||
# Essential: A flexible way to open a dialog akin to an alert dialog.
|
||||
|
||||
@@ -140,14 +140,18 @@ class AtomApplication
|
||||
|
||||
# Registers basic application commands, non-idempotent.
|
||||
handleEvents: ->
|
||||
getLoadSettings = =>
|
||||
devMode: @focusedWindow()?.devMode
|
||||
safeMode: @focusedWindow()?.safeMode
|
||||
|
||||
@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())
|
||||
@on 'application:new-window', -> @openPath(_.extend(windowDimensions: @focusedWindow()?.getDimensions(), getLoadSettings()))
|
||||
@on 'application:new-file', -> (@focusedWindow() ? this).openPath()
|
||||
@on 'application:open', -> @promptForPath(type: 'all')
|
||||
@on 'application:open-file', -> @promptForPath(type: 'file')
|
||||
@on 'application:open-folder', -> @promptForPath(type: 'folder')
|
||||
@on 'application:open', -> @promptForPath(_.extend(type: 'all', getLoadSettings()))
|
||||
@on 'application:open-file', -> @promptForPath(_.extend(type: 'file', getLoadSettings()))
|
||||
@on 'application:open-folder', -> @promptForPath(_.extend(type: 'folder', getLoadSettings()))
|
||||
@on 'application:open-dev', -> @promptForPath(devMode: true)
|
||||
@on 'application:open-safe', -> @promptForPath(safeMode: true)
|
||||
@on 'application:inspect', ({x,y, atomWindow}) ->
|
||||
@@ -355,7 +359,7 @@ class AtomApplication
|
||||
|
||||
if existingWindow?
|
||||
openedWindow = existingWindow
|
||||
openedWindow.openPath(pathToOpen, initialLine)
|
||||
openedWindow.openPath(pathToOpen, initialLine, initialColumn)
|
||||
if openedWindow.isMinimized()
|
||||
openedWindow.restore()
|
||||
else
|
||||
|
||||
@@ -18,7 +18,7 @@ class AtomWindow
|
||||
isSpec: null
|
||||
|
||||
constructor: (settings={}) ->
|
||||
{@resourcePath, pathToOpen, initialLine, initialColumn, @isSpec, @exitWhenDone, @safeMode} = settings
|
||||
{@resourcePath, pathToOpen, initialLine, initialColumn, @isSpec, @exitWhenDone, @safeMode, @devMode} = settings
|
||||
|
||||
# Normalize to make sure drive letter case is consistent on Windows
|
||||
@resourcePath = path.normalize(@resourcePath) if @resourcePath
|
||||
@@ -38,6 +38,8 @@ class AtomWindow
|
||||
loadSettings.windowState ?= '{}'
|
||||
loadSettings.appVersion = app.getVersion()
|
||||
loadSettings.resourcePath = @resourcePath
|
||||
loadSettings.devMode ?= false
|
||||
loadSettings.safeMode ?= false
|
||||
|
||||
# Only send to the first non-spec window created
|
||||
if @constructor.includeShellLoadTime and not @isSpec
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
autoUpdater = null
|
||||
_ = require 'underscore-plus'
|
||||
{EventEmitter} = require 'events'
|
||||
path = require 'path'
|
||||
|
||||
IdleState = 'idle'
|
||||
CheckingState = 'checking'
|
||||
DownladingState = 'downloading'
|
||||
UpdateAvailableState = 'update-available'
|
||||
NoUpdateAvailableState = 'no-update-available'
|
||||
UnsupportedState = 'unsupported'
|
||||
ErrorState = 'error'
|
||||
|
||||
module.exports =
|
||||
@@ -50,8 +52,13 @@ class AutoUpdateManager
|
||||
@emitUpdateAvailableEvent(@getWindows()...)
|
||||
|
||||
# Only released versions should check for updates.
|
||||
unless /\w{7}/.test(@version)
|
||||
@check(hidePopups: true)
|
||||
@check(hidePopups: true) unless /\w{7}/.test(@version)
|
||||
|
||||
switch process.platform
|
||||
when 'win32'
|
||||
@setState(UnsupportedState) unless autoUpdater.supportsUpdates()
|
||||
when 'linux'
|
||||
@setState(UnsupportedState)
|
||||
|
||||
emitUpdateAvailableEvent: (windows...) ->
|
||||
return unless @releaseVersion? and @releaseNotes
|
||||
@@ -79,12 +86,24 @@ class AutoUpdateManager
|
||||
onUpdateNotAvailable: =>
|
||||
autoUpdater.removeListener 'error', @onUpdateError
|
||||
dialog = require 'dialog'
|
||||
dialog.showMessageBox type: 'info', buttons: ['OK'], message: 'No update available.', detail: "Version #{@version} is the latest version."
|
||||
dialog.showMessageBox
|
||||
type: 'info'
|
||||
buttons: ['OK']
|
||||
icon: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
message: 'No update available.'
|
||||
title: 'No Update Available'
|
||||
detail: "Version #{@version} is the latest version."
|
||||
|
||||
onUpdateError: (event, message) =>
|
||||
autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable
|
||||
dialog = require 'dialog'
|
||||
dialog.showMessageBox type: 'warning', buttons: ['OK'], message: 'There was an error checking for updates.', detail: message
|
||||
dialog.showMessageBox
|
||||
type: 'warning'
|
||||
buttons: ['OK']
|
||||
icon: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
message: 'There was an error checking for updates.'
|
||||
title: 'Update Error'
|
||||
detail: message
|
||||
|
||||
getWindows: ->
|
||||
global.atomApplication.windows
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{EventEmitter} = require 'events'
|
||||
_ = require 'underscore-plus'
|
||||
shellAutoUpdater = require 'auto-updater'
|
||||
SquirrelUpdate = require './squirrel-update'
|
||||
|
||||
class AutoUpdater
|
||||
@@ -9,15 +8,10 @@ class AutoUpdater
|
||||
setFeedUrl: (@updateUrl) ->
|
||||
|
||||
quitAndInstall: ->
|
||||
unless SquirrelUpdate.existsSync()
|
||||
shellAutoUpdater.quitAndInstall()
|
||||
return
|
||||
|
||||
@installUpdate (error) ->
|
||||
return if error?
|
||||
|
||||
SquirrelUpdate.spawn ['--processStart', 'atom.exe'], ->
|
||||
shellAutoUpdater.quitAndInstall()
|
||||
if SquirrelUpdate.existsSync()
|
||||
SquirrelUpdate.restartAtom(require('app'))
|
||||
else
|
||||
require('auto-updater').quitAndInstall()
|
||||
|
||||
downloadUpdate: (callback) ->
|
||||
SquirrelUpdate.spawn ['--download', @updateUrl], (error, stdout) ->
|
||||
@@ -36,6 +30,9 @@ class AutoUpdater
|
||||
installUpdate: (callback) ->
|
||||
SquirrelUpdate.spawn(['--update', @updateUrl], callback)
|
||||
|
||||
supportsUpdates: ->
|
||||
SquirrelUpdate.existsSync()
|
||||
|
||||
checkForUpdates: ->
|
||||
throw new Error('Update URL is not set') unless @updateUrl
|
||||
|
||||
@@ -47,7 +44,6 @@ class AutoUpdater
|
||||
|
||||
@downloadUpdate (error, update) =>
|
||||
if error?
|
||||
console.log "Failed to download: #{error.message} - #{error.code} - #{error.stdout}"
|
||||
@emit 'update-not-available'
|
||||
return
|
||||
|
||||
@@ -57,12 +53,9 @@ class AutoUpdater
|
||||
|
||||
@installUpdate (error) =>
|
||||
if error?
|
||||
console.log "Failed to update: #{error.message} - #{error.code} - #{error.stdout}"
|
||||
@emit 'update-not-available'
|
||||
return
|
||||
|
||||
console.log "Updated to #{update.version}"
|
||||
|
||||
@emit 'update-available'
|
||||
@emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), 'https://atom.io', => @quitAndInstall()
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ fs.lstatSyncNoException = (pathToStat) ->
|
||||
start = ->
|
||||
if process.platform is 'win32'
|
||||
SquirrelUpdate = require './squirrel-update'
|
||||
return if SquirrelUpdate.handleStartupEvent()
|
||||
squirrelCommand = process.argv[1]
|
||||
return if SquirrelUpdate.handleStartupEvent(app, squirrelCommand)
|
||||
|
||||
args = parseCommandLine()
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
app = require 'app'
|
||||
ChildProcess = require 'child_process'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
|
||||
rootAtomFolder = path.resolve(process.execPath, '..', '..')
|
||||
appFolder = path.resolve(process.execPath, '..')
|
||||
rootAtomFolder = path.resolve(appFolder, '..')
|
||||
binFolder = path.join(rootAtomFolder, 'bin')
|
||||
updateDotExe = path.join(rootAtomFolder, 'Update.exe')
|
||||
exeName = path.basename(process.execPath)
|
||||
@@ -25,9 +25,15 @@ environmentKeyPath = 'HKCU\\Environment'
|
||||
# Spawn a command and invoke the callback when it completes with an error
|
||||
# and the output from standard out.
|
||||
spawn = (command, args, callback) ->
|
||||
spawnedProcess = ChildProcess.spawn(command, args)
|
||||
|
||||
stdout = ''
|
||||
|
||||
try
|
||||
spawnedProcess = ChildProcess.spawn(command, args)
|
||||
catch error
|
||||
# Spawn can throw an error
|
||||
process.nextTick -> callback?(error, stdout)
|
||||
return
|
||||
|
||||
spawnedProcess.stdout.on 'data', (data) -> stdout += data
|
||||
|
||||
error = null
|
||||
@@ -36,7 +42,7 @@ spawn = (command, args, callback) ->
|
||||
error ?= new Error("Command failed: #{signal ? code}") if code isnt 0
|
||||
error?.code ?= code
|
||||
error?.stdout ?= stdout
|
||||
callback(error, stdout)
|
||||
callback?(error, stdout)
|
||||
|
||||
# Spawn reg.exe and callback when it completes
|
||||
spawnReg = (args, callback) ->
|
||||
@@ -111,22 +117,26 @@ uninstallContextMenu = (callback) ->
|
||||
addCommandsToPath = (callback) ->
|
||||
installCommands = (callback) ->
|
||||
atomCommandPath = path.join(binFolder, 'atom.cmd')
|
||||
relativeExePath = path.relative(binFolder, process.execPath)
|
||||
atomCommand = """
|
||||
@echo off
|
||||
"%~dp0\\#{relativeExePath}" %*
|
||||
"""
|
||||
relativeAtomPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.cmd'))
|
||||
atomCommand = "@echo off\r\n\"%~dp0\\#{relativeAtomPath}\" %*"
|
||||
|
||||
atomShCommandPath = path.join(binFolder, 'atom')
|
||||
relativeAtomShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.sh'))
|
||||
atomShCommand = "#!/bin/sh\r\n\"$0/../#{relativeAtomShPath.replace(/\\/g, '/')}\" \"$@\""
|
||||
|
||||
apmCommandPath = path.join(binFolder, 'apm.cmd')
|
||||
relativeApmPath = path.relative(binFolder, path.join(process.resourcesPath, 'app', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm.cmd'))
|
||||
apmCommand = """
|
||||
@echo off
|
||||
"%~dp0\\#{relativeApmPath}" %*
|
||||
"""
|
||||
apmCommand = "@echo off\r\n\"%~dp0\\#{relativeApmPath}\" %*"
|
||||
|
||||
apmShCommandPath = path.join(binFolder, 'apm')
|
||||
relativeApmShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'apm.sh'))
|
||||
apmShCommand = "#!/bin/sh\r\n\"$0/../#{relativeApmShPath.replace(/\\/g, '/')}\" \"$@\""
|
||||
|
||||
fs.writeFile atomCommandPath, atomCommand, ->
|
||||
fs.writeFile apmCommandPath, apmCommand, ->
|
||||
callback()
|
||||
fs.writeFile atomShCommandPath, atomShCommand, ->
|
||||
fs.writeFile apmCommandPath, apmCommand, ->
|
||||
fs.writeFile apmShCommandPath, apmShCommand, ->
|
||||
callback()
|
||||
|
||||
addBinToPath = (pathSegments, callback) ->
|
||||
pathSegments.push(binFolder)
|
||||
@@ -159,15 +169,31 @@ removeCommandsFromPath = (callback) ->
|
||||
else
|
||||
callback()
|
||||
|
||||
|
||||
# Create a desktop and start menu shortcut by using the command line API
|
||||
# provided by Squirrel's Update.exe
|
||||
createShortcut = (callback) ->
|
||||
createShortcuts = (callback) ->
|
||||
spawnUpdate(['--createShortcut', exeName], callback)
|
||||
|
||||
# Update the desktop and start menu shortcuts by using the command line API
|
||||
# provided by Squirrel's Update.exe
|
||||
updateShortcuts = (callback) ->
|
||||
if homeDirectory = fs.getHomeDirectory()
|
||||
desktopShortcutPath = path.join(homeDirectory, 'Desktop', 'Atom.lnk')
|
||||
# Check if the desktop shortcut has been previously deleted and
|
||||
# and keep it deleted if it was
|
||||
fs.exists desktopShortcutPath, (desktopShortcutExists) ->
|
||||
createShortcuts ->
|
||||
if desktopShortcutExists
|
||||
callback()
|
||||
else
|
||||
# Remove the unwanted desktop shortcut that was recreated
|
||||
fs.unlink(desktopShortcutPath, callback)
|
||||
else
|
||||
createShortcuts(callback)
|
||||
|
||||
# Remove the desktop and start menu shortcuts by using the command line API
|
||||
# provided by Squirrel's Update.exe
|
||||
removeShortcut = (callback) ->
|
||||
removeShortcuts = (callback) ->
|
||||
spawnUpdate(['--removeShortcut', exeName], callback)
|
||||
|
||||
exports.spawn = spawnUpdate
|
||||
@@ -176,17 +202,30 @@ exports.spawn = spawnUpdate
|
||||
exports.existsSync = ->
|
||||
fs.existsSync(updateDotExe)
|
||||
|
||||
# Restart Atom using the version pointed to by the atom.cmd shim
|
||||
exports.restartAtom = (app) ->
|
||||
if projectPath = global.atomApplication?.lastFocusedWindow?.projectPath
|
||||
args = [projectPath]
|
||||
app.once 'will-quit', -> spawn(path.join(binFolder, 'atom.cmd'), args)
|
||||
app.quit()
|
||||
|
||||
# Handle squirrel events denoted by --squirrel-* command line arguments.
|
||||
exports.handleStartupEvent = ->
|
||||
switch process.argv[1]
|
||||
when '--squirrel-install', '--squirrel-updated'
|
||||
createShortcut ->
|
||||
exports.handleStartupEvent = (app, squirrelCommand) ->
|
||||
switch squirrelCommand
|
||||
when '--squirrel-install'
|
||||
createShortcuts ->
|
||||
installContextMenu ->
|
||||
addCommandsToPath ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-updated'
|
||||
updateShortcuts ->
|
||||
installContextMenu ->
|
||||
addCommandsToPath ->
|
||||
app.quit()
|
||||
true
|
||||
when '--squirrel-uninstall'
|
||||
removeShortcut ->
|
||||
removeShortcuts ->
|
||||
uninstallContextMenu ->
|
||||
removeCommandsFromPath ->
|
||||
app.quit()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
_ = require 'underscore-plus'
|
||||
ChildProcess = require 'child_process'
|
||||
{Emitter} = require 'event-kit'
|
||||
path = require 'path'
|
||||
|
||||
# Extended: A wrapper which provides standard error/output line buffering for
|
||||
# Node's ChildProcess.
|
||||
@@ -17,6 +19,10 @@ ChildProcess = require 'child_process'
|
||||
# ```
|
||||
module.exports =
|
||||
class BufferedProcess
|
||||
###
|
||||
Section: Construction
|
||||
###
|
||||
|
||||
# Public: Runs the given command by spawning a new child process.
|
||||
#
|
||||
# * `options` An {Object} with the following keys:
|
||||
@@ -39,14 +45,15 @@ class BufferedProcess
|
||||
# * `exit` The callback {Function} which receives a single argument
|
||||
# containing the exit status (optional).
|
||||
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
|
||||
@emitter = new Emitter
|
||||
options ?= {}
|
||||
# Related to joyent/node#2318
|
||||
if process.platform is "win32"
|
||||
if process.platform is 'win32'
|
||||
# Quote all arguments and escapes inner quotes
|
||||
if args?
|
||||
cmdArgs = args.filter (arg) -> arg?
|
||||
cmdArgs = cmdArgs.map (arg) ->
|
||||
if command in ['explorer.exe', 'explorer'] and /^\/[a-zA-Z]+,.*$/.test(arg)
|
||||
cmdArgs = cmdArgs.map (arg) =>
|
||||
if @isExplorerCommand(command) 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
|
||||
@@ -61,7 +68,7 @@ class BufferedProcess
|
||||
cmdArgs = ['/s', '/c', "\"#{cmdArgs.join(' ')}\""]
|
||||
cmdOptions = _.clone(options)
|
||||
cmdOptions.windowsVerbatimArguments = true
|
||||
@process = ChildProcess.spawn(process.env.comspec or 'cmd.exe', cmdArgs, cmdOptions)
|
||||
@process = ChildProcess.spawn(@getCmdPath(), cmdArgs, cmdOptions)
|
||||
else
|
||||
@process = ChildProcess.spawn(command, args, options)
|
||||
@killed = false
|
||||
@@ -94,6 +101,41 @@ class BufferedProcess
|
||||
processExited = true
|
||||
triggerExitCallback()
|
||||
|
||||
@process.on 'error', (error) =>
|
||||
handled = false
|
||||
handle = -> handled = true
|
||||
|
||||
@emitter.emit 'will-throw-error', {error, handle}
|
||||
|
||||
if error.code is 'ENOENT' and error.syscall.indexOf('spawn') is 0
|
||||
error = new Error("Failed to spawn command `#{command}`. Make sure `#{command}` is installed and on your PATH", error.path)
|
||||
error.name = 'BufferedProcessError'
|
||||
|
||||
throw error unless handled
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
# Public: Will call your callback when an error will be raised by the process.
|
||||
# Usually this is due to the command not being available or not on the PATH.
|
||||
# You can call `handle()` on the object passed to your callback to indicate
|
||||
# that you have handled this error.
|
||||
#
|
||||
# * `callback` {Function} callback
|
||||
# * `errorObject` {Object}
|
||||
# * `error` {Object} the error object
|
||||
# * `handle` {Function} call this to indicate you have handled the error.
|
||||
# The error will not be thrown if this function is called.
|
||||
#
|
||||
# Returns a {Disposable}
|
||||
onWillThrowError: (callback) ->
|
||||
@emitter.on 'will-throw-error', callback
|
||||
|
||||
###
|
||||
Section: Helper Methods
|
||||
###
|
||||
|
||||
# Helper method to pass data line by line.
|
||||
#
|
||||
# * `stream` The Stream to read from.
|
||||
@@ -150,6 +192,22 @@ class BufferedProcess
|
||||
@process?.kill()
|
||||
@process = null
|
||||
|
||||
isExplorerCommand: (command) ->
|
||||
if command is 'explorer.exe' or command is 'explorer'
|
||||
true
|
||||
else if process.env.SystemRoot
|
||||
command is path.join(process.env.SystemRoot, 'explorer.exe') or command is path.join(process.env.SystemRoot, 'explorer')
|
||||
else
|
||||
false
|
||||
|
||||
getCmdPath: ->
|
||||
if process.env.comspec
|
||||
process.env.comspec
|
||||
else if process.env.SystemRoot
|
||||
path.join(process.env.SystemRoot, 'System32', 'cmd.exe')
|
||||
else
|
||||
'cmd.exe'
|
||||
|
||||
# Public: Terminate the process.
|
||||
kill: ->
|
||||
return if @killed
|
||||
|
||||
@@ -54,9 +54,10 @@ class CommandRegistry
|
||||
#
|
||||
# ## Arguments: Registering One Command
|
||||
#
|
||||
# * `selector` A {String} containing a CSS selector matching elements on which
|
||||
# you want to handle the commands. The `,` combinator is not currently
|
||||
# supported.
|
||||
# * `target` A {String} containing a CSS selector or a DOM element. If you
|
||||
# pass a selector, the command will be globally associated with all matching
|
||||
# elements. The `,` combinator is not currently supported. If you pass a
|
||||
# DOM element, the command will be associated with just that element.
|
||||
# * `commandName` A {String} containing the name of a command you want to
|
||||
# handle such as `user:insert-date`.
|
||||
# * `callback` A {Function} to call when the given command is invoked on an
|
||||
@@ -67,9 +68,11 @@ class CommandRegistry
|
||||
#
|
||||
# ## Arguments: Registering Multiple Commands
|
||||
#
|
||||
# * `selector` A {String} containing a CSS selector matching elements on which
|
||||
# you want to handle the commands. The `,` combinator is not currently
|
||||
# supported.
|
||||
# * `target` A {String} containing a CSS selector or a DOM element. If you
|
||||
# pass a selector, the commands will be globally associated with all
|
||||
# matching elements. The `,` combinator is not currently supported.
|
||||
# If you pass a DOM element, the command will be associated with just that
|
||||
# element.
|
||||
# * `commands` An {Object} mapping command names like `user:insert-date` to
|
||||
# listener {Function}s.
|
||||
#
|
||||
|
||||
@@ -16,6 +16,11 @@ module.exports =
|
||||
type: 'boolean'
|
||||
default: true
|
||||
title: 'Exclude VCS Ignored Paths'
|
||||
followSymlinks:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
title: 'Follow symlinks'
|
||||
description: 'Used when searching and when opening files with the fuzzy finder.'
|
||||
disabledPackages:
|
||||
type: 'array'
|
||||
default: []
|
||||
@@ -93,6 +98,11 @@ module.exports =
|
||||
type: ['string', 'null']
|
||||
|
||||
# These can be used as globals or scoped, thus defaults.
|
||||
completions:
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
default: []
|
||||
fontFamily:
|
||||
type: 'string'
|
||||
default: ''
|
||||
@@ -149,7 +159,7 @@ module.exports =
|
||||
default: false
|
||||
undoGroupingInterval:
|
||||
type: 'integer'
|
||||
default: 500
|
||||
default: 300
|
||||
minimum: 0
|
||||
description: 'Time interval in milliseconds within which operations will be grouped together in the undo history'
|
||||
useHardwareAcceleration:
|
||||
@@ -158,9 +168,9 @@ module.exports =
|
||||
description: 'Disabling will improve editor font rendering but reduce scrolling performance.'
|
||||
useShadowDOM:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
default: true
|
||||
title: 'Use Shadow DOM'
|
||||
description: 'Enable to test out themes and packages with the new shadow DOM before it ships by default.'
|
||||
description: 'Disable if you experience styling issues with packages or themes. Be sure to open an issue on the relevant package or theme, because this option is going away eventually.'
|
||||
confirmCheckoutHeadRevision:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
|
||||
+282
-203
@@ -6,7 +6,7 @@ CSON = require 'season'
|
||||
path = require 'path'
|
||||
async = require 'async'
|
||||
pathWatcher = require 'pathwatcher'
|
||||
{deprecate} = require 'grim'
|
||||
Grim = require 'grim'
|
||||
|
||||
ScopedPropertyStore = require 'scoped-property-store'
|
||||
ScopeDescriptor = require './scope-descriptor'
|
||||
@@ -313,11 +313,13 @@ class Config
|
||||
@defaultSettings = {}
|
||||
@settings = {}
|
||||
@scopedSettingsStore = new ScopedPropertyStore
|
||||
@usersScopedSettings = new CompositeDisposable
|
||||
@usersScopedSettingPriority = {priority: 1000}
|
||||
@configFileHasErrors = false
|
||||
@configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson'])
|
||||
@configFilePath ?= path.join(@configDirPath, 'config.cson')
|
||||
@transactDepth = 0
|
||||
|
||||
@debouncedSave = _.debounce(@save, 100)
|
||||
@debouncedLoad = _.debounce(@loadUserConfig, 100)
|
||||
|
||||
###
|
||||
Section: Config Subscription
|
||||
@@ -337,32 +339,36 @@ class Config
|
||||
# # do stuff with value
|
||||
# ```
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` {String} name of the key to observe
|
||||
# * `options` {Object}
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `callback` {Function} to call when the value of the key changes.
|
||||
# * `value` the new value of the key
|
||||
#
|
||||
# Returns a {Disposable} with the following keys on which you can call
|
||||
# `.dispose()` to unsubscribe.
|
||||
observe: (scopeDescriptor, keyPath, options, callback) ->
|
||||
args = Array::slice.call(arguments)
|
||||
if args.length is 2
|
||||
# observe(keyPath, callback)
|
||||
[keyPath, callback, scopeDescriptor, options] = args
|
||||
else if args.length is 3 and (Array.isArray(scopeDescriptor) or scopeDescriptor instanceof ScopeDescriptor)
|
||||
# observe(scopeDescriptor, keyPath, callback)
|
||||
[scopeDescriptor, keyPath, callback, options] = args
|
||||
else if args.length is 3 and _.isString(scopeDescriptor) and _.isObject(keyPath)
|
||||
# observe(keyPath, options, callback) # Deprecated!
|
||||
[keyPath, options, callback, scopeDescriptor] = args
|
||||
|
||||
message = ""
|
||||
message = "`callNow` was set to false. Use ::onDidChange instead. Note that ::onDidChange calls back with different arguments." if options.callNow == false
|
||||
deprecate "Config::observe no longer supports options; see https://atom.io/docs/api/latest/Config. #{message}"
|
||||
observe: ->
|
||||
if arguments.length is 2
|
||||
[keyPath, callback] = arguments
|
||||
else if arguments.length is 3 and (_.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor)
|
||||
Grim.deprecate """
|
||||
Passing a scope descriptor as the first argument to Config::observe is deprecated.
|
||||
Pass a `scope` in an options hash as the third argument instead.
|
||||
"""
|
||||
[scopeDescriptor, keyPath, callback] = arguments
|
||||
else if arguments.length is 3 and (_.isString(arguments[0]) and _.isObject(arguments[1]))
|
||||
[keyPath, options, callback] = arguments
|
||||
scopeDescriptor = options.scope
|
||||
if options.callNow?
|
||||
Grim.deprecate """
|
||||
Config::observe no longer takes a `callNow` option. Use ::onDidChange instead.
|
||||
Note that ::onDidChange passes its callback different arguments.
|
||||
See https://atom.io/docs/api/latest/Config
|
||||
"""
|
||||
else
|
||||
console.error 'An unsupported form of Config::observe is being used. See https://atom.io/docs/api/latest/Config for details'
|
||||
return
|
||||
@@ -375,13 +381,14 @@ class Config
|
||||
# Essential: Add a listener for changes to a given key path. If `keyPath` is
|
||||
# not specified, your callback will be called on changes to any key.
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` (optional) {String} name of the key to observe. Must be
|
||||
# specified if `scopeDescriptor` is specified.
|
||||
# * `optional` (optional) {Object}
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `callback` {Function} to call when the value of the key changes.
|
||||
# * `event` {Object}
|
||||
# * `newValue` the new value of the key
|
||||
@@ -390,12 +397,20 @@ class Config
|
||||
#
|
||||
# Returns a {Disposable} with the following keys on which you can call
|
||||
# `.dispose()` to unsubscribe.
|
||||
onDidChange: (scopeDescriptor, keyPath, callback) ->
|
||||
args = Array::slice.call(arguments)
|
||||
onDidChange: ->
|
||||
if arguments.length is 1
|
||||
[callback, scopeDescriptor, keyPath] = args
|
||||
[callback] = arguments
|
||||
else if arguments.length is 2
|
||||
[keyPath, callback, scopeDescriptor] = args
|
||||
[keyPath, callback] = arguments
|
||||
else if _.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor
|
||||
Grim.deprecate """
|
||||
Passing a scope descriptor as the first argument to Config::onDidChange is deprecated.
|
||||
Pass a `scope` in an options hash as the third argument instead.
|
||||
"""
|
||||
[scopeDescriptor, keyPath, callback] = arguments
|
||||
else
|
||||
[keyPath, options, callback] = arguments
|
||||
scopeDescriptor = options.scope
|
||||
|
||||
if scopeDescriptor?
|
||||
@onDidChangeScopedKeyPath(scopeDescriptor, keyPath, callback)
|
||||
@@ -421,14 +436,14 @@ class Config
|
||||
# files.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 2
|
||||
# ```
|
||||
#
|
||||
# This setting in ruby files might be different than the global tabLength setting
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get('editor.tabLength') # => 4
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 2
|
||||
# ```
|
||||
#
|
||||
# You can get the language scope descriptor via
|
||||
@@ -436,34 +451,72 @@ class Config
|
||||
# for the editor's language.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get(@editor.getRootScopeDescriptor(), 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: @editor.getRootScopeDescriptor()) # => 2
|
||||
# ```
|
||||
#
|
||||
# Additionally, you can get the setting at the specific cursor position.
|
||||
#
|
||||
# ```coffee
|
||||
# scopeDescriptor = @editor.getLastCursor().getScopeDescriptor()
|
||||
# atom.config.get(scopeDescriptor, 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: scopeDescriptor) # => 2
|
||||
# ```
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key to retrieve.
|
||||
# * `options` (optional) {Object}
|
||||
# * `sources` (optional) {Array} of {String} source names. If provided, only
|
||||
# values that were associated with these sources during {::set} will be used.
|
||||
# * `excludeSources` (optional) {Array} of {String} source names. If provided,
|
||||
# values that were associated with these sources during {::set} will not
|
||||
# be used.
|
||||
# * `scope` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
# file in the type specified by the configuration schema.
|
||||
get: (scopeDescriptor, keyPath) ->
|
||||
if arguments.length == 1
|
||||
# cannot assign to keyPath for the sake of v8 optimization
|
||||
globalKeyPath = scopeDescriptor
|
||||
@getRawValue(globalKeyPath)
|
||||
get: ->
|
||||
if arguments.length > 1
|
||||
if typeof arguments[0] is 'string' or not arguments[0]?
|
||||
[keyPath, options] = arguments
|
||||
{scope} = options
|
||||
else
|
||||
Grim.deprecate """
|
||||
Passing a scope descriptor as the first argument to Config::get is deprecated.
|
||||
Pass a `scope` in an options hash as the final argument instead.
|
||||
"""
|
||||
[scope, keyPath] = arguments
|
||||
else
|
||||
value = @getRawScopedValue(scopeDescriptor, keyPath)
|
||||
value ?= @getRawValue(keyPath)
|
||||
value
|
||||
[keyPath] = arguments
|
||||
|
||||
if scope?
|
||||
value = @getRawScopedValue(scope, keyPath, options)
|
||||
value ? @getRawValue(keyPath, options)
|
||||
else
|
||||
@getRawValue(keyPath, options)
|
||||
|
||||
# Extended: Get all of the values for the given key-path, along with their
|
||||
# associated scope selector.
|
||||
#
|
||||
# * `keyPath` The {String} name of the key to retrieve
|
||||
# * `options` (optional) {Object} see the `options` argument to {::get}
|
||||
#
|
||||
# Returns an {Array} of {Object}s with the following keys:
|
||||
# * `scopeSelector` The scope-selector {String} with which the value is associated
|
||||
# * `value` The value for the key-path
|
||||
getAll: (keyPath, options) ->
|
||||
{scope, sources} = options if options?
|
||||
result = []
|
||||
|
||||
if scope?
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scope)
|
||||
result = result.concat @scopedSettingsStore.getAll(scopeDescriptor.getScopeChain(), keyPath, options)
|
||||
|
||||
if globalValue = @getRawValue(keyPath, options)
|
||||
result.push(scopeSelector: '*', value: globalValue)
|
||||
|
||||
result
|
||||
|
||||
# Essential: Sets the value for a configuration setting.
|
||||
#
|
||||
@@ -482,75 +535,113 @@ class Config
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get('editor.tabLength') # => 4
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 4
|
||||
# atom.config.get(['source.js'], 'editor.tabLength') # => 4
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 4
|
||||
# atom.config.get('editor.tabLength', scope: ['source.js']) # => 4
|
||||
#
|
||||
# # Set ruby to 2
|
||||
# atom.config.set('source.ruby', 'editor.tabLength', 2) # => true
|
||||
# atom.config.set('editor.tabLength', 2, scopeSelector: 'source.ruby') # => true
|
||||
#
|
||||
# # Notice it's only set to 2 in the case of ruby
|
||||
# atom.config.get('editor.tabLength') # => 4
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 2
|
||||
# atom.config.get(['source.js'], 'editor.tabLength') # => 4
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 2
|
||||
# atom.config.get('editor.tabLength', scope: ['source.js']) # => 4
|
||||
# ```
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key.
|
||||
# * `value` The value of the setting. Passing `undefined` will revert the
|
||||
# setting to the default value.
|
||||
# * `options` (optional) {Object}
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `source` (optional) {String} The name of a file with which the setting
|
||||
# is associated. Defaults to the user's config file.
|
||||
#
|
||||
# Returns a {Boolean}
|
||||
# * `true` if the value was set.
|
||||
# * `false` if the value was not able to be coerced to the type specified in the setting's schema.
|
||||
set: (scopeSelector, keyPath, value) ->
|
||||
if arguments.length < 3
|
||||
value = keyPath
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = undefined
|
||||
set: ->
|
||||
if arguments[0]?[0] is '.'
|
||||
Grim.deprecate """
|
||||
Passing a scope selector as the first argument to Config::set is deprecated.
|
||||
Pass a `scopeSelector` in an options hash as the final argument instead.
|
||||
"""
|
||||
[scopeSelector, keyPath, value] = arguments
|
||||
else
|
||||
[keyPath, value, options] = arguments
|
||||
scopeSelector = options?.scopeSelector
|
||||
source = options?.source
|
||||
shouldSave = options?.save ? true
|
||||
|
||||
unless value == undefined
|
||||
if source and not scopeSelector
|
||||
throw new Error("::set with a 'source' and no 'sourceSelector' is not yet implemented!")
|
||||
|
||||
source ?= @getUserConfigPath()
|
||||
|
||||
unless value is undefined
|
||||
try
|
||||
value = @makeValueConformToSchema(keyPath, value)
|
||||
catch e
|
||||
return false
|
||||
|
||||
if scopeSelector?
|
||||
@setRawScopedValue(scopeSelector, keyPath, value)
|
||||
@setRawScopedValue(source, scopeSelector, keyPath, value)
|
||||
else
|
||||
@setRawValue(keyPath, value)
|
||||
|
||||
@save() unless @configFileHasErrors
|
||||
@debouncedSave() if source is @getUserConfigPath() and shouldSave and not @configFileHasErrors
|
||||
true
|
||||
|
||||
# Extended: Restore the global setting at `keyPath` to its default value.
|
||||
# Essential: Restore the setting at `keyPath` to its default value.
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key.
|
||||
# * `options` (optional) {Object}
|
||||
# * `scopeSelector` (optional) {String}. See {::set}
|
||||
# * `source` (optional) {String}. See {::set}
|
||||
unset: (keyPath, options) ->
|
||||
if typeof options is 'string'
|
||||
Grim.deprecate """
|
||||
Passing a scope selector as the first argument to Config::unset is deprecated.
|
||||
Pass a `scopeSelector` in an options hash as the second argument instead.
|
||||
"""
|
||||
scopeSelector = keyPath
|
||||
keyPath = options
|
||||
else
|
||||
{scopeSelector, source} = options ? {}
|
||||
|
||||
source ?= @getUserConfigPath()
|
||||
|
||||
if scopeSelector?
|
||||
if keyPath?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector(source, scopeSelector)
|
||||
if _.valueForKeyPath(settings, keyPath)?
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector(source, scopeSelector)
|
||||
_.setValueForKeyPath(settings, keyPath, undefined)
|
||||
settings = withoutEmptyObjects(settings)
|
||||
@set(null, settings, {scopeSelector, source, priority: @priorityForSource(source)}) if settings?
|
||||
@debouncedSave()
|
||||
else
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector(source, scopeSelector)
|
||||
@emitChangeEvent()
|
||||
else
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
if keyPath?
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
|
||||
# Extended: Get an {Array} of all of the `source` {String}s with which
|
||||
# settings have been added via {::set}.
|
||||
getSources: ->
|
||||
_.uniq(_.pluck(@scopedSettingsStore.propertySets, 'source')).sort()
|
||||
|
||||
# Deprecated: Restore the global setting at `keyPath` to its default value.
|
||||
#
|
||||
# Returns the new value.
|
||||
restoreDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
Grim.deprecate("Use ::unset instead.")
|
||||
@unset(scopeSelector, keyPath)
|
||||
@get(keyPath)
|
||||
|
||||
if scopeSelector?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
if _.valueForKeyPath(settings, keyPath)?
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
_.setValueForKeyPath(settings, keyPath, undefined)
|
||||
settings = withoutEmptyObjects(settings)
|
||||
@addScopedSettings('user-config', scopeSelector, settings, @usersScopedSettingPriority) if settings?
|
||||
@save() unless @configFileHasErrors
|
||||
@getDefault(scopeSelector, keyPath)
|
||||
else
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
@get(keyPath)
|
||||
|
||||
# Extended: Get the global default value of the key path. _Please note_ that in most
|
||||
# Deprecated: Get the global default value of the key path. _Please note_ that in most
|
||||
# cases calling this is not necessary! {::get} returns the default value when
|
||||
# a custom value is not specified.
|
||||
#
|
||||
@@ -558,35 +649,30 @@ class Config
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns the default value.
|
||||
getDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
defaultValue = @scopedSettingsStore.getPropertyValue(scopeSelector, keyPath, excludeSources: ['user-config'])
|
||||
defaultValue ?= _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
getDefault: ->
|
||||
Grim.deprecate("Use `::get(keyPath, {scope, excludeSources: [atom.config.getUserConfigPath()]})` instead")
|
||||
if arguments.length is 1
|
||||
[keyPath] = arguments
|
||||
else
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
_.deepClone(defaultValue)
|
||||
[scopeSelector, keyPath] = arguments
|
||||
scope = [scopeSelector]
|
||||
@get(keyPath, {scope, excludeSources: [@getUserConfigPath()]})
|
||||
|
||||
# Extended: Is the value at `keyPath` its default value?
|
||||
# Deprecated: Is the value at `keyPath` its default value?
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns a {Boolean}, `true` if the current value is the default, `false`
|
||||
# otherwise.
|
||||
isDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
not _.valueForKeyPath(settings, keyPath)?
|
||||
isDefault: ->
|
||||
Grim.deprecate("Use `not ::get(keyPath, {scope, sources: [atom.config.getUserConfigPath()]})?` instead")
|
||||
if arguments.length is 1
|
||||
[keyPath] = arguments
|
||||
else
|
||||
not _.valueForKeyPath(@settings, keyPath)?
|
||||
[scopeSelector, keyPath] = arguments
|
||||
scope = [scopeSelector]
|
||||
not @get(keyPath, {scope, sources: [@getUserConfigPath()]})?
|
||||
|
||||
# Extended: Retrieve the schema for a specific key path. The schema will tell
|
||||
# you what type the keyPath expects, and other metadata about the config
|
||||
@@ -604,47 +690,53 @@ class Config
|
||||
schema = schema.properties[key]
|
||||
schema
|
||||
|
||||
# Extended: Returns a new {Object} containing all of the global settings and
|
||||
# Deprecated: Returns a new {Object} containing all of the global settings and
|
||||
# defaults. Returns the scoped settings when a `scopeSelector` is specified.
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
getSettings: (scopeSelector) ->
|
||||
settings = _.deepExtend(@settings, @defaultSettings)
|
||||
|
||||
if scopeSelector?
|
||||
scopedSettings = @scopedSettingsStore.propertiesForSelector(scopeSelector)
|
||||
settings = _.deepExtend(scopedSettings, settings)
|
||||
|
||||
settings
|
||||
getSettings: ->
|
||||
Grim.deprecate "Use ::get(keyPath) instead"
|
||||
_.deepExtend({}, @settings, @defaultSettings)
|
||||
|
||||
# Extended: Get the {String} path to the config file being used.
|
||||
getUserConfigPath: ->
|
||||
@configFilePath
|
||||
|
||||
# Extended: Suppress calls to handler functions registered with {::onDidChange}
|
||||
# and {::observe} for the duration of `callback`. After `callback` executes,
|
||||
# handlers will be called once if the value for their key-path has changed.
|
||||
#
|
||||
# * `callback` {Function} to execute while suppressing calls to handlers.
|
||||
transact: (callback) ->
|
||||
@transactDepth++
|
||||
try
|
||||
callback()
|
||||
finally
|
||||
@transactDepth--
|
||||
@emitChangeEvent()
|
||||
|
||||
###
|
||||
Section: Deprecated
|
||||
###
|
||||
|
||||
getInt: (keyPath) ->
|
||||
deprecate '''Config::getInt is no longer necessary. Use ::get instead.
|
||||
Grim.deprecate '''Config::getInt is no longer necessary. Use ::get instead.
|
||||
Make sure the config option you are accessing has specified an `integer`
|
||||
schema. See the schema section of
|
||||
https://atom.io/docs/api/latest/Config for more info.'''
|
||||
parseInt(@get(keyPath))
|
||||
|
||||
getPositiveInt: (keyPath, defaultValue=0) ->
|
||||
deprecate '''Config::getPositiveInt is no longer necessary. Use ::get instead.
|
||||
Grim.deprecate '''Config::getPositiveInt is no longer necessary. Use ::get instead.
|
||||
Make sure the config option you are accessing has specified an `integer`
|
||||
schema with `minimum: 1`. See the schema section of
|
||||
https://atom.io/docs/api/latest/Config for more info.'''
|
||||
Math.max(@getInt(keyPath), 0) or defaultValue
|
||||
|
||||
toggle: (keyPath) ->
|
||||
deprecate 'Config::toggle is no longer supported. Please remove from your code.'
|
||||
Grim.deprecate 'Config::toggle is no longer supported. Please remove from your code.'
|
||||
@set(keyPath, !@get(keyPath))
|
||||
|
||||
unobserve: (keyPath) ->
|
||||
deprecate 'Config::unobserve no longer does anything. Call `.dispose()` on the object returned by Config::observe instead.'
|
||||
Grim.deprecate 'Config::unobserve no longer does anything. Call `.dispose()` on the object returned by Config::observe instead.'
|
||||
|
||||
###
|
||||
Section: Internal methods used by core
|
||||
@@ -729,7 +821,7 @@ class Config
|
||||
observeUserConfig: ->
|
||||
try
|
||||
@watchSubscription ?= pathWatcher.watch @configFilePath, (eventType) =>
|
||||
@loadUserConfig() if eventType is 'change' and @watchSubscription?
|
||||
@debouncedLoad() if eventType is 'change' and @watchSubscription?
|
||||
catch error
|
||||
@notifyFailure('Failed to watch user config', error)
|
||||
|
||||
@@ -740,13 +832,13 @@ class Config
|
||||
notifyFailure: (errorMessage, error) ->
|
||||
message = "#{errorMessage}"
|
||||
detail = error.stack
|
||||
atom.notifications.addError(message, {detail, closable: true})
|
||||
atom.notifications.addError(message, {detail, dismissable: true})
|
||||
console.error message
|
||||
console.error detail
|
||||
|
||||
save: ->
|
||||
allSettings = global: @settings
|
||||
allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource('user-config')
|
||||
allSettings = {'*': @settings}
|
||||
allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource(@getUserConfigPath())
|
||||
CSON.writeFileSync(@configFilePath, allSettings)
|
||||
|
||||
###
|
||||
@@ -756,44 +848,28 @@ class Config
|
||||
resetUserSettings: (newSettings) ->
|
||||
unless isPlainObject(newSettings)
|
||||
@settings = {}
|
||||
@emitter.emit 'did-change'
|
||||
@emitChangeEvent()
|
||||
return
|
||||
|
||||
if newSettings.global?
|
||||
newSettings['*'] = newSettings.global
|
||||
delete newSettings.global
|
||||
|
||||
if newSettings['*']?
|
||||
scopedSettings = newSettings
|
||||
newSettings = newSettings.global
|
||||
delete scopedSettings.global
|
||||
newSettings = newSettings['*']
|
||||
delete scopedSettings['*']
|
||||
@resetUserScopedSettings(scopedSettings)
|
||||
|
||||
unsetUnspecifiedValues = (keyPath, value) =>
|
||||
if isPlainObject(value)
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of value
|
||||
continue unless value.hasOwnProperty(key)
|
||||
unsetUnspecifiedValues(keys.concat([key]).join('.'), childValue)
|
||||
else
|
||||
@setRawValue(keyPath, undefined) unless _.valueForKeyPath(newSettings, keyPath)?
|
||||
return
|
||||
@transact =>
|
||||
@settings = {}
|
||||
@set(key, value, save: false) for key, value of newSettings
|
||||
|
||||
@setRecursive(null, newSettings)
|
||||
unsetUnspecifiedValues(null, @settings)
|
||||
|
||||
setRecursive: (keyPath, value) ->
|
||||
if isPlainObject(value)
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of value
|
||||
continue unless value.hasOwnProperty(key)
|
||||
@setRecursive(keys.concat([key]).join('.'), childValue)
|
||||
else
|
||||
try
|
||||
value = @makeValueConformToSchema(keyPath, value)
|
||||
@setRawValue(keyPath, value)
|
||||
catch e
|
||||
console.warn("'#{keyPath}' could not be set. Attempted value: #{JSON.stringify(value)}; Schema: #{JSON.stringify(@getSchema(keyPath))}")
|
||||
|
||||
getRawValue: (keyPath) ->
|
||||
value = _.valueForKeyPath(@settings, keyPath)
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
getRawValue: (keyPath, options) ->
|
||||
unless options?.excludeSources?.indexOf(@getUserConfigPath()) >= 0
|
||||
value = _.valueForKeyPath(@settings, keyPath)
|
||||
unless options?.sources?.length > 0
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
|
||||
if value?
|
||||
value = _.deepClone(value)
|
||||
@@ -807,19 +883,24 @@ class Config
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
value = undefined if _.isEqual(defaultValue, value)
|
||||
|
||||
oldValue = _.clone(@get(keyPath))
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
newValue = @get(keyPath)
|
||||
@emitter.emit 'did-change', {oldValue, newValue, keyPath} unless _.isEqual(newValue, oldValue)
|
||||
if keyPath?
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
else
|
||||
@settings = value
|
||||
@emitChangeEvent()
|
||||
|
||||
observeKeyPath: (keyPath, options, callback) ->
|
||||
callback(_.clone(@get(keyPath))) unless options.callNow == false
|
||||
@emitter.on 'did-change', (event) =>
|
||||
callback(event.newValue) if keyPath? and @isSubKeyPath(keyPath, event?.keyPath)
|
||||
callback(@get(keyPath))
|
||||
@onDidChangeKeyPath keyPath, (event) -> callback(event.newValue)
|
||||
|
||||
onDidChangeKeyPath: (keyPath, callback) ->
|
||||
@emitter.on 'did-change', (event) =>
|
||||
callback(event) if not keyPath? or (keyPath? and @isSubKeyPath(keyPath, event?.keyPath))
|
||||
oldValue = @get(keyPath)
|
||||
@emitter.on 'did-change', =>
|
||||
newValue = @get(keyPath)
|
||||
unless _.isEqual(oldValue, newValue)
|
||||
event = {oldValue, newValue}
|
||||
oldValue = newValue
|
||||
callback(event)
|
||||
|
||||
isSubKeyPath: (keyPath, subKeyPath) ->
|
||||
return false unless keyPath? and subKeyPath?
|
||||
@@ -828,10 +909,8 @@ class Config
|
||||
_.isEqual(pathTokens, pathSubTokens)
|
||||
|
||||
setRawDefault: (keyPath, value) ->
|
||||
oldValue = _.clone(@get(keyPath))
|
||||
_.setValueForKeyPath(@defaultSettings, keyPath, value)
|
||||
newValue = @get(keyPath)
|
||||
@emitter.emit 'did-change', {oldValue, newValue, keyPath} unless _.isEqual(newValue, oldValue)
|
||||
@emitChangeEvent()
|
||||
|
||||
setDefaults: (keyPath, defaults) ->
|
||||
if defaults? and isPlainObject(defaults)
|
||||
@@ -889,22 +968,32 @@ class Config
|
||||
Section: Private Scoped Settings
|
||||
###
|
||||
|
||||
priorityForSource: (source) ->
|
||||
if source is @getUserConfigPath()
|
||||
1000
|
||||
else
|
||||
0
|
||||
|
||||
emitChangeEvent: ->
|
||||
@emitter.emit 'did-change' unless @transactDepth > 0
|
||||
|
||||
resetUserScopedSettings: (newScopedSettings) ->
|
||||
@usersScopedSettings?.dispose()
|
||||
@usersScopedSettings = new CompositeDisposable
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', newScopedSettings, @usersScopedSettingPriority)
|
||||
@emitter.emit 'did-change'
|
||||
source = @getUserConfigPath()
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
@scopedSettingsStore.addProperties(source, newScopedSettings, priority: @priorityForSource(source))
|
||||
@emitChangeEvent()
|
||||
|
||||
addScopedSettings: (source, selector, value, options) ->
|
||||
Grim.deprecate("Use ::set instead")
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
disposable = @scopedSettingsStore.addProperties(source, settingsBySelector, options)
|
||||
@emitter.emit 'did-change'
|
||||
@emitChangeEvent()
|
||||
new Disposable =>
|
||||
disposable.dispose()
|
||||
@emitter.emit 'did-change'
|
||||
@emitChangeEvent()
|
||||
|
||||
setRawScopedValue: (selector, keyPath, value) ->
|
||||
setRawScopedValue: (source, selector, keyPath, value) ->
|
||||
if keyPath?
|
||||
newValue = {}
|
||||
_.setValueForKeyPath(newValue, keyPath, value)
|
||||
@@ -912,40 +1001,30 @@ class Config
|
||||
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', settingsBySelector, @usersScopedSettingPriority)
|
||||
@emitter.emit 'did-change'
|
||||
@scopedSettingsStore.addProperties(source, settingsBySelector, priority: @priorityForSource(source))
|
||||
@emitChangeEvent()
|
||||
|
||||
getRawScopedValue: (scopeDescriptor, keyPath) ->
|
||||
getRawScopedValue: (scopeDescriptor, keyPath, options) ->
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor)
|
||||
@scopedSettingsStore.getPropertyValue(scopeDescriptor.getScopeChain(), keyPath)
|
||||
@scopedSettingsStore.getPropertyValue(scopeDescriptor.getScopeChain(), keyPath, options)
|
||||
|
||||
observeScopedKeyPath: (scopeDescriptor, keyPath, callback) ->
|
||||
oldValue = @get(scopeDescriptor, keyPath)
|
||||
observeScopedKeyPath: (scope, keyPath, callback) ->
|
||||
callback(@get(keyPath, {scope}))
|
||||
@onDidChangeScopedKeyPath scope, keyPath, (event) -> callback(event.newValue)
|
||||
|
||||
callback(oldValue)
|
||||
onDidChangeScopedKeyPath: (scope, keyPath, callback) ->
|
||||
oldValue = @get(keyPath, {scope})
|
||||
@emitter.on 'did-change', =>
|
||||
newValue = @get(keyPath, {scope})
|
||||
unless _.isEqual(oldValue, newValue)
|
||||
event = {oldValue, newValue}
|
||||
oldValue = newValue
|
||||
callback(event)
|
||||
|
||||
didChange = =>
|
||||
newValue = @get(scopeDescriptor, keyPath)
|
||||
callback(newValue) unless _.isEqual(oldValue, newValue)
|
||||
oldValue = newValue
|
||||
|
||||
@emitter.on 'did-change', didChange
|
||||
|
||||
onDidChangeScopedKeyPath: (scopeDescriptor, keyPath, callback) ->
|
||||
oldValue = @get(scopeDescriptor, keyPath)
|
||||
didChange = =>
|
||||
newValue = @get(scopeDescriptor, keyPath)
|
||||
callback({oldValue, newValue, keyPath}) unless _.isEqual(oldValue, newValue)
|
||||
oldValue = newValue
|
||||
|
||||
@emitter.on 'did-change', didChange
|
||||
|
||||
# TODO: figure out how to change / remove this. The return value is awkward.
|
||||
# * language mode uses it for one thing.
|
||||
# * autocomplete uses it for editor.completions
|
||||
settingsForScopeDescriptor: (scopeDescriptor, keyPath) ->
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor)
|
||||
@scopedSettingsStore.getProperties(scopeDescriptor.getScopeChain(), keyPath)
|
||||
Grim.deprecate("Use Config::getAll instead")
|
||||
entries = @getAll(null, scope: scopeDescriptor)
|
||||
value for {value} in entries when _.valueForKeyPath(value, keyPath)?
|
||||
|
||||
# Base schema enforcers. These will coerce raw input into the specified type,
|
||||
# and will throw an error when the value cannot be coerced. Throwing the error
|
||||
|
||||
@@ -16,6 +16,31 @@ SpecificityCache = {}
|
||||
#
|
||||
# An instance of this class is always available as the `atom.contextMenu`
|
||||
# global.
|
||||
#
|
||||
# ## Context Menu CSON Format
|
||||
#
|
||||
# # ```coffee
|
||||
# 'atom-workspace': [{label: 'Help', command: 'application:open-documentation'}]
|
||||
# 'atom-text-editor': [{
|
||||
# label: 'History',
|
||||
# submenu: [
|
||||
# {label: 'Undo', command:'core:undo'}
|
||||
# {label: 'Redo', command:'core:redo'}
|
||||
# ]
|
||||
# }]
|
||||
# ```
|
||||
#
|
||||
# In your package's menu `.cson` file you need to specify it under a
|
||||
# `context-menu` key:
|
||||
#
|
||||
# ```coffee
|
||||
# 'context-menu':
|
||||
# 'atom-workspace': [{label: 'Help', command: 'application:open-documentation'}]
|
||||
# ...
|
||||
# ```
|
||||
#
|
||||
# The format for use in {::add} is the same minus the `context-menu` key. See
|
||||
# {::add} for more information.
|
||||
module.exports =
|
||||
class ContextMenuManager
|
||||
constructor: ({@resourcePath, @devMode}) ->
|
||||
@@ -46,8 +71,8 @@ class ContextMenuManager
|
||||
# 'atom-text-editor': [{
|
||||
# label: 'History',
|
||||
# submenu: [
|
||||
# {label: 'Undo': command:'core:undo'}
|
||||
# {label: 'Redo': command:'core:redo'}
|
||||
# {label: 'Undo', command:'core:undo'}
|
||||
# {label: 'Redo', command:'core:redo'}
|
||||
# ]
|
||||
# }]
|
||||
# }
|
||||
@@ -77,14 +102,22 @@ class ContextMenuManager
|
||||
add: (itemsBySelector) ->
|
||||
# Detect deprecated file path as first argument
|
||||
if itemsBySelector? and typeof itemsBySelector isnt 'object'
|
||||
Grim.deprecate("ContextMenuManager::add has changed to take a single object as its argument. Please consult the documentation.")
|
||||
Grim.deprecate """
|
||||
ContextMenuManager::add has changed to take a single object as its
|
||||
argument. Please see
|
||||
https://atom.io/docs/api/latest/ContextMenuManager for more info.
|
||||
"""
|
||||
itemsBySelector = arguments[1]
|
||||
devMode = arguments[2]?.devMode
|
||||
|
||||
# Detect deprecated format for items object
|
||||
for key, value of itemsBySelector
|
||||
unless _.isArray(value)
|
||||
Grim.deprecate("The format for declaring context menu items has changed. Please consult the documentation.")
|
||||
Grim.deprecate """
|
||||
ContextMenuManager::add has changed to take a single object as its
|
||||
argument. Please see
|
||||
https://atom.io/docs/api/latest/ContextMenuManager for more info.
|
||||
"""
|
||||
itemsBySelector = @convertLegacyItemsBySelector(itemsBySelector, devMode)
|
||||
|
||||
addedItemSets = []
|
||||
|
||||
+16
-10
@@ -45,7 +45,7 @@ class Cursor extends Model
|
||||
cursor: this
|
||||
|
||||
@emit 'moved', movedEvent
|
||||
@emitter.emit 'did-change-position'
|
||||
@emitter.emit 'did-change-position', movedEvent
|
||||
@editor.cursorMoved(movedEvent)
|
||||
@marker.onDidDestroy =>
|
||||
@destroyed = true
|
||||
@@ -202,14 +202,20 @@ class Cursor extends Model
|
||||
[before, after] = @editor.getTextInBufferRange(range)
|
||||
return false if /\s/.test(before) or /\s/.test(after)
|
||||
|
||||
nonWordCharacters = atom.config.get(@getScopeDescriptor(), 'editor.nonWordCharacters').split('')
|
||||
nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()).split('')
|
||||
_.contains(nonWordCharacters, before) isnt _.contains(nonWordCharacters, after)
|
||||
|
||||
# Public: Returns whether this cursor is between a word's start and end.
|
||||
isInsideWord: ->
|
||||
#
|
||||
# * `options` (optional) {Object}
|
||||
# * `wordRegex` A {RegExp} indicating what constitutes a "word"
|
||||
# (default: {::wordRegExp}).
|
||||
#
|
||||
# Returns a {Boolean}
|
||||
isInsideWord: (options) ->
|
||||
{row, column} = @getBufferPosition()
|
||||
range = [[row, column], [row, Infinity]]
|
||||
@editor.getTextInBufferRange(range).search(@wordRegExp()) == 0
|
||||
@editor.getTextInBufferRange(range).search(options?.wordRegex ? @wordRegExp()) == 0
|
||||
|
||||
# Public: Returns the indentation level of the current line.
|
||||
getIndentLevel: ->
|
||||
@@ -476,7 +482,7 @@ class Cursor extends Model
|
||||
endOfWordPosition or currentBufferPosition
|
||||
|
||||
getMoveNextWordBoundaryBufferPosition: (options) ->
|
||||
deprecate 'Use `::getNextWordBoundaryBufferPosition(options)` instead'
|
||||
Grim.deprecate 'Use `::getNextWordBoundaryBufferPosition(options)` instead'
|
||||
@getNextWordBoundaryBufferPosition(options)
|
||||
|
||||
# Public: Retrieves the buffer position of where the current word starts.
|
||||
@@ -544,7 +550,7 @@ class Cursor extends Model
|
||||
# Returns a {Range}
|
||||
getBeginningOfNextWordBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
start = if @isInsideWord() then @getEndOfCurrentWordBufferPosition() else currentBufferPosition
|
||||
start = if @isInsideWord(options) then @getEndOfCurrentWordBufferPosition(options) else currentBufferPosition
|
||||
scanRange = [start, @editor.getEofBufferPosition()]
|
||||
|
||||
beginningOfNextWordPosition = null
|
||||
@@ -636,7 +642,7 @@ class Cursor extends Model
|
||||
# Returns a {RegExp}.
|
||||
wordRegExp: ({includeNonWordCharacters}={}) ->
|
||||
includeNonWordCharacters ?= true
|
||||
nonWordCharacters = atom.config.get(@getScopeDescriptor(), 'editor.nonWordCharacters')
|
||||
nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor())
|
||||
segments = ["^[\t ]*$"]
|
||||
segments.push("[^\\s#{_.escapeRegExp(nonWordCharacters)}]+")
|
||||
if includeNonWordCharacters
|
||||
@@ -665,7 +671,7 @@ class Cursor extends Model
|
||||
autoscroll: (options) ->
|
||||
@editor.scrollToScreenRange(@getScreenRange(), options)
|
||||
|
||||
getBeginningOfNextParagraphBufferPosition: (editor) ->
|
||||
getBeginningOfNextParagraphBufferPosition: ->
|
||||
start = @getBufferPosition()
|
||||
eof = @editor.getEofBufferPosition()
|
||||
scanRange = [start, eof]
|
||||
@@ -679,8 +685,8 @@ class Cursor extends Model
|
||||
stop()
|
||||
@editor.screenPositionForBufferPosition(position)
|
||||
|
||||
getBeginningOfPreviousParagraphBufferPosition: (editor) ->
|
||||
start = @editor.getCursorBufferPosition()
|
||||
getBeginningOfPreviousParagraphBufferPosition: ->
|
||||
start = @getBufferPosition()
|
||||
|
||||
{row, column} = start
|
||||
scanRange = [[row-1, column], [0,0]]
|
||||
|
||||
+26
-12
@@ -67,24 +67,24 @@ class DisplayBuffer extends Model
|
||||
|
||||
oldConfigSettings = @configSettings
|
||||
@configSettings =
|
||||
scrollPastEnd: atom.config.get(scopeDescriptor, 'editor.scrollPastEnd')
|
||||
softWrap: atom.config.get(scopeDescriptor, 'editor.softWrap')
|
||||
softWrapAtPreferredLineLength: atom.config.get(scopeDescriptor, 'editor.softWrapAtPreferredLineLength')
|
||||
preferredLineLength: atom.config.get(scopeDescriptor, 'editor.preferredLineLength')
|
||||
scrollPastEnd: atom.config.get('editor.scrollPastEnd', scope: scopeDescriptor)
|
||||
softWrap: atom.config.get('editor.softWrap', scope: scopeDescriptor)
|
||||
softWrapAtPreferredLineLength: atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor)
|
||||
preferredLineLength: atom.config.get('editor.preferredLineLength', scope: scopeDescriptor)
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.softWrap', ({newValue}) =>
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrap', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrap = newValue
|
||||
@updateWrappedScreenLines()
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.softWrapAtPreferredLineLength', ({newValue}) =>
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrapAtPreferredLineLength', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrapAtPreferredLineLength = newValue
|
||||
@updateWrappedScreenLines() if @isSoftWrapped()
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.preferredLineLength', ({newValue}) =>
|
||||
subscriptions.add atom.config.onDidChange 'editor.preferredLineLength', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.preferredLineLength = newValue
|
||||
@updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get(scopeDescriptor, 'editor.softWrapAtPreferredLineLength')
|
||||
@updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor)
|
||||
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.scrollPastEnd', (value) =>
|
||||
subscriptions.add atom.config.observe 'editor.scrollPastEnd', scope: scopeDescriptor, (value) =>
|
||||
@configSettings.scrollPastEnd = value
|
||||
|
||||
@updateWrappedScreenLines() if oldConfigSettings? and not _.isEqual(oldConfigSettings, @configSettings)
|
||||
@@ -883,14 +883,28 @@ class DisplayBuffer extends Model
|
||||
decorationForId: (id) ->
|
||||
@decorationsById[id]
|
||||
|
||||
getDecorations: ->
|
||||
getDecorations: (propertyFilter) ->
|
||||
allDecorations = []
|
||||
for markerId, decorations of @decorationsByMarkerId
|
||||
allDecorations = allDecorations.concat(decorations) if decorations?
|
||||
if propertyFilter?
|
||||
allDecorations = allDecorations.filter (decoration) ->
|
||||
for key, value of propertyFilter
|
||||
return false unless decoration.properties[key] is value
|
||||
true
|
||||
allDecorations
|
||||
|
||||
getOverlayDecorations: ->
|
||||
@getDecorations().filter (decoration) -> decoration.isType('overlay')
|
||||
getLineDecorations: (propertyFilter) ->
|
||||
@getDecorations(propertyFilter).filter (decoration) -> decoration.isType('line')
|
||||
|
||||
getGutterDecorations: (propertyFilter) ->
|
||||
@getDecorations(propertyFilter).filter (decoration) -> decoration.isType('gutter')
|
||||
|
||||
getHighlightDecorations: (propertyFilter) ->
|
||||
@getDecorations(propertyFilter).filter (decoration) -> decoration.isType('highlight')
|
||||
|
||||
getOverlayDecorations: (propertyFilter) ->
|
||||
@getDecorations(propertyFilter).filter (decoration) -> decoration.isType('overlay')
|
||||
|
||||
decorationsForScreenRowRange: (startScreenRow, endScreenRow) ->
|
||||
decorationsByMarkerId = {}
|
||||
|
||||
@@ -412,6 +412,8 @@ class GitRepository
|
||||
bufferSubscriptions.add buffer.onDidDestroy =>
|
||||
bufferSubscriptions.dispose()
|
||||
@subscriptions.remove(bufferSubscriptions)
|
||||
@subscriptions.add(bufferSubscriptions)
|
||||
return
|
||||
|
||||
# Subscribes to editor view event.
|
||||
checkoutHeadForEditor: (editor) ->
|
||||
|
||||
@@ -67,5 +67,5 @@ class GrammarRegistry extends FirstMate.GrammarRegistry
|
||||
atom.config.getRawScopedValue(scope, keyPath)
|
||||
|
||||
propertiesForScope: (scope, keyPath) ->
|
||||
deprecate 'A direct (but private) replacement is available at atom.config.scopedSettingsForScopeDescriptor().'
|
||||
deprecate 'Use atom.config.getAll instead.'
|
||||
atom.config.settingsForScopeDescriptor(scope, keyPath)
|
||||
|
||||
@@ -25,7 +25,7 @@ KeymapManager::loadUserKeymap = ->
|
||||
|
||||
KeymapManager::subscribeToFileReadFailure = ->
|
||||
this.onDidFailToReadFile (error) ->
|
||||
atom.notifications.addError('Failed to load keymap.cson', {detail: error.stack, closable: true})
|
||||
atom.notifications.addError('Failed to load keymap.cson', {detail: error.stack, dismissable: true})
|
||||
|
||||
# This enables command handlers registered via jQuery to call
|
||||
# `.abortKeyBinding()` on the `jQuery.Event` object passed to the handler.
|
||||
|
||||
@@ -26,17 +26,16 @@ class LanguageMode
|
||||
#
|
||||
# startRow - The row {Number} to start at
|
||||
# endRow - The row {Number} to end at
|
||||
#
|
||||
# Returns an {Array} of the commented {Ranges}.
|
||||
toggleLineCommentsForBufferRows: (start, end) ->
|
||||
scopeDescriptor = @editor.scopeDescriptorForBufferPosition([start, 0])
|
||||
properties = atom.config.settingsForScopeDescriptor(scopeDescriptor, 'editor.commentStart')[0]
|
||||
return unless properties
|
||||
scope = @editor.scopeDescriptorForBufferPosition([start, 0])
|
||||
commentStartEntry = atom.config.getAll('editor.commentStart', {scope})[0]
|
||||
|
||||
commentStartString = _.valueForKeyPath(properties, 'editor.commentStart')
|
||||
commentEndString = _.valueForKeyPath(properties, 'editor.commentEnd')
|
||||
return unless commentStartEntry?
|
||||
|
||||
return unless commentStartString
|
||||
commentEndEntry = atom.config.getAll('editor.commentEnd', {scope}).find (entry) ->
|
||||
entry.scopeSelector is commentStartEntry.scopeSelector
|
||||
commentStartString = commentStartEntry?.value
|
||||
commentEndString = commentEndEntry?.value
|
||||
|
||||
buffer = @editor.buffer
|
||||
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '(?:$1)?')
|
||||
@@ -96,6 +95,7 @@ class LanguageMode
|
||||
buffer.insert([row, indentLength], commentStartString)
|
||||
else
|
||||
buffer.setTextInRange([[row, 0], [row, indentString.length]], indentString + commentStartString)
|
||||
return
|
||||
|
||||
# Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
@@ -113,6 +113,7 @@ class LanguageMode
|
||||
#
|
||||
# indentLevel - A {Number} indicating indentLevel; 0 based.
|
||||
foldAllAtIndentLevel: (indentLevel) ->
|
||||
@unfoldAll()
|
||||
for currentRow in [0..@buffer.getLastRow()]
|
||||
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
continue unless startRow?
|
||||
@@ -316,7 +317,7 @@ class LanguageMode
|
||||
@editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
||||
|
||||
getRegexForProperty: (scopeDescriptor, property) ->
|
||||
if pattern = atom.config.get(scopeDescriptor, property)
|
||||
if pattern = atom.config.get(property, scope: scopeDescriptor)
|
||||
new OnigRegExp(pattern)
|
||||
|
||||
increaseIndentRegexForScopeDescriptor: (scopeDescriptor) ->
|
||||
|
||||
@@ -12,6 +12,49 @@ MenuHelpers = require './menu-helpers'
|
||||
# application menu.
|
||||
#
|
||||
# An instance of this class is always available as the `atom.menu` global.
|
||||
#
|
||||
# ## Menu CSON Format
|
||||
#
|
||||
# Here is an example from the [tree-view](https://github.com/atom/tree-view/blob/master/menus/tree-view.cson):
|
||||
#
|
||||
# ```coffee
|
||||
# [
|
||||
# {
|
||||
# 'label': 'View'
|
||||
# 'submenu': [
|
||||
# { 'label': 'Toggle Tree View', 'command': 'tree-view:toggle' }
|
||||
# ]
|
||||
# }
|
||||
# {
|
||||
# 'label': 'Packages'
|
||||
# 'submenu': [
|
||||
# 'label': 'Tree View'
|
||||
# 'submenu': [
|
||||
# { 'label': 'Focus', 'command': 'tree-view:toggle-focus' }
|
||||
# { 'label': 'Toggle', 'command': 'tree-view:toggle' }
|
||||
# { 'label': 'Reveal Active File', 'command': 'tree-view:reveal-active-file' }
|
||||
# { 'label': 'Toggle Tree Side', 'command': 'tree-view:toggle-side' }
|
||||
# ]
|
||||
# ]
|
||||
# }
|
||||
# ]
|
||||
# ```
|
||||
#
|
||||
# Use in your package's menu `.cson` file requires that you place your menu
|
||||
# structure under a `menu` key.
|
||||
#
|
||||
# ```coffee
|
||||
# 'menu': [
|
||||
# {
|
||||
# 'label': 'View'
|
||||
# 'submenu': [
|
||||
# { 'label': 'Toggle Tree View', 'command': 'tree-view:toggle' }
|
||||
# ]
|
||||
# }
|
||||
# ]
|
||||
# ```
|
||||
#
|
||||
# See {::add} for more info about adding menu's directly.
|
||||
module.exports =
|
||||
class MenuManager
|
||||
constructor: ({@resourcePath}) ->
|
||||
|
||||
@@ -59,6 +59,8 @@ loadDependencies = (modulePath, rootPath, rootMetadata, moduleCache) ->
|
||||
if childMetadata?.version
|
||||
try
|
||||
mainPath = require.resolve(childPath)
|
||||
catch error
|
||||
mainPath = null
|
||||
|
||||
if mainPath
|
||||
moduleCache.dependencies.push
|
||||
|
||||
@@ -42,3 +42,9 @@ class NotificationManager
|
||||
@notifications.push(notification)
|
||||
@emitter.emit('did-add-notification', notification)
|
||||
notification
|
||||
|
||||
###
|
||||
Section: Getting Notifications
|
||||
###
|
||||
|
||||
getNotifications: -> @notifications
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
{Emitter} = require 'event-kit'
|
||||
|
||||
# Experimental: This will likely change, do not use.
|
||||
module.exports =
|
||||
class Notification
|
||||
constructor: (@type, @message, @options={}) ->
|
||||
@emitter = new Emitter
|
||||
@timestamp = new Date()
|
||||
@dismissed = true
|
||||
@dismissed = false if @isDismissable()
|
||||
|
||||
onDidDismiss: (callback) ->
|
||||
@emitter.on 'did-dismiss', callback
|
||||
|
||||
getOptions: -> @options
|
||||
|
||||
@@ -20,8 +27,14 @@ class Notification
|
||||
and @getType() == other.getType() \
|
||||
and @getDetail() == other.getDetail()
|
||||
|
||||
isClosable: ->
|
||||
!!@options.closable
|
||||
dismiss: ->
|
||||
return unless @isDismissable() and not @isDismissed()
|
||||
@dismissed = true
|
||||
@emitter.emit 'did-dismiss'
|
||||
|
||||
isDismissed: -> @dismissed
|
||||
|
||||
isDismissable: -> !!@options.dismissable
|
||||
|
||||
getIcon: ->
|
||||
return @options.icon if @options.icon?
|
||||
|
||||
@@ -48,7 +48,7 @@ class PackageManager
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
# Public: Invoke the given callback when all packages have been activated.
|
||||
# Public: Invoke the given callback when all packages have been loaded.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
#
|
||||
@@ -295,12 +295,12 @@ class PackageManager
|
||||
pack = new Package(packagePath, metadata)
|
||||
pack.load()
|
||||
@loadedPackages[pack.name] = pack
|
||||
pack
|
||||
return pack
|
||||
catch error
|
||||
console.warn "Failed to load package.json '#{path.basename(packagePath)}'", error.stack ? error
|
||||
|
||||
else
|
||||
throw new Error("Could not resolve '#{nameOrPath}' to a package path")
|
||||
console.warn "Could not resolve '#{nameOrPath}' to a package path"
|
||||
null
|
||||
|
||||
unloadPackages: ->
|
||||
@unloadPackage(name) for name in _.keys(@loadedPackages)
|
||||
@@ -329,22 +329,25 @@ class PackageManager
|
||||
@packageActivators.push([activator, types])
|
||||
|
||||
activatePackages: (packages) ->
|
||||
@activatePackage(pack.name) for pack in packages
|
||||
atom.config.transact =>
|
||||
@activatePackage(pack.name) for pack in packages
|
||||
@observeDisabledPackages()
|
||||
|
||||
# Activate a single package by name
|
||||
activatePackage: (name) ->
|
||||
if pack = @getActivePackage(name)
|
||||
Q(pack)
|
||||
else
|
||||
pack = @loadPackage(name)
|
||||
else if pack = @loadPackage(name)
|
||||
pack.activate().then =>
|
||||
@activePackages[pack.name] = pack
|
||||
pack
|
||||
else
|
||||
Q.reject(new Error("Failed to load package '#{name}'"))
|
||||
|
||||
# Deactivate all packages
|
||||
deactivatePackages: ->
|
||||
@deactivatePackage(pack.name) for pack in @getLoadedPackages()
|
||||
atom.config.transact =>
|
||||
@deactivatePackage(pack.name) for pack in @getLoadedPackages()
|
||||
@unobserveDisabledPackages()
|
||||
|
||||
# Deactivate the package with the given name
|
||||
|
||||
+42
-26
@@ -9,7 +9,6 @@ EmitterMixin = require('emissary').Emitter
|
||||
Q = require 'q'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
$ = null # Defer require in case this is in the window-less browser process
|
||||
ModuleCache = require './module-cache'
|
||||
ScopedProperties = require './scoped-properties'
|
||||
|
||||
@@ -52,7 +51,7 @@ class Package
|
||||
stylesheets: null
|
||||
stylesheetDisposables: null
|
||||
grammars: null
|
||||
scopedProperties: null
|
||||
settings: null
|
||||
mainModulePath: null
|
||||
resolvedMainModulePath: false
|
||||
mainModule: null
|
||||
@@ -110,7 +109,7 @@ class Package
|
||||
|
||||
getType: -> 'atom'
|
||||
|
||||
getStylesheetType: -> 'bundled'
|
||||
getStyleSheetPriority: -> 0
|
||||
|
||||
load: ->
|
||||
@measure 'loadTime', =>
|
||||
@@ -118,7 +117,7 @@ class Package
|
||||
@loadKeymaps()
|
||||
@loadMenus()
|
||||
@loadStylesheets()
|
||||
@scopedPropertiesPromise = @loadScopedProperties()
|
||||
@settingsPromise = @loadSettings()
|
||||
@requireMainModule() unless @hasActivationCommands()
|
||||
|
||||
catch error
|
||||
@@ -130,7 +129,7 @@ class Package
|
||||
@keymaps = []
|
||||
@menus = []
|
||||
@grammars = []
|
||||
@scopedProperties = []
|
||||
@settings = []
|
||||
|
||||
activate: ->
|
||||
@grammarsPromise ?= @loadGrammars()
|
||||
@@ -144,7 +143,7 @@ class Package
|
||||
else
|
||||
@activateNow()
|
||||
|
||||
Q.all([@grammarsPromise, @scopedPropertiesPromise, @activationDeferred.promise])
|
||||
Q.all([@grammarsPromise, @settingsPromise, @activationDeferred.promise])
|
||||
|
||||
activateNow: ->
|
||||
try
|
||||
@@ -156,7 +155,7 @@ class Package
|
||||
catch e
|
||||
console.warn "Failed to activate package named '#{@name}'", e.stack
|
||||
|
||||
@activationDeferred.resolve()
|
||||
@activationDeferred?.resolve()
|
||||
|
||||
activateConfig: ->
|
||||
return if @configActivated
|
||||
@@ -176,8 +175,9 @@ class Package
|
||||
activateStylesheets: ->
|
||||
return if @stylesheetsActivated
|
||||
|
||||
group = @getStylesheetType()
|
||||
@stylesheetDisposables = new CompositeDisposable
|
||||
|
||||
priority = @getStyleSheetPriority()
|
||||
for [sourcePath, source] in @stylesheets
|
||||
if match = path.basename(sourcePath).match(/[^.]*\.([^.]*)\./)
|
||||
context = match[1]
|
||||
@@ -186,7 +186,7 @@ class Package
|
||||
else
|
||||
context = undefined
|
||||
|
||||
@stylesheetDisposables.add(atom.styles.addStyleSheet(source, {sourcePath, group, context}))
|
||||
@stylesheetDisposables.add(atom.styles.addStyleSheet(source, {sourcePath, priority, context}))
|
||||
@stylesheetsActivated = true
|
||||
|
||||
activateResources: ->
|
||||
@@ -199,20 +199,20 @@ class Package
|
||||
grammar.activate() for grammar in @grammars
|
||||
@grammarsActivated = true
|
||||
|
||||
scopedProperties.activate() for scopedProperties in @scopedProperties
|
||||
@scopedPropertiesActivated = true
|
||||
settings.activate() for settings in @settings
|
||||
@settingsActivated = true
|
||||
|
||||
loadKeymaps: ->
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
@keymaps = (["#{atom.packages.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of packagesCache[@name].keymaps)
|
||||
else
|
||||
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath)]
|
||||
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath) ? {}]
|
||||
|
||||
loadMenus: ->
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
@menus = (["#{atom.packages.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of packagesCache[@name].menus)
|
||||
else
|
||||
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath)]
|
||||
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath) ? {}]
|
||||
|
||||
getKeymapPaths: ->
|
||||
keymapsDirPath = path.join(@path, 'keymaps')
|
||||
@@ -283,22 +283,28 @@ class Package
|
||||
async.each grammarPaths, loadGrammar, -> deferred.resolve()
|
||||
deferred.promise
|
||||
|
||||
loadScopedProperties: ->
|
||||
@scopedProperties = []
|
||||
loadSettings: ->
|
||||
@settings = []
|
||||
|
||||
loadScopedPropertiesFile = (scopedPropertiesPath, callback) =>
|
||||
ScopedProperties.load scopedPropertiesPath, (error, scopedProperties) =>
|
||||
loadSettingsFile = (settingsPath, callback) =>
|
||||
ScopedProperties.load settingsPath, (error, settings) =>
|
||||
if error?
|
||||
console.warn("Failed to load scoped properties: #{scopedPropertiesPath}", error.stack ? error)
|
||||
console.warn("Failed to load package settings: #{settingsPath}", error.stack ? error)
|
||||
else
|
||||
@scopedProperties.push(scopedProperties)
|
||||
scopedProperties.activate() if @scopedPropertiesActivated
|
||||
@settings.push(settings)
|
||||
settings.activate() if @settingsActivated
|
||||
callback()
|
||||
|
||||
deferred = Q.defer()
|
||||
scopedPropertiesDirPath = path.join(@path, 'scoped-properties')
|
||||
fs.list scopedPropertiesDirPath, ['json', 'cson'], (error, scopedPropertiesPaths=[]) ->
|
||||
async.each scopedPropertiesPaths, loadScopedPropertiesFile, -> deferred.resolve()
|
||||
|
||||
if fs.isDirectorySync(path.join(@path, 'scoped-properties'))
|
||||
settingsDirPath = path.join(@path, 'scoped-properties')
|
||||
deprecate("Store package settings files in the `settings` directory instead of `scoped-properties`")
|
||||
else
|
||||
settingsDirPath = path.join(@path, 'settings')
|
||||
|
||||
fs.list settingsDirPath, ['json', 'cson'], (error, settingsPaths=[]) ->
|
||||
async.each settingsPaths, loadSettingsFile, -> deferred.resolve()
|
||||
deferred.promise
|
||||
|
||||
serialize: ->
|
||||
@@ -328,17 +334,17 @@ class Package
|
||||
|
||||
deactivateResources: ->
|
||||
grammar.deactivate() for grammar in @grammars
|
||||
scopedProperties.deactivate() for scopedProperties in @scopedProperties
|
||||
settings.deactivate() for settings in @settings
|
||||
@stylesheetDisposables?.dispose()
|
||||
@activationDisposables?.dispose()
|
||||
@stylesheetsActivated = false
|
||||
@grammarsActivated = false
|
||||
@scopedPropertiesActivated = false
|
||||
@settingsActivated = false
|
||||
|
||||
reloadStylesheets: ->
|
||||
oldSheets = _.clone(@stylesheets)
|
||||
@loadStylesheets()
|
||||
@stylesheetDisposables.dispose()
|
||||
@stylesheetDisposables?.dispose()
|
||||
@stylesheetDisposables = new CompositeDisposable
|
||||
@stylesheetsActivated = false
|
||||
@activateStylesheets()
|
||||
@@ -408,6 +414,16 @@ class Package
|
||||
@activationCommands[selector].push(commands...)
|
||||
|
||||
if @metadata.activationEvents?
|
||||
deprecate """
|
||||
Use `activationCommands` instead of `activationEvents` in your package.json
|
||||
Commands should be grouped by selector as follows:
|
||||
```json
|
||||
"activationCommands": {
|
||||
"atom-workspace": ["foo:bar", "foo:baz"],
|
||||
"atom-text-editor": ["foo:quux"]
|
||||
}
|
||||
```
|
||||
"""
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
for eventName in @metadata.activationEvents
|
||||
@activationCommands['atom-workspace'] ?= []
|
||||
|
||||
@@ -8,7 +8,7 @@ class PaneAxisElement extends HTMLElement
|
||||
detachedCallback: ->
|
||||
@subscriptions.dispose()
|
||||
|
||||
setModel: (@model) ->
|
||||
initialize: (@model) ->
|
||||
@subscriptions.add @model.onDidAddChild(@childAdded.bind(this))
|
||||
@subscriptions.add @model.onDidRemoveChild(@childRemoved.bind(this))
|
||||
@subscriptions.add @model.onDidReplaceChild(@childReplaced.bind(this))
|
||||
@@ -20,14 +20,15 @@ class PaneAxisElement extends HTMLElement
|
||||
@classList.add('horizontal', 'pane-row')
|
||||
when 'vertical'
|
||||
@classList.add('vertical', 'pane-column')
|
||||
this
|
||||
|
||||
childAdded: ({child, index}) ->
|
||||
view = @model.getView(child)
|
||||
view = atom.views.getView(child)
|
||||
@insertBefore(view, @children[index])
|
||||
callAttachHooks(view) # for backward compatibility with SpacePen views
|
||||
|
||||
childRemoved: ({child}) ->
|
||||
view = @model.getView(child)
|
||||
view = atom.views.getView(child)
|
||||
view.remove()
|
||||
|
||||
childReplaced: ({index, oldChild, newChild}) ->
|
||||
|
||||
@@ -39,9 +39,6 @@ class PaneAxis extends Model
|
||||
|
||||
getOrientation: -> @orientation
|
||||
|
||||
getView: (object) ->
|
||||
@container.getView(object)
|
||||
|
||||
getChildren: -> @children.slice()
|
||||
|
||||
getPanes: ->
|
||||
|
||||
@@ -11,15 +11,16 @@ class PaneContainerElement extends HTMLElement
|
||||
PaneContainerView ?= require './pane-container-view'
|
||||
@__spacePenView = new PaneContainerView(this)
|
||||
|
||||
setModel: (@model) ->
|
||||
initialize: (@model) ->
|
||||
@subscriptions.add @model.observeRoot(@rootChanged.bind(this))
|
||||
@__spacePenView.setModel(@model)
|
||||
this
|
||||
|
||||
rootChanged: (root) ->
|
||||
focusedElement = document.activeElement if @hasFocus()
|
||||
@firstChild?.remove()
|
||||
if root?
|
||||
view = @model.getView(root)
|
||||
view = atom.views.getView(root)
|
||||
@appendChild(view)
|
||||
callAttachHooks(view)
|
||||
focusedElement?.focus()
|
||||
@@ -45,7 +46,7 @@ class PaneContainerElement extends HTMLElement
|
||||
y = pointB.y - pointA.y
|
||||
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
|
||||
|
||||
paneView = @model.getView(@model.getActivePane())
|
||||
paneView = atom.views.getView(@model.getActivePane())
|
||||
box = @boundingBoxForPaneView(paneView)
|
||||
|
||||
paneViews = _.toArray(@querySelectorAll('atom-pane'))
|
||||
|
||||
@@ -23,7 +23,7 @@ class PaneContainerView extends View
|
||||
@subscriptions.add @model.onDidChangeActivePaneItem(@onActivePaneItemChanged)
|
||||
|
||||
getRoot: ->
|
||||
view = @model.getView(@model.getRoot())
|
||||
view = atom.views.getView(@model.getRoot())
|
||||
view.__spacePenView ? view
|
||||
|
||||
onActivePaneItemChanged: (activeItem) =>
|
||||
@@ -55,7 +55,7 @@ class PaneContainerView extends View
|
||||
@getActivePaneView()
|
||||
|
||||
getActivePaneView: ->
|
||||
@model.getView(@model.getActivePane()).__spacePenView
|
||||
atom.views.getView(@model.getActivePane()).__spacePenView
|
||||
|
||||
getActivePaneItem: ->
|
||||
@model.getActivePaneItem()
|
||||
@@ -64,7 +64,7 @@ class PaneContainerView extends View
|
||||
@getActivePaneView()?.activeView
|
||||
|
||||
paneForUri: (uri) ->
|
||||
@model.getView(@model.paneForUri(uri)).__spacePenView
|
||||
atom.views.getView(@model.paneForUri(uri)).__spacePenView
|
||||
|
||||
focusNextPaneView: ->
|
||||
@model.activateNextPane()
|
||||
|
||||
+24
-24
@@ -9,7 +9,6 @@ PaneAxisElement = require './pane-axis-element'
|
||||
PaneAxis = require './pane-axis'
|
||||
TextEditor = require './text-editor'
|
||||
TextEditorElement = require './text-editor-element'
|
||||
ViewRegistry = require './view-registry'
|
||||
ItemRegistry = require './item-registry'
|
||||
|
||||
module.exports =
|
||||
@@ -36,7 +35,6 @@ class PaneContainer extends Model
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
@itemRegistry = new ItemRegistry
|
||||
@viewRegistry = params?.viewRegistry ? new ViewRegistry
|
||||
@registerViewProviders()
|
||||
|
||||
@setRoot(params?.root ? new Pane)
|
||||
@@ -58,24 +56,14 @@ class PaneContainer extends Model
|
||||
activePaneId: @activePane.id
|
||||
|
||||
registerViewProviders: ->
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: PaneContainer
|
||||
viewConstructor: PaneContainerElement
|
||||
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: PaneAxis
|
||||
viewConstructor: PaneAxisElement
|
||||
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: Pane
|
||||
viewConstructor: PaneElement
|
||||
|
||||
@viewRegistry.addViewProvider
|
||||
modelConstructor: TextEditor
|
||||
viewConstructor: TextEditorElement
|
||||
|
||||
getView: (object) ->
|
||||
@viewRegistry.getView(object)
|
||||
atom.views.addViewProvider PaneContainer, (model) ->
|
||||
new PaneContainerElement().initialize(model)
|
||||
atom.views.addViewProvider PaneAxis, (model) ->
|
||||
new PaneAxisElement().initialize(model)
|
||||
atom.views.addViewProvider Pane, (model) ->
|
||||
new PaneElement().initialize(model)
|
||||
atom.views.addViewProvider TextEditor, (model) ->
|
||||
new TextEditorElement().initialize(model)
|
||||
|
||||
onDidChangeRoot: (fn) ->
|
||||
@emitter.on 'did-change-root', fn
|
||||
@@ -91,6 +79,9 @@ class PaneContainer extends Model
|
||||
fn(pane) for pane in @getPanes()
|
||||
@onDidAddPane ({pane}) -> fn(pane)
|
||||
|
||||
onDidDestroyPane: (fn) ->
|
||||
@emitter.on 'did-destroy-pane', fn
|
||||
|
||||
onDidChangeActivePane: (fn) ->
|
||||
@emitter.on 'did-change-active-pane', fn
|
||||
|
||||
@@ -112,6 +103,9 @@ class PaneContainer extends Model
|
||||
fn(@getActivePaneItem())
|
||||
@onDidChangeActivePaneItem(fn)
|
||||
|
||||
onWillDestroyPaneItem: (fn) ->
|
||||
@emitter.on 'will-destroy-pane-item', fn
|
||||
|
||||
onDidDestroyPaneItem: (fn) ->
|
||||
@emitter.on 'did-destroy-pane-item', fn
|
||||
|
||||
@@ -193,11 +187,17 @@ class PaneContainer extends Model
|
||||
destroyEmptyPanes: ->
|
||||
pane.destroy() for pane in @getPanes() when pane.items.length is 0
|
||||
|
||||
paneItemDestroyed: (item) ->
|
||||
@emitter.emit 'did-destroy-pane-item', item
|
||||
willDestroyPaneItem: (event) ->
|
||||
@emitter.emit 'will-destroy-pane-item', event
|
||||
|
||||
didAddPane: (pane) ->
|
||||
@emitter.emit 'did-add-pane', pane
|
||||
didDestroyPaneItem: (event) ->
|
||||
@emitter.emit 'did-destroy-pane-item', event
|
||||
|
||||
didAddPane: (event) ->
|
||||
@emitter.emit 'did-add-pane', event
|
||||
|
||||
didDestroyPane: (event) ->
|
||||
@emitter.emit 'did-destroy-pane', event
|
||||
|
||||
# Called by Model superclass when destroyed
|
||||
destroyed: ->
|
||||
|
||||
@@ -43,15 +43,16 @@ class PaneElement extends HTMLElement
|
||||
createSpacePenShim: ->
|
||||
@__spacePenView = new PaneView(this)
|
||||
|
||||
getModel: -> @model
|
||||
|
||||
setModel: (@model) ->
|
||||
initialize: (@model) ->
|
||||
@subscriptions.add @model.onDidActivate(@activated.bind(this))
|
||||
@subscriptions.add @model.observeActive(@activeStatusChanged.bind(this))
|
||||
@subscriptions.add @model.observeActiveItem(@activeItemChanged.bind(this))
|
||||
@subscriptions.add @model.onDidRemoveItem(@itemRemoved.bind(this))
|
||||
@subscriptions.add @model.onDidDestroy(@paneDestroyed.bind(this))
|
||||
@__spacePenView.setModel(@model)
|
||||
this
|
||||
|
||||
getModel: -> @model
|
||||
|
||||
activated: ->
|
||||
@focus()
|
||||
@@ -66,7 +67,7 @@ class PaneElement extends HTMLElement
|
||||
return unless item?
|
||||
|
||||
hasFocus = @hasFocus()
|
||||
itemView = @model.getView(item)
|
||||
itemView = atom.views.getView(item)
|
||||
|
||||
unless @itemViews.contains(itemView)
|
||||
@itemViews.appendChild(itemView)
|
||||
@@ -94,14 +95,14 @@ class PaneElement extends HTMLElement
|
||||
itemView.style.display = 'none'
|
||||
|
||||
itemRemoved: ({item, index, destroyed}) ->
|
||||
if viewToRemove = @model.getView(item)
|
||||
if viewToRemove = atom.views.getView(item)
|
||||
callRemoveHooks(viewToRemove) if destroyed
|
||||
viewToRemove.remove()
|
||||
|
||||
paneDestroyed: ->
|
||||
@subscriptions.dispose()
|
||||
|
||||
getActiveView: -> @model.getView(@model.getActiveItem())
|
||||
getActiveView: -> atom.views.getView(@model.getActiveItem())
|
||||
|
||||
hasFocus: ->
|
||||
this is document.activeElement or @contains(document.activeElement)
|
||||
|
||||
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