Comparar commits
267 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 43acb99f86 | |||
| 8dccc8e07c | |||
| 3c800b00f5 | |||
| cb0f531b9a | |||
| 5e61c7b38a | |||
| 57f85e1720 | |||
| f4ced3b078 | |||
| 9553c46030 | |||
| 14e73e0c63 | |||
| 5c5c6e77fd | |||
| e9678a15f1 | |||
| f0135adb62 | |||
| 58fe92a41b | |||
| 5689fbf7cc | |||
| af052c79a7 | |||
| f431bb6396 | |||
| e21cc17a7b | |||
| 1247e40e88 | |||
| 6159209d49 | |||
| d8263a1fcd | |||
| 5e3b88f42d | |||
| a0e4d8b582 | |||
| ff80545285 | |||
| 3462d99675 | |||
| 11ec0c579d | |||
| 0de9f54e3c | |||
| 75e499004d | |||
| 11a817c442 | |||
| 8db843a57c | |||
| 08dd51a12f | |||
| 3f869ec191 | |||
| 0fba8ba402 | |||
| 7756f4b945 | |||
| 832e7113f7 | |||
| aa46e3d26f | |||
| d48719ab1c | |||
| 0c40a1ef92 | |||
| bad0504e1d | |||
| 01fdd83c6c | |||
| 0a92b6b681 | |||
| 167467339a | |||
| efd3329c50 | |||
| a140787252 | |||
| d09c4010f6 | |||
| e2f1a245b0 | |||
| 682045ef16 | |||
| dc6e825edd | |||
| 481e444ffe | |||
| 5193fa698f | |||
| b8d2bd6c30 | |||
| 33fde29acb | |||
| 6934b83acc | |||
| 330988ad16 | |||
| 058ef0a5a8 | |||
| 003c101f14 | |||
| 98d602628a | |||
| 46efc52a22 | |||
| f78891b600 | |||
| 05e3bbde45 | |||
| 4dc4a022ab | |||
| 226ae374c1 | |||
| fbfe1c7224 | |||
| 53f8ae3055 | |||
| 1634b3acfc | |||
| 3067323564 | |||
| c410b79af0 | |||
| f09fc23fdc | |||
| a9262b18c2 | |||
| ef129f9491 | |||
| b4d38d14e3 | |||
| 97a21d7bbf | |||
| ab395952a9 | |||
| 6e55c80d3c | |||
| f1079056cf | |||
| b29a61ec87 | |||
| 4894849adc | |||
| cf78b01d45 | |||
| 1ed927f213 | |||
| b978b4f8c7 | |||
| baea6fcb49 | |||
| 7e06e10fcf | |||
| 0bcfa591f6 | |||
| f2532b1a35 | |||
| e0f8d6f365 | |||
| 50c705fea4 | |||
| 8bfea240ea | |||
| 4099828525 | |||
| 26983adbdf | |||
| ede703453a | |||
| d97c81bf6a | |||
| bd76242851 | |||
| d85c07e7e2 | |||
| 4077e791c9 | |||
| e7eef89fa5 | |||
| 5437236304 | |||
| b7aa421e4e | |||
| 9458db0c1f | |||
| 80c15513bb | |||
| 951289f67f | |||
| 1e7ba12e60 | |||
| 9a423359c4 | |||
| bb56c6badc | |||
| ae461b21a4 | |||
| 670b44f250 | |||
| d330a8fac5 | |||
| 8bd2650d01 | |||
| 560d9387dc | |||
| 39cc463e24 | |||
| 2c83c3fe17 | |||
| 07505ea82a | |||
| 47d3b3edf3 | |||
| 3d394e854e | |||
| a37b8ff632 | |||
| f8a05dd8e0 | |||
| 6a58f6054a | |||
| ddd4a9a968 | |||
| 743c50014f | |||
| af761fb004 | |||
| badf1725fa | |||
| 2b2149bca1 | |||
| e1d6d55311 | |||
| 670a710753 | |||
| dd1e5338c6 | |||
| 100af7d27d | |||
| 9b70cf2044 | |||
| 7fe9c14772 | |||
| 9690e44ffe | |||
| 0e57ede712 | |||
| dd7335c30b | |||
| 4537e9bd1a | |||
| 0488fc21da | |||
| 160bb29034 | |||
| 497b4a4e24 | |||
| dd4e7d6921 | |||
| d060ecdc24 | |||
| 84d1101903 | |||
| 6f3c53a17a | |||
| dd17e8f018 | |||
| cf3f1aa2eb | |||
| adaf1829da | |||
| 7863db480e | |||
| 5cc243ec11 | |||
| 2e46cf9b8d | |||
| 5e8655fa60 | |||
| c64a4b7ca9 | |||
| bda1429293 | |||
| eb19989ecd | |||
| 62c0db11ee | |||
| 8aeabe5fe5 | |||
| ab846a2495 | |||
| 7202908780 | |||
| c4cfac5615 | |||
| 866f2d9a76 | |||
| 3b455c00d3 | |||
| 1f777addd9 | |||
| 58744f6b7b | |||
| 7badd9ba25 | |||
| e8d7058383 | |||
| 42fc54f716 | |||
| c11675dca1 | |||
| cdb62812d2 | |||
| 2d3d64f399 | |||
| 2321aa2bee | |||
| fa733c85ad | |||
| 158bbef38f | |||
| b2bc09c13d | |||
| 268fceb073 | |||
| 5be21d6743 | |||
| 5d3602d37b | |||
| b86f6870c5 | |||
| 2ab5fa405c | |||
| 5f4fb23057 | |||
| 22f6268116 | |||
| 65f40d6f7b | |||
| 596987fbce | |||
| 2b218d2e01 | |||
| 582066915b | |||
| 1a98cb7070 | |||
| c2d0b6d4f5 | |||
| 2affff30ff | |||
| 3b6189e94b | |||
| 4e8e5a84c4 | |||
| 087387e633 | |||
| 769c6c52bb | |||
| 963c92eb4e | |||
| 22212be90d | |||
| 8a640b35e0 | |||
| df9a0dc7a3 | |||
| 5251183410 | |||
| 5bd028b24e | |||
| 8485831f40 | |||
| da30b66ffa | |||
| 3da11bf478 | |||
| 9b1d5e1864 | |||
| 1f445acc12 | |||
| 022bc2e2a5 | |||
| da18db754f | |||
| c20403d983 | |||
| 78dc87d4b6 | |||
| 5dd310f9ac | |||
| 427a32c336 | |||
| f3d4a3ad45 | |||
| ba642682ca | |||
| b1a0258ad4 | |||
| 44112f2ecd | |||
| 54b8aa4a02 | |||
| 5791548ac4 | |||
| 26f21abcf3 | |||
| ab0f9e88a7 | |||
| 6d8b891b65 | |||
| afdb96e1b1 | |||
| 9c1ca86cb0 | |||
| 4e95977fbd | |||
| 4a8a379891 | |||
| fb0387f43e | |||
| 5231a548e3 | |||
| a466d6cdaf | |||
| 19b0f760a1 | |||
| 228ba5f96a | |||
| 25922872f0 | |||
| 15a1982e8c | |||
| fcca61c2b2 | |||
| ee4116536d | |||
| c217c6544a | |||
| 205095a198 | |||
| 4326898d5f | |||
| b8285a00b0 | |||
| 025967193a | |||
| 75627f50a2 | |||
| 9fca1d26f1 | |||
| 6e827434fd | |||
| b3f6b3af4b | |||
| 63a33bd1e7 | |||
| a153f1e244 | |||
| 037a7f435c | |||
| 7641f1d1e4 | |||
| 05c1ae71e1 | |||
| cefabd4eb8 | |||
| 9f80be4570 | |||
| 61f75b0764 | |||
| ae2f4ac36e | |||
| d20e91897a | |||
| 2e0bb66a9a | |||
| d205c4d664 | |||
| 8db5ea7bc7 | |||
| 3c7eecbb6a | |||
| 8dab3d90b3 | |||
| 44bc470a00 | |||
| 498631725a | |||
| 945345b0c7 | |||
| 6576ec5cde | |||
| ce8143f8e6 | |||
| e993175205 | |||
| 4242ac0911 | |||
| f22e741a9b | |||
| a41b582032 | |||
| a24279d0b9 | |||
| 5985175b07 | |||
| d2ef888f22 | |||
| 35925ed349 | |||
| 490ec1aac7 | |||
| 25eea7d19b | |||
| 4c9e71770a | |||
| 4032d96b13 | |||
| c5aa3eb441 | |||
| 68bb765304 | |||
| bd7996e071 |
+6
-13
@@ -101,30 +101,23 @@ For more information on how to work with Atom's official packages, see
|
||||
|
||||
## Documentation Styleguide
|
||||
|
||||
* Use [TomDoc](http://tomdoc.org).
|
||||
* Use [AtomDoc](https://github.com/atom/atomdoc).
|
||||
* Use [Markdown](https://daringfireball.net/projects/markdown).
|
||||
* Reference methods and classes in markdown with the custom `{}` notation:
|
||||
* Reference classes with `{ClassName}`
|
||||
* Reference instance methods with `{ClassName::methodName}`
|
||||
* Reference class methods with `{ClassName.methodName}`
|
||||
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
|
||||
style notation.
|
||||
|
||||
### Example
|
||||
|
||||
```coffee
|
||||
# Public: Disable the package with the given name.
|
||||
#
|
||||
# This method emits multiple events:
|
||||
#
|
||||
# * `package-will-be-disabled` - before the package is disabled.
|
||||
# * `package-disabled` - after the package is disabled.
|
||||
#
|
||||
# name - The {String} name of the package to disable.
|
||||
# options - The {Object} with disable options (default: {}):
|
||||
# :trackTime - `true` to track the amount of time disabling took.
|
||||
# :ignoreErrors - `true` to catch and ignore errors thrown.
|
||||
# callback - The {Function} to call after the package has been disabled.
|
||||
# * `name` The {String} name of the package to disable.
|
||||
# * `options` (optional) The {Object} with disable options (default: {}):
|
||||
# * `trackTime` A {Boolean}, `true` to track the amount of time taken.
|
||||
# * `ignoreErrors` A {Boolean}, `true` to catch and ignore errors thrown.
|
||||
# * `callback` The {Function} to call after the package has been disabled.
|
||||
#
|
||||
# Returns `undefined`.
|
||||
disablePackage: (name, options, callback) ->
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.109.0"
|
||||
"atom-package-manager": "0.111.0"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ if [ $OS == 'Mac' ]; then
|
||||
"$ATOM_PATH/$ATOM_APP_NAME/Contents/MacOS/Atom" --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
exit $?
|
||||
else
|
||||
open -a "$ATOM_PATH/$ATOM_APP_NAME" -n --args --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
open -a "$ATOM_PATH/$ATOM_APP_NAME" -n --args --executed-from="$(pwd)" --pid=$$ --path-environment="$PATH" "$@"
|
||||
fi
|
||||
elif [ $OS == 'Linux' ]; then
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "editorView.", ->
|
||||
|
||||
beforeEach ->
|
||||
atom.workspaceViewParentSelector = '#jasmine-content'
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
atom.workspaceView.width(1024)
|
||||
|
||||
@@ -60,3 +60,18 @@ module.exports =
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
"""
|
||||
|
||||
'jschardet@1.1.0':
|
||||
license: 'LGPL'
|
||||
source: 'README.md in the repository'
|
||||
sourceText: """
|
||||
JsChardet
|
||||
=========
|
||||
|
||||
Port of python's chardet (http://chardet.feedparser.org/).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
LGPL
|
||||
"""
|
||||
|
||||
@@ -123,10 +123,22 @@ getAtomDraftRelease = (callback) ->
|
||||
logError('Fetching atom/atom releases failed', error, releases)
|
||||
callback(error)
|
||||
else
|
||||
for release in releases when release.draft
|
||||
callback(null, release)
|
||||
return
|
||||
callback(new Error('No draft release in atom/atom repo'))
|
||||
[firstDraft] = releases.filter ({draft}) -> draft
|
||||
if firstDraft?
|
||||
options =
|
||||
uri: firstDraft.assets_url
|
||||
method: 'GET'
|
||||
headers: defaultHeaders
|
||||
json: true
|
||||
request options, (error, response, assets=[]) ->
|
||||
if error? or response.statusCode isnt 200
|
||||
logError('Fetching draft release assets failed', error, assets)
|
||||
callback(error ? new Error(response.statusCode))
|
||||
else
|
||||
firstDraft.assets = assets
|
||||
callback(null, firstDraft)
|
||||
else
|
||||
callback(new Error('No draft release in atom/atom repo'))
|
||||
|
||||
deleteRelease = (release) ->
|
||||
options =
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
# after packages are loaded/activated and after the previous editor state
|
||||
# has been restored.
|
||||
#
|
||||
# An example hack to make opened Markdown files always be soft wrapped:
|
||||
# An example hack to log to the console when each text editor is saved.
|
||||
#
|
||||
# path = require 'path'
|
||||
#
|
||||
# atom.workspaceView.eachEditorView (editorView) ->
|
||||
# editor = editorView.getEditor()
|
||||
# if path.extname(editor.getPath()) is '.md'
|
||||
# editor.setSoftWrapped(true)
|
||||
# atom.workspace.observeTextEditors (editor) ->
|
||||
# editor.onDidSave ->
|
||||
# console.log "Saved! #{editor.getPath()}"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# 'atom-text-editor':
|
||||
# 'enter': 'editor:newline'
|
||||
#
|
||||
# '.workspace':
|
||||
# 'atom-workspace':
|
||||
# 'ctrl-shift-p': 'core:move-up'
|
||||
# 'ctrl-p': 'core:move-down'
|
||||
#
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'ctrl-K': 'editor:delete-line'
|
||||
|
||||
'.select-list atom-text-editor.mini':
|
||||
'enter': 'core:confirm'
|
||||
|
||||
'.tool-panel.panel-left, .tool-panel.panel-right':
|
||||
'escape': 'tool-panel:unfocus'
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
'ctrl-alt-cmd-l': 'window:reload'
|
||||
'alt-cmd-i': 'window:toggle-dev-tools'
|
||||
'cmd-alt-ctrl-p': 'window:run-package-specs'
|
||||
'ctrl-shift-left': 'pane:move-item-left'
|
||||
'ctrl-shift-right': 'pane:move-item-right'
|
||||
|
||||
# Sublime Parity
|
||||
'cmd-,': 'application:show-settings'
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
'ctrl-alt-o': 'application:open-dev'
|
||||
'ctrl-shift-o': 'application:open-folder'
|
||||
'ctrl-shift-pageup': 'pane:move-item-left'
|
||||
'ctrl-shift-pagedown': 'pane:move-item-right'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
'ctrl-alt-o': 'application:open-dev'
|
||||
'ctrl-shift-o': 'application:open-folder'
|
||||
'ctrl-shift-left': 'pane:move-item-left'
|
||||
'ctrl-shift-right': 'pane:move-item-right'
|
||||
'F11': 'window:toggle-full-screen'
|
||||
|
||||
# Sublime Parity
|
||||
|
||||
@@ -190,6 +190,12 @@
|
||||
submenu: [
|
||||
{ label: 'Terms of Use', command: 'application:open-terms-of-use' }
|
||||
{ label: 'Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
{ label: 'Frequently Asked Questions', command: 'application:open-faq' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Community Discussions', command: 'application:open-discussions' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Search Issues', command: 'application:search-issues' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -147,6 +147,12 @@
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
{ label: 'Frequently Asked Questions', command: 'application:open-faq' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Community Discussions', command: 'application:open-discussions' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Search Issues', command: 'application:search-issues' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
|
||||
+7
-1
@@ -109,7 +109,7 @@
|
||||
{ label: 'Focus Pane On Left', command: 'window:focus-pane-on-left' }
|
||||
{ label: 'Focus Pane On Right', command: 'window:focus-pane-on-right' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Close pane', command: 'pane:close' }
|
||||
{ label: 'Close Pane', command: 'pane:close' }
|
||||
]
|
||||
}
|
||||
{
|
||||
@@ -165,6 +165,12 @@
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
{ label: 'Frequently Asked Questions', command: 'application:open-faq' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Community Discussions', command: 'application:open-discussions' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Search Issues', command: 'application:search-issues' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
|
||||
+29
-29
@@ -1,7 +1,7 @@
|
||||
{
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.141.0",
|
||||
"version": "0.145.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,10 +17,10 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.18.2",
|
||||
"atomShellVersion": "0.19.1",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.2.1",
|
||||
"atom-keymap": "^2.2.2",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.7.0",
|
||||
@@ -43,7 +43,7 @@
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.4",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^2.1.3",
|
||||
"pathwatcher": "^2.3.2",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
@@ -56,15 +56,15 @@
|
||||
"season": "^1.0.2",
|
||||
"semver": "2.2.1",
|
||||
"serializable": "^1",
|
||||
"space-pen": "3.8.0",
|
||||
"space-pen": "3.8.1",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.3.0",
|
||||
"text-buffer": "^3.6.0",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.1",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.20.0",
|
||||
"atom-dark-syntax": "0.21.0",
|
||||
"atom-dark-ui": "0.35.0",
|
||||
"atom-light-syntax": "0.21.0",
|
||||
"atom-light-ui": "0.30.0",
|
||||
@@ -73,67 +73,67 @@
|
||||
"solarized-dark-syntax": "0.22.0",
|
||||
"solarized-light-syntax": "0.12.0",
|
||||
"archive-view": "0.37.0",
|
||||
"autocomplete": "0.32.0",
|
||||
"autocomplete": "0.33.0",
|
||||
"autoflow": "0.18.0",
|
||||
"autosave": "0.18.0",
|
||||
"background-tips": "0.17.0",
|
||||
"bookmarks": "0.28.0",
|
||||
"bookmarks": "0.30.0",
|
||||
"bracket-matcher": "0.62.0",
|
||||
"command-palette": "0.27.0",
|
||||
"deprecation-cop": "0.11.0",
|
||||
"dev-live-reload": "0.34.0",
|
||||
"dev-live-reload": "0.35.0",
|
||||
"encoding-selector": "0.7.0",
|
||||
"exception-reporting": "0.20.0",
|
||||
"feedback": "0.33.0",
|
||||
"find-and-replace": "0.141.0",
|
||||
"find-and-replace": "0.146.0",
|
||||
"fuzzy-finder": "0.60.0",
|
||||
"git-diff": "0.42.0",
|
||||
"git-diff": "0.43.0",
|
||||
"go-to-line": "0.26.0",
|
||||
"grammar-selector": "0.35.0",
|
||||
"image-view": "0.38.0",
|
||||
"grammar-selector": "0.37.0",
|
||||
"image-view": "0.40.0",
|
||||
"incompatible-packages": "0.10.0",
|
||||
"keybinding-resolver": "0.20.0",
|
||||
"link": "0.26.0",
|
||||
"markdown-preview": "0.107.0",
|
||||
"metrics": "0.36.0",
|
||||
"markdown-preview": "0.110.0",
|
||||
"metrics": "0.38.0",
|
||||
"open-on-github": "0.30.0",
|
||||
"package-generator": "0.31.0",
|
||||
"package-generator": "0.32.0",
|
||||
"release-notes": "0.36.0",
|
||||
"settings-view": "0.153.0",
|
||||
"settings-view": "0.158.0",
|
||||
"snippets": "0.56.0",
|
||||
"spell-check": "0.43.0",
|
||||
"status-bar": "0.46.0",
|
||||
"styleguide": "0.30.0",
|
||||
"symbols-view": "0.66.0",
|
||||
"symbols-view": "0.68.0",
|
||||
"tabs": "0.55.0",
|
||||
"timecop": "0.23.0",
|
||||
"tree-view": "0.131.0",
|
||||
"tree-view": "0.132.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.19.0",
|
||||
"whitespace": "0.26.0",
|
||||
"wrap-guide": "0.23.0",
|
||||
"language-c": "0.29.0",
|
||||
"language-c": "0.30.0",
|
||||
"language-coffee-script": "0.37.0",
|
||||
"language-css": "0.21.0",
|
||||
"language-css": "0.23.0",
|
||||
"language-gfm": "0.53.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.19.0",
|
||||
"language-html": "0.26.0",
|
||||
"language-hyperlink": "0.12.0",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.42.0",
|
||||
"language-javascript": "0.43.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.18.0",
|
||||
"language-make": "0.12.0",
|
||||
"language-mustache": "0.10.0",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.17.0",
|
||||
"language-php": "0.18.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.21.0",
|
||||
"language-python": "0.23.0",
|
||||
"language-ruby": "0.41.0",
|
||||
"language-ruby-on-rails": "0.18.0",
|
||||
"language-sass": "0.24.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-sass": "0.25.0",
|
||||
"language-shellscript": "0.10.0",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.11.0",
|
||||
"language-text": "0.6.0",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Package: <%= name %>
|
||||
Version: <%= version %>
|
||||
Depends: python (>= 2.6), libc6
|
||||
Depends: gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11, libnotify4, libxtst6, libnss3, python, gvfs-bin, xdg-utils
|
||||
Suggests: libgnome-keyring0, gir1.2-gnomekeyring-1.0
|
||||
Section: <%= section %>
|
||||
Priority: optional
|
||||
Architecture: <%= arch %>
|
||||
|
||||
@@ -4,9 +4,6 @@ Release: 0.1%{?dist}
|
||||
Summary: Atom is a hackable text editor for the 21st century
|
||||
License: MIT
|
||||
URL: https://atom.io/
|
||||
BuildConflicts: gyp
|
||||
BuildRequires: make, gcc, gcc-c++, glibc-devel, git-core, libgnome-keyring-devel
|
||||
Requires: libgnome-keyring
|
||||
AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
|
||||
|
||||
%description
|
||||
|
||||
@@ -6,7 +6,7 @@ ThemeManager = require '../src/theme-manager'
|
||||
|
||||
describe "the `atom` global", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
|
||||
describe 'window sizing methods', ->
|
||||
describe '::getPosition and ::setPosition', ->
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CommandRegistry = require '../src/command-registry'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
describe "CommandRegistry", ->
|
||||
[registry, parent, child, grandchild] = []
|
||||
@@ -154,8 +155,15 @@ describe "CommandRegistry", ->
|
||||
registry.add '.grandchild', 'namespace:command-3', ->
|
||||
registry.add '.grandchild.no-match', 'namespace:command-4', ->
|
||||
|
||||
expect(registry.findCommands(target: grandchild)[0..2]).toEqual [
|
||||
registry.add grandchild, 'namespace:inline-command-1', ->
|
||||
registry.add child, 'namespace:inline-command-2', ->
|
||||
|
||||
commands = registry.findCommands(target: grandchild)
|
||||
nonJqueryCommands = _.reject commands, (cmd) -> cmd.jQuery
|
||||
expect(nonJqueryCommands).toEqual [
|
||||
{name: 'namespace:inline-command-1', displayName: 'Namespace: Inline Command 1'}
|
||||
{name: 'namespace:command-3', displayName: 'Namespace: Command 3'}
|
||||
{name: 'namespace:inline-command-2', displayName: 'Namespace: Inline Command 2'}
|
||||
{name: 'namespace:command-2', displayName: 'Namespace: Command 2'}
|
||||
{name: 'namespace:command-1', displayName: 'Namespace: Command 1'}
|
||||
]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
a { color: red }
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"theme": "syntax",
|
||||
"stylesheets": ["editor.less"]
|
||||
}
|
||||
@@ -3,7 +3,7 @@ Package = require '../src/package'
|
||||
|
||||
describe "PackageManager", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
|
||||
describe "::loadPackage(name)", ->
|
||||
it "continues if the package has an invalid package.json", ->
|
||||
@@ -48,9 +48,10 @@ describe "PackageManager", ->
|
||||
describe "when called multiple times", ->
|
||||
it "it only calls activate on the package once", ->
|
||||
spyOn(Package.prototype, 'activateNow').andCallThrough()
|
||||
atom.packages.activatePackage('package-with-index')
|
||||
atom.packages.activatePackage('package-with-index')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('package-with-index')
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('package-with-index')
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('package-with-index')
|
||||
|
||||
@@ -182,8 +183,10 @@ describe "PackageManager", ->
|
||||
pack.mainModule.someNumber = 77
|
||||
atom.packages.deactivatePackage("package-with-serialization")
|
||||
spyOn(pack.mainModule, 'activate').andCallThrough()
|
||||
atom.packages.activatePackage("package-with-serialization")
|
||||
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-serialization")
|
||||
runs ->
|
||||
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
|
||||
|
||||
it "logs warning instead of throwing an exception if the package fails to load", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
@@ -202,11 +205,13 @@ describe "PackageManager", ->
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])).toHaveLength 0
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
|
||||
|
||||
atom.packages.activatePackage("package-with-keymaps")
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-keymaps")
|
||||
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe "test-1"
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])[0].command).toBe "test-2"
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
|
||||
runs ->
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe "test-1"
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])[0].command).toBe "test-2"
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
|
||||
|
||||
describe "when the metadata contains a 'keymaps' manifest", ->
|
||||
it "loads only the keymaps specified by the manifest, in the specified order", ->
|
||||
@@ -215,11 +220,13 @@ describe "PackageManager", ->
|
||||
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])).toHaveLength 0
|
||||
|
||||
atom.packages.activatePackage("package-with-keymaps-manifest")
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-keymaps-manifest")
|
||||
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe 'keymap-1'
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-n', target:element1[0])[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-y', target:element3[0])).toHaveLength 0
|
||||
runs ->
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe 'keymap-1'
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-n', target:element1[0])[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-y', target:element3[0])).toHaveLength 0
|
||||
|
||||
describe "menu loading", ->
|
||||
beforeEach ->
|
||||
@@ -232,14 +239,16 @@ describe "PackageManager", ->
|
||||
|
||||
expect(atom.contextMenu.templateForElement(element)).toEqual []
|
||||
|
||||
atom.packages.activatePackage("package-with-menus")
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-menus")
|
||||
|
||||
expect(atom.menu.template.length).toBe 2
|
||||
expect(atom.menu.template[0].label).toBe "Second to Last"
|
||||
expect(atom.menu.template[1].label).toBe "Last"
|
||||
expect(atom.contextMenu.templateForElement(element)[0].label).toBe "Menu item 1"
|
||||
expect(atom.contextMenu.templateForElement(element)[1].label).toBe "Menu item 2"
|
||||
expect(atom.contextMenu.templateForElement(element)[2].label).toBe "Menu item 3"
|
||||
runs ->
|
||||
expect(atom.menu.template.length).toBe 2
|
||||
expect(atom.menu.template[0].label).toBe "Second to Last"
|
||||
expect(atom.menu.template[1].label).toBe "Last"
|
||||
expect(atom.contextMenu.templateForElement(element)[0].label).toBe "Menu item 1"
|
||||
expect(atom.contextMenu.templateForElement(element)[1].label).toBe "Menu item 2"
|
||||
expect(atom.contextMenu.templateForElement(element)[2].label).toBe "Menu item 3"
|
||||
|
||||
describe "when the metadata contains a 'menus' manifest", ->
|
||||
it "loads only the menus specified by the manifest, in the specified order", ->
|
||||
@@ -247,13 +256,15 @@ describe "PackageManager", ->
|
||||
|
||||
expect(atom.contextMenu.templateForElement(element)).toEqual []
|
||||
|
||||
atom.packages.activatePackage("package-with-menus-manifest")
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-menus-manifest")
|
||||
|
||||
expect(atom.menu.template[0].label).toBe "Second to Last"
|
||||
expect(atom.menu.template[1].label).toBe "Last"
|
||||
expect(atom.contextMenu.templateForElement(element)[0].label).toBe "Menu item 2"
|
||||
expect(atom.contextMenu.templateForElement(element)[1].label).toBe "Menu item 1"
|
||||
expect(atom.contextMenu.templateForElement(element)[2]).toBeUndefined()
|
||||
runs ->
|
||||
expect(atom.menu.template[0].label).toBe "Second to Last"
|
||||
expect(atom.menu.template[1].label).toBe "Last"
|
||||
expect(atom.contextMenu.templateForElement(element)[0].label).toBe "Menu item 2"
|
||||
expect(atom.contextMenu.templateForElement(element)[1].label).toBe "Menu item 1"
|
||||
expect(atom.contextMenu.templateForElement(element)[2]).toBeUndefined()
|
||||
|
||||
describe "stylesheet loading", ->
|
||||
describe "when the metadata contains a 'stylesheets' manifest", ->
|
||||
@@ -270,33 +281,67 @@ describe "PackageManager", ->
|
||||
expect(atom.themes.stylesheetElementForId(two)).toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(three)).toBeNull()
|
||||
|
||||
atom.packages.activatePackage("package-with-stylesheets-manifest")
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-stylesheets-manifest")
|
||||
|
||||
expect(atom.themes.stylesheetElementForId(one)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(two)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(three)).toBeNull()
|
||||
expect($('#jasmine-content').css('font-size')).toBe '1px'
|
||||
runs ->
|
||||
expect(atom.themes.stylesheetElementForId(one)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(two)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(three)).toBeNull()
|
||||
expect($('#jasmine-content').css('font-size')).toBe '1px'
|
||||
|
||||
describe "when the metadata does not contain a 'stylesheets' manifest", ->
|
||||
it "loads all stylesheets from the stylesheets directory", ->
|
||||
one = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/1.css")
|
||||
two = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/2.less")
|
||||
three = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/3.css")
|
||||
|
||||
three = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/3.test-context.css")
|
||||
four = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/4.css")
|
||||
|
||||
one = atom.themes.stringToId(one)
|
||||
two = atom.themes.stringToId(two)
|
||||
three = atom.themes.stringToId(three)
|
||||
four = atom.themes.stringToId(four)
|
||||
|
||||
expect(atom.themes.stylesheetElementForId(one)).toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(two)).toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(three)).toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(four)).toBeNull()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-stylesheets")
|
||||
|
||||
runs ->
|
||||
expect(atom.themes.stylesheetElementForId(one)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(two)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(three)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(four)).not.toBeNull()
|
||||
expect($('#jasmine-content').css('font-size')).toBe '3px'
|
||||
|
||||
it "assigns the stylesheet's context based on the filename", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-stylesheets")
|
||||
expect(atom.themes.stylesheetElementForId(one)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(two)).not.toBeNull()
|
||||
expect(atom.themes.stylesheetElementForId(three)).not.toBeNull()
|
||||
expect($('#jasmine-content').css('font-size')).toBe '3px'
|
||||
|
||||
runs ->
|
||||
count = 0
|
||||
|
||||
for styleElement in atom.styles.getStyleElements()
|
||||
if styleElement.sourcePath.match /1.css/
|
||||
expect(styleElement.context).toBe undefined
|
||||
count++
|
||||
|
||||
if styleElement.sourcePath.match /2.less/
|
||||
expect(styleElement.context).toBe undefined
|
||||
count++
|
||||
|
||||
if styleElement.sourcePath.match /3.test-context.css/
|
||||
expect(styleElement.context).toBe 'test-context'
|
||||
count++
|
||||
|
||||
if styleElement.sourcePath.match /4.css/
|
||||
expect(styleElement.context).toBe undefined
|
||||
count++
|
||||
|
||||
expect(count).toBe 4
|
||||
|
||||
describe "grammar loading", ->
|
||||
it "loads the package's grammars", ->
|
||||
|
||||
@@ -92,7 +92,7 @@ describe "Package", ->
|
||||
|
||||
it "reloads without readding to the stylesheets list", ->
|
||||
expect(theme.getStylesheetPaths().length).toBe 3
|
||||
theme.reloadStylesheet(theme.getStylesheetPaths()[0])
|
||||
theme.reloadStylesheets()
|
||||
expect(theme.getStylesheetPaths().length).toBe 3
|
||||
|
||||
describe "events", ->
|
||||
|
||||
@@ -33,6 +33,13 @@ describe "PaneContainer", ->
|
||||
[pane1B, pane2B, pane3B] = containerB.getPanes()
|
||||
expect(containerB.getActivePane()).toBe pane3B
|
||||
|
||||
it "makes the first pane active if no pane exists for the activePaneId", ->
|
||||
pane3A.activate()
|
||||
state = containerA.serialize()
|
||||
state.activePaneId = -22
|
||||
containerB = atom.deserializers.deserialize(state)
|
||||
expect(containerB.getActivePane()).toBe containerB.getPanes()[0]
|
||||
|
||||
it "does not allow the root pane to be destroyed", ->
|
||||
container = new PaneContainer
|
||||
container.getRoot().destroy()
|
||||
|
||||
@@ -19,7 +19,7 @@ describe "PaneContainerView", ->
|
||||
save: -> @saved = true
|
||||
isEqual: (other) -> @name is other?.name
|
||||
|
||||
container = atom.workspace.getView(atom.workspace.paneContainer).__spacePenView
|
||||
container = atom.views.getView(atom.workspace.paneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(new TestView('1'))
|
||||
pane2 = pane1.splitRight(new TestView('2'))
|
||||
@@ -73,7 +73,7 @@ describe "PaneContainerView", ->
|
||||
|
||||
describe "serialization", ->
|
||||
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > :contains(1)')).toExist()
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > :contains(2)')).toExist()
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > :contains(3)')).toExist()
|
||||
@@ -89,14 +89,14 @@ describe "PaneContainerView", ->
|
||||
|
||||
describe "if the 'core.destroyEmptyPanes' config option is false (the default)", ->
|
||||
it "leaves the empty panes intact", ->
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > :contains(1)')).toExist()
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > atom-pane').length).toBe 2
|
||||
|
||||
describe "if the 'core.destroyEmptyPanes' config option is true", ->
|
||||
it "removes empty panes on deserialization", ->
|
||||
atom.config.set('core.destroyEmptyPanes', true)
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('atom-pane-axis.horizontal, atom-pane-axis.vertical')).not.toExist()
|
||||
expect(newContainer.find('> :contains(1)')).toExist()
|
||||
|
||||
@@ -109,7 +109,7 @@ describe "PaneContainerView", ->
|
||||
item2b = new TestView('2b')
|
||||
item3a = new TestView('3a')
|
||||
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
container = atom.views.getView(new PaneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(item1a)
|
||||
container.attachToDom()
|
||||
@@ -259,7 +259,7 @@ describe "PaneContainerView", ->
|
||||
# |7|8|9|
|
||||
# -------
|
||||
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
container = atom.views.getView(new PaneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(new TestView('1'))
|
||||
pane4 = pane1.splitDown(new TestView('4'))
|
||||
|
||||
@@ -146,6 +146,24 @@ describe "Pane", ->
|
||||
pane.activateNextItem()
|
||||
expect(pane.getActiveItem()).toBe item1
|
||||
|
||||
describe "::moveItemRight() and ::moveItemLeft()", ->
|
||||
it "moves the active item to the right and left, without looping around at either end", ->
|
||||
pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
|
||||
[item1, item2, item3] = pane.getItems()
|
||||
|
||||
pane.activateItemAtIndex(0)
|
||||
expect(pane.getActiveItem()).toBe item1
|
||||
pane.moveItemLeft()
|
||||
expect(pane.getItems()).toEqual [item1, item2, item3]
|
||||
pane.moveItemRight()
|
||||
expect(pane.getItems()).toEqual [item2, item1, item3]
|
||||
pane.moveItemLeft()
|
||||
expect(pane.getItems()).toEqual [item1, item2, item3]
|
||||
pane.activateItemAtIndex(2)
|
||||
expect(pane.getActiveItem()).toBe item3
|
||||
pane.moveItemRight()
|
||||
expect(pane.getItems()).toEqual [item1, item2, item3]
|
||||
|
||||
describe "::activateItemAtIndex(index)", ->
|
||||
it "activates the item at the given index", ->
|
||||
pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
|
||||
@@ -565,6 +583,37 @@ describe "Pane", ->
|
||||
expect(pane1.isActive()).toBe false
|
||||
expect(pane2.isActive()).toBe true
|
||||
|
||||
describe "::close()", ->
|
||||
it "prompts to save unsaved items before destroying the pane", ->
|
||||
pane = new Pane(items: [new Item("A"), new Item("B")])
|
||||
[item1, item2] = pane.getItems()
|
||||
|
||||
item1.shouldPromptToSave = -> true
|
||||
item1.getUri = -> "/test/path"
|
||||
item1.save = jasmine.createSpy("save")
|
||||
|
||||
spyOn(atom, 'confirm').andReturn(0)
|
||||
pane.close()
|
||||
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
expect(item1.save).toHaveBeenCalled()
|
||||
expect(pane.isDestroyed()).toBe true
|
||||
|
||||
it "does not destroy the pane if cancel is called", ->
|
||||
pane = new Pane(items: [new Item("A"), new Item("B")])
|
||||
[item1, item2] = pane.getItems()
|
||||
|
||||
item1.shouldPromptToSave = -> true
|
||||
item1.getUri = -> "/test/path"
|
||||
item1.save = jasmine.createSpy("save")
|
||||
|
||||
spyOn(atom, 'confirm').andReturn(1)
|
||||
pane.close()
|
||||
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
expect(item1.save).not.toHaveBeenCalled()
|
||||
expect(pane.isDestroyed()).toBe false
|
||||
|
||||
describe "::destroy()", ->
|
||||
[container, pane1, pane2] = []
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ describe "PaneView", ->
|
||||
|
||||
beforeEach ->
|
||||
deserializerDisposable = atom.deserializers.add(TestView)
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
container = atom.views.getView(new PaneContainer).__spacePenView
|
||||
containerModel = container.model
|
||||
view1 = new TestView(id: 'view-1', text: 'View 1')
|
||||
view2 = new TestView(id: 'view-2', text: 'View 2')
|
||||
@@ -144,12 +144,15 @@ describe "PaneView", ->
|
||||
|
||||
describe "when an item is moved to another pane", ->
|
||||
it "detaches the item's view rather than removing it", ->
|
||||
container.attachToDom()
|
||||
expect(view1.is(':visible')).toBe true
|
||||
paneModel2 = paneModel.splitRight()
|
||||
view1.data('preservative', 1234)
|
||||
paneModel.moveItemToPane(view1, paneModel2, 1)
|
||||
expect(view1.data('preservative')).toBe 1234
|
||||
paneModel2.activateItemAtIndex(1)
|
||||
expect(view1.data('preservative')).toBe 1234
|
||||
expect(view1.is(':visible')).toBe true
|
||||
|
||||
describe "when the title of the active item changes", ->
|
||||
describe 'when there is no onDidChangeTitle method', ->
|
||||
@@ -311,13 +314,13 @@ describe "PaneView", ->
|
||||
container.attachToDom()
|
||||
pane.focus()
|
||||
|
||||
container2 = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
container2 = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
pane2 = container2.getRoot()
|
||||
container2.attachToDom()
|
||||
expect(pane2).toMatchSelector(':has(:focus)')
|
||||
|
||||
$(document.activeElement).blur()
|
||||
container3 = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
container3 = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
pane3 = container3.getRoot()
|
||||
container3.attachToDom()
|
||||
expect(pane3).not.toMatchSelector(':has(:focus)')
|
||||
|
||||
@@ -43,21 +43,76 @@ describe "PanelContainerElement", ->
|
||||
expect(element.parentNode).not.toBe jasmineContent
|
||||
|
||||
describe "adding and removing panels", ->
|
||||
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
|
||||
expect(element.childNodes.length).toBe 0
|
||||
describe "when the container is at the left location", ->
|
||||
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), location: 'left'})
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel1)
|
||||
expect(element.childNodes.length).toBe 1
|
||||
expect(element.childNodes[0].getAttribute('location')).toBe 'left'
|
||||
|
||||
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel2)
|
||||
expect(element.childNodes.length).toBe 2
|
||||
|
||||
expect(panel1.getView().style.display).not.toBe 'none'
|
||||
expect(panel2.getView().style.display).not.toBe 'none'
|
||||
|
||||
panel1.destroy()
|
||||
expect(element.childNodes.length).toBe 1
|
||||
|
||||
panel2.destroy()
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
describe "when the container is at the bottom location", ->
|
||||
beforeEach ->
|
||||
container = new PanelContainer({viewRegistry, location: 'bottom'})
|
||||
element = container.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), className: 'one'})
|
||||
container.addPanel(panel1)
|
||||
expect(element.childNodes.length).toBe 1
|
||||
expect(element.childNodes[0].getAttribute('location')).toBe 'bottom'
|
||||
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
|
||||
expect(panel1.getView()).toHaveClass 'one'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), className: 'two'})
|
||||
container.addPanel(panel2)
|
||||
expect(element.childNodes.length).toBe 2
|
||||
expect(panel2.getView()).toHaveClass 'two'
|
||||
|
||||
panel1.destroy()
|
||||
expect(element.childNodes.length).toBe 1
|
||||
|
||||
panel2.destroy()
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
describe "when the container is modal", ->
|
||||
beforeEach ->
|
||||
container = new PanelContainer({viewRegistry, location: 'modal'})
|
||||
element = container.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
it "allows only one panel to be visible at a time", ->
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel1)
|
||||
expect(element.childNodes.length).toBe 1
|
||||
|
||||
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
|
||||
expect(panel1.getView().style.display).not.toBe 'none'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), location: 'left'})
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
|
||||
container.addPanel(panel2)
|
||||
expect(element.childNodes.length).toBe 2
|
||||
|
||||
panel1.destroy()
|
||||
expect(element.childNodes.length).toBe 1
|
||||
expect(panel1.getView().style.display).toBe 'none'
|
||||
expect(panel2.getView().style.display).not.toBe 'none'
|
||||
|
||||
panel2.destroy()
|
||||
expect(element.childNodes.length).toBe 0
|
||||
panel1.show()
|
||||
|
||||
expect(panel1.getView().style.display).not.toBe 'none'
|
||||
expect(panel2.getView().style.display).toBe 'none'
|
||||
|
||||
@@ -54,3 +54,12 @@ describe "PanelElement", ->
|
||||
|
||||
panel.show()
|
||||
expect(element.style.display).not.toBe 'none'
|
||||
|
||||
describe "when a class name is specified", ->
|
||||
it 'initially renders panel created with visibile: false', ->
|
||||
panel = new Panel({viewRegistry, className: 'some classes', item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element).toHaveClass 'some'
|
||||
expect(element).toHaveClass 'classes'
|
||||
|
||||
@@ -184,7 +184,7 @@ describe "SelectListView", ->
|
||||
describe "when the mini editor loses focus", ->
|
||||
it "triggers the cancelled hook and detaches the select list", ->
|
||||
spyOn(selectList, 'detach')
|
||||
filterEditorView.hiddenInput.trigger 'focusout'
|
||||
filterEditorView.trigger 'blur'
|
||||
expect(selectList.cancelled).toHaveBeenCalled()
|
||||
expect(selectList.detach).toHaveBeenCalled()
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ beforeEach ->
|
||||
config.set "editor.autoIndent", false
|
||||
config.set "core.disabledPackages", ["package-that-throws-an-exception",
|
||||
"package-with-broken-package-json", "package-with-broken-keymap"]
|
||||
config.set "editor.useShadowDOM", true
|
||||
config.load.reset()
|
||||
config.save.reset()
|
||||
|
||||
@@ -219,7 +220,7 @@ addCustomMatchers = (spec) ->
|
||||
@message = -> return "Expected element '" + @actual + "' or its descendants" + notText + " to have focus."
|
||||
element = @actual
|
||||
element = element.get(0) if element.jquery
|
||||
element.webkitMatchesSelector(":focus") or element.querySelector(":focus")
|
||||
element is document.activeElement or element.contains(document.activeElement)
|
||||
|
||||
toShow: ->
|
||||
notText = if @isNot then " not" else ""
|
||||
@@ -338,12 +339,8 @@ window.setEditorWidthInChars = (editorView, widthInChars, charWidth=editorView.c
|
||||
$(window).trigger 'resize' # update width of editor view's on-screen lines
|
||||
|
||||
window.setEditorHeightInLines = (editorView, heightInLines, lineHeight=editorView.lineHeight) ->
|
||||
if editorView.hasClass('react')
|
||||
editorView.height(editorView.getEditor().getLineHeightInPixels() * heightInLines)
|
||||
editorView.component?.measureHeightAndWidth()
|
||||
else
|
||||
editorView.height(lineHeight * heightInLines + editorView.renderedLines.position().top)
|
||||
$(window).trigger 'resize' # update editor view's on-screen lines
|
||||
editorView.height(editorView.getEditor().getLineHeightInPixels() * heightInLines)
|
||||
editorView.component?.measureHeightAndWidth()
|
||||
|
||||
$.fn.resultOfTrigger = (type) ->
|
||||
event = $.Event(type)
|
||||
|
||||
@@ -52,3 +52,25 @@ describe "StylesElement", ->
|
||||
expect(element.children.length).toBe initialChildCount + 1
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: blue;}"
|
||||
expect(updatedStyleElements).toEqual [element.children[initialChildCount]]
|
||||
|
||||
it "only includes style elements matching the 'context' attribute", ->
|
||||
initialChildCount = element.children.length
|
||||
|
||||
atom.styles.addStyleSheet("a {color: red;}", context: 'test-context')
|
||||
atom.styles.addStyleSheet("a {color: green;}")
|
||||
|
||||
expect(element.children.length).toBe initialChildCount + 2
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: red;}"
|
||||
expect(element.children[initialChildCount + 1].textContent).toBe "a {color: green;}"
|
||||
|
||||
element.setAttribute('context', 'test-context')
|
||||
|
||||
expect(element.children.length).toBe 1
|
||||
expect(element.children[0].textContent).toBe "a {color: red;}"
|
||||
|
||||
atom.styles.addStyleSheet("a {color: blue;}", context: 'test-context')
|
||||
atom.styles.addStyleSheet("a {color: yellow;}")
|
||||
|
||||
expect(element.children.length).toBe 2
|
||||
expect(element.children[0].textContent).toBe "a {color: red;}"
|
||||
expect(element.children[1].textContent).toBe "a {color: blue;}"
|
||||
|
||||
@@ -721,11 +721,11 @@ describe "TextEditorComponent", ->
|
||||
editor.setCursorScreenPosition([0, 16])
|
||||
nextAnimationFrame()
|
||||
|
||||
atom.themes.applyStylesheet 'test', """
|
||||
atom.styles.addStyleSheet """
|
||||
.function.js {
|
||||
font-weight: bold;
|
||||
}
|
||||
"""
|
||||
""", context: 'atom-text-editor'
|
||||
nextAnimationFrame() # update based on new measurements
|
||||
|
||||
cursor = componentNode.querySelector('.cursor')
|
||||
@@ -1537,8 +1537,9 @@ describe "TextEditorComponent", ->
|
||||
|
||||
it "transfers focus to the hidden input", ->
|
||||
expect(document.activeElement).toBe document.body
|
||||
componentNode.focus()
|
||||
expect(document.activeElement).toBe inputNode
|
||||
wrapperNode.focus()
|
||||
expect(document.activeElement).toBe wrapperNode
|
||||
expect(wrapperNode.shadowRoot.activeElement).toBe inputNode
|
||||
|
||||
it "adds the 'is-focused' class to the editor when the hidden input is focused", ->
|
||||
expect(document.activeElement).toBe document.body
|
||||
@@ -1667,12 +1668,13 @@ describe "TextEditorComponent", ->
|
||||
component.measureHeightAndWidth()
|
||||
nextAnimationFrame()
|
||||
|
||||
atom.themes.applyStylesheet "test", """
|
||||
atom.styles.addStyleSheet """
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
"""
|
||||
""", context: 'atom-text-editor'
|
||||
|
||||
nextAnimationFrame()
|
||||
|
||||
scrollbarCornerNode = componentNode.querySelector('.scrollbar-corner')
|
||||
@@ -1922,6 +1924,31 @@ describe "TextEditorComponent", ->
|
||||
expect(nextAnimationFrame).toBe noAnimationFrame
|
||||
expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () {'
|
||||
|
||||
it "groups events that occur close together in time into single undo entries", ->
|
||||
currentTime = 0
|
||||
spyOn(Date, 'now').andCallFake -> currentTime
|
||||
|
||||
atom.config.set('editor.undoGroupingInterval', 100)
|
||||
|
||||
editor.setText("")
|
||||
componentNode.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode))
|
||||
|
||||
currentTime += 99
|
||||
componentNode.dispatchEvent(buildTextInputEvent(data: 'y', target: inputNode))
|
||||
|
||||
currentTime += 99
|
||||
componentNode.dispatchEvent(new CustomEvent('editor:duplicate-lines', bubbles: true, cancelable: true))
|
||||
|
||||
currentTime += 100
|
||||
componentNode.dispatchEvent(new CustomEvent('editor:duplicate-lines', bubbles: true, cancelable: true))
|
||||
expect(editor.getText()).toBe "xy\nxy\nxy"
|
||||
|
||||
componentNode.dispatchEvent(new CustomEvent('core:undo', bubbles: true, cancelable: true))
|
||||
expect(editor.getText()).toBe "xy\nxy"
|
||||
|
||||
componentNode.dispatchEvent(new CustomEvent('core:undo', bubbles: true, cancelable: true))
|
||||
expect(editor.getText()).toBe ""
|
||||
|
||||
describe "when IME composition is used to insert international characters", ->
|
||||
inputNode = null
|
||||
|
||||
@@ -2286,6 +2313,12 @@ describe "TextEditorComponent", ->
|
||||
editor.setGrammar(atom.syntax.nullGrammar)
|
||||
expect(wrapperNode.dataset.grammar).toBe 'text plain null-grammar'
|
||||
|
||||
describe "encoding data attributes", ->
|
||||
it "adds and updates the encoding data attribute based on the current encoding", ->
|
||||
expect(wrapperNode.dataset.encoding).toBe 'utf8'
|
||||
editor.setEncoding('utf16le')
|
||||
expect(wrapperNode.dataset.encoding).toBe 'utf16le'
|
||||
|
||||
describe "detaching and reattaching the editor (regression)", ->
|
||||
it "does not throw an exception", ->
|
||||
wrapperView.detach()
|
||||
|
||||
@@ -19,18 +19,74 @@ describe "TextEditorElement", ->
|
||||
element = jasmineContent.firstChild
|
||||
expect(element.getModel().getPlaceholderText()).toBe 'testing'
|
||||
|
||||
describe "::focus()", ->
|
||||
it "transfers focus to the hidden text area and does not emit 'focusout' or 'blur' events", ->
|
||||
element = new TextEditorElement
|
||||
describe "focus and blur handling", ->
|
||||
describe "when the editor.useShadowDOM config option is true", ->
|
||||
it "proxies focus/blur events to/from the hidden input inside the shadow root", ->
|
||||
atom.config.set('editor.useShadowDOM', true)
|
||||
|
||||
element = new TextEditorElement
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
blurCalled = false
|
||||
element.addEventListener 'blur', -> blurCalled = true
|
||||
|
||||
element.focus()
|
||||
expect(blurCalled).toBe false
|
||||
expect(element.hasFocus()).toBe true
|
||||
expect(document.activeElement).toBe element
|
||||
expect(element.shadowRoot.activeElement).toBe element.shadowRoot.querySelector('input')
|
||||
|
||||
document.body.focus()
|
||||
expect(blurCalled).toBe true
|
||||
|
||||
describe "when the editor.useShadowDOM config option is false", ->
|
||||
it "proxies focus/blur events to/from the hidden input", ->
|
||||
atom.config.set('editor.useShadowDOM', false)
|
||||
|
||||
element = new TextEditorElement
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
blurCalled = false
|
||||
element.addEventListener 'blur', -> blurCalled = true
|
||||
|
||||
element.focus()
|
||||
expect(blurCalled).toBe false
|
||||
expect(element.hasFocus()).toBe true
|
||||
expect(document.activeElement).toBe element.querySelector('input')
|
||||
|
||||
document.body.focus()
|
||||
expect(blurCalled).toBe true
|
||||
|
||||
describe "when the themes finish loading", ->
|
||||
[themeReloadCallback, initialThemeLoadComplete, element] = []
|
||||
|
||||
beforeEach ->
|
||||
themeReloadCallback = null
|
||||
initialThemeLoadComplete = false
|
||||
|
||||
spyOn(atom.themes, 'isInitialLoadComplete').andCallFake ->
|
||||
initialThemeLoadComplete
|
||||
spyOn(atom.themes, 'onDidReloadAll').andCallFake (fn) ->
|
||||
themeReloadCallback = fn
|
||||
|
||||
atom.config.set("editor.useShadowDOM", false)
|
||||
|
||||
element = new TextEditorElement()
|
||||
element.style.height = '200px'
|
||||
element.getModel().setText [0..20].join("\n")
|
||||
|
||||
it "re-renders the scrollbar", ->
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
focusoutCalled = false
|
||||
element.addEventListener 'focusout', -> focusoutCalled = true
|
||||
blurCalled = false
|
||||
element.addEventListener 'blur', -> blurCalled = true
|
||||
atom.styles.addStyleSheet """
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
"""
|
||||
|
||||
element.focus()
|
||||
expect(focusoutCalled).toBe false
|
||||
expect(blurCalled).toBe false
|
||||
expect(element.hasFocus()).toBe true
|
||||
expect(element.querySelector('input')).toBe document.activeElement
|
||||
initialThemeLoadComplete = true
|
||||
themeReloadCallback()
|
||||
|
||||
verticalScrollbarNode = element.querySelector(".vertical-scrollbar")
|
||||
scrollbarWidth = verticalScrollbarNode.offsetWidth - verticalScrollbarNode.clientWidth
|
||||
expect(scrollbarWidth).toEqual(8)
|
||||
|
||||
@@ -157,6 +157,19 @@ describe "TextEditor", ->
|
||||
|
||||
expect(observed).toEqual [__filename, undefined]
|
||||
|
||||
describe "encoding", ->
|
||||
it "notifies ::onDidChangeEncoding observers when the editor encoding changes", ->
|
||||
observed = []
|
||||
editor.onDidChangeEncoding (encoding) -> observed.push(encoding)
|
||||
|
||||
editor.setEncoding('utf16le')
|
||||
editor.setEncoding('utf16le')
|
||||
editor.setEncoding('utf16be')
|
||||
editor.setEncoding()
|
||||
editor.setEncoding()
|
||||
|
||||
expect(observed).toEqual ['utf16le', 'utf16be', 'utf8']
|
||||
|
||||
describe "cursor", ->
|
||||
describe ".getLastCursor()", ->
|
||||
it "returns the most recently created cursor", ->
|
||||
@@ -1145,6 +1158,21 @@ describe "TextEditor", ->
|
||||
editor.selectLinesContainingCursors()
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0,0], [2,0]]
|
||||
|
||||
it "autoscrolls to the selection", ->
|
||||
editor.manageScrollPosition = true
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setDefaultCharWidth(10)
|
||||
editor.setHeight(50)
|
||||
editor.setWidth(50)
|
||||
editor.setHorizontalScrollbarHeight(0)
|
||||
editor.setCursorScreenPosition([5, 6])
|
||||
|
||||
editor.scrollToTop()
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
|
||||
editor.selectLinesContainingCursors()
|
||||
expect(editor.getScrollBottom()).toBe (7 + editor.getVerticalScrollMargin()) * 10
|
||||
|
||||
describe ".selectToBeginningOfWord()", ->
|
||||
it "selects text from cusor position to beginning of word", ->
|
||||
editor.setCursorScreenPosition [0,13]
|
||||
@@ -1792,6 +1820,16 @@ describe "TextEditor", ->
|
||||
expect(willInsertSpy).toHaveBeenCalled()
|
||||
expect(didInsertSpy).not.toHaveBeenCalled()
|
||||
|
||||
describe "when the undo option is set to 'skip'", ->
|
||||
beforeEach ->
|
||||
editor.setSelectedBufferRange([[1, 2], [1, 2]])
|
||||
|
||||
it "does not undo the skipped operation", ->
|
||||
range = editor.insertText('x')
|
||||
range = editor.insertText('y', undo: 'skip')
|
||||
editor.undo()
|
||||
expect(buffer.lineForRow(1)).toBe ' yvar sort = function(items) {'
|
||||
|
||||
describe ".insertNewline()", ->
|
||||
describe "when there is a single cursor", ->
|
||||
describe "when the cursor is at the beginning of a line", ->
|
||||
@@ -3087,6 +3125,11 @@ describe "TextEditor", ->
|
||||
expect(editor.getTabLength()).toBe 6
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 6
|
||||
|
||||
changeHandler = jasmine.createSpy('changeHandler')
|
||||
editor.onDidChange(changeHandler)
|
||||
editor.setTabLength(6)
|
||||
expect(changeHandler).not.toHaveBeenCalled()
|
||||
|
||||
it 'retokenizes when the editor.tabLength setting is updated', ->
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
|
||||
@@ -85,16 +85,7 @@ describe "ThemeManager", ->
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style.theme')).toHaveLength 0
|
||||
atom.config.set('core.themes', ['atom-dark-syntax'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount == 1
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 1
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-syntax/
|
||||
atom.config.set('core.themes', ['atom-light-syntax', 'atom-dark-syntax'])
|
||||
atom.config.set('core.themes', ['atom-dark-ui'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount == 1
|
||||
@@ -102,8 +93,17 @@ describe "ThemeManager", ->
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-syntax/
|
||||
expect($('style[group=theme]:eq(1)').attr('source-path')).toMatch /atom-light-syntax/
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-ui/
|
||||
atom.config.set('core.themes', ['atom-light-ui', 'atom-dark-ui'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount == 1
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-ui/
|
||||
expect($('style[group=theme]:eq(1)').attr('source-path')).toMatch /atom-light-ui/
|
||||
atom.config.set('core.themes', [])
|
||||
|
||||
waitsFor ->
|
||||
@@ -111,7 +111,7 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 0
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
# atom-dark-ui has an directory path, the syntax one doesn't
|
||||
atom.config.set('core.themes', ['theme-with-index-less', 'atom-dark-ui'])
|
||||
|
||||
@@ -208,7 +208,7 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.append $('<atom-text-editor>')
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
@@ -217,7 +217,7 @@ describe "ThemeManager", ->
|
||||
|
||||
it "loads the correct values from the theme's ui-variables file", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables'])
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
@@ -234,7 +234,7 @@ describe "ThemeManager", ->
|
||||
describe "when there is a theme with incomplete variables", ->
|
||||
it "loads the correct values from the fallback ui-variables", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-incomplete-ui-variables'])
|
||||
atom.config.set('core.themes', ['theme-with-incomplete-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
@@ -251,7 +251,7 @@ describe "ThemeManager", ->
|
||||
expect(atom.workspaceView).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables'])
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
@@ -259,7 +259,9 @@ describe "ThemeManager", ->
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(atom.workspaceView).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(atom.workspaceView).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(atom.workspaceView).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(atom.workspaceView).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
it "reloads it", ->
|
||||
@@ -308,24 +310,19 @@ describe "ThemeManager", ->
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a non-existent theme is present in the config", ->
|
||||
it "logs a warning but does not throw an exception (regression)", ->
|
||||
reloaded = false
|
||||
beforeEach ->
|
||||
spyOn(console, 'warn')
|
||||
atom.config.set('core.themes', ['non-existent-dark-ui', 'non-existent-dark-syntax'])
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
disposable = themeManager.onDidReloadAll ->
|
||||
disposable.dispose()
|
||||
reloaded = true
|
||||
spyOn(console, 'warn')
|
||||
expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow()
|
||||
|
||||
waitsFor -> reloaded
|
||||
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
|
||||
it 'uses the default dark UI and syntax themes and logs a warning', ->
|
||||
activeThemeNames = themeManager.getActiveNames()
|
||||
expect(console.warn.callCount).toBe 2
|
||||
expect(activeThemeNames.length).toBe(2)
|
||||
expect(activeThemeNames).toContain('atom-dark-ui')
|
||||
expect(activeThemeNames).toContain('atom-dark-syntax')
|
||||
|
||||
describe "when in safe mode", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -492,3 +492,12 @@ describe "Workspace", ->
|
||||
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
describe '::addModalPanel(model)', ->
|
||||
it 'adds a panel to the correct panel container', ->
|
||||
atom.workspace.panelContainers.modal.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = atom.workspace.addModalPanel(item: new TestPanel())
|
||||
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
expect(panel.getClassName()).toBe 'overlay from-top' # the default
|
||||
|
||||
@@ -13,7 +13,7 @@ describe "WorkspaceView", ->
|
||||
atom.project.setPaths([atom.project.resolve('dir')])
|
||||
pathToOpen = atom.project.resolve('a')
|
||||
atom.workspace = new Workspace
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.enableKeymap()
|
||||
atom.workspaceView.focus()
|
||||
|
||||
@@ -29,7 +29,7 @@ describe "WorkspaceView", ->
|
||||
atom.workspaceView.remove()
|
||||
atom.project = atom.deserializers.deserialize(projectState)
|
||||
atom.workspace = Workspace.deserialize(workspaceState)
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
describe "when the serialized WorkspaceView has an unsaved buffer", ->
|
||||
@@ -274,7 +274,7 @@ describe "WorkspaceView", ->
|
||||
describe 'panel containers', ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
workspaceElement = atom.workspace.getView(atom.workspace)
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
|
||||
it 'inserts panel container elements in the correct places in the DOM', ->
|
||||
leftContainer = workspaceElement.querySelector('atom-panel-container[location="left"]')
|
||||
@@ -286,3 +286,6 @@ describe "WorkspaceView", ->
|
||||
bottomContainer = workspaceElement.querySelector('atom-panel-container[location="bottom"]')
|
||||
expect(topContainer.nextSibling).toBe workspaceElement.paneContainer
|
||||
expect(bottomContainer.previousSibling).toBe workspaceElement.paneContainer
|
||||
|
||||
modalContainer = workspaceElement.querySelector('atom-panel-container[location="modal"]')
|
||||
expect(modalContainer.parentNode).toBe workspaceElement
|
||||
|
||||
+16
-1
@@ -140,6 +140,9 @@ class Atom extends Model
|
||||
# Public: A {DeserializerManager} instance
|
||||
deserializers: null
|
||||
|
||||
# Public: A {ViewRegistry} instance
|
||||
views: null
|
||||
|
||||
# Public: A {Workspace} instance
|
||||
workspace: null
|
||||
|
||||
@@ -174,6 +177,7 @@ class Atom extends Model
|
||||
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
|
||||
@lastUncaughtError = Array::slice.call(arguments)
|
||||
@emit 'uncaught-error', arguments...
|
||||
@emitter.emit 'did-throw-error', arguments...
|
||||
|
||||
@unsubscribe()
|
||||
@setBodyPlatformClass()
|
||||
@@ -182,6 +186,7 @@ class Atom extends Model
|
||||
|
||||
Config = require './config'
|
||||
KeymapManager = require './keymap-extensions'
|
||||
ViewRegistry = require './view-registry'
|
||||
CommandRegistry = require './command-registry'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
@@ -209,6 +214,7 @@ class Atom extends Model
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@commands = new CommandRegistry
|
||||
@views = new ViewRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@styles = new StyleManager
|
||||
document.head.appendChild(new StylesElement)
|
||||
@@ -242,6 +248,15 @@ class Atom extends Model
|
||||
onDidBeep: (callback) ->
|
||||
@emitter.on 'did-beep', callback
|
||||
|
||||
# Extended: Invoke the given callback whenever there is an unhandled error.
|
||||
#
|
||||
# * `callback` {Function} to be called whenever there is an unhandled error
|
||||
# * `errorMessage` {String}
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidThrowError: (callback) ->
|
||||
@emitter.on 'did-throw-error', callback
|
||||
|
||||
###
|
||||
Section: Atom Details
|
||||
###
|
||||
@@ -597,7 +612,7 @@ class Atom extends Model
|
||||
|
||||
startTime = Date.now()
|
||||
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
|
||||
@workspaceView = @workspace.getView(@workspace).__spacePenView
|
||||
@workspaceView = @views.getView(@workspace).__spacePenView
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
|
||||
@keymaps.defaultTarget = @workspaceView[0]
|
||||
|
||||
@@ -22,14 +22,10 @@ class ApplicationMenu
|
||||
# keystrokesByCommand - An Object where the keys are commands and the values
|
||||
# are Arrays containing the keystroke.
|
||||
update: (window, template, keystrokesByCommand) ->
|
||||
return unless window is @lastFocusedWindow
|
||||
|
||||
@translateTemplate(template, keystrokesByCommand)
|
||||
@substituteVersion(template)
|
||||
@windowTemplates.set(window, template)
|
||||
@setActiveTemplate(template)
|
||||
|
||||
@showUpdateMenuItem(global.atomApplication.autoUpdateManager.getState())
|
||||
@setActiveTemplate(template) if window is @lastFocusedWindow
|
||||
|
||||
setActiveTemplate: (template) ->
|
||||
unless _.isEqual(template, @activeTemplate)
|
||||
@@ -37,6 +33,8 @@ class ApplicationMenu
|
||||
@menu = Menu.buildFromTemplate(_.deepClone(template))
|
||||
Menu.setApplicationMenu(@menu)
|
||||
|
||||
@showUpdateMenuItem(global.atomApplication.autoUpdateManager.getState())
|
||||
|
||||
# Register a BrowserWindow with this application menu.
|
||||
addWindow: (window) ->
|
||||
@lastFocusedWindow ?= window
|
||||
|
||||
@@ -70,7 +70,7 @@ class AtomApplication
|
||||
|
||||
@autoUpdateManager = new AutoUpdateManager(@version)
|
||||
@applicationMenu = new ApplicationMenu(@version)
|
||||
@atomProtocolHandler = new AtomProtocolHandler(@resourcePath)
|
||||
@atomProtocolHandler = new AtomProtocolHandler(@resourcePath, @safeMode)
|
||||
|
||||
@listenForArgumentsFromNewProcess()
|
||||
@setupJavaScriptArguments()
|
||||
@@ -155,7 +155,13 @@ class AtomApplication
|
||||
atomWindow?.browserWindow.inspectElement(x, y)
|
||||
|
||||
@on 'application:open-documentation', -> require('shell').openExternal('https://atom.io/docs/latest/?app')
|
||||
@on 'application:open-discussions', -> require('shell').openExternal('https://discuss.atom.io')
|
||||
@on 'application:open-roadmap', -> require('shell').openExternal('https://atom.io/roadmap?app')
|
||||
@on 'application:open-faq', -> require('shell').openExternal('https://atom.io/faq')
|
||||
@on 'application:open-terms-of-use', -> require('shell').openExternal('https://atom.io/terms')
|
||||
@on 'application:report-issue', -> require('shell').openExternal('https://github.com/atom/atom/issues/new')
|
||||
@on 'application:search-issues', -> require('shell').openExternal('https://github.com/issues?q=+is%3Aissue+user%3Aatom')
|
||||
|
||||
@on 'application:install-update', -> @autoUpdateManager.install()
|
||||
@on 'application:check-for-update', => @autoUpdateManager.check()
|
||||
|
||||
|
||||
@@ -5,16 +5,26 @@ protocol = require 'protocol'
|
||||
|
||||
# Handles requests with 'atom' protocol.
|
||||
#
|
||||
# It's created by {AtomApplication} upon instantiation, and is used to create a
|
||||
# custom resource loader by adding the 'atom' custom protocol.
|
||||
# It's created by {AtomApplication} upon instantiation and is used to create a
|
||||
# custom resource loader for 'atom://' URLs.
|
||||
#
|
||||
# The following directories are searched in order:
|
||||
# * ~/.atom/assets
|
||||
# * ~/.atom/dev/packages (unless in safe mode)
|
||||
# * ~/.atom/packages
|
||||
# * RESOURCE_PATH/node_modules
|
||||
#
|
||||
module.exports =
|
||||
class AtomProtocolHandler
|
||||
constructor: (@resourcePath) ->
|
||||
@loadPaths = [
|
||||
path.join(app.getHomeDir(), '.atom', 'dev', 'packages')
|
||||
path.join(app.getHomeDir(), '.atom', 'packages')
|
||||
path.join(@resourcePath, 'node_modules')
|
||||
]
|
||||
constructor: (resourcePath, safeMode) ->
|
||||
@loadPaths = []
|
||||
@dotAtomDirectory = path.join(app.getHomeDir(), '.atom')
|
||||
|
||||
unless safeMode
|
||||
@loadPaths.push(path.join(@dotAtomDirectory, 'dev', 'packages'))
|
||||
|
||||
@loadPaths.push(path.join(@dotAtomDirectory, 'packages'))
|
||||
@loadPaths.push(path.join(resourcePath, 'node_modules'))
|
||||
|
||||
@registerAtomProtocol()
|
||||
|
||||
@@ -22,7 +32,14 @@ class AtomProtocolHandler
|
||||
registerAtomProtocol: ->
|
||||
protocol.registerProtocol 'atom', (request) =>
|
||||
relativePath = path.normalize(request.url.substr(7))
|
||||
for loadPath in @loadPaths
|
||||
filePath = path.join(loadPath, relativePath)
|
||||
break if fs.statSyncNoException(filePath).isFile?()
|
||||
return new protocol.RequestFileJob(filePath)
|
||||
|
||||
if relativePath.indexOf('assets/') is 0
|
||||
assetsPath = path.join(@dotAtomDirectory, relativePath)
|
||||
filePath = assetsPath if fs.statSyncNoException(assetsPath).isFile?()
|
||||
|
||||
unless filePath
|
||||
for loadPath in @loadPaths
|
||||
filePath = path.join(loadPath, relativePath)
|
||||
break if fs.statSyncNoException(filePath).isFile?()
|
||||
|
||||
new protocol.RequestFileJob(filePath)
|
||||
|
||||
@@ -134,6 +134,10 @@ parseCommandLine = ->
|
||||
unless fs.statSyncNoException(resourcePath)
|
||||
resourcePath = path.dirname(path.dirname(__dirname))
|
||||
|
||||
# On Yosemite the $PATH is not inherited by the "open" command, so we have to
|
||||
# explicitly pass it by command line, see http://git.io/YC8_Ew.
|
||||
process.env.PATH = args['path-environment'] if args['path-environment']
|
||||
|
||||
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile}
|
||||
|
||||
start()
|
||||
|
||||
@@ -35,9 +35,7 @@ SpecificityCache = {}
|
||||
# ```coffee
|
||||
# atom.commands.add 'atom-text-editor',
|
||||
# 'user:insert-date': (event) ->
|
||||
# editor = $(this).view().getModel()
|
||||
# # soon the above above line will be:
|
||||
# # editor = @getModel()
|
||||
# editor = @getModel()
|
||||
# editor.insertText(new Date().toLocaleString())
|
||||
# ```
|
||||
module.exports =
|
||||
@@ -130,25 +128,26 @@ class CommandRegistry
|
||||
# * `jQuery` Present if the command was registered with the legacy
|
||||
# `$::command` method.
|
||||
findCommands: ({target}) ->
|
||||
commandNames = new Set
|
||||
commands = []
|
||||
currentTarget = target
|
||||
loop
|
||||
for name, listeners of @inlineListenersByCommandName
|
||||
if listeners.has(currentTarget) and not commandNames.has(name)
|
||||
commandNames.add(name)
|
||||
commands.push({name, displayName: _.humanizeEventName(name)})
|
||||
|
||||
for commandName, listeners of @selectorBasedListenersByCommandName
|
||||
for listener in listeners
|
||||
if currentTarget.webkitMatchesSelector?(listener.selector)
|
||||
commands.push
|
||||
name: commandName
|
||||
displayName: _.humanizeEventName(commandName)
|
||||
unless commandNames.has(commandName)
|
||||
commandNames.add(commandName)
|
||||
commands.push
|
||||
name: commandName
|
||||
displayName: _.humanizeEventName(commandName)
|
||||
|
||||
break if currentTarget is @rootNode
|
||||
currentTarget = currentTarget.parentNode
|
||||
break unless currentTarget?
|
||||
|
||||
for name, displayName of $(target).events() when displayName
|
||||
commands.push({name, displayName, jQuery: true})
|
||||
|
||||
for name, displayName of $(window).events() when displayName
|
||||
commands.push({name, displayName, jQuery: true})
|
||||
break if currentTarget is window
|
||||
currentTarget = currentTarget.parentNode ? window
|
||||
|
||||
commands
|
||||
|
||||
|
||||
@@ -105,10 +105,20 @@ module.exports =
|
||||
scrollPastEnd:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
undoGroupingInterval:
|
||||
type: 'integer'
|
||||
default: 500
|
||||
minimum: 0
|
||||
description: 'Time interval in milliseconds within which operations will be grouped together in the undo history'
|
||||
useHardwareAcceleration:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
description: 'Disabling will improve editor font rendering but reduce scrolling performance.'
|
||||
useShadowDOM:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
title: 'Use Shadow DOM'
|
||||
description: 'Enable to test out themes and packages with the new shadow DOM before it ships by default.'
|
||||
confirmCheckoutHeadRevision:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
|
||||
+52
-44
@@ -392,7 +392,7 @@ class Cursor extends Model
|
||||
|
||||
# Public: Moves the cursor to the next word boundary.
|
||||
moveToNextWordBoundary: ->
|
||||
if position = @getMoveNextWordBoundaryBufferPosition()
|
||||
if position = @getNextWordBoundaryBufferPosition()
|
||||
@setBufferPosition(position)
|
||||
|
||||
# Public: Moves the cursor to the beginning of the buffer line, skipping all
|
||||
@@ -420,6 +420,57 @@ class Cursor extends Model
|
||||
Section: Local Positions and Ranges
|
||||
###
|
||||
|
||||
# Public: Retrieves buffer position of previous word boundary. It might be on
|
||||
# the current word, or the previous word.
|
||||
#
|
||||
# * `options` (optional) {Object} with the following keys:
|
||||
# * `wordRegex` A {RegExp} indicating what constitutes a "word"
|
||||
# (default: {::wordRegExp})
|
||||
getPreviousWordBoundaryBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
scanRange = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
|
||||
beginningOfWordPosition = null
|
||||
@editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
|
||||
if range.start.row < currentBufferPosition.row and currentBufferPosition.column > 0
|
||||
# force it to stop at the beginning of each line
|
||||
beginningOfWordPosition = new Point(currentBufferPosition.row, 0)
|
||||
else if range.end.isLessThan(currentBufferPosition)
|
||||
beginningOfWordPosition = range.end
|
||||
else
|
||||
beginningOfWordPosition = range.start
|
||||
|
||||
if not beginningOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
beginningOfWordPosition or currentBufferPosition
|
||||
|
||||
# Public: Retrieves buffer position of the next word boundary. It might be on
|
||||
# the current word, or the previous word.
|
||||
#
|
||||
# * `options` (optional) {Object} with the following keys:
|
||||
# * `wordRegex` A {RegExp} indicating what constitutes a "word"
|
||||
# (default: {::wordRegExp})
|
||||
getNextWordBoundaryBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
scanRange = [currentBufferPosition, @editor.getEofBufferPosition()]
|
||||
|
||||
endOfWordPosition = null
|
||||
@editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
|
||||
if range.start.row > currentBufferPosition.row
|
||||
# force it to stop at the beginning of each line
|
||||
endOfWordPosition = new Point(range.start.row, 0)
|
||||
else if range.start.isGreaterThan(currentBufferPosition)
|
||||
endOfWordPosition = range.start
|
||||
else
|
||||
endOfWordPosition = range.end
|
||||
|
||||
if not endOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
endOfWordPosition or currentBufferPosition
|
||||
|
||||
# Public: Retrieves the buffer position of where the current word starts.
|
||||
#
|
||||
# * `options` (optional) An {Object} with the following keys:
|
||||
@@ -452,49 +503,6 @@ class Cursor extends Model
|
||||
else
|
||||
currentBufferPosition
|
||||
|
||||
# Public: Retrieves buffer position of previous word boundary. It might be on
|
||||
# the current word, or the previous word.
|
||||
getPreviousWordBoundaryBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
scanRange = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
|
||||
beginningOfWordPosition = null
|
||||
@editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
|
||||
if range.start.row < currentBufferPosition.row and currentBufferPosition.column > 0
|
||||
# force it to stop at the beginning of each line
|
||||
beginningOfWordPosition = new Point(currentBufferPosition.row, 0)
|
||||
else if range.end.isLessThan(currentBufferPosition)
|
||||
beginningOfWordPosition = range.end
|
||||
else
|
||||
beginningOfWordPosition = range.start
|
||||
|
||||
if not beginningOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
beginningOfWordPosition or currentBufferPosition
|
||||
|
||||
# Public: Retrieves buffer position of the next word boundary. It might be on
|
||||
# the current word, or the previous word.
|
||||
getMoveNextWordBoundaryBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
scanRange = [currentBufferPosition, @editor.getEofBufferPosition()]
|
||||
|
||||
endOfWordPosition = null
|
||||
@editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
|
||||
if range.start.row > currentBufferPosition.row
|
||||
# force it to stop at the beginning of each line
|
||||
endOfWordPosition = new Point(range.start.row, 0)
|
||||
else if range.start.isGreaterThan(currentBufferPosition)
|
||||
endOfWordPosition = range.start
|
||||
else
|
||||
endOfWordPosition = range.end
|
||||
|
||||
if not endOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
endOfWordPosition or currentBufferPosition
|
||||
|
||||
# Public: Retrieves the buffer position of where the current word ends.
|
||||
#
|
||||
# * `options` (optional) {Object} with the following keys:
|
||||
|
||||
@@ -735,9 +735,7 @@ class DisplayBuffer extends Model
|
||||
#
|
||||
# Returns a {Point}.
|
||||
screenPositionForBufferPosition: (bufferPosition, options) ->
|
||||
# TODO: Expand this exception to cover all versions once we burn it in on non-release builds
|
||||
if @isDestroyed() and not atom.isReleasedVersion()
|
||||
throw new Error("This TextEditor has been destroyed")
|
||||
throw new Error("This TextEditor has been destroyed") if @isDestroyed()
|
||||
|
||||
{ row, column } = @buffer.clipPosition(bufferPosition)
|
||||
[startScreenRow, endScreenRow] = @rowMap.screenRowRangeForBufferRow(row)
|
||||
@@ -1077,8 +1075,9 @@ class DisplayBuffer extends Model
|
||||
|
||||
destroyed: ->
|
||||
marker.unsubscribe() for id, marker of @markers
|
||||
@tokenizedBuffer.destroy()
|
||||
@scopedConfigSubscriptions.dispose()
|
||||
@unsubscribe()
|
||||
@tokenizedBuffer.destroy()
|
||||
|
||||
logLines: (start=0, end=@getLastRow()) ->
|
||||
for row in [start..end]
|
||||
|
||||
@@ -16,12 +16,12 @@ GutterComponent = React.createClass
|
||||
measuredWidth: null
|
||||
|
||||
render: ->
|
||||
{scrollHeight, scrollViewHeight, onMouseDown, backgroundColor, gutterBackgroundColor} = @props
|
||||
{scrollHeight, scrollViewHeight, backgroundColor, gutterBackgroundColor} = @props
|
||||
|
||||
if gutterBackgroundColor isnt 'rbga(0, 0, 0, 0)'
|
||||
backgroundColor = gutterBackgroundColor
|
||||
|
||||
div className: 'gutter', onClick: @onClick, onMouseDown: @onMouseDown,
|
||||
div className: 'gutter',
|
||||
div className: 'line-numbers', ref: 'lineNumbers', style:
|
||||
height: Math.max(scrollHeight, scrollViewHeight)
|
||||
WebkitTransform: @getTransform()
|
||||
@@ -45,6 +45,10 @@ GutterComponent = React.createClass
|
||||
@appendDummyLineNumber()
|
||||
@updateLineNumbers() if @props.performedInitialMeasurement
|
||||
|
||||
node = @getDOMNode()
|
||||
node.addEventListener 'click', @onClick
|
||||
node.addEventListener 'mousedown', @onMouseDown
|
||||
|
||||
# Only update the gutter if the visible row range has changed or if a
|
||||
# non-zero-delta change to the screen lines has occurred within the current
|
||||
# visible row range.
|
||||
|
||||
@@ -21,5 +21,11 @@ HighlightsComponent = React.createClass
|
||||
|
||||
highlightComponents
|
||||
|
||||
componentDidMount: ->
|
||||
if atom.config.get('editor.useShadowDOM')
|
||||
insertionPoint = document.createElement('content')
|
||||
insertionPoint.setAttribute('select', '.underlayer')
|
||||
@getDOMNode().appendChild(insertionPoint)
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
not isEqualForProperties(newProps, @props, 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth', 'scopedCharacterWidthsChangeCount')
|
||||
|
||||
@@ -7,16 +7,17 @@ InputComponent = React.createClass
|
||||
displayName: 'InputComponent'
|
||||
|
||||
render: ->
|
||||
{className, style, onFocus, onBlur} = @props
|
||||
{className, style} = @props
|
||||
|
||||
input {className, style, onFocus, onBlur, 'data-react-skip-selection-restoration': true}
|
||||
input {className, style, 'data-react-skip-selection-restoration': true}
|
||||
|
||||
getInitialState: ->
|
||||
{lastChar: ''}
|
||||
|
||||
componentDidMount: ->
|
||||
@getDOMNode().addEventListener 'paste', @onPaste
|
||||
@getDOMNode().addEventListener 'compositionupdate', @onCompositionUpdate
|
||||
node = @getDOMNode()
|
||||
node.addEventListener 'paste', @onPaste
|
||||
node.addEventListener 'compositionupdate', @onCompositionUpdate
|
||||
|
||||
# Don't let text accumulate in the input forever, but avoid excessive reflows
|
||||
componentDidUpdate: ->
|
||||
@@ -34,11 +35,5 @@ InputComponent = React.createClass
|
||||
onPaste: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
onFocus: ->
|
||||
@props.onFocus?()
|
||||
|
||||
onBlur: ->
|
||||
@props.onBlur?()
|
||||
|
||||
focus: ->
|
||||
@getDOMNode().focus()
|
||||
|
||||
@@ -57,6 +57,12 @@ LinesComponent = React.createClass
|
||||
@lineIdsByScreenRow = {}
|
||||
@renderedDecorationsByLineId = {}
|
||||
|
||||
componentDidMount: ->
|
||||
if atom.config.get('editor.useShadowDOM')
|
||||
insertionPoint = document.createElement('content')
|
||||
insertionPoint.setAttribute('select', '.overlayer')
|
||||
@getDOMNode().appendChild(insertionPoint)
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
return true unless isEqualForProperties(newProps, @props,
|
||||
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
|
||||
|
||||
+17
-9
@@ -50,6 +50,7 @@ class Package
|
||||
keymaps: null
|
||||
menus: null
|
||||
stylesheets: null
|
||||
stylesheetDisposables: null
|
||||
grammars: null
|
||||
scopedProperties: null
|
||||
mainModulePath: null
|
||||
@@ -175,9 +176,17 @@ class Package
|
||||
activateStylesheets: ->
|
||||
return if @stylesheetsActivated
|
||||
|
||||
type = @getStylesheetType()
|
||||
for [stylesheetPath, content] in @stylesheets
|
||||
atom.themes.applyStylesheet(stylesheetPath, content, type)
|
||||
group = @getStylesheetType()
|
||||
@stylesheetDisposables = new CompositeDisposable
|
||||
for [sourcePath, source] in @stylesheets
|
||||
if match = path.basename(sourcePath).match(/[^.]*\.([^.]*)\./)
|
||||
context = match[1]
|
||||
else if @metadata.theme is 'syntax'
|
||||
context = 'atom-text-editor'
|
||||
else
|
||||
context = undefined
|
||||
|
||||
@stylesheetDisposables.add(atom.styles.addStyleSheet(source, {sourcePath, group, context}))
|
||||
@stylesheetsActivated = true
|
||||
|
||||
activateResources: ->
|
||||
@@ -320,7 +329,7 @@ class Package
|
||||
deactivateResources: ->
|
||||
grammar.deactivate() for grammar in @grammars
|
||||
scopedProperties.deactivate() for scopedProperties in @scopedProperties
|
||||
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
|
||||
@stylesheetDisposables?.dispose()
|
||||
@activationDisposables?.dispose()
|
||||
@stylesheetsActivated = false
|
||||
@grammarsActivated = false
|
||||
@@ -329,11 +338,10 @@ class Package
|
||||
reloadStylesheets: ->
|
||||
oldSheets = _.clone(@stylesheets)
|
||||
@loadStylesheets()
|
||||
atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
|
||||
@reloadStylesheet(stylesheetPath, content) for [stylesheetPath, content] in @stylesheets
|
||||
|
||||
reloadStylesheet: (stylesheetPath, content) ->
|
||||
atom.themes.applyStylesheet(stylesheetPath, content, @getStylesheetType())
|
||||
@stylesheetDisposables.dispose()
|
||||
@stylesheetDisposables = new CompositeDisposable
|
||||
@stylesheetsActivated = false
|
||||
@activateStylesheets()
|
||||
|
||||
requireMainModule: ->
|
||||
return @mainModule if @mainModule?
|
||||
|
||||
@@ -40,6 +40,8 @@ class PaneContainer extends Model
|
||||
@registerViewProviders()
|
||||
|
||||
@setRoot(params?.root ? new Pane)
|
||||
@setActivePane(@getPanes()[0]) unless @getActivePane()
|
||||
|
||||
@destroyEmptyPanes() if params?.destroyEmptyPanes
|
||||
|
||||
@monitorActivePaneItem()
|
||||
@@ -137,6 +139,9 @@ class PaneContainer extends Model
|
||||
|
||||
setActivePane: (activePane) ->
|
||||
if activePane isnt @activePane
|
||||
unless activePane in @getPanes()
|
||||
throw new Error("Setting active pane that is not present in pane container")
|
||||
|
||||
@activePane = activePane
|
||||
@emitter.emit 'did-change-active-pane', @activePane
|
||||
@activePane
|
||||
@@ -147,6 +152,9 @@ class PaneContainer extends Model
|
||||
paneForUri: (uri) ->
|
||||
find @getPanes(), (pane) -> pane.itemForUri(uri)?
|
||||
|
||||
paneForItem: (item) ->
|
||||
@getPanes().find (pane) -> item in pane.getItems()
|
||||
|
||||
saveAll: ->
|
||||
pane.saveItems() for pane in @getPanes()
|
||||
|
||||
|
||||
+37
-33
@@ -28,39 +28,21 @@ class PaneElement extends HTMLElement
|
||||
@itemViews.setAttribute 'class', 'item-views'
|
||||
|
||||
subscribeToDOMEvents: ->
|
||||
@addEventListener 'focusin', => @model.focus()
|
||||
@addEventListener 'focusout', => @model.blur()
|
||||
@addEventListener 'focus', => @getActiveView()?.focus()
|
||||
handleFocus = (event) =>
|
||||
@model.focus()
|
||||
if event.target is this and view = @getActiveView()
|
||||
view.focus()
|
||||
event.stopPropagation()
|
||||
|
||||
handleBlur = (event) =>
|
||||
@model.blur() unless @contains(event.relatedTarget)
|
||||
|
||||
@addEventListener 'focus', handleFocus, true
|
||||
@addEventListener 'blur', handleBlur, true
|
||||
|
||||
createSpacePenShim: ->
|
||||
@__spacePenView = new PaneView(this)
|
||||
|
||||
addCommands = (handlersByName) =>
|
||||
for name, handler of handlersByName
|
||||
do (handler) =>
|
||||
@__spacePenView.command name, => handler.apply(this, arguments)
|
||||
|
||||
addCommands(
|
||||
'pane:save-items': -> @getModel().saveItems()
|
||||
'pane:show-next-item': -> @getModel().activateNextItem()
|
||||
'pane:show-previous-item': -> @getModel().activatePreviousItem()
|
||||
'pane:show-item-1': -> @getModel().activateItemAtIndex(0)
|
||||
'pane:show-item-2': -> @getModel().activateItemAtIndex(1)
|
||||
'pane:show-item-3': -> @getModel().activateItemAtIndex(2)
|
||||
'pane:show-item-4': -> @getModel().activateItemAtIndex(3)
|
||||
'pane:show-item-5': -> @getModel().activateItemAtIndex(4)
|
||||
'pane:show-item-6': -> @getModel().activateItemAtIndex(5)
|
||||
'pane:show-item-7': -> @getModel().activateItemAtIndex(6)
|
||||
'pane:show-item-8': -> @getModel().activateItemAtIndex(7)
|
||||
'pane:show-item-9': -> @getModel().activateItemAtIndex(8)
|
||||
'pane:split-left': -> @getModel().splitLeft(copyActiveItem: true)
|
||||
'pane:split-right': -> @getModel().splitRight(copyActiveItem: true)
|
||||
'pane:split-up': -> @getModel().splitUp(copyActiveItem: true)
|
||||
'pane:split-down': -> @getModel().splitDown(copyActiveItem: true)
|
||||
'pane:close': -> @getModel().destroy()
|
||||
'pane:close-other-items': -> @getModel().destroyInactiveItems()
|
||||
)
|
||||
|
||||
getModel: -> @model
|
||||
|
||||
setModel: (@model) ->
|
||||
@@ -86,16 +68,16 @@ class PaneElement extends HTMLElement
|
||||
hasFocus = @hasFocus()
|
||||
itemView = @model.getView(item)
|
||||
|
||||
unless @itemViews.contains(itemView)
|
||||
@itemViews.appendChild(itemView)
|
||||
callAttachHooks(itemView)
|
||||
|
||||
for child in @itemViews.children
|
||||
if child is itemView
|
||||
@showItemView(child) if @attached
|
||||
else
|
||||
@hideItemView(child)
|
||||
|
||||
unless @itemViews.contains(itemView)
|
||||
@itemViews.appendChild(itemView)
|
||||
callAttachHooks(itemView)
|
||||
|
||||
itemView.focus() if hasFocus
|
||||
|
||||
showItemView: (itemView) ->
|
||||
@@ -124,4 +106,26 @@ class PaneElement extends HTMLElement
|
||||
hasFocus: ->
|
||||
this is document.activeElement or @contains(document.activeElement)
|
||||
|
||||
atom.commands.add 'atom-pane',
|
||||
'pane:save-items': -> @getModel().saveItems()
|
||||
'pane:show-next-item': -> @getModel().activateNextItem()
|
||||
'pane:show-previous-item': -> @getModel().activatePreviousItem()
|
||||
'pane:show-item-1': -> @getModel().activateItemAtIndex(0)
|
||||
'pane:show-item-2': -> @getModel().activateItemAtIndex(1)
|
||||
'pane:show-item-3': -> @getModel().activateItemAtIndex(2)
|
||||
'pane:show-item-4': -> @getModel().activateItemAtIndex(3)
|
||||
'pane:show-item-5': -> @getModel().activateItemAtIndex(4)
|
||||
'pane:show-item-6': -> @getModel().activateItemAtIndex(5)
|
||||
'pane:show-item-7': -> @getModel().activateItemAtIndex(6)
|
||||
'pane:show-item-8': -> @getModel().activateItemAtIndex(7)
|
||||
'pane:show-item-9': -> @getModel().activateItemAtIndex(8)
|
||||
'pane:move-item-right': -> @getModel().moveItemRight()
|
||||
'pane:move-item-left': -> @getModel().moveItemLeft()
|
||||
'pane:split-left': -> @getModel().splitLeft(copyActiveItem: true)
|
||||
'pane:split-right': -> @getModel().splitRight(copyActiveItem: true)
|
||||
'pane:split-up': -> @getModel().splitUp(copyActiveItem: true)
|
||||
'pane:split-down': -> @getModel().splitDown(copyActiveItem: true)
|
||||
'pane:close': -> @getModel().close()
|
||||
'pane:close-other-items': -> @getModel().destroyInactiveItems()
|
||||
|
||||
module.exports = PaneElement = document.registerElement 'atom-pane', prototype: PaneElement.prototype
|
||||
|
||||
@@ -119,7 +119,7 @@ class PaneView extends View
|
||||
deprecate 'Please return a Disposable object from your ::onDidChangeTitle method!' unless disposable?.dispose?
|
||||
@activeItemDisposables.add(disposable) if disposable?.dispose?
|
||||
else if item.on?
|
||||
deprecate '::on methods for items are no longer supported. If you would like your item to support title change behavior, please implement a ::onDidChangeTitle() method.'
|
||||
deprecate 'If you would like your pane item to support title change behavior, please implement a ::onDidChangeTitle() method. ::on methods for items are no longer supported. If not, ignore this message.'
|
||||
disposable = item.on('title-changed', @activeItemTitleChanged)
|
||||
@activeItemDisposables.add(disposable) if disposable?.dispose?
|
||||
|
||||
@@ -128,16 +128,10 @@ class PaneView extends View
|
||||
deprecate 'Please return a Disposable object from your ::onDidChangeModified method!' unless disposable?.dispose?
|
||||
@activeItemDisposables.add(disposable) if disposable?.dispose?
|
||||
else if item.on?
|
||||
deprecate '::on methods for items are no longer supported. If you would like your item to support modified behavior, please implement a ::onDidChangeModified() method.'
|
||||
deprecate 'If you would like your pane item to support modified behavior, please implement a ::onDidChangeModified() method. If not, ignore this message. ::on methods for items are no longer supported.'
|
||||
item.on('modified-status-changed', @activeItemModifiedChanged)
|
||||
@activeItemDisposables.add(disposable) if disposable?.dispose?
|
||||
|
||||
view = @model.getView(item).__spacePenView
|
||||
otherView.hide() for otherView in @itemViews.children().not(view).views()
|
||||
@itemViews.append(view) unless view.parent().is(@itemViews)
|
||||
view.show() if @attached
|
||||
view.focus() if @hasFocus()
|
||||
|
||||
@trigger 'pane:active-item-changed', [item]
|
||||
|
||||
onItemAdded: ({item, index}) =>
|
||||
|
||||
@@ -289,6 +289,18 @@ class Pane extends Model
|
||||
else
|
||||
@activateItemAtIndex(@items.length - 1)
|
||||
|
||||
# Public: Move the active tab to the right.
|
||||
moveItemRight: ->
|
||||
index = @getActiveItemIndex()
|
||||
rightItemIndex = index + 1
|
||||
@moveItem(@getActiveItem(), rightItemIndex) unless rightItemIndex > @items.length - 1
|
||||
|
||||
# Public: Move the active tab to the left
|
||||
moveItemLeft: ->
|
||||
index = @getActiveItemIndex()
|
||||
leftItemIndex = index - 1
|
||||
@moveItem(@getActiveItem(), leftItemIndex) unless leftItemIndex < 0
|
||||
|
||||
# Public: Get the index of the active item.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
@@ -502,6 +514,8 @@ class Pane extends Model
|
||||
|
||||
# Public: Makes this pane the *active* pane, causing it to gain focus.
|
||||
activate: ->
|
||||
throw new Error("Pane has been destroyed") if @isDestroyed()
|
||||
|
||||
@container?.setActivePane(this)
|
||||
@emit 'activated'
|
||||
@emitter.emit 'did-activate'
|
||||
@@ -606,3 +620,11 @@ class Pane extends Model
|
||||
rightmostSibling
|
||||
else
|
||||
@splitRight()
|
||||
|
||||
close: ->
|
||||
@destroy() if @confirmClose()
|
||||
|
||||
confirmClose: ->
|
||||
for item in @getItems()
|
||||
return false unless @promptToSaveItem(item)
|
||||
true
|
||||
|
||||
@@ -14,17 +14,29 @@ class PanelContainerElement extends HTMLElement
|
||||
@setAttribute('location', @model.getLocation())
|
||||
|
||||
panelAdded: ({panel, index}) ->
|
||||
panelElement = panel.getView()
|
||||
panelElement.setAttribute('location', @model.getLocation())
|
||||
if index >= @childNodes.length
|
||||
@appendChild(panel.getView())
|
||||
@appendChild(panelElement)
|
||||
else
|
||||
referenceItem = @childNodes[index + 1]
|
||||
@insertBefore(panel.getView(), referenceItem)
|
||||
@insertBefore(panelElement, referenceItem)
|
||||
|
||||
if @model.isModal()
|
||||
@hideAllPanelsExcept(panel)
|
||||
@subscriptions.add panel.onDidChangeVisible (visible) =>
|
||||
@hideAllPanelsExcept(panel) if visible
|
||||
|
||||
panelRemoved: ({panel, index}) ->
|
||||
@removeChild(@childNodes[index])
|
||||
@removeChild(panel.getView())
|
||||
|
||||
destroyed: ->
|
||||
@subscriptions.dispose()
|
||||
@parentNode?.removeChild(this)
|
||||
|
||||
hideAllPanelsExcept: (excludedPanel) ->
|
||||
for panel in @model.getPanels()
|
||||
panel.hide() unless panel is excludedPanel
|
||||
return
|
||||
|
||||
module.exports = PanelContainerElement = document.registerElement 'atom-panel-container', prototype: PanelContainerElement.prototype
|
||||
|
||||
@@ -8,7 +8,7 @@ class PanelContainer
|
||||
@panels = []
|
||||
|
||||
destroy: ->
|
||||
pane.destroy() for pane in @getPanels()
|
||||
panel.destroy() for panel in @getPanels()
|
||||
@subscriptions.dispose()
|
||||
@emitter.emit 'did-destroy', this
|
||||
@emitter.dispose()
|
||||
@@ -34,10 +34,12 @@ class PanelContainer
|
||||
|
||||
getLocation: -> @location
|
||||
|
||||
isModal: -> @location is 'modal'
|
||||
|
||||
getPanels: -> @panels
|
||||
|
||||
addPanel: (panel) ->
|
||||
@subscriptions.add panel.onDidDestroy(@panelDestoryed.bind(this))
|
||||
@subscriptions.add panel.onDidDestroy(@panelDestroyed.bind(this))
|
||||
|
||||
index = @getPanelIndex(panel)
|
||||
if index is @panels.length
|
||||
@@ -48,7 +50,7 @@ class PanelContainer
|
||||
@emitter.emit 'did-add-panel', {panel, index}
|
||||
panel
|
||||
|
||||
panelDestoryed: (panel) ->
|
||||
panelDestroyed: (panel) ->
|
||||
index = @panels.indexOf(panel)
|
||||
if index > -1
|
||||
@panels.splice(index, 1)
|
||||
|
||||
@@ -12,6 +12,7 @@ class PanelElement extends HTMLElement
|
||||
@appendChild(view)
|
||||
callAttachHooks(view) # for backward compatibility with SpacePen views
|
||||
|
||||
@classList.add(@model.getClassName().split(' ')...) if @model.getClassName()?
|
||||
@subscriptions.add @model.onDidChangeVisible(@visibleChanged.bind(this))
|
||||
@subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
|
||||
|
||||
|
||||
+4
-1
@@ -14,7 +14,7 @@ class Panel
|
||||
Section: Construction and Destruction
|
||||
###
|
||||
|
||||
constructor: ({@viewRegistry, @item, @visible, @priority}) ->
|
||||
constructor: ({@viewRegistry, @item, @visible, @priority, @className}) ->
|
||||
@emitter = new Emitter
|
||||
@visible ?= true
|
||||
@priority ?= 100
|
||||
@@ -22,6 +22,7 @@ class Panel
|
||||
# Public: Destroy and remove this panel from the UI.
|
||||
destroy: ->
|
||||
@emitter.emit 'did-destroy', this
|
||||
@emitter.dispose()
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
@@ -62,6 +63,8 @@ class Panel
|
||||
# Public: Returns a {Number} indicating this panel's priority.
|
||||
getPriority: -> @priority
|
||||
|
||||
getClassName: -> @className
|
||||
|
||||
# Public: Returns a {Boolean} true when the panel is visible.
|
||||
isVisible: -> @visible
|
||||
|
||||
|
||||
@@ -196,7 +196,8 @@ class Project extends Model
|
||||
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
|
||||
exclusions: atom.config.get('core.ignoredNames')
|
||||
|
||||
task = Task.once require.resolve('./scan-handler'), @getPath(), regex.source, searchOptions, ->
|
||||
# TODO: need to support all paths in @getPaths()
|
||||
task = Task.once require.resolve('./scan-handler'), @getPaths()[0], regex.source, searchOptions, ->
|
||||
deferred.resolve()
|
||||
|
||||
task.on 'scan:result-found', (result) =>
|
||||
|
||||
@@ -23,7 +23,7 @@ ScrollbarComponent = React.createClass
|
||||
style.right = verticalScrollbarWidth if scrollableInOppositeDirection
|
||||
style.height = horizontalScrollbarHeight
|
||||
|
||||
div {className, style, @onScroll},
|
||||
div {className, style},
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
div className: 'scrollbar-content', style: {height: scrollHeight}
|
||||
@@ -36,6 +36,11 @@ ScrollbarComponent = React.createClass
|
||||
unless orientation is 'vertical' or orientation is 'horizontal'
|
||||
throw new Error("Must specify an orientation property of 'vertical' or 'horizontal'")
|
||||
|
||||
@getDOMNode().addEventListener 'scroll', @onScroll
|
||||
|
||||
componentWillUnmount: ->
|
||||
@getDOMNode().removeEventListener 'scroll', @onScroll
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
return true if newProps.visible isnt @props.visible
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ class SelectListView extends View
|
||||
initialize: ->
|
||||
@filterEditorView.getEditor().getBuffer().onDidChange =>
|
||||
@schedulePopulateList()
|
||||
@filterEditorView.hiddenInput.on 'focusout', =>
|
||||
@filterEditorView.on 'blur', =>
|
||||
@cancel() unless @cancelling
|
||||
|
||||
# This prevents the focusout event from firing on the filter editor view
|
||||
@@ -254,7 +254,7 @@ class SelectListView extends View
|
||||
# Extended: Store the currently focused element. This element will be given
|
||||
# back focus when {::cancel} is called.
|
||||
storeFocusedElement: ->
|
||||
@previouslyFocusedElement = $(':focus')
|
||||
@previouslyFocusedElement = $(document.activeElement)
|
||||
|
||||
###
|
||||
Section: Private
|
||||
|
||||
@@ -322,7 +322,7 @@ class Selection extends Model
|
||||
# * `row` The line {Number} to select (default: the row of the cursor).
|
||||
selectLine: (row=@cursor.getBufferPosition().row) ->
|
||||
range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
|
||||
@setBufferRange(@getBufferRange().union(range))
|
||||
@setBufferRange(@getBufferRange().union(range), autoscroll: true)
|
||||
@linewise = true
|
||||
@wordwise = false
|
||||
@initialScreenRange = @getScreenRange()
|
||||
@@ -348,6 +348,7 @@ class Selection extends Model
|
||||
# * `autoIndentNewline` if `true`, indent newline appropriately.
|
||||
# * `autoDecreaseIndent` if `true`, decreases indent level appropriately
|
||||
# (for example, when a closing bracket is inserted).
|
||||
# * `normalizeLineEndings` (optional) {Boolean} (default: true)
|
||||
# * `undo` if `skip`, skips the undo stack for this operation.
|
||||
insertText: (text, options={}) ->
|
||||
oldBufferRange = @getBufferRange()
|
||||
@@ -359,7 +360,7 @@ class Selection extends Model
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
text = @normalizeIndents(text, options.indentBasis)
|
||||
|
||||
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo'))
|
||||
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo', 'normalizeLineEndings'))
|
||||
|
||||
if options.select
|
||||
@setBufferRange(newBufferRange, reversed: wasReversed)
|
||||
|
||||
@@ -7,7 +7,7 @@ Subscriber.includeInto(SpacePen.View)
|
||||
jQuery = SpacePen.jQuery
|
||||
JQueryCleanData = jQuery.cleanData
|
||||
jQuery.cleanData = (elements) ->
|
||||
jQuery(element).view()?.unsubscribe() for element in elements
|
||||
jQuery(element).view()?.unsubscribe?() for element in elements
|
||||
JQueryCleanData(elements)
|
||||
|
||||
SpacePenCallRemoveHooks = SpacePen.callRemoveHooks
|
||||
@@ -20,13 +20,16 @@ NativeEventNames.add(nativeEvent) for nativeEvent in ["blur", "focus", "focusin"
|
||||
"focusout", "load", "resize", "scroll", "unload", "click", "dblclick", "mousedown",
|
||||
"mouseup", "mousemove", "mouseover", "mouseout", "mouseenter", "mouseleave", "change",
|
||||
"select", "submit", "keydown", "keypress", "keyup", "error", "contextmenu", "textInput",
|
||||
"textinput"]
|
||||
"textinput", "beforeunload"]
|
||||
|
||||
JQueryTrigger = jQuery.fn.trigger
|
||||
jQuery.fn.trigger = (eventName, data) ->
|
||||
if NativeEventNames.has(eventName) or typeof eventName is 'object'
|
||||
JQueryTrigger.call(this, eventName, data)
|
||||
else
|
||||
data ?= {}
|
||||
data.jQueryTrigger = true
|
||||
|
||||
for element in this
|
||||
atom.commands.dispatch(element, eventName, data)
|
||||
this
|
||||
@@ -78,6 +81,18 @@ jQuery.event.remove = (elem, types, originalHandler, selector, mappedTypes) ->
|
||||
handler = HandlersByOriginalHandler.get(originalHandler) ? originalHandler
|
||||
JQueryEventRemove(elem, types, handler, selector, mappedTypes, RemoveEventListener if atom?.commands?)
|
||||
|
||||
JQueryContains = jQuery.contains
|
||||
|
||||
jQuery.contains = (a, b) ->
|
||||
shadowRoot = null
|
||||
currentNode = b
|
||||
while currentNode
|
||||
if currentNode instanceof ShadowRoot and a.contains(currentNode.host)
|
||||
return true
|
||||
currentNode = currentNode.parentNode
|
||||
|
||||
JQueryContains.call(this, a, b)
|
||||
|
||||
tooltipDefaults =
|
||||
delay:
|
||||
show: 1000
|
||||
|
||||
@@ -25,6 +25,7 @@ class StyleManager
|
||||
|
||||
addStyleSheet: (source, params) ->
|
||||
sourcePath = params?.sourcePath
|
||||
context = params?.context
|
||||
group = params?.group
|
||||
|
||||
if sourcePath? and styleElement = @styleElementsBySourcePath[sourcePath]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{Emitter, CompositeDisposable} = require 'event-kit'
|
||||
|
||||
class StylesElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@emitter = new Emitter
|
||||
subscriptions: null
|
||||
context: null
|
||||
|
||||
onDidAddStyleElement: (callback) ->
|
||||
@emitter.on 'did-add-style-element', callback
|
||||
@@ -13,15 +13,42 @@ class StylesElement extends HTMLElement
|
||||
onDidUpdateStyleElement: (callback) ->
|
||||
@emitter.on 'did-update-style-element', callback
|
||||
|
||||
attachedCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
createdCallback: ->
|
||||
@emitter = new Emitter
|
||||
@styleElementClonesByOriginalElement = new WeakMap
|
||||
|
||||
attachedCallback: ->
|
||||
@initialize()
|
||||
|
||||
detachedCallback: ->
|
||||
@subscriptions.dispose()
|
||||
@subscriptions = null
|
||||
|
||||
attributeChangedCallback: (attrName, oldVal, newVal) ->
|
||||
@contextChanged() if attrName is 'context'
|
||||
|
||||
initialize: ->
|
||||
return if @subscriptions?
|
||||
|
||||
@subscriptions = new CompositeDisposable
|
||||
@context = @getAttribute('context') ? undefined
|
||||
|
||||
@subscriptions.add atom.styles.observeStyleElements(@styleElementAdded.bind(this))
|
||||
@subscriptions.add atom.styles.onDidRemoveStyleElement(@styleElementRemoved.bind(this))
|
||||
@subscriptions.add atom.styles.onDidUpdateStyleElement(@styleElementUpdated.bind(this))
|
||||
|
||||
contextChanged: ->
|
||||
return unless @subscriptions?
|
||||
|
||||
@styleElementRemoved(child) for child in Array::slice.call(@children)
|
||||
@context = @getAttribute('context')
|
||||
@styleElementAdded(styleElement) for styleElement in atom.styles.getStyleElements()
|
||||
|
||||
styleElementAdded: (styleElement) ->
|
||||
return unless @styleElementMatchesContext(styleElement)
|
||||
|
||||
styleElementClone = styleElement.cloneNode(true)
|
||||
styleElementClone.context = styleElement.context
|
||||
@styleElementClonesByOriginalElement.set(styleElement, styleElementClone)
|
||||
|
||||
group = styleElement.getAttribute('group')
|
||||
@@ -35,16 +62,20 @@ class StylesElement extends HTMLElement
|
||||
@emitter.emit 'did-add-style-element', styleElementClone
|
||||
|
||||
styleElementRemoved: (styleElement) ->
|
||||
styleElementClone = @styleElementClonesByOriginalElement.get(styleElement)
|
||||
return unless @styleElementMatchesContext(styleElement)
|
||||
|
||||
styleElementClone = @styleElementClonesByOriginalElement.get(styleElement) ? styleElement
|
||||
styleElementClone.remove()
|
||||
@emitter.emit 'did-remove-style-element', styleElementClone
|
||||
|
||||
styleElementUpdated: (styleElement) ->
|
||||
return unless @styleElementMatchesContext(styleElement)
|
||||
|
||||
styleElementClone = @styleElementClonesByOriginalElement.get(styleElement)
|
||||
styleElementClone.textContent = styleElement.textContent
|
||||
@emitter.emit 'did-update-style-element', styleElementClone
|
||||
|
||||
detachedCallback: ->
|
||||
@subscriptions.dispose()
|
||||
styleElementMatchesContext: (styleElement) ->
|
||||
not @context? or styleElement.context is @context
|
||||
|
||||
module.exports = StylesElement = document.registerElement 'atom-styles', prototype: StylesElement.prototype
|
||||
|
||||
@@ -93,7 +93,7 @@ TextEditorComponent = React.createClass
|
||||
className += ' is-focused' if focused
|
||||
className += ' has-selection' if hasSelection
|
||||
|
||||
div {className, style, tabIndex: -1},
|
||||
div {className, style},
|
||||
if @shouldRenderGutter()
|
||||
GutterComponent {
|
||||
ref: 'gutter', onMouseDown: @onGutterMouseDown, lineDecorations,
|
||||
@@ -102,13 +102,11 @@ TextEditorComponent = React.createClass
|
||||
@useHardwareAcceleration, @performedInitialMeasurement, @backgroundColor, @gutterBackgroundColor
|
||||
}
|
||||
|
||||
div ref: 'scrollView', className: 'scroll-view', onMouseDown: @onMouseDown,
|
||||
div ref: 'scrollView', className: 'scroll-view',
|
||||
InputComponent
|
||||
ref: 'input'
|
||||
className: 'hidden-input'
|
||||
style: hiddenInputStyle
|
||||
onFocus: @onInputFocused
|
||||
onBlur: @onInputBlurred
|
||||
|
||||
LinesComponent {
|
||||
ref: 'lines',
|
||||
@@ -175,16 +173,16 @@ TextEditorComponent = React.createClass
|
||||
@setScrollSensitivity(atom.config.get('editor.scrollSensitivity'))
|
||||
|
||||
componentDidMount: ->
|
||||
{editor} = @props
|
||||
{editor, stylesElement} = @props
|
||||
|
||||
@observeEditor()
|
||||
@listenForDOMEvents()
|
||||
|
||||
@subscribe atom.themes.onDidAddStylesheet @onStylesheetsChanged
|
||||
@subscribe atom.themes.onDidUpdateStylesheet @onStylesheetsChanged
|
||||
@subscribe atom.themes.onDidRemoveStylesheet @onStylesheetsChanged
|
||||
@subscribe stylesElement.onDidAddStyleElement @onStylesheetsChanged
|
||||
@subscribe stylesElement.onDidUpdateStyleElement @onStylesheetsChanged
|
||||
@subscribe stylesElement.onDidRemoveStyleElement @onStylesheetsChanged
|
||||
unless atom.themes.isInitialLoadComplete()
|
||||
@subscribe atom.themes.onDidReloadAll @onStylesheetsChanged
|
||||
@subscribe atom.themes.onDidReloadAll @onAllThemesLoaded
|
||||
@subscribe scrollbarStyle.changes, @refreshScrollbars
|
||||
|
||||
@domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval)
|
||||
@@ -193,10 +191,11 @@ TextEditorComponent = React.createClass
|
||||
@checkForVisibilityChange()
|
||||
|
||||
componentWillUnmount: ->
|
||||
{editor, parentView} = @props
|
||||
{editor, hostElement} = @props
|
||||
|
||||
parentView.__spacePenView.trigger 'editor:will-be-removed', [parentView.__spacePenView]
|
||||
hostElement.__spacePenView.trigger 'editor:will-be-removed', [hostElement.__spacePenView]
|
||||
@unsubscribe()
|
||||
@scopedConfigSubscriptions.dispose()
|
||||
window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
clearInterval(@domPollingIntervalId)
|
||||
@domPollingIntervalId = null
|
||||
@@ -214,9 +213,9 @@ TextEditorComponent = React.createClass
|
||||
if @props.editor.isAlive()
|
||||
@updateParentViewFocusedClassIfNeeded(prevState)
|
||||
@updateParentViewMiniClassIfNeeded(prevState)
|
||||
@props.parentView.__spacePenView.trigger 'cursor:moved' if cursorMoved
|
||||
@props.parentView.__spacePenView.trigger 'selection:changed' if selectionChanged
|
||||
@props.parentView.__spacePenView.trigger 'editor:display-updated'
|
||||
@props.hostElement.__spacePenView.trigger 'cursor:moved' if cursorMoved
|
||||
@props.hostElement.__spacePenView.trigger 'selection:changed' if selectionChanged
|
||||
@props.hostElement.__spacePenView.trigger 'editor:display-updated'
|
||||
|
||||
becameVisible: ->
|
||||
@updatesPaused = true
|
||||
@@ -260,7 +259,7 @@ TextEditorComponent = React.createClass
|
||||
@forceUpdate()
|
||||
|
||||
getTopmostDOMNode: ->
|
||||
@props.parentView
|
||||
@props.hostElement
|
||||
|
||||
getRenderedRowRange: ->
|
||||
{editor, lineOverdrawMargin} = @props
|
||||
@@ -377,8 +376,8 @@ TextEditorComponent = React.createClass
|
||||
listenForDOMEvents: ->
|
||||
node = @getDOMNode()
|
||||
node.addEventListener 'mousewheel', @onMouseWheel
|
||||
node.addEventListener 'focus', @onFocus # For some reason, React's built in focus events seem to bubble
|
||||
node.addEventListener 'textInput', @onTextInput
|
||||
@refs.scrollView.getDOMNode().addEventListener 'mousedown', @onMouseDown
|
||||
|
||||
scrollViewNode = @refs.scrollView.getDOMNode()
|
||||
scrollViewNode.addEventListener 'scroll', @onScrollViewScroll
|
||||
@@ -414,6 +413,9 @@ TextEditorComponent = React.createClass
|
||||
|
||||
observeConfig: ->
|
||||
@subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration
|
||||
@subscribe atom.config.onDidChange 'editor.fontSize', @sampleFontStyling
|
||||
@subscribe atom.config.onDidChange 'editor.fontFamily', @sampleFontStyling
|
||||
@subscribe atom.config.onDidChange 'editor.lineHeight', @sampleFontStyling
|
||||
|
||||
onGrammarChanged: ->
|
||||
{editor} = @props
|
||||
@@ -427,8 +429,14 @@ TextEditorComponent = React.createClass
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.showLineNumbers', @setShowLineNumbers
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.scrollSensitivity', @setScrollSensitivity
|
||||
|
||||
onFocus: ->
|
||||
@refs.input.focus() if @isMounted()
|
||||
focused: ->
|
||||
if @isMounted()
|
||||
@setState(focused: true)
|
||||
@refs.input.focus()
|
||||
|
||||
blurred: ->
|
||||
if @isMounted()
|
||||
@setState(focused: false)
|
||||
|
||||
onTextInput: (event) ->
|
||||
event.stopPropagation()
|
||||
@@ -449,13 +457,9 @@ TextEditorComponent = React.createClass
|
||||
selectedLength = inputNode.selectionEnd - inputNode.selectionStart
|
||||
editor.selectLeft() if selectedLength is 1
|
||||
|
||||
inputNode.value = event.data if editor.insertText(event.data)
|
||||
|
||||
onInputFocused: ->
|
||||
@setState(focused: true)
|
||||
|
||||
onInputBlurred: ->
|
||||
@setState(focused: false)
|
||||
insertedRange = editor.transact atom.config.get('editor.undoGroupingInterval'), ->
|
||||
editor.insertText(event.data)
|
||||
inputNode.value = event.data if insertedRange
|
||||
|
||||
onVerticalScroll: (scrollTop) ->
|
||||
{editor} = @props
|
||||
@@ -620,11 +624,17 @@ TextEditorComponent = React.createClass
|
||||
else
|
||||
editor.setSelectedScreenRange([tailPosition, [dragRow + 1, 0]], preserveFolds: true)
|
||||
|
||||
onStylesheetsChanged: (stylesheet) ->
|
||||
onStylesheetsChanged: (styleElement) ->
|
||||
return unless @performedInitialMeasurement
|
||||
return unless atom.themes.isInitialLoadComplete()
|
||||
@refreshScrollbars() if not styleElement.sheet? or @containsScrollbarSelector(styleElement.sheet)
|
||||
@handleStylingChange()
|
||||
|
||||
@refreshScrollbars() if not stylesheet? or @containsScrollbarSelector(stylesheet)
|
||||
onAllThemesLoaded: ->
|
||||
@refreshScrollbars()
|
||||
@handleStylingChange()
|
||||
|
||||
handleStylingChange: ->
|
||||
@sampleFontStyling()
|
||||
@sampleBackgroundColors()
|
||||
@remeasureCharacterWidths()
|
||||
@@ -770,10 +780,10 @@ TextEditorComponent = React.createClass
|
||||
measureHeightAndWidth: ->
|
||||
return unless @isMounted()
|
||||
|
||||
{editor, parentView} = @props
|
||||
{editor, hostElement} = @props
|
||||
scrollViewNode = @refs.scrollView.getDOMNode()
|
||||
{position} = getComputedStyle(parentView)
|
||||
{height} = parentView.style
|
||||
{position} = getComputedStyle(hostElement)
|
||||
{height} = hostElement.style
|
||||
|
||||
if position is 'absolute' or height
|
||||
if @autoHeight
|
||||
@@ -805,9 +815,9 @@ TextEditorComponent = React.createClass
|
||||
@remeasureCharacterWidths()
|
||||
|
||||
sampleBackgroundColors: (suppressUpdate) ->
|
||||
{parentView} = @props
|
||||
{hostElement} = @props
|
||||
{showLineNumbers} = @state
|
||||
{backgroundColor} = getComputedStyle(parentView)
|
||||
{backgroundColor} = getComputedStyle(hostElement)
|
||||
|
||||
if backgroundColor isnt @backgroundColor
|
||||
@backgroundColor = backgroundColor
|
||||
@@ -906,10 +916,10 @@ TextEditorComponent = React.createClass
|
||||
lineNumberNodeForScreenRow: (screenRow) -> @refs.gutter.lineNumberNodeForScreenRow(screenRow)
|
||||
|
||||
screenRowForNode: (node) ->
|
||||
while node isnt document
|
||||
while node?
|
||||
if screenRow = node.dataset.screenRow
|
||||
return parseInt(screenRow)
|
||||
node = node.parentNode
|
||||
node = node.parentElement
|
||||
null
|
||||
|
||||
getFontSize: ->
|
||||
@@ -976,11 +986,13 @@ TextEditorComponent = React.createClass
|
||||
|
||||
updateParentViewFocusedClassIfNeeded: (prevState) ->
|
||||
if prevState.focused isnt @state.focused
|
||||
@props.parentView.classList.toggle('is-focused', @state.focused)
|
||||
@props.hostElement.classList.toggle('is-focused', @state.focused)
|
||||
@props.rootElement.classList.toggle('is-focused', @state.focused)
|
||||
|
||||
updateParentViewMiniClassIfNeeded: (prevProps) ->
|
||||
if prevProps.mini isnt @props.mini
|
||||
@props.parentView.classList.toggle('mini', @props.mini)
|
||||
@props.hostElement.classList.toggle('mini', @props.mini)
|
||||
@props.rootElement.classList.toggle('mini', @props.mini)
|
||||
|
||||
runScrollBenchmark: ->
|
||||
unless process.env.NODE_ENV is 'production'
|
||||
|
||||
+154
-108
@@ -18,13 +18,31 @@ class TextEditorElement extends HTMLElement
|
||||
@initializeContent()
|
||||
@createSpacePenShim()
|
||||
@addEventListener 'focus', @focused.bind(this)
|
||||
@addEventListener 'focusout', @focusedOut.bind(this)
|
||||
@addEventListener 'blur', @blurred.bind(this)
|
||||
|
||||
initializeContent: (attributes) ->
|
||||
@classList.add('editor', 'react', 'editor-colors')
|
||||
@classList.add('editor')
|
||||
@setAttribute('tabindex', -1)
|
||||
|
||||
if atom.config.get('editor.useShadowDOM')
|
||||
@createShadowRoot()
|
||||
|
||||
@stylesElement = document.createElement('atom-styles')
|
||||
@stylesElement.setAttribute('context', 'atom-text-editor')
|
||||
@stylesElement.initialize()
|
||||
|
||||
@rootElement = document.createElement('div')
|
||||
@rootElement.classList.add('shadow')
|
||||
|
||||
@shadowRoot.appendChild(@stylesElement)
|
||||
@shadowRoot.appendChild(@rootElement)
|
||||
else
|
||||
@stylesElement = document.head.querySelector('atom-styles')
|
||||
@rootElement = this
|
||||
|
||||
@rootElement.classList.add('editor', 'editor-colors')
|
||||
|
||||
|
||||
createSpacePenShim: ->
|
||||
TextEditorView ?= require './text-editor-view'
|
||||
@__spacePenView = new TextEditorView(this)
|
||||
@@ -43,6 +61,8 @@ class TextEditorElement extends HTMLElement
|
||||
@mountComponent()
|
||||
@addGrammarScopeAttribute()
|
||||
@model.onDidChangeGrammar => @addGrammarScopeAttribute()
|
||||
@addEncodingAttribute()
|
||||
@model.onDidChangeEncoding => @addEncodingAttribute()
|
||||
@model.onDidDestroy => @unmountComponent()
|
||||
@__spacePenView.setModel(@model)
|
||||
@model
|
||||
@@ -62,12 +82,19 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
mountComponent: ->
|
||||
@componentDescriptor ?= TextEditorComponent(
|
||||
parentView: this
|
||||
hostElement: this
|
||||
rootElement: @rootElement
|
||||
stylesElement: @stylesElement
|
||||
editor: @model
|
||||
mini: @model.mini
|
||||
lineOverdrawMargin: @lineOverdrawMargin
|
||||
)
|
||||
@component = React.renderComponent(@componentDescriptor, this)
|
||||
@component = React.renderComponent(@componentDescriptor, @rootElement)
|
||||
|
||||
unless atom.config.get('editor.useShadowDOM')
|
||||
inputNode = @component.refs.input.getDOMNode()
|
||||
inputNode.addEventListener 'focus', @focused.bind(this)
|
||||
inputNode.addEventListener 'blur', => @dispatchEvent(new FocusEvent('blur', bubbles: false))
|
||||
|
||||
unmountComponent: ->
|
||||
return unless @component?.isMounted()
|
||||
@@ -77,132 +104,151 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
focused: ->
|
||||
if @component?
|
||||
@component.onFocus()
|
||||
@component.focused()
|
||||
else
|
||||
@focusOnAttach = true
|
||||
|
||||
focusedOut: (event) ->
|
||||
event.stopImmediatePropagation() if @contains(event.relatedTarget)
|
||||
|
||||
blurred: (event) ->
|
||||
event.stopImmediatePropagation() if @contains(event.relatedTarget)
|
||||
unless atom.config.get('editor.useShadowDOM')
|
||||
if event.relatedTarget is @component?.refs.input?.getDOMNode()
|
||||
event.stopImmediatePropagation()
|
||||
return
|
||||
|
||||
@component?.blurred()
|
||||
|
||||
addGrammarScopeAttribute: ->
|
||||
grammarScope = @model.getGrammar()?.scopeName?.replace(/\./g, ' ')
|
||||
@setAttribute('data-grammar', grammarScope)
|
||||
@dataset.grammar = grammarScope
|
||||
|
||||
addEncodingAttribute: ->
|
||||
@dataset.encoding = @model.getEncoding()
|
||||
|
||||
hasFocus: ->
|
||||
this is document.activeElement or @contains(document.activeElement)
|
||||
|
||||
stopCommandEventPropagation = (commandListeners) ->
|
||||
stopEventPropagation = (commandListeners) ->
|
||||
newCommandListeners = {}
|
||||
for commandName, commandListener of commandListeners
|
||||
do (commandListener) ->
|
||||
newCommandListeners[commandName] = (event) ->
|
||||
event.stopPropagation()
|
||||
commandListener.call(this, event)
|
||||
commandListener.call(@getModel(), event)
|
||||
newCommandListeners
|
||||
|
||||
atom.commands.add 'atom-text-editor', stopCommandEventPropagation(
|
||||
'core:move-left': -> @getModel().moveLeft()
|
||||
'core:move-right': -> @getModel().moveRight()
|
||||
'core:select-left': -> @getModel().selectLeft()
|
||||
'core:select-right': -> @getModel().selectRight()
|
||||
'core:select-all': -> @getModel().selectAll()
|
||||
'core:backspace': -> @getModel().backspace()
|
||||
'core:delete': -> @getModel().delete()
|
||||
'core:undo': -> @getModel().undo()
|
||||
'core:redo': -> @getModel().redo()
|
||||
'core:cut': -> @getModel().cutSelectedText()
|
||||
'core:copy': -> @getModel().copySelectedText()
|
||||
'core:paste': -> @getModel().pasteText()
|
||||
'editor:move-to-previous-word': -> @getModel().moveToPreviousWord()
|
||||
'editor:select-word': -> @getModel().selectWordsContainingCursors()
|
||||
'editor:consolidate-selections': (event) -> event.abortKeyBinding() unless @getModel().consolidateSelections()
|
||||
'editor:delete-to-beginning-of-word': -> @getModel().deleteToBeginningOfWord()
|
||||
'editor:delete-to-beginning-of-line': -> @getModel().deleteToBeginningOfLine()
|
||||
'editor:delete-to-end-of-line': -> @getModel().deleteToEndOfLine()
|
||||
'editor:delete-to-end-of-word': -> @getModel().deleteToEndOfWord()
|
||||
'editor:delete-line': -> @getModel().deleteLine()
|
||||
'editor:cut-to-end-of-line': -> @getModel().cutToEndOfLine()
|
||||
'editor:move-to-beginning-of-next-paragraph': -> @getModel().moveToBeginningOfNextParagraph()
|
||||
'editor:move-to-beginning-of-previous-paragraph': -> @getModel().moveToBeginningOfPreviousParagraph()
|
||||
'editor:move-to-beginning-of-screen-line': -> @getModel().moveToBeginningOfScreenLine()
|
||||
'editor:move-to-beginning-of-line': -> @getModel().moveToBeginningOfLine()
|
||||
'editor:move-to-end-of-screen-line': -> @getModel().moveToEndOfScreenLine()
|
||||
'editor:move-to-end-of-line': -> @getModel().moveToEndOfLine()
|
||||
'editor:move-to-first-character-of-line': -> @getModel().moveToFirstCharacterOfLine()
|
||||
'editor:move-to-beginning-of-word': -> @getModel().moveToBeginningOfWord()
|
||||
'editor:move-to-end-of-word': -> @getModel().moveToEndOfWord()
|
||||
'editor:move-to-beginning-of-next-word': -> @getModel().moveToBeginningOfNextWord()
|
||||
'editor:move-to-previous-word-boundary': -> @getModel().moveToPreviousWordBoundary()
|
||||
'editor:move-to-next-word-boundary': -> @getModel().moveToNextWordBoundary()
|
||||
'editor:select-to-beginning-of-next-paragraph': -> @getModel().selectToBeginningOfNextParagraph()
|
||||
'editor:select-to-beginning-of-previous-paragraph': -> @getModel().selectToBeginningOfPreviousParagraph()
|
||||
'editor:select-to-end-of-line': -> @getModel().selectToEndOfLine()
|
||||
'editor:select-to-beginning-of-line': -> @getModel().selectToBeginningOfLine()
|
||||
'editor:select-to-end-of-word': -> @getModel().selectToEndOfWord()
|
||||
'editor:select-to-beginning-of-word': -> @getModel().selectToBeginningOfWord()
|
||||
'editor:select-to-beginning-of-next-word': -> @getModel().selectToBeginningOfNextWord()
|
||||
'editor:select-to-next-word-boundary': -> @getModel().selectToNextWordBoundary()
|
||||
'editor:select-to-previous-word-boundary': -> @getModel().selectToPreviousWordBoundary()
|
||||
'editor:select-to-first-character-of-line': -> @getModel().selectToFirstCharacterOfLine()
|
||||
'editor:select-line': -> @getModel().selectLinesContainingCursors()
|
||||
'editor:transpose': -> @getModel().transpose()
|
||||
'editor:upper-case': -> @getModel().upperCase()
|
||||
'editor:lower-case': -> @getModel().lowerCase()
|
||||
stopEventPropagationAndGroupUndo = (commandListeners) ->
|
||||
newCommandListeners = {}
|
||||
for commandName, commandListener of commandListeners
|
||||
do (commandListener) ->
|
||||
newCommandListeners[commandName] = (event) ->
|
||||
event.stopPropagation()
|
||||
model = @getModel()
|
||||
model.transact atom.config.get('editor.undoGroupingInterval'), ->
|
||||
commandListener.call(model, event)
|
||||
newCommandListeners
|
||||
|
||||
atom.commands.add 'atom-text-editor', stopEventPropagation(
|
||||
'core:undo': -> @undo()
|
||||
'core:redo': -> @redo()
|
||||
)
|
||||
|
||||
atom.commands.add 'atom-text-editor:not(.mini)', stopCommandEventPropagation(
|
||||
'core:move-up': -> @getModel().moveUp()
|
||||
'core:move-down': -> @getModel().moveDown()
|
||||
'core:move-to-top': -> @getModel().moveToTop()
|
||||
'core:move-to-bottom': -> @getModel().moveToBottom()
|
||||
'core:page-up': -> @getModel().pageUp()
|
||||
'core:page-down': -> @getModel().pageDown()
|
||||
'core:select-up': -> @getModel().selectUp()
|
||||
'core:select-down': -> @getModel().selectDown()
|
||||
'core:select-to-top': -> @getModel().selectToTop()
|
||||
'core:select-to-bottom': -> @getModel().selectToBottom()
|
||||
'core:select-page-up': -> @getModel().selectPageUp()
|
||||
'core:select-page-down': -> @getModel().selectPageDown()
|
||||
'editor:indent': -> @getModel().indent()
|
||||
'editor:auto-indent': -> @getModel().autoIndentSelectedRows()
|
||||
'editor:indent-selected-rows': -> @getModel().indentSelectedRows()
|
||||
'editor:outdent-selected-rows': -> @getModel().outdentSelectedRows()
|
||||
'editor:newline': -> @getModel().insertNewline()
|
||||
'editor:newline-below': -> @getModel().insertNewlineBelow()
|
||||
'editor:newline-above': -> @getModel().insertNewlineAbove()
|
||||
'editor:add-selection-below': -> @getModel().addSelectionBelow()
|
||||
'editor:add-selection-above': -> @getModel().addSelectionAbove()
|
||||
'editor:split-selections-into-lines': -> @getModel().splitSelectionsIntoLines()
|
||||
'editor:toggle-soft-tabs': -> @getModel().toggleSoftTabs()
|
||||
'editor:toggle-soft-wrap': -> @getModel().toggleSoftWrapped()
|
||||
'editor:fold-all': -> @getModel().foldAll()
|
||||
'editor:unfold-all': -> @getModel().unfoldAll()
|
||||
'editor:fold-current-row': -> @getModel().foldCurrentRow()
|
||||
'editor:unfold-current-row': -> @getModel().unfoldCurrentRow()
|
||||
'editor:fold-selection': -> @getModel().foldSelectedLines()
|
||||
'editor:fold-at-indent-level-1': -> @getModel().foldAllAtIndentLevel(0)
|
||||
'editor:fold-at-indent-level-2': -> @getModel().foldAllAtIndentLevel(1)
|
||||
'editor:fold-at-indent-level-3': -> @getModel().foldAllAtIndentLevel(2)
|
||||
'editor:fold-at-indent-level-4': -> @getModel().foldAllAtIndentLevel(3)
|
||||
'editor:fold-at-indent-level-5': -> @getModel().foldAllAtIndentLevel(4)
|
||||
'editor:fold-at-indent-level-6': -> @getModel().foldAllAtIndentLevel(5)
|
||||
'editor:fold-at-indent-level-7': -> @getModel().foldAllAtIndentLevel(6)
|
||||
'editor:fold-at-indent-level-8': -> @getModel().foldAllAtIndentLevel(7)
|
||||
'editor:fold-at-indent-level-9': -> @getModel().foldAllAtIndentLevel(8)
|
||||
'editor:toggle-line-comments': -> @getModel().toggleLineCommentsInSelection()
|
||||
'editor:log-cursor-scope': -> @getModel().logCursorScope()
|
||||
'editor:checkout-head-revision': -> atom.project.getRepositories()[0]?.checkoutHeadForEditor(@getModel())
|
||||
'editor:copy-path': -> @getModel().copyPathToClipboard()
|
||||
'editor:move-line-up': -> @getModel().moveLineUp()
|
||||
'editor:move-line-down': -> @getModel().moveLineDown()
|
||||
'editor:duplicate-lines': -> @getModel().duplicateLines()
|
||||
'editor:join-lines': -> @getModel().joinLines()
|
||||
atom.commands.add 'atom-text-editor', stopEventPropagationAndGroupUndo(
|
||||
'core:move-left': -> @moveLeft()
|
||||
'core:move-right': -> @moveRight()
|
||||
'core:select-left': -> @selectLeft()
|
||||
'core:select-right': -> @selectRight()
|
||||
'core:select-all': -> @selectAll()
|
||||
'core:backspace': -> @backspace()
|
||||
'core:delete': -> @delete()
|
||||
'core:cut': -> @cutSelectedText()
|
||||
'core:copy': -> @copySelectedText()
|
||||
'core:paste': -> @pasteText()
|
||||
'editor:move-to-previous-word': -> @moveToPreviousWord()
|
||||
'editor:select-word': -> @selectWordsContainingCursors()
|
||||
'editor:consolidate-selections': (event) -> event.abortKeyBinding() unless @consolidateSelections()
|
||||
'editor:delete-to-beginning-of-word': -> @deleteToBeginningOfWord()
|
||||
'editor:delete-to-beginning-of-line': -> @deleteToBeginningOfLine()
|
||||
'editor:delete-to-end-of-line': -> @deleteToEndOfLine()
|
||||
'editor:delete-to-end-of-word': -> @deleteToEndOfWord()
|
||||
'editor:delete-line': -> @deleteLine()
|
||||
'editor:cut-to-end-of-line': -> @cutToEndOfLine()
|
||||
'editor:move-to-beginning-of-next-paragraph': -> @moveToBeginningOfNextParagraph()
|
||||
'editor:move-to-beginning-of-previous-paragraph': -> @moveToBeginningOfPreviousParagraph()
|
||||
'editor:move-to-beginning-of-screen-line': -> @moveToBeginningOfScreenLine()
|
||||
'editor:move-to-beginning-of-line': -> @moveToBeginningOfLine()
|
||||
'editor:move-to-end-of-screen-line': -> @moveToEndOfScreenLine()
|
||||
'editor:move-to-end-of-line': -> @moveToEndOfLine()
|
||||
'editor:move-to-first-character-of-line': -> @moveToFirstCharacterOfLine()
|
||||
'editor:move-to-beginning-of-word': -> @moveToBeginningOfWord()
|
||||
'editor:move-to-end-of-word': -> @moveToEndOfWord()
|
||||
'editor:move-to-beginning-of-next-word': -> @moveToBeginningOfNextWord()
|
||||
'editor:move-to-previous-word-boundary': -> @moveToPreviousWordBoundary()
|
||||
'editor:move-to-next-word-boundary': -> @moveToNextWordBoundary()
|
||||
'editor:select-to-beginning-of-next-paragraph': -> @selectToBeginningOfNextParagraph()
|
||||
'editor:select-to-beginning-of-previous-paragraph': -> @selectToBeginningOfPreviousParagraph()
|
||||
'editor:select-to-end-of-line': -> @selectToEndOfLine()
|
||||
'editor:select-to-beginning-of-line': -> @selectToBeginningOfLine()
|
||||
'editor:select-to-end-of-word': -> @selectToEndOfWord()
|
||||
'editor:select-to-beginning-of-word': -> @selectToBeginningOfWord()
|
||||
'editor:select-to-beginning-of-next-word': -> @selectToBeginningOfNextWord()
|
||||
'editor:select-to-next-word-boundary': -> @selectToNextWordBoundary()
|
||||
'editor:select-to-previous-word-boundary': -> @selectToPreviousWordBoundary()
|
||||
'editor:select-to-first-character-of-line': -> @selectToFirstCharacterOfLine()
|
||||
'editor:select-line': -> @selectLinesContainingCursors()
|
||||
'editor:transpose': -> @transpose()
|
||||
'editor:upper-case': -> @upperCase()
|
||||
'editor:lower-case': -> @lowerCase()
|
||||
)
|
||||
|
||||
atom.commands.add 'atom-text-editor:not(.mini)', stopEventPropagationAndGroupUndo(
|
||||
'core:move-up': -> @moveUp()
|
||||
'core:move-down': -> @moveDown()
|
||||
'core:move-to-top': -> @moveToTop()
|
||||
'core:move-to-bottom': -> @moveToBottom()
|
||||
'core:page-up': -> @pageUp()
|
||||
'core:page-down': -> @pageDown()
|
||||
'core:select-up': -> @selectUp()
|
||||
'core:select-down': -> @selectDown()
|
||||
'core:select-to-top': -> @selectToTop()
|
||||
'core:select-to-bottom': -> @selectToBottom()
|
||||
'core:select-page-up': -> @selectPageUp()
|
||||
'core:select-page-down': -> @selectPageDown()
|
||||
'editor:indent': -> @indent()
|
||||
'editor:auto-indent': -> @autoIndentSelectedRows()
|
||||
'editor:indent-selected-rows': -> @indentSelectedRows()
|
||||
'editor:outdent-selected-rows': -> @outdentSelectedRows()
|
||||
'editor:newline': -> @insertNewline()
|
||||
'editor:newline-below': -> @insertNewlineBelow()
|
||||
'editor:newline-above': -> @insertNewlineAbove()
|
||||
'editor:add-selection-below': -> @addSelectionBelow()
|
||||
'editor:add-selection-above': -> @addSelectionAbove()
|
||||
'editor:split-selections-into-lines': -> @splitSelectionsIntoLines()
|
||||
'editor:toggle-soft-tabs': -> @toggleSoftTabs()
|
||||
'editor:toggle-soft-wrap': -> @toggleSoftWrapped()
|
||||
'editor:fold-all': -> @foldAll()
|
||||
'editor:unfold-all': -> @unfoldAll()
|
||||
'editor:fold-current-row': -> @foldCurrentRow()
|
||||
'editor:unfold-current-row': -> @unfoldCurrentRow()
|
||||
'editor:fold-selection': -> @foldSelectedLines()
|
||||
'editor:fold-at-indent-level-1': -> @foldAllAtIndentLevel(0)
|
||||
'editor:fold-at-indent-level-2': -> @foldAllAtIndentLevel(1)
|
||||
'editor:fold-at-indent-level-3': -> @foldAllAtIndentLevel(2)
|
||||
'editor:fold-at-indent-level-4': -> @foldAllAtIndentLevel(3)
|
||||
'editor:fold-at-indent-level-5': -> @foldAllAtIndentLevel(4)
|
||||
'editor:fold-at-indent-level-6': -> @foldAllAtIndentLevel(5)
|
||||
'editor:fold-at-indent-level-7': -> @foldAllAtIndentLevel(6)
|
||||
'editor:fold-at-indent-level-8': -> @foldAllAtIndentLevel(7)
|
||||
'editor:fold-at-indent-level-9': -> @foldAllAtIndentLevel(8)
|
||||
'editor:toggle-line-comments': -> @toggleLineCommentsInSelection()
|
||||
'editor:log-cursor-scope': -> @logCursorScope()
|
||||
'editor:checkout-head-revision': -> atom.project.getRepositories()[0]?.checkoutHeadForEditor(this)
|
||||
'editor:copy-path': -> @copyPathToClipboard()
|
||||
'editor:move-line-up': -> @moveLineUp()
|
||||
'editor:move-line-down': -> @moveLineDown()
|
||||
'editor:duplicate-lines': -> @duplicateLines()
|
||||
'editor:join-lines': -> @joinLines()
|
||||
'editor:toggle-indent-guide': -> atom.config.set('editor.showIndentGuide', not atom.config.get('editor.showIndentGuide'))
|
||||
'editor:toggle-line-numbers': -> atom.config.set('editor.showLineNumbers', not atom.config.get('editor.showLineNumbers'))
|
||||
'editor:scroll-to-cursor': -> @getModel().scrollToCursorPosition()
|
||||
'editor:scroll-to-cursor': -> @scrollToCursorPosition()
|
||||
)
|
||||
|
||||
module.exports = TextEditorElement = document.registerElement 'atom-text-editor', prototype: TextEditorElement.prototype
|
||||
|
||||
@@ -73,13 +73,26 @@ class TextEditorView extends View
|
||||
setModel: (@model) ->
|
||||
@editor = @model
|
||||
|
||||
@scrollView = @find('.scroll-view')
|
||||
@underlayer = @find('.highlights').addClass('underlayer')
|
||||
@overlayer = @find('.lines').addClass('overlayer')
|
||||
@hiddenInput = @.find('.hidden-input')
|
||||
@root = $(@element.rootElement)
|
||||
|
||||
@scrollView = @root.find('.scroll-view')
|
||||
|
||||
|
||||
if atom.config.get('editor.useShadowDOM')
|
||||
@underlayer = $("<div class='underlayer'></div>").appendTo(this)
|
||||
@overlayer = $("<div class='overlayer'></div>").appendTo(this)
|
||||
else
|
||||
@underlayer = @find('.highlights').addClass('underlayer')
|
||||
@overlayer = @find('.lines').addClass('overlayer')
|
||||
|
||||
@hiddenInput = @root.find('.hidden-input')
|
||||
|
||||
@hiddenInput.on = (args...) =>
|
||||
args[0] = 'blur' if args[0] is 'focusout'
|
||||
$::on.apply(this, args)
|
||||
|
||||
@subscribe atom.config.observe 'editor.showLineNumbers', =>
|
||||
@gutter = @find('.gutter')
|
||||
@gutter = @root.find('.gutter')
|
||||
|
||||
@gutter.removeClassFromAllLines = (klass) =>
|
||||
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
||||
@@ -95,6 +108,13 @@ class TextEditorView extends View
|
||||
lines.addClass(klass)
|
||||
lines.length > 0
|
||||
|
||||
find: ->
|
||||
shadowResult = @root.find.apply(@root, arguments)
|
||||
if shadowResult.length > 0
|
||||
shadowResult
|
||||
else
|
||||
super
|
||||
|
||||
# Public: Get the underlying editor model for this view.
|
||||
#
|
||||
# Returns an {TextEditor}
|
||||
@@ -107,7 +127,7 @@ class TextEditorView extends View
|
||||
Object.defineProperty @::, 'firstRenderedScreenRow', get: -> @component.getRenderedRowRange()[0]
|
||||
Object.defineProperty @::, 'lastRenderedScreenRow', get: -> @component.getRenderedRowRange()[1]
|
||||
Object.defineProperty @::, 'active', get: -> @is(@getPaneView()?.activeView)
|
||||
Object.defineProperty @::, 'isFocused', get: -> @component?.state.focused
|
||||
Object.defineProperty @::, 'isFocused', get: -> document.activeElement is @element or document.activeElement is @element.component?.refs.input.getDOMNode()
|
||||
Object.defineProperty @::, 'mini', get: -> @component?.props.mini
|
||||
Object.defineProperty @::, 'component', get: -> @element?.component
|
||||
|
||||
@@ -164,7 +184,7 @@ class TextEditorView extends View
|
||||
appendToLinesView: (view) ->
|
||||
view.css('position', 'absolute')
|
||||
view.css('z-index', 1)
|
||||
@find('.lines').prepend(view)
|
||||
@overlayer.append(view)
|
||||
|
||||
unmountComponent: ->
|
||||
React.unmountComponentAtNode(@element) if @component.isMounted()
|
||||
|
||||
@@ -134,9 +134,11 @@ class TextEditor extends Model
|
||||
@emitter.emit 'did-change-title', @getTitle()
|
||||
@emit "path-changed"
|
||||
@emitter.emit 'did-change-path', @getPath()
|
||||
@subscribe @buffer.onDidChangeEncoding =>
|
||||
@emitter.emit 'did-change-encoding', @getEncoding()
|
||||
@subscribe @buffer.onDidDestroy => @destroy()
|
||||
|
||||
# TODO: remove these thwne we remove the deprecations. They are old events.
|
||||
# TODO: remove these when we remove the deprecations. They are old events.
|
||||
@subscribe @buffer.onDidStopChanging => @emit "contents-modified"
|
||||
@subscribe @buffer.onDidConflict => @emit "contents-conflicted"
|
||||
@subscribe @buffer.onDidChangeModified => @emit "modified-status-changed"
|
||||
@@ -173,6 +175,7 @@ class TextEditor extends Model
|
||||
|
||||
destroyed: ->
|
||||
@unsubscribe()
|
||||
@scopedConfigSubscriptions.dispose()
|
||||
selection.destroy() for selection in @getSelections()
|
||||
@buffer.release()
|
||||
@displayBuffer.destroy()
|
||||
@@ -260,6 +263,14 @@ class TextEditor extends Model
|
||||
onDidChangeSoftWrapped: (callback) ->
|
||||
@displayBuffer.onDidChangeSoftWrapped(callback)
|
||||
|
||||
# Extended: Calls your `callback` when the buffer's encoding has changed.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidChangeEncoding: (callback) ->
|
||||
@emitter.on 'did-change-encoding', callback
|
||||
|
||||
# Extended: Calls your `callback` when the grammar that interprets and
|
||||
# colorizes the text has been changed. Immediately calls your callback with
|
||||
# the current grammar.
|
||||
@@ -568,6 +579,16 @@ class TextEditor extends Model
|
||||
# Essential: Returns the {String} path of this editor's text buffer.
|
||||
getPath: -> @buffer.getPath()
|
||||
|
||||
# Extended: Returns the {String} character set encoding of this editor's text
|
||||
# buffer.
|
||||
getEncoding: -> @buffer.getEncoding()
|
||||
|
||||
# Extended: Set the character set encoding to use in this editor's text
|
||||
# buffer.
|
||||
#
|
||||
# * `encoding` The {String} character set encoding name such as 'utf8'
|
||||
setEncoding: (encoding) -> @buffer.setEncoding(encoding)
|
||||
|
||||
# Essential: Returns {Boolean} `true` if this editor has been modified.
|
||||
isModified: -> @buffer.isModified()
|
||||
|
||||
@@ -717,9 +738,12 @@ class TextEditor extends Model
|
||||
#
|
||||
# * `range` A {Range} or range-compatible {Array}.
|
||||
# * `text` A {String}
|
||||
# * `options` (optional) {Object}
|
||||
# * `normalizeLineEndings` (optional) {Boolean} (default: true)
|
||||
# * `undo` (optional) {String} 'skip' will skip the undo system
|
||||
#
|
||||
# Returns the {Range} of the newly-inserted text.
|
||||
setTextInBufferRange: (range, text, normalizeLineEndings) -> @getBuffer().setTextInRange(range, text, normalizeLineEndings)
|
||||
setTextInBufferRange: (range, text, options) -> @getBuffer().setTextInRange(range, text, options)
|
||||
|
||||
# Essential: For each selection, replace the selected text with the given text.
|
||||
#
|
||||
@@ -1073,8 +1097,10 @@ class TextEditor extends Model
|
||||
# abort the transaction, call {::abortTransaction} to terminate the function's
|
||||
# execution and revert any changes performed up to the abortion.
|
||||
#
|
||||
# * `groupingInterval` (optional) This is the sames as the `groupingInterval`
|
||||
# parameter in {::beginTransaction}
|
||||
# * `fn` A {Function} to call inside the transaction.
|
||||
transact: (fn) -> @buffer.transact(fn)
|
||||
transact: (groupingInterval, fn) -> @buffer.transact(groupingInterval, fn)
|
||||
|
||||
# Extended: Start an open-ended transaction.
|
||||
#
|
||||
@@ -1082,7 +1108,12 @@ class TextEditor extends Model
|
||||
# transaction. If you nest calls to transactions, only the outermost
|
||||
# transaction is considered. You must match every begin with a matching
|
||||
# commit, but a single call to abort will cancel all nested transactions.
|
||||
beginTransaction: -> @buffer.beginTransaction()
|
||||
#
|
||||
# * `groupingInterval` (optional) The {Number} of milliseconds for which this
|
||||
# transaction should be considered 'groupable' after it begins. If a transaction
|
||||
# with a positive `groupingInterval` is committed while the previous transaction is
|
||||
# still 'groupable', the two transactions are merged with respect to undo and redo.
|
||||
beginTransaction: (groupingInterval) -> @buffer.beginTransaction(groupingInterval)
|
||||
|
||||
# Extended: Commit an open-ended transaction started with {::beginTransaction}
|
||||
# and push it to the undo stack.
|
||||
|
||||
@@ -159,11 +159,14 @@ class ThemeManager
|
||||
themeNames = atom.config.get('core.themes') ? []
|
||||
themeNames = [themeNames] unless _.isArray(themeNames)
|
||||
themeNames = themeNames.filter (themeName) ->
|
||||
themeName and typeof themeName is 'string'
|
||||
if themeName and typeof themeName is 'string'
|
||||
return true if atom.packages.resolvePackagePath(themeName)
|
||||
console.warn("Enabled theme '#{themeName}' is not installed.")
|
||||
false
|
||||
|
||||
# Use a built-in syntax and UI theme when in safe mode since themes
|
||||
# installed to ~/.atom/packages will not be loaded.
|
||||
if @safeMode
|
||||
# Use a built-in syntax and UI theme any time the configured themes are not
|
||||
# available.
|
||||
if themeNames.length < 2
|
||||
builtInThemeNames = [
|
||||
'atom-dark-syntax'
|
||||
'atom-dark-ui'
|
||||
@@ -238,7 +241,7 @@ class ThemeManager
|
||||
@applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
|
||||
|
||||
loadBaseStylesheets: ->
|
||||
@requireStylesheet('bootstrap/less/bootstrap')
|
||||
@requireStylesheet('../static/bootstrap')
|
||||
@reloadBaseStylesheets()
|
||||
|
||||
reloadBaseStylesheets: ->
|
||||
@@ -246,6 +249,9 @@ class ThemeManager
|
||||
if nativeStylesheetPath = fs.resolveOnLoadPath(process.platform, ['css', 'less'])
|
||||
@requireStylesheet(nativeStylesheetPath)
|
||||
|
||||
textEditorStylesPath = path.join(@resourcePath, 'static', 'text-editor-shadow.less')
|
||||
atom.styles.addStyleSheet(@loadLessStylesheet(textEditorStylesPath), sourcePath: textEditorStylesPath, context: 'atom-text-editor')
|
||||
|
||||
stylesheetElementForId: (id) ->
|
||||
document.head.querySelector("atom-styles style[source-path=\"#{id}\"]")
|
||||
|
||||
|
||||
@@ -125,7 +125,10 @@ class TokenizedBuffer extends Model
|
||||
getTabLength: ->
|
||||
@tabLength ? @configSettings.tabLength
|
||||
|
||||
setTabLength: (@tabLength) ->
|
||||
setTabLength: (tabLength) ->
|
||||
return if tabLength is @tabLength
|
||||
|
||||
@tabLength = tabLength
|
||||
@retokenizeLines()
|
||||
|
||||
setInvisibles: (invisibles) ->
|
||||
|
||||
+101
-2
@@ -1,17 +1,116 @@
|
||||
{Disposable} = require 'event-kit'
|
||||
{jQuery} = require './space-pen-extensions'
|
||||
|
||||
# Essential: `ViewRegistry` handles the association between model and view
|
||||
# types in Atom. We call this association a View Provider. As in, for a given
|
||||
# model, this class can provide a view via {::getView}, as long as the
|
||||
# model/view association was registered via {::addViewProvider}
|
||||
#
|
||||
# If you're adding your own kind of pane item, a good strategy for all but the
|
||||
# simplest items is to separate the model and the view. The model handles
|
||||
# application logic and is the primary point of API interaction. The view
|
||||
# just handles presentation.
|
||||
#
|
||||
# View providers to inform the workspace how your model objects should be
|
||||
# presented in the DOM. A view provider must always return a DOM node, which
|
||||
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
|
||||
# an ideal tool for implementing views in Atom.
|
||||
#
|
||||
# You can access the `ViewRegistry` object via `atom.views`.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting the workspace element
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceElement = atom.views.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# ### Getting An Editor Element
|
||||
#
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorElement = atom.views.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane Element
|
||||
#
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneElement = atom.views.getView(pane)
|
||||
# ```
|
||||
module.exports =
|
||||
class ViewRegistry
|
||||
constructor: ->
|
||||
@views = new WeakMap
|
||||
@providers = []
|
||||
|
||||
# Essential: Add a provider that will be used to construct views in the
|
||||
# workspace's view layer based on model objects in its model layer.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# Text editors are divided into a model and a view layer, so when you interact
|
||||
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
|
||||
# to get the model object. We display text editors on screen by teaching the
|
||||
# workspace what view constructor it should use to represent them:
|
||||
#
|
||||
# ```coffee
|
||||
# atom.views.addViewProvider
|
||||
# modelConstructor: TextEditor
|
||||
# viewConstructor: TextEditorElement
|
||||
# ```
|
||||
#
|
||||
# * `providerSpec` {Object} containing the following keys:
|
||||
# * `modelConstructor` Constructor {Function} for your model.
|
||||
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
|
||||
# should be a subclass of `HTMLElement` (that is, your view should be a
|
||||
# DOM node) and have a `::setModel()` method which will be called
|
||||
# immediately after construction. If you don't supply this property, you
|
||||
# must supply the `createView` property with a function that never returns
|
||||
# `undefined`.
|
||||
# * `createView` (Optional) Factory {Function} that must return a subclass
|
||||
# of `HTMLElement` or `undefined`. If this property is not present or the
|
||||
# function returns `undefined`, the view provider will fall back to the
|
||||
# `viewConstructor` property. If you don't provide this property, you must
|
||||
# provider a `viewConstructor` property.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# added provider.
|
||||
addViewProvider: (providerSpec) ->
|
||||
@providers.push(providerSpec)
|
||||
new Disposable =>
|
||||
@providers = @providers.filter (provider) -> provider isnt providerSpec
|
||||
|
||||
# Essential: Get the view associated with an object in the workspace.
|
||||
#
|
||||
# If you're just *using* the workspace, you shouldn't need to access the view
|
||||
# layer, but view layer access may be necessary if you want to perform DOM
|
||||
# manipulation that isn't supported via the model API.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting An Editor View
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorView = atom.views.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane View
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneView = atom.views.getView(pane)
|
||||
# ```
|
||||
#
|
||||
# ### Getting The Workspace View
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceView = atom.views.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# * `object` The object for which you want to retrieve a view. This can be a
|
||||
# pane item, a pane, or the workspace itself.
|
||||
#
|
||||
# Returns a DOM element.
|
||||
getView: (object) ->
|
||||
return unless object?
|
||||
|
||||
@@ -25,7 +124,7 @@ class ViewRegistry
|
||||
createView: (object) ->
|
||||
if object instanceof HTMLElement
|
||||
object
|
||||
else if object instanceof jQuery
|
||||
else if object?.jquery
|
||||
object[0]?.__spacePenView ?= object
|
||||
object[0]
|
||||
else if provider = @findProvider(object)
|
||||
|
||||
@@ -28,7 +28,7 @@ class WindowEventHandler
|
||||
|
||||
@subscribe $(window), 'blur', -> document.body.classList.add('is-blurred')
|
||||
|
||||
@subscribe $(window), 'window:open-path', (event, {pathToOpen, initialLine, initialColumn}) ->
|
||||
@subscribeToCommand $(window), 'window:open-path', (event, {pathToOpen, initialLine, initialColumn}) ->
|
||||
unless atom.project?.getPath()
|
||||
if fs.existsSync(pathToOpen) or fs.existsSync(path.dirname(pathToOpen))
|
||||
atom.project?.setPath(pathToOpen)
|
||||
|
||||
@@ -64,7 +64,7 @@ class WorkspaceElement extends HTMLElement
|
||||
getModel: -> @model
|
||||
|
||||
setModel: (@model) ->
|
||||
@paneContainer = @model.getView(@model.paneContainer)
|
||||
@paneContainer = atom.views.getView(@model.paneContainer)
|
||||
@verticalAxis.appendChild(@paneContainer)
|
||||
|
||||
@addEventListener 'focus', @handleFocus.bind(this)
|
||||
@@ -77,6 +77,7 @@ class WorkspaceElement extends HTMLElement
|
||||
left: @model.panelContainers.left.getView()
|
||||
right: @model.panelContainers.right.getView()
|
||||
bottom: @model.panelContainers.bottom.getView()
|
||||
modal: @model.panelContainers.modal.getView()
|
||||
|
||||
@horizontalAxis.insertBefore(@panelContainers.left, @verticalAxis)
|
||||
@horizontalAxis.appendChild(@panelContainers.right)
|
||||
@@ -84,6 +85,8 @@ class WorkspaceElement extends HTMLElement
|
||||
@verticalAxis.insertBefore(@panelContainers.top, @paneContainer)
|
||||
@verticalAxis.appendChild(@panelContainers.bottom)
|
||||
|
||||
@appendChild(@panelContainers.modal)
|
||||
|
||||
@__spacePenView.setModel(@model)
|
||||
|
||||
setTextEditorFontSize: (fontSize) ->
|
||||
|
||||
@@ -59,7 +59,7 @@ class WorkspaceView extends View
|
||||
|
||||
constructor: (@element) ->
|
||||
unless @element?
|
||||
return atom.workspace.getView(atom.workspace).__spacePenView
|
||||
return atom.views.getView(atom.workspace).__spacePenView
|
||||
super
|
||||
@deprecateViewEvents()
|
||||
|
||||
|
||||
+47
-107
@@ -45,15 +45,16 @@ class Workspace extends Model
|
||||
@emitter = new Emitter
|
||||
@openers = []
|
||||
|
||||
@viewRegistry ?= new ViewRegistry
|
||||
@paneContainer ?= new PaneContainer({@viewRegistry})
|
||||
viewRegistry = atom.views
|
||||
@paneContainer ?= new PaneContainer({viewRegistry})
|
||||
@paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed)
|
||||
|
||||
@panelContainers =
|
||||
top: new PanelContainer({@viewRegistry, location: 'top'})
|
||||
left: new PanelContainer({@viewRegistry, location: 'left'})
|
||||
right: new PanelContainer({@viewRegistry, location: 'right'})
|
||||
bottom: new PanelContainer({@viewRegistry, location: 'bottom'})
|
||||
top: new PanelContainer({viewRegistry, location: 'top'})
|
||||
left: new PanelContainer({viewRegistry, location: 'left'})
|
||||
right: new PanelContainer({viewRegistry, location: 'right'})
|
||||
bottom: new PanelContainer({viewRegistry, location: 'bottom'})
|
||||
modal: new PanelContainer({viewRegistry, location: 'modal'})
|
||||
|
||||
@subscribeToActiveItem()
|
||||
|
||||
@@ -68,15 +69,15 @@ class Workspace extends Model
|
||||
when 'atom://.atom/init-script'
|
||||
@open(atom.getUserInitScriptPath())
|
||||
|
||||
@addViewProvider
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: Workspace
|
||||
viewConstructor: WorkspaceElement
|
||||
|
||||
@addViewProvider
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: PanelContainer
|
||||
viewConstructor: PanelContainerElement
|
||||
|
||||
@addViewProvider
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
|
||||
@@ -85,8 +86,7 @@ class Workspace extends Model
|
||||
for packageName in params.packagesWithActiveGrammars ? []
|
||||
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
|
||||
|
||||
params.viewRegistry = new ViewRegistry
|
||||
params.paneContainer.viewRegistry = params.viewRegistry
|
||||
params.paneContainer.viewRegistry = atom.views
|
||||
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
|
||||
params
|
||||
|
||||
@@ -315,7 +315,7 @@ class Workspace extends Model
|
||||
when 'editor-created'
|
||||
deprecate("Use Workspace::onDidAddTextEditor or Workspace::observeTextEditors instead.")
|
||||
when 'uri-opened'
|
||||
deprecate("Use Workspace::onDidAddPaneItem instead.")
|
||||
deprecate("Use Workspace::onDidOpen or Workspace::onDidAddPaneItem instead. https://atom.io/docs/api/latest/Workspace#instance-onDidOpen")
|
||||
else
|
||||
deprecate("Subscribing via ::on is deprecated. Use documented event subscription methods instead.")
|
||||
|
||||
@@ -402,8 +402,6 @@ class Workspace extends Model
|
||||
item ?= opener(atom.project.resolve(uri), options) for opener in @getOpeners() when !item
|
||||
item ?= atom.project.open(uri, options)
|
||||
|
||||
console.profile('open')
|
||||
|
||||
Q(item)
|
||||
.then (item) =>
|
||||
if not pane
|
||||
@@ -415,7 +413,6 @@ class Workspace extends Model
|
||||
index = pane.getActiveItemIndex()
|
||||
@emit "uri-opened"
|
||||
@emitter.emit 'did-open', {uri, pane, item, index}
|
||||
console.profileEnd('open')
|
||||
item
|
||||
.catch (error) ->
|
||||
console.error(error.stack ? error)
|
||||
@@ -555,7 +552,7 @@ class Workspace extends Model
|
||||
activatePreviousPane: ->
|
||||
@paneContainer.activatePreviousPane()
|
||||
|
||||
# Extended: Get the first pane {Pane} with an item for the given URI.
|
||||
# Extended: Get the first {Pane} with an item for the given URI.
|
||||
#
|
||||
# * `uri` {String} uri
|
||||
#
|
||||
@@ -563,6 +560,14 @@ class Workspace extends Model
|
||||
paneForUri: (uri) ->
|
||||
@paneContainer.paneForUri(uri)
|
||||
|
||||
# Extended: Get the {Pane} containing the given item.
|
||||
#
|
||||
# * `item` Item the returned pane contains.
|
||||
#
|
||||
# Returns a {Pane} or `undefined` if no pane exists for the given item.
|
||||
paneForItem: (item) ->
|
||||
@paneContainer.paneForItem(item)
|
||||
|
||||
# Destroy (close) the active pane.
|
||||
destroyActivePane: ->
|
||||
@activePane?.destroy()
|
||||
@@ -608,8 +613,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -623,8 +628,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -638,8 +643,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -653,8 +658,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -664,89 +669,24 @@ class Workspace extends Model
|
||||
addTopPanel: (options) ->
|
||||
@addPanel('top', options)
|
||||
|
||||
# Essential: Adds a panel item as a modal dialog.
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
# forced closer to the edges of the window. (default: 100)
|
||||
#
|
||||
# Returns a {Panel}
|
||||
addModalPanel: (options={}) ->
|
||||
# TODO: remove these default classes. They are to supoprt existing themes.
|
||||
options.className ?= 'overlay from-top'
|
||||
@addPanel('modal', options)
|
||||
|
||||
addPanel: (location, options) ->
|
||||
options ?= {}
|
||||
options.viewRegistry = @viewRegistry
|
||||
options.viewRegistry = atom.views
|
||||
@panelContainers[location].addPanel(new Panel(options))
|
||||
|
||||
###
|
||||
Section: View Management
|
||||
###
|
||||
|
||||
# Essential: Get the view associated with an object in the workspace.
|
||||
#
|
||||
# If you're just *using* the workspace, you shouldn't need to access the view
|
||||
# layer, but view layer access may be necessary if you want to perform DOM
|
||||
# manipulation that isn't supported via the model API.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting An Editor View
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorView = atom.workspace.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane View
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneView = atom.workspace.getView(pane)
|
||||
# ```
|
||||
#
|
||||
# ### Getting The Workspace View
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceView = atom.workspace.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# * `object` The object for which you want to retrieve a view. This can be a
|
||||
# pane item, a pane, or the workspace itself.
|
||||
#
|
||||
# Returns a DOM element.
|
||||
getView: (object) ->
|
||||
@viewRegistry.getView(object)
|
||||
|
||||
# Essential: Add a provider that will be used to construct views in the
|
||||
# workspace's view layer based on model objects in its model layer.
|
||||
#
|
||||
# If you're adding your own kind of pane item, a good strategy for all but the
|
||||
# simplest items is to separate the model and the view. The model handles
|
||||
# application logic and is the primary point of API interaction. The view
|
||||
# just handles presentation.
|
||||
#
|
||||
# Use view providers to inform the workspace how your model objects should be
|
||||
# presented in the DOM. A view provider must always return a DOM node, which
|
||||
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
|
||||
# an ideal tool for implementing views in Atom.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# Text editors are divided into a model and a view layer, so when you interact
|
||||
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
|
||||
# to get the model object. We display text editors on screen by teaching the
|
||||
# workspace what view constructor it should use to represent them:
|
||||
#
|
||||
# ```coffee
|
||||
# atom.workspace.addViewProvider
|
||||
# modelConstructor: TextEditor
|
||||
# viewConstructor: TextEditorElement
|
||||
# ```
|
||||
#
|
||||
# * `providerSpec` {Object} containing the following keys:
|
||||
# * `modelConstructor` Constructor {Function} for your model.
|
||||
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
|
||||
# should be a subclass of `HTMLElement` (that is, your view should be a
|
||||
# DOM node) and have a `::setModel()` method which will be called
|
||||
# immediately after construction. If you don't supply this property, you
|
||||
# must supply the `createView` property with a function that never returns
|
||||
# `undefined`.
|
||||
# * `createView` (Optional) Factory {Function} that must return a subclass
|
||||
# of `HTMLElement` or `undefined`. If this property is not present or the
|
||||
# function returns `undefined`, the view provider will fall back to the
|
||||
# `viewConstructor` property. If you don't provide this property, you must
|
||||
# provider a `viewConstructor` property.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# added provider.
|
||||
addViewProvider: (providerSpec) ->
|
||||
@viewRegistry.addViewProvider(providerSpec)
|
||||
|
||||
+2
-3
@@ -10,19 +10,18 @@
|
||||
@import "octicon-mixins";
|
||||
|
||||
@import "workspace-view";
|
||||
@import "bootstrap";
|
||||
@import "bootstrap-overrides";
|
||||
@import "buttons";
|
||||
@import "icons";
|
||||
@import "links";
|
||||
@import "panes";
|
||||
@import "panels";
|
||||
@import "sections";
|
||||
@import "overlay";
|
||||
@import "lists";
|
||||
@import "popover-list";
|
||||
@import "messages";
|
||||
@import "markdown";
|
||||
@import "editor";
|
||||
@import "text-editor-light";
|
||||
@import "select-list";
|
||||
@import "syntax";
|
||||
@import "utilities";
|
||||
|
||||
externo
+14
@@ -0,0 +1,14 @@
|
||||
@import "ui-variables";
|
||||
|
||||
.nav {
|
||||
> li > a {
|
||||
border-radius: @component-border-radius;
|
||||
}
|
||||
> li > a:hover {
|
||||
background-color: @background-color-highlight;
|
||||
}
|
||||
|
||||
&.nav-pills > li.active > a {
|
||||
background-color: @background-color-selected;
|
||||
}
|
||||
}
|
||||
externo
+29
-12
@@ -1,14 +1,31 @@
|
||||
@import "ui-variables";
|
||||
// Core variables and mixins
|
||||
@import "../node_modules/bootstrap/less/variables.less";
|
||||
@import "../node_modules/bootstrap/less/mixins.less";
|
||||
|
||||
.nav {
|
||||
> li > a {
|
||||
border-radius: @component-border-radius;
|
||||
}
|
||||
> li > a:hover {
|
||||
background-color: @background-color-highlight;
|
||||
}
|
||||
// Reset
|
||||
@import "../node_modules/bootstrap/less/normalize.less";
|
||||
|
||||
&.nav-pills > li.active > a {
|
||||
background-color: @background-color-selected;
|
||||
}
|
||||
}
|
||||
// Core CSS
|
||||
@import "../node_modules/bootstrap/less/scaffolding.less";
|
||||
@import "../node_modules/bootstrap/less/type.less";
|
||||
@import "../node_modules/bootstrap/less/code.less";
|
||||
@import "../node_modules/bootstrap/less/grid.less";
|
||||
@import "../node_modules/bootstrap/less/tables.less";
|
||||
@import "../node_modules/bootstrap/less/forms.less";
|
||||
@import "../node_modules/bootstrap/less/buttons.less";
|
||||
|
||||
// Components
|
||||
@import "../node_modules/bootstrap/less/button-groups.less";
|
||||
@import "../node_modules/bootstrap/less/input-groups.less";
|
||||
@import "../node_modules/bootstrap/less/navs.less";
|
||||
@import "../node_modules/bootstrap/less/labels.less";
|
||||
@import "../node_modules/bootstrap/less/badges.less";
|
||||
@import "../node_modules/bootstrap/less/alerts.less";
|
||||
@import "../node_modules/bootstrap/less/list-group.less";
|
||||
@import "../node_modules/bootstrap/less/thumbnails.less";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "../node_modules/bootstrap/less/tooltip.less";
|
||||
|
||||
// Utility classes
|
||||
@import "../node_modules/bootstrap/less/utilities.less";
|
||||
|
||||
@@ -1,310 +0,0 @@
|
||||
@import "ui-variables";
|
||||
@import "octicon-utf-codes";
|
||||
@import "octicon-mixins";
|
||||
|
||||
atom-text-editor.react {
|
||||
.editor-contents {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.underlayer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
.lines {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.cursor {
|
||||
z-index: 4;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.editor-contents.is-focused .cursor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.cursors.blink-off .cursor {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.horizontal-scrollbar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
height: 15px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
z-index: 3;
|
||||
|
||||
.scrollbar-content {
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.vertical-scrollbar {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.scrollbar-corner {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.scroll-view-content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
.line-number {
|
||||
white-space: nowrap;
|
||||
padding-left: .5em;
|
||||
|
||||
.icon-right {
|
||||
padding: 0 .4em;
|
||||
&:before {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
atom-text-editor.mini {
|
||||
font-size: @input-font-size;
|
||||
line-height: @component-line-height;
|
||||
max-height: @component-line-height + 2; // +2 for borders
|
||||
|
||||
.placeholder-text {
|
||||
position: absolute;
|
||||
color: @text-color-subtle;
|
||||
}
|
||||
}
|
||||
|
||||
atom-text-editor {
|
||||
z-index: 0;
|
||||
font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
atom-text-editor, .editor-contents {
|
||||
overflow: hidden;
|
||||
cursor: text;
|
||||
display: -webkit-flex;
|
||||
-webkit-user-select: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter .line-number.cursor-line {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter {
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
cursor: default;
|
||||
min-width: 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter .line-number {
|
||||
padding-left: .5em;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter .line-numbers {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter .line-number.folded.cursor-line {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter .line-number .icon-right {
|
||||
.octicon(chevron-down, 0.8em);
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
padding-left: .1em;
|
||||
padding-right: .5em;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
atom-text-editor .gutter:hover .line-number.foldable .icon-right {
|
||||
visibility: visible;
|
||||
|
||||
&:before {
|
||||
content: @chevron-down;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
atom-text-editor .gutter, atom-text-editor .gutter:hover {
|
||||
.line-number.folded .icon-right {
|
||||
.octicon(chevron-right, 0.8em);
|
||||
visibility: visible;
|
||||
|
||||
&:before { // chevron-right renders too far right compared to chevron-down
|
||||
position: relative;
|
||||
left: -.1em;
|
||||
content: @chevron-right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
atom-text-editor .fold-marker {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
atom-text-editor .fold-marker:after {
|
||||
.icon(0.8em, inline);
|
||||
content: @ellipsis;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
|
||||
atom-text-editor .line.cursor-line .fold-marker:after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
atom-text-editor.is-blurred .line.cursor-line {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
atom-text-editor .invisible-character {
|
||||
font-weight: normal !important;
|
||||
font-style: normal !important;
|
||||
}
|
||||
|
||||
atom-text-editor .indent-guide {
|
||||
display: inline-block;
|
||||
box-shadow: inset 1px 0;
|
||||
}
|
||||
|
||||
atom-text-editor .vertical-scrollbar,
|
||||
atom-text-editor .horizontal-scrollbar {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
atom-text-editor .vertical-scrollbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 15px;
|
||||
overflow-y: auto;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
atom-text-editor .scroll-view {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-flex: 1;
|
||||
min-width: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
atom-text-editor.soft-wrap .scroll-view {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
atom-text-editor .underlayer {
|
||||
z-index: 0;
|
||||
position: absolute;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
atom-text-editor .lines {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
atom-text-editor .overlayer {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
atom-text-editor .line {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
atom-text-editor .line span {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
atom-text-editor .cursor {
|
||||
position: absolute;
|
||||
border-left: 1px solid;
|
||||
}
|
||||
|
||||
atom-text-editor .cursor,
|
||||
atom-text-editor.is-focused .cursor.blink-off {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
atom-text-editor.is-focused .cursor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.cursor.hidden-cursor {
|
||||
display: none;
|
||||
}
|
||||
|
||||
atom-text-editor .hidden-input {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
atom-text-editor .highlight {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
atom-text-editor .highlight .region,
|
||||
atom-text-editor .selection .region {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
atom-text-editor.mini:not(.react) {
|
||||
height: auto;
|
||||
line-height: 25px;
|
||||
|
||||
.cursor {
|
||||
width: 2px;
|
||||
line-height: 20px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -2,10 +2,15 @@ window.onload = function() {
|
||||
try {
|
||||
var startTime = Date.now();
|
||||
|
||||
var path = require('path');
|
||||
|
||||
// Skip "?loadSettings=".
|
||||
var loadSettings = JSON.parse(decodeURIComponent(location.search.substr(14)));
|
||||
|
||||
var devMode = loadSettings.devMode || !loadSettings.resourcePath.startsWith(process.resourcesPath + require('path').sep);
|
||||
// Normalize to make sure drive letter case is consistent on Windows
|
||||
process.resourcesPath = path.normalize(process.resourcesPath);
|
||||
|
||||
var devMode = loadSettings.devMode || !loadSettings.resourcePath.startsWith(process.resourcesPath + path.sep);
|
||||
|
||||
// Require before the module cache in dev mode
|
||||
if (devMode) {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
@import "ui-variables";
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: 500px;
|
||||
margin-left: -250px;
|
||||
z-index: 9999;
|
||||
box-sizing: border-box;
|
||||
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
color: @text-color-highlight;
|
||||
font-size: 1.6em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay atom-text-editor.mini {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.overlay .message {
|
||||
padding-top: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.overlay.mini {
|
||||
width: 200px;
|
||||
margin-left: -100px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.overlay.from-top {
|
||||
top: 0;
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.overlay.from-bottom {
|
||||
bottom: 0;
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.overlay.floating {
|
||||
left: auto;
|
||||
}
|
||||
+98
-11
@@ -1,17 +1,7 @@
|
||||
@import "ui-variables";
|
||||
|
||||
atom-panel-container[location="left"],
|
||||
atom-panel-container[location="right"] {
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: row;
|
||||
-webkit-align-items: stretch;
|
||||
height: 100%;
|
||||
atom-panel {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Override bootstrap styles here.
|
||||
|
||||
.panel {
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
@@ -25,6 +15,8 @@ atom-panel-container[location="right"] {
|
||||
}
|
||||
}
|
||||
|
||||
// interstitial panels
|
||||
|
||||
.inset-panel {
|
||||
.panel-heading {
|
||||
border-radius: @component-border-radius @component-border-radius 0 0;
|
||||
@@ -33,6 +25,7 @@ atom-panel-container[location="right"] {
|
||||
|
||||
.panel-heading {
|
||||
margin: 0;
|
||||
padding: @component-padding;
|
||||
|
||||
border-radius: 0;
|
||||
|
||||
@@ -48,3 +41,97 @@ atom-panel-container[location="right"] {
|
||||
top: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
// Tool panels
|
||||
|
||||
atom-panel-container[location="left"],
|
||||
atom-panel-container[location="right"] {
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: row;
|
||||
-webkit-align-items: stretch;
|
||||
height: 100%;
|
||||
atom-panel {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
atom-panel {
|
||||
display: block;
|
||||
}
|
||||
|
||||
atom-panel[location="top"],
|
||||
atom-panel[location="bottom"],
|
||||
atom-panel[location="left"],
|
||||
atom-panel[location="right"] {
|
||||
background-color: @tool-panel-background-color;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
.tool-panel {
|
||||
position: relative;
|
||||
background-color: @tool-panel-background-color;
|
||||
}
|
||||
|
||||
// Modal panels
|
||||
|
||||
.overlay, // deprecated .overlay
|
||||
atom-panel[location="modal"] {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: 500px;
|
||||
margin-left: -250px;
|
||||
z-index: 9999;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: @text-color;
|
||||
background-color: @overlay-background-color;
|
||||
|
||||
padding: 10px;
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
color: @text-color-highlight;
|
||||
font-size: 1.6em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
atom-text-editor.mini {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.message {
|
||||
padding-top: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
&.mini {
|
||||
width: 200px;
|
||||
margin-left: -100px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated: from-top, from-bottom
|
||||
.overlay.from-top,
|
||||
atom-panel[location="modal"] {
|
||||
top: 0;
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
// TODO: Remove these!
|
||||
.overlay.from-bottom {
|
||||
bottom: 0;
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.overlay.floating {
|
||||
left: auto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
@import "ui-variables";
|
||||
|
||||
atom-text-editor {
|
||||
display: block;
|
||||
font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
atom-text-editor.mini {
|
||||
font-size: @input-font-size;
|
||||
line-height: @component-line-height;
|
||||
max-height: @component-line-height + 2; // +2 for borders
|
||||
}
|
||||
|
||||
// TODO: remove this when the shadow DOM is the default
|
||||
atom-text-editor .highlight {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
@import "ui-variables";
|
||||
@import "octicon-utf-codes";
|
||||
@import "octicon-mixins";
|
||||
|
||||
.editor-contents {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.editor.shadow, .editor.shadow .editor-contents {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.underlayer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
.lines {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.cursor {
|
||||
z-index: 4;
|
||||
pointer-events: none;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
border-left: 1px solid;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.is-focused .cursor {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cursors.blink-off .cursor {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.horizontal-scrollbar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
height: 15px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
z-index: 3;
|
||||
cursor: default;
|
||||
|
||||
.scrollbar-content {
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.vertical-scrollbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 15px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
z-index: 3;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.scrollbar-corner {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
-webkit-flex: 1;
|
||||
min-width: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
.line-number {
|
||||
white-space: nowrap;
|
||||
padding-left: .5em;
|
||||
|
||||
.icon-right {
|
||||
padding: 0 .4em;
|
||||
&:before {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
position: absolute;
|
||||
color: @text-color-subtle;
|
||||
}
|
||||
|
||||
.editor {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.editor, .editor-contents {
|
||||
overflow: hidden;
|
||||
cursor: text;
|
||||
display: -webkit-flex;
|
||||
-webkit-user-select: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gutter .line-number.cursor-line {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.gutter {
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
cursor: default;
|
||||
min-width: 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.gutter .line-number {
|
||||
padding-left: .5em;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.gutter .line-numbers {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gutter .line-number.folded.cursor-line {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.gutter .line-number .icon-right {
|
||||
.octicon(chevron-down, 0.8em);
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
padding-left: .1em;
|
||||
padding-right: .5em;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.gutter:hover .line-number.foldable .icon-right {
|
||||
visibility: visible;
|
||||
|
||||
&:before {
|
||||
content: @chevron-down;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.gutter, .gutter:hover {
|
||||
.line-number.folded .icon-right {
|
||||
.octicon(chevron-right, 0.8em);
|
||||
visibility: visible;
|
||||
|
||||
&:before { // chevron-right renders too far right compared to chevron-down
|
||||
position: relative;
|
||||
left: -.1em;
|
||||
content: @chevron-right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fold-marker {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.fold-marker:after {
|
||||
.icon(0.8em, inline);
|
||||
content: @ellipsis;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
|
||||
.line.cursor-line .fold-marker:after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.editor.is-blurred .line.cursor-line {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.invisible-character {
|
||||
font-weight: normal !important;
|
||||
font-style: normal !important;
|
||||
}
|
||||
|
||||
.indent-guide {
|
||||
display: inline-block;
|
||||
box-shadow: inset 1px 0;
|
||||
}
|
||||
|
||||
.editor.soft-wrap .scroll-view {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.underlayer {
|
||||
z-index: 0;
|
||||
position: absolute;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.lines {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.overlayer {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.line {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.line span {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.hidden-input {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.highlight .region,
|
||||
.selection .region {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
externo
+1
-1
@@ -141,7 +141,7 @@ jasmine.JQuery.matchersClass = {};
|
||||
if (this.actual instanceof HTMLElement) {
|
||||
this.actual = jQuery(this.actual);
|
||||
}
|
||||
if (this.actual instanceof jQuery) {
|
||||
if (this.actual && this.actual.jquery) {
|
||||
var result = jQueryMatchers[methodName].apply(this, arguments);
|
||||
this.actual = jasmine.JQuery.elementToString(this.actual);
|
||||
return result;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário