Comparar commits
415 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 7d3553659a | |||
| 28dad3a01a | |||
| be872c2fdd | |||
| 526d87c355 | |||
| cbeb0187da | |||
| 7c614c6c79 | |||
| f4f0b4be72 | |||
| 3e27beeafa | |||
| 4a6b70d261 | |||
| 5917f71685 | |||
| fb42c499b1 | |||
| 1583271e2f | |||
| 020e22a13d | |||
| a37a7e0a76 | |||
| d1b4d0f9f2 | |||
| fb111dd0f4 | |||
| 1392deb29c | |||
| 2dafc5eaa1 | |||
| a407b0107a | |||
| 36c3c38047 | |||
| e56317bd64 | |||
| da49751f24 | |||
| 762559d2b7 | |||
| 2a0070ef10 | |||
| 7c7de4436e | |||
| 87afa50477 | |||
| 2e71e2fa4b | |||
| b537ba8864 | |||
| c156119882 | |||
| fea958c8e4 | |||
| 8e0a695f7c | |||
| 47f99cd74e | |||
| 0eb5fd4c3b | |||
| 0c01de350d | |||
| 77641f138b | |||
| f24843a928 | |||
| 03ab77c60b | |||
| ec0ec3bb16 | |||
| 690fc7180a | |||
| 02553bf8e2 | |||
| 81646532b4 | |||
| 1e7c80aebf | |||
| 27fe5b784c | |||
| 9b2901583e | |||
| 408665d7d2 | |||
| 6ec58e1163 | |||
| 541ffa5057 | |||
| 0ea683e0b5 | |||
| f12004d27b | |||
| 35d268fcf8 | |||
| 20c3ca21e3 | |||
| 37d2e00f4e | |||
| 5bf9bbe764 | |||
| e37fc316fb | |||
| 9128041c20 | |||
| 020c5e795a | |||
| be3a6bc6d0 | |||
| 142bb4b615 | |||
| ddf7bb5303 | |||
| 442342937f | |||
| a967e52f68 | |||
| c475e89a3e | |||
| 58da88b71a | |||
| 71328f21bd | |||
| a1b0f6c25d | |||
| fdccc2dae4 | |||
| 1246f8ed20 | |||
| fb56817895 | |||
| b6d8d5d100 | |||
| 8eb23dbe5c | |||
| 34f624c895 | |||
| d554b7fd03 | |||
| a61dff6e21 | |||
| 47b820ce7d | |||
| 33557b87eb | |||
| aed0c16acc | |||
| b4c8cb4bf9 | |||
| 8988d55d25 | |||
| 5824b127ed | |||
| d6ec73886f | |||
| 411cf579f4 | |||
| ad0ed7e634 | |||
| 7c00e02b1a | |||
| e6040972d8 | |||
| ac2f723aba | |||
| ecfb505144 | |||
| 326d1dce14 | |||
| c2f87fb73b | |||
| 1245835e96 | |||
| e174bdfa40 | |||
| 3d8bc89c42 | |||
| 5fc6524493 | |||
| 6e6c93e6bb | |||
| fd48ad1c67 | |||
| 5163166990 | |||
| 54b60a5253 | |||
| ff1d07bec9 | |||
| 6d56283448 | |||
| 6dfbd5733d | |||
| e56fa3ec4f | |||
| fe0d714710 | |||
| 7c1a7f52a5 | |||
| 590c6be33d | |||
| f1ca7fdbfd | |||
| a8b135b4bc | |||
| 1afdd62a5d | |||
| d47e8fc583 | |||
| 3644a36d67 | |||
| bb98b3ef38 | |||
| 356a7b014a | |||
| 1ea0ef4ea2 | |||
| f37ca3e19c | |||
| 8afd90b9f8 | |||
| 613e05f4ac | |||
| 068eeca862 | |||
| 0502afb0c3 | |||
| e1491ca154 | |||
| e9a975fd92 | |||
| 1459123b15 | |||
| 9996eb825f | |||
| 10392942d5 | |||
| c452d05f44 | |||
| 1043f75c72 | |||
| ec69bb5ffe | |||
| 41cc0ecab4 | |||
| 67f8ddc314 | |||
| 10d626d63a | |||
| 2ec526508b | |||
| 6017ff585f | |||
| e6d656830f | |||
| 1a15c3394e | |||
| b328a69f50 | |||
| e9ee6dca25 | |||
| a2f73fd6b0 | |||
| 9f09173d0f | |||
| 1e052c1113 | |||
| b72bb4ab65 | |||
| 24f751ec83 | |||
| d72e3d9c81 | |||
| 0aeb32ad70 | |||
| 3393583b72 | |||
| 6fcd905d4f | |||
| 993534337c | |||
| 03814246ef | |||
| 053965602c | |||
| b45c1c7548 | |||
| e96d821653 | |||
| e3448b0a46 | |||
| 63a80a4d4d | |||
| d07eea405f | |||
| 87d008c337 | |||
| 4a55c90c63 | |||
| 7bce6cb10a | |||
| 32499351dc | |||
| 2d7dda066c | |||
| 837f3c553f | |||
| 96e3c63291 | |||
| d5da396c0f | |||
| 4b089b62a6 | |||
| be8514b864 | |||
| e826b66dd2 | |||
| 83d6fc2374 | |||
| ecdaf48308 | |||
| a79885eafb | |||
| a3c9a65838 | |||
| 8ca5d6db35 | |||
| 980c17e50c | |||
| c9bf8f04b8 | |||
| 6613b9fd4d | |||
| 3168751c97 | |||
| 6bc471cef1 | |||
| 4b3240eeee | |||
| 1f9de98eb2 | |||
| 7eea30fa7f | |||
| 63e51af87d | |||
| bbc6433a75 | |||
| d4ae836225 | |||
| 789f29e0b5 | |||
| c584c158d7 | |||
| d63c4f88fd | |||
| db327b92f3 | |||
| cd01e6f2ad | |||
| b1be4e9183 | |||
| 009a142273 | |||
| f0f00fd317 | |||
| f5ea098417 | |||
| 82081aa5e9 | |||
| 33adaab8b1 | |||
| e21a1339a2 | |||
| b90849fa66 | |||
| 23d3405ae7 | |||
| d39c422da9 | |||
| 053c0f703a | |||
| 1c91bd3100 | |||
| 0ffb5da515 | |||
| b7db7f6c99 | |||
| cae9782e24 | |||
| 5dbab7bb89 | |||
| ceab8e8166 | |||
| 97cb440a7c | |||
| fcdb42dbe4 | |||
| 11a91fb974 | |||
| 1d426e8fd2 | |||
| 6f0094e6ce | |||
| 915cad39e8 | |||
| d8f0743888 | |||
| 7685b27218 | |||
| 3aab0b7f51 | |||
| 2f5735e264 | |||
| 56bea31b5e | |||
| 52d5e205c7 | |||
| 0f5f6c8657 | |||
| 7457be2805 | |||
| 86842658c0 | |||
| d0276e60b5 | |||
| 18d6a56e82 | |||
| 59108322e7 | |||
| 665088ce27 | |||
| 79399a3c5a | |||
| 4659b95d36 | |||
| bdf73cd198 | |||
| 6e422d5428 | |||
| e464c4f047 | |||
| 4610c4446a | |||
| 156ca14ea6 | |||
| cebb27154d | |||
| afe6685ce8 | |||
| 148e143255 | |||
| 96d1c84f62 | |||
| f40ecccdcc | |||
| 03b9713547 | |||
| 9fb364026e | |||
| 1aa64a9d80 | |||
| 2ea09aa6b6 | |||
| 76ce150448 | |||
| 1d01ff0797 | |||
| a1d78a1062 | |||
| 3ac41a544a | |||
| 3e24d045e5 | |||
| 143738033b | |||
| f153cbb41f | |||
| f1ed5dedd7 | |||
| e58c2d8368 | |||
| bcf1781040 | |||
| 0b0dbbe4ee | |||
| c9e297a511 | |||
| 18082f7cdc | |||
| ca016ce116 | |||
| bb59e46267 | |||
| 86c4b99eab | |||
| a1e1a00f9f | |||
| 53996e7bb0 | |||
| f88c71e1a1 | |||
| 2cccbff509 | |||
| b173fcdd59 | |||
| 7b6c62ab5e | |||
| 809e57cb84 | |||
| de16ed6250 | |||
| 606160d312 | |||
| 78e990d1f9 | |||
| d47cc6fa0b | |||
| 8f3951fbd8 | |||
| e09486d425 | |||
| 662f252912 | |||
| 784d22368e | |||
| a40660d125 | |||
| af632df48b | |||
| 4a35c9a1af | |||
| f90f48e3f0 | |||
| 9c6a3c3d03 | |||
| 4bccb81656 | |||
| 870e80446f | |||
| 4165a69fed | |||
| 93d9a00819 | |||
| a3789411de | |||
| 2b6b40bda7 | |||
| 61ae185494 | |||
| 0eae68973b | |||
| 6f2695388c | |||
| 0c12f712c9 | |||
| 727d1cf4aa | |||
| 9324b538f7 | |||
| 5aff4a042b | |||
| e36bc5bc9f | |||
| 1a88937f5a | |||
| 5737593957 | |||
| d61d8bea86 | |||
| 062974882b | |||
| 8415ddcb49 | |||
| 64f392a380 | |||
| fce09f9bfe | |||
| f04ce025f4 | |||
| 57844c2ca4 | |||
| 91433cfe90 | |||
| 86423698b1 | |||
| 7dda8e1b80 | |||
| 70cd6a6bc3 | |||
| 6e9217be5f | |||
| 3d8c916a72 | |||
| cae9c96622 | |||
| aaf283ceaa | |||
| 4bac60ad94 | |||
| cc2e87b784 | |||
| 363fb0d66e | |||
| 2d2295dcc6 | |||
| bf3daeccc5 | |||
| 63d5caebbc | |||
| 3ac3a89fa5 | |||
| af6d7204f9 | |||
| 642671161d | |||
| b2fdc25c83 | |||
| 893a3f63dd | |||
| 271b104120 | |||
| 247eec44d5 | |||
| d064c27faf | |||
| 8c6ed69176 | |||
| 56222a072a | |||
| 1021979d98 | |||
| fcc4376cdd | |||
| afbf011103 | |||
| e858f74a17 | |||
| 58dc45d496 | |||
| 3029dc8d2a | |||
| 11d7562c12 | |||
| b8b95d537b | |||
| 9ec342a545 | |||
| cf60b1fde3 | |||
| 556cdfd300 | |||
| c566e7f1f3 | |||
| 366312dee8 | |||
| 1acc6bfadf | |||
| 9fd21ce2e1 | |||
| 5525e046e9 | |||
| 68e1e36347 | |||
| 199a0f7089 | |||
| 65564e2012 | |||
| d612a71af5 | |||
| 477624387f | |||
| bf686101dc | |||
| b348ef633c | |||
| 68022837b4 | |||
| 537981ff62 | |||
| 5bc339afae | |||
| 4e9871a26a | |||
| e334d2b640 | |||
| c7efaef1be | |||
| ad751a1a2a | |||
| fad21c6d3e | |||
| 373a7a6d04 | |||
| 0742909953 | |||
| 25fcd25c32 | |||
| 0fe4258a44 | |||
| 0727c8efab | |||
| 7198740b26 | |||
| 634a12470b | |||
| 940145be7a | |||
| fca03552e2 | |||
| f42e880804 | |||
| 341c474dfa | |||
| c3a1831959 | |||
| dde1a0b2eb | |||
| ecfddc1523 | |||
| 13b59213eb | |||
| c0bb3b07c6 | |||
| c804c5ada3 | |||
| 0816e923f9 | |||
| 5d30e30a63 | |||
| 89fdffdfdc | |||
| 8f089a5ce1 | |||
| f3bc2310f0 | |||
| bd9cabea75 | |||
| 2520b3f85a | |||
| 22b967adf5 | |||
| cb514d10d5 | |||
| 9e3b67b4b9 | |||
| 49556e2aa8 | |||
| 94e70d3f25 | |||
| 05c47bd3c0 | |||
| 5b6fe70b7e | |||
| 424bf706e9 | |||
| b1feb9cf2f | |||
| 6948183270 | |||
| 4aa612e70c | |||
| d146faae1d | |||
| aa02bc1aaf | |||
| f9eb8e3466 | |||
| 18e13cfc3b | |||
| c46238f795 | |||
| 50e045212b | |||
| d5c831c64b | |||
| 75b355d632 | |||
| dcf4394741 | |||
| 36a6ecdd9a | |||
| d8dfea00d0 | |||
| 9784d49667 | |||
| cb76c698e7 | |||
| 9d2957a7c9 | |||
| 92a722495b | |||
| 30a2e5d902 | |||
| 409d5c7783 | |||
| 9f567051fb | |||
| 624c7baf44 | |||
| 2671d8bd46 | |||
| 8b928d9320 | |||
| 27ddcfcbcb | |||
| 48798dead9 | |||
| 0adae86b4d | |||
| 92283cabfa | |||
| fd6476e4d1 | |||
| d62b3d5236 | |||
| bb6aa5eedb | |||
| 6bd73f2647 | |||
| d816eca300 | |||
| 4aa6e78a4e | |||
| 7ecb0dcd4b |
@@ -1,4 +1,5 @@
|
||||
*.swp
|
||||
*~
|
||||
.DS_Store
|
||||
.project
|
||||
.svn
|
||||
|
||||
@@ -56,6 +56,7 @@ in the proper package's repository.
|
||||
* :racehorse: when improving performance
|
||||
* :non-potable_water: when plugging memory leaks
|
||||
* :memo: when writing docs
|
||||
* :penguin: when fixing something on Linux
|
||||
|
||||
## CoffeeScript Styleguide
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@ module.exports = (grunt) ->
|
||||
installDir = process.env.INSTALL_PREFIX ? '/usr/local'
|
||||
|
||||
coffeeConfig =
|
||||
options:
|
||||
sourceMap: true
|
||||
glob_to_multiple:
|
||||
expand: true
|
||||
src: [
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"grunt-shell": "~0.3.1",
|
||||
"harmony-collections": "~0.3.8",
|
||||
"json-front-matter": "~0.1.3",
|
||||
"legal-eagle": "~0.3.0",
|
||||
"legal-eagle": "~0.4.0",
|
||||
"minidump": "0.5.x",
|
||||
"rcedit": "~0.1.2",
|
||||
"request": "~2.27.0",
|
||||
|
||||
@@ -47,7 +47,9 @@ module.exports = (grunt) ->
|
||||
path.join('less', 'test')
|
||||
path.join('bootstrap', 'docs')
|
||||
path.join('bootstrap', 'examples')
|
||||
path.join('spellchecker', 'vendor')
|
||||
path.join('pegjs', 'examples')
|
||||
# Add .* to avoid matching hunspell_dictionaries.
|
||||
path.join('spellchecker', 'vendor', 'hunspell', '.*')
|
||||
path.join('xmldom', 'test')
|
||||
path.join('jasmine-reporters', 'ext')
|
||||
path.join('build', 'Release', 'obj.target')
|
||||
@@ -56,6 +58,9 @@ module.exports = (grunt) ->
|
||||
path.join('resources', 'mac')
|
||||
path.join('resources', 'win')
|
||||
]
|
||||
# Hunspell dictionaries are only not needed on OS X.
|
||||
if process.platform is 'darwin'
|
||||
ignoredPaths.push path.join('spellchecker', 'vendor', 'hunspell_dictionaries')
|
||||
ignoredPaths = ignoredPaths.map (ignoredPath) -> "(#{ignoredPath})"
|
||||
nodeModulesFilter = new RegExp(ignoredPaths.join('|'))
|
||||
packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(cson|coffee)$)")
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
fs = require 'fs-plus'
|
||||
runas = null
|
||||
|
||||
module.exports = (grunt) ->
|
||||
@@ -28,3 +30,10 @@ module.exports = (grunt) ->
|
||||
rm shareDir
|
||||
mkdir path.dirname(shareDir)
|
||||
cp shellAppDir, shareDir
|
||||
|
||||
# Create relative symbol link for apm.
|
||||
process.chdir(binDir)
|
||||
rm('apm')
|
||||
fs.symlinkSync(path.join('..', 'share', 'atom', 'resources', 'app', 'apm', 'node_modules', '.bin', 'apm'), 'apm')
|
||||
|
||||
fs.chmodSync(path.join(shareDir, 'atom'), "755")
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = (grunt) ->
|
||||
{name, version, description} = grunt.file.readJSON('package.json')
|
||||
section = 'devel'
|
||||
arch = 'amd64'
|
||||
maintainer = 'GitHub <support@github.com>'
|
||||
maintainer = 'GitHub <atom@github.com>'
|
||||
data = {name, version, description, section, arch, maintainer}
|
||||
|
||||
control = path.join('resources', 'linux', 'debian', 'control')
|
||||
|
||||
@@ -83,6 +83,22 @@ file. For now, we've opted to handle cases where selector ordering is critical
|
||||
by breaking the keymap into two separate files, such as `snippets-1.cson` and
|
||||
`snippets-2.cson`.
|
||||
|
||||
## Removing Bindings
|
||||
|
||||
When the keymap system encounters a binding with the `unset!` directive as its
|
||||
command, it will treat the current element as if it had no key bindings matching
|
||||
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.
|
||||
|
||||
## Forcing Chromium's Native Keystroke Handling
|
||||
|
||||
If you want to force the native browser behavior for a given keystroke, use the
|
||||
`native!` directive as the command of a binding. This can be useful to enable
|
||||
the correct behavior in native input elements, for example. If you apply the
|
||||
`.native-key-bindings` class to an element, all the keystrokes typically handled
|
||||
by the browser will be assigned the `native!` directive.
|
||||
|
||||
## Overloading Key Bindings
|
||||
|
||||
Occasionally, it makes sense to layer multiple actions on top of the same key
|
||||
|
||||
@@ -73,7 +73,7 @@ from.
|
||||
You can split any editor pane horizontally or vertically by using `cmd-k right`
|
||||
or `cmd-k down`. Once you have a split pane, you can move focus between them
|
||||
with `cmd-k cmd-right` or `cmd-k cmd-down`. To close a pane, close all its
|
||||
editors with `meta-w`, then press `meta-w` one more time to close the pane. You
|
||||
editors with `cmd-w`, then press `cmd-w` one more time to close the pane. You
|
||||
can configure panes to auto-close when empty in the Settings view.
|
||||
|
||||
### Folding
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
'shift-home': 'editor:select-to-first-character-of-line'
|
||||
'shift-end': 'editor:select-to-end-of-line'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-t': 'editor:transpose'
|
||||
|
||||
'.editor:not(.mini)':
|
||||
# Atom Specific
|
||||
'ctrl-C': 'editor:copy-path'
|
||||
@@ -21,8 +18,6 @@
|
||||
'enter': 'editor:newline'
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'ctrl-K': 'editor:delete-line'
|
||||
'ctrl-shift-up': 'editor:add-selection-above'
|
||||
'ctrl-shift-down': 'editor:add-selection-below'
|
||||
|
||||
'.tool-panel.panel-left, .tool-panel.panel-right':
|
||||
'escape': 'tool-panel:unfocus'
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
'cmd-k cmd-u': 'editor:upper-case'
|
||||
'cmd-k cmd-l': 'editor:lower-case'
|
||||
'cmd-l': 'editor:select-line'
|
||||
'ctrl-t': 'editor:transpose'
|
||||
|
||||
'.workspace .editor:not(.mini)':
|
||||
# Atom specific
|
||||
@@ -137,6 +138,8 @@
|
||||
'cmd-j': 'editor:join-lines'
|
||||
'cmd-D': 'editor:duplicate-lines'
|
||||
'cmd-L': 'editor:split-selections-into-lines'
|
||||
'ctrl-shift-up': 'editor:add-selection-above'
|
||||
'ctrl-shift-down': 'editor:add-selection-below'
|
||||
|
||||
'cmd-alt-[': 'editor:fold-current-row'
|
||||
'cmd-alt-]': 'editor:unfold-current-row'
|
||||
|
||||
@@ -10,11 +10,14 @@
|
||||
'ctrl-alt-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'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-N': 'application:new-window'
|
||||
'ctrl-W': 'window:close'
|
||||
'ctrl-o': 'application:open'
|
||||
'ctrl-o': 'application:open-file'
|
||||
'ctrl-q': 'application:quit'
|
||||
'ctrl-T': 'pane:reopen-closed-item'
|
||||
'ctrl-n': 'application:new-file'
|
||||
'ctrl-s': 'core:save'
|
||||
@@ -82,6 +85,8 @@
|
||||
'ctrl-/': 'editor:toggle-line-comments'
|
||||
'ctrl-j': 'editor:join-lines'
|
||||
'ctrl-D': 'editor:duplicate-lines'
|
||||
'alt-shift-up': 'editor:add-selection-above'
|
||||
'alt-shift-down': 'editor:add-selection-below'
|
||||
|
||||
'ctrl-alt-[': 'editor:fold-current-row'
|
||||
'ctrl-alt-]': 'editor:unfold-current-row'
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# Sublime Parity
|
||||
'ctrl-N': 'application:new-window'
|
||||
'ctrl-W': 'window:close'
|
||||
'ctrl-o': 'application:open'
|
||||
'ctrl-o': 'application:open-file'
|
||||
'ctrl-T': 'pane:reopen-closed-item'
|
||||
'ctrl-n': 'application:new-file'
|
||||
'ctrl-s': 'core:save'
|
||||
|
||||
+4
-4
@@ -4,10 +4,10 @@
|
||||
submenu: [
|
||||
{ label: 'About Atom', command: 'application:about' }
|
||||
{ label: 'View License', command: 'application:open-license' }
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ label: "Restart and Install Update", command: 'application:install-update', visible: false}
|
||||
{ label: "Check for Update", command: 'application:check-for-update', visible: false}
|
||||
{ label: "Downloading Update", command: 'application:check-for-update', enabled: false, visible: false}
|
||||
{ label: 'VERSION', enabled: false }
|
||||
{ label: 'Restart and Install Update', command: 'application:install-update', visible: false}
|
||||
{ label: 'Check for Update', command: 'application:check-for-update', visible: false}
|
||||
{ label: 'Downloading Update', enabled: false, visible: false}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Preferences...', command: 'application:show-settings' }
|
||||
{ label: 'Open Your Config', command: 'application:open-your-config' }
|
||||
|
||||
+3
-4
@@ -4,7 +4,8 @@
|
||||
submenu: [
|
||||
{ label: 'New &Window', command: 'application:new-window' }
|
||||
{ label: '&New File', command: 'application:new-file' }
|
||||
{ label: '&Open...', command: 'application:open' }
|
||||
{ label: '&Open File...', command: 'application:open-file' }
|
||||
{ label: 'Open Folder...', command: 'application:open-folder' }
|
||||
{ label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Preferences...', command: 'application:show-settings' }
|
||||
@@ -17,7 +18,7 @@
|
||||
{ label: 'Close All &Buffers', command: 'pane:close' }
|
||||
{ label: 'Clos&e Window', command: 'window:close' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'E&xit', command: 'application:quit' }
|
||||
{ label: 'Quit', command: 'application:quit' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -144,10 +145,8 @@
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
{ label: '&About Atom...', command: 'application:about' }
|
||||
{ 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' }
|
||||
|
||||
+2
-1
@@ -4,7 +4,8 @@
|
||||
submenu: [
|
||||
{ label: 'New &Window', command: 'application:new-window' }
|
||||
{ label: '&New File', command: 'application:new-file' }
|
||||
{ label: '&Open...', command: 'application:open' }
|
||||
{ label: '&Open File...', command: 'application:open-file' }
|
||||
{ label: 'Open Folder...', command: 'application:open-folder' }
|
||||
{ label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Preferences...', command: 'application:show-settings' }
|
||||
|
||||
+62
-60
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.77.0",
|
||||
"version": "0.90.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -12,120 +12,122 @@
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"license": "All Rights Reserved",
|
||||
"atomShellVersion": "0.11.3",
|
||||
"atomShellVersion": "0.11.10",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^0.11.0",
|
||||
"atom-keymap": "^0.18.0",
|
||||
"bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.7.0",
|
||||
"coffeestack": "0.7.0",
|
||||
"delegato": "1.x",
|
||||
"emissary": "^1.2",
|
||||
"first-mate": ">=1.4.2 <2.0",
|
||||
"fs-plus": ">=2.0.4 < 3.0",
|
||||
"emissary": "^1.2.1",
|
||||
"first-mate": "^1.5.1",
|
||||
"fs-plus": "^2.2.2",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "~1.1",
|
||||
"git-utils": "^1.1.1",
|
||||
"git-utils": "^1.2.2",
|
||||
"grim": "0.9.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-tagged": ">=1.1.1 <2.0",
|
||||
"mkdirp": "0.3.5",
|
||||
"keytar": "1.x",
|
||||
"jasmine-tagged": "^1.1.1",
|
||||
"less-cache": "0.12.0",
|
||||
"mixto": "1.x",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "0.5.0",
|
||||
"oniguruma": "^1.0.4",
|
||||
"oniguruma": "^1.0.6",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^1.1",
|
||||
"pathwatcher": "^1.1.1",
|
||||
"property-accessors": "1.x",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
"runas": "0.5.x",
|
||||
"scandal": "0.15.0",
|
||||
"scandal": "0.15.2",
|
||||
"scoped-property-store": "^0.8.0",
|
||||
"scrollbar-style": "^0.1.0",
|
||||
"season": ">=1.0.2 <2.0",
|
||||
"season": "^1.0.2",
|
||||
"semver": "1.1.4",
|
||||
"serializable": "1.x",
|
||||
"space-pen": "3.1.1",
|
||||
"temp": "0.5.0",
|
||||
"text-buffer": "^1.4.5",
|
||||
"text-buffer": "^2.1.0",
|
||||
"theorist": "1.x",
|
||||
"underscore-plus": ">=1.0.5 <2.0",
|
||||
"underscore-plus": "^1.1.2",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.15.0",
|
||||
"atom-dark-ui": "0.26.0",
|
||||
"atom-light-syntax": "0.16.0",
|
||||
"atom-light-ui": "0.23.0",
|
||||
"base16-tomorrow-dark-theme": "0.13.0",
|
||||
"atom-light-ui": "0.24.0",
|
||||
"base16-tomorrow-dark-theme": "0.14.0",
|
||||
"solarized-dark-syntax": "0.14.0",
|
||||
"solarized-light-syntax": "0.7.0",
|
||||
"archive-view": "0.30.0",
|
||||
"autocomplete": "0.27.0",
|
||||
"autoflow": "0.15.0",
|
||||
"autoflow": "0.16.0",
|
||||
"autosave": "0.13.0",
|
||||
"background-tips": "0.9.0",
|
||||
"background-tips": "0.13.0",
|
||||
"bookmarks": "0.22.0",
|
||||
"bracket-matcher": "0.26.0",
|
||||
"command-palette": "0.19.0",
|
||||
"bracket-matcher": "0.33.0",
|
||||
"command-palette": "0.21.0",
|
||||
"deprecation-cop": "0.5.0",
|
||||
"dev-live-reload": "0.30.0",
|
||||
"exception-reporting": "0.17.0",
|
||||
"feedback": "0.28.0",
|
||||
"find-and-replace": "0.92.0",
|
||||
"fuzzy-finder": "0.42.0",
|
||||
"git-diff": "0.25.0",
|
||||
"go-to-line": "0.18.0",
|
||||
"grammar-selector": "0.23.0",
|
||||
"image-view": "0.32.0",
|
||||
"keybinding-resolver": "0.12.0",
|
||||
"link": "0.20.0",
|
||||
"markdown-preview": "0.51.0",
|
||||
"feedback": "0.30.0",
|
||||
"find-and-replace": "0.99.0",
|
||||
"fuzzy-finder": "0.50.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",
|
||||
"link": "0.22.0",
|
||||
"markdown-preview": "0.64.0",
|
||||
"metrics": "0.32.0",
|
||||
"open-on-github": "0.23.0",
|
||||
"open-on-github": "0.28.0",
|
||||
"package-generator": "0.30.0",
|
||||
"release-notes": "0.26.0",
|
||||
"settings-view": "0.97.0",
|
||||
"snippets": "0.40.0",
|
||||
"spell-check": "0.28.0",
|
||||
"status-bar": "0.37.0",
|
||||
"styleguide": "0.26.0",
|
||||
"symbols-view": "0.46.0",
|
||||
"tabs": "0.31.0",
|
||||
"timecop": "0.17.0",
|
||||
"tree-view": "0.83.0",
|
||||
"release-notes": "0.27.0",
|
||||
"settings-view": "0.110.0",
|
||||
"snippets": "0.41.0",
|
||||
"spell-check": "0.34.0",
|
||||
"status-bar": "0.40.0",
|
||||
"styleguide": "0.29.0",
|
||||
"symbols-view": "0.49.0",
|
||||
"tabs": "0.36.0",
|
||||
"timecop": "0.18.0",
|
||||
"tree-view": "0.90.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.11.0",
|
||||
"whitespace": "0.21.0",
|
||||
"welcome": "0.12.0",
|
||||
"whitespace": "0.22.0",
|
||||
"wrap-guide": "0.18.0",
|
||||
"language-c": "0.13.0",
|
||||
"language-coffee-script": "0.16.0",
|
||||
"language-css": "0.13.0",
|
||||
"language-gfm": "0.25.0",
|
||||
"language-c": "0.14.0",
|
||||
"language-coffee-script": "0.22.0",
|
||||
"language-css": "0.16.0",
|
||||
"language-gfm": "0.31.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.7.0",
|
||||
"language-html": "0.15.0",
|
||||
"language-go": "0.9.0",
|
||||
"language-html": "0.19.0",
|
||||
"language-hyperlink": "0.9.0",
|
||||
"language-java": "0.9.0",
|
||||
"language-javascript": "0.21.0",
|
||||
"language-javascript": "0.24.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.6.0",
|
||||
"language-make": "0.9.0",
|
||||
"language-less": "0.8.0",
|
||||
"language-make": "0.10.0",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.8.0",
|
||||
"language-php": "0.13.0",
|
||||
"language-php": "0.14.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.12.0",
|
||||
"language-ruby": "0.17.0",
|
||||
"language-python": "0.15.0",
|
||||
"language-ruby": "0.22.0",
|
||||
"language-ruby-on-rails": "0.12.0",
|
||||
"language-sass": "0.8.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.7.0",
|
||||
"language-sql": "0.7.0",
|
||||
"language-sql": "0.8.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.9.0",
|
||||
"language-todo": "0.10.0",
|
||||
"language-toml": "0.12.0",
|
||||
"language-xml": "0.9.0",
|
||||
"language-xml": "0.11.0",
|
||||
"language-yaml": "0.6.0"
|
||||
},
|
||||
"private": true,
|
||||
|
||||
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 48 KiB Depois Largura: | Altura: | Tamanho: 191 KiB |
+1
-1
@@ -23,9 +23,9 @@ var commands = [
|
||||
[home, '.atom', '.node-gyp'],
|
||||
[home, '.atom', 'storage'],
|
||||
[home, '.atom', '.npm'],
|
||||
[home, '.atom', 'compile-cache'],
|
||||
[tmpdir, 'atom-build'],
|
||||
[tmpdir, 'atom-cached-atom-shells'],
|
||||
[tmpdir, 'atom-compile-cache'],
|
||||
];
|
||||
var run = function() {
|
||||
var next = commands.shift();
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ ICON_FILE="$4"
|
||||
DEB_PATH="$5"
|
||||
|
||||
TARGET_ROOT="`mktemp -d`"
|
||||
TARGET="$TARGET_ROOT/atom-$VERSION"
|
||||
TARGET="$TARGET_ROOT/atom-$VERSION-amd64"
|
||||
|
||||
mkdir -p "$TARGET/usr"
|
||||
env INSTALL_PREFIX="$TARGET/usr" script/grunt install
|
||||
@@ -27,5 +27,5 @@ mkdir -p "$TARGET/usr/share/pixmaps"
|
||||
cp "$ICON_FILE" "$TARGET/usr/share/pixmaps"
|
||||
|
||||
dpkg-deb -b "$TARGET"
|
||||
mv "$TARGET_ROOT/atom-$VERSION.deb" "$DEB_PATH"
|
||||
mv "$TARGET_ROOT/atom-$VERSION-amd64.deb" "$DEB_PATH"
|
||||
rm -rf $TARGET_ROOT
|
||||
|
||||
+12
-12
@@ -170,28 +170,28 @@ describe "the `atom` global", ->
|
||||
element2 = $$ -> @div class: 'test-2'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
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
|
||||
|
||||
atom.packages.activatePackage("package-with-keymaps")
|
||||
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe "test-1"
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)[0].command).toBe "test-2"
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
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
|
||||
|
||||
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.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
|
||||
atom.packages.activatePackage("package-with-keymaps-manifest")
|
||||
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe 'keymap-1'
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-n', element1)[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-y', element3)).toHaveLength 0
|
||||
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
|
||||
|
||||
describe "menu loading", ->
|
||||
beforeEach ->
|
||||
@@ -377,8 +377,8 @@ describe "the `atom` global", ->
|
||||
|
||||
runs ->
|
||||
atom.packages.deactivatePackage('package-with-keymaps')
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
|
||||
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
|
||||
|
||||
it "removes the package's stylesheets", ->
|
||||
waitsForPromise ->
|
||||
|
||||
@@ -36,15 +36,53 @@ describe "Config", ->
|
||||
|
||||
describe "when the value equals the default value", ->
|
||||
it "does not store the value", ->
|
||||
atom.config.setDefaults("foo", same: 1, changes: 1)
|
||||
atom.config.setDefaults "foo",
|
||||
same: 1
|
||||
changes: 1
|
||||
sameArray: [1, 2, 3]
|
||||
sameObject: {a: 1, b: 2}
|
||||
null: null
|
||||
undefined: undefined
|
||||
expect(atom.config.settings.foo).toBeUndefined()
|
||||
|
||||
atom.config.set('foo.same', 1)
|
||||
atom.config.set('foo.changes', 2)
|
||||
atom.config.set('foo.sameArray', [1, 2, 3])
|
||||
atom.config.set('foo.null', undefined)
|
||||
atom.config.set('foo.undefined', null)
|
||||
atom.config.set('foo.sameObject', {b: 2, a: 1})
|
||||
expect(atom.config.settings.foo).toEqual {changes: 2}
|
||||
|
||||
atom.config.set('foo.changes', 1)
|
||||
expect(atom.config.settings.foo).toEqual {}
|
||||
|
||||
describe ".getDefault(keyPath)", ->
|
||||
it "returns a clone of the default value", ->
|
||||
atom.config.setDefaults("foo", same: 1, changes: 1)
|
||||
expect(atom.config.getDefault('foo.same')).toBe 1
|
||||
expect(atom.config.getDefault('foo.changes')).toBe 1
|
||||
|
||||
atom.config.set('foo.same', 2)
|
||||
atom.config.set('foo.changes', 3)
|
||||
expect(atom.config.getDefault('foo.same')).toBe 1
|
||||
expect(atom.config.getDefault('foo.changes')).toBe 1
|
||||
|
||||
initialDefaultValue = [1, 2, 3]
|
||||
atom.config.setDefaults("foo", bar: initialDefaultValue)
|
||||
expect(atom.config.getDefault('foo.bar')).toEqual initialDefaultValue
|
||||
expect(atom.config.getDefault('foo.bar')).not.toBe initialDefaultValue
|
||||
|
||||
describe ".isDefault(keyPath)", ->
|
||||
it "returns true when the value of the key path is its default value", ->
|
||||
atom.config.setDefaults("foo", same: 1, changes: 1)
|
||||
expect(atom.config.isDefault('foo.same')).toBe true
|
||||
expect(atom.config.isDefault('foo.changes')).toBe true
|
||||
|
||||
atom.config.set('foo.same', 2)
|
||||
atom.config.set('foo.changes', 3)
|
||||
expect(atom.config.isDefault('foo.same')).toBe false
|
||||
expect(atom.config.isDefault('foo.changes')).toBe false
|
||||
|
||||
describe ".toggle(keyPath)", ->
|
||||
it "negates the boolean value of the current key path value", ->
|
||||
atom.config.set('foo.a', 1)
|
||||
@@ -170,6 +208,13 @@ describe "Config", ->
|
||||
expect(atom.config.get("foo.quux.x")).toBe 0
|
||||
expect(atom.config.get("foo.quux.y")).toBe 1
|
||||
|
||||
it "emits an updated event", ->
|
||||
updatedCallback = jasmine.createSpy('updated')
|
||||
atom.config.observe('foo.bar.baz.a', callNow: false, updatedCallback)
|
||||
expect(updatedCallback.callCount).toBe 0
|
||||
atom.config.setDefaults("foo.bar.baz", a: 2)
|
||||
expect(updatedCallback.callCount).toBe 1
|
||||
|
||||
describe ".observe(keyPath)", ->
|
||||
[observeHandler, observeSubscription] = []
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ describe "DisplayBuffer", ->
|
||||
displayBuffer.destroy()
|
||||
buffer.release()
|
||||
|
||||
describe ".copy()", ->
|
||||
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)
|
||||
@@ -82,7 +82,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when there is no whitespace before the boundary", ->
|
||||
it "wraps the line exactly at the boundary since there's no more graceful place to wrap it", ->
|
||||
buffer.change([[0, 0], [1, 0]], 'abcdefghijklmnopqrstuvwxyz\n')
|
||||
buffer.setTextInRange([[0, 0], [1, 0]], 'abcdefghijklmnopqrstuvwxyz\n')
|
||||
displayBuffer.setEditorWidthInChars(10)
|
||||
expect(displayBuffer.lineForRow(0).text).toBe 'abcdefghij'
|
||||
expect(displayBuffer.lineForRow(1).text).toBe 'klmnopqrst'
|
||||
@@ -142,7 +142,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when buffer lines are removed", ->
|
||||
it "removes lines and emits a change event", ->
|
||||
buffer.change([[3, 21], [7, 5]], ';')
|
||||
buffer.setTextInRange([[3, 21], [7, 5]], ';')
|
||||
expect(displayBuffer.lineForRow(3).text).toBe ' var pivot = items;'
|
||||
expect(displayBuffer.lineForRow(4).text).toBe ' return '
|
||||
expect(displayBuffer.lineForRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));'
|
||||
@@ -330,7 +330,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when the old range surrounds a fold", ->
|
||||
beforeEach ->
|
||||
buffer.change([[1, 0], [5, 1]], 'party!')
|
||||
buffer.setTextInRange([[1, 0], [5, 1]], 'party!')
|
||||
|
||||
it "removes the fold and replaces the selection with the new text", ->
|
||||
expect(displayBuffer.lineForRow(0).text).toBe "0"
|
||||
@@ -352,7 +352,7 @@ describe "DisplayBuffer", ->
|
||||
displayBuffer.createFold(2, 9)
|
||||
changeHandler.reset()
|
||||
|
||||
buffer.change([[1, 0], [10, 0]], 'goodbye')
|
||||
buffer.setTextInRange([[1, 0], [10, 0]], 'goodbye')
|
||||
|
||||
expect(displayBuffer.lineForRow(0).text).toBe "0"
|
||||
expect(displayBuffer.lineForRow(1).text).toBe "goodbye10"
|
||||
@@ -371,7 +371,7 @@ describe "DisplayBuffer", ->
|
||||
describe "when the old range precedes lines with a fold", ->
|
||||
describe "when the new range precedes lines with a fold", ->
|
||||
it "updates the buffer and re-positions subsequent folds", ->
|
||||
buffer.change([[0, 0], [1, 1]], 'abc')
|
||||
buffer.setTextInRange([[0, 0], [1, 1]], 'abc')
|
||||
|
||||
expect(displayBuffer.lineForRow(0).text).toBe "abc"
|
||||
expect(displayBuffer.lineForRow(1).fold).toBe fold1
|
||||
@@ -394,7 +394,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when the old range straddles the beginning of a fold", ->
|
||||
it "destroys the fold", ->
|
||||
buffer.change([[1, 1], [3, 0]], "a\nb\nc\nd\n")
|
||||
buffer.setTextInRange([[1, 1], [3, 0]], "a\nb\nc\nd\n")
|
||||
expect(displayBuffer.lineForRow(1).text).toBe '1a'
|
||||
expect(displayBuffer.lineForRow(2).text).toBe 'b'
|
||||
expect(displayBuffer.lineForRow(2).fold).toBeUndefined()
|
||||
@@ -402,7 +402,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when the old range follows a fold", ->
|
||||
it "re-positions the screen ranges for the change event based on the preceding fold", ->
|
||||
buffer.change([[10, 0], [11, 0]], 'abc')
|
||||
buffer.setTextInRange([[10, 0], [11, 0]], 'abc')
|
||||
|
||||
expect(displayBuffer.lineForRow(1).text).toBe "1"
|
||||
expect(displayBuffer.lineForRow(2).fold).toBe fold1
|
||||
@@ -430,7 +430,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when the end of the new range exceeds the end of the fold", ->
|
||||
it "expands the fold to contain all the inserted lines", ->
|
||||
buffer.change([[3, 0], [4, 0]], 'a\nb\nc\nd\n')
|
||||
buffer.setTextInRange([[3, 0], [4, 0]], 'a\nb\nc\nd\n')
|
||||
expect(fold1.getStartRow()).toBe 2
|
||||
expect(fold1.getEndRow()).toBe 7
|
||||
|
||||
@@ -447,7 +447,7 @@ describe "DisplayBuffer", ->
|
||||
describe "when the end of the new range precedes the end of the fold", ->
|
||||
it "destroys the fold", ->
|
||||
fold2.destroy()
|
||||
buffer.change([[3, 0], [6, 0]], 'a\n')
|
||||
buffer.setTextInRange([[3, 0], [6, 0]], 'a\n')
|
||||
expect(displayBuffer.lineForRow(2).text).toBe '2'
|
||||
expect(displayBuffer.lineForRow(2).fold).toBeUndefined()
|
||||
expect(displayBuffer.lineForRow(3).text).toBe 'a'
|
||||
@@ -536,7 +536,7 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.outermostFoldsInBufferRowRange(3, 18)).toEqual [fold1, fold3, fold5]
|
||||
expect(displayBuffer.outermostFoldsInBufferRowRange(5, 16)).toEqual [fold3]
|
||||
|
||||
describe ".clipScreenPosition(screenPosition, wrapBeyondNewlines: false, wrapAtSoftNewlines: false, skipAtomicTokens: false)", ->
|
||||
describe "::clipScreenPosition(screenPosition, wrapBeyondNewlines: false, wrapAtSoftNewlines: false, skipAtomicTokens: false)", ->
|
||||
beforeEach ->
|
||||
displayBuffer.setSoftWrap(true)
|
||||
displayBuffer.setEditorWidthInChars(50)
|
||||
@@ -598,7 +598,7 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.clipScreenPosition([0, 1], skipAtomicTokens: true)).toEqual [0, tabLength]
|
||||
expect(displayBuffer.clipScreenPosition([0, tabLength], skipAtomicTokens: true)).toEqual [0, tabLength]
|
||||
|
||||
describe ".screenPositionForBufferPosition(bufferPosition, options)", ->
|
||||
describe "::screenPositionForBufferPosition(bufferPosition, options)", ->
|
||||
it "clips the specified buffer position", ->
|
||||
expect(displayBuffer.screenPositionForBufferPosition([0, 2])).toEqual [0, 2]
|
||||
expect(displayBuffer.screenPositionForBufferPosition([0, 100000])).toEqual [0, 29]
|
||||
@@ -618,13 +618,13 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.screenPositionForBufferPosition([0, 10], wrapAtSoftNewlines: true)).toEqual [1, 0]
|
||||
expect(displayBuffer.bufferPositionForScreenPosition([1, 0])).toEqual [0, 10]
|
||||
|
||||
describe ".getMaxLineLength()", ->
|
||||
describe "::getMaxLineLength()", ->
|
||||
it "returns the length of the longest screen line", ->
|
||||
expect(displayBuffer.getMaxLineLength()).toBe 65
|
||||
buffer.delete([[6, 0], [6, 65]])
|
||||
expect(displayBuffer.getMaxLineLength()).toBe 62
|
||||
|
||||
describe ".destroy()", ->
|
||||
describe "::destroy()", ->
|
||||
it "unsubscribes all display buffer markers from their underlying buffer marker (regression)", ->
|
||||
marker = displayBuffer.markBufferPosition([12, 2])
|
||||
displayBuffer.destroy()
|
||||
@@ -777,17 +777,17 @@ describe "DisplayBuffer", ->
|
||||
isValid: true
|
||||
}
|
||||
|
||||
xit "triggers the 'changed' event whenever the marker is invalidated or revalidated", ->
|
||||
it "triggers the 'changed' event whenever the marker is invalidated or revalidated", ->
|
||||
buffer.deleteRow(8)
|
||||
expect(markerChangedHandler).toHaveBeenCalled()
|
||||
expect(markerChangedHandler.argsForCall[0][0]).toEqual {
|
||||
oldHeadScreenPosition: [5, 10]
|
||||
oldHeadBufferPosition: [8, 10]
|
||||
newHeadScreenPosition: [5, 10]
|
||||
newHeadScreenPosition: [5, 0]
|
||||
newHeadBufferPosition: [8, 0]
|
||||
oldTailScreenPosition: [5, 4]
|
||||
oldTailBufferPosition: [8, 4]
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailScreenPosition: [5, 0]
|
||||
newTailBufferPosition: [8, 0]
|
||||
textChanged: true
|
||||
isValid: false
|
||||
@@ -798,12 +798,12 @@ describe "DisplayBuffer", ->
|
||||
|
||||
expect(markerChangedHandler).toHaveBeenCalled()
|
||||
expect(markerChangedHandler.argsForCall[0][0]).toEqual {
|
||||
oldHeadScreenPosition: [5, 10]
|
||||
oldHeadBufferPosition: [8, 10]
|
||||
oldHeadScreenPosition: [5, 0]
|
||||
oldHeadBufferPosition: [8, 0]
|
||||
newHeadScreenPosition: [5, 10]
|
||||
newHeadBufferPosition: [8, 10]
|
||||
oldTailScreenPosition: [5, 4]
|
||||
oldTailBufferPosition: [8, 4]
|
||||
oldTailScreenPosition: [5, 0]
|
||||
oldTailBufferPosition: [8, 0]
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
textChanged: true
|
||||
@@ -814,7 +814,7 @@ describe "DisplayBuffer", ->
|
||||
displayBuffer.createFold(10, 11)
|
||||
expect(markerChangedHandler).not.toHaveBeenCalled()
|
||||
|
||||
xit "updates markers before emitting buffer change events, but does not notify their observers until the change event", ->
|
||||
it "updates markers before emitting buffer change events, but does not notify their observers until the change event", ->
|
||||
marker2 = displayBuffer.markBufferRange([[8, 1], [8, 1]])
|
||||
marker2.on 'changed', marker2ChangedHandler = jasmine.createSpy("marker2ChangedHandler")
|
||||
displayBuffer.on 'changed', changeHandler = jasmine.createSpy("changeHandler").andCallFake -> onDisplayBufferChange()
|
||||
@@ -831,7 +831,7 @@ describe "DisplayBuffer", ->
|
||||
expect(marker.getTailScreenPosition()).toEqual [5, 7]
|
||||
expect(marker2.isValid()).toBeFalsy()
|
||||
|
||||
buffer.change([[8, 0], [8, 2]], ".....")
|
||||
buffer.setTextInRange([[8, 0], [8, 2]], ".....")
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
expect(markerChangedHandler).toHaveBeenCalled()
|
||||
expect(marker2ChangedHandler).toHaveBeenCalled()
|
||||
@@ -902,7 +902,7 @@ describe "DisplayBuffer", ->
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
expect(markerChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe ".findMarkers(attributes)", ->
|
||||
describe "::findMarkers(attributes)", ->
|
||||
it "allows the startBufferRow and endBufferRow to be specified", ->
|
||||
marker1 = displayBuffer.markBufferRange([[0, 0], [3, 0]], class: 'a')
|
||||
marker2 = displayBuffer.markBufferRange([[0, 0], [5, 0]], class: 'a')
|
||||
@@ -932,7 +932,7 @@ describe "DisplayBuffer", ->
|
||||
buffer.getMarker(marker2.id).destroy()
|
||||
expect(destroyedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "DisplayBufferMarker.copy(attributes)", ->
|
||||
describe "DisplayBufferMarker::copy(attributes)", ->
|
||||
it "creates a copy of the marker with the given attributes merged in", ->
|
||||
initialMarkerCount = displayBuffer.getMarkerCount()
|
||||
marker1 = displayBuffer.markScreenRange([[5, 4], [5, 10]], a: 1, b: 2)
|
||||
|
||||
@@ -1424,6 +1424,35 @@ describe "Editor", ->
|
||||
editor.undo()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [3,4]
|
||||
|
||||
it "indents the new line to the correct level when editor.autoIndent is true", ->
|
||||
atom.config.set('editor.autoIndent', true)
|
||||
|
||||
editor.setText(' var test')
|
||||
editor.setCursorBufferPosition([0,2])
|
||||
editor.insertNewlineAbove()
|
||||
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0,2]
|
||||
expect(editor.lineForBufferRow(0)).toBe ' '
|
||||
expect(editor.lineForBufferRow(1)).toBe ' var test'
|
||||
|
||||
editor.setText('\n var test')
|
||||
editor.setCursorBufferPosition([1,2])
|
||||
editor.insertNewlineAbove()
|
||||
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1,2]
|
||||
expect(editor.lineForBufferRow(0)).toBe ''
|
||||
expect(editor.lineForBufferRow(1)).toBe ' '
|
||||
expect(editor.lineForBufferRow(2)).toBe ' var test'
|
||||
|
||||
editor.setText('function() {\n}')
|
||||
editor.setCursorBufferPosition([1,1])
|
||||
editor.insertNewlineAbove()
|
||||
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1,2]
|
||||
expect(editor.lineForBufferRow(0)).toBe 'function() {'
|
||||
expect(editor.lineForBufferRow(1)).toBe ' '
|
||||
expect(editor.lineForBufferRow(2)).toBe '}'
|
||||
|
||||
describe ".backspace()", ->
|
||||
describe "when there is a single cursor", ->
|
||||
changeScreenRangeHandler = null
|
||||
@@ -1596,6 +1625,11 @@ describe "Editor", ->
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 13]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 34]
|
||||
|
||||
editor.setText(' var sort')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
editor.backspaceToBeginningOfWord()
|
||||
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]]])
|
||||
|
||||
@@ -432,9 +432,9 @@ describe "EditorView", ->
|
||||
editorView.setFontFamily('sans-serif')
|
||||
|
||||
it "positions the cursor to the clicked row and column", ->
|
||||
{top, left} = editorView.pixelOffsetForScreenPosition([3, 30])
|
||||
editorView.renderedLines.trigger mousedownEvent(pageX: left, pageY: top)
|
||||
expect(editor.getCursorScreenPosition()).toEqual [3, 30]
|
||||
{top, left} = editorView.pixelOffsetForScreenPosition([3, 30])
|
||||
editorView.renderedLines.trigger mousedownEvent(pageX: left, pageY: top)
|
||||
expect(editor.getCursorScreenPosition()).toEqual [3, 30]
|
||||
|
||||
describe "double-click", ->
|
||||
it "selects the word under the cursor, and expands the selection wordwise in either direction on a subsequent shift-click", ->
|
||||
@@ -464,6 +464,20 @@ describe "EditorView", ->
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 12], originalEvent: {detail: 1}, shiftKey: true)
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]]
|
||||
|
||||
it "stops selecting by word when another selection is made", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
|
||||
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.getSelectedText()).toBe "quicksort"
|
||||
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 10])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [3, 12], which: 1)
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]]
|
||||
|
||||
describe "when clicking between a word and a non-word", ->
|
||||
it "selects the word", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
|
||||
@@ -1371,7 +1385,7 @@ describe "EditorView", ->
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12)
|
||||
|
||||
buffer.change([[1,0], [3,0]], "1\n2\n3\n")
|
||||
buffer.setTextInRange([[1,0], [3,0]], "1\n2\n3\n")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 7
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12)
|
||||
@@ -1384,21 +1398,21 @@ describe "EditorView", ->
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12)
|
||||
|
||||
buffer.change([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n9\n")
|
||||
buffer.setTextInRange([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n9\n")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 7
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12)
|
||||
|
||||
describe "when the change straddles the last rendered row", ->
|
||||
it "doesn't render rows that were not previously rendered", ->
|
||||
buffer.change([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n")
|
||||
buffer.setTextInRange([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 7
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6)
|
||||
|
||||
describe "when the change the follows the last rendered row", ->
|
||||
it "does not change the rendered lines", ->
|
||||
buffer.change([[12,0], [12,0]], "12\n13\n14\n")
|
||||
buffer.setTextInRange([[12,0], [12,0]], "12\n13\n14\n")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 7
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6)
|
||||
@@ -1408,7 +1422,7 @@ describe "EditorView", ->
|
||||
setEditorWidthInChars(editorView, maxLineLength)
|
||||
widthBefore = editorView.renderedLines.width()
|
||||
expect(widthBefore).toBe editorView.scrollView.width() + 20
|
||||
buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join(''))
|
||||
buffer.setTextInRange([[12,0], [12,0]], [1..maxLineLength*2].join(''))
|
||||
expect(editorView.renderedLines.width()).toBeGreaterThan widthBefore
|
||||
|
||||
describe "when lines are removed", ->
|
||||
@@ -1418,7 +1432,7 @@ describe "EditorView", ->
|
||||
it "sets the rendered screen line's width to either the max line length or the scollView's width (whichever is greater)", ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
setEditorWidthInChars(editorView, maxLineLength)
|
||||
buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join(''))
|
||||
buffer.setTextInRange([[12,0], [12,0]], [1..maxLineLength*2].join(''))
|
||||
expect(editorView.renderedLines.width()).toBeGreaterThan editorView.scrollView.width()
|
||||
widthBefore = editorView.renderedLines.width()
|
||||
buffer.delete([[12, 0], [12, Infinity]])
|
||||
@@ -1431,7 +1445,7 @@ describe "EditorView", ->
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12)
|
||||
|
||||
buffer.change([[1,0], [2,0]], "")
|
||||
buffer.setTextInRange([[1,0], [2,0]], "")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 6
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(11)
|
||||
@@ -1443,21 +1457,21 @@ describe "EditorView", ->
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12)
|
||||
|
||||
buffer.change([[7,0], [11,0]], "1\n2\n")
|
||||
buffer.setTextInRange([[7,0], [11,0]], "1\n2\n")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 5
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(10)
|
||||
|
||||
describe "when the change straddles the last rendered row", ->
|
||||
it "renders the correct rows", ->
|
||||
buffer.change([[2,0], [7,0]], "")
|
||||
buffer.setTextInRange([[2,0], [7,0]], "")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 7
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6)
|
||||
|
||||
describe "when the change the follows the last rendered row", ->
|
||||
it "does not change the rendered lines", ->
|
||||
buffer.change([[10,0], [12,0]], "")
|
||||
buffer.setTextInRange([[10,0], [12,0]], "")
|
||||
expect(editorView.renderedLines.find(".line").length).toBe 7
|
||||
expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0)
|
||||
expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6)
|
||||
@@ -2802,7 +2816,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.keymap.bindKeys 'name', '.editor', {'escape': 'test-event'}
|
||||
atom.keymaps.bindKeys 'name', '.editor', {'escape': 'test-event'}
|
||||
testEventHandler = jasmine.createSpy("testEventHandler")
|
||||
|
||||
editorView.on 'test-event', testEventHandler
|
||||
@@ -2894,6 +2908,20 @@ describe "EditorView", ->
|
||||
for rowNumber in [1..5]
|
||||
expect(editorView.lineElementForScreenRow(rowNumber).text()).toBe buffer.lineForRow(rowNumber)
|
||||
|
||||
it "correctly calculates the position left for non-monospaced invisibles", ->
|
||||
editorView.setShowInvisibles(true)
|
||||
editorView.setInvisibles tab: '♘'
|
||||
editor.setText('\tx')
|
||||
|
||||
editorView.setFontFamily('serif')
|
||||
editorView.setFontSize(10)
|
||||
editorView.attachToDom()
|
||||
editorView.setWidthInChars(5)
|
||||
|
||||
expect(editorView.pixelPositionForScreenPosition([0, 0]).left).toEqual 0
|
||||
expect(editorView.pixelPositionForScreenPosition([0, 1]).left).toEqual 10
|
||||
expect(editorView.pixelPositionForScreenPosition([0, 2]).left).toEqual 13
|
||||
|
||||
describe "when the window is resized", ->
|
||||
it "updates the active edit session with the current soft wrap column", ->
|
||||
editorView.attachToDom()
|
||||
|
||||
+21
-4
@@ -177,6 +177,24 @@ describe "Git", ->
|
||||
status = repo.getPathStatus(filePath)
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
describe ".getDirectoryStatus(path)", ->
|
||||
[directoryPath, filePath, originalPathText] = []
|
||||
|
||||
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)
|
||||
|
||||
it "gets the status based on the files inside the directory", ->
|
||||
expect(repo.isStatusModified(repo.getDirectoryStatus(directoryPath))).toBe false
|
||||
fs.writeFileSync(filePath, 'abc')
|
||||
repo.getPathStatus(filePath)
|
||||
expect(repo.isStatusModified(repo.getDirectoryStatus(directoryPath))).toBe true
|
||||
|
||||
describe ".refreshStatus()", ->
|
||||
[newPath, modifiedPath, cleanPath, originalModifiedPathText] = []
|
||||
|
||||
@@ -203,10 +221,9 @@ describe "Git", ->
|
||||
statusHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
statuses = repo.statuses
|
||||
expect(statuses[cleanPath]).toBeUndefined()
|
||||
expect(repo.isStatusNew(statuses[newPath])).toBeTruthy()
|
||||
expect(repo.isStatusModified(statuses[modifiedPath])).toBeTruthy()
|
||||
expect(repo.getCachedPathStatus(cleanPath)).toBeUndefined()
|
||||
expect(repo.isStatusNew(repo.getCachedPathStatus(newPath))).toBeTruthy()
|
||||
expect(repo.isStatusModified(repo.getCachedPathStatus(modifiedPath))).toBeTruthy()
|
||||
|
||||
describe "buffer events", ->
|
||||
[originalContent, editor] = []
|
||||
|
||||
@@ -46,6 +46,16 @@ describe "LanguageMode", ->
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe " // var i;"
|
||||
|
||||
buffer.setText(' ')
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe " // "
|
||||
|
||||
buffer.setText (' a\n \n b')
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 2)
|
||||
expect(buffer.lineForRow(0)).toBe " // a"
|
||||
expect(buffer.lineForRow(1)).toBe " // "
|
||||
expect(buffer.lineForRow(2)).toBe " // b"
|
||||
|
||||
describe ".rowRangeForCodeFoldAtBufferRow(bufferRow)", ->
|
||||
it "returns the start/end rows of the foldable region starting at the given row", ->
|
||||
expect(languageMode.rowRangeForCodeFoldAtBufferRow(0)).toEqual [0, 12]
|
||||
@@ -178,17 +188,17 @@ describe "LanguageMode", ->
|
||||
expect(buffer.lineForRow(3)).toBe " font-weight: bold !important;"
|
||||
|
||||
it "uncomments lines with leading whitespace", ->
|
||||
buffer.change([[2, 0], [2, Infinity]], " /*width: 110%;*/")
|
||||
buffer.setTextInRange([[2, 0], [2, Infinity]], " /*width: 110%;*/")
|
||||
languageMode.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(2)).toBe " width: 110%;"
|
||||
|
||||
it "uncomments lines with trailing whitespace", ->
|
||||
buffer.change([[2, 0], [2, Infinity]], "/*width: 110%;*/ ")
|
||||
buffer.setTextInRange([[2, 0], [2, Infinity]], "/*width: 110%;*/ ")
|
||||
languageMode.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(2)).toBe "width: 110%; "
|
||||
|
||||
it "uncomments lines with leading and trailing whitespace", ->
|
||||
buffer.change([[2, 0], [2, Infinity]], " /*width: 110%;*/ ")
|
||||
buffer.setTextInRange([[2, 0], [2, Infinity]], " /*width: 110%;*/ ")
|
||||
languageMode.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(2)).toBe " width: 110%; "
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ describe "PaneContainerView", ->
|
||||
afterEach ->
|
||||
atom.deserializers.remove(TestView)
|
||||
|
||||
describe ".getActivePane()", ->
|
||||
describe ".getActivePaneView()", ->
|
||||
it "returns the most-recently focused pane", ->
|
||||
focusStealer = $$ -> @div tabindex: -1, "focus stealer"
|
||||
focusStealer.attachToDom()
|
||||
@@ -35,15 +35,15 @@ describe "PaneContainerView", ->
|
||||
|
||||
pane2.focus()
|
||||
expect(container.getFocusedPane()).toBe pane2
|
||||
expect(container.getActivePane()).toBe pane2
|
||||
expect(container.getActivePaneView()).toBe pane2
|
||||
|
||||
focusStealer.focus()
|
||||
expect(container.getFocusedPane()).toBeUndefined()
|
||||
expect(container.getActivePane()).toBe pane2
|
||||
expect(container.getActivePaneView()).toBe pane2
|
||||
|
||||
pane3.focus()
|
||||
expect(container.getFocusedPane()).toBe pane3
|
||||
expect(container.getActivePane()).toBe pane3
|
||||
expect(container.getActivePaneView()).toBe pane3
|
||||
|
||||
describe ".eachPaneView(callback)", ->
|
||||
it "runs the callback with all current and future panes until the subscription is cancelled", ->
|
||||
|
||||
+12
-54
@@ -33,21 +33,7 @@ describe "Project", ->
|
||||
deserializedProject.getBuffers()[0].destroy()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
|
||||
describe "when an edit session is destroyed", ->
|
||||
it "removes edit session and calls destroy on buffer (if buffer is not referenced by other edit sessions)", ->
|
||||
editor = atom.project.openSync("a")
|
||||
anotherEditor = atom.project.openSync("a")
|
||||
|
||||
expect(atom.project.editors.length).toBe 2
|
||||
expect(editor.buffer).toBe anotherEditor.buffer
|
||||
|
||||
editor.destroy()
|
||||
expect(atom.project.editors.length).toBe 1
|
||||
|
||||
anotherEditor.destroy()
|
||||
expect(atom.project.editors.length).toBe 0
|
||||
|
||||
describe "when an edit session is saved and the project has no path", ->
|
||||
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)
|
||||
@@ -56,73 +42,49 @@ describe "Project", ->
|
||||
editor.saveAs(tempFile)
|
||||
expect(atom.project.getPath()).toBe path.dirname(tempFile)
|
||||
|
||||
describe "when an edit session is copied", ->
|
||||
it "emits an 'editor-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
atom.project.on 'editor-created', handler
|
||||
|
||||
editor1 = atom.project.openSync("a")
|
||||
expect(handler.callCount).toBe 1
|
||||
expect(atom.project.getEditors().length).toBe 1
|
||||
expect(atom.project.getEditors()[0]).toBe editor1
|
||||
|
||||
editor2 = editor1.copy()
|
||||
expect(handler.callCount).toBe 2
|
||||
expect(atom.project.getEditors().length).toBe 2
|
||||
expect(atom.project.getEditors()[0]).toBe editor1
|
||||
expect(atom.project.getEditors()[1]).toBe editor2
|
||||
|
||||
describe ".openSync(path)", ->
|
||||
[absolutePath, newBufferHandler, newEditorHandler] = []
|
||||
[absolutePath, newBufferHandler] = []
|
||||
beforeEach ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
newBufferHandler = jasmine.createSpy('newBufferHandler')
|
||||
atom.project.on 'buffer-created', newBufferHandler
|
||||
newEditorHandler = jasmine.createSpy('newEditorHandler')
|
||||
atom.project.on 'editor-created', newEditorHandler
|
||||
|
||||
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' and 'editor-created' events", ->
|
||||
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
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
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' and 'editor-created' events", ->
|
||||
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
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when passed the path to a buffer that has already been opened", ->
|
||||
it "returns a new edit session containing previously opened buffer and emits a 'editor-created' event", ->
|
||||
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()
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when not passed a path", ->
|
||||
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
|
||||
it "returns a new edit session and emits 'buffer-created'", ->
|
||||
editor = atom.project.openSync()
|
||||
expect(editor.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe ".open(path)", ->
|
||||
[absolutePath, newBufferHandler, newEditorHandler] = []
|
||||
[absolutePath, newBufferHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
newBufferHandler = jasmine.createSpy('newBufferHandler')
|
||||
atom.project.on 'buffer-created', newBufferHandler
|
||||
newEditorHandler = jasmine.createSpy('newEditorHandler')
|
||||
atom.project.on 'editor-created', newEditorHandler
|
||||
|
||||
describe "when given an absolute path that isn't currently open", ->
|
||||
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
|
||||
it "returns a new edit session for the given path and emits 'buffer-created'", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
@@ -130,10 +92,9 @@ describe "Project", ->
|
||||
runs ->
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when given a relative path that isn't currently opened", ->
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created'", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
@@ -141,10 +102,9 @@ describe "Project", ->
|
||||
runs ->
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when passed the path to a buffer that is currently opened", ->
|
||||
it "returns a new edit session containing currently opened buffer and emits a 'editor-created' event", ->
|
||||
it "returns a new edit session containing currently opened buffer", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
@@ -154,10 +114,9 @@ describe "Project", ->
|
||||
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
|
||||
expect(atom.project.openSync('a').buffer).toBe editor.buffer
|
||||
expect(newBufferHandler).not.toHaveBeenCalled()
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when not passed a path", ->
|
||||
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
|
||||
it "returns a new edit session and emits 'buffer-created'", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
atom.project.open().then (o) -> editor = o
|
||||
@@ -165,7 +124,6 @@ describe "Project", ->
|
||||
runs ->
|
||||
expect(editor.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
it "returns number of read bytes as progress indicator", ->
|
||||
filePath = atom.project.resolve 'a'
|
||||
@@ -312,7 +270,7 @@ describe "Project", ->
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.buffer.change([[0,0],[0,0]], 'omg')
|
||||
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
results = []
|
||||
|
||||
@@ -6,8 +6,8 @@ require '../vendor/jasmine-jquery'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
Keymap = require '../src/keymap-extensions'
|
||||
{$, WorkspaceView} = require 'atom'
|
||||
KeymapManager = require '../src/keymap-extensions'
|
||||
{$, WorkspaceView, Workspace} = require 'atom'
|
||||
Config = require '../src/config'
|
||||
{Point} = require 'text-buffer'
|
||||
Project = require '../src/project'
|
||||
@@ -22,8 +22,8 @@ atom.themes.requireStylesheet '../static/jasmine'
|
||||
|
||||
fixturePackagesPath = path.resolve(__dirname, './fixtures/packages')
|
||||
atom.packages.packageDirPaths.unshift(fixturePackagesPath)
|
||||
atom.keymap.loadBundledKeymaps()
|
||||
keyBindingsToRestore = atom.keymap.getKeyBindings()
|
||||
atom.keymaps.loadBundledKeymaps()
|
||||
keyBindingsToRestore = atom.keymaps.getKeyBindings()
|
||||
|
||||
$(window).on 'core:close', -> window.close()
|
||||
$(window).on 'unload', ->
|
||||
@@ -50,7 +50,8 @@ beforeEach ->
|
||||
$.fx.off = true
|
||||
projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures')
|
||||
atom.project = new Project(path: projectPath)
|
||||
atom.keymap.keyBindings = _.clone(keyBindingsToRestore)
|
||||
atom.workspace = new Workspace()
|
||||
atom.keymaps.keyBindings = _.clone(keyBindingsToRestore)
|
||||
|
||||
window.resetTimeouts()
|
||||
atom.packages.packageStates = {}
|
||||
@@ -112,7 +113,7 @@ afterEach ->
|
||||
atom.workspaceView = null
|
||||
delete atom.state.workspace
|
||||
|
||||
atom.project?.destroy?()
|
||||
atom.project?.destroy()
|
||||
atom.project = null
|
||||
|
||||
delete atom.state.packageStates
|
||||
@@ -187,7 +188,7 @@ window.keydownEvent = (key, properties={}) ->
|
||||
originalEventProperties.cmd = properties.metaKey
|
||||
originalEventProperties.target = properties.target?[0] ? properties.target
|
||||
originalEventProperties.which = properties.which
|
||||
originalEvent = Keymap.keydownEvent(key, originalEventProperties)
|
||||
originalEvent = KeymapManager.keydownEvent(key, originalEventProperties)
|
||||
properties = $.extend({originalEvent}, properties)
|
||||
$.Event("keydown", properties)
|
||||
|
||||
@@ -278,7 +279,7 @@ $.fn.resultOfTrigger = (type) ->
|
||||
event.result
|
||||
|
||||
$.fn.enableKeymap = ->
|
||||
@on 'keydown', (e) => atom.keymap.handleKeyEvent(e)
|
||||
@on 'keydown', (e) => atom.keymaps.handleKeyEvent(e)
|
||||
|
||||
$.fn.attachToDom = ->
|
||||
@appendTo($('#jasmine-content'))
|
||||
|
||||
@@ -36,6 +36,22 @@ describe "ThemeManager", ->
|
||||
themes = themeManager.getActiveThemes()
|
||||
expect(themes).toHaveLength(names.length)
|
||||
|
||||
describe "when the core.themes config value contains invalid entry", ->
|
||||
fit "ignores theme", ->
|
||||
atom.config.set 'core.themes', [
|
||||
'atom-light-ui'
|
||||
null
|
||||
undefined
|
||||
''
|
||||
false
|
||||
4
|
||||
{}
|
||||
[]
|
||||
'atom-dark-ui'
|
||||
]
|
||||
|
||||
expect(themeManager.getEnabledThemeNames()).toEqual ['atom-dark-ui', 'atom-light-ui']
|
||||
|
||||
describe "getImportPaths()", ->
|
||||
it "returns the theme directories before the themes are loaded", ->
|
||||
atom.config.set('core.themes', ['theme-with-index-less', 'atom-dark-ui', 'atom-light-ui'])
|
||||
|
||||
@@ -119,7 +119,7 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when there is a buffer change surrounding an invalid row", ->
|
||||
it "pushes the invalid row to the end of the change", ->
|
||||
buffer.change([[4, 0], [6, 0]], "\n\n\n")
|
||||
buffer.setTextInRange([[4, 0], [6, 0]], "\n\n\n")
|
||||
changeHandler.reset()
|
||||
|
||||
expect(tokenizedBuffer.firstInvalidRow()).toBe 8
|
||||
@@ -128,7 +128,7 @@ describe "TokenizedBuffer", ->
|
||||
describe "when there is a buffer change inside an invalid region", ->
|
||||
it "does not attempt to tokenize the lines in the change, and preserves the existing invalid row", ->
|
||||
expect(tokenizedBuffer.firstInvalidRow()).toBe 5
|
||||
buffer.change([[6, 0], [7, 0]], "\n\n\n")
|
||||
buffer.setTextInRange([[6, 0], [7, 0]], "\n\n\n")
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(6).ruleStack?).toBeFalsy()
|
||||
expect(tokenizedBuffer.lineForScreenRow(7).ruleStack?).toBeFalsy()
|
||||
@@ -143,7 +143,7 @@ describe "TokenizedBuffer", ->
|
||||
describe "when there is a buffer change that is smaller than the chunk size", ->
|
||||
describe "when lines are updated, but none are added or removed", ->
|
||||
it "updates tokens to reflect the change", ->
|
||||
buffer.change([[0, 0], [2, 0]], "foo()\n7\n")
|
||||
buffer.setTextInRange([[0, 0], [2, 0]], "foo()\n7\n")
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.brace.round.js'])
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.js'])
|
||||
@@ -185,7 +185,7 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when lines are both updated and removed", ->
|
||||
it "updates tokens to reflect the change", ->
|
||||
buffer.change([[1, 0], [3, 0]], "foo()")
|
||||
buffer.setTextInRange([[1, 0], [3, 0]], "foo()")
|
||||
|
||||
# previous line 0 remains
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
@@ -209,7 +209,7 @@ describe "TokenizedBuffer", ->
|
||||
buffer.insert([5, 30], '/* */')
|
||||
changeHandler.reset()
|
||||
|
||||
buffer.change([[2, 0], [3, 0]], '/*')
|
||||
buffer.setTextInRange([[2, 0], [3, 0]], '/*')
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
|
||||
expect(tokenizedBuffer.lineForScreenRow(3).tokens[0].scopes).toEqual ['source.js']
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
@@ -228,7 +228,7 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when lines are both updated and inserted", ->
|
||||
it "updates tokens to reflect the change", ->
|
||||
buffer.change([[1, 0], [2, 0]], "foo()\nbar()\nbaz()\nquux()")
|
||||
buffer.setTextInRange([[1, 0], [2, 0]], "foo()\nbar()\nbaz()\nquux()")
|
||||
|
||||
# previous line 0 remains
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
|
||||
@@ -102,7 +102,7 @@ describe "Window", ->
|
||||
it "unsubscribes from all buffers", ->
|
||||
atom.workspaceView.openSync('sample.js')
|
||||
buffer = atom.workspaceView.getActivePaneItem().buffer
|
||||
pane = atom.workspaceView.getActivePane()
|
||||
pane = atom.workspaceView.getActivePaneView()
|
||||
pane.splitRight(pane.copyActiveItem())
|
||||
expect(atom.workspaceView.find('.editor').length).toBe 2
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ describe "Workspace", ->
|
||||
|
||||
beforeEach ->
|
||||
atom.project.setPath(atom.project.resolve('dir'))
|
||||
workspace = new Workspace
|
||||
atom.workspace = workspace = new Workspace
|
||||
|
||||
describe "::open(uri, options)", ->
|
||||
beforeEach ->
|
||||
@@ -152,6 +152,18 @@ describe "Workspace", ->
|
||||
workspace.open("bar://baz").then (item) ->
|
||||
expect(item).toEqual { bar: "bar://baz" }
|
||||
|
||||
it "emits an 'editor-created' event", ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
newEditorHandler = jasmine.createSpy('newEditorHandler')
|
||||
workspace.on 'editor-created', newEditorHandler
|
||||
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
workspace.open(absolutePath).then (e) -> editor = e
|
||||
|
||||
runs ->
|
||||
expect(newEditorHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "::openSync(uri, options)", ->
|
||||
[activePane, initialItemCount] = []
|
||||
|
||||
@@ -245,3 +257,26 @@ describe "Workspace", ->
|
||||
it "opens the license as plain-text in a buffer", ->
|
||||
waitsForPromise -> workspace.openLicense()
|
||||
runs -> expect(workspace.activePaneItem.getText()).toMatch /Copyright/
|
||||
|
||||
describe "when an editor is destroyed", ->
|
||||
it "removes the editor", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
workspace.open("a").then (e) -> editor = e
|
||||
|
||||
runs ->
|
||||
expect(workspace.getEditors()).toHaveLength 1
|
||||
editor.destroy()
|
||||
expect(workspace.getEditors()).toHaveLength 0
|
||||
|
||||
describe "when an editor is copied", ->
|
||||
it "emits an 'editor-created' event", ->
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
workspace.on 'editor-created', handler
|
||||
|
||||
editor1 = workspace.openSync("a")
|
||||
expect(handler.callCount).toBe 1
|
||||
|
||||
editor2 = editor1.copy()
|
||||
expect(handler.callCount).toBe 2
|
||||
|
||||
@@ -36,18 +36,18 @@ describe "WorkspaceView", ->
|
||||
editorView1 = atom.workspaceView.getActiveView()
|
||||
buffer = editorView1.getEditor().getBuffer()
|
||||
editorView1.splitRight()
|
||||
expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
|
||||
simulateReload()
|
||||
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 2
|
||||
expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPaneViews()[1]
|
||||
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", ->
|
||||
atom.workspaceView.attachToDom()
|
||||
pane1 = atom.workspaceView.getActivePane()
|
||||
pane1 = atom.workspaceView.getActivePaneView()
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitRight()
|
||||
pane4 = pane2.splitDown()
|
||||
@@ -89,7 +89,7 @@ describe "WorkspaceView", ->
|
||||
|
||||
describe "where there are no open editors", ->
|
||||
it "constructs the view with no open editors", ->
|
||||
atom.workspaceView.getActivePane().remove()
|
||||
atom.workspaceView.getActivePaneView().remove()
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 0
|
||||
simulateReload()
|
||||
expect(atom.workspaceView.getEditorViews().length).toBe 0
|
||||
@@ -99,7 +99,7 @@ describe "WorkspaceView", ->
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
it "hands off focus to the active pane", ->
|
||||
activePane = atom.workspaceView.getActivePane()
|
||||
activePane = atom.workspaceView.getActivePaneView()
|
||||
$('body').focus()
|
||||
expect(activePane.hasFocus()).toBe false
|
||||
atom.workspaceView.focus()
|
||||
@@ -111,7 +111,7 @@ describe "WorkspaceView", ->
|
||||
commandHandler = jasmine.createSpy('commandHandler')
|
||||
atom.workspaceView.on('foo-command', commandHandler)
|
||||
|
||||
atom.keymap.bindKeys('name', '*', 'x': 'foo-command')
|
||||
atom.keymaps.bindKeys('name', '*', 'x': 'foo-command')
|
||||
|
||||
describe "when a keydown event is triggered in the WorkspaceView", ->
|
||||
it "triggers matching keybindings for that event", ->
|
||||
@@ -132,30 +132,30 @@ describe "WorkspaceView", ->
|
||||
|
||||
describe "when there is an active pane item", ->
|
||||
it "sets the title to the pane item's title plus the project path", ->
|
||||
item = atom.workspaceView.getActivePaneItem()
|
||||
item = atom.workspaceView.getActivePaneViewItem()
|
||||
expect(atom.workspaceView.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
describe "when the title of the active pane item changes", ->
|
||||
it "updates the window title based on the item's new title", ->
|
||||
editor = atom.workspaceView.getActivePaneItem()
|
||||
editor = atom.workspaceView.getActivePaneViewItem()
|
||||
editor.buffer.setPath(path.join(temp.dir, 'hi'))
|
||||
expect(atom.workspaceView.title).toBe "#{editor.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
describe "when the active pane's item changes", ->
|
||||
it "updates the title to the new item's title plus the project path", ->
|
||||
atom.workspaceView.getActivePane().showNextItem()
|
||||
item = atom.workspaceView.getActivePaneItem()
|
||||
atom.workspaceView.getActivePaneView().showNextItem()
|
||||
item = atom.workspaceView.getActivePaneViewItem()
|
||||
expect(atom.workspaceView.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
describe "when the last pane item is removed", ->
|
||||
it "updates the title to contain the project's path", ->
|
||||
atom.workspaceView.getActivePane().remove()
|
||||
expect(atom.workspaceView.getActivePaneItem()).toBeUndefined()
|
||||
atom.workspaceView.getActivePaneView().remove()
|
||||
expect(atom.workspaceView.getActivePaneViewItem()).toBeUndefined()
|
||||
expect(atom.workspaceView.title).toBe atom.project.getPath()
|
||||
|
||||
describe "when an inactive pane's item changes", ->
|
||||
it "does not update the title", ->
|
||||
pane = atom.workspaceView.getActivePane()
|
||||
pane = atom.workspaceView.getActivePaneView()
|
||||
pane.splitRight()
|
||||
initialTitle = atom.workspaceView.title
|
||||
pane.showNextItem()
|
||||
@@ -164,7 +164,7 @@ describe "WorkspaceView", ->
|
||||
describe "when the root view is deserialized", ->
|
||||
it "updates the title to contain the project's path", ->
|
||||
workspaceView2 = new WorkspaceView(atom.workspace.testSerialization())
|
||||
item = atom.workspaceView.getActivePaneItem()
|
||||
item = atom.workspaceView.getActivePaneViewItem()
|
||||
expect(workspaceView2.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
workspaceView2.remove()
|
||||
|
||||
@@ -238,9 +238,9 @@ describe "WorkspaceView", ->
|
||||
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.getActivePane().getItems()).toHaveLength 1
|
||||
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 1
|
||||
atom.workspaceView.trigger('core:close')
|
||||
expect(atom.workspaceView.getActivePane().getItems()).toHaveLength 0
|
||||
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 0
|
||||
|
||||
describe "the scrollbar visibility class", ->
|
||||
it "has a class based on the style of the scrollbar", ->
|
||||
|
||||
+36
-25
@@ -1,6 +1,5 @@
|
||||
crypto = require 'crypto'
|
||||
ipc = require 'ipc'
|
||||
keytar = require 'keytar'
|
||||
os = require 'os'
|
||||
path = require 'path'
|
||||
remote = require 'remote'
|
||||
@@ -8,6 +7,7 @@ screen = require 'screen'
|
||||
shell = require 'shell'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{deprecated} = require 'grim'
|
||||
{Model} = require 'theorist'
|
||||
fs = require 'fs-plus'
|
||||
|
||||
@@ -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.keymap` - A {Keymap} instance
|
||||
# * `atom.keymaps` - A {Keymap} instance
|
||||
# * `atom.menu` - A {MenuManager} instance
|
||||
# * `atom.packages` - A {PackageManager} instance
|
||||
# * `atom.project` - A {Project} instance
|
||||
@@ -132,6 +132,7 @@ class Atom extends Model
|
||||
initialize: ->
|
||||
window.onerror = =>
|
||||
@openDevTools()
|
||||
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
|
||||
@emit 'uncaught-error', arguments...
|
||||
|
||||
@unsubscribe()
|
||||
@@ -140,7 +141,7 @@ class Atom extends Model
|
||||
@loadTime = null
|
||||
|
||||
Config = require './config'
|
||||
Keymap = require './keymap-extensions'
|
||||
KeymapManager = require './keymap-extensions'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
Syntax = require './syntax'
|
||||
@@ -157,7 +158,8 @@ class Atom extends Model
|
||||
process.env.NODE_PATH = exportsPath
|
||||
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymap = new Keymap({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath})
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath})
|
||||
@contextMenu = new ContextMenuManager(devMode)
|
||||
@@ -179,9 +181,11 @@ class Atom extends Model
|
||||
|
||||
# Deprecated: Callers should be converted to use atom.deserializers
|
||||
registerRepresentationClass: ->
|
||||
deprecated("Callers should be converted to use atom.deserializers")
|
||||
|
||||
# Deprecated: Callers should be converted to use atom.deserializers
|
||||
registerRepresentationClasses: ->
|
||||
deprecated("Callers should be converted to use atom.deserializers")
|
||||
|
||||
setBodyPlatformClass: ->
|
||||
document.body.classList.add("platform-#{process.platform}")
|
||||
@@ -218,12 +222,26 @@ class Atom extends Model
|
||||
else
|
||||
@center()
|
||||
|
||||
storeDefaultWindowDimensions: ->
|
||||
dimensions = JSON.stringify(atom.getWindowDimensions())
|
||||
localStorage.setItem("defaultWindowDimensions", dimensions)
|
||||
|
||||
getDefaultWindowDimensions: ->
|
||||
{windowDimensions} = @getLoadSettings()
|
||||
return windowDimensions if windowDimensions?
|
||||
|
||||
dimensions = null
|
||||
try
|
||||
dimensions = JSON.parse(localStorage.getItem("defaultWindowDimensions"))
|
||||
catch error
|
||||
console.warn "Error parsing default window dimensions", error
|
||||
localStorage.removeItem("defaultWindowDimensions")
|
||||
|
||||
{width, height} = screen.getPrimaryDisplay().workAreaSize
|
||||
dimensions ? {x: 0, y: 0, width: Math.min(1024, width), height: height}
|
||||
|
||||
restoreWindowDimensions: ->
|
||||
workAreaSize = screen.getPrimaryDisplay().workAreaSize
|
||||
windowDimensions = @state.windowDimensions ? {}
|
||||
{initialSize} = @getLoadSettings()
|
||||
windowDimensions.height ?= initialSize?.height ? workAreaSize.height
|
||||
windowDimensions.width ?= initialSize?.width ? Math.min(workAreaSize.width, 1024)
|
||||
windowDimensions = @state.windowDimensions ? @getDefaultWindowDimensions()
|
||||
@setWindowDimensions(windowDimensions)
|
||||
|
||||
storeWindowDimensions: ->
|
||||
@@ -244,7 +262,7 @@ class Atom extends Model
|
||||
WorkspaceView = require './workspace-view'
|
||||
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
|
||||
@workspaceView = new WorkspaceView(@workspace)
|
||||
@keymap.defaultTarget = @workspaceView[0]
|
||||
@keymaps.defaultTarget = @workspaceView[0]
|
||||
$(@workspaceViewParentSelector).append(@workspaceView)
|
||||
|
||||
deserializePackageStates: ->
|
||||
@@ -269,12 +287,12 @@ class Atom extends Model
|
||||
@config.load()
|
||||
@config.setDefaults('core', require('./workspace-view').configDefaults)
|
||||
@config.setDefaults('editor', require('./editor-view').configDefaults)
|
||||
@keymap.loadBundledKeymaps()
|
||||
@keymaps.loadBundledKeymaps()
|
||||
@themes.loadBaseStylesheets()
|
||||
@packages.loadPackages()
|
||||
@deserializeEditorWindow()
|
||||
@packages.activate()
|
||||
@keymap.loadUserKeymap()
|
||||
@keymaps.loadUserKeymap()
|
||||
@requireUserInitScript()
|
||||
@menu.update()
|
||||
|
||||
@@ -298,7 +316,7 @@ class Atom extends Model
|
||||
@workspaceView = null
|
||||
@project.destroy()
|
||||
@windowEventHandler?.unsubscribe()
|
||||
@keymap.destroy()
|
||||
@keymaps.destroy()
|
||||
@windowState = null
|
||||
|
||||
loadThemes: ->
|
||||
@@ -379,6 +397,10 @@ class Atom extends Model
|
||||
toggleDevTools: ->
|
||||
ipc.sendChannel('call-window-method', 'toggleDevTools')
|
||||
|
||||
# Public: Execute code in dev tools.
|
||||
executeJavaScriptInDevTools: (code) ->
|
||||
ipc.sendChannel('call-window-method', 'executeJavaScriptInDevTools', code)
|
||||
|
||||
# Public: Reload the current window.
|
||||
reload: ->
|
||||
ipc.sendChannel('call-window-method', 'restart')
|
||||
@@ -431,7 +453,7 @@ class Atom extends Model
|
||||
exit: (status) ->
|
||||
app = remote.require('app')
|
||||
app.emit('will-exit')
|
||||
app.exit(status)
|
||||
remote.process.exit(status)
|
||||
|
||||
# Public: Is the current window in development mode?
|
||||
inDevMode: ->
|
||||
@@ -461,17 +483,6 @@ class Atom extends Model
|
||||
isReleasedVersion: ->
|
||||
@constructor.isReleasedVersion()
|
||||
|
||||
getGitHubAuthTokenName: ->
|
||||
'Atom GitHub API Token'
|
||||
|
||||
# Public: Set the the github token in the keychain
|
||||
setGitHubAuthToken: (token) ->
|
||||
keytar.replacePassword(@getGitHubAuthTokenName(), 'github', token)
|
||||
|
||||
# Public: Get the github token from the keychain
|
||||
getGitHubAuthToken: ->
|
||||
keytar.getPassword(@getGitHubAuthTokenName(), 'github')
|
||||
|
||||
# Public: Get the directory path to Atom's configuration area.
|
||||
#
|
||||
# Returns the absolute path to ~/.atom
|
||||
|
||||
@@ -9,30 +9,28 @@ _ = require 'underscore-plus'
|
||||
# and maintain the state of all menu items.
|
||||
module.exports =
|
||||
class ApplicationMenu
|
||||
version: null
|
||||
menu: null
|
||||
|
||||
constructor: (@version) ->
|
||||
@menu = Menu.buildFromTemplate @getDefaultTemplate()
|
||||
Menu.setApplicationMenu @menu
|
||||
global.atomApplication.autoUpdateManager.on 'state-changed', (state) =>
|
||||
@showUpdateMenuItem(state)
|
||||
|
||||
# Public: Updates the entire menu with the given keybindings.
|
||||
#
|
||||
# * template:
|
||||
# The Object which describes the menu to display.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystroke.
|
||||
# template - The Object which describes the menu to display.
|
||||
# keystrokesByCommand - An Object where the keys are commands and the values
|
||||
# are Arrays containing the keystroke.
|
||||
update: (template, keystrokesByCommand) ->
|
||||
@translateTemplate(template, keystrokesByCommand)
|
||||
@substituteVersion(template)
|
||||
@menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(@menu)
|
||||
|
||||
@showUpdateMenuItem(global.atomApplication.autoUpdateManager.getState())
|
||||
|
||||
# Flattens the given menu and submenu items into an single Array.
|
||||
#
|
||||
# * menu:
|
||||
# A complete menu configuration object for atom-shell's menu API.
|
||||
# menu - A complete menu configuration object for atom-shell's menu API.
|
||||
#
|
||||
# Returns an Array of native menu items.
|
||||
flattenMenuItems: (menu) ->
|
||||
@@ -44,8 +42,7 @@ class ApplicationMenu
|
||||
|
||||
# Flattens the given menu template into an single Array.
|
||||
#
|
||||
# * template:
|
||||
# An object describing the menu item.
|
||||
# template - An object describing the menu item.
|
||||
#
|
||||
# Returns an Array of native menu items.
|
||||
flattenMenuTemplate: (template) ->
|
||||
@@ -57,44 +54,36 @@ class ApplicationMenu
|
||||
|
||||
# Public: Used to make all window related menu items are active.
|
||||
#
|
||||
# * enable:
|
||||
# If true enables all window specific items, if false disables all window
|
||||
# specific items.
|
||||
# enable - If true enables all window specific items, if false disables all
|
||||
# window specific items.
|
||||
enableWindowSpecificItems: (enable) ->
|
||||
for item in @flattenMenuItems(@menu)
|
||||
item.enabled = enable if item.metadata?['windowSpecific']
|
||||
|
||||
# Replaces VERSION with the current version.
|
||||
substituteVersion: (template) ->
|
||||
if (item = _.find(@flattenMenuTemplate(template), (i) -> i.label == 'VERSION'))
|
||||
if (item = _.find(@flattenMenuTemplate(template), ({label}) -> label == 'VERSION'))
|
||||
item.label = "Version #{@version}"
|
||||
|
||||
# Toggles Install Update Item
|
||||
showInstallUpdateItem: (visible=true) ->
|
||||
if visible
|
||||
@showDownloadingUpdateItem(false)
|
||||
@showCheckForUpdateItem(false)
|
||||
# Sets the proper visible state the update menu items
|
||||
showUpdateMenuItem: (state) ->
|
||||
checkForUpdateItem = _.find(@flattenMenuItems(@menu), ({label}) -> label == 'Check for Update')
|
||||
downloadingUpdateItem = _.find(@flattenMenuItems(@menu), ({label}) -> label == 'Downloading Update')
|
||||
installUpdateItem = _.find(@flattenMenuItems(@menu), ({label}) -> label == 'Restart and Install Update')
|
||||
|
||||
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Restart and Install Update'))
|
||||
item.visible = visible
|
||||
return unless checkForUpdateItem? and downloadingUpdateItem? and installUpdateItem?
|
||||
|
||||
# Toggles Downloading Update Item
|
||||
showDownloadingUpdateItem: (visible=true) ->
|
||||
if visible
|
||||
@showInstallUpdateItem(false)
|
||||
@showCheckForUpdateItem(false)
|
||||
checkForUpdateItem.visible = false
|
||||
downloadingUpdateItem.visible = false
|
||||
installUpdateItem.visible = false
|
||||
|
||||
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Downloading Update'))
|
||||
item.visible = visible
|
||||
|
||||
# Toggles Check For Update Item
|
||||
showCheckForUpdateItem: (visible=true) ->
|
||||
if visible
|
||||
@showDownloadingUpdateItem(false)
|
||||
@showInstallUpdateItem(false)
|
||||
|
||||
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Check for Update'))
|
||||
item.visible = visible
|
||||
switch state
|
||||
when 'idle', 'error', 'no-update-available'
|
||||
checkForUpdateItem.visible = true
|
||||
when 'checking', 'downloading'
|
||||
downloadingUpdateItem.visible = true
|
||||
when 'update-available'
|
||||
installUpdateItem.visible = true
|
||||
|
||||
# Default list of menu items.
|
||||
#
|
||||
@@ -103,26 +92,28 @@ class ApplicationMenu
|
||||
[
|
||||
label: "Atom"
|
||||
submenu: [
|
||||
{ label: 'Reload', accelerator: 'Command+R', click: -> @focusedWindow()?.reload() }
|
||||
{ label: 'Close Window', accelerator: 'Command+Shift+W', click: -> @focusedWindow()?.close() }
|
||||
{ label: 'Toggle Dev Tools', accelerator: 'Command+Alt+I', click: -> @focusedWindow()?.toggleDevTools() }
|
||||
{ label: "Check for Update", metadata: {autoUpdate: true}}
|
||||
{ label: 'Reload', accelerator: 'Command+R', click: => @focusedWindow()?.reload() }
|
||||
{ label: 'Close Window', accelerator: 'Command+Shift+W', click: => @focusedWindow()?.close() }
|
||||
{ label: 'Toggle Dev Tools', accelerator: 'Command+Alt+I', click: => @focusedWindow()?.toggleDevTools() }
|
||||
{ label: 'Quit', accelerator: 'Command+Q', click: -> app.quit() }
|
||||
]
|
||||
]
|
||||
|
||||
focusedWindow: ->
|
||||
_.find global.atomApplication.windows, (atomWindow) -> atomWindow.isFocused()
|
||||
|
||||
# Combines a menu template with the appropriate keystroke.
|
||||
#
|
||||
# * template:
|
||||
# An Object conforming to atom-shell's menu api but lacking accelerator and
|
||||
# click properties.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystroke.
|
||||
# template - An Object conforming to atom-shell's menu api but lacking
|
||||
# accelerator and click properties.
|
||||
# keystrokesByCommand - An Object where the keys are commands and the values
|
||||
# are Arrays containing the keystroke.
|
||||
#
|
||||
# Returns a complete menu configuration object for atom-shell's menu API.
|
||||
translateTemplate: (template, keystrokesByCommand) ->
|
||||
template.forEach (item) =>
|
||||
item.metadata = {}
|
||||
item.metadata ?= {}
|
||||
if item.command
|
||||
item.accelerator = @acceleratorForCommand(item.command, keystrokesByCommand)
|
||||
item.click = => global.atomApplication.sendCommand(item.command)
|
||||
@@ -132,11 +123,9 @@ class ApplicationMenu
|
||||
|
||||
# Determine the accelerator for a given command.
|
||||
#
|
||||
# * command:
|
||||
# The name of the command.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystroke.
|
||||
# command - The name of the command.
|
||||
# keystrokesByCommand - An Object where the keys are commands and the values
|
||||
# are Arrays containing the keystroke.
|
||||
#
|
||||
# Returns a String containing the keystroke in a format that can be interpreted
|
||||
# by atom shell to provide nice icons where available.
|
||||
@@ -147,7 +136,6 @@ class ApplicationMenu
|
||||
modifiers = firstKeystroke.split('-')
|
||||
key = modifiers.pop()
|
||||
|
||||
modifiers.push("Shift") if key != key.toLowerCase()
|
||||
modifiers = modifiers.map (modifier) ->
|
||||
modifier.replace(/shift/ig, "Shift")
|
||||
.replace(/cmd/ig, "Command")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
AtomWindow = require './atom-window'
|
||||
ApplicationMenu = require './application-menu'
|
||||
AtomProtocolHandler = require './atom-protocol-handler'
|
||||
AutoUpdateManager = require './auto-update-manager'
|
||||
BrowserWindow = require 'browser-window'
|
||||
Menu = require 'menu'
|
||||
autoUpdater = require 'auto-updater'
|
||||
app = require 'app'
|
||||
dialog = require 'dialog'
|
||||
fs = require 'fs'
|
||||
@@ -66,13 +66,13 @@ class AtomApplication
|
||||
@pathsToOpen ?= []
|
||||
@windows = []
|
||||
|
||||
@autoUpdateManager = new AutoUpdateManager(@version)
|
||||
@applicationMenu = new ApplicationMenu(@version)
|
||||
@atomProtocolHandler = new AtomProtocolHandler(@resourcePath)
|
||||
|
||||
@listenForArgumentsFromNewProcess()
|
||||
@setupJavaScriptArguments()
|
||||
@handleEvents()
|
||||
@setupAutoUpdater()
|
||||
|
||||
@openWithOptions(options)
|
||||
|
||||
@@ -96,6 +96,8 @@ class AtomApplication
|
||||
addWindow: (window) ->
|
||||
@windows.push window
|
||||
@applicationMenu?.enableWindowSpecificItems(true)
|
||||
window.once 'window:loaded', =>
|
||||
@autoUpdateManager.emitUpdateAvailableEvent(window)
|
||||
|
||||
# Creates server to listen for additional atom application launches.
|
||||
#
|
||||
@@ -125,68 +127,38 @@ class AtomApplication
|
||||
|
||||
# Configures required javascript environment flags.
|
||||
setupJavaScriptArguments: ->
|
||||
app.commandLine.appendSwitch 'js-flags', '--harmony_collections --harmony-proxies'
|
||||
|
||||
# Enable updates unless running from a local build of Atom.
|
||||
setupAutoUpdater: ->
|
||||
return if /\w{7}/.test(@version) # Only released versions should check for updates.
|
||||
|
||||
autoUpdater.setFeedUrl "https://atom.io/api/updates?version=#{@version}"
|
||||
|
||||
autoUpdater.on 'checking-for-update', =>
|
||||
@applicationMenu.showDownloadingUpdateItem(false)
|
||||
@applicationMenu.showInstallUpdateItem(false)
|
||||
@applicationMenu.showCheckForUpdateItem(false)
|
||||
|
||||
autoUpdater.on 'update-not-available', =>
|
||||
@applicationMenu.showCheckForUpdateItem(true)
|
||||
|
||||
autoUpdater.on 'update-available', =>
|
||||
@applicationMenu.showDownloadingUpdateItem(true)
|
||||
|
||||
autoUpdater.on 'update-downloaded', (event, releaseNotes, releaseVersion, releaseDate, releaseURL) =>
|
||||
atomWindow.sendCommand('window:update-available', [releaseVersion, releaseNotes]) for atomWindow in @windows
|
||||
@applicationMenu.showInstallUpdateItem(true)
|
||||
|
||||
autoUpdater.on 'error', (event, message) =>
|
||||
@applicationMenu.showCheckForUpdateItem(true)
|
||||
|
||||
# Check for update after Atom has fully started and the menus are created
|
||||
setTimeout((-> autoUpdater.checkForUpdates()), 5000)
|
||||
|
||||
checkForUpdate: ->
|
||||
@onUpdateNotAvailable ?= =>
|
||||
autoUpdater.removeListener 'error', @onUpdateError
|
||||
dialog.showMessageBox type: 'info', buttons: ['OK'], message: 'No update available.', detail: "Version #{@version} is the latest version."
|
||||
|
||||
@onUpdateError ?= (event, message) =>
|
||||
autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable
|
||||
dialog.showMessageBox type: 'warning', buttons: ['OK'], message: 'There was an error checking for updates.', detail: message
|
||||
|
||||
autoUpdater.once 'update-not-available', @onUpdateNotAvailable
|
||||
autoUpdater.once 'error', @onUpdateError
|
||||
autoUpdater.checkForUpdates()
|
||||
app.commandLine.appendSwitch 'js-flags', '--harmony'
|
||||
|
||||
# Registers basic application commands, non-idempotent.
|
||||
handleEvents: ->
|
||||
@on 'application:about', -> Menu.sendActionToFirstResponder('orderFrontStandardAboutPanel:')
|
||||
@on 'application:run-all-specs', -> @runSpecs(exitWhenDone: false, resourcePath: global.devResourcePath)
|
||||
@on 'application:run-benchmarks', -> @runBenchmarks()
|
||||
@on 'application:quit', -> app.quit()
|
||||
@on 'application:hide', -> Menu.sendActionToFirstResponder('hide:')
|
||||
@on 'application:hide-other-applications', -> Menu.sendActionToFirstResponder('hideOtherApplications:')
|
||||
@on 'application:unhide-all-applications', -> Menu.sendActionToFirstResponder('unhideAllApplications:')
|
||||
@on 'application:new-window', -> @openPath(initialSize: @getFocusedWindowSize())
|
||||
@on 'application:new-window', -> @openPath(windowDimensions: @focusedWindow()?.getDimensions())
|
||||
@on 'application:new-file', -> (@focusedWindow() ? this).openPath()
|
||||
@on 'application:open', -> @promptForPath()
|
||||
@on 'application:open', -> @promptForPath(type: 'all')
|
||||
@on 'application:open-file', -> @promptForPath(type: 'file')
|
||||
@on 'application:open-folder', -> @promptForPath(type: 'folder')
|
||||
@on 'application:open-dev', -> @promptForPath(devMode: true)
|
||||
@on 'application:minimize', -> Menu.sendActionToFirstResponder('performMiniaturize:')
|
||||
@on 'application:zoom', -> Menu.sendActionToFirstResponder('zoom:')
|
||||
@on 'application:bring-all-windows-to-front', -> Menu.sendActionToFirstResponder('arrangeInFront:')
|
||||
@on 'application:inspect', ({x,y}) -> @focusedWindow().browserWindow.inspectElement(x, y)
|
||||
@on 'application:inspect', ({x,y, atomWindow}) ->
|
||||
atomWindow ?= @focusedWindow()
|
||||
atomWindow?.browserWindow.inspectElement(x, y)
|
||||
|
||||
@on 'application:open-documentation', -> shell.openExternal('https://atom.io/docs/latest/?app')
|
||||
@on 'application:install-update', -> autoUpdater.quitAndInstall()
|
||||
@on 'application:check-for-update', => @checkForUpdate()
|
||||
@on 'application:install-update', -> @autoUpdateManager.install()
|
||||
@on 'application:check-for-update', => @autoUpdateManager.check()
|
||||
|
||||
if process.platform is 'darwin'
|
||||
@on 'application:about', -> Menu.sendActionToFirstResponder('orderFrontStandardAboutPanel:')
|
||||
@on 'application:bring-all-windows-to-front', -> Menu.sendActionToFirstResponder('arrangeInFront:')
|
||||
@on 'application:hide', -> Menu.sendActionToFirstResponder('hide:')
|
||||
@on 'application:hide-other-applications', -> Menu.sendActionToFirstResponder('hideOtherApplications:')
|
||||
@on 'application:minimize', -> Menu.sendActionToFirstResponder('performMiniaturize:')
|
||||
@on 'application:unhide-all-applications', -> Menu.sendActionToFirstResponder('unhideAllApplications:')
|
||||
@on 'application:zoom', -> Menu.sendActionToFirstResponder('zoom:')
|
||||
else
|
||||
@on 'application:minimize', -> @focusedWindow()?.minimize()
|
||||
@on 'application:zoom', -> @focusedWindow()?.maximize()
|
||||
|
||||
@openPathOnEvent('application:show-settings', 'atom://config')
|
||||
@openPathOnEvent('application:open-your-config', 'atom://.atom/config')
|
||||
@@ -214,6 +186,10 @@ class AtomApplication
|
||||
event.preventDefault()
|
||||
@openUrl({urlToOpen, @devMode})
|
||||
|
||||
app.on 'activate-with-no-open-windows', (event) =>
|
||||
event.preventDefault()
|
||||
@emit('application:new-window')
|
||||
|
||||
# A request from the associated render process to open a new render process.
|
||||
ipc.on 'open', (processId, routingId, options) =>
|
||||
if options?
|
||||
@@ -245,10 +221,8 @@ class AtomApplication
|
||||
#
|
||||
# If it isn't handled globally, delegate to the currently focused window.
|
||||
#
|
||||
# * command:
|
||||
# The string representing the command.
|
||||
# * args:
|
||||
# The optional arguments to pass along.
|
||||
# command - The string representing the command.
|
||||
# args - The optional arguments to pass along.
|
||||
sendCommand: (command, args...) ->
|
||||
unless @emit(command, args...)
|
||||
focusedWindow = @focusedWindow()
|
||||
@@ -257,6 +231,18 @@ class AtomApplication
|
||||
else
|
||||
@sendCommandToFirstResponder(command)
|
||||
|
||||
# Public: Executes the given command on the given window.
|
||||
#
|
||||
# command - The string representing the command.
|
||||
# atomWindow - The {AtomWindow} to send the command to.
|
||||
# args - The optional arguments to pass along.
|
||||
sendCommandToWindow: (command, atomWindow, args...) ->
|
||||
unless @emit(command, args...)
|
||||
if atomWindow?
|
||||
atomWindow.sendCommand(command, args...)
|
||||
else
|
||||
@sendCommandToFirstResponder(command)
|
||||
|
||||
# Translates the command into OS X action and sends it to application's first
|
||||
# responder.
|
||||
sendCommandToFirstResponder: (command) ->
|
||||
@@ -277,8 +263,8 @@ class AtomApplication
|
||||
#
|
||||
# A new window will be created if there is no currently focused window.
|
||||
#
|
||||
# * eventName: The event to listen for.
|
||||
# * pathToOpen: The path to open when the event is triggered.
|
||||
# eventName - The event to listen for.
|
||||
# pathToOpen - The path to open when the event is triggered.
|
||||
openPathOnEvent: (eventName, pathToOpen) ->
|
||||
@on eventName, ->
|
||||
if window = @focusedWindow()
|
||||
@@ -295,45 +281,25 @@ class AtomApplication
|
||||
focusedWindow: ->
|
||||
_.find @windows, (atomWindow) -> atomWindow.isFocused()
|
||||
|
||||
# Public: Get the height and width of the focused window.
|
||||
#
|
||||
# Returns an object with height and width keys or null if there is no
|
||||
# focused window.
|
||||
getFocusedWindowSize: ->
|
||||
if focusedWindow = @focusedWindow()
|
||||
[width, height] = focusedWindow.getSize()
|
||||
{width, height}
|
||||
else
|
||||
null
|
||||
|
||||
# Public: Opens multiple paths, in existing windows if possible.
|
||||
#
|
||||
# * options
|
||||
# + pathsToOpen:
|
||||
# The array of file paths to open
|
||||
# + pidToKillWhenClosed:
|
||||
# The integer of the pid to kill
|
||||
# + newWindow:
|
||||
# Boolean of whether this should be opened in a new window.
|
||||
# + devMode:
|
||||
# Boolean to control the opened window's dev mode.
|
||||
# options -
|
||||
# :pathsToOpen - The array of file paths to open
|
||||
# :pidToKillWhenClosed - The integer of the pid to kill
|
||||
# :newWindow - Boolean of whether this should be opened in a new window.
|
||||
# :devMode - Boolean to control the opened window's dev mode.
|
||||
openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode}) ->
|
||||
@openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode}) for pathToOpen in pathsToOpen ? []
|
||||
|
||||
# Public: Opens a single path, in an existing window if possible.
|
||||
#
|
||||
# * options
|
||||
# + pathToOpen:
|
||||
# The file path to open
|
||||
# + pidToKillWhenClosed:
|
||||
# The integer of the pid to kill
|
||||
# + newWindow:
|
||||
# Boolean of whether this should be opened in a new window.
|
||||
# + devMode:
|
||||
# Boolean to control the opened window's dev mode.
|
||||
# + initialSize:
|
||||
# Object with height and width keys.
|
||||
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, initialSize}={}) ->
|
||||
# options -
|
||||
# :pathToOpen - The file path to open
|
||||
# :pidToKillWhenClosed - The integer of the pid to kill
|
||||
# :newWindow - Boolean of whether this should be opened in a new window.
|
||||
# :devMode - Boolean to control the opened window's dev mode.
|
||||
# :windowDimensions - Object with height and width keys.
|
||||
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, windowDimensions}={}) ->
|
||||
if pathToOpen
|
||||
[basename, initialLine] = path.basename(pathToOpen).split(':')
|
||||
if initialLine
|
||||
@@ -353,7 +319,7 @@ class AtomApplication
|
||||
|
||||
bootstrapScript ?= require.resolve('../window-bootstrap')
|
||||
resourcePath ?= @resourcePath
|
||||
openedWindow = new AtomWindow({pathToOpen, initialLine, bootstrapScript, resourcePath, devMode, initialSize})
|
||||
openedWindow = new AtomWindow({pathToOpen, initialLine, bootstrapScript, resourcePath, devMode, windowDimensions})
|
||||
|
||||
if pidToKillWhenClosed?
|
||||
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
|
||||
@@ -385,11 +351,9 @@ class AtomApplication
|
||||
# responsible for opening the URL. A new window will be created with
|
||||
# that package's `urlMain` as the bootstrap script.
|
||||
#
|
||||
# * options
|
||||
# + urlToOpen:
|
||||
# The atom:// url to open.
|
||||
# + devMode:
|
||||
# Boolean to control the opened window's dev mode.
|
||||
# options -
|
||||
# :urlToOpen - The atom:// url to open.
|
||||
# :devMode - Boolean to control the opened window's dev mode.
|
||||
openUrl: ({urlToOpen, devMode}) ->
|
||||
unless @packages?
|
||||
PackageManager = require '../package-manager'
|
||||
@@ -405,7 +369,8 @@ class AtomApplication
|
||||
if pack.urlMain
|
||||
packagePath = @packages.resolvePackagePath(packageName)
|
||||
bootstrapScript = path.resolve(packagePath, pack.urlMain)
|
||||
new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen, initialSize: @getFocusedWindowSize()})
|
||||
windowDimensions = @focusedWindow()?.getDimensions()
|
||||
new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen, windowDimensions})
|
||||
else
|
||||
console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}"
|
||||
else
|
||||
@@ -413,13 +378,11 @@ class AtomApplication
|
||||
|
||||
# Opens up a new {AtomWindow} to run specs within.
|
||||
#
|
||||
# * options
|
||||
# + exitWhenDone:
|
||||
# A Boolean that if true, will close the window upon completion.
|
||||
# + resourcePath:
|
||||
# The path to include specs from.
|
||||
# + specPath:
|
||||
# The directory to load specs from.
|
||||
# options -
|
||||
# :exitWhenDone - A Boolean that if true, will close the window upon
|
||||
# completion.
|
||||
# :resourcePath - The path to include specs from.
|
||||
# :specPath - The directory to load specs from.
|
||||
runSpecs: ({exitWhenDone, resourcePath, specDirectory, logFile}) ->
|
||||
if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath)
|
||||
resourcePath = @resourcePath
|
||||
@@ -446,10 +409,18 @@ class AtomApplication
|
||||
#
|
||||
# Once paths are selected, they're opened in a new or existing {AtomWindow}s.
|
||||
#
|
||||
# * options
|
||||
# + devMode:
|
||||
# A Boolean which controls whether any newly opened windows should be in
|
||||
# dev mode or not.
|
||||
promptForPath: ({devMode}={}) ->
|
||||
dialog.showOpenDialog title: 'Open', properties: ['openFile', 'openDirectory', 'multiSelections', 'createDirectory'], (pathsToOpen) =>
|
||||
# options -
|
||||
# :type - A String which specifies the type of the dialog, could be 'file',
|
||||
# 'folder' or 'all'. The 'all' is only available on OS X.
|
||||
# :devMode - A Boolean which controls whether any newly opened windows
|
||||
# should be in dev mode or not.
|
||||
promptForPath: ({type, devMode}={}) ->
|
||||
type ?= 'all'
|
||||
properties =
|
||||
switch type
|
||||
when 'file' then ['openFile']
|
||||
when 'folder' then ['openDirectory']
|
||||
when 'all' then ['openFile', 'openDirectory']
|
||||
else throw new Error("#{type} is an invalid type for promptForPath")
|
||||
dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) =>
|
||||
@openPaths({pathsToOpen, devMode})
|
||||
|
||||
@@ -7,9 +7,12 @@ path = require 'path'
|
||||
fs = require 'fs'
|
||||
url = require 'url'
|
||||
_ = require 'underscore-plus'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
module.exports =
|
||||
class AtomWindow
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
|
||||
@iconPath: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
@includeShellLoadTime: true
|
||||
|
||||
@@ -38,7 +41,10 @@ class AtomWindow
|
||||
loadSettings.initialPath = path.dirname(pathToOpen)
|
||||
|
||||
@browserWindow.loadSettings = loadSettings
|
||||
@browserWindow.once 'window:loaded', => @loaded = true
|
||||
@browserWindow.once 'window:loaded', =>
|
||||
@emit 'window:loaded'
|
||||
@loaded = true
|
||||
|
||||
@browserWindow.loadUrl @getUrl(loadSettings)
|
||||
@browserWindow.focusOnWebView() if @isSpec
|
||||
|
||||
@@ -101,7 +107,7 @@ class AtomWindow
|
||||
when 1 then @browserWindow.restart()
|
||||
|
||||
@browserWindow.on 'context-menu', (menuTemplate) =>
|
||||
new ContextMenu(menuTemplate, @browserWindow)
|
||||
new ContextMenu(menuTemplate, this)
|
||||
|
||||
if @isSpec
|
||||
# Spec window's web view should always have focus
|
||||
@@ -132,11 +138,18 @@ class AtomWindow
|
||||
action = if args[0]?.contextCommand then 'context-command' else 'command'
|
||||
ipc.sendChannel @browserWindow.getProcessId(), @browserWindow.getRoutingId(), action, command, args...
|
||||
|
||||
getDimensions: ->
|
||||
[x, y] = @browserWindow.getPosition()
|
||||
[width, height] = @browserWindow.getSize()
|
||||
{x, y, width, height}
|
||||
|
||||
close: -> @browserWindow.close()
|
||||
|
||||
focus: -> @browserWindow.focus()
|
||||
|
||||
getSize: -> @browserWindow.getSize()
|
||||
minimize: -> @browserWindow.minimize()
|
||||
|
||||
maximize: -> @browserWindow.maximize()
|
||||
|
||||
handlesAtomCommands: ->
|
||||
not @isSpecWindow() and @isWebViewFocused()
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
autoUpdater = require 'auto-updater'
|
||||
dialog = require 'dialog'
|
||||
_ = require 'underscore-plus'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
IDLE_STATE='idle'
|
||||
CHECKING_STATE='checking'
|
||||
DOWNLOADING_STATE='downloading'
|
||||
UPDATE_AVAILABLE_STATE='update-available'
|
||||
NO_UPDATE_AVAILABLE_STATE='no-update-available'
|
||||
ERROR_STATE='error'
|
||||
|
||||
module.exports =
|
||||
class AutoUpdateManager
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
|
||||
constructor: (@version) ->
|
||||
@state = IDLE_STATE
|
||||
|
||||
# Only released versions should check for updates.
|
||||
return if /\w{7}/.test(@version)
|
||||
|
||||
autoUpdater.setFeedUrl "https://atom.io/api/updates?version=#{@version}"
|
||||
|
||||
autoUpdater.on 'checking-for-update', =>
|
||||
@setState(CHECKING_STATE)
|
||||
|
||||
autoUpdater.on 'update-not-available', =>
|
||||
@setState(NO_UPDATE_AVAILABLE_STATE)
|
||||
|
||||
autoUpdater.on 'update-available', =>
|
||||
@setState(DOWNLOADING_STATE)
|
||||
|
||||
autoUpdater.on 'error', (event, message) =>
|
||||
@setState(ERROR_STATE)
|
||||
console.error "Error Downloading Update: #{message}"
|
||||
|
||||
autoUpdater.on 'update-downloaded', (event, @releaseNotes, @releaseVersion) =>
|
||||
@setState(UPDATE_AVAILABLE_STATE)
|
||||
@emitUpdateAvailableEvent(@getWindows()...)
|
||||
|
||||
@check(hidePopups: true)
|
||||
|
||||
emitUpdateAvailableEvent: (windows...) ->
|
||||
return unless @releaseVersion? and @releaseNotes
|
||||
for atomWindow in windows
|
||||
atomWindow.sendCommand('window:update-available', [@releaseVersion, @releaseNotes])
|
||||
|
||||
setState: (state) ->
|
||||
return unless @state != state
|
||||
@state = state
|
||||
@emit 'state-changed', @state
|
||||
|
||||
getState: ->
|
||||
@state
|
||||
|
||||
check: ({hidePopups}={})->
|
||||
unless hidePopups
|
||||
autoUpdater.once 'update-not-available', @onUpdateNotAvailable
|
||||
autoUpdater.once 'error', @onUpdateError
|
||||
|
||||
autoUpdater.checkForUpdates()
|
||||
|
||||
install: ->
|
||||
autoUpdater.quitAndInstall()
|
||||
|
||||
onUpdateNotAvailable: =>
|
||||
autoUpdater.removeListener 'error', @onUpdateError
|
||||
dialog.showMessageBox type: 'info', buttons: ['OK'], message: 'No update available.', detail: "Version #{@version} is the latest version."
|
||||
|
||||
onUpdateError: (event, message) =>
|
||||
autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable
|
||||
dialog.showMessageBox type: 'warning', buttons: ['OK'], message: 'There was an error checking for updates.', detail: message
|
||||
|
||||
getWindows: ->
|
||||
global.atomApplication.windows
|
||||
@@ -2,10 +2,10 @@ Menu = require 'menu'
|
||||
|
||||
module.exports =
|
||||
class ContextMenu
|
||||
constructor: (template, browserWindow) ->
|
||||
constructor: (template, @atomWindow) ->
|
||||
template = @createClickHandlers(template)
|
||||
menu = Menu.buildFromTemplate(template)
|
||||
menu.popup(browserWindow)
|
||||
menu.popup(@atomWindow.browserWindow)
|
||||
|
||||
# It's necessary to build the event handlers in this process, otherwise
|
||||
# closures are drug across processes and failed to be garbage collected
|
||||
@@ -13,7 +13,10 @@ class ContextMenu
|
||||
createClickHandlers: (template) ->
|
||||
for item in template
|
||||
if item.command
|
||||
(item.commandOptions ?= {}).contextCommand = true
|
||||
item.click = do (item) ->
|
||||
=> global.atomApplication.sendCommand(item.command, item.commandOptions)
|
||||
item.commandOptions ?= {}
|
||||
item.commandOptions.contextCommand = true
|
||||
item.commandOptions.atomWindow = @atomWindow
|
||||
do (item) =>
|
||||
item.click = =>
|
||||
global.atomApplication.sendCommandToWindow(item.command, @atomWindow, item.commandOptions)
|
||||
item
|
||||
|
||||
@@ -1,33 +1,29 @@
|
||||
crypto = require 'crypto'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
os = require 'os'
|
||||
|
||||
CoffeeScript = require 'coffee-script'
|
||||
CSON = require 'season'
|
||||
mkdir = require('mkdirp').sync
|
||||
fs = require 'fs-plus'
|
||||
|
||||
tmpDir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
|
||||
cacheDir = path.join(tmpDir, 'atom-compile-cache')
|
||||
cacheDir = path.join(fs.getHomeDirectory(), 'compile-cache')
|
||||
coffeeCacheDir = path.join(cacheDir, 'coffee')
|
||||
CSON.setCacheDir(path.join(cacheDir, 'cson'))
|
||||
|
||||
getCachePath = (coffee) ->
|
||||
digest = crypto.createHash('sha1').update(coffee, 'utf8').digest('hex')
|
||||
path.join(coffeeCacheDir, "#{digest}.coffee")
|
||||
path.join(coffeeCacheDir, "#{digest}.js")
|
||||
|
||||
getCachedJavaScript = (cachePath) ->
|
||||
if stat = fs.statSyncNoException(cachePath)
|
||||
if fs.isFileSync(cachePath)
|
||||
try
|
||||
fs.readFileSync(cachePath, 'utf8') if stat.isFile()
|
||||
fs.readFileSync(cachePath, 'utf8')
|
||||
|
||||
compileCoffeeScript = (coffee, filePath, cachePath) ->
|
||||
{js,v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
|
||||
{js, v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
|
||||
# Include source map in the web page environment.
|
||||
if btoa? and JSON? and unescape? and encodeURIComponent?
|
||||
js = "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=#{filePath}"
|
||||
try
|
||||
mkdir(path.dirname(cachePath))
|
||||
fs.writeFileSync(cachePath, js)
|
||||
js
|
||||
|
||||
|
||||
+41
-20
@@ -18,9 +18,9 @@ pathWatcher = require 'pathwatcher'
|
||||
# ## Example
|
||||
#
|
||||
# ```coffeescript
|
||||
# atom.config.set('myplugin.key', 'value')
|
||||
# atom.config.observe 'myplugin.key', ->
|
||||
# console.log 'My configuration changed:', atom.config.get('myplugin.key')
|
||||
# atom.config.set('my-package.key', 'value')
|
||||
# atom.config.observe 'my-package.key', ->
|
||||
# console.log 'My configuration changed:', atom.config.get('my-package.key')
|
||||
# ```
|
||||
module.exports =
|
||||
class Config
|
||||
@@ -86,9 +86,9 @@ class Config
|
||||
hash = hash[key]
|
||||
|
||||
_.extend hash, defaults
|
||||
@update()
|
||||
@emit 'updated'
|
||||
|
||||
# Public: Get the path to the config file being used.
|
||||
# Public: Get the {String} path to the config file being used.
|
||||
getUserConfigPath: ->
|
||||
@configFilePath
|
||||
|
||||
@@ -98,10 +98,10 @@ class Config
|
||||
|
||||
# Public: Retrieves the setting for the given key.
|
||||
#
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
# keyPath - The {String} name of the key to retrieve.
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `null` if the key doesn't exist in either.
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
# file, or `null` if the key doesn't exist in either.
|
||||
get: (keyPath) ->
|
||||
value = _.valueForKeyPath(@settings, keyPath) ? _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
_.deepClone(value)
|
||||
@@ -110,8 +110,8 @@ class Config
|
||||
#
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `NaN` if the key doesn't exist in either.
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
# file, or `NaN` if the key doesn't exist in either.
|
||||
getInt: (keyPath) ->
|
||||
parseInt(@get(keyPath))
|
||||
|
||||
@@ -121,8 +121,8 @@ class Config
|
||||
# defaultValue - The integer {Number} to fall back to if the value isn't
|
||||
# positive, defaults to 0.
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `defaultValue` if the key value isn't greater than zero.
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
# file, or `defaultValue` if the key value isn't greater than zero.
|
||||
getPositiveInt: (keyPath, defaultValue=0) ->
|
||||
Math.max(@getInt(keyPath), 0) or defaultValue
|
||||
|
||||
@@ -130,13 +130,14 @@ class Config
|
||||
#
|
||||
# This value is stored in Atom's internal configuration file.
|
||||
#
|
||||
# keyPath - The {String} name of the key
|
||||
# value - The value of the setting
|
||||
# keyPath - The {String} name of the key.
|
||||
# value - The value of the setting.
|
||||
#
|
||||
# Returns the `value`.
|
||||
set: (keyPath, value) ->
|
||||
if @get(keyPath) != value
|
||||
value = undefined if _.valueForKeyPath(@defaultSettings, keyPath) == value
|
||||
if @get(keyPath) isnt value
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
value = undefined if _.isEqual(defaultValue, value)
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
@update()
|
||||
value
|
||||
@@ -146,6 +147,8 @@ class Config
|
||||
# The new value will be `true` if the value is currently falsy and will be
|
||||
# `false` if the value is currently truthy.
|
||||
#
|
||||
# keyPath - The {String} name of the key.
|
||||
#
|
||||
# Returns the new value.
|
||||
toggle: (keyPath) ->
|
||||
@set(keyPath, !@get(keyPath))
|
||||
@@ -158,12 +161,30 @@ class Config
|
||||
restoreDefault: (keyPath) ->
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
|
||||
# Public: Get the default value of the key path.
|
||||
#
|
||||
# keyPath - The {String} name of the key.
|
||||
#
|
||||
# Returns the default value.
|
||||
getDefault: (keyPath) ->
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
_.deepClone(defaultValue)
|
||||
|
||||
# Public: Is the key path value its default value?
|
||||
#
|
||||
# keyPath - The {String} name of the key.
|
||||
#
|
||||
# Returns a {Boolean}, `true` if the current value is the default, `false`
|
||||
# otherwise.
|
||||
isDefault: (keyPath) ->
|
||||
not _.valueForKeyPath(@settings, keyPath)?
|
||||
|
||||
# Public: Push the value to the array at the key path.
|
||||
#
|
||||
# keyPath - The {String} key path.
|
||||
# value - The value to push to the array.
|
||||
#
|
||||
# Returns the new array length of the setting.
|
||||
# Returns the new array length {Number} of the setting.
|
||||
pushAtKeyPath: (keyPath, value) ->
|
||||
arrayValue = @get(keyPath) ? []
|
||||
result = arrayValue.push(value)
|
||||
@@ -175,7 +196,7 @@ class Config
|
||||
# keyPath - The {String} key path.
|
||||
# value - The value to shift onto the array.
|
||||
#
|
||||
# Returns the new array length of the setting.
|
||||
# Returns the new array length {Number} of the setting.
|
||||
unshiftAtKeyPath: (keyPath, value) ->
|
||||
arrayValue = @get(keyPath) ? []
|
||||
result = arrayValue.unshift(value)
|
||||
@@ -225,9 +246,9 @@ class Config
|
||||
callback(value) if options.callNow ? true
|
||||
subscription
|
||||
|
||||
# Public: Unobserve all callbacks on a given key
|
||||
# Public: Unobserve all callbacks on a given key.
|
||||
#
|
||||
# keyPath - The {String} name of the key to unobserve
|
||||
# keyPath - The {String} name of the key to unobserve.
|
||||
unobserve: (keyPath) ->
|
||||
@off("updated.#{keyPath.replace(/\./, '-')}")
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class ContextMenuManager
|
||||
label: 'Inspect Element'
|
||||
command: 'application:inspect'
|
||||
executeAtBuild: (e) ->
|
||||
@.commandOptions = x: e.pageX, y: e.pageY
|
||||
@commandOptions = x: e.pageX, y: e.pageY
|
||||
]
|
||||
|
||||
# Public: Creates menu definitions from the object specified by the menu
|
||||
|
||||
+9
-2
@@ -315,12 +315,14 @@ class Cursor
|
||||
# :includeNonWordCharacters - A {Boolean} indicating whether to include
|
||||
# non-word characters in the default word regex.
|
||||
# Has no effect if wordRegex is set.
|
||||
# :allowPrevious - A {Boolean} indicating whether the beginning of the
|
||||
# previous word can be returned.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getBeginningOfCurrentWordBufferPosition: (options = {}) ->
|
||||
allowPrevious = options.allowPrevious ? true
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row) ? 0
|
||||
scanRange = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
|
||||
beginningOfWordPosition = null
|
||||
@@ -330,7 +332,12 @@ class Cursor
|
||||
if not beginningOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
beginningOfWordPosition or currentBufferPosition
|
||||
if beginningOfWordPosition?
|
||||
beginningOfWordPosition
|
||||
else if allowPrevious
|
||||
new Point(0, 0)
|
||||
else
|
||||
currentBufferPosition
|
||||
|
||||
# Public: Retrieves buffer position of previous word boundary. It might be on
|
||||
# the current word, or the previous word.
|
||||
|
||||
@@ -140,10 +140,10 @@ class DisplayBufferMarker
|
||||
@bufferMarker.isDestroyed()
|
||||
|
||||
getAttributes: ->
|
||||
@bufferMarker.getAttributes()
|
||||
@bufferMarker.getProperties()
|
||||
|
||||
setAttributes: (attributes) ->
|
||||
@bufferMarker.setAttributes(attributes)
|
||||
@bufferMarker.setProperties(attributes)
|
||||
|
||||
matchesAttributes: (attributes) ->
|
||||
attributes = @displayBuffer.translateToBufferMarkerParams(attributes)
|
||||
|
||||
@@ -493,8 +493,8 @@ class DisplayBuffer extends Model
|
||||
# options - Options to pass to the {Marker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markBufferRange: (args...) ->
|
||||
@getMarker(@buffer.markRange(args...).id)
|
||||
markBufferRange: (range, options) ->
|
||||
@getMarker(@buffer.markRange(range, options).id)
|
||||
|
||||
# Public: Constructs a new marker at the given screen position.
|
||||
#
|
||||
|
||||
+20
-15
@@ -50,7 +50,7 @@ class EditorView extends View
|
||||
showLineNumbers: true
|
||||
autoIndent: true
|
||||
normalizeIndentOnPaste: true
|
||||
nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?-"
|
||||
nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
|
||||
preferredLineLength: 80
|
||||
tabLength: 2
|
||||
softWrap: false
|
||||
@@ -343,7 +343,6 @@ class EditorView extends View
|
||||
@subscribe atom.config.observe 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily)
|
||||
@subscribe atom.config.observe 'editor.lineHeight', (lineHeight) => @setLineHeight(lineHeight)
|
||||
|
||||
|
||||
handleEvents: ->
|
||||
@on 'focus', =>
|
||||
@hiddenInput.focus()
|
||||
@@ -528,7 +527,7 @@ class EditorView extends View
|
||||
|
||||
if @editor
|
||||
@saveScrollPositionForEditor()
|
||||
@editor.off(".editor")
|
||||
@unsubscribe(@editor)
|
||||
|
||||
@editor = editor
|
||||
|
||||
@@ -536,34 +535,34 @@ class EditorView extends View
|
||||
|
||||
@editor.setVisible(true)
|
||||
|
||||
@editor.on "destroyed", =>
|
||||
@subscribe @editor, "destroyed", =>
|
||||
@remove()
|
||||
|
||||
@editor.on "contents-conflicted.editor", =>
|
||||
@subscribe @editor, "contents-conflicted", =>
|
||||
@showBufferConflictAlert(@editor)
|
||||
|
||||
@editor.on "path-changed.editor", =>
|
||||
@subscribe @editor, "path-changed", =>
|
||||
@editor.reloadGrammar()
|
||||
@trigger 'editor:path-changed'
|
||||
|
||||
@editor.on "grammar-changed.editor", =>
|
||||
@subscribe @editor, "grammar-changed", =>
|
||||
@trigger 'editor:grammar-changed'
|
||||
|
||||
@editor.on 'selection-added.editor', (selection) =>
|
||||
@subscribe @editor, 'selection-added', (selection) =>
|
||||
@newCursors.push(selection.cursor)
|
||||
@newSelections.push(selection)
|
||||
@requestDisplayUpdate()
|
||||
|
||||
@editor.on 'screen-lines-changed.editor', (e) =>
|
||||
@subscribe @editor, 'screen-lines-changed', (e) =>
|
||||
@handleScreenLinesChange(e)
|
||||
|
||||
@editor.on 'scroll-top-changed.editor', (scrollTop) =>
|
||||
@subscribe @editor, 'scroll-top-changed', (scrollTop) =>
|
||||
@scrollTop(scrollTop)
|
||||
|
||||
@editor.on 'scroll-left-changed.editor', (scrollLeft) =>
|
||||
@subscribe @editor, 'scroll-left-changed', (scrollLeft) =>
|
||||
@scrollLeft(scrollLeft)
|
||||
|
||||
@editor.on 'soft-wrap-changed.editor', (softWrap) =>
|
||||
@subscribe @editor, 'soft-wrap-changed', (softWrap) =>
|
||||
@setSoftWrap(softWrap)
|
||||
|
||||
@trigger 'editor:path-changed'
|
||||
@@ -750,11 +749,14 @@ class EditorView extends View
|
||||
# Returns a {String} identifying the CSS `font-family`.
|
||||
getFontFamily: -> @css("font-family")
|
||||
|
||||
# Public: Sets the line height of the editor
|
||||
# Public: Sets the line height of the editor.
|
||||
#
|
||||
# Calling this method has no effect when called on a mini editor.
|
||||
#
|
||||
# lineHeight - A {Number} without a unit suffix identifying the CSS
|
||||
# `line-height`.
|
||||
setLineHeight: (lineHeight) ->
|
||||
return if @mini
|
||||
@css('line-height', lineHeight)
|
||||
@redraw()
|
||||
|
||||
@@ -1335,14 +1337,17 @@ class EditorView extends View
|
||||
return 0 if screenColumn == 0
|
||||
|
||||
tokenizedLine = @editor.displayBuffer.lineForRow(screenRow)
|
||||
textContent = lineElement.textContent
|
||||
|
||||
left = 0
|
||||
index = 0
|
||||
for token in tokenizedLine.tokens
|
||||
for char in token.value
|
||||
for bufferChar in token.value
|
||||
return left if index >= screenColumn
|
||||
|
||||
val = @getCharacterWidthCache(token.scopes, char)
|
||||
# Invisibles might cause renderedChar to be different than bufferChar
|
||||
renderedChar = textContent[index]
|
||||
val = @getCharacterWidthCache(token.scopes, renderedChar)
|
||||
if val?
|
||||
left += val
|
||||
else
|
||||
|
||||
+28
-12
@@ -2,6 +2,7 @@ _ = require 'underscore-plus'
|
||||
path = require 'path'
|
||||
Serializable = require 'serializable'
|
||||
Delegator = require 'delegato'
|
||||
{deprecate} = require 'grim'
|
||||
{Model} = require 'theorist'
|
||||
{Point, Range} = require 'text-buffer'
|
||||
LanguageMode = require './language-mode'
|
||||
@@ -181,7 +182,7 @@ class Editor extends Model
|
||||
@subscribe @$scrollTop, (scrollTop) => @emit 'scroll-top-changed', scrollTop
|
||||
@subscribe @$scrollLeft, (scrollLeft) => @emit 'scroll-left-changed', scrollLeft
|
||||
|
||||
atom.project.addEditor(this) if registerEditor
|
||||
atom.workspace?.editorAdded(this) if registerEditor
|
||||
|
||||
serializeParams: ->
|
||||
id: @id
|
||||
@@ -224,19 +225,17 @@ class Editor extends Model
|
||||
@buffer.release()
|
||||
@displayBuffer.destroy()
|
||||
@languageMode.destroy()
|
||||
atom.project?.removeEditor(this)
|
||||
|
||||
# Create an {Editor} with its initial state based on this object
|
||||
copy: ->
|
||||
tabLength = @getTabLength()
|
||||
displayBuffer = @displayBuffer.copy()
|
||||
softTabs = @getSoftTabs()
|
||||
newEditor = new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true})
|
||||
newEditor = new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true, registerEditor: true})
|
||||
newEditor.setScrollTop(@getScrollTop())
|
||||
newEditor.setScrollLeft(@getScrollLeft())
|
||||
for marker in @findMarkers(editorId: @id)
|
||||
marker.copy(editorId: newEditor.id, preserveFolds: true)
|
||||
atom.project.addEditor(newEditor)
|
||||
newEditor
|
||||
|
||||
# Public: Get the title the editor's title for display in other parts of the
|
||||
@@ -382,7 +381,7 @@ class Editor extends Model
|
||||
else
|
||||
endColumn = @lineForBufferRow(bufferRow).match(/^\s*/)[0].length
|
||||
newIndentString = @buildIndentString(newLevel)
|
||||
@buffer.change([[bufferRow, 0], [bufferRow, endColumn]], newIndentString)
|
||||
@buffer.setTextInRange([[bufferRow, 0], [bufferRow, endColumn]], newIndentString)
|
||||
|
||||
# Public: Get the indentation level of the given line of text.
|
||||
#
|
||||
@@ -457,8 +456,8 @@ class Editor extends Model
|
||||
# {Delegates to: TextBuffer.nextNonBlankRow}
|
||||
nextNonBlankBufferRow: (bufferRow) -> @buffer.nextNonBlankRow(bufferRow)
|
||||
|
||||
# {Delegates to: TextBuffer.getEofPosition}
|
||||
getEofBufferPosition: -> @buffer.getEofPosition()
|
||||
# {Delegates to: TextBuffer.getEndPosition}
|
||||
getEofBufferPosition: -> @buffer.getEndPosition()
|
||||
|
||||
# Public: Returns a {Number} representing the last zero-indexed buffer row
|
||||
# number of the editor.
|
||||
@@ -622,11 +621,20 @@ class Editor extends Model
|
||||
# Public: For each cursor, insert a newline at the end of the preceding line.
|
||||
insertNewlineAbove: ->
|
||||
@transact =>
|
||||
onFirstLine = @getCursorBufferPosition().row is 0
|
||||
bufferRow = @getCursorBufferPosition().row
|
||||
indentLevel = @indentationForBufferRow(bufferRow)
|
||||
onFirstLine = bufferRow is 0
|
||||
|
||||
@moveCursorToBeginningOfLine()
|
||||
@moveCursorLeft()
|
||||
@insertNewline()
|
||||
@moveCursorUp() if onFirstLine
|
||||
|
||||
if @shouldAutoIndent() and @indentationForBufferRow(bufferRow) < indentLevel
|
||||
@setIndentationForBufferRow(bufferRow, indentLevel)
|
||||
|
||||
if onFirstLine
|
||||
@moveCursorUp()
|
||||
@moveCursorToEndOfLine()
|
||||
|
||||
# Indent all lines intersecting selections. See {Selection::indent} for more
|
||||
# information.
|
||||
@@ -905,7 +913,7 @@ class Editor extends Model
|
||||
for foldedRow in foldedRows when 0 <= foldedRow <= @getLastBufferRow()
|
||||
@foldBufferRow(foldedRow)
|
||||
|
||||
@setSelectedBufferRange(selection.translate([-insertDelta]), preserveFolds: true)
|
||||
@setSelectedBufferRange(selection.translate([-insertDelta]), preserveFolds: true, autoscroll: true)
|
||||
|
||||
# Move lines intersecting the most recent selection down by one row in screen
|
||||
# coordinates.
|
||||
@@ -961,7 +969,7 @@ class Editor extends Model
|
||||
for foldedRow in foldedRows when 0 <= foldedRow <= @getLastBufferRow()
|
||||
@foldBufferRow(foldedRow)
|
||||
|
||||
@setSelectedBufferRange(selection.translate([insertDelta]), preserveFolds: true)
|
||||
@setSelectedBufferRange(selection.translate([insertDelta]), preserveFolds: true, autoscroll: true)
|
||||
|
||||
# Duplicate the most recent cursor's current line.
|
||||
duplicateLines: ->
|
||||
@@ -991,8 +999,15 @@ class Editor extends Model
|
||||
|
||||
# Deprecated: Use {::duplicateLines} instead.
|
||||
duplicateLine: ->
|
||||
deprecate("Use Editor::duplicateLines() instead")
|
||||
@duplicateLines()
|
||||
|
||||
# Public: Mutate the text of all the selections in a single transaction.
|
||||
#
|
||||
# All the changes made inside the given {Function} can be reverted with a
|
||||
# single call to {::undo}.
|
||||
#
|
||||
# fn - A {Function} that will be called with each {Selection}.
|
||||
mutateSelectedText: (fn) ->
|
||||
@transact => fn(selection) for selection in @getSelections()
|
||||
|
||||
@@ -1333,7 +1348,7 @@ class Editor extends Model
|
||||
# text - A {String}
|
||||
#
|
||||
# Returns the {Range} of the newly-inserted text.
|
||||
setTextInBufferRange: (range, text) -> @getBuffer().change(range, text)
|
||||
setTextInBufferRange: (range, text) -> @getBuffer().setTextInRange(range, text)
|
||||
|
||||
# Public: Get the {Range} of the paragraph surrounding the most recently added
|
||||
# cursor.
|
||||
@@ -1758,4 +1773,5 @@ class Editor extends Model
|
||||
|
||||
# Deprecated: Call {::joinLines} instead.
|
||||
joinLine: ->
|
||||
deprecate("Use Editor::joinLines() instead")
|
||||
@joinLines()
|
||||
|
||||
+24
-8
@@ -1,9 +1,12 @@
|
||||
{join, sep} = require 'path'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
Task = require './task'
|
||||
{Emitter, Subscriber} = require 'emissary'
|
||||
fs = require 'fs-plus'
|
||||
GitUtils = require 'git-utils'
|
||||
|
||||
Task = require './task'
|
||||
|
||||
# Public: Represents the underlying git operations performed by Atom.
|
||||
#
|
||||
# This class shouldn't be instantiated directly but instead by accessing the
|
||||
@@ -68,6 +71,9 @@ class Git
|
||||
|
||||
@statuses = {}
|
||||
@upstream = {ahead: 0, behind: 0}
|
||||
for submodulePath, submoduleRepo of @repo.submodules
|
||||
submoduleRepo.upstream = {ahead: 0, behind: 0}
|
||||
|
||||
{@project, refreshOnWindowFocus} = options
|
||||
|
||||
refreshOnWindowFocus ?= true
|
||||
@@ -125,13 +131,14 @@ class Git
|
||||
# Returns a {Number} representing the status. This value can be passed to
|
||||
# {::isStatusModified} or {::isStatusNew} to get more information.
|
||||
getPathStatus: (path) ->
|
||||
currentPathStatus = @statuses[path] ? 0
|
||||
repo = @getRepo(path)
|
||||
relativePath = @relativize(path)
|
||||
currentPathStatus = @statuses[relativePath] ? 0
|
||||
pathStatus = repo.getStatus(repo.relativize(path)) ? 0
|
||||
if pathStatus > 0
|
||||
@statuses[path] = pathStatus
|
||||
@statuses[relativePath] = pathStatus
|
||||
else
|
||||
delete @statuses[path]
|
||||
delete @statuses[relativePath]
|
||||
if currentPathStatus isnt pathStatus
|
||||
@emit 'status-changed', path, pathStatus
|
||||
pathStatus
|
||||
@@ -222,12 +229,14 @@ class Git
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isSubmodule: (path) ->
|
||||
return false unless path
|
||||
|
||||
repo = @getRepo(path)
|
||||
if repo.isSubmodule(repo.relativize(path))
|
||||
true
|
||||
else
|
||||
# Check if the path is a working directory in a repo that isn't the root.
|
||||
path is repo.getWorkingDirectory() and repo isnt @getRepo()
|
||||
repo isnt @getRepo() and repo.relativize(join(path, 'dir')) is 'dir'
|
||||
|
||||
# Public: Get the status of a directory in the repository's working directory.
|
||||
#
|
||||
@@ -236,8 +245,7 @@ class Git
|
||||
# Returns a {Number} representing the status. This value can be passed to
|
||||
# {::isStatusModified} or {::isStatusNew} to get more information.
|
||||
getDirectoryStatus: (directoryPath) ->
|
||||
{sep} = require 'path'
|
||||
directoryPath = "#{directoryPath}#{sep}"
|
||||
directoryPath = "#{@relativize(directoryPath)}#{sep}"
|
||||
directoryStatus = 0
|
||||
for path, status of @statuses
|
||||
directoryStatus |= status if path.indexOf(directoryPath) is 0
|
||||
@@ -322,6 +330,14 @@ class Git
|
||||
getCachedUpstreamAheadBehindCount: (path) ->
|
||||
@getRepo(path).upstream ? @upstream
|
||||
|
||||
# Public: Get the cached status for the given path.
|
||||
#
|
||||
# path - A {String} path in the repository, relative or absolute.
|
||||
#
|
||||
# Returns a status {Number} or null if the path is not in the cache.
|
||||
getCachedPathStatus: (path) ->
|
||||
@statuses[@relativize(path)]
|
||||
|
||||
# Public: Returns true if the given branch exists.
|
||||
hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")?
|
||||
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
Keymap = require 'atom-keymap'
|
||||
KeymapManager = require 'atom-keymap'
|
||||
CSON = require 'season'
|
||||
{jQuery} = require 'space-pen'
|
||||
|
||||
Keymap::loadBundledKeymaps = ->
|
||||
@loadKeyBindings(path.join(@resourcePath, 'keymaps'))
|
||||
KeymapManager::loadBundledKeymaps = ->
|
||||
@loadKeymap(path.join(@resourcePath, 'keymaps'))
|
||||
@emit('bundled-keymaps-loaded')
|
||||
|
||||
Keymap::getUserKeymapPath = ->
|
||||
KeymapManager::getUserKeymapPath = ->
|
||||
if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap'))
|
||||
userKeymapPath
|
||||
else
|
||||
path.join(@configDirPath, 'keymap.cson')
|
||||
|
||||
Keymap::loadUserKeymap = ->
|
||||
KeymapManager::loadUserKeymap = ->
|
||||
userKeymapPath = @getUserKeymapPath()
|
||||
if fs.isFileSync(userKeymapPath)
|
||||
@loadKeyBindings(userKeymapPath, watch: true, suppressErrors: true)
|
||||
@loadKeymap(userKeymapPath, watch: true, suppressErrors: true)
|
||||
|
||||
# This enables command handlers registered via jQuery to call
|
||||
# `.abortKeyBinding()` on the `jQuery.Event` object passed to the handler.
|
||||
jQuery.Event::abortKeyBinding = ->
|
||||
@originalEvent?.abortKeyBinding?()
|
||||
|
||||
module.exports = Keymap
|
||||
module.exports = KeymapManager
|
||||
|
||||
@@ -53,11 +53,11 @@ class LanguageMode
|
||||
buffer.transact ->
|
||||
columnStart = startMatch[1].length
|
||||
columnEnd = columnStart + startMatch[2].length
|
||||
buffer.change([[start, columnStart], [start, columnEnd]], "")
|
||||
buffer.setTextInRange([[start, columnStart], [start, columnEnd]], "")
|
||||
|
||||
endLength = buffer.lineLengthForRow(end) - endMatch[2].length
|
||||
endColumn = endLength - endMatch[1].length
|
||||
buffer.change([[end, endColumn], [end, endLength]], "")
|
||||
buffer.setTextInRange([[end, endColumn], [end, endLength]], "")
|
||||
else
|
||||
buffer.transact ->
|
||||
buffer.insert([start, 0], commentStartString)
|
||||
@@ -72,9 +72,12 @@ class LanguageMode
|
||||
if match = commentStartRegex.search(buffer.lineForRow(row))
|
||||
columnStart = match[1].length
|
||||
columnEnd = columnStart + match[2].length
|
||||
buffer.change([[row, columnStart], [row, columnEnd]], "")
|
||||
buffer.setTextInRange([[row, columnStart], [row, columnEnd]], "")
|
||||
else
|
||||
indent = @minIndentLevelForRowRange(start, end)
|
||||
if start is end
|
||||
indent = @editor.indentationForBufferRow(start)
|
||||
else
|
||||
indent = @minIndentLevelForRowRange(start, end)
|
||||
indentString = @editor.buildIndentString(indent)
|
||||
tabLength = @editor.getTabLength()
|
||||
indentRegex = new RegExp("(\t|[ ]{#{tabLength}}){#{Math.floor(indent)}}")
|
||||
@@ -83,7 +86,7 @@ class LanguageMode
|
||||
if indentLength = line.match(indentRegex)?[0].length
|
||||
buffer.insert([row, indentLength], commentStartString)
|
||||
else
|
||||
buffer.change([[row, 0], [row, indentString.length]], indentString + commentStartString)
|
||||
buffer.setTextInRange([[row, 0], [row, indentString.length]], indentString + commentStartString)
|
||||
|
||||
# Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
path = require 'path'
|
||||
os = require 'os'
|
||||
fs = require 'fs-plus'
|
||||
LessCache = require 'less-cache'
|
||||
{Subscriber} = require 'emissary'
|
||||
|
||||
tmpDir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
|
||||
|
||||
# {LessCache} wrapper used by {ThemeManager} to read stylesheets.
|
||||
module.exports =
|
||||
class LessCompileCache
|
||||
Subscriber.includeInto(this)
|
||||
|
||||
@cacheDir: path.join(tmpDir, 'atom-compile-cache', 'less')
|
||||
@cacheDir: path.join(fs.getHomeDirectory(), 'compile-cache', 'less')
|
||||
|
||||
constructor: ({resourcePath, importPaths}) ->
|
||||
@lessSearchPaths = [
|
||||
|
||||
@@ -14,7 +14,7 @@ class MenuManager
|
||||
constructor: ({@resourcePath}) ->
|
||||
@pendingUpdateOperation = null
|
||||
@template = []
|
||||
atom.keymap.on 'bundled-keymaps-loaded', => @loadPlatformItems()
|
||||
atom.keymaps.on 'bundled-keymaps-loaded', => @loadPlatformItems()
|
||||
|
||||
# Public: Adds the given item definition to the existing template.
|
||||
#
|
||||
@@ -59,7 +59,8 @@ class MenuManager
|
||||
testBody.classList.add(@classesForElement(document.body)...)
|
||||
|
||||
testWorkspace = document.createElement('body')
|
||||
workspaceClasses = @classesForElement(document.body.querySelector('.workspace')) ? ['.workspace']
|
||||
workspaceClasses = @classesForElement(document.body.querySelector('.workspace'))
|
||||
workspaceClasses = ['workspace'] if workspaceClasses.length is 0
|
||||
testWorkspace.classList.add(workspaceClasses...)
|
||||
|
||||
testBody.appendChild(testWorkspace)
|
||||
@@ -75,9 +76,9 @@ class MenuManager
|
||||
clearImmediate(@pendingUpdateOperation) if @pendingUpdateOperation?
|
||||
@pendingUpdateOperation = setImmediate =>
|
||||
keystrokesByCommand = {}
|
||||
for binding in atom.keymap.getKeyBindings() when @includeSelector(binding.selector)
|
||||
for binding in atom.keymaps.getKeyBindings() when @includeSelector(binding.selector)
|
||||
keystrokesByCommand[binding.command] ?= []
|
||||
keystrokesByCommand[binding.command].unshift binding.keystroke
|
||||
keystrokesByCommand[binding.command].unshift binding.keystrokes
|
||||
@sendToBrowserProcess(@template, keystrokesByCommand)
|
||||
|
||||
loadPlatformItems: ->
|
||||
@@ -91,10 +92,10 @@ class MenuManager
|
||||
merge: (menu, item) ->
|
||||
item = _.deepClone(item)
|
||||
|
||||
if item.submenu? and match = _.find(menu, (i) => i.submenu? and @normalizeLabel(i.label) == @normalizeLabel(item.label))
|
||||
if item.submenu? and match = _.find(menu, ({label, submenu}) => submenu? and label and @normalizeLabel(label) is @normalizeLabel(item.label))
|
||||
@merge(match.submenu, i) for i in item.submenu
|
||||
else
|
||||
menu.push(item) unless _.find(menu, (i) => @normalizeLabel(i.label) == @normalizeLabel(item.label))
|
||||
menu.push(item) unless _.find(menu, ({label}) => label and @normalizeLabel(label) is @normalizeLabel(item.label))
|
||||
|
||||
# OSX can't handle displaying accelerators for multiple keystrokes.
|
||||
# If they are sent across, it will stop processing accelerators for the rest
|
||||
@@ -116,10 +117,10 @@ class MenuManager
|
||||
normalizeLabel: (label) ->
|
||||
return undefined unless label?
|
||||
|
||||
if process.platform is 'win32'
|
||||
label.replace(/\&/g, '')
|
||||
else
|
||||
if process.platform is 'darwin'
|
||||
label
|
||||
else
|
||||
label.replace(/\&/g, '')
|
||||
|
||||
# Get an {Array} of {String} classes for the given element.
|
||||
classesForElement: (element) ->
|
||||
|
||||
@@ -7,7 +7,7 @@ fs = require 'fs-plus'
|
||||
{Emitter} = require 'emissary'
|
||||
Q = require 'q'
|
||||
|
||||
{$} = require './space-pen-extensions'
|
||||
$ = null # Defer require in case this is in the window-less browser process
|
||||
ScopedProperties = require './scoped-properties'
|
||||
|
||||
# Loads and activates a package's main module and resources such as
|
||||
@@ -124,7 +124,7 @@ class Package
|
||||
@stylesheetsActivated = true
|
||||
|
||||
activateResources: ->
|
||||
atom.keymap.add(keymapPath, map) for [keymapPath, map] in @keymaps
|
||||
atom.keymaps.add(keymapPath, map) for [keymapPath, map] in @keymaps
|
||||
atom.contextMenu.add(menuPath, map['context-menu']) for [menuPath, map] in @menus
|
||||
atom.menu.add(map.menu) for [menuPath, map] in @menus when map.menu
|
||||
|
||||
@@ -232,7 +232,7 @@ class Package
|
||||
deactivateResources: ->
|
||||
grammar.deactivate() for grammar in @grammars
|
||||
scopedProperties.deactivate() for scopedProperties in @scopedProperties
|
||||
atom.keymap.remove(keymapPath) for [keymapPath] in @keymaps
|
||||
atom.keymaps.remove(keymapPath) for [keymapPath] in @keymaps
|
||||
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
|
||||
@stylesheetsActivated = false
|
||||
@grammarsActivated = false
|
||||
@@ -286,6 +286,7 @@ class Package
|
||||
handleActivationEvent: (event) =>
|
||||
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
|
||||
@activateNow()
|
||||
$ ?= require('./space-pen-extensions').$
|
||||
$(event.target).trigger(event)
|
||||
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
|
||||
@unsubscribeFromActivationEvents()
|
||||
@@ -303,6 +304,7 @@ class Package
|
||||
disableEventHandlersOnBubblePath: (event) ->
|
||||
bubblePathEventHandlers = []
|
||||
disabledHandler = ->
|
||||
$ ?= require('./space-pen-extensions').$
|
||||
element = $(event.target)
|
||||
while element.length
|
||||
if eventHandlers = element.handlers()?[event.type]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{deprecate} = require 'grim'
|
||||
Delegator = require 'delegato'
|
||||
{$, View} = require './space-pen-extensions'
|
||||
PaneView = require './pane-view'
|
||||
@@ -54,9 +55,9 @@ class PaneContainerView extends View
|
||||
|
||||
confirmClose: ->
|
||||
saved = true
|
||||
for pane in @getPaneViews()
|
||||
for item in pane.getItems()
|
||||
if not pane.promptToSaveItem(item)
|
||||
for paneView in @getPaneViews()
|
||||
for item in paneView.getItems()
|
||||
if not paneView.promptToSaveItem(item)
|
||||
saved = false
|
||||
break
|
||||
saved
|
||||
@@ -64,29 +65,33 @@ class PaneContainerView extends View
|
||||
getPaneViews: ->
|
||||
@find('.pane').views()
|
||||
|
||||
indexOfPane: (pane) ->
|
||||
@getPaneViews().indexOf(pane.view())
|
||||
indexOfPane: (paneView) ->
|
||||
@getPaneViews().indexOf(paneView.view())
|
||||
|
||||
paneAtIndex: (index) ->
|
||||
@getPaneViews()[index]
|
||||
|
||||
eachPaneView: (callback) ->
|
||||
callback(pane) for pane in @getPaneViews()
|
||||
paneAttached = (e) -> callback($(e.target).view())
|
||||
@on 'pane:attached', paneAttached
|
||||
off: => @off 'pane:attached', paneAttached
|
||||
callback(paneView) for paneView in @getPaneViews()
|
||||
paneViewAttached = (e) -> callback($(e.target).view())
|
||||
@on 'pane:attached', paneViewAttached
|
||||
off: => @off 'pane:attached', paneViewAttached
|
||||
|
||||
getFocusedPane: ->
|
||||
@find('.pane:has(:focus)').view()
|
||||
|
||||
getActivePane: ->
|
||||
deprecate("Use PaneContainerView::getActivePaneView instead.")
|
||||
@getActivePaneView()
|
||||
|
||||
getActivePaneView: ->
|
||||
@viewForModel(@model.activePane)
|
||||
|
||||
getActivePaneItem: ->
|
||||
@model.activePaneItem
|
||||
|
||||
getActiveView: ->
|
||||
@getActivePane()?.activeView
|
||||
@getActivePaneView()?.activeView
|
||||
|
||||
paneForUri: (uri) ->
|
||||
@viewForModel(@model.paneForUri(uri))
|
||||
@@ -115,29 +120,29 @@ class PaneContainerView extends View
|
||||
y = pointB.y - pointA.y
|
||||
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
|
||||
|
||||
pane = @getActivePane()
|
||||
box = @boundingBoxForPane(pane)
|
||||
panes = @getPaneViews()
|
||||
.filter (otherPane) =>
|
||||
otherBox = @boundingBoxForPane(otherPane)
|
||||
paneView = @getActivePaneView()
|
||||
box = @boundingBoxForPaneView(paneView)
|
||||
paneViews = @getPaneViews()
|
||||
.filter (otherPaneView) =>
|
||||
otherBox = @boundingBoxForPaneView(otherPaneView)
|
||||
switch direction
|
||||
when 'left' then otherBox.right.x <= box.left.x
|
||||
when 'right' then otherBox.left.x >= box.right.x
|
||||
when 'above' then otherBox.bottom.y <= box.top.y
|
||||
when 'below' then otherBox.top.y >= box.bottom.y
|
||||
.sort (paneA, paneB) =>
|
||||
boxA = @boundingBoxForPane(paneA)
|
||||
boxB = @boundingBoxForPane(paneB)
|
||||
.sort (paneViewA, paneViewB) =>
|
||||
boxA = @boundingBoxForPaneView(paneViewA)
|
||||
boxB = @boundingBoxForPaneView(paneViewB)
|
||||
switch direction
|
||||
when 'left' then distance(box.left, boxA.right) - distance(box.left, boxB.right)
|
||||
when 'right' then distance(box.right, boxA.left) - distance(box.right, boxB.left)
|
||||
when 'above' then distance(box.top, boxA.bottom) - distance(box.top, boxB.bottom)
|
||||
when 'below' then distance(box.bottom, boxA.top) - distance(box.bottom, boxB.top)
|
||||
|
||||
panes[0]
|
||||
paneViews[0]
|
||||
|
||||
boundingBoxForPane: (pane) ->
|
||||
boundingBox = pane[0].getBoundingClientRect()
|
||||
boundingBoxForPaneView: (paneView) ->
|
||||
boundingBox = paneView[0].getBoundingClientRect()
|
||||
|
||||
left: {x: boundingBox.left, y: boundingBox.top}
|
||||
right: {x: boundingBox.right, y: boundingBox.top}
|
||||
@@ -146,4 +151,5 @@ class PaneContainerView extends View
|
||||
|
||||
# Deprecated
|
||||
getPanes: ->
|
||||
deprecate("Use PaneContainerView::getPaneViews() instead")
|
||||
@getPaneViews()
|
||||
|
||||
@@ -39,6 +39,9 @@ class PaneContainer extends Model
|
||||
getPanes: ->
|
||||
@root?.getPanes() ? []
|
||||
|
||||
getActivePane: ->
|
||||
@activePane
|
||||
|
||||
paneForUri: (uri) ->
|
||||
find @getPanes(), (pane) -> pane.itemForUri(uri)?
|
||||
|
||||
|
||||
+19
-6
@@ -1,5 +1,6 @@
|
||||
{$, View} = require './space-pen-extensions'
|
||||
Delegator = require 'delegato'
|
||||
{deprecate} = require 'grim'
|
||||
PropertyAccessors = require 'property-accessors'
|
||||
|
||||
Pane = require './pane'
|
||||
@@ -81,22 +82,34 @@ class PaneView extends View
|
||||
@command 'pane:close-other-items', => @destroyInactiveItems()
|
||||
|
||||
# Deprecated: Use ::destroyItem
|
||||
removeItem: (item) -> @destroyItem(item)
|
||||
removeItem: (item) ->
|
||||
deprecate("Use PaneView::destroyItem instead")
|
||||
@destroyItem(item)
|
||||
|
||||
# Deprecated: Use ::activateItem
|
||||
showItem: (item) -> @activateItem(item)
|
||||
showItem: (item) ->
|
||||
deprecate("Use PaneView::activateItem instead")
|
||||
@activateItem(item)
|
||||
|
||||
# Deprecated: Use ::activateItemForUri
|
||||
showItemForUri: (item) -> @activateItemForUri(item)
|
||||
showItemForUri: (item) ->
|
||||
deprecate("Use PaneView::activateItemForUri instead")
|
||||
@activateItemForUri(item)
|
||||
|
||||
# Deprecated: Use ::activateItemAtIndex
|
||||
showItemAtIndex: (index) -> @activateItemAtIndex(index)
|
||||
showItemAtIndex: (index) ->
|
||||
deprecate("Use PaneView::activateItemAtIndex instead")
|
||||
@activateItemAtIndex(index)
|
||||
|
||||
# Deprecated: Use ::activateNextItem
|
||||
showNextItem: -> @activateNextItem()
|
||||
showNextItem: ->
|
||||
deprecate("Use PaneView::destroyItem instead")
|
||||
@activateNextItem()
|
||||
|
||||
# Deprecated: Use ::activatePreviousItem
|
||||
showPreviousItem: -> @activatePreviousItem()
|
||||
showPreviousItem: ->
|
||||
deprecate("Use PaneView::activatePreviousItem instead")
|
||||
@activatePreviousItem()
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if @model.focused and onDom
|
||||
|
||||
+13
-20
@@ -4,6 +4,7 @@ url = require 'url'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
Q = require 'q'
|
||||
{deprecate} = require 'grim'
|
||||
{Model} = require 'theorist'
|
||||
{Emitter, Subscriber} = require 'emissary'
|
||||
Serializable = require 'serializable'
|
||||
@@ -30,13 +31,11 @@ class Project extends Model
|
||||
|
||||
constructor: ({path, @buffers}={}) ->
|
||||
@buffers ?= []
|
||||
@openers = []
|
||||
|
||||
for buffer in @buffers
|
||||
do (buffer) =>
|
||||
buffer.once 'destroyed', => @removeBuffer(buffer)
|
||||
|
||||
@editors = []
|
||||
@setPath(path)
|
||||
|
||||
serializeParams: ->
|
||||
@@ -48,7 +47,6 @@ class Project extends Model
|
||||
params
|
||||
|
||||
destroyed: ->
|
||||
editor.destroy() for editor in @getEditors()
|
||||
buffer.destroy() for buffer in @getBuffers()
|
||||
@destroyRepo()
|
||||
|
||||
@@ -127,18 +125,10 @@ class Project extends Model
|
||||
|
||||
# Deprecated
|
||||
openSync: (filePath, options={}) ->
|
||||
deprecate("Use Project::open instead")
|
||||
filePath = @resolve(filePath)
|
||||
@buildEditorForBuffer(@bufferForPathSync(filePath), options)
|
||||
|
||||
# Add the given {Editor}.
|
||||
addEditor: (editor) ->
|
||||
@editors.push editor
|
||||
@emit 'editor-created', editor
|
||||
|
||||
# Return and removes the given {Editor}.
|
||||
removeEditor: (editor) ->
|
||||
_.remove(@editors, editor)
|
||||
|
||||
# Retrieves all the {TextBuffer}s in the project; that is, the
|
||||
# buffers for all open files.
|
||||
#
|
||||
@@ -151,7 +141,7 @@ class Project extends Model
|
||||
@findBufferForPath(@resolve(filePath))?.isModified()
|
||||
|
||||
findBufferForPath: (filePath) ->
|
||||
_.find @buffers, (buffer) -> buffer.getPath() == filePath
|
||||
_.find @buffers, (buffer) -> buffer.getPath() == filePath
|
||||
|
||||
# Only to be used in specs
|
||||
bufferForPathSync: (filePath) ->
|
||||
@@ -177,6 +167,7 @@ class Project extends Model
|
||||
|
||||
# DEPRECATED
|
||||
buildBufferSync: (absoluteFilePath) ->
|
||||
deprecate("Use Project::buildBuffer instead")
|
||||
buffer = new TextBuffer({filePath: absoluteFilePath})
|
||||
@addBuffer(buffer)
|
||||
buffer.loadSync()
|
||||
@@ -301,8 +292,7 @@ class Project extends Model
|
||||
deferred.promise
|
||||
|
||||
buildEditorForBuffer: (buffer, editorOptions) ->
|
||||
editor = new Editor(_.extend({buffer}, editorOptions))
|
||||
@addEditor(editor)
|
||||
editor = new Editor(_.extend({buffer, registerEditor: true}, editorOptions))
|
||||
editor
|
||||
|
||||
eachBuffer: (args...) ->
|
||||
@@ -317,17 +307,20 @@ class Project extends Model
|
||||
|
||||
# Deprecated: delegate
|
||||
registerOpener: (opener) ->
|
||||
@openers.push(opener)
|
||||
deprecate("Use Workspace::registerOpener instead")
|
||||
atom.workspace.registerOpener(opener)
|
||||
|
||||
# Deprecated: delegate
|
||||
unregisterOpener: (opener) ->
|
||||
_.remove(@openers, opener)
|
||||
deprecate("Use Workspace::unregisterOpener instead")
|
||||
atom.workspace.unregisterOpener(opener)
|
||||
|
||||
# Deprecated: delegate
|
||||
eachEditor: (callback) ->
|
||||
callback(editor) for editor in @getEditors()
|
||||
@on 'editor-created', (editor) -> callback(editor)
|
||||
deprecate("Use Workspace::eachEditor instead")
|
||||
atom.workspace.eachEditor(callback)
|
||||
|
||||
# Deprecated: delegate
|
||||
getEditors: ->
|
||||
new Array(@editors...)
|
||||
deprecate("Use Workspace::getEditors instead")
|
||||
atom.workspace.getEditors()
|
||||
|
||||
@@ -13,7 +13,7 @@ module.exports = (repoPath) ->
|
||||
# Statuses in main repo
|
||||
workingDirectoryPath = repo.getWorkingDirectory()
|
||||
for filePath, status of repo.getStatus()
|
||||
statuses[path.join(workingDirectoryPath, filePath)] = status
|
||||
statuses[filePath] = status
|
||||
|
||||
# Statuses in submodules
|
||||
for submodulePath, submoduleRepo of repo.submodules
|
||||
@@ -23,7 +23,10 @@ module.exports = (repoPath) ->
|
||||
|
||||
workingDirectoryPath = submoduleRepo.getWorkingDirectory()
|
||||
for filePath, status of submoduleRepo.getStatus()
|
||||
statuses[path.join(workingDirectoryPath, filePath)] = status
|
||||
absolutePath = path.join(workingDirectoryPath, filePath)
|
||||
# Make path relative to parent repository
|
||||
relativePath = repo.relativize(absolutePath)
|
||||
statuses[relativePath] = status
|
||||
|
||||
upstream = repo.getAheadBehindCount()
|
||||
branch = repo.getHead()
|
||||
|
||||
@@ -74,7 +74,7 @@ class Selection
|
||||
setBufferRange: (bufferRange, options={}) ->
|
||||
bufferRange = Range.fromObject(bufferRange)
|
||||
@needsAutoscroll = options.autoscroll
|
||||
options.isReversed ?= @isReversed()
|
||||
options.reversed ?= @isReversed()
|
||||
@editor.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
|
||||
@modifySelection =>
|
||||
@cursor.needsAutoscroll = false if options.autoscroll?
|
||||
@@ -99,6 +99,7 @@ class Selection
|
||||
clear: ->
|
||||
@marker.setAttributes(goalBufferRange: null)
|
||||
@marker.clearTail() unless @retainSelection
|
||||
@finalize()
|
||||
|
||||
# Public: Modifies the selection to encompass the current word.
|
||||
#
|
||||
@@ -292,7 +293,7 @@ class Selection
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
text = @normalizeIndents(text, options.indentBasis)
|
||||
|
||||
newBufferRange = @editor.buffer.change(oldBufferRange, text, pick(options, 'undo'))
|
||||
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo'))
|
||||
if options.select
|
||||
@setBufferRange(newBufferRange, isReversed: wasReversed)
|
||||
else
|
||||
|
||||
@@ -26,7 +26,7 @@ humanizeKeystrokes = (keystroke) ->
|
||||
|
||||
getKeystroke = (bindings) ->
|
||||
if bindings?.length
|
||||
"<span class=\"keystroke\">#{humanizeKeystrokes(bindings[0].keystroke)}</span>"
|
||||
"<span class=\"keystroke\">#{humanizeKeystrokes(bindings[0].keystrokes)}</span>"
|
||||
else
|
||||
''
|
||||
|
||||
@@ -39,10 +39,10 @@ jQuery.fn.setTooltip = (tooltipOptions, {command, commandElement}={}) ->
|
||||
|
||||
tooltipOptions = {title: tooltipOptions} if _.isString(tooltipOptions)
|
||||
|
||||
bindings = if commandElement
|
||||
atom.keymap.keyBindingsForCommandMatchingElement(command, commandElement)
|
||||
else
|
||||
atom.keymap.keyBindingsForCommand(command)
|
||||
if commandElement
|
||||
bindings = atom.keymaps.findKeyBindings(command: command, target: commandElement[0])
|
||||
else if command
|
||||
bindings = atom.keymaps.findKeyBindings(command: command)
|
||||
|
||||
tooltipOptions.title = "#{tooltipOptions.title} #{getKeystroke(bindings)}"
|
||||
|
||||
|
||||
+28
-55
@@ -1,7 +1,10 @@
|
||||
_ = require 'underscore-plus'
|
||||
{deprecate} = require 'grim'
|
||||
{specificity} = require 'clear-cut'
|
||||
{Subscriber} = require 'emissary'
|
||||
{GrammarRegistry, ScopeSelector} = require 'first-mate'
|
||||
ScopedPropertyStore = require 'scoped-property-store'
|
||||
PropertyAccessors = require 'property-accessors'
|
||||
|
||||
{$, $$} = require './space-pen-extensions'
|
||||
Token = require './token'
|
||||
@@ -14,6 +17,7 @@ Token = require './token'
|
||||
# language-specific comment regexes.
|
||||
module.exports =
|
||||
class Syntax extends GrammarRegistry
|
||||
PropertyAccessors.includeInto(this)
|
||||
Subscriber.includeInto(this)
|
||||
atom.deserializers.add(this)
|
||||
|
||||
@@ -23,35 +27,31 @@ class Syntax extends GrammarRegistry
|
||||
syntax
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@scopedPropertiesIndex = 0
|
||||
@scopedProperties = []
|
||||
super(maxTokensPerLine: 100)
|
||||
@propertyStore = new ScopedPropertyStore
|
||||
|
||||
serialize: ->
|
||||
{deserializer: @constructor.name, @grammarOverridesByPath}
|
||||
|
||||
createToken: (value, scopes) -> new Token({value, scopes})
|
||||
|
||||
# Deprecated: Used by settings-view to display snippets for packages
|
||||
@::accessor 'scopedProperties', ->
|
||||
deprecate("Use Syntax::getProperty instead")
|
||||
@propertyStore.propertySets
|
||||
|
||||
addProperties: (args...) ->
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, properties] = args
|
||||
|
||||
@scopedProperties.unshift(
|
||||
name: name
|
||||
selector: selector,
|
||||
properties: properties,
|
||||
specificity: specificity(selector),
|
||||
index: @scopedPropertiesIndex++
|
||||
)
|
||||
propertiesBySelector = {}
|
||||
propertiesBySelector[selector] = properties
|
||||
@propertyStore.addProperties(name, propertiesBySelector)
|
||||
|
||||
removeProperties: (name) ->
|
||||
for properties in @scopedProperties.filter((properties) -> properties.name is name)
|
||||
_.remove(@scopedProperties, properties)
|
||||
@propertyStore.removeProperties(name)
|
||||
|
||||
clearProperties: ->
|
||||
@scopedProperties = []
|
||||
@scopedPropertiesIndex = 0
|
||||
@propertyStore = new ScopedPropertyStore
|
||||
|
||||
# Public: Get a property for the given scope and key path.
|
||||
#
|
||||
@@ -66,48 +66,21 @@ class Syntax extends GrammarRegistry
|
||||
#
|
||||
# Returns a {String} property value or undefined.
|
||||
getProperty: (scope, keyPath) ->
|
||||
for object in @propertiesForScope(scope, keyPath)
|
||||
value = _.valueForKeyPath(object, keyPath)
|
||||
return value if value?
|
||||
undefined
|
||||
scopeChain = scope
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope.indexOf('.') is 0
|
||||
scope
|
||||
.join(' ')
|
||||
@propertyStore.getPropertyValue(scopeChain, keyPath)
|
||||
|
||||
propertiesForScope: (scope, keyPath) ->
|
||||
matchingProperties = []
|
||||
candidates = @scopedProperties.filter ({properties}) -> _.valueForKeyPath(properties, keyPath)?
|
||||
if candidates.length
|
||||
element = @buildScopeElement(scope)
|
||||
while element
|
||||
matchingProperties.push(@matchingPropertiesForElement(element, candidates)...)
|
||||
element = element.parentNode
|
||||
matchingProperties
|
||||
scopeChain = scope
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope.indexOf('.') is 0
|
||||
scope
|
||||
.join(' ')
|
||||
|
||||
matchingPropertiesForElement: (element, candidates) ->
|
||||
matchingScopedProperties = candidates.filter ({selector}) ->
|
||||
$.find.matchesSelector(element, selector)
|
||||
matchingScopedProperties.sort (a, b) ->
|
||||
if a.specificity == b.specificity
|
||||
b.index - a.index
|
||||
else
|
||||
b.specificity - a.specificity
|
||||
_.pluck matchingScopedProperties, 'properties'
|
||||
|
||||
buildScopeElement: (scope) ->
|
||||
scope = scope.slice()
|
||||
element = $$ ->
|
||||
elementsForRemainingScopes = =>
|
||||
classString = scope.shift()
|
||||
classes = classString.replace(/^\./, '').replace(/\./g, ' ')
|
||||
if scope.length
|
||||
@div class: classes, elementsForRemainingScopes
|
||||
else
|
||||
@div class: classes
|
||||
elementsForRemainingScopes()
|
||||
|
||||
deepestChild = element.find(":not(:has(*))")
|
||||
if deepestChild.length
|
||||
deepestChild[0]
|
||||
else
|
||||
element[0]
|
||||
@propertyStore.getProperties(scopeChain, keyPath)
|
||||
|
||||
cssSelectorFromScopeSelector: (scopeSelector) ->
|
||||
new ScopeSelector(scopeSelector).toCssSelector()
|
||||
|
||||
@@ -48,6 +48,8 @@ class ThemeManager
|
||||
getEnabledThemeNames: ->
|
||||
themeNames = atom.config.get('core.themes') ? []
|
||||
themeNames = [themeNames] unless _.isArray(themeNames)
|
||||
themeNames = themeNames.filter (themeName) ->
|
||||
themeName and typeof themeName is 'string'
|
||||
|
||||
# Reverse so the first (top) theme is loaded after the others. We want
|
||||
# the first/top theme to override later themes in the stack.
|
||||
|
||||
@@ -37,25 +37,28 @@ class WindowEventHandler
|
||||
@reloadRequested = false
|
||||
confirmed
|
||||
|
||||
@subscribe $(window), 'blur unload', ->
|
||||
atom.storeDefaultWindowDimensions()
|
||||
|
||||
@subscribe $(window), 'unload', ->
|
||||
atom.storeWindowDimensions()
|
||||
|
||||
@subscribeToCommand $(window), 'window:toggle-full-screen', => atom.toggleFullScreen()
|
||||
@subscribeToCommand $(window), 'window:toggle-full-screen', -> atom.toggleFullScreen()
|
||||
|
||||
@subscribeToCommand $(window), 'window:close', => atom.close()
|
||||
@subscribeToCommand $(window), 'window:close', -> atom.close()
|
||||
|
||||
@subscribeToCommand $(window), 'window:reload', =>
|
||||
@reloadRequested = true
|
||||
atom.reload()
|
||||
|
||||
@subscribeToCommand $(window), 'window:toggle-dev-tools', => atom.toggleDevTools()
|
||||
@subscribeToCommand $(window), 'window:toggle-dev-tools', -> atom.toggleDevTools()
|
||||
|
||||
@subscribeToCommand $(document), 'core:focus-next', @focusNext
|
||||
|
||||
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
|
||||
|
||||
@subscribe $(document), 'keydown', (event) ->
|
||||
atom.keymap.handleKeyEvent(event)
|
||||
atom.keymaps.handleKeyboardEvent(event.originalEvent)
|
||||
|
||||
@subscribe $(document), 'drop', (e) ->
|
||||
e.preventDefault()
|
||||
@@ -92,7 +95,7 @@ class WindowEventHandler
|
||||
bindCommandToAction('core:redo', 'redo:')
|
||||
bindCommandToAction('core:select-all', 'selectAll:')
|
||||
|
||||
openLink: (event) =>
|
||||
openLink: (event) ->
|
||||
location = $(event.target).attr('href')
|
||||
if location and location[0] isnt '#' and /^https?:\/\//.test(location)
|
||||
shell.openExternal(location)
|
||||
|
||||
@@ -3,6 +3,7 @@ path = require 'path'
|
||||
Q = require 'q'
|
||||
_ = require 'underscore-plus'
|
||||
Delegator = require 'delegato'
|
||||
{deprecate, logDeprecationWarnings} = require 'grim'
|
||||
scrollbarStyle = require 'scrollbar-style'
|
||||
{$, $$, View} = require './space-pen-extensions'
|
||||
fs = require 'fs-plus'
|
||||
@@ -78,7 +79,7 @@ class WorkspaceView extends View
|
||||
@div class: 'panes', outlet: 'panes'
|
||||
|
||||
initialize: (@model) ->
|
||||
@model ?= new Workspace
|
||||
@model = atom.workspace ? new Workspace unless @model?
|
||||
|
||||
panes = new PaneContainerView(@model.paneContainer)
|
||||
@panes.replaceWith(panes)
|
||||
@@ -115,6 +116,8 @@ class WorkspaceView extends View
|
||||
@command 'application:new-window', -> ipc.sendChannel('command', 'application:new-window')
|
||||
@command 'application:new-file', -> ipc.sendChannel('command', 'application:new-file')
|
||||
@command 'application:open', -> ipc.sendChannel('command', 'application:open')
|
||||
@command 'application:open-file', -> ipc.sendChannel('command', 'application:open-file')
|
||||
@command 'application:open-folder', -> ipc.sendChannel('command', 'application:open-folder')
|
||||
@command 'application:open-dev', -> ipc.sendChannel('command', 'application:open-dev')
|
||||
@command 'application:minimize', -> ipc.sendChannel('command', 'application:minimize')
|
||||
@command 'application:zoom', -> ipc.sendChannel('command', 'application:zoom')
|
||||
@@ -140,15 +143,15 @@ class WorkspaceView extends View
|
||||
@command 'window:focus-pane-on-left', => @focusPaneViewOnLeft()
|
||||
@command 'window:focus-pane-on-right', => @focusPaneViewOnRight()
|
||||
@command 'window:save-all', => @saveAll()
|
||||
@command 'window:toggle-invisibles', =>
|
||||
atom.config.toggle("editor.showInvisibles")
|
||||
@command 'window:toggle-invisibles', -> atom.config.toggle("editor.showInvisibles")
|
||||
@command 'window:log-deprecation-warnings', -> logDeprecationWarnings()
|
||||
|
||||
@command 'window:toggle-auto-indent', =>
|
||||
atom.config.toggle("editor.autoIndent")
|
||||
|
||||
@command 'pane:reopen-closed-item', => @reopenItemSync()
|
||||
|
||||
@command 'core:close', => if @getActivePaneItem()? then @destroyActivePaneItem() else @destroyActivePane()
|
||||
@command 'core:close', => if @getModel().getActivePaneItem()? then @destroyActivePaneItem() else @destroyActivePane()
|
||||
@command 'core:save', => @saveActivePaneItem()
|
||||
@command 'core:save-as', => @saveActivePaneItemAs()
|
||||
|
||||
@@ -179,8 +182,8 @@ class WorkspaceView extends View
|
||||
detailedMessage: "The shell commands `atom` and `apm` are installed."
|
||||
|
||||
handleFocus: ->
|
||||
if @getActivePane()
|
||||
@getActivePane().focus()
|
||||
if @getActivePaneView()
|
||||
@getActivePaneView().focus()
|
||||
false
|
||||
else
|
||||
@updateTitle()
|
||||
@@ -202,7 +205,7 @@ class WorkspaceView extends View
|
||||
# Updates the application's title, based on whichever file is open.
|
||||
updateTitle: ->
|
||||
if projectPath = atom.project.getPath()
|
||||
if item = @getActivePaneItem()
|
||||
if item = @getModel().getActivePaneItem()
|
||||
@setTitle("#{item.getTitle?() ? 'untitled'} - #{projectPath}")
|
||||
else
|
||||
@setTitle(projectPath)
|
||||
@@ -269,7 +272,7 @@ class WorkspaceView extends View
|
||||
#
|
||||
# Returns a {PaneView}.
|
||||
getActivePaneView: ->
|
||||
@panes.getActivePane()
|
||||
@panes.getActivePaneView()
|
||||
|
||||
# Public: Get the view associated with the active pane item.
|
||||
#
|
||||
@@ -313,7 +316,7 @@ class WorkspaceView extends View
|
||||
#
|
||||
# Returns an Array of all open {PaneView}s.
|
||||
getPaneViews: ->
|
||||
@panes.getPanes()
|
||||
@panes.getPaneViews()
|
||||
|
||||
# Public: Register a function to be called for every current and future
|
||||
# editor view in the workspace.
|
||||
@@ -334,16 +337,20 @@ class WorkspaceView extends View
|
||||
|
||||
# Deprecated
|
||||
eachPane: (callback) ->
|
||||
deprecate("Use WorkspaceView::eachPaneView instead")
|
||||
@eachPaneView(callback)
|
||||
|
||||
# Deprecated
|
||||
getPanes: ->
|
||||
deprecate("Use WorkspaceView::getPaneViews instead")
|
||||
@getPaneViews()
|
||||
|
||||
# Deprecated
|
||||
getActivePane: ->
|
||||
deprecate("Use WorkspaceView::getActivePaneView instead")
|
||||
@getActivePaneView()
|
||||
|
||||
# Deprecated: Call {Workspace::getActivePaneItem} instead.
|
||||
getActivePaneItem: ->
|
||||
deprecate("Use Workspace::getActivePaneItem instead")
|
||||
@model.activePaneItem
|
||||
|
||||
+29
-8
@@ -1,9 +1,11 @@
|
||||
{remove, last} = require 'underscore-plus'
|
||||
{deprecate} = require 'grim'
|
||||
_ = require 'underscore-plus'
|
||||
{join} = require 'path'
|
||||
{Model} = require 'theorist'
|
||||
Q = require 'q'
|
||||
Serializable = require 'serializable'
|
||||
Delegator = require 'delegato'
|
||||
Editor = require './editor'
|
||||
PaneContainer = require './pane-container'
|
||||
Pane = require './pane'
|
||||
|
||||
@@ -27,13 +29,16 @@ class Workspace extends Model
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@openers = []
|
||||
|
||||
@subscribe @paneContainer, 'item-destroyed', @onPaneItemDestroyed
|
||||
@registerOpener (filePath) =>
|
||||
switch filePath
|
||||
when 'atom://.atom/stylesheet'
|
||||
@open(atom.themes.getUserStylesheetPath())
|
||||
when 'atom://.atom/keymap'
|
||||
@open(atom.keymap.getUserKeymapPath())
|
||||
@open(atom.keymaps.getUserKeymapPath())
|
||||
when 'atom://.atom/config'
|
||||
@open(atom.config.getUserConfigPath())
|
||||
when 'atom://.atom/init-script'
|
||||
@@ -49,6 +54,9 @@ class Workspace extends Model
|
||||
paneContainer: @paneContainer.serialize()
|
||||
fullScreen: atom.isFullScreen()
|
||||
|
||||
editorAdded: (editor) ->
|
||||
@emit 'editor-created', editor
|
||||
|
||||
# Public: Register a function to be called for every current and future
|
||||
# {Editor} in the workspace.
|
||||
#
|
||||
@@ -57,13 +65,18 @@ class Workspace extends Model
|
||||
# Returns a subscription object with an `.off` method that you can call to
|
||||
# unregister the callback.
|
||||
eachEditor: (callback) ->
|
||||
atom.project.eachEditor(callback)
|
||||
callback(editor) for editor in @getEditors()
|
||||
@subscribe this, 'editor-created', (editor) -> callback(editor)
|
||||
|
||||
# Public: Get all current editors in the workspace.
|
||||
#
|
||||
# Returns an {Array} of {Editor}s.
|
||||
getEditors: ->
|
||||
atom.project.getEditors()
|
||||
editors = []
|
||||
for pane in @paneContainer.getPanes()
|
||||
editors.push(item) for item in pane.getItems() when item instanceof Editor
|
||||
|
||||
editors
|
||||
|
||||
# Public: Open a given a URI in Atom asynchronously.
|
||||
#
|
||||
@@ -114,6 +127,8 @@ class Workspace extends Model
|
||||
# :activatePane - A {Boolean} indicating whether to call {Pane::activate} on
|
||||
# the containing pane. Defaults to `true`.
|
||||
openSync: (uri='', options={}) ->
|
||||
deprecate("Don't use the `changeFocus` option") if options.changeFocus?
|
||||
|
||||
{initialLine} = options
|
||||
# TODO: Remove deprecated changeFocus option
|
||||
activatePane = options.activatePane ? options.changeFocus ? true
|
||||
@@ -169,14 +184,14 @@ class Workspace extends Model
|
||||
#
|
||||
# opener - A {Function} to be called when a path is being opened.
|
||||
registerOpener: (opener) ->
|
||||
atom.project.registerOpener(opener)
|
||||
@openers.push(opener)
|
||||
|
||||
# Public: Unregister an opener registered with {::registerOpener}.
|
||||
unregisterOpener: (opener) ->
|
||||
atom.project.unregisterOpener(opener)
|
||||
_.remove(@openers, opener)
|
||||
|
||||
getOpeners: ->
|
||||
atom.project.openers
|
||||
@openers
|
||||
|
||||
# Public: Get the active {Pane}.
|
||||
#
|
||||
@@ -208,6 +223,12 @@ class Workspace extends Model
|
||||
paneForUri: (uri) ->
|
||||
@paneContainer.paneForUri(uri)
|
||||
|
||||
# Public: Get the active {Pane}'s active item.
|
||||
#
|
||||
# Returns an pane item {Object}.
|
||||
getActivePaneItem: ->
|
||||
@paneContainer.getActivePane().getActiveItem()
|
||||
|
||||
# Public: Save the active pane item.
|
||||
#
|
||||
# If the active pane item currently has a URI according to the item's
|
||||
@@ -259,7 +280,7 @@ class Workspace extends Model
|
||||
# Removes the item's uri from the list of potential items to reopen.
|
||||
itemOpened: (item) ->
|
||||
if uri = item.getUri?()
|
||||
remove(@destroyedItemUris, uri)
|
||||
_.remove(@destroyedItemUris, uri)
|
||||
|
||||
# Adds the destroyed item's uri to the list of items to reopen.
|
||||
onPaneItemDestroyed: (item) =>
|
||||
|
||||
externo
+1
-1
Submodule vendor/apm updated: 3f0003c60e...d349e45263
Referência em uma Nova Issue
Bloquear um usuário