Comparar commits
924 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 7ae6cba337 | |||
| a3e85d6758 | |||
| decce0e3a1 | |||
| aa2868efbf | |||
| 7dcafb44f1 | |||
| f9c975bba7 | |||
| 1c6f7b00eb | |||
| fc1709f113 | |||
| 35c2ef09a0 | |||
| dbbf310e36 | |||
| ee1c17d787 | |||
| fe3ea229a2 | |||
| 381ebe1a38 | |||
| 965a65d6f8 | |||
| 25b641125d | |||
| 53aff00218 | |||
| 9f8e1fbb80 | |||
| 5e7a26dc9d | |||
| 7ca6277403 | |||
| 774e86da8d | |||
| 893d349594 | |||
| f7d18154e7 | |||
| 4f5098f0a3 | |||
| e04c6b4732 | |||
| f31cc1b0da | |||
| 3b6711d83d | |||
| 776e8a308c | |||
| d62ac36062 | |||
| 1734182191 | |||
| e0b54d8501 | |||
| 66661f2d10 | |||
| cae5cdc81c | |||
| 8e6dcf43b0 | |||
| 15bb3ee31d | |||
| 7afb25cead | |||
| b0ddab842b | |||
| a2d08547b6 | |||
| a6aa94110c | |||
| 8f5018f925 | |||
| a47feb9dd8 | |||
| 9ef4ea180b | |||
| 24be115cf6 | |||
| d61504873a | |||
| ae7047571f | |||
| 40fdce9c00 | |||
| d3ede06cad | |||
| 31d25209a0 | |||
| 1d2ce26b81 | |||
| 56095187e6 | |||
| 58af226359 | |||
| 88cb7e2f96 | |||
| 728aacd3fb | |||
| 4f56bc32dc | |||
| d16bd0d7eb | |||
| b6fc17e363 | |||
| b6056a44e2 | |||
| 6ce4efa3ce | |||
| 0c0f143f91 | |||
| 2a5ac13e4c | |||
| 6cc6c81493 | |||
| a215cd77ed | |||
| ddad8ef45c | |||
| c1ce1e624d | |||
| d611dbb36a | |||
| 646d8a5966 | |||
| 7be8bd7118 | |||
| e98b43e479 | |||
| c167166add | |||
| 68964f1ca1 | |||
| fbcb152107 | |||
| c51ede98fc | |||
| 51183f4be5 | |||
| bf16527aa6 | |||
| 2cce36694d | |||
| 11fbb33a24 | |||
| 2e5c844d46 | |||
| 0b088e8b72 | |||
| 1479197ffb | |||
| c79c7b7a98 | |||
| dfb72c287b | |||
| 1db983a0a0 | |||
| 3ead596a5d | |||
| b8a2139c05 | |||
| 99af9e2c33 | |||
| b7bd11a883 | |||
| 1ac40b2673 | |||
| 5434a26636 | |||
| 50445a73bd | |||
| ff9c031f57 | |||
| c1ebbf36be | |||
| 8717547db4 | |||
| e99996d5b4 | |||
| 7c4a32fffa | |||
| 196729e6d2 | |||
| db94aa94eb | |||
| f670673baf | |||
| f5bd6a6baf | |||
| 9e20cefd4b | |||
| 3f8d7d54cf | |||
| b5703ff57a | |||
| f97db691c3 | |||
| 41ab48bc6e | |||
| ae1b640725 | |||
| dc49875af9 | |||
| a36454c86c | |||
| 8fa68c488d | |||
| a25cf0a899 | |||
| 6e1efdf2ee | |||
| 8e095d7b5b | |||
| 9899e7f2e3 | |||
| a62a0f4bb7 | |||
| dac792a243 | |||
| 31b3d8f967 | |||
| 55fb816998 | |||
| ce527aea10 | |||
| a7a9301f25 | |||
| 0f551d4b11 | |||
| 35a7bb115d | |||
| 553abc2009 | |||
| 0ad1aeea43 | |||
| 7e52c86095 | |||
| 950338ed22 | |||
| 8ed3b7a250 | |||
| 390c36ca15 | |||
| 1df2e50bbf | |||
| 749dba1ac7 | |||
| a28566a559 | |||
| 64f1c8b80e | |||
| b47f6265c7 | |||
| 9511c952af | |||
| be0877327e | |||
| 3134bfda95 | |||
| 1c177aa206 | |||
| ec65def5d3 | |||
| 3aefa53b33 | |||
| 4fd07a4cf3 | |||
| 03463da729 | |||
| 1cc5ef3479 | |||
| 77f78d0a11 | |||
| 8f98f2368b | |||
| f467e3eed4 | |||
| 3052fe3f3b | |||
| 1bce626324 | |||
| e222998f82 | |||
| 2aca16dc6b | |||
| 653a2623bf | |||
| 03ce9e0ec8 | |||
| 0245ec28eb | |||
| 94f86cb461 | |||
| b4871fddfb | |||
| a598dcc259 | |||
| 918c86476c | |||
| 4d65a220e2 | |||
| 7697f19c3d | |||
| 6ad6409efe | |||
| b6fcc35131 | |||
| bd873dc851 | |||
| 4c2931f6b5 | |||
| 1704c78eea | |||
| bcad8c1b3e | |||
| 81d9193bf4 | |||
| 7514f70434 | |||
| 12a8688a9b | |||
| 0524a724e1 | |||
| 805c7ae301 | |||
| 3f3dabed41 | |||
| 516035a82c | |||
| 08686ee769 | |||
| 5b479ad5f5 | |||
| d4366aa09e | |||
| 3f549bbada | |||
| 1187d50b81 | |||
| a1d4c2a4c7 | |||
| afe386ce40 | |||
| d31669c67f | |||
| 5259a1ced4 | |||
| 437b0decab | |||
| 61ee1be2cb | |||
| 2548891b99 | |||
| 115a7e1dfb | |||
| 5d2be8d5c5 | |||
| 6d08ade20c | |||
| 0043072ecf | |||
| 89c57b6d52 | |||
| f2a08cd178 | |||
| df524e4803 | |||
| b8c4b83653 | |||
| 2df2254227 | |||
| f4d256eef2 | |||
| cb109dc09f | |||
| 919181067a | |||
| 48d252e118 | |||
| 75a07ac722 | |||
| e06bbfac6b | |||
| 4265cfc61e | |||
| 57531d75fe | |||
| 5c1d9a6a2e | |||
| 883009a3bd | |||
| 3ed5e64a01 | |||
| 0fdceb8474 | |||
| 041ec8c7cf | |||
| 07e64152be | |||
| 87d2e51adb | |||
| 30582c69e8 | |||
| 6e34562d94 | |||
| 3da933372f | |||
| 3601baeb80 | |||
| 64b4adf6c8 | |||
| d2d63d3241 | |||
| 4840987082 | |||
| 249a14704b | |||
| cf64d80abe | |||
| 5e511ca6c6 | |||
| c4a547a9ea | |||
| b936e126da | |||
| 5418e74fb9 | |||
| 40a2ed3703 | |||
| 67c8de623d | |||
| bf7c14e6f3 | |||
| 512a50814b | |||
| 3c251dbe56 | |||
| eae33be515 | |||
| a343e4b9f7 | |||
| 5f359a4271 | |||
| ae1dd6e876 | |||
| d1bd2113bf | |||
| c9ae9e11c1 | |||
| b10b8d80ae | |||
| 7f57a094f6 | |||
| b7df08cbdd | |||
| 89dc5f26ad | |||
| 2c60b0463e | |||
| 3093198662 | |||
| 7b8ef2f6e3 | |||
| c56ac70181 | |||
| d77c914fd8 | |||
| 8e91e503c9 | |||
| 97c9f05447 | |||
| 2715bec4c8 | |||
| 45717d7431 | |||
| afd61a369b | |||
| 86082d19e1 | |||
| b7d6825287 | |||
| 1fe13fbad8 | |||
| 1f21e4178d | |||
| aef75238ec | |||
| 419b1ec348 | |||
| bb31af5e8c | |||
| befedac546 | |||
| be0dcb840e | |||
| b521af9b4a | |||
| 61cb22840e | |||
| eaeb5b3b13 | |||
| 466a50ff37 | |||
| 4f2d935a1d | |||
| b19126024a | |||
| 56eb1fc6e4 | |||
| 07a2a6710d | |||
| cbedd221f3 | |||
| d684911fce | |||
| b625965982 | |||
| 9688469501 | |||
| f9cb9b7ea2 | |||
| 6448258f4e | |||
| 9f1a3c6eff | |||
| 21c2bf4861 | |||
| b9753a0785 | |||
| ff27ac5670 | |||
| 720679b41b | |||
| 248843583e | |||
| 1f3ef99390 | |||
| e74b56c50e | |||
| c924d55a26 | |||
| 4964a067d0 | |||
| 264196a11f | |||
| bfa70b4ba6 | |||
| 7e5d554bd8 | |||
| a90039baab | |||
| 55228f9667 | |||
| 6295c2ddc4 | |||
| 5ca6d01911 | |||
| 6d9fed6644 | |||
| 3c8bfb8bc8 | |||
| 00987f3642 | |||
| 6e070ae057 | |||
| ac70bfc456 | |||
| fd0f323666 | |||
| 0e31557abf | |||
| e7c1d20d8e | |||
| e8c8f0de0d | |||
| ea0773e8fc | |||
| 037306a30c | |||
| 9ea94cb6cc | |||
| 97fe09f157 | |||
| 5b149bd41a | |||
| 8a899f2116 | |||
| dfa2f46ced | |||
| 2b2d1d87f7 | |||
| 3784b77b95 | |||
| 7f418e2de4 | |||
| 78da19f479 | |||
| 4e18ebe843 | |||
| 152a8b311f | |||
| 64470a3c7d | |||
| fae035731f | |||
| 446a48ca00 | |||
| ce9b34c9eb | |||
| d1ed176550 | |||
| 652219b8cf | |||
| e6229f6145 | |||
| 9c066d93fa | |||
| e754689014 | |||
| de96de2de1 | |||
| 6d89c893b7 | |||
| 16df6a32d6 | |||
| a337384e7b | |||
| cdb6de05b3 | |||
| 1b262eadaa | |||
| fd5ea8a0b1 | |||
| fe31d2d28a | |||
| 40b66e8eb3 | |||
| 71e83962ac | |||
| 5316d586d1 | |||
| f79039e4f7 | |||
| f4d6b69002 | |||
| 08e6dc20e1 | |||
| 4f14d8a64f | |||
| da53dfc903 | |||
| 875cfefd36 | |||
| b6fb996ceb | |||
| 316559ae09 | |||
| 08d28d7ed4 | |||
| 3a3adf43a4 | |||
| 0951305962 | |||
| 481935c880 | |||
| 8ffcdad89a | |||
| 9e3ce09658 | |||
| 8c5d0775bc | |||
| 36e8b10917 | |||
| b2b048994c | |||
| 6db23e67e8 | |||
| 7872e95561 | |||
| 45eeee9aea | |||
| 9cbc693c77 | |||
| ee9d4ab70e | |||
| 68c3113b75 | |||
| 3a71b0470b | |||
| 421cdb41b9 | |||
| a8538a1361 | |||
| c3cedd2dc9 | |||
| da38218941 | |||
| c700ca0430 | |||
| 0fe3f2d03c | |||
| 65b1e13b83 | |||
| 2acb387446 | |||
| 746273a2ef | |||
| 778beba901 | |||
| 9278920093 | |||
| ece868c9de | |||
| 651ed9b91e | |||
| ac993680db | |||
| 48b33ed07d | |||
| 724953206f | |||
| c4e3b90201 | |||
| a722d1aa36 | |||
| 25e3ae0325 | |||
| e26da5887d | |||
| 31037797e4 | |||
| 2ae7cba452 | |||
| fa3ebc8c0f | |||
| ff36781c98 | |||
| 2f038cbe66 | |||
| f962888b35 | |||
| 6880368a79 | |||
| 13ba6883b4 | |||
| 1e6e804ebb | |||
| 5690d9fe81 | |||
| 6fef8de63e | |||
| e29185ef11 | |||
| c999a6e0e4 | |||
| 2bbf5c7800 | |||
| 273203e4c9 | |||
| 1211680998 | |||
| 84e76556da | |||
| 55881d594b | |||
| 6f0882a098 | |||
| dda465d08a | |||
| 124c517056 | |||
| 6fa6863244 | |||
| 0ad26c337a | |||
| 353eb27d2e | |||
| 6edb0b7a3d | |||
| cd5f0c0047 | |||
| 5716c7c574 | |||
| ce30299122 | |||
| 9b5593d020 | |||
| 4d642b91ef | |||
| 8b4cff474f | |||
| 73ce81d597 | |||
| 09e4c585aa | |||
| 2c5af98cca | |||
| cbe07b49aa | |||
| aa557a7bdf | |||
| 65cafdda03 | |||
| 9a18ff5954 | |||
| d2bc7ab192 | |||
| bf7d2defd6 | |||
| c4e4429744 | |||
| bfc382c398 | |||
| 795399e184 | |||
| 37bdfb716b | |||
| 405afca1c6 | |||
| 7627e0b0f0 | |||
| 25d2206471 | |||
| 2d96444e21 | |||
| f5c3bdb845 | |||
| 22b932ebee | |||
| ad157fe423 | |||
| 50a6d251d6 | |||
| f3d36a9726 | |||
| c2b8cedef1 | |||
| 314833bbac | |||
| e643fe7e7d | |||
| 0d8a05bdb1 | |||
| 21fd2b8f1d | |||
| c7461f476e | |||
| 7410f9a90d | |||
| 3d98f66330 | |||
| 8e65d30a84 | |||
| b4977ff617 | |||
| d397001c33 | |||
| bd7de18c7a | |||
| 9ca506de4b | |||
| 626964f15b | |||
| 532f119b9d | |||
| 187cf2a710 | |||
| c058483422 | |||
| a83a6e5127 | |||
| 57e6419d1d | |||
| 9b7547cbe0 | |||
| e74dfe3438 | |||
| fe82e3e30f | |||
| b000e8e4a2 | |||
| 64c82f1c87 | |||
| 0ad2730353 | |||
| 6017b73acf | |||
| 0334177696 | |||
| 54cec0a5ff | |||
| c5fa2bf12d | |||
| bc8a1756f3 | |||
| 3f01e2f748 | |||
| 7dfe829fc8 | |||
| c87bc57f9e | |||
| 89bd241a78 | |||
| d15fd34f7a | |||
| a118cdd32b | |||
| 3a2de9c698 | |||
| c60e5d90fd | |||
| e9bff37e06 | |||
| 695f8da3c3 | |||
| ea5c5c9e84 | |||
| 4f9108980f | |||
| 8148e4e50d | |||
| f07a832c83 | |||
| 070d239f41 | |||
| 9b02055db9 | |||
| 0162247bd7 | |||
| 9001d34ddf | |||
| cbcc30b384 | |||
| ce9fe90217 | |||
| 7a9278e6a7 | |||
| 01622140e3 | |||
| e44027b186 | |||
| d53f97ecfe | |||
| f3efd7d60b | |||
| 8d25da9474 | |||
| 1aee276b45 | |||
| 191bc115cf | |||
| 63488997ee | |||
| a22480d857 | |||
| 757ae6de39 | |||
| cfc08e8b98 | |||
| c8e9282557 | |||
| a36163ce86 | |||
| e3d1a6aef8 | |||
| 7d8256d343 | |||
| bf9f8597a7 | |||
| 9f2c8c1756 | |||
| 0ae8765a8a | |||
| 308960309d | |||
| b8ac8516fe | |||
| 3f1ce617a7 | |||
| 10e609ba27 | |||
| 6cae6981d8 | |||
| bff396ab1a | |||
| 7f442d045b | |||
| 8918eb4758 | |||
| 628ea72943 | |||
| fc2830bacb | |||
| b5bff9f8b8 | |||
| 5e2181e665 | |||
| b0e91f8b33 | |||
| 635af7f838 | |||
| e537080b64 | |||
| f2c7d171bf | |||
| 7a4a85cb20 | |||
| 2952f4c2ad | |||
| ce668e7139 | |||
| 917b223c6c | |||
| e3302b3f73 | |||
| 38a347ddab | |||
| e3dbd412e1 | |||
| fc9a11959c | |||
| 71155abf57 | |||
| d5458c1865 | |||
| 56af2ca4d7 | |||
| f30c56c237 | |||
| cc1e6e2a1f | |||
| d7c98cb394 | |||
| 4ff5f96fd4 | |||
| 1c1c3617e9 | |||
| bb9d67a1b1 | |||
| 187e264445 | |||
| 493cd24059 | |||
| 3c766d87c2 | |||
| f360ca2cb7 | |||
| ba8bd80173 | |||
| 6102143faf | |||
| 3eadc61a3b | |||
| 2bef7e26d7 | |||
| 7d655bf840 | |||
| 42c4dc6937 | |||
| a4059110f9 | |||
| 952c96d03b | |||
| 4c73f4e968 | |||
| 5f36406b52 | |||
| 385cf0f3df | |||
| e70ad97273 | |||
| 0b7bf34a0f | |||
| 713bce7f0b | |||
| 534704a32c | |||
| 37241a7919 | |||
| 333c5b66d1 | |||
| a47d55f016 | |||
| 58c55cdf81 | |||
| 50a616d91c | |||
| a2be86d15a | |||
| 73f8c28add | |||
| d015793851 | |||
| 0b5b741db4 | |||
| aeac32ae47 | |||
| fab60e7faa | |||
| 6296665f46 | |||
| 7882ac60d8 | |||
| 4fa0b6e783 | |||
| 3a8ddc0cd6 | |||
| 3803b473c5 | |||
| 93d993d876 | |||
| 2b3a3ac3c0 | |||
| c8b2e6ed2a | |||
| 58fa414c21 | |||
| 8872b0bc9b | |||
| c77a6b10de | |||
| f86280a77b | |||
| 65ae582d96 | |||
| 5694f9c703 | |||
| 6c4d1be004 | |||
| 9cfa46ea37 | |||
| 11d5dfee3a | |||
| 864f61c430 | |||
| ca164a0b0b | |||
| e011becc1a | |||
| 25f5717ccf | |||
| 3f0640f4c3 | |||
| 65e8de9db8 | |||
| c1ed25d5dc | |||
| f731769afd | |||
| c466cef7d1 | |||
| b4cb92af99 | |||
| 5e7cbbf506 | |||
| 397e0a8ac2 | |||
| 111b5d1fbe | |||
| b2e86c80c4 | |||
| b77ea04056 | |||
| ba94f38166 | |||
| 7cdaaf2f78 | |||
| 6caf60bd6b | |||
| 19c7086200 | |||
| 1519dda294 | |||
| a7efca8bb4 | |||
| dbe15f7dda | |||
| c81a6737ad | |||
| 5b0d974b43 | |||
| 2b73dff0f4 | |||
| adf0ff0a67 | |||
| c79ef0473d | |||
| d51b955e09 | |||
| 774d7ec0af | |||
| d6f4b00e16 | |||
| 9d81df8670 | |||
| 14a430b939 | |||
| 07de4a70a1 | |||
| eb84ac829b | |||
| b8db56a77b | |||
| 1036f16d1e | |||
| 5ed1cfc259 | |||
| ce5c29fb47 | |||
| f0fd48202c | |||
| d5eb8c21b2 | |||
| 76b9982e04 | |||
| ca7f11f7d0 | |||
| 1c1ace90db | |||
| bdd605e85b | |||
| e1b4b921ba | |||
| ab1ede5fe6 | |||
| 5e6d91d66c | |||
| dbd271f70a | |||
| 527ada47f9 | |||
| afb70d0a95 | |||
| b5f910ad06 | |||
| e412371b88 | |||
| 7b4bc16531 | |||
| e6df30e94c | |||
| d9ba9262bf | |||
| c4be32a5dd | |||
| 0a32f6b5f0 | |||
| f9fe5efbb0 | |||
| 87e723e33b | |||
| 3f0302b256 | |||
| 88d024e73b | |||
| 47a2e57633 | |||
| e7acbb314e | |||
| d6a4c70929 | |||
| 839cad0c2a | |||
| d3845db403 | |||
| 3d68bdf126 | |||
| 0d190d2cd4 | |||
| 4afae028ec | |||
| 5165f0df88 | |||
| 5b7b3501a6 | |||
| c3937d0c4c | |||
| 6e27208c5c | |||
| 91342db0ba | |||
| 8f7123ae12 | |||
| 3a22b3d4b8 | |||
| 919ca82ccd | |||
| d35baac054 | |||
| 9302242299 | |||
| ed90a78ea5 | |||
| 9aa2df7cee | |||
| 41ea18a8f1 | |||
| 5cf37fd13e | |||
| 3e12695914 | |||
| ed1c8897ec | |||
| 75eb0182e9 | |||
| 554165ca48 | |||
| 5a5cb869e2 | |||
| a649d75ab8 | |||
| 255cdbb60a | |||
| bd4e56fd08 | |||
| 5246d784db | |||
| e945b83318 | |||
| 38bd996996 | |||
| 8f3a72e11b | |||
| ddc62efb44 | |||
| 8f08e497a0 | |||
| 8048f8af5f | |||
| 4fc4e36902 | |||
| c66d3fdba0 | |||
| 9b49c2f987 | |||
| bceed13606 | |||
| d99c9edc43 | |||
| 31306a3243 | |||
| 67de17e0c3 | |||
| 3371252656 | |||
| a7e9037e5b | |||
| b3e376ce7c | |||
| d24b664873 | |||
| b8394830a0 | |||
| 7d76105530 | |||
| bbe399196f | |||
| 8c6cdf7358 | |||
| f71bb9349b | |||
| 6bb260140b | |||
| 88aec85f92 | |||
| 61cdee9743 | |||
| 15c3efa6e4 | |||
| a1835efb4e | |||
| 5e0f132d33 | |||
| 2c7c4c95f2 | |||
| 81f115d3db | |||
| c4f872acff | |||
| b3dbb18889 | |||
| 02a278d80c | |||
| c7954a4c5e | |||
| 61fff23be2 | |||
| 7070ed8ae4 | |||
| 101b18e408 | |||
| f0bd3b1c20 | |||
| 921bf8501f | |||
| 594a2d201b | |||
| cb0ba55871 | |||
| 27bcf046b1 | |||
| 44f19610b6 | |||
| a1d2e253ea | |||
| a961a8f644 | |||
| 86b7fec0bb | |||
| 6060e0d8a9 | |||
| c160601a9d | |||
| 56a1ecf6c1 | |||
| 648441ee5c | |||
| 03f0e084e1 | |||
| ab57dc840f | |||
| 2ff5309d54 | |||
| a308903735 | |||
| b6cb604330 | |||
| fb557e9b90 | |||
| 3180ab067c | |||
| 4b7d982eb4 | |||
| fbabc6f455 | |||
| fa759d8128 | |||
| e9ed45671f | |||
| 8cc871f326 | |||
| 3651adbefd | |||
| ff70ded25b | |||
| 244c06b524 | |||
| e7309b254c | |||
| 0cdce9c665 | |||
| 7a10bf1c33 | |||
| a6d5a4ab5d | |||
| 68f3c98872 | |||
| 0b8c0cc431 | |||
| d9eaf8d334 | |||
| 8d29ec4116 | |||
| 806ff4e141 | |||
| 4b0ddbf2ab | |||
| 1ea54f8c92 | |||
| 31cb4c58c2 | |||
| b9bffc32b0 | |||
| b267a781da | |||
| 6f7209c68b | |||
| fb6782ef31 | |||
| fae8aafc17 | |||
| ba38dddf4d | |||
| 0a4600409a | |||
| 706e4476d5 | |||
| c113a0a217 | |||
| ef05278537 | |||
| 1254425ba8 | |||
| e3641286e7 | |||
| 3a03f470c7 | |||
| 4ea44d9612 | |||
| 15c2540c29 | |||
| 112f90979c | |||
| cbe73fd916 | |||
| 3ea28c8ed6 | |||
| 5a219a9087 | |||
| 11eae4d5db | |||
| fe4016a49d | |||
| 0b786427f4 | |||
| 4900dc6bcd | |||
| 31b06b2e47 | |||
| cf6d83a896 | |||
| 637410a8c5 | |||
| 084e4ab830 | |||
| 5a53b34697 | |||
| 8f3b76d3c9 | |||
| f5df111b5c | |||
| 1d31a10dc4 | |||
| db61de6cf3 | |||
| c75d36ef93 | |||
| bb2527bbb8 | |||
| eb31c6c85f | |||
| 546f81f2d0 | |||
| 7bb6cd99eb | |||
| 3dbdaee25c | |||
| b458de0f2d | |||
| 240747ed76 | |||
| 8b5fd64dd4 | |||
| 1c514bdc6b | |||
| f4d9abc789 | |||
| e5197f6f0f | |||
| 8f57246571 | |||
| 7658107e3b | |||
| c33227830e | |||
| 43f2153c86 | |||
| 084d84660a | |||
| 4120b34d22 | |||
| c4a0bce92f | |||
| 858c18114b | |||
| 91f9302fc4 | |||
| 4f3bf04668 | |||
| 11c9417e8d | |||
| db141d9d7f | |||
| 5624596c88 | |||
| cda7ca047c | |||
| ac25ad3985 | |||
| 1bf4e7ab96 | |||
| 49587ace05 | |||
| 54fb06d4b0 | |||
| 8f81b5dc63 | |||
| d5e1649607 | |||
| e2c1f6c0e2 | |||
| 8ec7d1273c | |||
| 7ffc5cc02b | |||
| aac27db552 | |||
| 03acb1c40a | |||
| 5eb332042e | |||
| 66943c4820 | |||
| 4ed9e34893 | |||
| 4f4da78e54 | |||
| 832dfd057e | |||
| dd74280146 | |||
| a7d1a68fb8 | |||
| 6b8b454625 | |||
| 5c5b7df70d | |||
| 7d3abda86f | |||
| 7f824ffbb3 | |||
| 0b7475a4c1 | |||
| cf62d3212c | |||
| b260cbb43a | |||
| 1367f08de8 | |||
| 27b02a7981 | |||
| e62ae02c00 | |||
| 233402dd33 | |||
| 69821b7a6b | |||
| efcffe5205 | |||
| 802e651b6e | |||
| 0e8b951050 | |||
| 8ef97bd78e | |||
| 6749988de1 | |||
| 4a26f8f28b | |||
| a4ee412e96 | |||
| 4f655d7de5 | |||
| 33c02ef3e1 | |||
| aa4749f175 | |||
| 6ace49b0e8 | |||
| 9cf642e910 | |||
| 2990f36595 | |||
| 032fc86a4d | |||
| 868cbb680c | |||
| 98d2aaf10e | |||
| f7dead17c0 | |||
| f3168b2672 | |||
| e8c62b501f | |||
| 6ff2b2a01e | |||
| 960285a270 | |||
| 17cd979299 | |||
| b5846f9755 | |||
| dd39ffdf3b | |||
| 368b871270 | |||
| 9c06b4d344 | |||
| f48241bc5e | |||
| a7b94e1709 | |||
| 3d2dedb49f | |||
| dd5ab8098e | |||
| f5b833c49c | |||
| ba032be402 | |||
| a96a448063 | |||
| faeed9f604 | |||
| 0a8f2422d3 | |||
| 24dbe19a82 | |||
| 7d8901072c | |||
| 848a4e2052 | |||
| e8090b16f3 | |||
| 950964eee3 | |||
| b403f76d81 | |||
| 8f2cdae0eb | |||
| fa4b3c8dea | |||
| e76bbc0f13 | |||
| c9a377d4ac | |||
| c7e308bca0 | |||
| 5193e6e46b | |||
| 66628e8c52 | |||
| bec65cf2ac | |||
| 606b249430 | |||
| 8bc1b7e955 | |||
| 2ceccf5239 | |||
| ad8bd98c9a | |||
| 6c4e138ec0 | |||
| 9ad1021c2d | |||
| c03dec2783 | |||
| 9d92a27ccf | |||
| b652dc8fd8 | |||
| c1929540a3 | |||
| 1601423f30 | |||
| 1de2c14e50 | |||
| c1907054b7 | |||
| 5f524c1181 | |||
| b897603b66 | |||
| 0e5c530006 | |||
| 4a60b5787a | |||
| 88cc69f87a | |||
| 42e91defb9 | |||
| aeb5a84696 | |||
| 228836447c | |||
| 832cc40a7f | |||
| d89b4534f1 | |||
| 725f6f7cf2 | |||
| b760d3e4fc | |||
| 1d634e471e | |||
| babbdbf9e5 | |||
| e9d820e8a8 | |||
| 16e05347a7 | |||
| 2574ee5936 | |||
| 38c25feee0 | |||
| a15bb260c0 | |||
| 6b833043db | |||
| b30a2c9442 | |||
| 3eb99c9391 | |||
| 10636b96bc | |||
| b5ac7c89a3 | |||
| 01298bb470 | |||
| 3bd7bfcbf1 | |||
| 3e94c0be22 | |||
| db0cce6234 | |||
| f3d4cbbd8f | |||
| 81df4ed238 | |||
| 7b756ec3f3 | |||
| 0d95718d1f | |||
| 1da23e8d04 | |||
| 43792d019a | |||
| ec0b4a2dc6 | |||
| 1083136dec |
+1
-1
@@ -1,6 +1,7 @@
|
||||
*.swp
|
||||
*~
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.project
|
||||
.svn
|
||||
.nvm-version
|
||||
@@ -12,4 +13,3 @@ debug.log
|
||||
docs/output
|
||||
docs/includes
|
||||
spec/fixtures/evil-files/
|
||||
/apm
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[submodule "vendor/apm"]
|
||||
path = vendor/apm
|
||||
url = https://github.com/atom/apm.git
|
||||
@@ -1,2 +1 @@
|
||||
ca =
|
||||
cache = ~/.atom/.npm
|
||||
|
||||
+76
-47
@@ -1,77 +1,106 @@
|
||||
# :tada: Contributing to Atom :tada:
|
||||
# Contributing to Atom
|
||||
|
||||
These are just guidelines, not rules, use your best judgement and feel free
|
||||
to propose changes to this document in a pull request.
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
## Issues
|
||||
* Include screenshots and animated GIFs whenever possible, they are immensely
|
||||
helpful.
|
||||
* Include the behavior you expected to happen and other places you've seen
|
||||
that behavior such as Emacs, vi, Xcode, etc.
|
||||
* Check the Console app for stack traces to include if reporting a crash.
|
||||
* Check the Dev tools (`alt-cmd-i`) for errors and stack traces to include.
|
||||
The following is a set of guidelines for contributing to Atom and its packages,
|
||||
which are hosted in the [Atom Organization](https://github.com/atom) on GitHub.
|
||||
If you're unsure which package is causing your problem or if you're having an
|
||||
issue with Atom core, please open an issue on the [main atom repository](https://github.com/atom/atom/issues).
|
||||
These are just guidelines, not rules, use your best judgement and feel free to
|
||||
propose changes to this document in a pull request.
|
||||
|
||||
## Submitting Issues
|
||||
|
||||
* Include the version of Atom you are using and the OS.
|
||||
* Include screenshots and animated GIFs whenever possible; they are immensely
|
||||
helpful.
|
||||
* Include the behavior you expected and other places you've seen that behavior
|
||||
such as Emacs, vi, Xcode, etc.
|
||||
* Check the dev tools (`alt-cmd-i`) for errors to include. If the dev tools
|
||||
are open _before_ the error is triggered, a full stack trace for the error
|
||||
will be logged. If you can reproduce the error, use this approach to get the
|
||||
full stack trace and include it in the issue.
|
||||
* On Mac, check Console.app for stack traces to include if reporting a crash.
|
||||
* Perform a cursory search to see if a similar issue has already been submitted.
|
||||
|
||||
### Package Repositories
|
||||
|
||||
This is the repository for the core Atom editor only. Atom comes bundled with
|
||||
many packages and themes that are stored in other repos under the
|
||||
[atom organization](https://github.com/atom) such as [tabs](https://github.com/atom/tabs),
|
||||
[Atom organization](https://github.com/atom) such as
|
||||
[tabs](https://github.com/atom/tabs),
|
||||
[find-and-replace](https://github.com/atom/find-and-replace),
|
||||
[language-javascript](https://github.com/atom/language-javascript),
|
||||
and [atom-light-ui](http://github.com/atom/atom-light-ui).
|
||||
[language-javascript](https://github.com/atom/language-javascript), and
|
||||
[atom-light-ui](http://github.com/atom/atom-light-ui).
|
||||
|
||||
If you think you know which package is causing the issue you are reporting, feel
|
||||
free to open up the issue in that specific repository instead. When in doubt
|
||||
just open the issue here but be aware that it may get closed here and reopened
|
||||
in the proper package's repository.
|
||||
For more information on how to work with Atom's official packages, see
|
||||
[Contributing to Atom Packages](https://atom.io/docs/latest/contributing-to-packages.html)
|
||||
|
||||
## Pull Requests
|
||||
* Include screenshots and animated GIFs whenever possible.
|
||||
* Follow the [CoffeeScript](#coffeescript-styleguide),
|
||||
[JavaScript](https://github.com/styleguide/javascript),
|
||||
and [CSS](https://github.com/styleguide/css) styleguides
|
||||
* Include thoughtfully worded [Jasmine](http://pivotal.github.com/jasmine)
|
||||
specs
|
||||
* Avoid placing files in `vendor`. 3rd-party packages should be added as a
|
||||
`package.json` dependency.
|
||||
* Files end with a newline.
|
||||
* Requires should be in the following order:
|
||||
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Follow the [CoffeeScript](#coffeescript-styleguide),
|
||||
[JavaScript](https://github.com/styleguide/javascript),
|
||||
and [CSS](https://github.com/styleguide/css) styleguides.
|
||||
* Include thoughtfully-worded, well-structured
|
||||
[Jasmine](http://jasmine.github.io/) specs.
|
||||
* Document new code based on the
|
||||
[Documentation Styleguide](#documentation-styleguide)
|
||||
* End files with a newline.
|
||||
* Place requires in the following order:
|
||||
* Built in Node Modules (such as `path`)
|
||||
* Built in Atom and Atom Shell Modules (such as `atom`, `shell`)
|
||||
* Local Modules (using relative paths)
|
||||
* Class variables and methods should be in the following order:
|
||||
* Class methods (methods starting with a `@`)
|
||||
* Instance methods
|
||||
* Beware of platform differences
|
||||
* Place class properties in the following order:
|
||||
* Class methods and properties (methods starting with a `@`)
|
||||
* Instance methods and properties
|
||||
* Avoid platform-dependent code:
|
||||
* Use `require('atom').fs.getHomeDirectory()` to get the home directory.
|
||||
* Use `path.join()` to concatenate filenames.
|
||||
* Temporary directory is not `/tmp` on Windows, use `os.tmpdir()` when
|
||||
possible
|
||||
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
|
||||
temporary directory.
|
||||
|
||||
## Git Commit Messages
|
||||
* Use the present tense
|
||||
* Reference issues and pull requests liberally
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :lipstick: when improving the format/structure of the code
|
||||
* :racehorse: when improving performance
|
||||
* :non-potable_water: when plugging memory leaks
|
||||
* :memo: when writing docs
|
||||
* :penguin: when fixing something on Linux
|
||||
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :lipstick: `:lipstick:` when improving the format/structure of the code
|
||||
* :racehorse: `:racehorse:` when improving performance
|
||||
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
|
||||
* :memo: `:memo:` when writing docs
|
||||
* :penguin: `:penguin:` when fixing something on Linux
|
||||
* :apple: `:apple:` when fixing something on Mac OS
|
||||
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
|
||||
* :bug: `:bug:` when fixing a bug
|
||||
* :fire: `:fire:` when removing code or files
|
||||
* :green_heart: `:green_heart:` when fixing the CI build
|
||||
* :white_check_mark: `:white_check_mark:` when adding tests
|
||||
* :lock: `:lock:` when dealing with security
|
||||
|
||||
## CoffeeScript Styleguide
|
||||
|
||||
* Set parameter defaults without spaces around the equal sign
|
||||
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
|
||||
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
|
||||
* Use parentheses if it improves code clarity.
|
||||
* Prefer alphabetic keywords to symbolic keywords:
|
||||
* `a is b` instead of `a == b`
|
||||
* Avoid spaces inside the curly-braces of hash literals:
|
||||
* `{a: 1, b: 2}` instead of `{ a: 1, b: 2 }`
|
||||
* Include a single line of whitespace between methods.
|
||||
|
||||
## Documentation Styleguide
|
||||
|
||||
* Use [TomDoc](http://tomdoc.org).
|
||||
* Use [Markdown](https://daringfireball.net/projects/markdown).
|
||||
* Reference classes with `{ClassName}`.
|
||||
* Reference instance methods with `{ClassName::methodName}`.
|
||||
* Reference class methods with `{ClassName.methodName}`.
|
||||
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
|
||||
style notation.
|
||||
* Reference methods and classes in markdown with the custom `{}` notation:
|
||||
* Reference classes with `{ClassName}`
|
||||
* Reference instance methods with `{ClassName::methodName}`
|
||||
* Reference class methods with `{ClassName.methodName}`
|
||||
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
|
||||
style notation.
|
||||
|
||||
### Example
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Copyright 2014 GitHub, Inc.
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+9
-5
@@ -1,8 +1,8 @@
|
||||
# Atom — The hackable editor
|
||||

|
||||
|
||||

|
||||
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.
|
||||
|
||||
Check out our [guides and API documentation](https://atom.io/docs/latest).
|
||||
Visit [atom.io](https://atom.io) to learn more.
|
||||
|
||||
## Installing
|
||||
|
||||
@@ -12,6 +12,10 @@ Atom will automatically update when a new release is available.
|
||||
|
||||
## Building
|
||||
|
||||
Follow the instructions in the [build docs][building].
|
||||
* [Linux](docs/build-instructions/linux.md)
|
||||
* [OS X](docs/build-instructions/os-x.md)
|
||||
* [FreeBSD](docs/build-instructions/freebsd.md)
|
||||
* [Windows](docs/build-instructions/windows.md)
|
||||
|
||||
[building]: https://github.com/atom/atom/blob/master/docs/building-atom.md
|
||||
## Developing
|
||||
Check out the [guides](https://atom.io/docs/latest) and the [API reference](https://atom.io/docs/api).
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
This folder is where [apm](https://github.com/atom/apm) is installed to so that
|
||||
it is bundled with Atom.
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "atom-bundled-apm",
|
||||
"description": "Atom's bundled APM",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.68.0"
|
||||
}
|
||||
}
|
||||
+17
-9
@@ -1,17 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "`uname`" == 'Darwin' ]; then
|
||||
if [ "$(uname)" == 'Darwin' ]; then
|
||||
OS='Mac'
|
||||
elif [ "`expr substr $(uname -s) 1 5`" == 'Linux' ]; then
|
||||
elif [ "$(expr substr $(uname -s) 1 5)" == 'Linux' ]; then
|
||||
OS='Linux'
|
||||
elif [ "`expr substr $(uname -s) 1 10`" == 'MINGW32_NT' ]; then
|
||||
elif [ "$(expr substr $(uname -s) 1 10)" == 'MINGW32_NT' ]; then
|
||||
OS='Cygwin'
|
||||
else
|
||||
echo "Your platform (`uname -a`) is not supported."
|
||||
echo "Your platform ($(uname -a)) is not supported."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while getopts ":wtfvhs-:" opt; do
|
||||
while getopts ":wtfvh-:" opt; do
|
||||
case "$opt" in
|
||||
-)
|
||||
case "${OPTARG}" in
|
||||
@@ -66,17 +66,25 @@ if [ $OS == 'Mac' ]; then
|
||||
open -a "$ATOM_PATH/$ATOM_APP_NAME" -n --args --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
fi
|
||||
elif [ $OS == 'Linux' ]; then
|
||||
SCRIPT=`readlink -f "$0"`
|
||||
USR_DIRECTORY=`readlink -f $(dirname $SCRIPT)/..`
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
USR_DIRECTORY=$(readlink -f $(dirname $SCRIPT)/..)
|
||||
ATOM_PATH="$USR_DIRECTORY/share/atom/atom"
|
||||
|
||||
[ -x "$ATOM_PATH" ] || ATOM_PATH='/tmp/atom-build/Atom/atom'
|
||||
: ${TMPDIR:=/tmp}
|
||||
|
||||
[ -x "$ATOM_PATH" ] || ATOM_PATH="$TMPDIR/atom-build/Atom/atom"
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
"$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
exit $?
|
||||
else
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > /dev/null 2>&1 &
|
||||
(
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$TMPDIR/atom-nohup.out" 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
cat "$TMPDIR/atom-nohup.out"
|
||||
exit $?
|
||||
fi
|
||||
) &
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -36,35 +36,23 @@ module.exports = (grunt) ->
|
||||
grunt.log.write = (args...) -> grunt.log
|
||||
|
||||
[major, minor, patch] = packageJson.version.split('.')
|
||||
tmpDir = os.tmpdir()
|
||||
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
if process.platform is 'win32'
|
||||
appName = 'Atom'
|
||||
tmpDir = os.tmpdir()
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
|
||||
installDir = path.join(process.env.ProgramFiles, appName)
|
||||
else if process.platform is 'darwin'
|
||||
appName = 'Atom.app'
|
||||
tmpDir = '/tmp'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
contentsDir = path.join(shellAppDir, 'Contents')
|
||||
appDir = path.join(contentsDir, 'Resources', 'app')
|
||||
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
|
||||
installDir = path.join('/Applications', appName)
|
||||
else
|
||||
appName = 'Atom'
|
||||
tmpDir = '/tmp'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
|
||||
installDir = process.env.INSTALL_PREFIX ? '/usr/local'
|
||||
|
||||
coffeeConfig =
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"grunt-cson": "0.8.0",
|
||||
"grunt-download-atom-shell": "git+https://atom-bot:467bac80a0017b96fb5be5cfc686f5e0cc607b10@github.com/atom/grunt-download-atom-shell#v0.6.1",
|
||||
"grunt-download-atom-shell": "~0.8.0",
|
||||
"grunt-lesslint": "0.13.0",
|
||||
"grunt-markdown": "~0.4.0",
|
||||
"grunt-peg": "~1.1.0",
|
||||
@@ -26,7 +26,9 @@
|
||||
"harmony-collections": "~0.3.8",
|
||||
"json-front-matter": "~0.1.3",
|
||||
"legal-eagle": "~0.4.0",
|
||||
"minidump": "0.5.x",
|
||||
"minidump": "~0.6",
|
||||
"read-package-json": "1.1.8",
|
||||
"normalize-package-data": "0.2.12",
|
||||
"rcedit": "~0.1.2",
|
||||
"request": "~2.27.0",
|
||||
"rimraf": "~2.2.2",
|
||||
|
||||
@@ -5,7 +5,7 @@ module.exports = (grunt) ->
|
||||
{rm} = require('./task-helpers')(grunt)
|
||||
|
||||
grunt.registerTask 'partial-clean', 'Delete some of the build files', ->
|
||||
tmpdir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
|
||||
tmpdir = os.tmpdir()
|
||||
|
||||
rm grunt.config.get('atom.buildDir')
|
||||
rm require('../src/coffee-cache').cacheDir
|
||||
|
||||
@@ -143,7 +143,7 @@ downloadFileFromRepo = ({repo, file}, callback) ->
|
||||
|
||||
downloadIncludes = (callback) ->
|
||||
includes = [
|
||||
{repo: 'atom-keymap', file: 'src/keymap.coffee'}
|
||||
{repo: 'atom-keymap', file: 'src/keymap-manager.coffee'}
|
||||
{repo: 'atom-keymap', file: 'src/key-binding.coffee'}
|
||||
{repo: 'first-mate', file: 'src/grammar.coffee'}
|
||||
{repo: 'first-mate', file: 'src/grammar-registry.coffee'}
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = (grunt) ->
|
||||
|
||||
licenseText = getLicenseText(dependencyLicenses)
|
||||
if mode is 'save'
|
||||
targetPath = path.join(grunt.config.get('atom.appDir'), 'LICENSE')
|
||||
targetPath = path.join(grunt.config.get('atom.appDir'), 'LICENSE.md')
|
||||
fs.writeFileSync(targetPath, licenseText)
|
||||
else
|
||||
console.log licenseText
|
||||
@@ -26,7 +26,7 @@ module.exports = (grunt) ->
|
||||
getLicenseText = (dependencyLicenses) ->
|
||||
{keys} = require 'underscore-plus'
|
||||
text = """
|
||||
Copyright 2014 GitHub, Inc.
|
||||
#{fs.readFileSync('LICENSE.md', 'utf8')}
|
||||
|
||||
This application bundles the following third-party packages in accordance
|
||||
with the following licenses:\n\n
|
||||
|
||||
@@ -13,9 +13,15 @@ module.exports = (grunt) ->
|
||||
grunt.registerTask 'mkdeb', 'Create debian package', ->
|
||||
done = @async()
|
||||
|
||||
if process.arch is 'ia32'
|
||||
arch = 'i386'
|
||||
else if process.arch is 'x64'
|
||||
arch = 'amd64'
|
||||
else
|
||||
return done("Unsupported arch #{process.arch}")
|
||||
|
||||
{name, version, description} = grunt.file.readJSON('package.json')
|
||||
section = 'devel'
|
||||
arch = 'amd64'
|
||||
maintainer = 'GitHub <atom@github.com>'
|
||||
data = {name, version, description, section, arch, maintainer}
|
||||
|
||||
@@ -27,5 +33,5 @@ module.exports = (grunt) ->
|
||||
buildDir = grunt.config.get('atom.buildDir')
|
||||
|
||||
cmd = path.join('script', 'mkdeb')
|
||||
args = [version, control, desktop, icon, buildDir]
|
||||
args = [version, arch, control, desktop, icon, buildDir]
|
||||
spawn({cmd, args}, done)
|
||||
|
||||
@@ -29,21 +29,14 @@ module.exports = (gruntObject) ->
|
||||
done = @async()
|
||||
buildDir = grunt.config.get('atom.buildDir')
|
||||
|
||||
createBuildRelease (error, release) ->
|
||||
zipApps buildDir, assets, (error) ->
|
||||
return done(error) if error?
|
||||
|
||||
zipApps buildDir, assets, (error) ->
|
||||
getAtomDraftRelease (error, release) ->
|
||||
return done(error) if error?
|
||||
uploadAssets release, buildDir, assets, (error) ->
|
||||
assetNames = (asset.assetName for asset in assets)
|
||||
deleteExistingAssets release, assetNames, (error) ->
|
||||
return done(error) if error?
|
||||
publishRelease release, (error) ->
|
||||
return done(error) if error?
|
||||
getAtomDraftRelease (error, release) ->
|
||||
return done(error) if error?
|
||||
assetNames = (asset.assetName for asset in assets)
|
||||
deleteExistingAssets release, assetNames, (error) ->
|
||||
return done(error) if error?
|
||||
uploadAssets(release, buildDir, assets, done)
|
||||
uploadAssets(release, buildDir, assets, done)
|
||||
|
||||
logError = (message, error, details) ->
|
||||
grunt.log.error(message)
|
||||
@@ -64,25 +57,6 @@ zipApps = (buildDir, assets, callback) ->
|
||||
tasks.push(zip.bind(this, buildDir, sourceName, assetName))
|
||||
async.parallel(tasks, callback)
|
||||
|
||||
getRelease = (callback) ->
|
||||
options =
|
||||
uri: 'https://api.github.com/repos/atom/atom-master-builds/releases'
|
||||
method: 'GET'
|
||||
headers: defaultHeaders
|
||||
json: true
|
||||
request options, (error, response, releases=[]) ->
|
||||
if error? or response.statusCode isnt 200
|
||||
logError('Fetching releases failed', error, releases)
|
||||
callback(error ? new Error(response.statusCode))
|
||||
else
|
||||
if releases.length > maxReleases
|
||||
deleteRelease(release) for release in releases[maxReleases..]
|
||||
|
||||
for release in releases when release.name is commitSha
|
||||
callback(null, release)
|
||||
return
|
||||
callback()
|
||||
|
||||
getAtomDraftRelease = (callback) ->
|
||||
atomRepo = new GitHub({repo: 'atom/atom', token})
|
||||
atomRepo.getReleases (error, releases=[]) ->
|
||||
@@ -125,35 +99,6 @@ deleteExistingAssets = (release, assetNames, callback) ->
|
||||
tasks.push(deleteAsset.bind(this, asset.url))
|
||||
async.parallel(tasks, callback)
|
||||
|
||||
createBuildRelease = (callback) ->
|
||||
getRelease (error, release) ->
|
||||
if error?
|
||||
callback(error)
|
||||
return
|
||||
|
||||
if release?
|
||||
deleteExistingAssets release, (error) ->
|
||||
callback(error, release)
|
||||
return
|
||||
|
||||
options =
|
||||
uri: 'https://api.github.com/repos/atom/atom-master-builds/releases'
|
||||
method: 'POST'
|
||||
headers: defaultHeaders
|
||||
json:
|
||||
tag_name: "v#{commitSha}"
|
||||
target_commitish: 'master'
|
||||
name: commitSha
|
||||
body: "Build of [atom@#{commitSha.substring(0, 7)}](https://github.com/atom/atom/commits/#{commitSha})"
|
||||
draft: true
|
||||
prerelease: true
|
||||
request options, (error, response, release={}) ->
|
||||
if error? or response.statusCode isnt 201
|
||||
logError('Creating release failed', error, release)
|
||||
callback(error ? new Error(response.statusCode))
|
||||
else
|
||||
callback(null, release)
|
||||
|
||||
uploadAssets = (release, buildDir, assets, callback) ->
|
||||
upload = (release, assetName, assetPath, callback) ->
|
||||
options =
|
||||
@@ -178,17 +123,3 @@ uploadAssets = (release, buildDir, assets, callback) ->
|
||||
assetPath = path.join(buildDir, assetName)
|
||||
tasks.push(upload.bind(this, release, assetName, assetPath))
|
||||
async.parallel(tasks, callback)
|
||||
|
||||
publishRelease = (release, callback) ->
|
||||
options =
|
||||
uri: release.url
|
||||
method: 'POST'
|
||||
headers: defaultHeaders
|
||||
json:
|
||||
draft: false
|
||||
request options, (error, response, body={}) ->
|
||||
if error? or response.statusCode isnt 200
|
||||
logError('Creating release failed', error, body)
|
||||
callback(error ? new Error(response.statusCode))
|
||||
else
|
||||
callback()
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
async = require 'async'
|
||||
request = require 'request'
|
||||
|
||||
# Configure and publish all packages in package.json to atom.io
|
||||
#
|
||||
# This task should be run whenever you want to be sure that atom.io contains
|
||||
# all the packages and versions referenced in Atom's package.json file.
|
||||
module.exports = (grunt) ->
|
||||
{spawn} = require('./task-helpers')(grunt)
|
||||
|
||||
baseUrl = "https://atom.io/api/packages"
|
||||
|
||||
packageExists = (packageName, token, callback) ->
|
||||
requestSettings =
|
||||
url: "#{baseUrl}/#{packageName}"
|
||||
json: true
|
||||
headers:
|
||||
authorization: token
|
||||
request.get requestSettings, (error, response, body={}) ->
|
||||
if error?
|
||||
callback(error)
|
||||
else
|
||||
callback(null, response.statusCode is 404)
|
||||
|
||||
createPackage = (packageName, token, callback) ->
|
||||
requestSettings =
|
||||
url: baseUrl
|
||||
json: true
|
||||
headers:
|
||||
authorization: token
|
||||
method: 'POST'
|
||||
body:
|
||||
repository: "atom/#{packageName}"
|
||||
|
||||
request.get requestSettings, (error, response, body={}) ->
|
||||
if error?
|
||||
callback(error)
|
||||
else if response.statusCode isnt 201
|
||||
message = body.message ? body.error ? body
|
||||
callback(new Error("Creating package failed: #{message}"))
|
||||
else
|
||||
callback()
|
||||
|
||||
createPackageVersion = (packageName, tag, token, callback) ->
|
||||
requestSettings =
|
||||
url: "#{baseUrl}/#{packageName}/versions"
|
||||
json: true
|
||||
method: 'POST'
|
||||
headers:
|
||||
authorization: token
|
||||
body:
|
||||
tag: tag
|
||||
|
||||
request.get requestSettings, (error, response, body={}) ->
|
||||
if error?
|
||||
callback(error)
|
||||
else if response.statusCode isnt 201
|
||||
message = body.message ? body.error ? body
|
||||
if message is 'Version exists'
|
||||
callback()
|
||||
else
|
||||
callback(new Error("Creating new version failed: #{message}"))
|
||||
else
|
||||
callback()
|
||||
|
||||
getToken = (callback) ->
|
||||
if token = process.env.ATOM_ACCESS_TOKEN
|
||||
callback(null, token)
|
||||
else
|
||||
spawn {cmd: 'security', args: ['-q', 'find-generic-password', '-ws', 'GitHub API Token']}, (error, result, code) ->
|
||||
token = result.toString() unless error?
|
||||
callback(error, token)
|
||||
|
||||
grunt.registerTask 'publish-packages', 'Publish all bundled packages', ->
|
||||
done = @async()
|
||||
|
||||
getToken (error, token) ->
|
||||
unless token
|
||||
grunt.log.error('Token not found in keychain or ATOM_ACCESS_TOKEN environment variable')
|
||||
done(false)
|
||||
|
||||
{packageDependencies} = grunt.file.readJSON('package.json') ? {}
|
||||
tasks = []
|
||||
for name, version of packageDependencies
|
||||
do (name, version) ->
|
||||
tasks.push (callback) ->
|
||||
grunt.verbose.writeln("Publishing #{name}@#{version}")
|
||||
tag = "v#{version}"
|
||||
packageExists name, token, (error, exists) ->
|
||||
if error?
|
||||
callback(error)
|
||||
return
|
||||
|
||||
if exists
|
||||
createPackage name, token, (error) ->
|
||||
if error?
|
||||
callback(error)
|
||||
else
|
||||
createPackageVersion(name, tag, token, callback)
|
||||
else
|
||||
createPackageVersion(name, tag, token, callback)
|
||||
|
||||
async.waterfall tasks, (error) ->
|
||||
if error?
|
||||
grunt.log.error(error.message)
|
||||
done(false)
|
||||
else
|
||||
done()
|
||||
@@ -5,14 +5,18 @@ module.exports = (grunt) ->
|
||||
{spawn} = require('./task-helpers')(grunt)
|
||||
|
||||
getVersion = (callback) ->
|
||||
if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
|
||||
{version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json'))
|
||||
onBuildMachine = process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
|
||||
inRepository = fs.existsSync(path.resolve(__dirname, '..', '..', '.git'))
|
||||
{version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json'))
|
||||
if onBuildMachine or not inRepository
|
||||
callback(null, version)
|
||||
else
|
||||
cmd = 'git'
|
||||
args = ['rev-parse', '--short', 'HEAD']
|
||||
spawn {cmd, args}, (error, {stdout}={}, code) ->
|
||||
callback(error, stdout?.trim?())
|
||||
commitHash = stdout?.trim?()
|
||||
combinedVersion = "#{version}-#{commitHash}"
|
||||
callback(error, combinedVersion)
|
||||
|
||||
grunt.registerTask 'set-version', 'Set the version in the plist and package.json', ->
|
||||
done = @async()
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Welcome to the Atom API Documentation
|
||||
|
||||

|
||||

|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ keystrokes pass through elements with the class `.editor`:
|
||||
|
||||
```coffee
|
||||
'.editor':
|
||||
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
||||
'alt-backspace': 'editor:backspace-to-beginning-of-word'
|
||||
'cmd-delete': 'editor:delete-to-beginning-of-line'
|
||||
'alt-backspace': 'editor:delete-to-beginning-of-word'
|
||||
'ctrl-A': 'editor:select-to-first-character-of-line'
|
||||
'ctrl-shift-e': 'editor:select-to-end-of-line'
|
||||
'cmd-left': 'editor:move-to-first-character-of-line'
|
||||
@@ -24,7 +24,7 @@ keystrokes pass through elements with the class `.editor`:
|
||||
Beneath the first selector are several bindings, mapping specific *keystroke
|
||||
patterns* to *commands*. When an element with the `.editor` class is focused and
|
||||
`cmd-delete` is pressed, an custom DOM event called
|
||||
`editor:backspace-to-beginning-of-line` is emitted on the `.editor` element.
|
||||
`editor:delete-to-beginning-of-line` is emitted on the `.editor` element.
|
||||
|
||||
The second selector group also targets editors, but only if they don't have the
|
||||
`.mini` class. In this example, the commands for code folding don't really make
|
||||
@@ -91,6 +91,16 @@ the current keystroke sequence and continue searching from its parent. If you
|
||||
want to remove a binding from a keymap you don't control, such as keymaps in
|
||||
Atom core or in packages, use the `unset!` directive.
|
||||
|
||||
For example, the following code removes the keybinding for `a` in the Tree View,
|
||||
which is normally used to trigger the `tree-view:add-file` command:
|
||||
|
||||
```coffee
|
||||
'.tree-view':
|
||||
'a': 'unset!'
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Forcing Chromium's Native Keystroke Handling
|
||||
|
||||
If you want to force the native browser behavior for a given keystroke, use the
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
## Developing Node Modules
|
||||
|
||||
Atom contains a number of packages that are Node modules instead of Atom packages. If you want to
|
||||
make changes to the Node modules, for instance `atom-keymap`, you have to link them into the
|
||||
development environment differently than you would a normal Atom package.
|
||||
|
||||
### Linking a Node Module Into Your Atom Dev Environment
|
||||
|
||||
Here are the steps to run a local version of a node module *not an apm* within Atom. We're using
|
||||
`atom-keymap` as an example:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/atom/atom-keymap.git
|
||||
$ cd atom-keymap
|
||||
$ npm install
|
||||
$ npm link
|
||||
$ apm rebuild # This is the special step, it makes the npm work with Atom's version of Node
|
||||
$ cd WHERE-YOU-CLONED-ATOM
|
||||
$ npm link atom-keymap
|
||||
$ atom # Should work!
|
||||
```
|
||||
|
||||
After this, you'll have to `npm install` and `apm rebuild` when you make a change to the node
|
||||
module's code.
|
||||
@@ -0,0 +1,216 @@
|
||||
## Atom.io package and update API
|
||||
|
||||
This guide describes the web API used by [apm](https://github.com/atom/apm) and
|
||||
Atom. The vast majority of use cases are met by the `apm` command-line tool,
|
||||
which does other useful things like incrementing your version in `package.json`
|
||||
and making sure you have pushed your git tag. In fact, Atom itself shells out to
|
||||
`apm` rather than hitting the API directly. If you're curious about how Atom
|
||||
uses `apm`, see the [PackageManager class](https://github.com/atom/settings-view/blob/master/lib/package-manager.coffee)
|
||||
in the `settings-view` package.
|
||||
|
||||
### Authorization
|
||||
|
||||
For calls to the API that require authentication, provide a valid token from your
|
||||
[Atom.io account page](https://atom.io/account) in the `Authorization` header.
|
||||
|
||||
### Media type
|
||||
|
||||
All requests that take parameters require `application/json`.
|
||||
|
||||
## Resources
|
||||
|
||||
### Packages
|
||||
|
||||
#### GET /api/packages
|
||||
|
||||
Returns a list of all packages in the following format:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"releases": {
|
||||
"latest": "0.6.0"
|
||||
},
|
||||
"name": "thedaniel-test-package",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thedaniel/test-package"
|
||||
}
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
#### GET /api/packages/:package_name
|
||||
|
||||
Returns package details and versions for a single package
|
||||
|
||||
Parameters:
|
||||
|
||||
- **engine** (optional) - Only show packages with versions compatible with this
|
||||
Atom version. Must be valid [SemVer](http://semver.org).
|
||||
|
||||
Returns:
|
||||
|
||||
```json
|
||||
{
|
||||
"releases": {
|
||||
"latest": "0.6.0"
|
||||
},
|
||||
"name": "thedaniel-test-package",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thedaniel/test-package"
|
||||
},
|
||||
"versions": [
|
||||
(see single version output below)
|
||||
...,
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/packages
|
||||
|
||||
Create a new package; requires authentication.
|
||||
|
||||
The name and version will be fetched from the `package.json`
|
||||
file in the specified repository. The authenticating user *must* have access
|
||||
to the indicated repository.
|
||||
|
||||
When a package is created, a release hook is registered with GitHub for package
|
||||
version creation.
|
||||
|
||||
Parameters:
|
||||
|
||||
- **repository** - String. The repository containing the plugin, in the form "owner/repo"
|
||||
|
||||
Returns:
|
||||
|
||||
- **201** - Successfully created, returns created package.
|
||||
- **400** - Repository is inaccessible, nonexistent, not an atom package. Possible
|
||||
error messages include:
|
||||
- That repo does not exist, isn't an atom package, or atombot does not have access
|
||||
- The package.json at owner/repo isn't valid
|
||||
- **409** - A package by that name already exists
|
||||
|
||||
|
||||
#### DELETE /api/packages/:package_name
|
||||
|
||||
Delete a package; requires authentication.
|
||||
|
||||
Returns:
|
||||
|
||||
- **204** - Success
|
||||
- **400** - Repository is inaccessible
|
||||
- **401** - Unauthorized
|
||||
|
||||
### Package Versions
|
||||
|
||||
#### GET /api/packages/:package_name/versions/:version_name
|
||||
|
||||
Returns `package.json` with `dist` key added for e.g. tarball download:
|
||||
|
||||
```json
|
||||
{
|
||||
"bugs": {
|
||||
"url": "https://github.com/thedaniel/test-package/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "~0.2.6",
|
||||
"pegjs": "~0.7.0",
|
||||
"season": "~0.13.0"
|
||||
},
|
||||
"description": "Expand snippets matching the current prefix with `tab`.",
|
||||
"dist": {
|
||||
"tarball": "https://codeload.github.com/..."
|
||||
},
|
||||
"engines": {
|
||||
"atom": "*"
|
||||
},
|
||||
"main": "./lib/snippets",
|
||||
"name": "thedaniel-test-package",
|
||||
"publishConfig": {
|
||||
"registry": "https://...",
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thedaniel/test-package.git"
|
||||
},
|
||||
"version": "0.6.0"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Creating a new package version
|
||||
|
||||
#### POST /api/packages/:package_name/versions
|
||||
|
||||
Creates a new package version from a git tag; requires authentication.
|
||||
|
||||
#### Parameters
|
||||
|
||||
- **tag** - A git tag for the version you'd like to create. It's important to note
|
||||
that the version name will not be taken from the tag, but from the `version`
|
||||
key in the `package.json` file at that ref. The authenticating user *must* have
|
||||
access to the package repository.
|
||||
|
||||
#### Returns
|
||||
|
||||
- **201** - Successfully created. Returns created version.
|
||||
- **400** - Git tag not found / Repository inaccessible
|
||||
- **409** - Version exists
|
||||
|
||||
### Delete a version
|
||||
|
||||
#### DELETE /api/packages/:package_name/versions/:version_name
|
||||
|
||||
Deletes a package version; requires authentication.
|
||||
|
||||
Note that a version cannot be republished with a different tag if it is deleted.
|
||||
If you need to delete the latest version of a package for e.g. security reasons,
|
||||
you'll need to increment the version when republishing.
|
||||
|
||||
Returns 204 No Content
|
||||
|
||||
|
||||
### Stars
|
||||
|
||||
#### GET /api/users/:login/stars
|
||||
|
||||
List a user's starred packages.
|
||||
|
||||
Return value is similar to **GET /api/packages**
|
||||
|
||||
#### GET /api/stars
|
||||
|
||||
List the authenticated user's starred packages; requires authentication.
|
||||
|
||||
Return value is similar to **GET /api/packages**
|
||||
|
||||
#### POST /api/packages/:name/star
|
||||
|
||||
Star a package; requires authentication.
|
||||
|
||||
Returns a package.
|
||||
|
||||
#### DELETE /api/packages/:name/star
|
||||
|
||||
Unstar a package; requires authentication.
|
||||
|
||||
Returns 204 No Content.
|
||||
|
||||
### Atom updates
|
||||
|
||||
#### GET /api/updates
|
||||
|
||||
Atom update feed, following the format expected by [Squirrel](https://github.com/Squirrel/).
|
||||
|
||||
Returns:
|
||||
|
||||
```
|
||||
{
|
||||
"name": "0.96.0",
|
||||
"notes": "[HTML release notes]"
|
||||
"pub_date": "2014-05-19T15:52:06.000Z",
|
||||
"url": "https://www.atom.io/api/updates/download"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,22 @@
|
||||
# FreeBSD
|
||||
|
||||
FreeBSD -RELEASE 64-bit is the recommended platform.
|
||||
|
||||
## Requirements
|
||||
|
||||
* FreeBSD
|
||||
* `pkg install node`
|
||||
* `pkg install npm`
|
||||
* `pkg install libgnome-keyring`
|
||||
* `npm config set python /usr/local/bin/python2 -g` to ensure that gyp uses Python 2
|
||||
|
||||
## Instructions
|
||||
|
||||
```sh
|
||||
git clone https://github.com/atom/atom
|
||||
cd atom
|
||||
script/build # Creates application at $TMPDIR/atom-build/Atom
|
||||
sudo script/grunt install # Installs command to /usr/local/bin/atom
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@@ -0,0 +1,56 @@
|
||||
# Linux
|
||||
|
||||
Ubuntu LTS 12.04 64-bit is the recommended platform.
|
||||
|
||||
## Requirements
|
||||
|
||||
* OS with 64-bit or 32-bit architecture
|
||||
* [node.js](http://nodejs.org/download/) v0.10.x
|
||||
* [npm](http://www.npmjs.org/) v1.4.x
|
||||
* libgnome-keyring-dev
|
||||
* on Ubuntu/Debian: `sudo apt-get install libgnome-keyring-dev`
|
||||
* on Fedora: `sudo yum --assumeyes install libgnome-keyring-devel`
|
||||
* on other distributions refer to the manual on how to install packages
|
||||
* `npm config set python /usr/bin/python2 -g` to ensure that gyp uses Python 2
|
||||
* This command may require `sudo` depending on how you have
|
||||
[configured npm](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
|
||||
|
||||
|
||||
## Instructions
|
||||
|
||||
```sh
|
||||
git clone https://github.com/atom/atom
|
||||
cd atom
|
||||
script/build # Creates application at $TMPDIR/atom-build/Atom
|
||||
sudo script/grunt install # Installs command to /usr/local/bin/atom
|
||||
script/grunt mkdeb # Generates a .deb package at $TMPDIR/atom-build
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
### Exception: "TypeError: Unable to watch path"
|
||||
|
||||
If you get following error with a big traceback right after Atom starts:
|
||||
|
||||
```
|
||||
TypeError: Unable to watch path
|
||||
```
|
||||
|
||||
you have to increase number of watched files by inotify. For testing if
|
||||
this is the reason for this error you can issue
|
||||
|
||||
```sh
|
||||
sudo sysctl fs.inotify.max_user_watches=32768
|
||||
```
|
||||
|
||||
and restart Atom. If Atom now works fine, you can make this setting permanent:
|
||||
|
||||
```sh
|
||||
echo 32768 > /proc/sys/fs/inotify/max_user_watches
|
||||
```
|
||||
|
||||
See also https://github.com/atom/atom/issues/2082.
|
||||
|
||||
### 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.
|
||||
@@ -0,0 +1,20 @@
|
||||
# OS X
|
||||
|
||||
## Requirements
|
||||
|
||||
* OS X 10.8 or later
|
||||
* [node.js](http://nodejs.org/download/) v0.10.x
|
||||
* Command Line Tools for [Xcode](https://developer.apple.com/xcode/downloads/) (run `xcode-select --install` to install)
|
||||
|
||||
## Instructions
|
||||
|
||||
```sh
|
||||
git clone https://github.com/atom/atom.git
|
||||
cd atom
|
||||
script/build # Creates application at /Applications/Atom.app
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### OSX build error reports in atom/atom
|
||||
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Aos-x&type=Issues) to get a list of reports about build errors on OSX.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Windows
|
||||
|
||||
## Requirements
|
||||
|
||||
### On Windows 7
|
||||
* [Visual C++ 2010 Express](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_4)
|
||||
* [Visual Studio 2010 Service Pack 1](http://www.microsoft.com/en-us/download/details.aspx?id=23691)
|
||||
* [node.js](http://nodejs.org/download/) v0.10.x
|
||||
* For 64-bit builds of node and native modules you **must** have the
|
||||
[Windows 7 64-bit SDK](http://www.microsoft.com/en-us/download/details.aspx?id=8279).
|
||||
You may also need the [compiler update for the Windows SDK 7.1](http://www.microsoft.com/en-us/download/details.aspx?id=4422)
|
||||
|
||||
* [Python](http://www.python.org/download/) v2.7.x
|
||||
* [GitHub for Windows](http://windows.github.com/)
|
||||
|
||||
### On Windows 8
|
||||
* [Visual Studio Express 2013 for Windows Desktop](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_2)
|
||||
* [node.js](http://nodejs.org/download/) v0.10.x
|
||||
* [Python](http://www.python.org/download/) v2.7.x (required by [node-gyp](https://github.com/TooTallNate/node-gyp))
|
||||
* [GitHub for Windows](http://windows.github.com/)
|
||||
|
||||
## Instructions
|
||||
|
||||
```bat
|
||||
# Use the `Git Shell` app which was installed by GitHub for Windows. Also Make
|
||||
# sure you have logged into the GitHub for Windows GUI App.
|
||||
cd C:\
|
||||
git clone https://github.com/atom/atom/
|
||||
cd atom
|
||||
script/build # Creates application in the `Program Files` directory
|
||||
```
|
||||
|
||||
## Why do I have to use GitHub for Windows?
|
||||
|
||||
You don't, You can use your existing Git! GitHub for Windows's Git Shell is just
|
||||
easier to set up. You need to have Posix tools in your `%PATH%` (i.e. `grep`,
|
||||
`sed`, et al.), which isn't the default configuration when you install Git. To
|
||||
fix this, you probably need to fiddle with your system PATH.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Errors
|
||||
* `node is not recognized`
|
||||
|
||||
* If you just installed node you need to restart your computer before node is
|
||||
available on your Path.
|
||||
|
||||
|
||||
* `script/build` outputs only the Node and Python versions before returning
|
||||
|
||||
* Try moving the repository to `C:\atom`. Most likely, the path is too long.
|
||||
See [issue #2200](https://github.com/atom/atom/issues/2200).
|
||||
|
||||
### Windows build error reports in atom/atom
|
||||
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Awindows&type=Issues) to get a list of reports about build errors on Windows.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Contributing to Official Atom Packages
|
||||
|
||||
If you think you know which package is causing the issue you are reporting, feel
|
||||
free to open up the issue in that specific repository instead. When in doubt
|
||||
just open the issue here but be aware that it may get closed here and reopened
|
||||
in the proper package's repository.
|
||||
|
||||
## Hacking on Packages
|
||||
|
||||
### Cloning
|
||||
|
||||
The first step is creating your own clone. You can of course do this manually
|
||||
with git, or you can use the `apm develop` command to create a clone based on
|
||||
the package's `repository` field in the `package.json`.
|
||||
|
||||
For example, if you want to make changes to the `tree-view` package, run the
|
||||
following command:
|
||||
|
||||
```
|
||||
> apm develop tree-view
|
||||
Cloning https://github.com/atom/tree-view ✓
|
||||
Installing modules ✓
|
||||
~/.atom/dev/packages/tree-view -> ~/github/tree-view
|
||||
```
|
||||
|
||||
This clones the `tree-view` repository to `~/github`. If you prefer a different
|
||||
path, specify it via the `ATOM_REPOS_HOME` environment variable.
|
||||
|
||||
### Running in Development Mode
|
||||
|
||||
Editing a package in Atom is a bit of a circular experience: you're using Atom
|
||||
to modify itself. What happens if you temporarily break something? You don't
|
||||
want the version of Atom you're using to edit to become useless in the process.
|
||||
For this reason, you'll only want to load packages in **development mode** while
|
||||
you are working on them. You'll perform your editing in **stable mode**, only
|
||||
switching to development mode to test your changes.
|
||||
|
||||
To open a development mode window, use the "Application: Open Dev" command,
|
||||
which is normally bound to `cmd-shift-o`. You can also run dev mode from the
|
||||
command line with `atom --dev`.
|
||||
|
||||
To load your package in development mode, create a symlink to it in
|
||||
`~/.atom/dev/packages`. This occurs automatically when you clone the package
|
||||
with `apm develop`. You can also run `apm link --dev` and `apm unlink --dev`
|
||||
from the package directory to create and remove dev-mode symlinks.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
Finally, you need to install the cloned package's dependencies by running
|
||||
`apm install` within the package directory. This step is also performed
|
||||
automatically the first time you run `apm develop`, but you'll want to keep
|
||||
dependencies up to date by running `apm update` after pulling upstream changes.
|
||||
@@ -1,142 +0,0 @@
|
||||
# Contributing to Atom Packages
|
||||
|
||||
The following is a set of guidelines for contributing to Atom packages, which
|
||||
are hosted in the [Atom Organization](https://github.com/atom) on GitHub. If
|
||||
you're unsure which package is causing your problem or if you're having an issue
|
||||
with Atom core, please use the feedback form in the application or email
|
||||
[atom@github.com](mailto:atom@github.com).
|
||||
|
||||
## Submitting Issues
|
||||
|
||||
* Include screenshots and animated GIFs whenever possible; they are immensely
|
||||
helpful.
|
||||
* Include the behavior you expected and other places you've seen that behavior
|
||||
such as Emacs, vi, Xcode, etc.
|
||||
* Check the dev tools (`alt-cmd-i`) for errors and stack traces to include.
|
||||
* Check Console.app for stack traces to include if reporting a crash.
|
||||
* Perform a cursory search to see if a similar issue has already been submitted.
|
||||
|
||||
## Hacking on Packages
|
||||
|
||||
### Cloning
|
||||
|
||||
The first step is creating your own clone. You can of course do this manually
|
||||
with git, or you can use the `apm develop` command to create a clone based on
|
||||
the package's `repository` field in the `package.json`.
|
||||
|
||||
For example, if you want to make changes to the `tree-view` package, run the
|
||||
following command:
|
||||
|
||||
```
|
||||
> apm develop tree-view
|
||||
Cloning https://github.com/atom/tree-view ✓
|
||||
Installing modules ✓
|
||||
~/.atom/dev/packages/tree-view -> ~/github/tree-view
|
||||
```
|
||||
|
||||
This clones the `tree-view` repository to `~/github`. If you prefer a different
|
||||
path, specify it via the `ATOM_REPOS_HOME` environment variable.
|
||||
|
||||
### Running in Development Mode
|
||||
|
||||
Editing a package in Atom is a bit of a circular experience: you're using Atom
|
||||
to modify itself. What happens if you temporarily break something? You don't
|
||||
want the version of Atom you're using to edit to become useless in the process.
|
||||
For this reason, you'll only want to load packages in **development mode** while
|
||||
you are working on them. You'll perform your editing in **stable mode**, only
|
||||
switching to development mode to test your changes.
|
||||
|
||||
To open a development mode window, use the "Application: Open Dev" command,
|
||||
which is normally bound to `cmd-shift-o`. You can also run dev mode from the
|
||||
command line with `atom --dev`.
|
||||
|
||||
To load your package in development mode, create a symlink to it in
|
||||
`~/.atom/dev/packages`. This occurs automatically when you clone the package
|
||||
with `apm develop`. You can also run `apm link --dev` and `apm unlink --dev`
|
||||
from the package directory to create and remove dev-mode symlinks.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
Finally, you need to install the cloned package's dependencies by running
|
||||
`apm install` within the package directory. This step is also performed
|
||||
automatically the first time you run `apm develop`, but you'll want to keep
|
||||
dependencies up to date by running `apm update` after pulling upstream changes.
|
||||
|
||||
## Submitting Pull Requests
|
||||
|
||||
### Code Guidelines
|
||||
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Follow the [CoffeeScript](#coffeescript-styleguide),
|
||||
[JavaScript](https://github.com/styleguide/javascript),
|
||||
and [CSS](https://github.com/styleguide/css) styleguides.
|
||||
* Include thoughtfully-worded, well-structured
|
||||
[Jasmine](http://pivotal.github.com/jasmine) specs.
|
||||
* Document new code based on the
|
||||
[Documentation Styleguide](#documentation-styleguide)
|
||||
* End files with a newline.
|
||||
* Place requires in the following order:
|
||||
* Built in Node Modules (such as `path`)
|
||||
* Built in Atom and Atom Shell Modules (such as `atom`, `shell`)
|
||||
* Local Modules (using relative paths)
|
||||
* Place class properties in the following order:
|
||||
* Class methods and properties (methods starting with a `@`)
|
||||
* Instance methods and properties
|
||||
* Avoid platform-dependent code:
|
||||
* Use `require('atom').fs.getHomeDirectory()` to get the home directory.
|
||||
* Use `path.join()` to concatenate filenames.
|
||||
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
|
||||
temporary directory.
|
||||
|
||||
### Commit Message Guidelines
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :lipstick: when improving the format/structure of the code
|
||||
* :racehorse: when improving performance
|
||||
* :non-potable_water: when plugging memory leaks
|
||||
* :memo: when writing docs
|
||||
* :bulb: Check out the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com)
|
||||
for more ideas.
|
||||
|
||||
## CoffeeScript Styleguide
|
||||
|
||||
* Use parentheses if it improves code clarity.
|
||||
* Prefer alphabetic keywords to symbolic keywords:
|
||||
* `a is b` instead of `a == b`
|
||||
* Avoid spaces inside the curly-braces of hash literals:
|
||||
* `{a: 1, b: 2}` instead of `{ a: 1, b: 2 }`
|
||||
* Set parameter defaults without spaces around the equal sign:
|
||||
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
|
||||
* Include a single line of whitespace between methods.
|
||||
|
||||
## Documentation Styleguide
|
||||
|
||||
* Use [TomDoc](http://tomdoc.org).
|
||||
* Use [Markdown](https://daringfireball.net/projects/markdown).
|
||||
* Reference methods and classes in markdown with the custom `{}` notation:
|
||||
* Reference classes with `{ClassName}`
|
||||
* Reference instance methods with `{ClassName::methodName}`
|
||||
* Reference class methods with `{ClassName.methodName}`
|
||||
|
||||
### Example
|
||||
|
||||
```coffee
|
||||
# Public: Disable the package with the given name.
|
||||
#
|
||||
# This method emits multiple events:
|
||||
#
|
||||
# * `package-will-be-disabled` - before the package is disabled.
|
||||
# * `package-disabled` - after the package is disabled.
|
||||
#
|
||||
# name - The {String} name of the package to disable.
|
||||
# options - The {Object} with disable options (default: {}):
|
||||
# :trackTime - `true` to track the amount of time disabling took.
|
||||
# :ignoreErrors - `true` to catch and ignore errors thrown.
|
||||
# callback - The {Function} to call after the package has been disabled.
|
||||
#
|
||||
# Returns `undefined`.
|
||||
disablePackage: (name, options, callback) ->
|
||||
```
|
||||
Link simbólico
+1
@@ -0,0 +1 @@
|
||||
../CONTRIBUTING.md
|
||||
@@ -20,7 +20,7 @@ apm help init
|
||||
|
||||
You should see a message print out with details about the `apm init` command.
|
||||
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
|
||||
to install the `apm` and `atom` commands.
|
||||
|
||||
### Convert the Package
|
||||
@@ -49,4 +49,4 @@ the editor to see it in action!
|
||||
[plist]: http://en.wikipedia.org/wiki/Property_list
|
||||
[R]: http://en.wikipedia.org/wiki/R_(programming_language)
|
||||
[TextMate]: http://macromates.com
|
||||
[TextMateOrg]: https://github.com/textmate/r.tmbundle
|
||||
[TextMateOrg]: https://github.com/textmate
|
||||
|
||||
@@ -25,7 +25,7 @@ apm help init
|
||||
|
||||
You should see a message print out with details about the `apm init` command.
|
||||
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
|
||||
to install the `apm` and `atom` commands.
|
||||
|
||||
You can now run `apm help init` to see all the options for initializing new
|
||||
|
||||
@@ -225,6 +225,20 @@ elements until reaching the top of the DOM tree.
|
||||
In the example above, the `Add file` item will only appear when the focused item
|
||||
or one of its parents has the `tree-view` class applied to it.
|
||||
|
||||
You can also add separators and submenus to your context menus. To add a
|
||||
submenu, pass in another object instead of a command. To add a separator, use
|
||||
`-` for the name and command of the item.
|
||||
|
||||
```coffeescript
|
||||
'context-menu':
|
||||
'.workspace':
|
||||
'Inspect Element': 'core:inspect'
|
||||
'-': '-'
|
||||
'Text':
|
||||
'Select All': 'core:select-all'
|
||||
'Deleted Selected Text': 'core:delete'
|
||||
```
|
||||
|
||||
## Snippets
|
||||
|
||||
An extension can supply language snippets in the _snippets_ directory which
|
||||
|
||||
@@ -34,7 +34,7 @@ apm help install
|
||||
|
||||
You should see a message print out with details about the `apm install` command.
|
||||
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
|
||||
to install the `apm` and `atom` commands.
|
||||
|
||||
You can also install packages by using the `apm install` command:
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# Debugging
|
||||
|
||||
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
|
||||
|
||||
You might be running into an issue which was already fixed in a more recent version of Atom than the one you're using.
|
||||
|
||||
If you're building Atom from source, pull down the latest version of master and [re-build][building atom].
|
||||
|
||||
If you're using released version, check which version of Atom you're using:
|
||||
|
||||
```shell
|
||||
$ atom --version
|
||||
0.99.0
|
||||
```
|
||||
|
||||
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 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.
|
||||
|
||||
Open Atom's Settings View with `cmd-,` or the Atom > Preferences menu option.
|
||||
|
||||
![Settings View]
|
||||
|
||||
Check Atom's settings in the Settings pane, there's a description of each configuration option [here][customizing guide]. For example, if you want Atom to use hard tabs (real tabs) and not soft tabs (spaces), disable the "Soft Tabs" option.
|
||||
|
||||
Since Atom ships with a set of packages and you can install additional packages yourself, check the list of packages and their settings. For example, if you'd like to get rid of the vertical line in the middle of the editor, disable the [Wrap Guide package]. And if you don't like it when Atom strips trailing whitespace or ensures that there's a single trailing newline in the file, you can configure that in the [Whitespace packages'][whitespace package] settings.
|
||||
|
||||
![Package Settings]
|
||||
|
||||
## Check the keybindings
|
||||
|
||||
If a command is not executing when you hit a keystroke or the wrong command is executing, there might be an issue with the keybindings for that keystroke. Atom ships with the [Keybinding resolver][keybinding resolver package], a neat package which helps you understand which keybindings are executed.
|
||||
|
||||
Show the keybinding resolver with <code>cmd-.</code> or with "Key Binding Resolver: Show" from the Command palette. With the keybinding resolver shown, hit a keystroke:
|
||||
|
||||
![Keybinding Resolver]
|
||||
|
||||
The keybinding resolver shows you a list of keybindings that exist for the keystroke, where each item in the list has the following:
|
||||
* the command for the keybinding,
|
||||
* the CSS selector used to define the context in which the keybinding is valid, and
|
||||
* the file in which the keybinding is defined.
|
||||
|
||||
Of all the keybinding that are listed (grey color), at most one keybinding is matched and executed (green color). If the command you wanted to trigger isn't listed, then a keybinding for that command hasn't been defined. More keybindings are provided by [packages] and you can [define your own keybindings][customizing keybindings].
|
||||
|
||||
If multiple keybindings are matched, Atom determines which keybinding will be executed based on the [specificity of the selectors and the order in which they were loaded][specificity and order]. If the command you wanted to trigger is listed in the Keybinding resolver, but wasn't the one that was executed, this is normally explained by one of two causes:
|
||||
* the keystroke was not used in the context defined by the keybinding's selector. For example, you can't trigger the "Tree View: Add File" command if the Tree View is not focused, or
|
||||
* there is another keybinding that took precedence. This often happens when you install a package which defines keybinding that conflict with existing keybindings. If the package's keybindings have selectors with higher specificity or were loaded later, they'll have priority over existing ones.
|
||||
|
||||
Atom loads core Atom keybindings and package keybindings first, and user-defined keybindings after last. Since user-defined keybindings are loaded last, you can use your `keymap.cson` file to tweak the keybindings and sort out problems like these. For example, you can remove keybindings with [the `unset!` directive][unset directive].
|
||||
|
||||
If you notice that a package's keybindings are taking precedence over core Atom keybindings, it might be a good idea to report the issue on the package's GitHub repository.
|
||||
|
||||
## Check if the problem shows up in safe mode
|
||||
|
||||
A large part of Atom's functionality comes from packages you can install. In some cases, these packages might be causing unexpected behavior, problems, or performance issues.
|
||||
|
||||
To determine if a package you installed is causing problems, start Atom from the terminal in safe mode:
|
||||
|
||||
```
|
||||
$ atom --safe
|
||||
```
|
||||
|
||||
This starts Atom, but does not load packages from `~/.atom/packages` or `~/.atom/dev/packages`. If you can no longer reproduce the problem in safe mode, it's likely it was caused by one of the packages.
|
||||
|
||||
To figure out which package is causing trouble, start Atom normally again and open Settings (`cmd-,`). Since Settings allow you to disable each installed package, you can disable packages one by one until you can no longer reproduce the issue. Restart (`cmd-q`) or reload (`cmd-ctrl-alt-l`) Atom after you disable each package to make sure it's completely gone.
|
||||
|
||||
When you find the problematic package, you can disable or uninstall the package, and consider creating an issue on the package's GitHub repository.
|
||||
|
||||
## Check your config files
|
||||
|
||||
You might have defined some custom functionality or styles in Atom's [Init script or Stylesheet]. In some situations, these personal hacks might be causing problems so try clearing those files and restarting Atom.
|
||||
|
||||
## Check for errors in the developer tools
|
||||
|
||||
When an error is thrown in Atom, the developer tools are automatically shown with the error logged in the Console tab. However, if the dev tools are open before the error is triggered, a full stack trace for the error will be logged:
|
||||
|
||||
![devtools error]
|
||||
|
||||
If you can reproduce the error, use this approach to get the full stack trace. The stack trace might point to a problem in your [Init script][init script or stylesheet] or a specific package you installed, which you can then disable and report an issue on its GitHub repository.
|
||||
|
||||
[submitting issues]: https://github.com/atom/atom/blob/master/CONTRIBUTING.md#submitting-issues
|
||||
[building atom]: https://github.com/atom/atom#building
|
||||
[atom releases]: https://github.com/atom/atom/releases
|
||||
[customizing guide]: https://atom.io/docs/latest/customizing-atom#configuration-key-reference
|
||||
[settings view]: https://f.cloud.github.com/assets/671378/2241795/ba4827d8-9ce4-11e3-93a8-6666ee100917.png
|
||||
[package settings]: https://cloud.githubusercontent.com/assets/38924/3173588/7e5f6b0c-ebe8-11e3-9ec3-e8d140967e79.png
|
||||
[wrap guide package]: https://atom.io/packages/wrap-guide
|
||||
[whitespace package]: https://atom.io/packages/whitespace
|
||||
[keybinding resolver package]: https://atom.io/packages/keybinding-resolver
|
||||
[keybinding resolver]: https://f.cloud.github.com/assets/671378/2241702/5dd5a102-9cde-11e3-9e3f-1d999930492f.png
|
||||
[customizing keybindings]: https://atom.io/docs/latest/customizing-atom#customizing-key-bindings
|
||||
[packages]: https://atom.io/packages
|
||||
[specificity and order]: https://atom.io/docs/latest/advanced/keymaps#specificity-and-cascade-order
|
||||
[unset directive]: https://atom.io/docs/latest/advanced/keymaps#removing-bindings
|
||||
[init script or stylesheet]: https://atom.io/docs/latest/customizing-atom#quick-personal-hacks
|
||||
[devtools error]: https://cloud.githubusercontent.com/assets/38924/3177710/11b4e510-ec13-11e3-96db-a2e8a7891773.png
|
||||
@@ -5,13 +5,16 @@
|
||||
* [Creating a Package](creating-a-package.md)
|
||||
* [Creating a Theme](creating-a-theme.md)
|
||||
* [Publishing a Package](publishing-a-package.md)
|
||||
* [Writing Specs](writing-specs.md)
|
||||
* [Converting a TextMate Bundle](converting-a-text-mate-bundle.md)
|
||||
* [Converting a TextMate Theme](converting-a-text-mate-theme.md)
|
||||
* [Contributing](contributing.md)
|
||||
* [Debugging](debugging.md)
|
||||
|
||||
### Advanced Topics
|
||||
|
||||
* [Configuration](advanced/configuration.md)
|
||||
* [Developing Node Modules](advanced/node-modules.md)
|
||||
* [Keymaps](advanced/keymaps.md)
|
||||
* [Serialization](advanced/serialization.md)
|
||||
* [View System](advanced/view-system.md)
|
||||
|
||||
@@ -7,7 +7,7 @@ Publishing a package allows other people to install it and use it in Atom. It
|
||||
is a great way to share what you've made and get feedback and contributions from
|
||||
others.
|
||||
|
||||
This guide assumes your package's name is `my-package` and but you should pick a
|
||||
This guide assumes your package's name is `my-package` but you should pick a
|
||||
better name.
|
||||
|
||||
### Install apm
|
||||
@@ -24,7 +24,7 @@ apm help publish
|
||||
|
||||
You should see a message print out with details about the `apm publish` command.
|
||||
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
|
||||
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
|
||||
to install the `apm` and `atom` commands.
|
||||
|
||||
### Prepare Your Package
|
||||
@@ -42,7 +42,7 @@ If not, there are a few things you should check before publishing:
|
||||
* Your package is in a Git repository that has been pushed to
|
||||
[GitHub][github]. Follow [this guide][repo-guide] if your package isn't
|
||||
already on GitHub.
|
||||
|
||||
|
||||
### Publish Your Package
|
||||
|
||||
Before you publish a package it is a good idea to check ahead of time if
|
||||
@@ -59,7 +59,7 @@ Now let's review what the `apm publish` command does:
|
||||
3. Creates a new [Git tag][git-tag] for the version being published.
|
||||
4. Pushes the tag and current branch up to GitHub.
|
||||
5. Updates atom.io with the new version being published.
|
||||
|
||||
|
||||
Now run the following commands to publish your package:
|
||||
|
||||
```sh
|
||||
@@ -75,18 +75,34 @@ credentials are stored securely in your [keychain][keychain] once you login.
|
||||
:tada: Your package is now published and available on atom.io. Head on over to
|
||||
`http://atom.io/packages/my-package` to see your package's page.
|
||||
|
||||
With `apm publish`, you can bump the version and publish by using
|
||||
```sh
|
||||
apm publish <version-type>
|
||||
```
|
||||
where `<version-type>` can be `major`, `minor` and `patch`.
|
||||
|
||||
The `major` option to the publish command tells apm to increment the first
|
||||
digit of the version before publishing so the published version will be `1.0.0`
|
||||
and the Git tag created will be `v1.0.0`.
|
||||
|
||||
The `minor` option to the publish command tells apm to increment the second
|
||||
digit of the version before publishing so the published version will be `0.1.0`
|
||||
and the Git tag created will be `v0.1.0`.
|
||||
|
||||
In the future you can run `apm publish major` to publish the `1.0.0` version but
|
||||
since this was the first version being published it is a good idead to start
|
||||
with a minor release.
|
||||
The `patch` option to the publish command tells apm to increment the third
|
||||
digit of the version before publishing so the published version will be `0.0.1`
|
||||
and the Git tag created will be `v0.0.1`.
|
||||
|
||||
Use `major` when you make a huge change, like a rewrite, or a large change to the functionality or interface.
|
||||
Use `minor` when adding or removing a feature.
|
||||
Use `patch` when you make a small change like a bug fix that does not add or remove features.
|
||||
|
||||
### Further Reading
|
||||
|
||||
* Check out [semantic versioning][semver] to learn more about versioning your
|
||||
package releases.
|
||||
* Consult the [Atom.io package API docs][apm-rest-api] to learn more about how
|
||||
`apm` works.
|
||||
|
||||
[atomio]: https://atom.io
|
||||
[github]: https://github.com
|
||||
@@ -95,3 +111,4 @@ with a minor release.
|
||||
[repo-guide]: http://guides.github.com/overviews/desktop
|
||||
[semver]: http://semver.org
|
||||
[your-first-package]: your-first-package.html
|
||||
[apm-rest-api]: apm-rest-api.md
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Writing specs
|
||||
|
||||
Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec framework. Any new functionality should have specs to guard against regressions.
|
||||
|
||||
## Create a new spec
|
||||
|
||||
[Atom specs](https://github.com/atom/atom/tree/master/spec) and [package specs](https://github.com/atom/markdown-preview/tree/master/spec) are added to their respective `spec` directory. The example below creates a spec for Atom core.
|
||||
|
||||
0. Create a spec file
|
||||
|
||||
Spec files **must** end with `-spec` so add `sample-spec.coffee` to `atom/spec`.
|
||||
|
||||
0. Add one or more `describe` methods
|
||||
|
||||
The `describe` method takes two arguments, a description and a function. If the description explains a behavior it typically begins with `when` if it is more like a unit test it begins with the method name.
|
||||
|
||||
```coffee
|
||||
describe "when a test is written", ->
|
||||
# contents
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```coffee
|
||||
describe "Editor::moveUp", ->
|
||||
# contents
|
||||
```
|
||||
|
||||
0. Add one or more `it` method
|
||||
|
||||
The `it` method also takes two arguments, a description and a function. Try and make the description flow with the `it` method. For example, a description of `this should work` doesn't read well as `it this should work`. But a description of `should work` sounds great as `it should work`.
|
||||
|
||||
```coffee
|
||||
describe "when a test is written", ->
|
||||
it "has some expectations that should pass", ->
|
||||
# Expectations
|
||||
```
|
||||
|
||||
0. Add one or more expectations
|
||||
|
||||
The best way to learn about expectations is to read the [jasmine documentation](http://jasmine.github.io/2.0/introduction.html#section-Expectations) about them. Below is a simple example.
|
||||
|
||||
```coffee
|
||||
describe "when a test is written", ->
|
||||
it "has some expectations that should pass", ->
|
||||
expect("apples").toEqual("apples")
|
||||
expect("oranges").not.toEqual("apples")
|
||||
```
|
||||
|
||||
## Running specs
|
||||
|
||||
Most of the time you'll want to run specs by triggering the `window:run-package-specs` command. This command is not only to run package specs, it is also for Atom core specs. This will run all the specs in the current project's spec directory. If you want to run the Atom core specs and **all** the default package specs trigger the `window:run-all-specs` command.
|
||||
|
||||
To run a limited subset of specs use the `fdescribe` or `fit` methods. You can use those to focus a single spec or several specs. In the example above, focusing an individual spec looks like this:
|
||||
|
||||
```coffee
|
||||
describe "when a test is written", ->
|
||||
fit "has some expectations that should pass", ->
|
||||
expect("apples").toEqual("apples")
|
||||
expect("oranges").not.toEqual("apples")
|
||||
```
|
||||
@@ -21,7 +21,7 @@ To begin, press `cmd-shift-P` to bring up the [Command
|
||||
Palette](https://github.com/atom/command-palette). Type "generate package" and
|
||||
select the "Package Generator: Generate Package" command. Now we need to name
|
||||
the package. Try to avoid naming your package with the *atom-* prefix, for
|
||||
example we are going to call this package _ascii-art_.
|
||||
example we are going to call this package _ascii-art_.
|
||||
|
||||
Atom will open a new window with the contents of our new _ascii-art_ package
|
||||
displayed in the Tree View. Because this window is opened **after** the package
|
||||
@@ -149,8 +149,10 @@ ASCII art professional!
|
||||
|
||||
* [Getting your project on GitHub guide](http://guides.github.com/overviews/desktop)
|
||||
|
||||
* [Writing specs](writing-specs.md) for your package
|
||||
|
||||
* [Creating a package guide](creating-a-package.html) for more information
|
||||
on the mechanics of packages
|
||||
|
||||
* [Publishing a package guide](publish-a-package.html) for more information
|
||||
* [Publishing a package guide](publishing-a-package.html) for more information
|
||||
on publishing your package to [atom.io](https://atom.io)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
storage
|
||||
compile-cache
|
||||
dev
|
||||
.npm
|
||||
.node-gyp
|
||||
+2
-4
@@ -1,9 +1,5 @@
|
||||
'.editor':
|
||||
# Platform Bindings
|
||||
'alt-left': 'editor:move-to-beginning-of-word'
|
||||
'alt-right': 'editor:move-to-end-of-word'
|
||||
'alt-shift-left': 'editor:select-to-beginning-of-word'
|
||||
'alt-shift-right': 'editor:select-to-end-of-word'
|
||||
'home': 'editor:move-to-first-character-of-line'
|
||||
'end': 'editor:move-to-end-of-screen-line'
|
||||
'shift-home': 'editor:select-to-first-character-of-line'
|
||||
@@ -16,6 +12,7 @@
|
||||
# Sublime Parity
|
||||
'tab': 'editor:indent'
|
||||
'enter': 'editor:newline'
|
||||
'num-enter': 'editor:newline'
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'ctrl-K': 'editor:delete-line'
|
||||
|
||||
@@ -30,6 +27,7 @@
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
'enter': 'native!'
|
||||
'num-enter': 'native!'
|
||||
'backspace': 'native!'
|
||||
'shift-backspace': 'native!'
|
||||
'delete': 'native!'
|
||||
|
||||
+14
-4
@@ -21,6 +21,7 @@
|
||||
'cmd-O': 'application:open-dev'
|
||||
'cmd-alt-ctrl-s': 'application:run-all-specs'
|
||||
'enter': 'core:confirm'
|
||||
'num-enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
@@ -53,6 +54,7 @@
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'shift-delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
@@ -65,6 +67,8 @@
|
||||
'cmd-}': 'pane:show-next-item'
|
||||
'cmd-alt-left': 'pane:show-previous-item'
|
||||
'cmd-alt-right': 'pane:show-next-item'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'cmd-=': 'window:increase-font-size'
|
||||
'cmd-+': 'window:increase-font-size'
|
||||
'cmd--': 'window:decrease-font-size'
|
||||
@@ -94,17 +98,23 @@
|
||||
'cmd-9': 'pane:show-item-9'
|
||||
|
||||
'.editor':
|
||||
# Platform Bindings
|
||||
'alt-left': 'editor:move-to-beginning-of-word'
|
||||
'alt-right': 'editor:move-to-end-of-word'
|
||||
'alt-shift-left': 'editor:select-to-beginning-of-word'
|
||||
'alt-shift-right': 'editor:select-to-end-of-word'
|
||||
|
||||
# Apple Specific
|
||||
'cmd-backspace': 'editor:backspace-to-beginning-of-line'
|
||||
'cmd-shift-backspace': 'editor:backspace-to-beginning-of-line'
|
||||
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
||||
'cmd-backspace': 'editor:delete-to-beginning-of-line'
|
||||
'cmd-shift-backspace': 'editor:delete-to-beginning-of-line'
|
||||
'cmd-delete': 'editor:delete-to-beginning-of-line'
|
||||
'ctrl-A': 'editor:select-to-first-character-of-line'
|
||||
'ctrl-E': 'editor:select-to-end-of-line'
|
||||
'cmd-left': 'editor:move-to-first-character-of-line'
|
||||
'cmd-right': 'editor:move-to-end-of-screen-line'
|
||||
'cmd-shift-left': 'editor:select-to-first-character-of-line'
|
||||
'cmd-shift-right': 'editor:select-to-end-of-line'
|
||||
'alt-backspace': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-backspace': 'editor:delete-to-beginning-of-word'
|
||||
'alt-delete': 'editor:delete-to-end-of-word'
|
||||
'ctrl-a': 'editor:move-to-beginning-of-line'
|
||||
'ctrl-e': 'editor:move-to-end-of-line'
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
'alt-F': 'editor:select-to-end-of-word'
|
||||
'alt-b': 'editor:move-to-beginning-of-word'
|
||||
'alt-B': 'editor:select-to-beginning-of-word'
|
||||
'alt-h': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-h': 'editor:delete-to-beginning-of-word'
|
||||
'alt-d': 'editor:delete-to-end-of-word'
|
||||
|
||||
+27
-4
@@ -1,13 +1,14 @@
|
||||
'body':
|
||||
# Atom Specific
|
||||
'enter': 'core:confirm'
|
||||
'num-enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
'left': 'core:move-left'
|
||||
'right': 'core:move-right'
|
||||
'ctrl-alt-r': 'window:reload'
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'ctrl-shift-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
'ctrl-shift-o': 'application:open-dev'
|
||||
@@ -28,14 +29,18 @@
|
||||
'ctrl-x': 'core:cut'
|
||||
'ctrl-c': 'core:copy'
|
||||
'ctrl-v': 'core:paste'
|
||||
'ctrl-insert': 'core:copy'
|
||||
'shift-insert': 'core:paste'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'shift-delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
@@ -58,14 +63,32 @@
|
||||
'ctrl-k ctrl-down': 'window:focus-pane-below'
|
||||
'ctrl-k ctrl-left': 'window:focus-pane-on-left'
|
||||
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
|
||||
'alt-1': 'pane:show-item-1'
|
||||
'alt-2': 'pane:show-item-2'
|
||||
'alt-3': 'pane:show-item-3'
|
||||
'alt-4': 'pane:show-item-4'
|
||||
'alt-5': 'pane:show-item-5'
|
||||
'alt-6': 'pane:show-item-6'
|
||||
'alt-7': 'pane:show-item-7'
|
||||
'alt-8': 'pane:show-item-8'
|
||||
'alt-9': 'pane:show-item-9'
|
||||
|
||||
'.workspace .editor':
|
||||
# Windows specific
|
||||
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
|
||||
# Platform Bindings
|
||||
'ctrl-left': 'editor:move-to-beginning-of-word'
|
||||
'ctrl-right': 'editor:move-to-end-of-word'
|
||||
'ctrl-shift-left': 'editor:select-to-beginning-of-word'
|
||||
'ctrl-shift-right': 'editor:select-to-end-of-word'
|
||||
'ctrl-backspace': 'editor:delete-to-beginning-of-word'
|
||||
'ctrl-delete': 'editor:delete-to-end-of-word'
|
||||
'ctrl-home': 'core:move-to-top'
|
||||
'ctrl-end': 'core:move-to-bottom'
|
||||
'ctrl-shift-home': 'core:select-to-top'
|
||||
'ctrl-shift-end': 'core:select-to-bottom'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-a': 'core:select-all'
|
||||
'ctrl-alt-p': 'editor:log-cursor-scope'
|
||||
'ctrl-alt-shift-p': 'editor:log-cursor-scope'
|
||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||
|
||||
|
||||
+22
-3
@@ -1,6 +1,11 @@
|
||||
'body':
|
||||
# Platform Bindings
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
|
||||
# Atom Specific
|
||||
'enter': 'core:confirm'
|
||||
'num-enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
@@ -10,6 +15,7 @@
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-N': 'application:new-window'
|
||||
@@ -25,18 +31,24 @@
|
||||
'ctrl-x': 'core:cut'
|
||||
'ctrl-c': 'core:copy'
|
||||
'ctrl-v': 'core:paste'
|
||||
'ctrl-insert': 'core:copy'
|
||||
'shift-insert': 'core:paste'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'shift-delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
'ctrl-shift-down': 'core:move-down'
|
||||
'ctrl-alt-up': 'editor:add-selection-above'
|
||||
'ctrl-alt-down': 'editor:add-selection-below'
|
||||
'ctrl-=': 'window:increase-font-size'
|
||||
'ctrl-+': 'window:increase-font-size'
|
||||
'ctrl--': 'window:decrease-font-size'
|
||||
@@ -57,12 +69,19 @@
|
||||
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
|
||||
|
||||
'.workspace .editor':
|
||||
# Windows specific
|
||||
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
|
||||
# Platform Bindings
|
||||
'ctrl-left': 'editor:move-to-beginning-of-word'
|
||||
'ctrl-right': 'editor:move-to-end-of-word'
|
||||
'ctrl-shift-left': 'editor:select-to-beginning-of-word'
|
||||
'ctrl-shift-right': 'editor:select-to-end-of-word'
|
||||
'ctrl-backspace': 'editor:delete-to-beginning-of-word'
|
||||
'ctrl-delete': 'editor:delete-to-end-of-word'
|
||||
'ctrl-home': 'core:move-to-top'
|
||||
'ctrl-end': 'core:move-to-bottom'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-a': 'core:select-all'
|
||||
'ctrl-alt-p': 'editor:log-cursor-scope'
|
||||
'ctrl-alt-shift-p': 'editor:log-cursor-scope'
|
||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||
|
||||
|
||||
@@ -134,6 +134,25 @@
|
||||
submenu: [
|
||||
{ label: 'Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle Full Screen', command: 'window:toggle-full-screen' }
|
||||
{
|
||||
label: 'Panes'
|
||||
submenu: [
|
||||
{ label: 'Split Up', command: 'pane:split-up' }
|
||||
{ label: 'Split Down', command: 'pane:split-down' }
|
||||
{ label: 'Split Left', command: 'pane:split-left' }
|
||||
{ label: 'Split Right', command: 'pane:split-right' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Focus Next Pane', command: 'window:focus-next-pane' }
|
||||
{ label: 'Focus Previous Pane', command: 'window:focus-previous-pane' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Focus Pane Above', command: 'window:focus-pane-above' }
|
||||
{ label: 'Focus Pane Below', command: 'window:focus-pane-below' }
|
||||
{ label: 'Focus Pane On Left', command: 'window:focus-pane-on-left' }
|
||||
{ label: 'Focus Pane On Right', command: 'window:focus-pane-on-right' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Close Pane', command: 'pane:close' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
@@ -166,6 +185,7 @@
|
||||
{
|
||||
label: 'Help'
|
||||
submenu: [
|
||||
{ label: 'Terms of Use', command: 'application:open-terms-of-use' }
|
||||
{ label: 'Documentation', command: 'application:open-documentation' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
{ label: 'View &Terms of Use', command: 'application:open-terms-of-use' }
|
||||
{ label: 'View &License', command: 'application:open-license' }
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ type: 'separator' }
|
||||
|
||||
+21
-3
@@ -8,7 +8,7 @@
|
||||
{ label: 'Open Folder...', command: 'application:open-folder' }
|
||||
{ label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Preferences...', command: 'application:show-settings' }
|
||||
{ label: 'Se&ttings', command: 'application:show-settings' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Save', command: 'core:save' }
|
||||
{ label: 'Save &As...', command: 'core:save-as' }
|
||||
@@ -88,6 +88,25 @@
|
||||
submenu: [
|
||||
{ label: '&Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' }
|
||||
{
|
||||
label: 'Panes'
|
||||
submenu: [
|
||||
{ label: 'Split Up', command: 'pane:split-up' }
|
||||
{ label: 'Split Down', command: 'pane:split-down' }
|
||||
{ label: 'Split Left', command: 'pane:split-left' }
|
||||
{ label: 'Split Right', command: 'pane:split-right' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Focus Next Pane', command: 'window:focus-next-pane' }
|
||||
{ label: 'Focus Previous Pane', command: 'window:focus-previous-pane' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Focus Pane Above', command: 'window:focus-pane-above' }
|
||||
{ label: 'Focus Pane Below', command: 'window:focus-pane-below' }
|
||||
{ label: 'Focus Pane On Left', command: 'window:focus-pane-on-left' }
|
||||
{ label: 'Focus Pane On Right', command: 'window:focus-pane-on-right' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Close pane', command: 'pane:close' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
@@ -145,10 +164,9 @@
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
{ label: '&About Atom...', command: 'application:about' }
|
||||
{ label: 'View &Terms of Use', command: 'application:open-terms-of-use' }
|
||||
{ label: 'View &License', command: 'application:open-license' }
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ label: "Install &update", command: 'application:install-update', visible: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ type: 'separator' }
|
||||
|
||||
+77
-72
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.91.0",
|
||||
"version": "0.102.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -11,125 +11,130 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"license": "All Rights Reserved",
|
||||
"atomShellVersion": "0.11.10",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.13.0",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^0.18.0",
|
||||
"bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"atom-keymap": "^0.26.0",
|
||||
"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.x",
|
||||
"delegato": "^1",
|
||||
"emissary": "^1.2.1",
|
||||
"first-mate": "^1.5.2",
|
||||
"fs-plus": "^2.2.2",
|
||||
"first-mate": "^1.7",
|
||||
"fs-plus": "^2.2.3",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "~1.1",
|
||||
"git-utils": "^1.2.2",
|
||||
"grim": "0.9.0",
|
||||
"fuzzaldrin": "^1.1",
|
||||
"git-utils": "^1.3",
|
||||
"grim": "0.10.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-tagged": "^1.1.1",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"less-cache": "0.12.0",
|
||||
"mixto": "1.x",
|
||||
"mixto": "^1",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "0.5.0",
|
||||
"oniguruma": "^1.0.6",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^1.2.1",
|
||||
"property-accessors": "1.x",
|
||||
"pathwatcher": "^1.3.2",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
"react": "^0.10.0",
|
||||
"reactionary": "^0.8.0",
|
||||
"runas": "0.5.x",
|
||||
"react-atom-fork": "^0.10.0",
|
||||
"reactionary-atom-fork": "^0.9.0",
|
||||
"runas": "^0.5",
|
||||
"scandal": "0.15.2",
|
||||
"scoped-property-store": "^0.8.0",
|
||||
"scrollbar-style": "^0.1.0",
|
||||
"scoped-property-store": "^0.9.0",
|
||||
"scrollbar-style": "^0.4.0",
|
||||
"season": "^1.0.2",
|
||||
"semver": "1.1.4",
|
||||
"serializable": "1.x",
|
||||
"space-pen": "3.1.1",
|
||||
"serializable": "^1",
|
||||
"space-pen": "3.3.0",
|
||||
"temp": "0.5.0",
|
||||
"text-buffer": "^2.1.0",
|
||||
"theorist": "1.x",
|
||||
"underscore-plus": "^1.2.1",
|
||||
"text-buffer": "^2.2.2",
|
||||
"theorist": "^1",
|
||||
"underscore-plus": "^1.4.1",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.15.0",
|
||||
"atom-dark-ui": "0.26.0",
|
||||
"atom-dark-syntax": "0.16.0",
|
||||
"atom-dark-ui": "0.29.0",
|
||||
"atom-light-syntax": "0.17.0",
|
||||
"atom-light-ui": "0.24.0",
|
||||
"base16-tomorrow-dark-theme": "0.15.0",
|
||||
"solarized-dark-syntax": "0.14.0",
|
||||
"solarized-light-syntax": "0.7.0",
|
||||
"archive-view": "0.30.0",
|
||||
"autocomplete": "0.27.0",
|
||||
"autoflow": "0.16.0",
|
||||
"atom-light-ui": "0.25.0",
|
||||
"base16-tomorrow-dark-theme": "0.16.0",
|
||||
"solarized-dark-syntax": "0.17.0",
|
||||
"solarized-light-syntax": "0.8.0",
|
||||
"archive-view": "0.31.0",
|
||||
"autocomplete": "0.28.0",
|
||||
"autoflow": "0.17.0",
|
||||
"autosave": "0.13.0",
|
||||
"background-tips": "0.13.0",
|
||||
"background-tips": "0.14.0",
|
||||
"bookmarks": "0.22.0",
|
||||
"bracket-matcher": "0.33.0",
|
||||
"bracket-matcher": "0.43.0",
|
||||
"command-palette": "0.21.0",
|
||||
"deprecation-cop": "0.5.0",
|
||||
"dev-live-reload": "0.30.0",
|
||||
"exception-reporting": "0.17.0",
|
||||
"feedback": "0.30.0",
|
||||
"find-and-replace": "0.99.0",
|
||||
"fuzzy-finder": "0.50.0",
|
||||
"deprecation-cop": "0.6.0",
|
||||
"dev-live-reload": "0.31.0",
|
||||
"exception-reporting": "0.18.0",
|
||||
"feedback": "0.33.0",
|
||||
"find-and-replace": "0.113.0",
|
||||
"fuzzy-finder": "0.54.0",
|
||||
"git-diff": "0.28.0",
|
||||
"go-to-line": "0.19.0",
|
||||
"grammar-selector": "0.24.0",
|
||||
"image-view": "0.33.0",
|
||||
"keybinding-resolver": "0.17.0",
|
||||
"go-to-line": "0.22.0",
|
||||
"grammar-selector": "0.27.0",
|
||||
"image-view": "0.34.0",
|
||||
"keybinding-resolver": "0.18.0",
|
||||
"link": "0.22.0",
|
||||
"markdown-preview": "0.64.0",
|
||||
"markdown-preview": "0.74.0",
|
||||
"metrics": "0.32.0",
|
||||
"open-on-github": "0.28.0",
|
||||
"package-generator": "0.30.0",
|
||||
"release-notes": "0.27.0",
|
||||
"settings-view": "0.110.0",
|
||||
"snippets": "0.41.0",
|
||||
"spell-check": "0.34.0",
|
||||
"release-notes": "0.32.0",
|
||||
"settings-view": "0.119.0",
|
||||
"snippets": "0.45.0",
|
||||
"spell-check": "0.36.0",
|
||||
"status-bar": "0.40.0",
|
||||
"styleguide": "0.29.0",
|
||||
"symbols-view": "0.49.0",
|
||||
"tabs": "0.37.0",
|
||||
"timecop": "0.18.0",
|
||||
"tree-view": "0.90.0",
|
||||
"symbols-view": "0.55.0",
|
||||
"tabs": "0.41.0",
|
||||
"timecop": "0.19.0",
|
||||
"tree-view": "0.98.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.12.0",
|
||||
"welcome": "0.16.0",
|
||||
"whitespace": "0.22.0",
|
||||
"wrap-guide": "0.18.0",
|
||||
"language-c": "0.14.0",
|
||||
"language-c": "0.16.0",
|
||||
"language-coffee-script": "0.22.0",
|
||||
"language-css": "0.16.0",
|
||||
"language-gfm": "0.31.0",
|
||||
"language-css": "0.17.0",
|
||||
"language-gfm": "0.39.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.9.0",
|
||||
"language-html": "0.19.0",
|
||||
"language-hyperlink": "0.9.0",
|
||||
"language-java": "0.9.0",
|
||||
"language-javascript": "0.24.0",
|
||||
"language-go": "0.12.0",
|
||||
"language-html": "0.22.0",
|
||||
"language-hyperlink": "0.10.0",
|
||||
"language-java": "0.10.0",
|
||||
"language-javascript": "0.26.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.8.0",
|
||||
"language-less": "0.9.0",
|
||||
"language-make": "0.10.0",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.8.0",
|
||||
"language-php": "0.14.0",
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.15.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.15.0",
|
||||
"language-ruby": "0.22.0",
|
||||
"language-ruby-on-rails": "0.12.0",
|
||||
"language-sass": "0.10.0",
|
||||
"language-python": "0.18.0",
|
||||
"language-ruby": "0.27.0",
|
||||
"language-ruby-on-rails": "0.14.0",
|
||||
"language-sass": "0.13.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.7.0",
|
||||
"language-sql": "0.8.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.10.0",
|
||||
"language-toml": "0.12.0",
|
||||
"language-xml": "0.11.0",
|
||||
"language-xml": "0.14.0",
|
||||
"language-yaml": "0.6.0"
|
||||
},
|
||||
"private": true,
|
||||
|
||||
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 191 KiB Depois Largura: | Altura: | Tamanho: 284 KiB |
+267
-89
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 361 KiB Depois Largura: | Altura: | Tamanho: 141 KiB |
+32
-27
@@ -1,13 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var nodeMinorVersion = process.versions.node.split('.')[1]
|
||||
if (nodeMinorVersion !== '10') {
|
||||
console.warn("You must run script/bootstrap and script/build with node v0.10.x");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var safeExec = require('./utils/child-process-wrapper.js').safeExec;
|
||||
var fs = require('fs');
|
||||
var verifyRequirements = require('./utils/verify-requirements');
|
||||
var safeExec = require('./utils/child-process-wrapper.js').safeExec;
|
||||
var path = require('path');
|
||||
|
||||
// Executes an array of commands one by one.
|
||||
@@ -21,37 +16,47 @@ function executeCommands(commands, done, index) {
|
||||
command = command.command;
|
||||
}
|
||||
safeExec(command, options, executeCommands.bind(this, commands, done, index + 1));
|
||||
} else
|
||||
}
|
||||
else
|
||||
done(null);
|
||||
}
|
||||
|
||||
var apmVendorPath = path.resolve(__dirname, '..', 'vendor', 'apm');
|
||||
var apmInstallPath = path.resolve(__dirname, '..', 'apm');
|
||||
if (!fs.existsSync(apmInstallPath))
|
||||
function bootstrap() {
|
||||
var apmInstallPath = path.resolve(__dirname, '..', 'apm');
|
||||
if (!fs.existsSync(apmInstallPath))
|
||||
fs.mkdirSync(apmInstallPath);
|
||||
if (!fs.existsSync(path.join(apmInstallPath, 'node_modules')))
|
||||
if (!fs.existsSync(path.join(apmInstallPath, 'node_modules')))
|
||||
fs.mkdirSync(path.join(apmInstallPath, 'node_modules'));
|
||||
|
||||
var apmPath = 'apm/node_modules/atom-package-manager/bin/apm'
|
||||
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
|
||||
var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm')
|
||||
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
|
||||
|
||||
var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm');
|
||||
var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' ';
|
||||
var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm');
|
||||
var initialNpmCommand = fs.existsSync(npmPath) ? npmPath : 'npm';
|
||||
var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' ';
|
||||
|
||||
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season'];
|
||||
var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo';
|
||||
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season'];
|
||||
var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo';
|
||||
|
||||
var commands = [
|
||||
'git submodule --quiet sync',
|
||||
'git submodule --quiet update --recursive --init',
|
||||
{command: 'npm' + npmFlags + 'install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
|
||||
{command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmVendorPath, ignoreStdout: true}},
|
||||
{command: npmPath + npmFlags + 'install --quiet ' + apmVendorPath, options: {cwd: apmInstallPath, ignoreStdout: true}},
|
||||
var commands = [
|
||||
{command: initialNpmCommand + npmFlags + 'install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
|
||||
{command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmInstallPath, ignoreStdout: true}},
|
||||
echoNewLine,
|
||||
apmPath + ' clean ' + apmFlags,
|
||||
apmPath + ' install --quiet ' + apmFlags,
|
||||
apmPath + ' dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '),
|
||||
];
|
||||
];
|
||||
|
||||
process.chdir(path.dirname(__dirname));
|
||||
executeCommands(commands, process.exit);
|
||||
process.chdir(path.dirname(__dirname));
|
||||
executeCommands(commands, process.exit);
|
||||
}
|
||||
|
||||
verifyRequirements(function(error, successMessage) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(successMessage);
|
||||
bootstrap();
|
||||
});
|
||||
|
||||
+15
-13
@@ -28,17 +28,19 @@ function readEnvironmentVariables() {
|
||||
}
|
||||
|
||||
readEnvironmentVariables();
|
||||
cp.safeExec.bind(global, 'node script/bootstrap', function(error) {
|
||||
if (error)
|
||||
process.exit(1);
|
||||
require('fs-plus').removeSync.bind(global, path.join(homeDir, '.atom'))
|
||||
var async = require('async');
|
||||
var gruntPath = path.join('build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
|
||||
var tasks = [
|
||||
cp.safeExec.bind(global, 'git clean -dff'),
|
||||
cp.safeExec.bind(global, gruntPath + ' ci --gruntfile build/Gruntfile.coffee --stack --no-color'),
|
||||
]
|
||||
async.series(tasks, function(error) {
|
||||
process.exit(error ? 1 : 0);
|
||||
});
|
||||
cp.safeExec.bind(global, 'npm install npm', {cwd: path.resolve(__dirname, '..', 'build')}, function() {
|
||||
cp.safeExec.bind(global, 'node script/bootstrap', function(error) {
|
||||
if (error)
|
||||
process.exit(1);
|
||||
require('fs-plus').removeSync.bind(global, path.join(homeDir, '.atom'))
|
||||
var async = require('async');
|
||||
var gruntPath = path.join('build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
|
||||
var tasks = [
|
||||
cp.safeExec.bind(global, 'git clean -dff'),
|
||||
cp.safeExec.bind(global, gruntPath + ' ci --gruntfile build/Gruntfile.coffee --stack --no-color'),
|
||||
]
|
||||
async.series(tasks, function(error) {
|
||||
process.exit(error ? 1 : 0);
|
||||
});
|
||||
})();
|
||||
})();
|
||||
|
||||
+12
-5
@@ -1,14 +1,15 @@
|
||||
#!/usr/bin/env node
|
||||
var cp = require('./utils/child-process-wrapper.js');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
|
||||
var removeCommand = process.platform === 'win32' ? 'del /F /Q /S ' : 'rm -rf ';
|
||||
var removeCommand = process.platform === 'win32' ? 'rmdir /S /Q ' : 'rm -rf ';
|
||||
var productName = require('../package.json').productName;
|
||||
|
||||
process.chdir(path.dirname(__dirname));
|
||||
var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
|
||||
var tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp';
|
||||
var tmpdir = os.tmpdir();
|
||||
|
||||
// Windows: Use START as a way to ignore error if Atom.exe isnt running
|
||||
var killatom = process.platform === 'win32' ? 'START taskkill /F /IM ' + productName + '.exe' : 'pkill -9 ' + productName + ' || true';
|
||||
@@ -18,7 +19,6 @@ var commands = [
|
||||
[__dirname, '..', 'node_modules'],
|
||||
[__dirname, '..', 'build', 'node_modules'],
|
||||
[__dirname, '..', 'apm', 'node_modules'],
|
||||
[__dirname, '..', 'vendor', 'apm', 'node_modules'],
|
||||
[__dirname, '..', 'atom-shell'],
|
||||
[home, '.atom', '.node-gyp'],
|
||||
[home, '.atom', 'storage'],
|
||||
@@ -31,8 +31,15 @@ var run = function() {
|
||||
var next = commands.shift();
|
||||
if (!next)
|
||||
process.exit(0);
|
||||
if (Array.isArray(next))
|
||||
next = removeCommand + path.resolve.apply(path.resolve, next);
|
||||
|
||||
if (Array.isArray(next)) {
|
||||
var pathToRemove = path.resolve.apply(path.resolve, next);
|
||||
if (fs.existsSync(pathToRemove))
|
||||
next = removeCommand + pathToRemove;
|
||||
else
|
||||
return run();
|
||||
}
|
||||
|
||||
cp.safeExec(next, run);
|
||||
};
|
||||
run();
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
var cp = require('./utils/child-process-wrapper.js');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// node build/node_modules/.bin/grunt "$@"
|
||||
var gruntPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
|
||||
|
||||
if (!fs.existsSync(gruntPath)) {
|
||||
console.error('Grunt command does not exist at: ' + gruntPath);
|
||||
console.error('Run script/bootstrap to install Grunt');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var args = ['--gruntfile', path.resolve('build', 'Gruntfile.coffee')];
|
||||
args = args.concat(process.argv.slice(2));
|
||||
cp.safeSpawn(gruntPath, args, process.exit);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
@IF EXIST "%~dp0\node.exe" (
|
||||
"%~dp0\node.exe" "%~dp0\grunt" %*
|
||||
) ELSE (
|
||||
node "%~dp0\grunt" %*
|
||||
)
|
||||
+12
-8
@@ -1,31 +1,35 @@
|
||||
#!/bin/bash
|
||||
# mkdeb version control-file-path deb-file-path
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT=`readlink -f "$0"`
|
||||
ROOT=`readlink -f $(dirname $SCRIPT)/..`
|
||||
cd $ROOT
|
||||
|
||||
VERSION="$1"
|
||||
CONTROL_FILE="$2"
|
||||
DESKTOP_FILE="$3"
|
||||
ICON_FILE="$4"
|
||||
DEB_PATH="$5"
|
||||
ARCH="$2"
|
||||
CONTROL_FILE="$3"
|
||||
DESKTOP_FILE="$4"
|
||||
ICON_FILE="$5"
|
||||
DEB_PATH="$6"
|
||||
|
||||
TARGET_ROOT="`mktemp -d`"
|
||||
TARGET="$TARGET_ROOT/atom-$VERSION-amd64"
|
||||
chmod 755 "$TARGET_ROOT"
|
||||
TARGET="$TARGET_ROOT/atom-$VERSION-$ARCH"
|
||||
|
||||
mkdir -p "$TARGET/usr"
|
||||
env INSTALL_PREFIX="$TARGET/usr" script/grunt install
|
||||
|
||||
mkdir -p "$TARGET/DEBIAN"
|
||||
mv "$CONTROL_FILE" "$TARGET/DEBIAN/control"
|
||||
cp "$CONTROL_FILE" "$TARGET/DEBIAN/control"
|
||||
|
||||
mkdir -p "$TARGET/usr/share/applications"
|
||||
mv "$DESKTOP_FILE" "$TARGET/usr/share/applications"
|
||||
cp "$DESKTOP_FILE" "$TARGET/usr/share/applications"
|
||||
|
||||
mkdir -p "$TARGET/usr/share/pixmaps"
|
||||
cp "$ICON_FILE" "$TARGET/usr/share/pixmaps"
|
||||
|
||||
dpkg-deb -b "$TARGET"
|
||||
mv "$TARGET_ROOT/atom-$VERSION-amd64.deb" "$DEB_PATH"
|
||||
mv "$TARGET_ROOT/atom-$VERSION-$ARCH.deb" "$DEB_PATH"
|
||||
rm -rf $TARGET_ROOT
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var childProcess = require('child_process');
|
||||
|
||||
var pythonExecutable = process.env.PYTHON;
|
||||
|
||||
module.exports = function(cb) {
|
||||
verifyNode(function(error, nodeSuccessMessage) {
|
||||
if (error) {
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
verifyPython27(function(error, pythonSuccessMessage) {
|
||||
cb(error, (nodeSuccessMessage + "\n" + pythonSuccessMessage).trim());
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
function verifyNode(cb) {
|
||||
var nodeVersion = process.versions.node;
|
||||
var versionArray = nodeVersion.split('.');
|
||||
var nodeMajorVersion = +versionArray[0];
|
||||
var nodeMinorVersion = +versionArray[1];
|
||||
if (nodeMajorVersion === 0 && nodeMinorVersion < 10) {
|
||||
error = "node v0.10 is required to build Atom.";
|
||||
cb(error);
|
||||
}
|
||||
else {
|
||||
cb(null, "Node: v" + nodeVersion);
|
||||
}
|
||||
}
|
||||
|
||||
function verifyPython27(cb) {
|
||||
if (process.platform == 'win32') {
|
||||
if (!pythonExecutable) {
|
||||
var systemDrive = process.env.SystemDrive || 'C:\\';
|
||||
pythonExecutable = path.join(systemDrive, 'Python27', 'python.exe');
|
||||
|
||||
if (!fs.existsSync(pythonExecutable)) {
|
||||
pythonExecutable = 'python';
|
||||
}
|
||||
}
|
||||
|
||||
checkPythonVersion(pythonExecutable, cb);
|
||||
}
|
||||
else {
|
||||
cb(null, '');
|
||||
}
|
||||
}
|
||||
|
||||
function checkPythonVersion (python, cb) {
|
||||
var pythonHelpMessage = "Set the PYTHON env var to '/path/to/Python27/python.exe' if your python is installed in a non-default location.";
|
||||
|
||||
childProcess.execFile(python, ['-c', 'import platform; print(platform.python_version());'], { env: process.env }, function (err, stdout) {
|
||||
if (err) {
|
||||
error = "Python 2.7 is required to build Atom. An error (" + err + ") occured when checking the version of '" + python + "'. ";
|
||||
error += pythonHelpMessage;
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
var version = stdout.trim();
|
||||
if (~version.indexOf('+')) {
|
||||
version = version.replace(/\+/g, '');
|
||||
}
|
||||
if (~version.indexOf('rc')) {
|
||||
version = version.replace(/rc(.*)$/ig, '');
|
||||
}
|
||||
|
||||
// Atom requires python 2.7 or higher (but not python 3) for node-gyp
|
||||
var versionArray = version.split('.').map(function(num) { return +num; });
|
||||
var goodPythonVersion = (versionArray[0] === 2 && versionArray[1] >= 7);
|
||||
if (!goodPythonVersion) {
|
||||
error = "Python 2.7 is required to build Atom. '" + python + "' returns version " + version + ". ";
|
||||
error += pythonHelpMessage;
|
||||
cb(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, if we've gotten this far, callback to resume the install process.
|
||||
cb(null, "Python: v" + version);
|
||||
});
|
||||
}
|
||||
@@ -7,8 +7,8 @@ sourceMaps = {}
|
||||
formatStackTrace = (spec, message='', stackTrace) ->
|
||||
return stackTrace unless stackTrace
|
||||
|
||||
jasminePattern = /^\s*at\s+.*\(?.*\/jasmine(-[^\/]*)?\.js:\d+:\d+\)?\s*$/
|
||||
firstJasmineLinePattern = /^\s*at \/.*\/jasmine(-[^\/]*)?\.js:\d+:\d+\)?\s*$/
|
||||
jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
|
||||
firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
|
||||
convertedLines = []
|
||||
for line in stackTrace.split('\n')
|
||||
convertedLines.push(line) unless jasminePattern.test(line)
|
||||
@@ -23,7 +23,7 @@ formatStackTrace = (spec, message='', stackTrace) ->
|
||||
|
||||
for line, index in lines
|
||||
# Remove prefix of lines matching: at [object Object].<anonymous> (path:1:2)
|
||||
prefixMatch = line.match(/at \[object Object\]\.<anonymous> \(([^\)]+)\)/)
|
||||
prefixMatch = line.match(/at \[object Object\]\.<anonymous> \(([^)]+)\)/)
|
||||
line = "at #{prefixMatch[1]}" if prefixMatch
|
||||
|
||||
# Relativize locations to spec directory
|
||||
|
||||
+33
-30
@@ -113,18 +113,21 @@ describe "the `atom` global", ->
|
||||
promise
|
||||
|
||||
it "triggers the activation event on all handlers registered during activation", ->
|
||||
atom.workspaceView.openSync()
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
eventHandler = jasmine.createSpy("activation-event")
|
||||
editorView.command 'activation-event', eventHandler
|
||||
editorView.trigger 'activation-event'
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
expect(mainModule.activationEventCallCount).toBe 1
|
||||
expect(eventHandler.callCount).toBe 1
|
||||
editorView.trigger 'activation-event'
|
||||
expect(mainModule.activationEventCallCount).toBe 2
|
||||
expect(eventHandler.callCount).toBe 2
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
waitsForPromise ->
|
||||
atom.workspaceView.open()
|
||||
|
||||
runs ->
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
eventHandler = jasmine.createSpy("activation-event")
|
||||
editorView.command 'activation-event', eventHandler
|
||||
editorView.trigger 'activation-event'
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
expect(mainModule.activationEventCallCount).toBe 1
|
||||
expect(eventHandler.callCount).toBe 1
|
||||
editorView.trigger 'activation-event'
|
||||
expect(mainModule.activationEventCallCount).toBe 2
|
||||
expect(eventHandler.callCount).toBe 2
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
|
||||
it "activates the package immediately when the events are empty", ->
|
||||
mainModule = require './fixtures/packages/package-with-empty-activation-events/index'
|
||||
@@ -170,28 +173,28 @@ describe "the `atom` global", ->
|
||||
element2 = $$ -> @div class: 'test-2'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)).toHaveLength 0
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
|
||||
|
||||
atom.packages.activatePackage("package-with-keymaps")
|
||||
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe "test-1"
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)[0].command).toBe "test-2"
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe "test-1"
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])[0].command).toBe "test-2"
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
|
||||
|
||||
describe "when the metadata contains a 'keymaps' manifest", ->
|
||||
it "loads only the keymaps specified by the manifest, in the specified order", ->
|
||||
element1 = $$ -> @div class: 'test-1'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])).toHaveLength 0
|
||||
|
||||
atom.packages.activatePackage("package-with-keymaps-manifest")
|
||||
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe 'keymap-1'
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-n', element1)[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-y', element3)).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe 'keymap-1'
|
||||
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 "menu loading", ->
|
||||
beforeEach ->
|
||||
@@ -377,8 +380,8 @@ describe "the `atom` global", ->
|
||||
|
||||
runs ->
|
||||
atom.packages.deactivatePackage('package-with-keymaps')
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target: ($$ -> @div class: 'test-1')[0])).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target: ($$ -> @div class: 'test-2')[0])).toHaveLength 0
|
||||
|
||||
it "removes the package's stylesheets", ->
|
||||
waitsForPromise ->
|
||||
@@ -507,20 +510,20 @@ describe "the `atom` global", ->
|
||||
# enabling of theme
|
||||
pack = atom.packages.enablePackage(packageName)
|
||||
|
||||
activatedPackages = null
|
||||
waitsFor ->
|
||||
activatedPackages = atom.packages.getActivePackages()
|
||||
activatedPackages.length > 0
|
||||
pack in atom.packages.getActivePackages()
|
||||
|
||||
runs ->
|
||||
expect(activatedPackages).toContain(pack)
|
||||
expect(atom.config.get('core.themes')).toContain packageName
|
||||
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
|
||||
|
||||
# disabling of theme
|
||||
pack = atom.packages.disablePackage(packageName)
|
||||
activatedPackages = atom.packages.getActivePackages()
|
||||
expect(activatedPackages).not.toContain(pack)
|
||||
|
||||
waitsFor ->
|
||||
not (pack in atom.packages.getActivePackages())
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get('core.themes')).not.toContain packageName
|
||||
expect(atom.config.get('core.themes')).not.toContain packageName
|
||||
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
|
||||
|
||||
@@ -5,6 +5,10 @@ fs = require 'fs-plus'
|
||||
|
||||
describe "Config", ->
|
||||
dotAtomPath = path.join(temp.dir, 'dot-atom-dir')
|
||||
dotAtomPath = null
|
||||
|
||||
beforeEach ->
|
||||
dotAtomPath = temp.path('dot-atom-dir')
|
||||
|
||||
describe ".get(keyPath)", ->
|
||||
it "allows a key path's value to be read", ->
|
||||
@@ -258,8 +262,10 @@ describe "Config", ->
|
||||
|
||||
describe ".initializeConfigDirectory()", ->
|
||||
beforeEach ->
|
||||
if fs.existsSync(dotAtomPath)
|
||||
fs.removeSync(dotAtomPath)
|
||||
|
||||
atom.config.configDirPath = dotAtomPath
|
||||
expect(fs.existsSync(atom.config.configDirPath)).toBeFalsy()
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(dotAtomPath)
|
||||
|
||||
@@ -17,6 +17,22 @@ describe "ContextMenuManager", ->
|
||||
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
|
||||
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
|
||||
|
||||
it "loads submenus", ->
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
'parent':
|
||||
'child-1': 'child-1:trigger'
|
||||
'child-2': 'child-2:trigger'
|
||||
'parent-2': 'parent-2:trigger'
|
||||
|
||||
expect(contextMenu.definitions['.selector'].length).toBe 2
|
||||
expect(contextMenu.definitions['.selector'][0].label).toEqual 'parent'
|
||||
expect(contextMenu.definitions['.selector'][0].submenu.length).toBe 2
|
||||
expect(contextMenu.definitions['.selector'][0].submenu[0].label).toBe 'child-1'
|
||||
expect(contextMenu.definitions['.selector'][0].submenu[0].command).toBe 'child-1:trigger'
|
||||
expect(contextMenu.definitions['.selector'][0].submenu[1].label).toBe 'child-2'
|
||||
expect(contextMenu.definitions['.selector'][0].submenu[1].command).toBe 'child-2:trigger'
|
||||
|
||||
describe 'dev mode', ->
|
||||
it 'loads', ->
|
||||
contextMenu.add 'file-path',
|
||||
@@ -105,7 +121,7 @@ describe "ContextMenuManager", ->
|
||||
expect(menu[2].command).toEqual 'dev-command'
|
||||
expect(menu[3]).toBeUndefined()
|
||||
|
||||
describe "#executeBuildHandlers", ->
|
||||
describe "executeBuildHandlers", ->
|
||||
menuTemplate = [
|
||||
label: 'label'
|
||||
executeAtBuild: ->
|
||||
@@ -119,4 +135,3 @@ describe "ContextMenuManager", ->
|
||||
|
||||
expect(buildFn).toHaveBeenCalled()
|
||||
expect(buildFn.mostRecentCall.args[0]).toBe event
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ describe "DisplayBuffer", ->
|
||||
describe "::copy()", ->
|
||||
it "creates a new DisplayBuffer with the same initial state", ->
|
||||
marker1 = displayBuffer.markBufferRange([[1, 2], [3, 4]], id: 1)
|
||||
marker2 = displayBuffer.markBufferRange([[2, 3], [4, 5]], isReversed: true, id: 2)
|
||||
marker2 = displayBuffer.markBufferRange([[2, 3], [4, 5]], reversed: true, id: 2)
|
||||
marker3 = displayBuffer.markBufferPosition([5, 6], id: 3)
|
||||
displayBuffer.createFold(3, 5)
|
||||
|
||||
@@ -948,7 +948,7 @@ describe "DisplayBuffer", ->
|
||||
it "returns the start and end positions of the marker based on the line height and character widths assigned to the DisplayBuffer", ->
|
||||
marker = displayBuffer.markScreenRange([[5, 10], [6, 4]])
|
||||
|
||||
displayBuffer.setLineHeight(20)
|
||||
displayBuffer.setLineHeightInPixels(20)
|
||||
displayBuffer.setDefaultCharWidth(10)
|
||||
displayBuffer.setScopedCharWidths(["source.js", "keyword.control.js"], r: 11, e: 11, t: 11, u: 11, n: 11)
|
||||
|
||||
@@ -959,7 +959,7 @@ describe "DisplayBuffer", ->
|
||||
describe "::setScrollTop", ->
|
||||
beforeEach ->
|
||||
displayBuffer.manageScrollPosition = true
|
||||
displayBuffer.setLineHeight(10)
|
||||
displayBuffer.setLineHeightInPixels(10)
|
||||
|
||||
it "disallows negative values", ->
|
||||
displayBuffer.setHeight(displayBuffer.getScrollHeight() + 100)
|
||||
@@ -979,6 +979,7 @@ describe "DisplayBuffer", ->
|
||||
describe "::setScrollLeft", ->
|
||||
beforeEach ->
|
||||
displayBuffer.manageScrollPosition = true
|
||||
displayBuffer.setLineHeightInPixels(10)
|
||||
displayBuffer.setDefaultCharWidth(10)
|
||||
|
||||
it "disallows negative values", ->
|
||||
@@ -999,8 +1000,9 @@ describe "DisplayBuffer", ->
|
||||
describe "::scrollToScreenPosition(position)", ->
|
||||
it "sets the scroll top and scroll left so the given screen position is in view", ->
|
||||
displayBuffer.manageScrollPosition = true
|
||||
displayBuffer.setLineHeight(10)
|
||||
displayBuffer.setLineHeightInPixels(10)
|
||||
displayBuffer.setDefaultCharWidth(10)
|
||||
displayBuffer.setHorizontalScrollbarHeight(0)
|
||||
|
||||
displayBuffer.setHeight(50)
|
||||
displayBuffer.setWidth(50)
|
||||
|
||||
+528
-166
@@ -1,12 +1,16 @@
|
||||
{extend, flatten, toArray} = require 'underscore-plus'
|
||||
_ = require 'underscore-plus'
|
||||
{extend, flatten, toArray, last} = _
|
||||
|
||||
ReactEditorView = require '../src/react-editor-view'
|
||||
nbsp = String.fromCharCode(160)
|
||||
|
||||
describe "EditorComponent", ->
|
||||
[editor, wrapperView, component, node, verticalScrollbarNode, horizontalScrollbarNode] = []
|
||||
[lineHeightInPixels, charWidth, delayAnimationFrames, nextAnimationFrame] = []
|
||||
[contentNode, editor, wrapperView, component, node, verticalScrollbarNode, horizontalScrollbarNode] = []
|
||||
[lineHeightInPixels, charWidth, delayAnimationFrames, nextAnimationFrame, lineOverdrawMargin] = []
|
||||
|
||||
beforeEach ->
|
||||
lineOverdrawMargin = 2
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
|
||||
@@ -22,67 +26,163 @@ describe "EditorComponent", ->
|
||||
else
|
||||
fn()
|
||||
|
||||
editor = atom.project.openSync('sample.js')
|
||||
wrapperView = new ReactEditorView(editor)
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
contentNode = document.querySelector('#jasmine-content')
|
||||
contentNode.style.width = '1000px'
|
||||
|
||||
wrapperView = new ReactEditorView(editor, {lineOverdrawMargin})
|
||||
wrapperView.attachToDom()
|
||||
{component} = wrapperView
|
||||
component.setLineHeight(1.3)
|
||||
component.setFontSize(20)
|
||||
|
||||
lineHeightInPixels = editor.getLineHeight()
|
||||
lineHeightInPixels = editor.getLineHeightInPixels()
|
||||
charWidth = editor.getDefaultCharWidth()
|
||||
node = component.getDOMNode()
|
||||
verticalScrollbarNode = node.querySelector('.vertical-scrollbar')
|
||||
horizontalScrollbarNode = node.querySelector('.horizontal-scrollbar')
|
||||
|
||||
node.style.height = editor.getLineCount() * lineHeightInPixels + 'px'
|
||||
node.style.width = '1000px'
|
||||
component.measureScrollView()
|
||||
|
||||
afterEach ->
|
||||
contentNode.style.width = ''
|
||||
|
||||
describe "line rendering", ->
|
||||
it "renders only the currently-visible lines", ->
|
||||
it "renders the currently-visible lines plus the overdraw margin", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
lines = node.querySelectorAll('.line')
|
||||
expect(lines.length).toBe 6
|
||||
expect(lines[0].textContent).toBe editor.lineForScreenRow(0).text
|
||||
expect(lines[5].textContent).toBe editor.lineForScreenRow(5).text
|
||||
linesNode = node.querySelector('.lines')
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
expect(node.querySelectorAll('.line').length).toBe 6 + 2 # no margin above
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe editor.lineForScreenRow(0).text
|
||||
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0
|
||||
expect(component.lineNodeForScreenRow(5).textContent).toBe editor.lineForScreenRow(5).text
|
||||
expect(component.lineNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels
|
||||
|
||||
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
|
||||
expect(node.querySelector('.scroll-view-content').style['-webkit-transform']).toBe "translate3d(0px, #{-2.5 * lineHeightInPixels}px, 0)"
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, #{-4.5 * lineHeightInPixels}px, 0px)"
|
||||
expect(node.querySelectorAll('.line').length).toBe 6 + 4 # margin above and below
|
||||
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(2).textContent).toBe editor.lineForScreenRow(2).text
|
||||
expect(component.lineNodeForScreenRow(9).offsetTop).toBe 9 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(9).textContent).toBe editor.lineForScreenRow(9).text
|
||||
|
||||
lineNodes = node.querySelectorAll('.line')
|
||||
expect(lineNodes.length).toBe 6
|
||||
expect(lineNodes[0].offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(lineNodes[0].textContent).toBe editor.lineForScreenRow(2).text
|
||||
expect(lineNodes[5].textContent).toBe editor.lineForScreenRow(7).text
|
||||
|
||||
it "updates absolute positions of subsequent lines when lines are inserted or removed", ->
|
||||
it "updates the top position of subsequent lines when lines are inserted or removed", ->
|
||||
editor.getBuffer().deleteRows(0, 1)
|
||||
lineNodes = node.querySelectorAll('.line')
|
||||
expect(lineNodes[0].offsetTop).toBe 0
|
||||
expect(lineNodes[1].offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(lineNodes[2].offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
|
||||
editor.getBuffer().insert([0, 0], '\n\n')
|
||||
lineNodes = node.querySelectorAll('.line')
|
||||
expect(lineNodes[0].offsetTop).toBe 0
|
||||
expect(lineNodes[1].offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(lineNodes[2].offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(lineNodes[3].offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(lineNodes[4].offsetTop).toBe 4 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
|
||||
|
||||
it "updates the top position of lines when the line height changes", ->
|
||||
initialLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
component.setLineHeight(2)
|
||||
|
||||
newLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
|
||||
|
||||
it "updates the top position of lines when the font size changes", ->
|
||||
initialLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
component.setFontSize(10)
|
||||
|
||||
newLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
|
||||
|
||||
it "updates the top position of lines when the font family changes", ->
|
||||
# Can't find a font that changes the line height, but we think one might exist
|
||||
linesComponent = component.refs.lines
|
||||
spyOn(linesComponent, 'measureLineHeightAndDefaultCharWidth').andCallFake -> editor.setLineHeightInPixels(10)
|
||||
|
||||
initialLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
component.setFontFamily('sans-serif')
|
||||
|
||||
expect(linesComponent.measureLineHeightAndDefaultCharWidth).toHaveBeenCalled()
|
||||
newLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
|
||||
|
||||
it "renders the .lines div at the full height of the editor if there aren't enough lines to scroll vertically", ->
|
||||
editor.setText('')
|
||||
node.style.height = '300px'
|
||||
component.measureScrollView()
|
||||
|
||||
linesNode = node.querySelector('.lines')
|
||||
expect(linesNode.offsetHeight).toBe 300
|
||||
|
||||
describe "when showInvisibles is enabled", ->
|
||||
invisibles = null
|
||||
|
||||
beforeEach ->
|
||||
invisibles =
|
||||
eol: 'E'
|
||||
space: 'S'
|
||||
tab: 'T'
|
||||
cr: 'C'
|
||||
|
||||
atom.config.set("editor.showInvisibles", true)
|
||||
atom.config.set("editor.invisibles", invisibles)
|
||||
|
||||
it "re-renders the lines when the showInvisibles config option changes", ->
|
||||
editor.setText " a line with tabs\tand spaces "
|
||||
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}"
|
||||
atom.config.set("editor.showInvisibles", false)
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe " a line with tabs and spaces "
|
||||
atom.config.set("editor.showInvisibles", true)
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}"
|
||||
|
||||
it "displays spaces, tabs, and newlines as visible characters", ->
|
||||
editor.setText " a line with tabs\tand spaces "
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}"
|
||||
|
||||
it "displays newlines as their own token outside of the other tokens' scopes", ->
|
||||
editor.setText "var"
|
||||
expect(component.lineNodeForScreenRow(0).innerHTML).toBe "<span class=\"source js\"><span class=\"storage modifier js\">var</span></span><span class=\"invisible-character\">#{invisibles.eol}</span>"
|
||||
|
||||
it "displays trailing carriage returns using a visible, non-empty value", ->
|
||||
editor.setText "a line that ends with a carriage return\r\n"
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that ends with a carriage return#{invisibles.cr}#{invisibles.eol}"
|
||||
|
||||
describe "when soft wrapping is enabled", ->
|
||||
beforeEach ->
|
||||
editor.setText "a line that wraps "
|
||||
editor.setSoftWrap(true)
|
||||
node.style.width = 15 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
it "doesn't show end of line invisibles at the end of wrapped lines", ->
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that "
|
||||
expect(component.lineNodeForScreenRow(1).textContent).toBe "wraps#{invisibles.space}#{invisibles.eol}"
|
||||
|
||||
describe "when indent guides are enabled", ->
|
||||
beforeEach ->
|
||||
component.setShowIndentGuide(true)
|
||||
|
||||
it "adds an 'indent-guide' class to spans comprising the leading whitespace", ->
|
||||
lines = node.querySelectorAll('.line')
|
||||
line1LeafNodes = getLeafNodes(lines[1])
|
||||
line1LeafNodes = getLeafNodes(component.lineNodeForScreenRow(1))
|
||||
expect(line1LeafNodes[0].textContent).toBe ' '
|
||||
expect(line1LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false
|
||||
|
||||
line2LeafNodes = getLeafNodes(lines[2])
|
||||
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
|
||||
expect(line2LeafNodes[0].textContent).toBe ' '
|
||||
expect(line2LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
expect(line2LeafNodes[1].textContent).toBe ' '
|
||||
@@ -92,8 +192,7 @@ describe "EditorComponent", ->
|
||||
it "renders leading whitespace spans with the 'indent-guide' class for empty lines", ->
|
||||
editor.getBuffer().insert([1, Infinity], '\n')
|
||||
|
||||
lines = node.querySelectorAll('.line')
|
||||
line2LeafNodes = getLeafNodes(lines[2])
|
||||
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
|
||||
|
||||
expect(line2LeafNodes.length).toBe 3
|
||||
expect(line2LeafNodes[0].textContent).toBe ' '
|
||||
@@ -105,8 +204,7 @@ describe "EditorComponent", ->
|
||||
|
||||
it "renders indent guides correctly on lines containing only whitespace", ->
|
||||
editor.getBuffer().insert([1, Infinity], '\n ')
|
||||
lines = node.querySelectorAll('.line')
|
||||
line2LeafNodes = getLeafNodes(lines[2])
|
||||
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
|
||||
expect(line2LeafNodes.length).toBe 3
|
||||
expect(line2LeafNodes[0].textContent).toBe ' '
|
||||
expect(line2LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
@@ -116,9 +214,8 @@ describe "EditorComponent", ->
|
||||
expect(line2LeafNodes[2].classList.contains('indent-guide')).toBe true
|
||||
|
||||
it "does not render indent guides in trailing whitespace for lines containing non whitespace characters", ->
|
||||
editor.getBuffer().setText (" hi ")
|
||||
lines = node.querySelectorAll('.line')
|
||||
line0LeafNodes = getLeafNodes(lines[0])
|
||||
editor.getBuffer().setText " hi "
|
||||
line0LeafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
|
||||
expect(line0LeafNodes[0].textContent).toBe ' '
|
||||
expect(line0LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
expect(line0LeafNodes[1].textContent).toBe ' '
|
||||
@@ -133,98 +230,116 @@ describe "EditorComponent", ->
|
||||
describe "gutter rendering", ->
|
||||
it "renders the currently-visible line numbers", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
lines = node.querySelectorAll('.line-number')
|
||||
expect(lines.length).toBe 6
|
||||
expect(lines[0].textContent).toBe "#{nbsp}1"
|
||||
expect(lines[5].textContent).toBe "#{nbsp}6"
|
||||
expect(node.querySelectorAll('.line-number').length).toBe 6 + 2 + 1 # line overdraw margin below + dummy line number
|
||||
expect(component.lineNumberNodeForScreenRow(0).textContent).toBe "#{nbsp}1"
|
||||
expect(component.lineNumberNodeForScreenRow(5).textContent).toBe "#{nbsp}6"
|
||||
|
||||
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
|
||||
expect(node.querySelector('.line-numbers').style['-webkit-transform']).toBe "translate3d(0, #{-2.5 * lineHeightInPixels}px, 0)"
|
||||
expect(node.querySelectorAll('.line-number').length).toBe 6 + 4 + 1 # line overdraw margin above/below + dummy line number
|
||||
|
||||
lineNumberNodes = node.querySelectorAll('.line-number')
|
||||
expect(lineNumberNodes.length).toBe 6
|
||||
expect(lineNumberNodes[0].offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(lineNumberNodes[5].offsetTop).toBe 7 * lineHeightInPixels
|
||||
expect(lineNumberNodes[0].textContent).toBe "#{nbsp}3"
|
||||
expect(lineNumberNodes[5].textContent).toBe "#{nbsp}8"
|
||||
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}3"
|
||||
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
return
|
||||
expect(component.lineNumberNodeForScreenRow(7).textContent).toBe "#{nbsp}8"
|
||||
expect(component.lineNumberNodeForScreenRow(7).offsetTop).toBe 7 * lineHeightInPixels
|
||||
|
||||
it "updates absolute positions of subsequent line numbers when lines are inserted or removed", ->
|
||||
it "updates the translation of subsequent line numbers when lines are inserted or removed", ->
|
||||
editor.getBuffer().insert([0, 0], '\n\n')
|
||||
|
||||
lineNumberNodes = node.querySelectorAll('.line-number')
|
||||
expect(lineNumberNodes[0].offsetTop).toBe 0
|
||||
expect(lineNumberNodes[1].offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(lineNumberNodes[2].offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(lineNumberNodes[3].offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(lineNumberNodes[4].offsetTop).toBe 4 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0
|
||||
expect(component.lineNumberNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
|
||||
|
||||
editor.getBuffer().insert([0, 0], '\n\n')
|
||||
lineNumberNodes = node.querySelectorAll('.line-number')
|
||||
expect(lineNumberNodes[0].offsetTop).toBe 0
|
||||
expect(lineNumberNodes[1].offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(lineNumberNodes[2].offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(lineNumberNodes[3].offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(lineNumberNodes[4].offsetTop).toBe 4 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0
|
||||
expect(component.lineNumberNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels
|
||||
expect(component.lineNumberNodeForScreenRow(6).offsetTop).toBe 6 * lineHeightInPixels
|
||||
|
||||
it "renders • characters for soft-wrapped lines", ->
|
||||
editor.setSoftWrap(true)
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 30 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
lines = node.querySelectorAll('.line-number')
|
||||
expect(lines.length).toBe 6
|
||||
expect(lines[0].textContent).toBe "#{nbsp}1"
|
||||
expect(lines[1].textContent).toBe "#{nbsp}•"
|
||||
expect(lines[2].textContent).toBe "#{nbsp}2"
|
||||
expect(lines[3].textContent).toBe "#{nbsp}•"
|
||||
expect(lines[4].textContent).toBe "#{nbsp}3"
|
||||
expect(lines[5].textContent).toBe "#{nbsp}•"
|
||||
expect(node.querySelectorAll('.line-number').length).toBe 6 + lineOverdrawMargin + 1 # 1 dummy line node
|
||||
expect(component.lineNumberNodeForScreenRow(0).textContent).toBe "#{nbsp}1"
|
||||
expect(component.lineNumberNodeForScreenRow(1).textContent).toBe "#{nbsp}•"
|
||||
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}2"
|
||||
expect(component.lineNumberNodeForScreenRow(3).textContent).toBe "#{nbsp}•"
|
||||
expect(component.lineNumberNodeForScreenRow(4).textContent).toBe "#{nbsp}3"
|
||||
expect(component.lineNumberNodeForScreenRow(5).textContent).toBe "#{nbsp}•"
|
||||
|
||||
it "pads line numbers to be right-justified based on the maximum number of line number digits", ->
|
||||
editor.getBuffer().setText([1..10].join('\n'))
|
||||
for screenRow in [0..8]
|
||||
expect(component.lineNumberNodeForScreenRow(screenRow).textContent).toBe "#{nbsp}#{screenRow + 1}"
|
||||
expect(component.lineNumberNodeForScreenRow(9).textContent).toBe "10"
|
||||
|
||||
gutterNode = node.querySelector('.gutter')
|
||||
initialGutterWidth = gutterNode.offsetWidth
|
||||
|
||||
# Removes padding when the max number of digits goes down
|
||||
editor.getBuffer().delete([[1, 0], [2, 0]])
|
||||
for screenRow in [0..8]
|
||||
expect(component.lineNumberNodeForScreenRow(screenRow).textContent).toBe "#{screenRow + 1}"
|
||||
expect(gutterNode.offsetWidth).toBeLessThan initialGutterWidth
|
||||
|
||||
# Increases padding when the max number of digits goes up
|
||||
editor.getBuffer().insert([0, 0], '\n\n')
|
||||
for screenRow in [0..8]
|
||||
expect(component.lineNumberNodeForScreenRow(screenRow).textContent).toBe "#{nbsp}#{screenRow + 1}"
|
||||
expect(component.lineNumberNodeForScreenRow(9).textContent).toBe "10"
|
||||
expect(gutterNode.offsetWidth).toBe initialGutterWidth
|
||||
|
||||
describe "cursor rendering", ->
|
||||
it "renders the currently visible cursors", ->
|
||||
it "renders the currently visible cursors, translated relative to the scroll position", ->
|
||||
cursor1 = editor.getCursor()
|
||||
cursor1.setScreenPosition([0, 5])
|
||||
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
node.style.width = 20 * lineHeightInPixels + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
cursorNodes = node.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 1
|
||||
expect(cursorNodes[0].offsetHeight).toBe lineHeightInPixels
|
||||
expect(cursorNodes[0].offsetWidth).toBe charWidth
|
||||
expect(cursorNodes[0].offsetTop).toBe 0
|
||||
expect(cursorNodes[0].offsetLeft).toBe 5 * charWidth
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{5 * charWidth}px, #{0 * lineHeightInPixels}px, 0px)"
|
||||
|
||||
cursor2 = editor.addCursorAtScreenPosition([6, 11])
|
||||
cursor2 = editor.addCursorAtScreenPosition([8, 11])
|
||||
cursor3 = editor.addCursorAtScreenPosition([4, 10])
|
||||
|
||||
cursorNodes = node.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 2
|
||||
expect(cursorNodes[0].offsetTop).toBe 0
|
||||
expect(cursorNodes[0].offsetLeft).toBe 5 * charWidth
|
||||
expect(cursorNodes[1].offsetTop).toBe 4 * lineHeightInPixels
|
||||
expect(cursorNodes[1].offsetLeft).toBe 10 * charWidth
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{5 * charWidth}px, #{0 * lineHeightInPixels}px, 0px)"
|
||||
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate3d(#{10 * charWidth}px, #{4 * lineHeightInPixels}px, 0px)"
|
||||
|
||||
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
horizontalScrollbarNode.scrollLeft = 3.5 * charWidth
|
||||
horizontalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
|
||||
cursorNodes = node.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 2
|
||||
expect(cursorNodes[0].offsetTop).toBe 6 * lineHeightInPixels
|
||||
expect(cursorNodes[0].offsetLeft).toBe 11 * charWidth
|
||||
expect(cursorNodes[1].offsetTop).toBe 4 * lineHeightInPixels
|
||||
expect(cursorNodes[1].offsetLeft).toBe 10 * charWidth
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{(11 - 3.5) * charWidth}px, #{(8 - 4.5) * lineHeightInPixels}px, 0px)"
|
||||
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate3d(#{(10 - 3.5) * charWidth}px, #{(4 - 4.5) * lineHeightInPixels}px, 0px)"
|
||||
|
||||
cursor3.destroy()
|
||||
cursorNodes = node.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 1
|
||||
expect(cursorNodes[0].offsetTop).toBe 6 * lineHeightInPixels
|
||||
expect(cursorNodes[0].offsetLeft).toBe 11 * charWidth
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{(11 - 3.5) * charWidth}px, #{(6 - 2.5) * lineHeightInPixels}px, 0px)"
|
||||
|
||||
it "accounts for character widths when positioning cursors", ->
|
||||
atom.config.set('editor.fontFamily', 'sans-serif')
|
||||
@@ -233,7 +348,7 @@ describe "EditorComponent", ->
|
||||
cursor = node.querySelector('.cursor')
|
||||
cursorRect = cursor.getBoundingClientRect()
|
||||
|
||||
cursorLocationTextNode = node.querySelector('.storage.type.function.js').firstChild.firstChild
|
||||
cursorLocationTextNode = component.lineNodeForScreenRow(0).querySelector('.storage.type.function.js').firstChild
|
||||
range = document.createRange()
|
||||
range.setStart(cursorLocationTextNode, 0)
|
||||
range.setEnd(cursorLocationTextNode, 1)
|
||||
@@ -243,63 +358,23 @@ describe "EditorComponent", ->
|
||||
expect(cursorRect.width).toBe rangeRect.width
|
||||
|
||||
it "blinks cursors when they aren't moving", ->
|
||||
editor.addCursorAtScreenPosition([1, 0])
|
||||
[cursorNode1, cursorNode2] = node.querySelectorAll('.cursor')
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe false
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe false
|
||||
spyOn(_._, 'now').andCallFake -> window.now # Ensure _.debounce is based on our fake spec timeline
|
||||
cursorsNode = node.querySelector('.cursors')
|
||||
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe false
|
||||
advanceClock(component.props.cursorBlinkPeriod / 2)
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe true
|
||||
|
||||
advanceClock(component.props.cursorBlinkPeriod / 2)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe true
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe true
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe false
|
||||
|
||||
advanceClock(component.props.cursorBlinkPeriod / 2)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe false
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe false
|
||||
|
||||
advanceClock(component.props.cursorBlinkPeriod / 2)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe true
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe true
|
||||
|
||||
# Stop blinking immediately when cursors move
|
||||
advanceClock(component.props.cursorBlinkPeriod / 4)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe true
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe true
|
||||
|
||||
# Stop blinking for one full period after moving the cursor
|
||||
# Stop blinking after moving the cursor
|
||||
editor.moveCursorRight()
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe false
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe false
|
||||
|
||||
advanceClock(component.props.cursorBlinkResumeDelay / 2)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe false
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe false
|
||||
|
||||
advanceClock(component.props.cursorBlinkResumeDelay / 2)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe true
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe true
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe false
|
||||
|
||||
advanceClock(component.props.cursorBlinkResumeDelay)
|
||||
advanceClock(component.props.cursorBlinkPeriod / 2)
|
||||
expect(cursorNode1.classList.contains('blink-off')).toBe false
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe false
|
||||
|
||||
it "renders the hidden input field at the position of the last cursor if it is on screen", ->
|
||||
inputNode = node.querySelector('.hidden-input')
|
||||
node.style.height = 5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
|
||||
expect(editor.getCursorScreenPosition()).toEqual [0, 0]
|
||||
editor.setScrollTop(3 * lineHeightInPixels)
|
||||
editor.setScrollLeft(3 * charWidth)
|
||||
expect(inputNode.offsetTop).toBe 0
|
||||
expect(inputNode.offsetLeft).toBe 0
|
||||
|
||||
editor.setCursorBufferPosition([5, 5])
|
||||
cursorRect = editor.getCursor().getPixelRect()
|
||||
cursorTop = cursorRect.top
|
||||
cursorLeft = cursorRect.left
|
||||
expect(inputNode.offsetTop).toBe cursorTop - editor.getScrollTop()
|
||||
expect(inputNode.offsetLeft).toBe cursorLeft - editor.getScrollLeft()
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe true
|
||||
|
||||
it "does not render cursors that are associated with non-empty selections", ->
|
||||
editor.setSelectedScreenRange([[0, 4], [4, 6]])
|
||||
@@ -307,13 +382,33 @@ describe "EditorComponent", ->
|
||||
|
||||
cursorNodes = node.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 1
|
||||
expect(cursorNodes[0].offsetTop).toBe 6 * lineHeightInPixels
|
||||
expect(cursorNodes[0].offsetLeft).toBe 8 * charWidth
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{8 * charWidth}px, #{6 * lineHeightInPixels}px, 0px)"
|
||||
|
||||
it "updates cursor positions when the line height changes", ->
|
||||
editor.setCursorBufferPosition([1, 10])
|
||||
component.setLineHeight(2)
|
||||
cursorNode = node.querySelector('.cursor')
|
||||
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px, 0px)"
|
||||
|
||||
it "updates cursor positions when the font size changes", ->
|
||||
editor.setCursorBufferPosition([1, 10])
|
||||
component.setFontSize(10)
|
||||
cursorNode = node.querySelector('.cursor')
|
||||
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px, 0px)"
|
||||
|
||||
it "updates cursor positions when the font family changes", ->
|
||||
editor.setCursorBufferPosition([1, 10])
|
||||
component.setFontFamily('sans-serif')
|
||||
cursorNode = node.querySelector('.cursor')
|
||||
|
||||
{left} = editor.pixelPositionForScreenPosition([1, 10])
|
||||
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{left}px, #{editor.getLineHeightInPixels()}px, 0px)"
|
||||
|
||||
describe "selection rendering", ->
|
||||
scrollViewClientLeft = null
|
||||
[scrollViewNode, scrollViewClientLeft] = []
|
||||
|
||||
beforeEach ->
|
||||
scrollViewNode = node.querySelector('.scroll-view')
|
||||
scrollViewClientLeft = node.querySelector('.scroll-view').getBoundingClientRect().left
|
||||
|
||||
it "renders 1 region for 1-line selections", ->
|
||||
@@ -337,7 +432,7 @@ describe "EditorComponent", ->
|
||||
expect(region1Rect.top).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.height).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.left).toBe scrollViewClientLeft + 6 * charWidth
|
||||
expect(Math.ceil(region1Rect.right)).toBe node.clientWidth # TODO: Remove ceiling when react-wrapper is removed
|
||||
expect(region1Rect.right).toBe scrollViewNode.getBoundingClientRect().right
|
||||
|
||||
region2Rect = regions[1].getBoundingClientRect()
|
||||
expect(region2Rect.top).toBe 2 * lineHeightInPixels
|
||||
@@ -354,13 +449,13 @@ describe "EditorComponent", ->
|
||||
expect(region1Rect.top).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.height).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.left).toBe scrollViewClientLeft + 6 * charWidth
|
||||
expect(Math.ceil(region1Rect.right)).toBe node.clientWidth # TODO: Remove ceiling when react-wrapper is removed
|
||||
expect(region1Rect.right).toBe scrollViewNode.getBoundingClientRect().right
|
||||
|
||||
region2Rect = regions[1].getBoundingClientRect()
|
||||
expect(region2Rect.top).toBe 2 * lineHeightInPixels
|
||||
expect(region2Rect.height).toBe 3 * lineHeightInPixels
|
||||
expect(region2Rect.left).toBe scrollViewClientLeft + 0
|
||||
expect(Math.ceil(region2Rect.right)).toBe node.clientWidth # TODO: Remove ceiling when react-wrapper is removed
|
||||
expect(region2Rect.right).toBe scrollViewNode.getBoundingClientRect().right
|
||||
|
||||
region3Rect = regions[2].getBoundingClientRect()
|
||||
expect(region3Rect.top).toBe 5 * lineHeightInPixels
|
||||
@@ -368,9 +463,74 @@ describe "EditorComponent", ->
|
||||
expect(region3Rect.left).toBe scrollViewClientLeft + 0
|
||||
expect(region3Rect.width).toBe 10 * charWidth
|
||||
|
||||
it "does not render empty selections", ->
|
||||
expect(editor.getSelection().isEmpty()).toBe true
|
||||
expect(node.querySelectorAll('.selection').length).toBe 0
|
||||
it "does not render empty selections unless they are the first selection (to prevent a Chromium rendering artifact caused by removing it)", ->
|
||||
editor.addSelectionForBufferRange([[2, 2], [2, 2]])
|
||||
expect(editor.getSelection(0).isEmpty()).toBe true
|
||||
expect(editor.getSelection(1).isEmpty()).toBe true
|
||||
|
||||
expect(node.querySelectorAll('.selection').length).toBe 1
|
||||
|
||||
it "updates selections when the line height changes", ->
|
||||
editor.setSelectedBufferRange([[1, 6], [1, 10]])
|
||||
component.setLineHeight(2)
|
||||
selectionNode = node.querySelector('.region')
|
||||
expect(selectionNode.offsetTop).toBe editor.getLineHeightInPixels()
|
||||
|
||||
it "updates selections when the font size changes", ->
|
||||
editor.setSelectedBufferRange([[1, 6], [1, 10]])
|
||||
component.setFontSize(10)
|
||||
selectionNode = node.querySelector('.region')
|
||||
expect(selectionNode.offsetTop).toBe editor.getLineHeightInPixels()
|
||||
expect(selectionNode.offsetLeft).toBe 6 * editor.getDefaultCharWidth()
|
||||
|
||||
it "updates selections when the font family changes", ->
|
||||
editor.setSelectedBufferRange([[1, 6], [1, 10]])
|
||||
component.setFontFamily('sans-serif')
|
||||
selectionNode = node.querySelector('.region')
|
||||
expect(selectionNode.offsetTop).toBe editor.getLineHeightInPixels()
|
||||
expect(selectionNode.offsetLeft).toBe editor.pixelPositionForScreenPosition([1, 6]).left
|
||||
|
||||
describe "hidden input field", ->
|
||||
it "renders the hidden input field at the position of the last cursor if the cursor is on screen and the editor is focused", ->
|
||||
editor.setVerticalScrollMargin(0)
|
||||
editor.setHorizontalScrollMargin(0)
|
||||
|
||||
inputNode = node.querySelector('.hidden-input')
|
||||
node.style.height = 5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
expect(editor.getCursorScreenPosition()).toEqual [0, 0]
|
||||
editor.setScrollTop(3 * lineHeightInPixels)
|
||||
editor.setScrollLeft(3 * charWidth)
|
||||
|
||||
expect(inputNode.offsetTop).toBe 0
|
||||
expect(inputNode.offsetLeft).toBe 0
|
||||
|
||||
# In bounds, not focused
|
||||
editor.setCursorBufferPosition([5, 4])
|
||||
expect(inputNode.offsetTop).toBe 0
|
||||
expect(inputNode.offsetLeft).toBe 0
|
||||
|
||||
# In bounds and focused
|
||||
inputNode.focus()
|
||||
expect(inputNode.offsetTop).toBe (5 * lineHeightInPixels) - editor.getScrollTop()
|
||||
expect(inputNode.offsetLeft).toBe (4 * charWidth) - editor.getScrollLeft()
|
||||
|
||||
# In bounds, not focused
|
||||
inputNode.blur()
|
||||
expect(inputNode.offsetTop).toBe 0
|
||||
expect(inputNode.offsetLeft).toBe 0
|
||||
|
||||
# Out of bounds, not focused
|
||||
editor.setCursorBufferPosition([1, 2])
|
||||
expect(inputNode.offsetTop).toBe 0
|
||||
expect(inputNode.offsetLeft).toBe 0
|
||||
|
||||
# Out of bounds, focused
|
||||
inputNode.focus()
|
||||
expect(inputNode.offsetTop).toBe 0
|
||||
expect(inputNode.offsetLeft).toBe 0
|
||||
|
||||
describe "mouse interactions", ->
|
||||
linesNode = null
|
||||
@@ -384,7 +544,7 @@ describe "EditorComponent", ->
|
||||
it "moves the cursor to the nearest screen position", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
editor.setScrollTop(3.5 * lineHeightInPixels)
|
||||
editor.setScrollLeft(2 * charWidth)
|
||||
|
||||
@@ -497,28 +657,28 @@ describe "EditorComponent", ->
|
||||
describe "scrolling", ->
|
||||
it "updates the vertical scrollbar when the scrollTop is changed in the model", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 0
|
||||
|
||||
editor.setScrollTop(10)
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
|
||||
it "updates the horizontal scrollbar and scroll view content x transform based on the scrollLeft of the model", ->
|
||||
it "updates the horizontal scrollbar and the x transform of the lines based on the scrollLeft of the model", ->
|
||||
node.style.width = 30 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
scrollViewContentNode = node.querySelector('.scroll-view-content')
|
||||
expect(scrollViewContentNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0)"
|
||||
linesNode = node.querySelector('.lines')
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
editor.setScrollLeft(100)
|
||||
expect(scrollViewContentNode.style['-webkit-transform']).toBe "translate3d(-100px, 0px, 0)"
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(-100px, 0px, 0px)"
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 100
|
||||
|
||||
it "updates the scrollLeft of the model when the scrollLeft of the horizontal scrollbar changes", ->
|
||||
node.style.width = 30 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
expect(editor.getScrollLeft()).toBe 0
|
||||
horizontalScrollbarNode.scrollLeft = 100
|
||||
@@ -526,22 +686,194 @@ describe "EditorComponent", ->
|
||||
|
||||
expect(editor.getScrollLeft()).toBe 100
|
||||
|
||||
it "does not obscure the last line with the horizontal scrollbar", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
editor.setScrollBottom(editor.getScrollHeight())
|
||||
lastLineNode = component.lineNodeForScreenRow(editor.getLastScreenRow())
|
||||
bottomOfLastLine = lastLineNode.getBoundingClientRect().bottom
|
||||
topOfHorizontalScrollbar = horizontalScrollbarNode.getBoundingClientRect().top
|
||||
expect(bottomOfLastLine).toBe topOfHorizontalScrollbar
|
||||
|
||||
# Scroll so there's no space below the last line when the horizontal scrollbar disappears
|
||||
node.style.width = 100 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
bottomOfLastLine = lastLineNode.getBoundingClientRect().bottom
|
||||
bottomOfEditor = node.getBoundingClientRect().bottom
|
||||
expect(bottomOfLastLine).toBe bottomOfEditor
|
||||
|
||||
it "does not obscure the last character of the longest line with the vertical scrollbar", ->
|
||||
node.style.height = 7 * lineHeightInPixels + 'px'
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
editor.setScrollLeft(Infinity)
|
||||
|
||||
rightOfLongestLine = component.lineNodeForScreenRow(6).getBoundingClientRect().right
|
||||
leftOfVerticalScrollbar = verticalScrollbarNode.getBoundingClientRect().left
|
||||
expect(Math.round(rightOfLongestLine)).toBe leftOfVerticalScrollbar - 1 # Leave 1 px so the cursor is visible on the end of the line
|
||||
|
||||
it "only displays dummy scrollbars when scrollable in that direction", ->
|
||||
expect(verticalScrollbarNode.style.display).toBe 'none'
|
||||
expect(horizontalScrollbarNode.style.display).toBe 'none'
|
||||
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = '1000px'
|
||||
component.measureScrollView()
|
||||
|
||||
expect(verticalScrollbarNode.style.display).toBe ''
|
||||
expect(horizontalScrollbarNode.style.display).toBe 'none'
|
||||
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
expect(verticalScrollbarNode.style.display).toBe ''
|
||||
expect(horizontalScrollbarNode.style.display).toBe ''
|
||||
|
||||
node.style.height = 20 * lineHeightInPixels + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
expect(verticalScrollbarNode.style.display).toBe 'none'
|
||||
expect(horizontalScrollbarNode.style.display).toBe ''
|
||||
|
||||
it "makes the dummy scrollbar divs only as tall/wide as the actual scrollbars", ->
|
||||
node.style.height = 4 * lineHeightInPixels + 'px'
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
atom.themes.applyStylesheet "test", """
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
"""
|
||||
|
||||
scrollbarCornerNode = node.querySelector('.scrollbar-corner')
|
||||
expect(verticalScrollbarNode.offsetWidth).toBe 8
|
||||
expect(horizontalScrollbarNode.offsetHeight).toBe 8
|
||||
expect(scrollbarCornerNode.offsetWidth).toBe 8
|
||||
expect(scrollbarCornerNode.offsetHeight).toBe 8
|
||||
|
||||
it "assigns the bottom/right of the scrollbars to the width of the opposite scrollbar if it is visible", ->
|
||||
scrollbarCornerNode = node.querySelector('.scrollbar-corner')
|
||||
|
||||
expect(verticalScrollbarNode.style.bottom).toBe ''
|
||||
expect(horizontalScrollbarNode.style.right).toBe ''
|
||||
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = '1000px'
|
||||
component.measureScrollView()
|
||||
expect(verticalScrollbarNode.style.bottom).toBe ''
|
||||
expect(horizontalScrollbarNode.style.right).toBe verticalScrollbarNode.offsetWidth + 'px'
|
||||
expect(scrollbarCornerNode.style.display).toBe 'none'
|
||||
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
expect(verticalScrollbarNode.style.bottom).toBe horizontalScrollbarNode.offsetHeight + 'px'
|
||||
expect(horizontalScrollbarNode.style.right).toBe verticalScrollbarNode.offsetWidth + 'px'
|
||||
expect(scrollbarCornerNode.style.display).toBe ''
|
||||
|
||||
node.style.height = 20 * lineHeightInPixels + 'px'
|
||||
component.measureScrollView()
|
||||
expect(verticalScrollbarNode.style.bottom).toBe horizontalScrollbarNode.offsetHeight + 'px'
|
||||
expect(horizontalScrollbarNode.style.right).toBe ''
|
||||
expect(scrollbarCornerNode.style.display).toBe 'none'
|
||||
|
||||
it "accounts for the width of the gutter in the scrollWidth of the horizontal scrollbar", ->
|
||||
gutterNode = node.querySelector('.gutter')
|
||||
node.style.width = 10 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
expect(horizontalScrollbarNode.scrollWidth).toBe gutterNode.offsetWidth + editor.getScrollWidth()
|
||||
|
||||
describe "when a mousewheel event occurs on the editor", ->
|
||||
it "updates the horizontal or vertical scrollbar depending on which delta is greater (x or y)", ->
|
||||
|
||||
describe "mousewheel events", ->
|
||||
it "updates the scrollLeft or scrollTop on mousewheel events depending on which delta is greater (x or y)", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 20 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 0
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -5, wheelDeltaY: -10))
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -15, wheelDeltaY: -5))
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 15
|
||||
|
||||
describe "when the mousewheel event's target is a line", ->
|
||||
it "keeps the line on the DOM if it is scrolled off-screen", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 20 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
component.measureScrollView()
|
||||
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 0
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
lineNode = node.querySelector('.line')
|
||||
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: -500)
|
||||
Object.defineProperty(wheelEvent, 'target', get: -> lineNode)
|
||||
node.dispatchEvent(wheelEvent)
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -5, wheelDeltaY: -10))
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
expect(node.contains(lineNode)).toBe true
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -15, wheelDeltaY: -5))
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 15
|
||||
it "does not set the mouseWheelScreenRow if scrolling horizontally", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 20 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
lineNode = node.querySelector('.line')
|
||||
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 10, wheelDeltaY: 0)
|
||||
Object.defineProperty(wheelEvent, 'target', get: -> lineNode)
|
||||
node.dispatchEvent(wheelEvent)
|
||||
|
||||
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 = node.querySelector('.line')
|
||||
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: 10)
|
||||
Object.defineProperty(wheelEvent, 'target', get: -> lineNode)
|
||||
node.dispatchEvent(wheelEvent)
|
||||
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
|
||||
expect(component.mouseWheelScreenRow).toBe 0
|
||||
advanceClock(component.mouseWheelScreenRowClearDelay)
|
||||
expect(component.mouseWheelScreenRow).toBe null
|
||||
|
||||
it "does not preserve the line if it is on screen", ->
|
||||
expect(node.querySelectorAll('.line-number').length).toBe 14 # dummy line
|
||||
lineNodes = node.querySelectorAll('.line')
|
||||
expect(lineNodes.length).toBe 13
|
||||
lineNode = lineNodes[0]
|
||||
|
||||
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: 100) # goes nowhere, we're already at scrollTop 0
|
||||
Object.defineProperty(wheelEvent, 'target', get: -> lineNode)
|
||||
node.dispatchEvent(wheelEvent)
|
||||
|
||||
expect(component.mouseWheelScreenRow).toBe 0
|
||||
editor.insertText("hello")
|
||||
expect(node.querySelectorAll('.line-number').length).toBe 14 # dummy line
|
||||
expect(node.querySelectorAll('.line').length).toBe 13
|
||||
|
||||
describe "when the mousewheel event's target is a line number", ->
|
||||
it "keeps the line number on the DOM if it is scrolled off-screen", ->
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
node.style.width = 20 * charWidth + 'px'
|
||||
component.measureScrollView()
|
||||
|
||||
lineNumberNode = node.querySelectorAll('.line-number')[1]
|
||||
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: -500)
|
||||
Object.defineProperty(wheelEvent, 'target', get: -> lineNumberNode)
|
||||
node.dispatchEvent(wheelEvent)
|
||||
|
||||
expect(node.contains(lineNumberNode)).toBe true
|
||||
|
||||
describe "input events", ->
|
||||
inputNode = null
|
||||
@@ -578,3 +910,33 @@ describe "EditorComponent", ->
|
||||
|
||||
expect(editor.consolidateSelections).toHaveBeenCalled()
|
||||
expect(event.abortKeyBinding).toHaveBeenCalled()
|
||||
|
||||
describe "hiding and showing the editor", ->
|
||||
describe "when fontSize, fontFamily, or lineHeight changes while the editor is hidden", ->
|
||||
it "does not attempt to measure the lineHeight and defaultCharWidth until the editor becomes visible again", ->
|
||||
wrapperView.hide()
|
||||
initialLineHeightInPixels = editor.getLineHeightInPixels()
|
||||
initialCharWidth = editor.getDefaultCharWidth()
|
||||
|
||||
component.setLineHeight(2)
|
||||
expect(editor.getLineHeightInPixels()).toBe initialLineHeightInPixels
|
||||
expect(editor.getDefaultCharWidth()).toBe initialCharWidth
|
||||
component.setFontSize(22)
|
||||
expect(editor.getLineHeightInPixels()).toBe initialLineHeightInPixels
|
||||
expect(editor.getDefaultCharWidth()).toBe initialCharWidth
|
||||
component.setFontFamily('monospace')
|
||||
expect(editor.getLineHeightInPixels()).toBe initialLineHeightInPixels
|
||||
expect(editor.getDefaultCharWidth()).toBe initialCharWidth
|
||||
|
||||
wrapperView.show()
|
||||
expect(editor.getLineHeightInPixels()).not.toBe initialLineHeightInPixels
|
||||
expect(editor.getDefaultCharWidth()).not.toBe initialCharWidth
|
||||
|
||||
describe "when lines are changed while the editor is hidden", ->
|
||||
it "does not measure new characters until the editor is shown again", ->
|
||||
editor.setText('')
|
||||
wrapperView.hide()
|
||||
editor.setText('var z = 1')
|
||||
editor.setCursorBufferPosition([0, Infinity])
|
||||
wrapperView.show()
|
||||
expect(node.querySelector('.cursor').style['-webkit-transform']).toBe "translate3d(#{9 * charWidth}px, 0px, 0px)"
|
||||
|
||||
+216
-73
@@ -7,9 +7,12 @@ describe "Editor", ->
|
||||
buffer.setText(buffer.getText().replace(/[ ]{2}/g, "\t"))
|
||||
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.js', autoIndent: false)
|
||||
buffer = editor.buffer
|
||||
lineLengths = buffer.getLines().map (line) -> line.length
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js', autoIndent: false).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
lineLengths = buffer.getLines().map (line) -> line.length
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
@@ -17,7 +20,7 @@ describe "Editor", ->
|
||||
describe "when the editor is deserialized", ->
|
||||
it "restores selections and folds based on markers in the buffer", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 4]])
|
||||
editor.addSelectionForBufferRange([[5, 6], [7, 5]], isReversed: true)
|
||||
editor.addSelectionForBufferRange([[5, 6], [7, 5]], reversed: true)
|
||||
editor.foldBufferRow(4)
|
||||
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
|
||||
|
||||
@@ -31,15 +34,33 @@ describe "Editor", ->
|
||||
editor2.destroy()
|
||||
|
||||
describe "when the editor is constructed with an initialLine option", ->
|
||||
it "and positions the cursor on the specified line", ->
|
||||
editor = atom.project.openSync('sample.js', initialLine: 2)
|
||||
buffer = editor.buffer
|
||||
expect(editor.getCursor().getBufferPosition().row).toEqual 2
|
||||
it "positions the cursor on the specified line", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialLine: 5).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
expect(editor.getCursor().getBufferPosition().row).toEqual 5
|
||||
expect(editor.getCursor().getBufferPosition().column).toEqual 0
|
||||
|
||||
describe "when the editor is constructed 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
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
expect(editor.getCursor().getBufferPosition().row).toEqual 0
|
||||
expect(editor.getCursor().getBufferPosition().column).toEqual 8
|
||||
|
||||
describe ".copy()", ->
|
||||
it "returns a different edit session with the same initial state", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 4]])
|
||||
editor.addSelectionForBufferRange([[5, 6], [7, 8]], isReversed: true)
|
||||
editor.addSelectionForBufferRange([[5, 6], [7, 8]], reversed: true)
|
||||
editor.foldBufferRow(4)
|
||||
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
|
||||
|
||||
@@ -57,21 +78,31 @@ describe "Editor", ->
|
||||
|
||||
describe "config defaults", ->
|
||||
it "uses the `editor.tabLength`, `editor.softWrap`, and `editor.softTabs` config values", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
atom.config.set('editor.tabLength', 4)
|
||||
atom.config.set('editor.softWrap', true)
|
||||
atom.config.set('editor.softTabs', false)
|
||||
editor1 = atom.project.openSync('a')
|
||||
expect(editor1.getTabLength()).toBe 4
|
||||
expect(editor1.getSoftWrap()).toBe true
|
||||
expect(editor1.getSoftTabs()).toBe false
|
||||
|
||||
atom.config.set('editor.tabLength', 100)
|
||||
atom.config.set('editor.softWrap', false)
|
||||
atom.config.set('editor.softTabs', true)
|
||||
editor2 = atom.project.openSync('b')
|
||||
expect(editor2.getTabLength()).toBe 100
|
||||
expect(editor2.getSoftWrap()).toBe false
|
||||
expect(editor2.getSoftTabs()).toBe true
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('a').then (o) -> editor1 = o
|
||||
|
||||
runs ->
|
||||
expect(editor1.getTabLength()).toBe 4
|
||||
expect(editor1.getSoftWrap()).toBe true
|
||||
expect(editor1.getSoftTabs()).toBe false
|
||||
|
||||
atom.config.set('editor.tabLength', 100)
|
||||
atom.config.set('editor.softWrap', false)
|
||||
atom.config.set('editor.softTabs', true)
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('b').then (o) -> editor2 = o
|
||||
|
||||
runs ->
|
||||
expect(editor2.getTabLength()).toBe 100
|
||||
expect(editor2.getSoftWrap()).toBe false
|
||||
expect(editor2.getSoftTabs()).toBe true
|
||||
|
||||
describe "title", ->
|
||||
describe ".getTitle()", ->
|
||||
@@ -591,6 +622,38 @@ describe "Editor", ->
|
||||
editor.moveCursorToBeginningOfNextWord()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [11, 9]
|
||||
|
||||
describe ".moveCursorToBeginningOfNextParagraph()", ->
|
||||
it "moves the cursor before the first line of the next paragraph", ->
|
||||
editor.setCursorBufferPosition [0,6]
|
||||
cursor = editor.getCursor()
|
||||
|
||||
editor.moveCursorToBeginningOfNextParagraph()
|
||||
|
||||
expect(cursor.getBufferPosition()).toEqual { row : 10, column : 0 }
|
||||
|
||||
editor.setText("")
|
||||
editor.setCursorBufferPosition [0,0]
|
||||
cursor = editor.getCursor()
|
||||
editor.moveCursorToBeginningOfNextParagraph()
|
||||
|
||||
expect(cursor.getBufferPosition()).toEqual [0, 0]
|
||||
|
||||
describe ".moveCursorToBeginningOfPreviousParagraph()", ->
|
||||
it "moves the cursor before the first line of the pevious paragraph", ->
|
||||
editor.setCursorBufferPosition [10,0]
|
||||
cursor = editor.getCursor()
|
||||
|
||||
editor.moveCursorToBeginningOfPreviousParagraph()
|
||||
|
||||
expect(cursor.getBufferPosition()).toEqual { row : 0, column : 0 }
|
||||
|
||||
editor.setText("")
|
||||
editor.setCursorBufferPosition [0,0]
|
||||
cursor = editor.getCursor()
|
||||
editor.moveCursorToBeginningOfPreviousParagraph()
|
||||
|
||||
expect(cursor.getBufferPosition()).toEqual [0, 0]
|
||||
|
||||
describe ".getCurrentParagraphBufferRange()", ->
|
||||
it "returns the buffer range of the current paragraph, delimited by blank lines or the beginning / end of the file", ->
|
||||
buffer.setText """
|
||||
@@ -665,8 +728,9 @@ describe "Editor", ->
|
||||
editor.manageScrollPosition = true
|
||||
editor.setVerticalScrollMargin(2)
|
||||
editor.setHorizontalScrollMargin(2)
|
||||
editor.setLineHeight(10)
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setDefaultCharWidth(10)
|
||||
editor.setHorizontalScrollbarHeight(0)
|
||||
editor.setHeight(5.5 * 10)
|
||||
editor.setWidth(5.5 * 10)
|
||||
|
||||
@@ -759,7 +823,7 @@ describe "Editor", ->
|
||||
expect(selection1.isReversed()).toBeFalsy()
|
||||
|
||||
it "merges selections when they intersect when moving up", ->
|
||||
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]]], isReversed: true)
|
||||
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]]], reversed: true)
|
||||
[selection1, selection2] = editor.getSelections()
|
||||
|
||||
editor.selectUp()
|
||||
@@ -770,7 +834,7 @@ describe "Editor", ->
|
||||
expect(selection1.isReversed()).toBeTruthy()
|
||||
|
||||
it "merges selections when they intersect when moving left", ->
|
||||
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], isReversed: true)
|
||||
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], reversed: true)
|
||||
[selection1, selection2] = editor.getSelections()
|
||||
|
||||
editor.selectLeft()
|
||||
@@ -1103,10 +1167,11 @@ describe "Editor", ->
|
||||
describe "when the 'autoscroll' option is true", ->
|
||||
it "autoscrolls to the selection", ->
|
||||
editor.manageScrollPosition = true
|
||||
editor.setLineHeight(10)
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setDefaultCharWidth(10)
|
||||
editor.setHeight(50)
|
||||
editor.setWidth(50)
|
||||
editor.setHorizontalScrollbarHeight(0)
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
|
||||
editor.setSelectedBufferRange([[5, 6], [6, 8]], autoscroll: true)
|
||||
@@ -1339,10 +1404,14 @@ describe "Editor", ->
|
||||
expect(selection.isEmpty()).toBeTruthy()
|
||||
|
||||
it "does not share selections between different edit sessions for the same buffer", ->
|
||||
editor2 = atom.project.openSync('sample.js')
|
||||
editor.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
|
||||
editor2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]])
|
||||
expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges()
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor2 = o
|
||||
|
||||
runs ->
|
||||
editor.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
|
||||
editor2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]])
|
||||
expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges()
|
||||
|
||||
describe "buffer manipulation", ->
|
||||
describe ".insertText(text)", ->
|
||||
@@ -1547,6 +1616,13 @@ describe "Editor", ->
|
||||
expect(editor.lineForBufferRow(1)).toBe ' '
|
||||
expect(editor.lineForBufferRow(2)).toBe '}'
|
||||
|
||||
describe "when a new line is appended before a closing tag (e.g. by pressing enter before a selection)", ->
|
||||
it "moves the line down and keeps the indentation level the same when editor.autoIndent is true", ->
|
||||
atom.config.set('editor.autoIndent', true)
|
||||
editor.setCursorBufferPosition([9,2])
|
||||
editor.insertNewline()
|
||||
expect(editor.lineForBufferRow(10)).toBe ' };'
|
||||
|
||||
describe ".backspace()", ->
|
||||
describe "when there is a single cursor", ->
|
||||
changeScreenRangeHandler = null
|
||||
@@ -1694,26 +1770,26 @@ describe "Editor", ->
|
||||
editor.backspace()
|
||||
expect(editor.lineForBufferRow(0)).toBe 'var = () {'
|
||||
|
||||
describe ".backspaceToBeginningOfWord()", ->
|
||||
describe ".deleteToBeginningOfWord()", ->
|
||||
describe "when no text is selected", ->
|
||||
it "deletes all text between the cursor and the beginning of the word", ->
|
||||
editor.setCursorBufferPosition([1, 24])
|
||||
editor.addCursorAtBufferPosition([3, 5])
|
||||
[cursor1, cursor2] = editor.getCursors()
|
||||
|
||||
editor.backspaceToBeginningOfWord()
|
||||
editor.deleteToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(ems) {'
|
||||
expect(buffer.lineForRow(3)).toBe ' ar pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 22]
|
||||
expect(cursor2.getBufferPosition()).toEqual [3, 4]
|
||||
|
||||
editor.backspaceToBeginningOfWord()
|
||||
editor.deleteToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = functionems) {'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return itemsar pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 21]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 39]
|
||||
|
||||
editor.backspaceToBeginningOfWord()
|
||||
editor.deleteToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = ems) {'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return ar pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 13]
|
||||
@@ -1721,24 +1797,24 @@ describe "Editor", ->
|
||||
|
||||
editor.setText(' var sort')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
editor.backspaceToBeginningOfWord()
|
||||
editor.deleteToBeginningOfWord()
|
||||
expect(buffer.lineForRow(0)).toBe 'var sort'
|
||||
|
||||
describe "when text is selected", ->
|
||||
it "deletes only selected text", ->
|
||||
editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]])
|
||||
editor.backspaceToBeginningOfWord()
|
||||
editor.deleteToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {'
|
||||
expect(buffer.lineForRow(2)).toBe 'if (items.length <= 1) return items;'
|
||||
|
||||
describe ".backspaceToBeginningOfLine()", ->
|
||||
describe ".deleteToBeginningOfLine()", ->
|
||||
describe "when no text is selected", ->
|
||||
it "deletes all text between the cursor and the beginning of the line", ->
|
||||
editor.setCursorBufferPosition([1, 24])
|
||||
editor.addCursorAtBufferPosition([2, 5])
|
||||
[cursor1, cursor2] = editor.getCursors()
|
||||
|
||||
editor.backspaceToBeginningOfLine()
|
||||
editor.deleteToBeginningOfLine()
|
||||
expect(buffer.lineForRow(1)).toBe 'ems) {'
|
||||
expect(buffer.lineForRow(2)).toBe 'f (items.length <= 1) return items;'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 0]
|
||||
@@ -1747,13 +1823,13 @@ describe "Editor", ->
|
||||
describe "when at the beginning of the line", ->
|
||||
it "deletes the newline", ->
|
||||
editor.setCursorBufferPosition([2])
|
||||
editor.backspaceToBeginningOfLine()
|
||||
editor.deleteToBeginningOfLine()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(items) { if (items.length <= 1) return items;'
|
||||
|
||||
describe "when text is selected", ->
|
||||
it "still deletes all text to begginning of the line", ->
|
||||
editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]])
|
||||
editor.backspaceToBeginningOfLine()
|
||||
editor.deleteToBeginningOfLine()
|
||||
expect(buffer.lineForRow(1)).toBe 'ems) {'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return items;'
|
||||
|
||||
@@ -2026,17 +2102,44 @@ describe "Editor", ->
|
||||
|
||||
describe ".copySelectedText()", ->
|
||||
it "copies selected text onto the clipboard", ->
|
||||
editor.setSelectedBufferRanges([[[0,4], [0,13]], [[1,6], [1, 10]], [[2,8], [2, 13]]])
|
||||
|
||||
editor.copySelectedText()
|
||||
expect(buffer.lineForRow(0)).toBe "var quicksort = function () {"
|
||||
expect(buffer.lineForRow(1)).toBe " var sort = function(items) {"
|
||||
expect(clipboard.readText()).toBe 'quicksort\nsort'
|
||||
expect(buffer.lineForRow(2)).toBe " if (items.length <= 1) return items;"
|
||||
expect(clipboard.readText()).toBe 'quicksort\nsort\nitems'
|
||||
expect(atom.clipboard.readWithMetadata().metadata.selections).toEqual([
|
||||
'quicksort'
|
||||
'sort'
|
||||
'items'
|
||||
])
|
||||
|
||||
describe ".pasteText()", ->
|
||||
it "pastes text into the buffer", ->
|
||||
atom.clipboard.write('first')
|
||||
editor.pasteText()
|
||||
expect(editor.buffer.lineForRow(0)).toBe "var first = function () {"
|
||||
expect(buffer.lineForRow(1)).toBe " var first = function(items) {"
|
||||
expect(editor.lineForBufferRow(0)).toBe "var first = function () {"
|
||||
expect(editor.lineForBufferRow(1)).toBe " var first = function(items) {"
|
||||
|
||||
describe 'when the clipboard has many selections', ->
|
||||
it "pastes each selection separately into the buffer", ->
|
||||
atom.clipboard.write('first\nsecond', {selections: ['first', 'second'] })
|
||||
editor.pasteText()
|
||||
expect(editor.lineForBufferRow(0)).toBe "var first = function () {"
|
||||
expect(editor.lineForBufferRow(1)).toBe " var second = function(items) {"
|
||||
|
||||
describe 'and the selections count does not match', ->
|
||||
it "pastes the whole text into the buffer", ->
|
||||
atom.clipboard.write('first\nsecond\nthird', {selections: ['first', 'second', 'third'] })
|
||||
editor.pasteText()
|
||||
expect(editor.lineForBufferRow(0)).toBe "var first"
|
||||
expect(editor.lineForBufferRow(1)).toBe "second"
|
||||
expect(editor.lineForBufferRow(2)).toBe "third = function () {"
|
||||
|
||||
expect(editor.lineForBufferRow(3)).toBe " var first"
|
||||
expect(editor.lineForBufferRow(4)).toBe "second"
|
||||
expect(editor.lineForBufferRow(5)).toBe "third = function(items) {"
|
||||
|
||||
describe ".indentSelectedRows()", ->
|
||||
describe "when nothing is selected", ->
|
||||
@@ -2225,10 +2328,14 @@ describe "Editor", ->
|
||||
|
||||
it "does not explode if the current language mode has no comment regex", ->
|
||||
editor.destroy()
|
||||
editor = atom.project.openSync(null, autoIndent: false)
|
||||
editor.setSelectedBufferRange([[4, 5], [4, 5]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(null, autoIndent: false).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.setSelectedBufferRange([[4, 5], [4, 5]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
|
||||
|
||||
it "uncomments when the line lacks the trailing whitespace in the comment regex", ->
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
@@ -2547,14 +2654,21 @@ describe "Editor", ->
|
||||
|
||||
describe "soft-tabs detection", ->
|
||||
it "assigns soft / hard tabs based on the contents of the buffer, or uses the default if unknown", ->
|
||||
editor = atom.project.openSync('sample.js', softTabs: false)
|
||||
expect(editor.getSoftTabs()).toBeTruthy()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js', softTabs: false).then (editor) ->
|
||||
expect(editor.getSoftTabs()).toBeTruthy()
|
||||
|
||||
editor = atom.project.openSync('sample-with-tabs.coffee', softTabs: true)
|
||||
expect(editor.getSoftTabs()).toBeFalsy()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample-with-tabs.coffee', softTabs: true).then (editor) ->
|
||||
expect(editor.getSoftTabs()).toBeFalsy()
|
||||
|
||||
editor = atom.project.openSync(null, softTabs: false)
|
||||
expect(editor.getSoftTabs()).toBeFalsy()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample-with-tabs-and-initial-comment.js', softTabs: true).then (editor) ->
|
||||
expect(editor.getSoftTabs()).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(null, softTabs: false).then (editor) ->
|
||||
expect(editor.getSoftTabs()).toBeFalsy()
|
||||
|
||||
describe ".indentLevelForLine(line)", ->
|
||||
it "returns the indent level when the line has only leading whitespace", ->
|
||||
@@ -2578,16 +2692,21 @@ describe "Editor", ->
|
||||
|
||||
describe "when a better-matched grammar is added to syntax", ->
|
||||
it "switches to the better-matched grammar and re-tokenizes the buffer", ->
|
||||
editor.destroy()
|
||||
|
||||
jsGrammar = atom.syntax.selectGrammar('a.js')
|
||||
atom.syntax.removeGrammar(jsGrammar)
|
||||
|
||||
editor2 = atom.project.openSync('sample.js', autoIndent: false)
|
||||
expect(editor2.getGrammar()).toBe atom.syntax.nullGrammar
|
||||
expect(editor2.lineForScreenRow(0).tokens.length).toBe 1
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js', autoIndent: false).then (o) -> editor = o
|
||||
|
||||
atom.syntax.addGrammar(jsGrammar)
|
||||
expect(editor2.getGrammar()).toBe jsGrammar
|
||||
expect(editor2.lineForScreenRow(0).tokens.length).toBeGreaterThan 1
|
||||
runs ->
|
||||
expect(editor.getGrammar()).toBe atom.syntax.nullGrammar
|
||||
expect(editor.lineForScreenRow(0).tokens.length).toBe 1
|
||||
|
||||
atom.syntax.addGrammar(jsGrammar)
|
||||
expect(editor.getGrammar()).toBe jsGrammar
|
||||
expect(editor.lineForScreenRow(0).tokens.length).toBeGreaterThan 1
|
||||
|
||||
describe "auto-indent", ->
|
||||
copyText = (text, {startColumn}={}) ->
|
||||
@@ -2764,6 +2883,18 @@ describe "Editor", ->
|
||||
expect(editor.lineForBufferRow(4)).toBe " }"
|
||||
expect(editor.lineForBufferRow(5)).toBe " i=1"
|
||||
|
||||
describe "soft and hard tabs", ->
|
||||
it "resets the tab style when tokenization is complete", ->
|
||||
editor.destroy()
|
||||
atom.project.open('sample-with-tabs-and-leading-comment.coffee').then (o) -> editor = o
|
||||
expect(editor.softTabs).toBe true
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-coffee-script')
|
||||
|
||||
runs ->
|
||||
expect(editor.softTabs).toBe false
|
||||
|
||||
describe ".destroy()", ->
|
||||
it "destroys all markers associated with the edit session", ->
|
||||
expect(buffer.getMarkerCount()).toBeGreaterThan 0
|
||||
@@ -2874,10 +3005,15 @@ describe "Editor", ->
|
||||
expect(editor.shouldPromptToSave()).toBeFalsy()
|
||||
buffer.setText('changed')
|
||||
expect(editor.shouldPromptToSave()).toBeTruthy()
|
||||
editor2 = atom.project.openSync('sample.js', autoIndent: false)
|
||||
expect(editor.shouldPromptToSave()).toBeFalsy()
|
||||
editor2.destroy()
|
||||
expect(editor.shouldPromptToSave()).toBeTruthy()
|
||||
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js', autoIndent: false).then (o) -> editor2 = o
|
||||
|
||||
runs ->
|
||||
expect(editor.shouldPromptToSave()).toBeFalsy()
|
||||
editor2.destroy()
|
||||
expect(editor.shouldPromptToSave()).toBeTruthy()
|
||||
|
||||
describe "when the edit session contains surrogate pair characters", ->
|
||||
it "correctly backspaces over them", ->
|
||||
@@ -2973,12 +3109,15 @@ describe "Editor", ->
|
||||
|
||||
describe "when the grammar is added", ->
|
||||
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.setText("// http://github.com")
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js').then (o) -> editor = o
|
||||
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " http://github.com"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
runs ->
|
||||
editor.setText("// http://github.com")
|
||||
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " http://github.com"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-hyperlink')
|
||||
@@ -2990,12 +3129,15 @@ describe "Editor", ->
|
||||
|
||||
describe "when the grammar is updated", ->
|
||||
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.setText("// SELECT * FROM OCTOCATS")
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js').then (o) -> editor = o
|
||||
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
runs ->
|
||||
editor.setText("// SELECT * FROM OCTOCATS")
|
||||
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('package-with-injection-selector')
|
||||
@@ -3032,10 +3174,11 @@ describe "Editor", ->
|
||||
describe ".scrollToCursorPosition()", ->
|
||||
it "scrolls the last cursor into view", ->
|
||||
editor.setCursorScreenPosition([8, 8])
|
||||
editor.setLineHeight(10)
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setDefaultCharWidth(10)
|
||||
editor.setHeight(50)
|
||||
editor.setWidth(50)
|
||||
editor.setHorizontalScrollbarHeight(0)
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
expect(editor.getScrollLeft()).toBe 0
|
||||
|
||||
@@ -3047,7 +3190,7 @@ describe "Editor", ->
|
||||
it "scrolls one screen height up or down", ->
|
||||
editor.manageScrollPosition = true
|
||||
|
||||
editor.setLineHeight(10)
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setHeight(50)
|
||||
expect(editor.getScrollHeight()).toBe 130
|
||||
|
||||
|
||||
+190
-102
@@ -7,28 +7,36 @@ path = require 'path'
|
||||
temp = require 'temp'
|
||||
|
||||
describe "EditorView", ->
|
||||
[buffer, editorView, editor, cachedLineHeight, cachedCharWidth] = []
|
||||
[buffer, editorView, editor, cachedEditor, cachedLineHeight, cachedCharWidth, fart] = []
|
||||
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
buffer = editor.buffer
|
||||
editorView = new EditorView(editor)
|
||||
editorView.lineOverdraw = 2
|
||||
editorView.isFocused = true
|
||||
editorView.enableKeymap()
|
||||
editorView.calculateHeightInLines = ->
|
||||
Math.ceil(@height() / @lineHeight)
|
||||
editorView.attachToDom = ({ heightInLines, widthInChars } = {}) ->
|
||||
heightInLines ?= @getEditor().getBuffer().getLineCount()
|
||||
@height(getLineHeight() * heightInLines)
|
||||
@width(getCharWidth() * widthInChars) if widthInChars
|
||||
$('#jasmine-content').append(this)
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js').then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-text', sync: true)
|
||||
atom.workspace.open('sample.less').then (o) -> cachedEditor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
editorView = new EditorView(editor)
|
||||
editorView.lineOverdraw = 2
|
||||
editorView.isFocused = true
|
||||
editorView.enableKeymap()
|
||||
|
||||
editorView.calculateHeightInLines = ->
|
||||
Math.ceil(@height() / @lineHeight)
|
||||
|
||||
editorView.attachToDom = ({ heightInLines, widthInChars } = {}) ->
|
||||
heightInLines ?= @getEditor().getBuffer().getLineCount()
|
||||
@height(getLineHeight() * heightInLines)
|
||||
@width(getCharWidth() * widthInChars) if widthInChars
|
||||
$('#jasmine-content').append(this)
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
atom.packages.activatePackage('language-text')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
|
||||
getLineHeight = ->
|
||||
return cachedLineHeight if cachedLineHeight?
|
||||
@@ -41,7 +49,7 @@ describe "EditorView", ->
|
||||
cachedCharWidth
|
||||
|
||||
calcDimensions = ->
|
||||
editorForMeasurement = new EditorView(editor: atom.project.openSync('sample.js'))
|
||||
editorForMeasurement = new EditorView({editor: cachedEditor})
|
||||
editorForMeasurement.attachToDom()
|
||||
cachedLineHeight = editorForMeasurement.lineHeight
|
||||
cachedCharWidth = editorForMeasurement.charWidth
|
||||
@@ -105,18 +113,23 @@ describe "EditorView", ->
|
||||
|
||||
describe "when the editor's file is modified on disk", ->
|
||||
it "triggers an alert", ->
|
||||
fileChangeHandler = null
|
||||
filePath = path.join(temp.dir, 'atom-changed-file.txt')
|
||||
fs.writeFileSync(filePath, "")
|
||||
editor = atom.project.openSync(filePath)
|
||||
editorView.edit(editor)
|
||||
editor.insertText("now the buffer is modified")
|
||||
|
||||
fileChangeHandler = jasmine.createSpy('fileChange')
|
||||
editor.buffer.file.on 'contents-changed', fileChangeHandler
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (o) -> editor = o
|
||||
|
||||
spyOn(atom, "confirm")
|
||||
runs ->
|
||||
editorView.edit(editor)
|
||||
editor.insertText("now the buffer is modified")
|
||||
|
||||
fs.writeFileSync(filePath, "a file change")
|
||||
fileChangeHandler = jasmine.createSpy('fileChange')
|
||||
editor.buffer.file.on 'contents-changed', fileChangeHandler
|
||||
|
||||
spyOn(atom, "confirm")
|
||||
|
||||
fs.writeFileSync(filePath, "a file change")
|
||||
|
||||
waitsFor "file to trigger contents-changed event", ->
|
||||
fileChangeHandler.callCount > 0
|
||||
@@ -133,8 +146,11 @@ describe "EditorView", ->
|
||||
[newEditor, newBuffer] = []
|
||||
|
||||
beforeEach ->
|
||||
newEditor = atom.project.openSync('two-hundred.txt')
|
||||
newBuffer = newEditor.buffer
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('two-hundred.txt').then (o) -> newEditor = o
|
||||
|
||||
runs ->
|
||||
newBuffer = newEditor.buffer
|
||||
|
||||
it "updates the rendered lines, cursors, selections, scroll position, and event subscriptions to match the given edit session", ->
|
||||
editorView.attachToDom(heightInLines: 5, widthInChars: 30)
|
||||
@@ -170,17 +186,24 @@ describe "EditorView", ->
|
||||
expect(editorView.lineElementForScreenRow(6).text()).toMatch /^ currentgoodbye/
|
||||
|
||||
it "triggers alert if edit session's buffer goes into conflict with changes on disk", ->
|
||||
contentsConflictedHandler = null
|
||||
filePath = path.join(temp.dir, 'atom-changed-file.txt')
|
||||
fs.writeFileSync(filePath, "")
|
||||
tempEditor = atom.project.openSync(filePath)
|
||||
editorView.edit(tempEditor)
|
||||
tempEditor.insertText("a buffer change")
|
||||
tempEditor = null
|
||||
|
||||
spyOn(atom, "confirm")
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (o) -> tempEditor = o
|
||||
|
||||
runs ->
|
||||
editorView.edit(tempEditor)
|
||||
tempEditor.insertText("a buffer change")
|
||||
|
||||
spyOn(atom, "confirm")
|
||||
|
||||
contentsConflictedHandler = jasmine.createSpy("contentsConflictedHandler")
|
||||
tempEditor.on 'contents-conflicted', contentsConflictedHandler
|
||||
fs.writeFileSync(filePath, "a file change")
|
||||
|
||||
contentsConflictedHandler = jasmine.createSpy("contentsConflictedHandler")
|
||||
tempEditor.on 'contents-conflicted', contentsConflictedHandler
|
||||
fs.writeFileSync(filePath, "a file change")
|
||||
waitsFor ->
|
||||
contentsConflictedHandler.callCount > 0
|
||||
|
||||
@@ -281,26 +304,34 @@ describe "EditorView", ->
|
||||
it "emits event when editor view view receives a new buffer", ->
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
editorView.on 'editor:path-changed', eventHandler
|
||||
editorView.edit(atom.project.openSync(filePath))
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (editor) ->
|
||||
editorView.edit(editor)
|
||||
|
||||
runs ->
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
it "stops listening to events on previously set buffers", ->
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
oldBuffer = editor.getBuffer()
|
||||
newEditor = atom.project.openSync(filePath)
|
||||
editorView.on 'editor:path-changed', eventHandler
|
||||
newEditor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (o) -> newEditor = o
|
||||
|
||||
editorView.edit(newEditor)
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
runs ->
|
||||
editorView.on 'editor:path-changed', eventHandler
|
||||
|
||||
eventHandler.reset()
|
||||
oldBuffer.saveAs(path.join(temp.dir, 'atom-bad.txt'))
|
||||
expect(eventHandler).not.toHaveBeenCalled()
|
||||
editorView.edit(newEditor)
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
eventHandler.reset()
|
||||
newEditor.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt'))
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
eventHandler.reset()
|
||||
oldBuffer.saveAs(path.join(temp.dir, 'atom-bad.txt'))
|
||||
expect(eventHandler).not.toHaveBeenCalled()
|
||||
|
||||
eventHandler.reset()
|
||||
newEditor.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt'))
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
it "loads the grammar for the new path", ->
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
@@ -478,7 +509,7 @@ describe "EditorView", ->
|
||||
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]]
|
||||
|
||||
describe "when clicking between a word and a non-word", ->
|
||||
describe "when double-clicking between a word and a non-word", ->
|
||||
it "selects the word", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 21], originalEvent: {detail: 1})
|
||||
@@ -501,6 +532,30 @@ describe "EditorView", ->
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
expect(editor.getSelectedText()).toBe "{"
|
||||
|
||||
describe "when double-clicking on whitespace", ->
|
||||
it "selects all adjacent whitespace", ->
|
||||
editor.setText(" some text ")
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 2], originalEvent: {detail: 1})
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 2], originalEvent: {detail: 2})
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 3]]
|
||||
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 1})
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 2})
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0, 7], [0, 9]]
|
||||
|
||||
editor.setCursorBufferPosition([0, 14])
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 14], originalEvent: {detail: 1})
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 14], originalEvent: {detail: 2})
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0, 13], [0, 17]]
|
||||
|
||||
describe "triple/quardruple/etc-click", ->
|
||||
it "selects the line under the cursor", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
|
||||
@@ -1529,14 +1584,18 @@ describe "EditorView", ->
|
||||
|
||||
describe "when autoscrolling at the end of the document", ->
|
||||
it "renders lines properly", ->
|
||||
editorView.edit(atom.project.openSync('two-hundred.txt'))
|
||||
editorView.attachToDom(heightInLines: 5.5)
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('two-hundred.txt').then (editor) ->
|
||||
editorView.edit(editor)
|
||||
|
||||
expect(editorView.renderedLines.find('.line').length).toBe 8
|
||||
runs ->
|
||||
editorView.attachToDom(heightInLines: 5.5)
|
||||
|
||||
editor.moveCursorToBottom()
|
||||
expect(editorView.renderedLines.find('.line').length).toBe 8
|
||||
|
||||
expect(editorView.renderedLines.find('.line').length).toBe 8
|
||||
editor.moveCursorToBottom()
|
||||
|
||||
expect(editorView.renderedLines.find('.line').length).toBe 8
|
||||
|
||||
describe "when line has a character that could push it to be too tall (regression)", ->
|
||||
it "does renders the line at a consistent height", ->
|
||||
@@ -1744,6 +1803,13 @@ describe "EditorView", ->
|
||||
expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} "
|
||||
expect(editorView.renderedLines.find('.line:eq(10) .invisible-character').text()).toBe eol
|
||||
|
||||
describe "when editor.showIndentGuide is set to false", ->
|
||||
it "does not render the indent guide on whitespace only lines (regression)", ->
|
||||
editorView.attachToDom()
|
||||
editor.setText(' ')
|
||||
atom.config.set('editor.showIndentGuide', false)
|
||||
expect(editorView.renderedLines.find('.line:eq(0) .indent-guide').length).toBe 0
|
||||
|
||||
describe "when soft-wrap is enabled", ->
|
||||
beforeEach ->
|
||||
jasmine.unspy(window, 'setTimeout')
|
||||
@@ -1784,10 +1850,14 @@ describe "EditorView", ->
|
||||
expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60]
|
||||
|
||||
it "does not wrap the lines of any newly assigned buffers", ->
|
||||
otherEditor = atom.project.openSync()
|
||||
otherEditor.buffer.setText([1..100].join(''))
|
||||
editorView.edit(otherEditor)
|
||||
expect(editorView.renderedLines.find('.line').length).toBe(1)
|
||||
otherEditor = null
|
||||
waitsForPromise ->
|
||||
atom.workspace.open().then (o) -> otherEditor = o
|
||||
|
||||
runs ->
|
||||
otherEditor.buffer.setText([1..100].join(''))
|
||||
editorView.edit(otherEditor)
|
||||
expect(editorView.renderedLines.find('.line').length).toBe(1)
|
||||
|
||||
it "unwraps lines when softwrap is disabled", ->
|
||||
editorView.toggleSoftWrap()
|
||||
@@ -1816,15 +1886,15 @@ describe "EditorView", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual [11, 0]
|
||||
|
||||
it "calls .setWidthInChars() when the editor view is attached because now its dimensions are available to calculate it", ->
|
||||
otherEditor = new EditorView(editor: atom.project.openSync('sample.js'))
|
||||
spyOn(otherEditor, 'setWidthInChars')
|
||||
otherEditorView = new EditorView(editor)
|
||||
spyOn(otherEditorView, 'setWidthInChars')
|
||||
|
||||
otherEditor.editor.setSoftWrap(true)
|
||||
expect(otherEditor.setWidthInChars).not.toHaveBeenCalled()
|
||||
otherEditorView.editor.setSoftWrap(true)
|
||||
expect(otherEditorView.setWidthInChars).not.toHaveBeenCalled()
|
||||
|
||||
otherEditor.simulateDomAttachment()
|
||||
expect(otherEditor.setWidthInChars).toHaveBeenCalled()
|
||||
otherEditor.remove()
|
||||
otherEditorView.simulateDomAttachment()
|
||||
expect(otherEditorView.setWidthInChars).toHaveBeenCalled()
|
||||
otherEditorView.remove()
|
||||
|
||||
describe "when the editor view's width changes", ->
|
||||
it "updates the width in characters on the edit session", ->
|
||||
@@ -1975,15 +2045,19 @@ describe "EditorView", ->
|
||||
|
||||
describe "when the switching from an edit session for a long buffer to an edit session for a short buffer", ->
|
||||
it "updates the line numbers to reflect the shorter buffer", ->
|
||||
emptyEditor = atom.project.openSync(null)
|
||||
editorView.edit(emptyEditor)
|
||||
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
|
||||
emptyEditor = null
|
||||
waitsForPromise ->
|
||||
atom.workspace.open().then (o) -> emptyEditor = o
|
||||
|
||||
editorView.edit(editor)
|
||||
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1
|
||||
runs ->
|
||||
editorView.edit(emptyEditor)
|
||||
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
|
||||
|
||||
editorView.edit(emptyEditor)
|
||||
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
|
||||
editorView.edit(editor)
|
||||
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1
|
||||
|
||||
editorView.edit(emptyEditor)
|
||||
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
|
||||
|
||||
describe "when the editor view is mini", ->
|
||||
it "hides the gutter", ->
|
||||
@@ -2203,10 +2277,13 @@ describe "EditorView", ->
|
||||
|
||||
describe "folding", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('two-hundred.txt')
|
||||
buffer = editor.buffer
|
||||
editorView.edit(editor)
|
||||
editorView.attachToDom()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('two-hundred.txt').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
editorView.edit(editor)
|
||||
editorView.attachToDom()
|
||||
|
||||
describe "when a fold-selection event is triggered", ->
|
||||
it "folds the lines covered by the selection into a single line with a fold class and marker", ->
|
||||
@@ -2260,7 +2337,7 @@ describe "EditorView", ->
|
||||
it "adds/removes the 'fold-selected' class to the fold's line element and hides the cursor if it is on the fold line", ->
|
||||
editor.createFold(2, 4)
|
||||
|
||||
editor.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, isReversed: true)
|
||||
editor.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, reversed: true)
|
||||
expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected')
|
||||
|
||||
editor.setSelectedBufferRange([[1, 0], [1, 1]], preserveFolds: true)
|
||||
@@ -2336,16 +2413,20 @@ describe "EditorView", ->
|
||||
expect(editorView.getFirstVisibleScreenRow()).toBe(0)
|
||||
|
||||
describe ".checkoutHead()", ->
|
||||
[filePath, originalPathText] = []
|
||||
[filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
filePath = atom.project.resolve('git/working-dir/file.txt')
|
||||
originalPathText = fs.readFileSync(filePath, 'utf8')
|
||||
editor = atom.project.openSync(filePath)
|
||||
editorView.edit(editor)
|
||||
workingDirPath = temp.mkdirSync('atom-working-dir')
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'git', 'working-dir'), workingDirPath)
|
||||
fs.renameSync(path.join(workingDirPath, 'git.git'), path.join(workingDirPath, '.git'))
|
||||
atom.project.setPath(workingDirPath)
|
||||
filePath = atom.project.resolve('file.txt')
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, originalPathText)
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editorView.edit(editor)
|
||||
|
||||
it "restores the contents of the editor view to the HEAD revision", ->
|
||||
editor.setText('')
|
||||
@@ -2360,7 +2441,7 @@ describe "EditorView", ->
|
||||
fileChangeHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(editor.getText()).toBe(originalPathText)
|
||||
expect(editor.getText()).toBe('undefined')
|
||||
|
||||
describe ".pixelPositionForBufferPosition(position)", ->
|
||||
describe "when the editor view is detached", ->
|
||||
@@ -2816,7 +2897,7 @@ describe "EditorView", ->
|
||||
|
||||
describe "when the escape key is pressed on the editor view", ->
|
||||
it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", ->
|
||||
atom.keymaps.bindKeys 'name', '.editor', {'escape': 'test-event'}
|
||||
atom.keymaps.add 'name', '.editor': {'escape': 'test-event'}
|
||||
testEventHandler = jasmine.createSpy("testEventHandler")
|
||||
|
||||
editorView.on 'test-event', testEventHandler
|
||||
@@ -2833,22 +2914,26 @@ describe "EditorView", ->
|
||||
describe "when the editor view is attached but invisible", ->
|
||||
describe "when the editor view's text is changed", ->
|
||||
it "redraws the editor view when it is next shown", ->
|
||||
displayUpdatedHandler = null
|
||||
atom.workspaceView = new WorkspaceView
|
||||
atom.workspaceView.openSync('sample.js')
|
||||
atom.workspaceView.attachToDom()
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
waitsForPromise ->
|
||||
atom.workspaceView.open('sample.txt').then (o) -> editor = o
|
||||
|
||||
view = $$ -> @div id: 'view', tabindex: -1, 'View'
|
||||
editorView.getPane().activateItem(view)
|
||||
expect(editorView.isVisible()).toBeFalsy()
|
||||
runs ->
|
||||
atom.workspaceView.attachToDom()
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
|
||||
editor.setText('hidden changes')
|
||||
editor.setCursorBufferPosition([0,4])
|
||||
view = $$ -> @div id: 'view', tabindex: -1, 'View'
|
||||
editorView.getPane().activateItem(view)
|
||||
expect(editorView.isVisible()).toBeFalsy()
|
||||
|
||||
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
|
||||
editorView.on 'editor:display-updated', displayUpdatedHandler
|
||||
editorView.getPane().activateItem(editorView.getModel())
|
||||
expect(editorView.isVisible()).toBeTruthy()
|
||||
editor.setText('hidden changes')
|
||||
editor.setCursorBufferPosition([0,4])
|
||||
|
||||
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
|
||||
editorView.on 'editor:display-updated', displayUpdatedHandler
|
||||
editorView.getPane().activateItem(editorView.getModel())
|
||||
expect(editorView.isVisible()).toBeTruthy()
|
||||
|
||||
waitsFor ->
|
||||
displayUpdatedHandler.callCount is 1
|
||||
@@ -2888,14 +2973,17 @@ describe "EditorView", ->
|
||||
describe "when the editor view is removed", ->
|
||||
it "fires a editor:will-be-removed event", ->
|
||||
atom.workspaceView = new WorkspaceView
|
||||
atom.workspaceView.openSync('sample.js')
|
||||
atom.workspaceView.attachToDom()
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js')
|
||||
|
||||
willBeRemovedHandler = jasmine.createSpy('willBeRemovedHandler')
|
||||
editorView.on 'editor:will-be-removed', willBeRemovedHandler
|
||||
editorView.getPane().destroyActiveItem()
|
||||
expect(willBeRemovedHandler).toHaveBeenCalled()
|
||||
runs ->
|
||||
atom.workspaceView.attachToDom()
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
|
||||
willBeRemovedHandler = jasmine.createSpy('willBeRemovedHandler')
|
||||
editorView.on 'editor:will-be-removed', willBeRemovedHandler
|
||||
editorView.getPane().destroyActiveItem()
|
||||
expect(willBeRemovedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when setInvisibles is toggled (regression)", ->
|
||||
it "renders inserted newlines properly", ->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
undefined
|
||||
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
+1
@@ -0,0 +1 @@
|
||||
x�ŽInB1³ö)úσ„¢°fÉ Úîvb�ù‘c†ãóQn�e=©žª,½· ÚÄ·9˜¡r&V!ªÆq¢êuH¢.Éâ)i6Ί|™àtuÞº�}-(+lUΉŒf_pUµQIcx�ßË€ßÚŽxoåÔ`wzáï}~ulçmYú(+•�QJ¤ëºvNþÿƒØµñž·ó1ÅiHL¢
|
||||
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
@@ -1 +1 @@
|
||||
ef046e9eecaa5255ea5e9817132d4001724d6ae1
|
||||
8a9c86f1cb1f14b8f436eb91f4b052c8802ca99e
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Full of text
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Look, this is a comment. Don't go making assumtions that I want soft tabs
|
||||
* because this block comment has leading spaces, Geez.
|
||||
*/
|
||||
|
||||
if (beNice) {
|
||||
console.log('Thank you for being nice.');
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# This is a comment
|
||||
if this.studyingEconomics
|
||||
buy() while supply > demand
|
||||
sell() until supply > demand
|
||||
+60
-95
@@ -4,6 +4,12 @@ fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
Task = require '../src/task'
|
||||
|
||||
copyRepository = ->
|
||||
workingDirPath = temp.mkdirSync('atom-working-dir')
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'git', 'working-dir'), workingDirPath)
|
||||
fs.renameSync(path.join(workingDirPath, 'git.git'), path.join(workingDirPath, '.git'))
|
||||
workingDirPath
|
||||
|
||||
describe "Git", ->
|
||||
repo = null
|
||||
|
||||
@@ -41,17 +47,13 @@ describe "Git", ->
|
||||
expect(repo.isPathIgnored('b.txt')).toBeFalsy()
|
||||
|
||||
describe ".isPathModified(path)", ->
|
||||
[repo, filePath, newPath, originalPathText] = []
|
||||
[repo, filePath, newPath] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
filePath = require.resolve('./fixtures/git/working-dir/file.txt')
|
||||
newPath = path.join(__dirname, 'fixtures', 'git', 'working-dir', 'new-path.txt')
|
||||
originalPathText = fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, originalPathText)
|
||||
fs.removeSync(newPath) if fs.existsSync(newPath)
|
||||
workingDirPath = copyRepository()
|
||||
repo = new Git(workingDirPath)
|
||||
filePath = path.join(workingDirPath, 'a.txt')
|
||||
newPath = path.join(workingDirPath, 'new-path.txt')
|
||||
|
||||
describe "when the path is unstaged", ->
|
||||
it "returns false if the path has not been modified", ->
|
||||
@@ -72,14 +74,12 @@ describe "Git", ->
|
||||
[filePath, newPath] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
filePath = require.resolve('./fixtures/git/working-dir/file.txt')
|
||||
newPath = path.join(__dirname, 'fixtures', 'git', 'working-dir', 'new-path.txt')
|
||||
workingDirPath = copyRepository()
|
||||
repo = new Git(workingDirPath)
|
||||
filePath = path.join(workingDirPath, 'a.txt')
|
||||
newPath = path.join(workingDirPath, 'new-path.txt')
|
||||
fs.writeFileSync(newPath, "i'm new here")
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(newPath) if fs.existsSync(newPath)
|
||||
|
||||
describe "when the path is unstaged", ->
|
||||
it "returns true if the path is new", ->
|
||||
expect(repo.isPathNew(newPath)).toBeTruthy()
|
||||
@@ -88,48 +88,35 @@ describe "Git", ->
|
||||
expect(repo.isPathNew(filePath)).toBeFalsy()
|
||||
|
||||
describe ".checkoutHead(path)", ->
|
||||
[path1, path2, originalPath1Text, originalPath2Text] = []
|
||||
[filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
path1 = require.resolve('./fixtures/git/working-dir/file.txt')
|
||||
originalPath1Text = fs.readFileSync(path1, 'utf8')
|
||||
path2 = require.resolve('./fixtures/git/working-dir/other.txt')
|
||||
originalPath2Text = fs.readFileSync(path2, 'utf8')
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(path1, originalPath1Text)
|
||||
fs.writeFileSync(path2, originalPath2Text)
|
||||
workingDirPath = copyRepository()
|
||||
repo = new Git(workingDirPath)
|
||||
filePath = path.join(workingDirPath, 'a.txt')
|
||||
|
||||
it "no longer reports a path as modified after checkout", ->
|
||||
expect(repo.isPathModified(path1)).toBeFalsy()
|
||||
fs.writeFileSync(path1, '')
|
||||
expect(repo.isPathModified(path1)).toBeTruthy()
|
||||
expect(repo.checkoutHead(path1)).toBeTruthy()
|
||||
expect(repo.isPathModified(path1)).toBeFalsy()
|
||||
expect(repo.isPathModified(filePath)).toBeFalsy()
|
||||
fs.writeFileSync(filePath, 'ch ch changes')
|
||||
expect(repo.isPathModified(filePath)).toBeTruthy()
|
||||
expect(repo.checkoutHead(filePath)).toBeTruthy()
|
||||
expect(repo.isPathModified(filePath)).toBeFalsy()
|
||||
|
||||
it "restores the contents of the path to the original text", ->
|
||||
fs.writeFileSync(path1, '')
|
||||
expect(repo.checkoutHead(path1)).toBeTruthy()
|
||||
expect(fs.readFileSync(path1, 'utf8')).toBe(originalPath1Text)
|
||||
|
||||
it "only restores the path specified", ->
|
||||
fs.writeFileSync(path2, 'path 2 is edited')
|
||||
expect(repo.isPathModified(path2)).toBeTruthy()
|
||||
expect(repo.checkoutHead(path1)).toBeTruthy()
|
||||
expect(fs.readFileSync(path2, 'utf8')).toBe('path 2 is edited')
|
||||
expect(repo.isPathModified(path2)).toBeTruthy()
|
||||
fs.writeFileSync(filePath, 'ch ch changes')
|
||||
expect(repo.checkoutHead(filePath)).toBeTruthy()
|
||||
expect(fs.readFileSync(filePath, 'utf8')).toBe ''
|
||||
|
||||
it "fires a status-changed event if the checkout completes successfully", ->
|
||||
fs.writeFileSync(path1, '')
|
||||
repo.getPathStatus(path1)
|
||||
fs.writeFileSync(filePath, 'ch ch changes')
|
||||
repo.getPathStatus(filePath)
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
repo.on 'status-changed', statusHandler
|
||||
repo.checkoutHead(path1)
|
||||
repo.checkoutHead(filePath)
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler.argsForCall[0][0..1]).toEqual [path1, 0]
|
||||
expect(statusHandler.argsForCall[0][0..1]).toEqual [filePath, 0]
|
||||
|
||||
repo.checkoutHead(path1)
|
||||
repo.checkoutHead(filePath)
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
describe ".destroy()", ->
|
||||
@@ -138,32 +125,13 @@ describe "Git", ->
|
||||
repo.destroy()
|
||||
expect(-> repo.getShortHead()).toThrow()
|
||||
|
||||
describe ".getDiffStats(path)", ->
|
||||
[filePath, originalPathText] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
filePath = require.resolve('./fixtures/git/working-dir/file.txt')
|
||||
originalPathText = fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, originalPathText)
|
||||
|
||||
it "returns the number of lines added and deleted", ->
|
||||
expect(repo.getDiffStats(filePath)).toEqual {added: 0, deleted: 0}
|
||||
fs.writeFileSync(filePath, "#{originalPathText} edited line")
|
||||
expect(repo.getDiffStats(filePath)).toEqual {added: 1, deleted: 1}
|
||||
|
||||
describe ".getPathStatus(path)", ->
|
||||
[filePath, originalPathText] = []
|
||||
[filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
filePath = require.resolve('./fixtures/git/working-dir/file.txt')
|
||||
originalPathText = fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, originalPathText)
|
||||
workingDirectory = copyRepository()
|
||||
repo = new Git(workingDirectory)
|
||||
filePath = path.join(workingDirectory, 'file.txt')
|
||||
|
||||
it "trigger a status-changed event when the new status differs from the last cached one", ->
|
||||
statusHandler = jasmine.createSpy("statusHandler")
|
||||
@@ -178,16 +146,13 @@ describe "Git", ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
describe ".getDirectoryStatus(path)", ->
|
||||
[directoryPath, filePath, originalPathText] = []
|
||||
[directoryPath, filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
directoryPath = path.join(__dirname, 'fixtures', 'git', 'working-dir', 'dir')
|
||||
filePath = require.resolve('./fixtures/git/working-dir/dir/b.txt')
|
||||
originalPathText = fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, originalPathText)
|
||||
workingDirectory = copyRepository()
|
||||
repo = new Git(workingDirectory)
|
||||
directoryPath = path.join(workingDirectory, 'dir')
|
||||
filePath = path.join(directoryPath, 'b.txt')
|
||||
|
||||
it "gets the status based on the files inside the directory", ->
|
||||
expect(repo.isStatusModified(repo.getDirectoryStatus(directoryPath))).toBe false
|
||||
@@ -199,18 +164,15 @@ describe "Git", ->
|
||||
[newPath, modifiedPath, cleanPath, originalModifiedPathText] = []
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
modifiedPath = atom.project.resolve('git/working-dir/file.txt')
|
||||
originalModifiedPathText = fs.readFileSync(modifiedPath, 'utf8')
|
||||
newPath = atom.project.resolve('git/working-dir/untracked.txt')
|
||||
cleanPath = atom.project.resolve('git/working-dir/other.txt')
|
||||
workingDirectory = copyRepository()
|
||||
repo = new Git(workingDirectory)
|
||||
modifiedPath = path.join(workingDirectory, 'file.txt')
|
||||
newPath = path.join(workingDirectory, 'untracked.txt')
|
||||
cleanPath = path.join(workingDirectory, 'other.txt')
|
||||
fs.writeFileSync(cleanPath, 'Full of text')
|
||||
fs.writeFileSync(newPath, '')
|
||||
newPath = fs.absolute newPath # specs could be running under symbol path.
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(modifiedPath, originalModifiedPathText)
|
||||
fs.removeSync(newPath) if fs.existsSync(newPath)
|
||||
|
||||
it "returns status information for all new and modified files", ->
|
||||
fs.writeFileSync(modifiedPath, 'making this path modified')
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
@@ -226,14 +188,13 @@ describe "Git", ->
|
||||
expect(repo.isStatusModified(repo.getCachedPathStatus(modifiedPath))).toBeTruthy()
|
||||
|
||||
describe "buffer events", ->
|
||||
[originalContent, editor] = []
|
||||
[editor] = []
|
||||
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
originalContent = editor.getText()
|
||||
atom.project.setPath(copyRepository())
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(editor.getPath(), originalContent)
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('other.txt').then (o) -> editor = o
|
||||
|
||||
it "emits a status-changed event when a buffer is saved", ->
|
||||
editor.insertNewline()
|
||||
@@ -267,16 +228,20 @@ describe "Git", ->
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
describe "when a project is deserialized", ->
|
||||
[originalContent, buffer, project2] = []
|
||||
[buffer, project2] = []
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(buffer.getPath(), originalContent)
|
||||
project2?.destroy()
|
||||
|
||||
it "subscribes to all the serialized buffers in the project", ->
|
||||
atom.project.openSync('sample.js')
|
||||
project2 = atom.project.testSerialization()
|
||||
buffer = project2.getBuffers()[0]
|
||||
atom.project.setPath(copyRepository())
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('file.txt')
|
||||
|
||||
runs ->
|
||||
project2 = atom.project.testSerialization()
|
||||
buffer = project2.getBuffers()[0]
|
||||
|
||||
waitsFor ->
|
||||
buffer.loaded
|
||||
|
||||
@@ -6,8 +6,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "javascript", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.js', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
@@ -112,8 +114,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "coffeescript", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('coffee.coffee', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('coffee.coffee', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-coffee-script')
|
||||
@@ -161,8 +165,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "css", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('css.css', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('css.css', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-css')
|
||||
@@ -178,13 +184,13 @@ describe "LanguageMode", ->
|
||||
languageMode.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(0)).toBe "/*body {"
|
||||
expect(buffer.lineForRow(1)).toBe " font-size: 1234px;*/"
|
||||
expect(buffer.lineForRow(2)).toBe "/* width: 110%;*/"
|
||||
expect(buffer.lineForRow(2)).toBe " /*width: 110%;*/"
|
||||
expect(buffer.lineForRow(3)).toBe " font-weight: bold !important;"
|
||||
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(buffer.lineForRow(0)).toBe "body {"
|
||||
expect(buffer.lineForRow(1)).toBe " font-size: 1234px;"
|
||||
expect(buffer.lineForRow(2)).toBe "/* width: 110%;*/"
|
||||
expect(buffer.lineForRow(2)).toBe " /*width: 110%;*/"
|
||||
expect(buffer.lineForRow(3)).toBe " font-weight: bold !important;"
|
||||
|
||||
it "uncomments lines with leading whitespace", ->
|
||||
@@ -204,8 +210,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "less", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.less', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-less')
|
||||
@@ -220,9 +228,11 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "xml", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.xml', autoIndent: false)
|
||||
editor.setText("<!-- test -->")
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.xml', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
editor.setText("<!-- test -->")
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-xml')
|
||||
@@ -234,8 +244,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "folding", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.js', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
@@ -319,8 +331,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "folding with comments", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample-with-comments.js', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample-with-comments.js', autoIndent: false).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
@@ -385,7 +399,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "css", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('css.css', autoIndent: true)
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('css.css', autoIndent: true).then (o) ->
|
||||
editor = o
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-source')
|
||||
|
||||
@@ -21,11 +21,16 @@ describe "PaneView", ->
|
||||
container = new PaneContainerView
|
||||
view1 = new TestView(id: 'view-1', text: 'View 1')
|
||||
view2 = new TestView(id: 'view-2', text: 'View 2')
|
||||
editor1 = atom.project.openSync('sample.js')
|
||||
editor2 = atom.project.openSync('sample.txt')
|
||||
pane = container.getRoot()
|
||||
paneModel = pane.model
|
||||
paneModel.addItems([view1, editor1, view2, editor2])
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js').then (o) -> editor1 = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.txt').then (o) -> editor2 = o
|
||||
|
||||
runs ->
|
||||
pane = container.getRoot()
|
||||
paneModel = pane.model
|
||||
paneModel.addItems([view1, editor1, view2, editor2])
|
||||
|
||||
afterEach ->
|
||||
atom.deserializers.remove(TestView)
|
||||
@@ -159,14 +164,21 @@ describe "PaneView", ->
|
||||
|
||||
describe "when an unmodifed buffer's path is deleted", ->
|
||||
it "removes the pane item", ->
|
||||
editor = null
|
||||
jasmine.unspy(window, 'setTimeout')
|
||||
filePath = temp.openSync('atom').path
|
||||
editor = atom.project.openSync(filePath)
|
||||
pane.activateItem(editor)
|
||||
expect(pane.items).toHaveLength(5)
|
||||
filePath = path.join(temp.mkdirSync(), 'file.txt')
|
||||
fs.writeFileSync(filePath, '')
|
||||
|
||||
fs.removeSync(filePath)
|
||||
waitsFor -> pane.items.length == 4
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(filePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
pane.activateItem(editor)
|
||||
expect(pane.items).toHaveLength(5)
|
||||
fs.removeSync(filePath)
|
||||
|
||||
waitsFor ->
|
||||
pane.items.length == 4
|
||||
|
||||
describe "when a pane is destroyed", ->
|
||||
[pane2, pane2Model] = []
|
||||
|
||||
+76
-75
@@ -18,62 +18,39 @@ describe "Project", ->
|
||||
deserializedProject?.destroy()
|
||||
|
||||
it "does not include unretained buffers in the serialized state", ->
|
||||
atom.project.bufferForPathSync('a')
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
waitsForPromise ->
|
||||
atom.project.bufferForPath('a')
|
||||
|
||||
deserializedProject = atom.project.testSerialization()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
runs ->
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
deserializedProject = atom.project.testSerialization()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
|
||||
it "listens for destroyed events on deserialized buffers and removes them when they are destroyed", ->
|
||||
atom.project.openSync('a')
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
deserializedProject = atom.project.testSerialization()
|
||||
waitsForPromise ->
|
||||
atom.project.open('a')
|
||||
|
||||
expect(deserializedProject.getBuffers().length).toBe 1
|
||||
deserializedProject.getBuffers()[0].destroy()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
runs ->
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
deserializedProject = atom.project.testSerialization()
|
||||
|
||||
expect(deserializedProject.getBuffers().length).toBe 1
|
||||
deserializedProject.getBuffers()[0].destroy()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
|
||||
describe "when an editor is saved and the project has no path", ->
|
||||
it "sets the project's path to the saved file's parent directory", ->
|
||||
tempFile = temp.openSync().path
|
||||
atom.project.setPath(undefined)
|
||||
expect(atom.project.getPath()).toBeUndefined()
|
||||
editor = atom.project.openSync()
|
||||
editor.saveAs(tempFile)
|
||||
expect(atom.project.getPath()).toBe path.dirname(tempFile)
|
||||
editor = null
|
||||
|
||||
describe ".openSync(path)", ->
|
||||
[absolutePath, newBufferHandler] = []
|
||||
beforeEach ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
newBufferHandler = jasmine.createSpy('newBufferHandler')
|
||||
atom.project.on 'buffer-created', newBufferHandler
|
||||
waitsForPromise ->
|
||||
atom.project.open().then (o) -> editor = o
|
||||
|
||||
describe "when given an absolute path that hasn't been opened previously", ->
|
||||
it "returns a new edit session for the given path and emits 'buffer-created'", ->
|
||||
editor = atom.project.openSync(absolutePath)
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
|
||||
describe "when given a relative path that hasn't been opened previously", ->
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created'", ->
|
||||
editor = atom.project.openSync('a')
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
|
||||
describe "when passed the path to a buffer that has already been opened", ->
|
||||
it "returns a new edit session containing previously opened buffer", ->
|
||||
editor = atom.project.openSync(absolutePath)
|
||||
newBufferHandler.reset()
|
||||
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
|
||||
expect(atom.project.openSync('a').buffer).toBe editor.buffer
|
||||
expect(newBufferHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when not passed a path", ->
|
||||
it "returns a new edit session and emits 'buffer-created'", ->
|
||||
editor = atom.project.openSync()
|
||||
expect(editor.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
|
||||
runs ->
|
||||
editor.saveAs(tempFile)
|
||||
expect(atom.project.getPath()).toBe path.dirname(tempFile)
|
||||
|
||||
describe ".open(path)", ->
|
||||
[absolutePath, newBufferHandler] = []
|
||||
@@ -106,14 +83,21 @@ describe "Project", ->
|
||||
describe "when passed the path to a buffer that is currently opened", ->
|
||||
it "returns a new edit session containing currently opened buffer", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
newBufferHandler.reset()
|
||||
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
|
||||
expect(atom.project.openSync('a').buffer).toBe editor.buffer
|
||||
expect(newBufferHandler).not.toHaveBeenCalled()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(absolutePath).then ({buffer}) ->
|
||||
expect(buffer).toBe editor.buffer
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('a').then ({buffer}) ->
|
||||
expect(buffer).toBe editor.buffer
|
||||
expect(newBufferHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when not passed a path", ->
|
||||
it "returns a new edit session and emits 'buffer-created'", ->
|
||||
@@ -137,20 +121,6 @@ describe "Project", ->
|
||||
runs ->
|
||||
expect(totalBytes).toBe fs.statSync(filePath).size
|
||||
|
||||
describe ".bufferForPathSync(path)", ->
|
||||
describe "when opening a previously opened path", ->
|
||||
it "does not create a new buffer", ->
|
||||
buffer = atom.project.bufferForPathSync("a").retain()
|
||||
expect(atom.project.bufferForPathSync("a")).toBe buffer
|
||||
|
||||
alternativeBuffer = atom.project.bufferForPathSync("b").retain().release()
|
||||
expect(alternativeBuffer).not.toBe buffer
|
||||
buffer.release()
|
||||
|
||||
it "creates a new buffer if the previous buffer was destroyed", ->
|
||||
buffer = atom.project.bufferForPathSync("a").retain().release()
|
||||
expect(atom.project.bufferForPathSync("a").retain().release()).not.toBe buffer
|
||||
|
||||
describe ".bufferForPath(path)", ->
|
||||
[buffer] = []
|
||||
beforeEach ->
|
||||
@@ -186,11 +156,20 @@ describe "Project", ->
|
||||
expect(atom.project.resolve('a')).toBe absolutePath
|
||||
expect(atom.project.resolve(absolutePath + '/../a')).toBe absolutePath
|
||||
expect(atom.project.resolve('a/../a')).toBe absolutePath
|
||||
expect(atom.project.resolve()).toBeUndefined()
|
||||
|
||||
describe "when passed a uri with a scheme", ->
|
||||
it "does not modify uris that begin with a scheme", ->
|
||||
expect(atom.project.resolve('http://zombo.com')).toBe 'http://zombo.com'
|
||||
|
||||
describe "when the project has no path", ->
|
||||
it "returns undefined for relative URIs", ->
|
||||
atom.project.setPath()
|
||||
expect(atom.project.resolve('test.txt')).toBeUndefined()
|
||||
expect(atom.project.resolve('http://github.com')).toBe 'http://github.com'
|
||||
absolutePath = fs.absolute(__dirname)
|
||||
expect(atom.project.resolve(absolutePath)).toBe absolutePath
|
||||
|
||||
describe ".setPath(path)", ->
|
||||
describe "when path is a file", ->
|
||||
it "sets its path to the files parent directory and updates the root directory", ->
|
||||
@@ -240,10 +219,15 @@ describe "Project", ->
|
||||
|
||||
describe "when a buffer is already open", ->
|
||||
it "replaces properly and saves when not modified", ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
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)
|
||||
@@ -256,10 +240,12 @@ describe "Project", ->
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
it "does not replace when the path is not specified", ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor = atom.project.openSync('sample-with-comments.js')
|
||||
|
||||
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)
|
||||
@@ -269,11 +255,16 @@ describe "Project", ->
|
||||
expect(results[0].filePath).toBe commentFilePath
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
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)
|
||||
@@ -437,9 +428,14 @@ describe "Project", ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editor = atom.project.openSync("a")
|
||||
editor.setText("Elephant")
|
||||
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
|
||||
|
||||
@@ -450,9 +446,14 @@ describe "Project", ->
|
||||
expect(resultForA.matches[0].matchText).toBe 'Elephant'
|
||||
|
||||
it "ignores buffers outside the project", ->
|
||||
editor = atom.project.openSync(temp.openSync().path)
|
||||
editor.setText("Elephant")
|
||||
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
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ describe "Selection", ->
|
||||
|
||||
describe "when only the selection's tail is moved (regression)", ->
|
||||
it "emits the 'screen-range-changed' event", ->
|
||||
selection.setBufferRange([[2, 0], [2, 10]], isReversed: true)
|
||||
selection.setBufferRange([[2, 0], [2, 10]], reversed: true)
|
||||
changeScreenRangeHandler = jasmine.createSpy('changeScreenRangeHandler')
|
||||
selection.on 'screen-range-changed', changeScreenRangeHandler
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ try
|
||||
|
||||
{runSpecSuite} = require './jasmine-helper'
|
||||
|
||||
# Add 'src/exports' to module search path.
|
||||
exportsPath = path.resolve(atom.getLoadSettings().resourcePath, 'exports')
|
||||
# Add 'exports' to module search path.
|
||||
exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports')
|
||||
require('module').globalPaths.push(exportsPath)
|
||||
# Still set NODE_PATH since tasks may need it.
|
||||
process.env.NODE_PATH = exportsPath
|
||||
|
||||
@@ -6,6 +6,7 @@ require '../vendor/jasmine-jquery'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
Grim = require 'grim'
|
||||
KeymapManager = require '../src/keymap-extensions'
|
||||
{$, WorkspaceView, Workspace} = require 'atom'
|
||||
Config = require '../src/config'
|
||||
@@ -37,6 +38,7 @@ jasmine.getEnv().defaultTimeoutInterval = 5000
|
||||
specPackageName = null
|
||||
specPackagePath = null
|
||||
specProjectPath = null
|
||||
isCoreSpec = false
|
||||
|
||||
{specDirectory, resourcePath} = atom.getLoadSettings()
|
||||
|
||||
@@ -46,7 +48,10 @@ if specDirectory
|
||||
specPackageName = JSON.parse(fs.readFileSync(path.join(specPackagePath, 'package.json')))?.name
|
||||
specProjectPath = path.join(specDirectory, 'fixtures')
|
||||
|
||||
isCoreSpec = specDirectory == fs.realpathSync(__dirname)
|
||||
|
||||
beforeEach ->
|
||||
Grim.clearDeprecations() if isCoreSpec
|
||||
$.fx.off = true
|
||||
projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures')
|
||||
atom.project = new Project(path: projectPath)
|
||||
@@ -124,6 +129,7 @@ afterEach ->
|
||||
jasmine.unspy(atom, 'saveSync')
|
||||
ensureNoPathSubscriptions()
|
||||
atom.syntax.off()
|
||||
ensureNoDeprecatedFunctionsCalled() if isCoreSpec
|
||||
waits(0) # yield to ui thread to make screen update more frequently
|
||||
|
||||
ensureNoPathSubscriptions = ->
|
||||
@@ -132,6 +138,27 @@ ensureNoPathSubscriptions = ->
|
||||
if watchedPaths.length > 0
|
||||
throw new Error("Leaking subscriptions for paths: " + watchedPaths.join(", "))
|
||||
|
||||
ensureNoDeprecatedFunctionsCalled = ->
|
||||
deprecations = Grim.getDeprecations()
|
||||
if deprecations.length > 0
|
||||
originalPrepareStackTrace = Error.prepareStackTrace
|
||||
Error.prepareStackTrace = (error, stack) ->
|
||||
output = []
|
||||
for deprecation in deprecations
|
||||
output.push "#{deprecation.originName} is deprecated. #{deprecation.message}"
|
||||
output.push _.multiplyString("-", output[output.length - 1].length)
|
||||
for stack in deprecation.getStacks()
|
||||
for {functionName, location} in stack
|
||||
output.push "#{functionName} -- #{location}"
|
||||
output.push ""
|
||||
output.join("\n")
|
||||
|
||||
error = new Error("Deprecated function(s) #{deprecations.map(({originName}) -> originName).join ', '}) were called.")
|
||||
error.stack
|
||||
Error.prepareStackTrace = originalPrepareStackTrace
|
||||
|
||||
throw error
|
||||
|
||||
emitObject = jasmine.StringPrettyPrinter.prototype.emitObject
|
||||
jasmine.StringPrettyPrinter.prototype.emitObject = (obj) ->
|
||||
if obj.inspect
|
||||
@@ -234,7 +261,9 @@ window.waitsForPromise = (args...) ->
|
||||
window.resetTimeouts = ->
|
||||
window.now = 0
|
||||
window.timeoutCount = 0
|
||||
window.intervalCount = 0
|
||||
window.timeouts = []
|
||||
window.intervalTimeouts = {}
|
||||
|
||||
window.fakeSetTimeout = (callback, ms) ->
|
||||
id = ++window.timeoutCount
|
||||
@@ -245,13 +274,15 @@ window.fakeClearTimeout = (idToClear) ->
|
||||
window.timeouts = window.timeouts.filter ([id]) -> id != idToClear
|
||||
|
||||
window.fakeSetInterval = (callback, ms) ->
|
||||
id = ++window.intervalCount
|
||||
action = ->
|
||||
callback()
|
||||
window.fakeSetTimeout(action, ms)
|
||||
window.fakeSetTimeout(action, ms)
|
||||
window.intervalTimeouts[id] = window.fakeSetTimeout(action, ms)
|
||||
window.intervalTimeouts[id] = window.fakeSetTimeout(action, ms)
|
||||
id
|
||||
|
||||
window.fakeClearInterval = (idToClear) ->
|
||||
window.fakeClearTimeout(idToClear)
|
||||
window.fakeClearTimeout(@intervalTimeouts[idToClear])
|
||||
|
||||
window.advanceClock = (delta=1) ->
|
||||
window.now += delta
|
||||
@@ -289,7 +320,11 @@ $.fn.resultOfTrigger = (type) ->
|
||||
event.result
|
||||
|
||||
$.fn.enableKeymap = ->
|
||||
@on 'keydown', (e) => atom.keymaps.handleKeyEvent(e)
|
||||
@on 'keydown', (e) ->
|
||||
originalEvent = e.originalEvent ? e
|
||||
Object.defineProperty(originalEvent, 'target', get: -> e.target) unless originalEvent.target?
|
||||
atom.keymaps.handleKeyboardEvent(originalEvent)
|
||||
not e.originalEvent.defaultPrevented
|
||||
|
||||
$.fn.attachToDom = ->
|
||||
@appendTo($('#jasmine-content'))
|
||||
|
||||
@@ -27,10 +27,8 @@ setSpecDirectory = (specDirectory) ->
|
||||
runAllSpecs = ->
|
||||
{resourcePath} = atom.getLoadSettings()
|
||||
|
||||
# Only run core specs when resource path is the Atom repository
|
||||
if Git.exists(resourcePath)
|
||||
requireSpecs(path.join(resourcePath, 'spec'))
|
||||
setSpecType('core')
|
||||
requireSpecs(path.join(resourcePath, 'spec'))
|
||||
setSpecType('core')
|
||||
|
||||
fixturesPackagesPath = path.join(__dirname, 'fixtures', 'packages')
|
||||
packagePaths = atom.packages.getAvailablePackageNames().map (packageName) ->
|
||||
|
||||
@@ -20,7 +20,7 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "theme getters and setters", ->
|
||||
beforeEach ->
|
||||
atom.packages.loadPackages(sync: true)
|
||||
atom.packages.loadPackages()
|
||||
|
||||
it 'getLoadedThemes get all the loaded themes', ->
|
||||
themes = themeManager.getLoadedThemes()
|
||||
@@ -131,15 +131,21 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "requireStylesheet(path)", ->
|
||||
it "synchronously loads css at the given path and installs a style tag for it in the head", ->
|
||||
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
|
||||
themeManager.on 'stylesheet-added', stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler")
|
||||
cssPath = atom.project.resolve('css.css')
|
||||
lengthBefore = $('head style').length
|
||||
|
||||
themeManager.requireStylesheet(cssPath)
|
||||
expect($('head style').length).toBe lengthBefore + 1
|
||||
|
||||
expect(stylesheetAddedHandler).toHaveBeenCalled()
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
element = $('head style[id*="css.css"]')
|
||||
expect(element.attr('id')).toBe themeManager.stringToId(cssPath)
|
||||
expect(element.text()).toBe fs.readFileSync(cssPath, 'utf8')
|
||||
expect(element[0].sheet).toBe stylesheetAddedHandler.argsForCall[0][0]
|
||||
|
||||
# doesn't append twice
|
||||
themeManager.requireStylesheet(cssPath)
|
||||
@@ -187,9 +193,18 @@ describe "ThemeManager", ->
|
||||
themeManager.requireStylesheet(cssPath)
|
||||
expect($(document.body).css('font-weight')).toBe("bold")
|
||||
|
||||
themeManager.on 'stylesheet-removed', stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler")
|
||||
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
|
||||
|
||||
themeManager.removeStylesheet(cssPath)
|
||||
|
||||
expect($(document.body).css('font-weight')).not.toBe("bold")
|
||||
|
||||
expect(stylesheetRemovedHandler).toHaveBeenCalled()
|
||||
stylesheet = stylesheetRemovedHandler.argsForCall[0][0]
|
||||
expect(stylesheet instanceof CSSStyleSheet).toBe true
|
||||
expect(stylesheet.cssRules[0].selectorText).toBe 'body'
|
||||
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
@@ -219,20 +234,21 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
it "reloads it", ->
|
||||
[stylesheetRemovedHandler, stylesheetAddedHandler, stylesheetsChangedHandler] = []
|
||||
userStylesheetPath = path.join(temp.mkdirSync("atom"), 'styles.less')
|
||||
fs.writeFileSync(userStylesheetPath, 'body {border-style: dotted !important;}')
|
||||
|
||||
spyOn(themeManager, 'getUserStylesheetPath').andReturn userStylesheetPath
|
||||
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
expect($(document.body).css('border-style')).toBe 'dotted'
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
stylesheetsChangedHandler.reset()
|
||||
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
|
||||
themeManager.on 'stylesheet-removed', stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler")
|
||||
themeManager.on 'stylesheet-added', stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler")
|
||||
spyOn(themeManager, 'loadUserStylesheet').andCallThrough()
|
||||
|
||||
expect($(document.body).css('border-style')).toBe 'dotted'
|
||||
fs.writeFileSync(userStylesheetPath, 'body {border-style: dashed}')
|
||||
|
||||
waitsFor ->
|
||||
@@ -240,7 +256,16 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
expect($(document.body).css('border-style')).toBe 'dashed'
|
||||
|
||||
expect(stylesheetRemovedHandler).toHaveBeenCalled()
|
||||
expect(stylesheetRemovedHandler.argsForCall[0][0].cssRules[0].style.border).toBe 'dotted'
|
||||
|
||||
expect(stylesheetAddedHandler).toHaveBeenCalled()
|
||||
expect(stylesheetAddedHandler.argsForCall[0][0].cssRules[0].style.border).toBe 'dashed'
|
||||
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
stylesheetRemovedHandler.reset()
|
||||
stylesheetsChangedHandler.reset()
|
||||
fs.removeSync(userStylesheetPath)
|
||||
|
||||
@@ -248,16 +273,25 @@ describe "ThemeManager", ->
|
||||
themeManager.loadUserStylesheet.callCount is 2
|
||||
|
||||
runs ->
|
||||
expect(stylesheetRemovedHandler).toHaveBeenCalled()
|
||||
expect(stylesheetRemovedHandler.argsForCall[0][0].cssRules[0].style.border).toBe 'dashed'
|
||||
expect($(document.body).css('border-style')).toBe 'none'
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a non-existent theme is present in the config", ->
|
||||
it "logs a warning but does not throw an exception (regression)", ->
|
||||
reloaded = false
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
themeManager.once 'reloaded', -> reloaded = true
|
||||
spyOn(console, 'warn')
|
||||
expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow()
|
||||
|
||||
waitsFor -> reloaded
|
||||
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
|
||||
|
||||
@@ -385,7 +385,58 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokens[1].value).toBeTruthy()
|
||||
expect(tokens[2].value).toBe 'xyz'
|
||||
|
||||
describe "when the grammar is tokenized", ->
|
||||
it "emits the `tokenized` event", ->
|
||||
editor = null
|
||||
tokenizedHandler = jasmine.createSpy("tokenized handler")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
tokenizedBuffer = editor.displayBuffer.tokenizedBuffer
|
||||
tokenizedBuffer.on 'tokenized', tokenizedHandler
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
expect(tokenizedHandler.callCount).toBe(1)
|
||||
|
||||
it "doesn't re-emit the `tokenized` event when it is re-tokenized", ->
|
||||
editor = null
|
||||
tokenizedHandler = jasmine.createSpy("tokenized handler")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
tokenizedBuffer = editor.displayBuffer.tokenizedBuffer
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
tokenizedBuffer.on 'tokenized', tokenizedHandler
|
||||
editor.getBuffer().insert([0, 0], "'")
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
expect(tokenizedHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when the grammar is updated because a grammar it includes is activated", ->
|
||||
it "re-emits the `tokenized` event", ->
|
||||
editor = null
|
||||
tokenizedBuffer = null
|
||||
tokenizedHandler = jasmine.createSpy("tokenized handler")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('coffee.coffee').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
tokenizedBuffer = editor.displayBuffer.tokenizedBuffer
|
||||
tokenizedBuffer.on 'tokenized', tokenizedHandler
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
tokenizedHandler.reset()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-coffee-script')
|
||||
|
||||
runs ->
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
expect(tokenizedHandler.callCount).toBe(1)
|
||||
|
||||
it "retokenizes the buffer", ->
|
||||
|
||||
waitsForPromise ->
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "TokenizedLine", ->
|
||||
|
||||
describe "::getScopeTree()", ->
|
||||
it "returns a tree whose inner nodes are scopes and whose leaf nodes are tokens in those scopes", ->
|
||||
editor = atom.project.openSync('coffee.coffee')
|
||||
[tokens, tokenIndex] = []
|
||||
|
||||
ensureValidScopeTree = (scopeTree, scopes=[]) ->
|
||||
if scopeTree.children?
|
||||
@@ -16,7 +16,11 @@ describe "TokenizedLine", ->
|
||||
expect(scopeTree).toBe tokens[tokenIndex++]
|
||||
expect(scopes).toEqual scopeTree.scopes
|
||||
|
||||
tokenIndex = 0
|
||||
tokens = editor.lineForScreenRow(1).tokens
|
||||
scopeTree = editor.lineForScreenRow(1).getScopeTree()
|
||||
ensureValidScopeTree(scopeTree)
|
||||
waitsForPromise ->
|
||||
atom.project.open('coffee.coffee').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
tokenIndex = 0
|
||||
tokens = editor.lineForScreenRow(1).tokens
|
||||
scopeTree = editor.lineForScreenRow(1).getScopeTree()
|
||||
ensureValidScopeTree(scopeTree)
|
||||
|
||||
+37
-20
@@ -64,27 +64,41 @@ describe "Window", ->
|
||||
|
||||
describe "when pane items are are modified", ->
|
||||
it "prompts user to save and and calls workspaceView.confirmClose", ->
|
||||
editor = null
|
||||
spyOn(atom.workspaceView, 'confirmClose').andCallThrough()
|
||||
spyOn(atom, "confirm").andReturn(2)
|
||||
editor = atom.workspaceView.openSync("sample.js")
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.workspaceView.confirmClose).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open("sample.js").then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.workspaceView.confirmClose).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
it "prompts user to save and handler returns true if don't save", ->
|
||||
editor = null
|
||||
spyOn(atom, "confirm").andReturn(2)
|
||||
editor = atom.workspaceView.openSync("sample.js")
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open("sample.js").then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
it "prompts user to save and handler returns false if dialog is canceled", ->
|
||||
editor = null
|
||||
spyOn(atom, "confirm").andReturn(1)
|
||||
editor = atom.workspaceView.openSync("sample.js")
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open("sample.js").then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
describe ".unloadEditorWindow()", ->
|
||||
it "saves the serialized state of the window so it can be deserialized after reload", ->
|
||||
@@ -100,15 +114,18 @@ describe "Window", ->
|
||||
expect(atom.saveSync).toHaveBeenCalled()
|
||||
|
||||
it "unsubscribes from all buffers", ->
|
||||
atom.workspaceView.openSync('sample.js')
|
||||
buffer = atom.workspaceView.getActivePaneItem().buffer
|
||||
pane = atom.workspaceView.getActivePaneView()
|
||||
pane.splitRight(pane.copyActiveItem())
|
||||
expect(atom.workspaceView.find('.editor').length).toBe 2
|
||||
waitsForPromise ->
|
||||
atom.workspace.open("sample.js")
|
||||
|
||||
atom.unloadEditorWindow()
|
||||
runs ->
|
||||
buffer = atom.workspace.getActivePaneItem().buffer
|
||||
pane = atom.workspaceView.getActivePaneView()
|
||||
pane.splitRight(pane.copyActiveItem())
|
||||
expect(atom.workspaceView.find('.editor').length).toBe 2
|
||||
|
||||
expect(buffer.getSubscriptionCount()).toBe 0
|
||||
atom.unloadEditorWindow()
|
||||
|
||||
expect(buffer.getSubscriptionCount()).toBe 0
|
||||
|
||||
describe "drag and drop", ->
|
||||
buildDragEvent = (type, files) ->
|
||||
|
||||
+109
-80
@@ -37,12 +37,17 @@ describe "Workspace", ->
|
||||
describe "when called with a uri", ->
|
||||
describe "when the active pane already has an editor for the given uri", ->
|
||||
it "activates the existing editor on the active pane", ->
|
||||
editor1 = workspace.openSync('a')
|
||||
editor2 = workspace.openSync('b')
|
||||
|
||||
editor = null
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.open('a').then (o) -> editor = o
|
||||
workspace.open('a').then (o) ->
|
||||
editor1 = o
|
||||
workspace.open('b').then (o) ->
|
||||
editor2 = o
|
||||
workspace.open('a').then (o) ->
|
||||
editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor).toBe editor1
|
||||
@@ -64,11 +69,21 @@ describe "Workspace", ->
|
||||
describe "when the 'searchAllPanes' option is true", ->
|
||||
describe "when an editor for the given uri is already open on an inactive pane", ->
|
||||
it "activates the existing editor on the inactive pane, then activates that pane", ->
|
||||
editor1 = workspace.openSync('a')
|
||||
pane1 = workspace.activePane
|
||||
pane2 = workspace.activePane.splitRight()
|
||||
editor2 = workspace.openSync('b')
|
||||
expect(workspace.activePaneItem).toBe editor2
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
pane1 = workspace.getActivePane()
|
||||
pane2 = workspace.getActivePane().splitRight()
|
||||
|
||||
waitsForPromise ->
|
||||
pane1.activate()
|
||||
workspace.open('a').then (o) -> editor1 = o
|
||||
|
||||
waitsForPromise ->
|
||||
pane2.activate()
|
||||
workspace.open('b').then (o) -> editor2 = o
|
||||
|
||||
runs ->
|
||||
expect(workspace.activePaneItem).toBe editor2
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.open('a', searchAllPanes: true)
|
||||
@@ -112,6 +127,22 @@ describe "Workspace", ->
|
||||
expect(pane1.items).toEqual [editor]
|
||||
expect(pane2.items).toEqual []
|
||||
|
||||
describe "when a pane axis is the leftmost sibling of the current pane", ->
|
||||
it "opens the new item in the current pane", ->
|
||||
editor = null
|
||||
pane1 = workspace.activePane
|
||||
pane2 = pane1.splitLeft()
|
||||
pane3 = pane2.splitDown()
|
||||
pane1.activate()
|
||||
expect(workspace.activePane).toBe pane1
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.open('a', split: 'left').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(workspace.activePane).toBe pane1
|
||||
expect(pane1.items).toEqual [editor]
|
||||
|
||||
describe "when the 'split' option is 'right'", ->
|
||||
it "opens the editor in the rightmost pane of the current pane axis", ->
|
||||
editor = null
|
||||
@@ -136,6 +167,26 @@ describe "Workspace", ->
|
||||
expect(pane1.items).toEqual []
|
||||
expect(pane2.items).toEqual [editor]
|
||||
|
||||
describe "when a pane axis is the rightmost sibling of the current pane", ->
|
||||
it "opens the new item in a new pane split to the right of the current pane", ->
|
||||
editor = null
|
||||
pane1 = workspace.activePane
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitDown()
|
||||
pane1.activate()
|
||||
expect(workspace.activePane).toBe pane1
|
||||
pane4 = null
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.open('a', split: 'right').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
pane4 = workspace.getPanes().filter((p) -> p != pane1)[0]
|
||||
expect(workspace.activePane).toBe pane4
|
||||
expect(pane4.items).toEqual [editor]
|
||||
expect(workspace.paneContainer.root.children[0]).toBe pane1
|
||||
expect(workspace.paneContainer.root.children[1]).toBe pane4
|
||||
|
||||
describe "when passed a path that matches a custom opener", ->
|
||||
it "returns the resource returned by the custom opener", ->
|
||||
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
|
||||
@@ -164,80 +215,55 @@ describe "Workspace", ->
|
||||
runs ->
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "::openSync(uri, options)", ->
|
||||
[activePane, initialItemCount] = []
|
||||
|
||||
beforeEach ->
|
||||
activePane = workspace.activePane
|
||||
spyOn(activePane, 'activate')
|
||||
initialItemCount = activePane.items.length
|
||||
|
||||
describe "when called without a uri", ->
|
||||
it "adds and activates an empty editor on the active pane", ->
|
||||
editor = workspace.openSync()
|
||||
expect(activePane.items.length).toBe initialItemCount + 1
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(editor.getPath()).toBeUndefined()
|
||||
expect(activePane.activate).toHaveBeenCalled()
|
||||
|
||||
describe "when called with a uri", ->
|
||||
describe "when the active pane already has an editor for the given uri", ->
|
||||
it "activates the existing editor on the active pane", ->
|
||||
editor1 = workspace.openSync('a')
|
||||
editor2 = workspace.openSync('b')
|
||||
expect(activePane.activeItem).toBe editor2
|
||||
expect(activePane.items.length).toBe 2
|
||||
|
||||
editor = workspace.openSync(editor1.getPath())
|
||||
expect(editor).toBe editor1
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(activePane.activate).toHaveBeenCalled()
|
||||
expect(activePane.items.length).toBe 2
|
||||
|
||||
describe "when the active pane does not have an editor for the given uri", ->
|
||||
it "adds and activates a new editor for the given path on the active pane", ->
|
||||
editor = workspace.openSync('a')
|
||||
expect(activePane.items.length).toBe 1
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(activePane.activate).toHaveBeenCalled()
|
||||
|
||||
describe "when the 'activatePane' option is false", ->
|
||||
it "does not activate the active pane", ->
|
||||
workspace.openSync('b', activatePane: false)
|
||||
expect(activePane.activate).not.toHaveBeenCalled()
|
||||
|
||||
describe "::reopenItemSync()", ->
|
||||
describe "::reopenItem()", ->
|
||||
it "opens the uri associated with the last closed pane that isn't currently open", ->
|
||||
pane = workspace.activePane
|
||||
workspace.openSync('a')
|
||||
workspace.openSync('b')
|
||||
workspace.openSync('file1')
|
||||
workspace.openSync()
|
||||
waitsForPromise ->
|
||||
workspace.open('a').then ->
|
||||
workspace.open('b').then ->
|
||||
workspace.open('file1').then ->
|
||||
workspace.open()
|
||||
|
||||
# does not reopen items with no uri
|
||||
expect(workspace.activePaneItem.getUri()).toBeUndefined()
|
||||
pane.destroyActiveItem()
|
||||
workspace.reopenItemSync()
|
||||
expect(workspace.activePaneItem.getUri()).not.toBeUndefined()
|
||||
runs ->
|
||||
# does not reopen items with no uri
|
||||
expect(workspace.activePaneItem.getUri()).toBeUndefined()
|
||||
pane.destroyActiveItem()
|
||||
|
||||
# destroy all items
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
|
||||
pane.destroyActiveItem()
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
|
||||
pane.destroyActiveItem()
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
|
||||
pane.destroyActiveItem()
|
||||
waitsForPromise ->
|
||||
workspace.reopenItem()
|
||||
|
||||
# reopens items with uris
|
||||
expect(workspace.activePaneItem).toBeUndefined()
|
||||
workspace.reopenItemSync()
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
|
||||
runs ->
|
||||
expect(workspace.activePaneItem.getUri()).not.toBeUndefined()
|
||||
|
||||
# destroy all items
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
|
||||
pane.destroyActiveItem()
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
|
||||
pane.destroyActiveItem()
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
|
||||
pane.destroyActiveItem()
|
||||
|
||||
# reopens items with uris
|
||||
expect(workspace.activePaneItem).toBeUndefined()
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.reopenItem()
|
||||
|
||||
runs ->
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
|
||||
|
||||
# does not reopen items that are already open
|
||||
workspace.openSync('b')
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
|
||||
workspace.reopenItemSync()
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
|
||||
waitsForPromise ->
|
||||
workspace.open('b')
|
||||
|
||||
runs ->
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.reopenItem()
|
||||
|
||||
runs ->
|
||||
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
|
||||
|
||||
describe "::increase/decreaseFontSize()", ->
|
||||
it "increases/decreases the font size without going below 1", ->
|
||||
@@ -272,11 +298,14 @@ describe "Workspace", ->
|
||||
|
||||
describe "when an editor is copied", ->
|
||||
it "emits an 'editor-created' event", ->
|
||||
editor = null
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
workspace.on 'editor-created', handler
|
||||
|
||||
editor1 = workspace.openSync("a")
|
||||
expect(handler.callCount).toBe 1
|
||||
waitsForPromise ->
|
||||
workspace.open("a").then (o) -> editor = o
|
||||
|
||||
editor2 = editor1.copy()
|
||||
expect(handler.callCount).toBe 2
|
||||
runs ->
|
||||
expect(handler.callCount).toBe 1
|
||||
editorCopy = editor.copy()
|
||||
expect(handler.callCount).toBe 2
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Q = require 'q'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
EditorView = require '../src/editor-view'
|
||||
PaneView = require '../src/pane-view'
|
||||
Workspace = require '../src/workspace'
|
||||
|
||||
@@ -14,9 +15,12 @@ describe "WorkspaceView", ->
|
||||
atom.workspace = new Workspace
|
||||
atom.workspaceView = new WorkspaceView(atom.workspace)
|
||||
atom.workspaceView.enableKeymap()
|
||||
atom.workspaceView.openSync(pathToOpen)
|
||||
atom.workspaceView.focus()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(pathToOpen)
|
||||
|
||||
|
||||
describe "@deserialize()", ->
|
||||
viewState = null
|
||||
|
||||
@@ -32,17 +36,21 @@ describe "WorkspaceView", ->
|
||||
describe "when the serialized WorkspaceView has an unsaved buffer", ->
|
||||
it "constructs the view with the same panes", ->
|
||||
atom.workspaceView.attachToDom()
|
||||
atom.workspaceView.openSync()
|
||||
editorView1 = atom.workspaceView.getActiveView()
|
||||
buffer = editorView1.getEditor().getBuffer()
|
||||
editorView1.splitRight()
|
||||
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
|
||||
simulateReload()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open()
|
||||
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 2
|
||||
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
expect(atom.workspaceView.title).toBe "untitled - #{atom.project.getPath()}"
|
||||
runs ->
|
||||
editorView1 = atom.workspaceView.getActiveView()
|
||||
buffer = editorView1.getEditor().getBuffer()
|
||||
editorView1.splitRight()
|
||||
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
|
||||
simulateReload()
|
||||
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 2
|
||||
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
expect(atom.workspaceView.title).toBe "untitled - #{atom.project.getPath()}"
|
||||
|
||||
describe "when there are open editors", ->
|
||||
it "constructs the view with the same panes", ->
|
||||
@@ -50,42 +58,56 @@ describe "WorkspaceView", ->
|
||||
pane1 = atom.workspaceView.getActivePaneView()
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitRight()
|
||||
pane4 = pane2.splitDown()
|
||||
pane2.activateItem(atom.project.openSync('b'))
|
||||
pane3.activateItem(atom.project.openSync('../sample.js'))
|
||||
pane3.activeItem.setCursorScreenPosition([2, 4])
|
||||
pane4.activateItem(atom.project.openSync('../sample.txt'))
|
||||
pane4.activeItem.setCursorScreenPosition([0, 2])
|
||||
pane2.focus()
|
||||
pane4 = null
|
||||
|
||||
simulateReload()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('b').then (editor) ->
|
||||
pane2.activateItem(editor)
|
||||
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 4
|
||||
editorView1 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(0)').view()
|
||||
editorView3 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(1)').view()
|
||||
editorView2 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(0)').view()
|
||||
editorView4 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(1)').view()
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('../sample.js').then (editor) ->
|
||||
pane3.activateItem(editor)
|
||||
|
||||
expect(editorView1.getEditor().getPath()).toBe atom.project.resolve('a')
|
||||
expect(editorView2.getEditor().getPath()).toBe atom.project.resolve('b')
|
||||
expect(editorView3.getEditor().getPath()).toBe atom.project.resolve('../sample.js')
|
||||
expect(editorView3.getEditor().getCursorScreenPosition()).toEqual [2, 4]
|
||||
expect(editorView4.getEditor().getPath()).toBe atom.project.resolve('../sample.txt')
|
||||
expect(editorView4.getEditor().getCursorScreenPosition()).toEqual [0, 2]
|
||||
runs ->
|
||||
pane3.activeItem.setCursorScreenPosition([2, 4])
|
||||
pane4 = pane2.splitDown()
|
||||
|
||||
# ensure adjust pane dimensions is called
|
||||
expect(editorView1.width()).toBeGreaterThan 0
|
||||
expect(editorView2.width()).toBeGreaterThan 0
|
||||
expect(editorView3.width()).toBeGreaterThan 0
|
||||
expect(editorView4.width()).toBeGreaterThan 0
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('../sample.txt').then (editor) ->
|
||||
pane4.activateItem(editor)
|
||||
|
||||
# ensure correct editorView is focused again
|
||||
expect(editorView2.isFocused).toBeTruthy()
|
||||
expect(editorView1.isFocused).toBeFalsy()
|
||||
expect(editorView3.isFocused).toBeFalsy()
|
||||
expect(editorView4.isFocused).toBeFalsy()
|
||||
runs ->
|
||||
pane4.activeItem.setCursorScreenPosition([0, 2])
|
||||
pane2.focus()
|
||||
|
||||
expect(atom.workspaceView.title).toBe "#{path.basename(editorView2.getEditor().getPath())} - #{atom.project.getPath()}"
|
||||
simulateReload()
|
||||
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 4
|
||||
editorView1 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(0)').view()
|
||||
editorView3 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(1)').view()
|
||||
editorView2 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(0)').view()
|
||||
editorView4 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(1)').view()
|
||||
|
||||
expect(editorView1.getEditor().getPath()).toBe atom.project.resolve('a')
|
||||
expect(editorView2.getEditor().getPath()).toBe atom.project.resolve('b')
|
||||
expect(editorView3.getEditor().getPath()).toBe atom.project.resolve('../sample.js')
|
||||
expect(editorView3.getEditor().getCursorScreenPosition()).toEqual [2, 4]
|
||||
expect(editorView4.getEditor().getPath()).toBe atom.project.resolve('../sample.txt')
|
||||
expect(editorView4.getEditor().getCursorScreenPosition()).toEqual [0, 2]
|
||||
|
||||
# ensure adjust pane dimensions is called
|
||||
expect(editorView1.width()).toBeGreaterThan 0
|
||||
expect(editorView2.width()).toBeGreaterThan 0
|
||||
expect(editorView3.width()).toBeGreaterThan 0
|
||||
expect(editorView4.width()).toBeGreaterThan 0
|
||||
|
||||
# ensure correct editorView is focused again
|
||||
expect(editorView2).toHaveFocus()
|
||||
expect(editorView1).not.toHaveFocus()
|
||||
expect(editorView3).not.toHaveFocus()
|
||||
expect(editorView4).not.toHaveFocus()
|
||||
|
||||
expect(atom.workspaceView.title).toBe "#{path.basename(editorView2.getEditor().getPath())} - #{atom.project.getPath()}"
|
||||
|
||||
describe "where there are no open editors", ->
|
||||
it "constructs the view with no open editors", ->
|
||||
@@ -101,9 +123,9 @@ describe "WorkspaceView", ->
|
||||
it "hands off focus to the active pane", ->
|
||||
activePane = atom.workspaceView.getActivePaneView()
|
||||
$('body').focus()
|
||||
expect(activePane.hasFocus()).toBe false
|
||||
expect(activePane).not.toHaveFocus()
|
||||
atom.workspaceView.focus()
|
||||
expect(activePane.hasFocus()).toBe true
|
||||
expect(activePane).toHaveFocus()
|
||||
|
||||
describe "keymap wiring", ->
|
||||
commandHandler = null
|
||||
@@ -111,7 +133,7 @@ describe "WorkspaceView", ->
|
||||
commandHandler = jasmine.createSpy('commandHandler')
|
||||
atom.workspaceView.on('foo-command', commandHandler)
|
||||
|
||||
atom.keymaps.bindKeys('name', '*', 'x': 'foo-command')
|
||||
atom.keymaps.add('name', '*': {'x': 'foo-command'})
|
||||
|
||||
describe "when a keydown event is triggered in the WorkspaceView", ->
|
||||
it "triggers matching keybindings for that event", ->
|
||||
@@ -128,7 +150,8 @@ describe "WorkspaceView", ->
|
||||
|
||||
describe "when the project has a path", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView.openSync('b')
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('b')
|
||||
|
||||
describe "when there is an active pane item", ->
|
||||
it "sets the title to the pane item's title plus the project path", ->
|
||||
@@ -143,7 +166,7 @@ describe "WorkspaceView", ->
|
||||
|
||||
describe "when the active pane's item changes", ->
|
||||
it "updates the title to the new item's title plus the project path", ->
|
||||
atom.workspaceView.getActivePaneView().showNextItem()
|
||||
atom.workspaceView.getActivePaneView().activateNextItem()
|
||||
item = atom.workspace.getActivePaneItem()
|
||||
expect(atom.workspaceView.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
@@ -158,7 +181,7 @@ describe "WorkspaceView", ->
|
||||
pane = atom.workspaceView.getActivePaneView()
|
||||
pane.splitRight()
|
||||
initialTitle = atom.workspaceView.title
|
||||
pane.showNextItem()
|
||||
pane.activateNextItem()
|
||||
expect(atom.workspaceView.title).toBe initialTitle
|
||||
|
||||
describe "when the root view is deserialized", ->
|
||||
@@ -222,6 +245,14 @@ describe "WorkspaceView", ->
|
||||
expect(count).toBe 1
|
||||
expect(callbackEditor).toBe atom.workspaceView.getActiveView()
|
||||
|
||||
it "does not invoke the callback for mini editors", ->
|
||||
editorViewCreatedHandler = jasmine.createSpy('editorViewCreatedHandler')
|
||||
atom.workspaceView.eachEditorView(editorViewCreatedHandler)
|
||||
editorViewCreatedHandler.reset()
|
||||
miniEditor = new EditorView(mini: true)
|
||||
atom.workspaceView.append(miniEditor)
|
||||
expect(editorViewCreatedHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "returns a subscription that can be disabled", ->
|
||||
count = 0
|
||||
callback = (editor) -> count++
|
||||
@@ -237,10 +268,22 @@ describe "WorkspaceView", ->
|
||||
describe "core:close", ->
|
||||
it "closes the active pane item until all that remains is a single empty pane", ->
|
||||
atom.config.set('core.destroyEmptyPanes', true)
|
||||
atom.project.openSync('../sample.txt')
|
||||
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 1
|
||||
|
||||
paneView1 = atom.workspaceView.getActivePaneView()
|
||||
editorView = atom.workspaceView.getActiveView()
|
||||
editorView.splitRight()
|
||||
paneView2 = atom.workspaceView.getActivePaneView()
|
||||
|
||||
expect(paneView1).not.toBe paneView2
|
||||
expect(atom.workspaceView.getPaneViews()).toHaveLength 2
|
||||
atom.workspaceView.trigger('core:close')
|
||||
|
||||
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 1
|
||||
expect(atom.workspaceView.getPaneViews()).toHaveLength 1
|
||||
atom.workspaceView.trigger('core:close')
|
||||
|
||||
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 0
|
||||
expect(atom.workspaceView.getPaneViews()).toHaveLength 1
|
||||
|
||||
describe "the scrollbar visibility class", ->
|
||||
it "has a class based on the style of the scrollbar", ->
|
||||
|
||||
+28
-25
@@ -24,7 +24,7 @@ WindowEventHandler = require './window-event-handler'
|
||||
# * `atom.config` - A {Config} instance
|
||||
# * `atom.contextMenu` - A {ContextMenuManager} instance
|
||||
# * `atom.deserializers` - A {DeserializerManager} instance
|
||||
# * `atom.keymaps` - A {Keymap} instance
|
||||
# * `atom.keymaps` - A {KeymapManager} instance
|
||||
# * `atom.menu` - A {MenuManager} instance
|
||||
# * `atom.packages` - A {PackageManager} instance
|
||||
# * `atom.project` - A {Project} instance
|
||||
@@ -38,8 +38,8 @@ class Atom extends Model
|
||||
|
||||
# Public: Load or create the Atom environment in the given mode.
|
||||
#
|
||||
# - mode: Pass 'editor' or 'spec' depending on the kind of environment you
|
||||
# want to build.
|
||||
# mode - Pass 'editor' or 'spec' depending on the kind of environment you
|
||||
# want to build.
|
||||
#
|
||||
# Returns an Atom instance, fully initialized
|
||||
@loadOrCreate: (mode) ->
|
||||
@@ -148,11 +148,11 @@ class Atom extends Model
|
||||
ThemeManager = require './theme-manager'
|
||||
ContextMenuManager = require './context-menu-manager'
|
||||
MenuManager = require './menu-manager'
|
||||
{devMode, resourcePath} = @getLoadSettings()
|
||||
{devMode, safeMode, resourcePath} = @getLoadSettings()
|
||||
configDirPath = @getConfigDirPath()
|
||||
|
||||
# Add 'src/exports' to module search path.
|
||||
exportsPath = path.resolve(resourcePath, 'exports')
|
||||
# Add 'exports' to module search path.
|
||||
exportsPath = path.join(resourcePath, 'exports')
|
||||
require('module').globalPaths.push(exportsPath)
|
||||
# Still set NODE_PATH since tasks may need it.
|
||||
process.env.NODE_PATH = exportsPath
|
||||
@@ -163,7 +163,7 @@ class Atom extends Model
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath})
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath})
|
||||
@contextMenu = new ContextMenuManager(devMode)
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@@ -212,11 +212,11 @@ class Atom extends Model
|
||||
# in the dimensions parameter. If x or y are omitted the window will be
|
||||
# centered. If height or width are omitted only the position will be changed.
|
||||
#
|
||||
# * dimensions:
|
||||
# + x: The new x coordinate.
|
||||
# + y: The new y coordinate.
|
||||
# + width: The new width.
|
||||
# + height: The new height.
|
||||
# dimensions - An {Object} with the following keys:
|
||||
# :x - The new x coordinate.
|
||||
# :y - The new y coordinate.
|
||||
# :width - The new width.
|
||||
# :height - The new height.
|
||||
setWindowDimensions: ({x, y, width, height}) ->
|
||||
if width? and height?
|
||||
@setSize(width, height)
|
||||
@@ -340,7 +340,7 @@ class Atom extends Model
|
||||
# options - An {Object} with the following keys:
|
||||
# :pathsToOpen - An {Array} of {String} paths to open.
|
||||
open: (options) ->
|
||||
ipc.sendChannel('open', options)
|
||||
ipc.send('open', options)
|
||||
|
||||
# Public: Open a confirm dialog.
|
||||
#
|
||||
@@ -394,50 +394,50 @@ class Atom extends Model
|
||||
|
||||
# Public: Open the dev tools for the current window.
|
||||
openDevTools: ->
|
||||
ipc.sendChannel('call-window-method', 'openDevTools')
|
||||
ipc.send('call-window-method', 'openDevTools')
|
||||
|
||||
# Public: Toggle the visibility of the dev tools for the current window.
|
||||
toggleDevTools: ->
|
||||
ipc.sendChannel('call-window-method', 'toggleDevTools')
|
||||
ipc.send('call-window-method', 'toggleDevTools')
|
||||
|
||||
# Public: Execute code in dev tools.
|
||||
executeJavaScriptInDevTools: (code) ->
|
||||
ipc.sendChannel('call-window-method', 'executeJavaScriptInDevTools', code)
|
||||
ipc.send('call-window-method', 'executeJavaScriptInDevTools', code)
|
||||
|
||||
# Public: Reload the current window.
|
||||
reload: ->
|
||||
ipc.sendChannel('call-window-method', 'restart')
|
||||
ipc.send('call-window-method', 'restart')
|
||||
|
||||
# Public: Focus the current window.
|
||||
focus: ->
|
||||
ipc.sendChannel('call-window-method', 'focus')
|
||||
ipc.send('call-window-method', 'focus')
|
||||
$(window).focus()
|
||||
|
||||
# Public: Show the current window.
|
||||
show: ->
|
||||
ipc.sendChannel('call-window-method', 'show')
|
||||
ipc.send('call-window-method', 'show')
|
||||
|
||||
# Public: Hide the current window.
|
||||
hide: ->
|
||||
ipc.sendChannel('call-window-method', 'hide')
|
||||
ipc.send('call-window-method', 'hide')
|
||||
|
||||
# Public: Set the size of current window.
|
||||
#
|
||||
# width - The {Number} of pixels.
|
||||
# height - The {Number} of pixels.
|
||||
setSize: (width, height) ->
|
||||
ipc.sendChannel('call-window-method', 'setSize', width, height)
|
||||
ipc.send('call-window-method', 'setSize', width, height)
|
||||
|
||||
# Public: Set the position of current window.
|
||||
#
|
||||
# x - The {Number} of pixels.
|
||||
# y - The {Number} of pixels.
|
||||
setPosition: (x, y) ->
|
||||
ipc.sendChannel('call-window-method', 'setPosition', x, y)
|
||||
ipc.send('call-window-method', 'setPosition', x, y)
|
||||
|
||||
# Public: Move current window to the center of the screen.
|
||||
center: ->
|
||||
ipc.sendChannel('call-window-method', 'center')
|
||||
ipc.send('call-window-method', 'center')
|
||||
|
||||
# Schedule the window to be shown and focused on the next tick.
|
||||
#
|
||||
@@ -472,13 +472,16 @@ class Atom extends Model
|
||||
|
||||
# Public: Set the full screen state of the current window.
|
||||
setFullScreen: (fullScreen=false) ->
|
||||
ipc.sendChannel('call-window-method', 'setFullScreen', fullScreen)
|
||||
ipc.send('call-window-method', 'setFullScreen', fullScreen)
|
||||
if fullScreen then document.body.classList.add("fullscreen") else document.body.classList.remove("fullscreen")
|
||||
|
||||
# Public: Is the current window in full screen mode?
|
||||
isFullScreen: ->
|
||||
@getCurrentWindow().isFullScreen()
|
||||
|
||||
# Public: Get the version of the Atom application.
|
||||
#
|
||||
# Returns the version text {String}.
|
||||
getVersion: ->
|
||||
@constructor.getVersion()
|
||||
|
||||
@@ -488,7 +491,7 @@ class Atom extends Model
|
||||
|
||||
# Public: Get the directory path to Atom's configuration area.
|
||||
#
|
||||
# Returns the absolute path to ~/.atom
|
||||
# Returns the absolute path to `~/.atom`.
|
||||
getConfigDirPath: ->
|
||||
@constructor.getConfigDirPath()
|
||||
|
||||
|
||||
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