Comparar commits

...

120 Commits

Autor SHA1 Mensagem Data
Nathan Sobo 2602e6ec0a Merge pull request #2865 from atom/ns-react-fix-width-remeasurement
Streamline character width remeasurement to hopefully avoid exceptions
2014-07-08 14:27:26 -06:00
Nathan Sobo 1a22fc3c68 Streamline character width remeasurement to hopefully avoid exceptions
Previously, I was just remeasuring characters whenever the stylesheets
changed. I think there were situations in which the model changed, then
I remeasured characters prior to updating the view to match the model,
causing DOM exceptions. This switches the approach to only ever measure
characters after an update, ensuring the view always matches the model.
2014-07-08 14:17:39 -06:00
Kevin Sawicki 6d02861f11 Upgrade to release-notes@0.33 2014-07-08 13:13:49 -07:00
Corey Johnson 57ed190ea3 Merge pull request #2859 from atom/cj-windows-updater
Add autoUpdater shim for Windows
2014-07-08 12:52:45 -07:00
probablycorey 436d7de817 Send empty event arg 2014-07-08 11:46:04 -07:00
probablycorey a9feed2e4a Maintain autoUpdater listeners even if the version is in dev mode.
This is so we can test the auto-updater
2014-07-08 11:41:41 -07:00
Kevin Sawicki 8b04e94d09 Upgrade to apm 0.71 2014-07-08 11:38:53 -07:00
Ben Ogle 5c5576c39d Use right margins for toolbar btn-groups rather than left.
Fixes #2830
2014-07-08 11:18:48 -07:00
Ben Ogle 2b957beeda 💄 Fix ugly test 2014-07-08 11:18:47 -07:00
probablycorey 832aeffd4f Add basic updater spec 2014-07-08 11:12:28 -07:00
Kevin Sawicki 5d08ecdcb2 Remove logging in specs 2014-07-08 10:57:22 -07:00
Nathan Sobo 997529774c Clean up after stylesheet applications in editor-component-spec 2014-07-08 11:55:50 -06:00
Nathan Sobo 48d20ff1ec Only remeasure char widths on stylesheet changes if editor is visible
Fixes #2856
2014-07-08 11:46:23 -06:00
Kevin Sawicki 0793f291d1 Prepare 0.112 2014-07-08 10:23:06 -07:00
Kevin Sawicki 8d479328ec Upgrade to language-ruby@0.32 2014-07-08 09:29:04 -07:00
Kevin Sawicki 569326e76a Upgrade to language-sql@0.9 2014-07-08 09:17:44 -07:00
Kevin Sawicki 8372b84e9f Prepare 0.111 2014-07-07 18:23:21 -07:00
Ben Ogle eda55156e5 Merge pull request #2819 from atom/bo-decoration-api
Update the decoration API
2014-07-07 18:06:35 -07:00
Kevin Sawicki c40a526302 Only require core specs to pass on Windows
Still ironing out some flaky package specs that occasionally fail
2014-07-07 18:02:54 -07:00
Ben Ogle 540b038ced Add is destroyed flag to decoration 2014-07-07 17:48:40 -07:00
Ben Ogle ce1ebec253 Fix specs 2014-07-07 17:48:24 -07:00
probablycorey 44e121c997 Add autoUpdater shim for Windows 2014-07-07 17:07:42 -07:00
Nathan Sobo 3579404bed Merge pull request #2858 from atom/ns-react-fix-wrap-guide
Make React editor indent guide work like it did in the old editor
2014-07-07 18:07:36 -06:00
Kevin Sawicki 1e19860409 Upgrade to markdown-preview@0.90 2014-07-07 17:03:02 -07:00
Ben Ogle eab4b578a3 Upgrade packages to use new decoration APIs 2014-07-07 17:01:49 -07:00
Nathan Sobo 2878196e0a Make React editor indent guide work like it did in the old editor
Fixes #2367

* The indent level of empty lines is the *max* of the nearest non empty
  line, rather than favoring the level of the line below.

* An extra wrap guide is no longer rendered for empty lines

I didn't port the specs over because we already had good coverage at the
model level. It just needed to be updated for the preferred behavior.
2014-07-07 17:59:26 -06:00
Kevin Sawicki 1c037411e9 Ignore domhandler tests 2014-07-07 16:09:40 -07:00
Kevin Sawicki 68144681b2 💄 2014-07-07 16:05:01 -07:00
Kevin Sawicki 484a516bd6 Relative path might be missing 2014-07-07 16:03:28 -07:00
Kevin Sawicki fa6e84415b Ignore gaze from jasmine-node
This is only used when jasmine-node is being launched from the CLI
with --autotest/--watch which the bundled spec runner does not use
or expose.

This reduces all bundled paths to be under 200 characters relative
to the root install location.
2014-07-07 15:57:38 -07:00
Kevin Sawicki 7117634ba8 Ignore more test directories 2014-07-07 15:57:38 -07:00
Kevin Sawicki a108c283cf Add grunt task to log long paths in built app 2014-07-07 15:57:38 -07:00
Kevin Sawicki 3dc61f4a7a Ignore more test directories 2014-07-07 15:57:37 -07:00
Nathan Sobo 9685e3f1db Merge pull request #2855 from atom/ns-active-pane-deserialization
Move serialization of active pane from Pane to PaneContainer
2014-07-07 16:49:29 -06:00
Nathan Sobo b2c70f9e69 Move serialization of active pane from Pane to PaneContainer
Fixes #2694
Fixel #2853

Previously, we were storing an `active` boolean for each pane. We've
had some strange bugs where every pane is serializing `active: false`,
which causes exceptions when loading up the stored data.

This new approach serializes the activePaneId on the PaneContainer
itself. Since the PaneContainer is the source of truth regarding the
active pane, it makes more sense to handle it here.

This unfortunately changes the serialization version for the
PaneContainer, so people won't have their state persisted after
upgrading. But it seems better than leaving cruft to handle the old
serialization situation.
2014-07-07 16:36:10 -06:00
Ben Ogle d7a3ffa9de Handle Decoration::update 2014-07-07 15:13:04 -07:00
Nathan Sobo 18ed91a402 Merge pull request #2852 from atom/ns-react-remeasure-characters-on-stylesheet-change
Re-measure character widths when stylesheets change
2014-07-07 15:47:29 -06:00
Ben Ogle e991b3d10c Move from addDecoration -> decorateMarker 2014-07-07 14:43:56 -07:00
Nathan Sobo f1b7f9ca30 Merge pull request #2851 from atom/ns-react-autoscroll-on-undo
Autoscroll to cursor on undo
2014-07-07 15:42:10 -06:00
Nathan Sobo e1e510e473 Re-measure character widths when stylesheets change
Fixes #2845
2014-07-07 15:39:00 -06:00
Nathan Sobo d042d15a50 Autoscroll to cursor on undo
Fixes #2815

This commit changes our autoscroll strategy for cursors significantly.

Originally, we were autoscrolling whenever the cursor's marker changed
positions. This worked well, except we didn't end up autoscrolling when
the user *attempted* to move the cursor to an invalid position, such as
moving down at the end of the buffer, due to the fact that the marker
wouldn't change.

Then, we moved to always requesting an autoscroll whenever a position
change was requested via Cursor::changePosition. This missed out on
moving the cursor when inserting text, so we then also added an explicit
autoscroll call when inserting text.

This had the problem of not autoscrolling due to undo. So finally, this
solution combines explicit autoscroll in ::changePosition to capture
intent, as well as implicit autoscrolling whenever the cursor's marker
position changes due to a textual change in the buffer. This captures
undo/redo correctly.
2014-07-07 15:21:48 -06:00
Ben Ogle fe9fec733d Stub out Decoration::destroy and Decoration::update 2014-07-07 14:19:20 -07:00
Kevin Sawicki 06095e57d7 Prepare 0.110 2014-07-07 14:07:41 -07:00
Nathan Sobo b83f908e28 Merge pull request #2850 from atom/ns-react-account-for-padding-in-softwrap
Account for padding-left on scroll view when soft-wrapping lines in the React editor
2014-07-07 14:36:20 -06:00
Nathan Sobo fad2a63a14 Account for padding-left on the scroll view when soft-wrapping lines
Fixes #2844
2014-07-07 14:02:24 -06:00
Nathan Sobo 2de42303d4 💄 2014-07-07 13:55:32 -06:00
Nathan Sobo a7aed07d70 Merge pull request #2849 from atom/ns-react-fix-softwrap-scroll-left
Scroll React editor all the way left when soft wrap is enabled
2014-07-07 13:31:15 -06:00
Nathan Sobo 673b62f547 Scroll React editor all the way left when soft wrap is enabled
Fixes #2842
2014-07-07 12:26:33 -06:00
Ben Ogle 19835f2f66 Upgrade tabs to support mousewheel navigation 2014-07-07 11:04:24 -07:00
Kevin Sawicki 7474de8f7e Upgrade to markdown-preview@0.89 2014-07-07 10:50:07 -07:00
Kevin Sawicki 84c30ef6c5 Set initial concurrency to 1 on all platforms 2014-07-07 10:26:12 -07:00
Kevin Sawicki 0aa5fa9eeb Increase timeout on Windows CI 2014-07-07 10:14:38 -07:00
Kevin Sawicki b5f8b159fc Upgrade to settings-view@0.132 2014-07-07 10:05:16 -07:00
Kevin Sawicki 79357be899 Upgrade to markdown-preview@0.88 2014-07-07 09:29:21 -07:00
Kevin Sawicki 12d6a90ddc Upgrade to wrap-guide@0.21 2014-07-07 09:13:11 -07:00
Kevin Sawicki 4eb3be6f17 Upgrade to markdown-preview@0.87 2014-07-07 09:12:29 -07:00
Kevin Sawicki af622c6b74 Upgrade to wrap-guide@0.20 2014-07-07 07:37:51 -07:00
Kevin Sawicki df8e0a8464 📝 Add is-focused class to cursor example
This is required to take effect for the default Atom light syntax
theme.

Closes #2834
2014-07-06 10:08:24 -07:00
Kevin Sawicki a1c1879ba6 Merge pull request #2813 from atom/ks-codesign-on-windows-ci
Codesign on Windows CI
2014-07-05 11:48:39 -07:00
Kevin Sawicki d1e52d4105 Restore spec task 2014-07-05 11:29:10 -07:00
Kevin Sawicki 0f01840e3e Restore publish checks 2014-07-05 11:28:56 -07:00
Kevin Sawicki e1945fce14 Comment out Janky check 2014-07-05 11:15:56 -07:00
Kevin Sawicki e6ecf10616 Publish builds from this branch to test signing 2014-07-05 11:12:59 -07:00
Kevin Sawicki b85ebbad2a Separate /F argument to taskkill 2014-07-05 11:06:07 -07:00
Kevin Sawicki 38ba96a54f Break up commands into two spawns 2014-07-05 10:49:25 -07:00
Kevin Sawicki 334e2ef7ab Temporarily disable specs 2014-07-05 10:46:22 -07:00
Kevin Sawicki 58efeb8a20 Force kill on Windows 2014-07-05 10:45:48 -07:00
Kevin Sawicki 3ae6540c70 Kill all atom.exe before signing 2014-07-05 10:45:35 -07:00
Kevin Sawicki 497ac5e5ce Add kill command for Windows 2014-07-05 10:41:45 -07:00
Kevin Sawicki 8735780473 Reenable specs 2014-07-05 10:29:50 -07:00
Kevin Sawicki 888b5ab098 Always pass specs to test signing 2014-07-05 10:19:14 -07:00
Kevin Sawicki c897f42d51 Use JANKY_SIGNTOOL env var to sign 2014-07-05 10:19:14 -07:00
Kevin Sawicki 3c5312e834 signtool is now on the PATH 2014-07-05 10:19:14 -07:00
Kevin Sawicki c59cbb3b25 Use full path to signtool.bat 2014-07-05 10:19:13 -07:00
Kevin Sawicki b3da11edfb 💄 Use switch 2014-07-05 10:19:13 -07:00
Kevin Sawicki f56b487935 Call signtool on Windows 2014-07-05 10:19:13 -07:00
Kevin Sawicki 840abd6780 Upgrade to settings-view@0.131 2014-07-05 10:17:49 -07:00
Kevin Sawicki 2e554ac819 Use cross platform path in Project::replace spec 2014-07-05 10:01:19 -07:00
Kevin Sawicki 35c7bc0eef Upgrade to language-coffee-script@0.24 2014-07-05 08:35:49 -07:00
Ben Ogle d99a9b0f3f Merge pull request #2826 from atom/ns-flash-specs
Explicitly test removal of flash class prior to next animation frame
2014-07-04 09:53:55 -07:00
Nathan Sobo 7ac8b80172 Explicitly test removal of flash class prior to next animation frame 2014-07-04 09:56:51 -06:00
Ben Ogle 68f2bd56f0 Upgrade find-and-replace to flash the current result 2014-07-03 17:51:43 -07:00
Ben Ogle e709b986cd Upgrade themes to fix atom/tabs#64 2014-07-03 17:51:21 -07:00
Ben Ogle 74bdd5f0e8 Merge pull request #2794 from atom/bo-flash
Add ability to 'flash' selections
2014-07-03 17:48:08 -07:00
Ben Ogle 48b6c24882 Add Editor::selectionFlashDuration rather than magic number 2014-07-03 17:36:45 -07:00
Ben Ogle e5f800ef35 💄 2014-07-03 17:32:38 -07:00
Ben Ogle 492022fdd8 Fix spec 2014-07-03 17:32:38 -07:00
Ben Ogle cf7b87842e Upgrade all the themes
Removes flash / highlighted from ui themes
Adds flash color to syntax themes
2014-07-03 17:32:38 -07:00
Ben Ogle 1838ff2502 Use ‘flash’ class rather than ‘highlighted’.
Pull the flash into the base theme rather than the ui themes
2014-07-03 17:32:38 -07:00
Ben Ogle 505bfc28db fix spec 2014-07-03 17:32:37 -07:00
Ben Ogle abbe8d2eec Flash works for selections 2014-07-03 17:32:37 -07:00
Ben Ogle bf33d96899 Decorations can be flashed 2014-07-03 17:32:37 -07:00
Ben Ogle a56b5eef2f Remove the decoration update stuff 2014-07-03 17:32:37 -07:00
Ben Ogle 80eb31679f Add a Decoration object. Rework to use this object 2014-07-03 17:32:37 -07:00
Ben Ogle 54039e9d3b Don’t use state. Modify the dom directly 2014-07-03 17:32:37 -07:00
Ben Ogle 92c28fc44f 💄 2014-07-03 17:32:37 -07:00
Ben Ogle bc67efb72b 💄 Waaay less awkward 2014-07-03 17:32:37 -07:00
Ben Ogle 0ee4d864be Move flashing into the highlight component 2014-07-03 17:32:37 -07:00
Ben Ogle 1d724339d6 Don’t use attributes 2014-07-03 17:32:37 -07:00
Ben Ogle ce90b72807 Handle the decoration + highlighted in the selection 2014-07-03 17:32:37 -07:00
Ben Ogle 4f356121d7 Handle decoration updates in the editor-component 2014-07-03 17:32:37 -07:00
Ben Ogle 7b19152a58 Add updateDecorationForMarker() 2014-07-03 17:32:37 -07:00
Ben Ogle 15da69287e Upgrade tabs, fix flicker issue 2014-07-03 17:23:03 -07:00
Kevin Sawicki 8d8db5142f Upgrade to language-javascript@0.33 2014-07-03 15:44:28 -07:00
Kevin Sawicki 6d7881bcfe Upgrade to language-less@0.12 2014-07-03 15:29:52 -07:00
Nathan Sobo c2b7955ec6 Adjust DisplayBuffer::longestScreenRow when lines are inserted/removed
Fixes #2810

The line corresponding to the longest screen row moves when lines are
inserted or removed above it, so we need to adjust it accordingly or we
won't always realize when a change affects the longest line.
2014-07-03 16:15:49 -06:00
Ben Ogle cc073ae462 Merge pull request #2816 from atom/bo-remove-fnr-marker-less
Remove fnr marker less from themes, and into fnr
2014-07-03 14:59:56 -07:00
Ben Ogle 3348c0e75a Upgrade syntax themes to remove find-result marker css
It is now in find-and-replace based on syntax-variables. Better!
2014-07-03 14:43:58 -07:00
Ben Ogle 376a850507 Update find-and-replace to set the marker css 2014-07-03 14:27:46 -07:00
Ben Ogle 168c6cdbca Revert "Move the find-and-replace marker css into the base theme "
This reverts commit 942041f214.
2014-07-03 14:22:58 -07:00
Nathan Sobo 9ece33dbfe Handle double and triple click with command key held down
Fixes #2812
2014-07-03 15:18:53 -06:00
Ben Ogle 942041f214 Move the find-and-replace marker css into the base theme 2014-07-03 14:12:23 -07:00
Nathan Sobo 260be2e096 Autoscroll *after* inserting text, not before
Fixes #2787
2014-07-03 14:47:43 -06:00
Kevin Sawicki 6c8b4de986 Upgrade to settings-view@0.130 2014-07-03 13:38:32 -07:00
Kevin Sawicki 9b267728d0 Upgrade to language-ruby@0.31 2014-07-03 13:07:52 -07:00
Kevin Sawicki 3360d8500f Upgrade to bracket-matcher@0.48 2014-07-03 10:58:57 -07:00
Nathan Sobo a4ed02c3c5 Update lines for line insertions/removals preceding rendered row range 2014-07-03 11:22:57 -06:00
Kevin Sawicki 5658f9ab07 Upgrade to language-coffee-script@0.23 2014-07-03 10:08:35 -07:00
Kevin Sawicki c890e56cef Upgrade to language-javascript@0.32 2014-07-03 09:49:46 -07:00
Kevin Sawicki 5d22ce7128 Prepare 0.109 2014-07-03 09:33:18 -07:00
33 arquivos alterados com 615 adições e 219 exclusões
+1 -1
Ver Arquivo
@@ -6,6 +6,6 @@
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "0.70.0"
"atom-package-manager": "0.71.0"
}
}
+4 -1
Ver Arquivo
@@ -47,14 +47,17 @@ module.exports = (grunt) ->
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
installDir ?= path.join(process.env.ProgramFiles, appName)
killCommand = 'taskkill /F /IM atom.exe'
else if process.platform is 'darwin'
contentsDir = path.join(shellAppDir, 'Contents')
appDir = path.join(contentsDir, 'Resources', 'app')
installDir ?= path.join('/Applications', appName)
killCommand = 'pkill -9 Atom'
else
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
killCommand ='pkill -9 Atom'
coffeeConfig =
glob_to_multiple:
@@ -213,7 +216,7 @@ module.exports = (grunt) ->
shell:
'kill-atom':
command: 'pkill -9 Atom'
command: killCommand
options:
stdout: false
stderr: false
+10
Ver Arquivo
@@ -51,7 +51,17 @@ module.exports = (grunt) ->
path.join('pegjs', 'examples')
path.join('plist', 'tests')
path.join('xmldom', 'test')
path.join('combined-stream', 'test')
path.join('delayed-stream', 'test')
path.join('domhandler', 'test')
path.join('fstream-ignore', 'test')
path.join('harmony-collections', 'test')
path.join('lru-cache', 'test')
path.join('minimatch', 'test')
path.join('normalize-package-data', 'test')
path.join('npm', 'test')
path.join('jasmine-reporters', 'ext')
path.join('jasmine-node', 'node_modules', 'gaze')
path.join('build', 'Release', 'obj.target')
path.join('build', 'Release', 'obj')
path.join('build', 'Release', '.deps')
+15 -6
Ver Arquivo
@@ -1,12 +1,12 @@
path = require 'path'
module.exports = (grunt) ->
{spawn} = require('./task-helpers')(grunt)
grunt.registerTask 'codesign', 'Codesign the app', ->
return unless process.platform is 'darwin'
done = @async()
if process.env.XCODE_KEYCHAIN
if process.platform is 'darwin' and process.env.XCODE_KEYCHAIN
unlockKeychain (error) ->
if error?
done(error)
@@ -22,6 +22,15 @@ module.exports = (grunt) ->
spawn {cmd, args}, (error) -> callback(error)
signApp = (callback) ->
cmd = 'codesign'
args = ['-f', '-v', '-s', 'Developer ID Application: GitHub', grunt.config.get('atom.shellAppDir')]
spawn {cmd, args}, (error) -> callback(error)
switch process.platform
when 'darwin'
cmd = 'codesign'
args = ['-f', '-v', '-s', 'Developer ID Application: GitHub', grunt.config.get('atom.shellAppDir')]
spawn {cmd, args}, (error) -> callback(error)
when 'win32'
spawn {cmd: 'taskkill', args: ['/F', '/IM', 'atom.exe']}, ->
cmd = process.env.JANKY_SIGNTOOL ? 'signtool'
args = [path.join(grunt.config.get('atom.shellAppDir'), 'atom.exe')]
spawn {cmd, args}, (error) -> callback(error)
else
callback()
+18
Ver Arquivo
@@ -0,0 +1,18 @@
path = require 'path'
module.exports = (grunt) ->
grunt.registerTask 'output-long-paths', 'Log long paths in the built application', ->
shellAppDir = grunt.config.get('atom.shellAppDir')
longPaths = []
grunt.file.recurse shellAppDir, (absolutePath, rootPath, relativePath, fileName) ->
if relativePath
fullPath = path.join(relativePath, fileName)
else
fullPath = fileName
longPaths.push(fullPath) if fullPath.length >= 200
longPaths.sort (longPath1, longPath2) -> longPath2.length - longPath1.length
longPaths.forEach (longPath) ->
grunt.log.error "#{longPath.length} character path: #{longPath}"
+7 -4
Ver Arquivo
@@ -53,9 +53,7 @@ module.exports = (grunt) ->
continue unless isAtomPackage(packagePath)
packageSpecQueue.push(packagePath)
# TODO: Restore concurrency on Windows
packageSpecQueue.concurrency = 1 unless process.platform is 'win32'
packageSpecQueue.concurrency = 1
packageSpecQueue.drain = -> callback(null, failedPackages)
runCoreSpecs = (callback) ->
@@ -105,4 +103,9 @@ module.exports = (grunt) ->
failures.push "atom core" if coreSpecFailed
grunt.log.error("[Error]".red + " #{failures.join(', ')} spec(s) failed") if failures.length > 0
done(!coreSpecFailed and failedPackages.length == 0)
if process.platform is 'win32' and process.env.JANKY_SHA1
# Package specs are still flaky on Windows CI
done(!coreSpecFailed)
else
done(!coreSpecFailed and failedPackages.length == 0)
+1 -1
Ver Arquivo
@@ -169,7 +169,7 @@ For example, to change the color of the cursor, you could add the following
rule to your _~/.atom/styles.less_ file:
```less
.editor .cursor {
.editor.is-focused .cursor {
border-color: pink;
}
```
+22 -22
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "0.108.0",
"version": "0.112.0",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/browser/main.js",
"repository": {
@@ -62,54 +62,54 @@
"vm-compatibility-layer": "0.1.0"
},
"packageDependencies": {
"atom-dark-syntax": "0.17.0",
"atom-dark-ui": "0.30.0",
"atom-light-syntax": "0.18.0",
"atom-light-ui": "0.26.0",
"base16-tomorrow-dark-theme": "0.17.0",
"solarized-dark-syntax": "0.18.0",
"solarized-light-syntax": "0.9.0",
"atom-dark-syntax": "0.19.0",
"atom-dark-ui": "0.32.0",
"atom-light-syntax": "0.20.0",
"atom-light-ui": "0.28.0",
"base16-tomorrow-dark-theme": "0.19.0",
"solarized-dark-syntax": "0.20.0",
"solarized-light-syntax": "0.11.0",
"archive-view": "0.33.0",
"autocomplete": "0.28.0",
"autoflow": "0.17.0",
"autosave": "0.14.0",
"background-tips": "0.15.0",
"bookmarks": "0.26.0",
"bracket-matcher": "0.47.0",
"bookmarks": "0.27.0",
"bracket-matcher": "0.48.0",
"command-palette": "0.24.0",
"deprecation-cop": "0.7.0",
"dev-live-reload": "0.31.0",
"exception-reporting": "0.18.0",
"feedback": "0.33.0",
"find-and-replace": "0.122.0",
"find-and-replace": "0.125.0",
"fuzzy-finder": "0.56.0",
"git-diff": "0.34.0",
"git-diff": "0.35.0",
"go-to-line": "0.23.0",
"grammar-selector": "0.27.0",
"image-view": "0.36.0",
"keybinding-resolver": "0.18.0",
"link": "0.24.0",
"markdown-preview": "0.86.0",
"markdown-preview": "0.90.0",
"metrics": "0.32.0",
"open-on-github": "0.29.0",
"package-generator": "0.31.0",
"release-notes": "0.32.0",
"settings-view": "0.129.0",
"release-notes": "0.33.0",
"settings-view": "0.132.0",
"snippets": "0.47.0",
"spell-check": "0.38.0",
"status-bar": "0.41.0",
"styleguide": "0.29.0",
"symbols-view": "0.59.0",
"tabs": "0.42.0",
"tabs": "0.44.0",
"timecop": "0.21.0",
"tree-view": "0.108.0",
"update-package-dependencies": "0.6.0",
"welcome": "0.17.0",
"whitespace": "0.23.0",
"wrap-guide": "0.19.0",
"wrap-guide": "0.21.0",
"language-c": "0.21.0",
"language-coffee-script": "0.22.0",
"language-coffee-script": "0.24.0",
"language-css": "0.17.0",
"language-gfm": "0.42.0",
"language-git": "0.9.0",
@@ -117,21 +117,21 @@
"language-html": "0.22.0",
"language-hyperlink": "0.10.0",
"language-java": "0.11.0",
"language-javascript": "0.30.0",
"language-javascript": "0.33.0",
"language-json": "0.8.0",
"language-less": "0.11.0",
"language-less": "0.12.0",
"language-make": "0.10.0",
"language-objective-c": "0.11.0",
"language-perl": "0.9.0",
"language-php": "0.15.0",
"language-property-list": "0.7.0",
"language-python": "0.18.0",
"language-ruby": "0.30.0",
"language-ruby": "0.32.0",
"language-ruby-on-rails": "0.15.0",
"language-sass": "0.13.0",
"language-shellscript": "0.8.0",
"language-source": "0.7.0",
"language-sql": "0.8.0",
"language-sql": "0.9.0",
"language-text": "0.6.0",
"language-todo": "0.10.0",
"language-toml": "0.12.0",
+15
Ver Arquivo
@@ -535,3 +535,18 @@ describe "the `atom` global", ->
expect(atom.isReleasedVersion()).toBe true
version = '36b5518'
expect(atom.isReleasedVersion()).toBe false
describe "window:update-available", ->
it "is triggered when the auto-updater sends the update-downloaded event", ->
updateAvailableHandler = jasmine.createSpy("update-available-handler")
atom.workspaceView.on 'window:update-available', updateAvailableHandler
autoUpdater = require('remote').require('auto-updater')
autoUpdater.emit 'update-downloaded', null, "notes", "version"
waitsFor ->
updateAvailableHandler.callCount > 0
runs ->
[event, version, notes] = updateAvailableHandler.mostRecentCall.args
expect(notes).toBe 'notes'
expect(version).toBe 'version'
+50 -6
Ver Arquivo
@@ -215,6 +215,19 @@ describe "DisplayBuffer", ->
displayBuffer.setEditorWidthInChars(-1)
expect(displayBuffer.editorWidthInChars).not.toBe -1
it "sets ::scrollLeft to 0 and keeps it there when soft wrapping is enabled", ->
displayBuffer.setDefaultCharWidth(10)
displayBuffer.setWidth(50)
displayBuffer.manageScrollPosition = true
displayBuffer.setSoftWrap(false)
displayBuffer.setScrollLeft(Infinity)
expect(displayBuffer.getScrollLeft()).toBeGreaterThan 0
displayBuffer.setSoftWrap(true)
expect(displayBuffer.getScrollLeft()).toBe 0
displayBuffer.setScrollLeft(10)
expect(displayBuffer.getScrollLeft()).toBe 0
describe "primitive folding", ->
beforeEach ->
displayBuffer.destroy()
@@ -329,8 +342,6 @@ describe "DisplayBuffer", ->
fold2 = displayBuffer.createFold(4, 9)
fold1 = displayBuffer.createFold(0, 4)
displayBuffer.logLines(0, 20)
expect(displayBuffer.lineForRow(0).text).toMatch /^0/
expect(displayBuffer.lineForRow(1).text).toMatch /^10/
@@ -643,6 +654,19 @@ describe "DisplayBuffer", ->
buffer.delete([[6, 0], [6, 65]])
expect(displayBuffer.getMaxLineLength()).toBe 62
it "correctly updates the location of the longest screen line when changes occur", ->
expect(displayBuffer.getLongestScreenRow()).toBe 6
buffer.delete([[0, 0], [2, 0]])
expect(displayBuffer.getLongestScreenRow()).toBe 4
buffer.delete([[4, 0], [5, 0]])
expect(displayBuffer.getLongestScreenRow()).toBe 1
expect(displayBuffer.getMaxLineLength()).toBe 62
buffer.delete([[2, 0], [4, 0]])
expect(displayBuffer.getLongestScreenRow()).toBe 1
expect(displayBuffer.getMaxLineLength()).toBe 62
describe "::destroy()", ->
it "unsubscribes all display buffer markers from their underlying buffer marker (regression)", ->
marker = displayBuffer.markBufferPosition([12, 2])
@@ -1014,15 +1038,35 @@ describe "DisplayBuffer", ->
expect(start.left).toBe (4 * 10) + (6 * 11)
describe "decorations", ->
it "can add decorations associated with markers and remove them", ->
decoration = {type: 'gutter', class: 'one'}
[marker, decoration, decorationParams] = []
beforeEach ->
marker = displayBuffer.markBufferRange([[2, 13], [3, 15]])
decorationParams = {type: 'gutter', class: 'one'}
decoration = displayBuffer.decorateMarker(marker, decorationParams)
displayBuffer.addDecorationForMarker(marker, decoration)
it "can add decorations associated with markers and remove them", ->
expect(decoration).toBeDefined()
expect(decoration.getParams()).toBe decorationParams
expect(displayBuffer.decorationForId(decoration.id)).toBe decoration
expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id][0]).toBe decoration
displayBuffer.removeDecorationForMarker(marker, decoration)
decoration.destroy()
expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id]).not.toBeDefined()
expect(displayBuffer.decorationForId(decoration.id)).not.toBeDefined()
it "will not fail if the decoration is removed twice", ->
decoration.destroy()
decoration.destroy()
expect(displayBuffer.decorationForId(decoration.id)).not.toBeDefined()
describe "when a decoration is updated via Decoration::update()", ->
it "emits an 'updated' event containing the new and old params", ->
decoration.on 'updated', updatedSpy = jasmine.createSpy()
decoration.update type: 'gutter', class: 'two'
{oldParams, newParams} = updatedSpy.mostRecentCall.args[0]
expect(oldParams).toEqual decorationParams
expect(newParams).toEqual type: 'gutter', class: 'two', id: decoration.id
describe "::setScrollTop", ->
beforeEach ->
+204 -44
Ver Arquivo
@@ -111,6 +111,22 @@ describe "EditorComponent", ->
expect(component.lineNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
expect(component.lineNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
it "updates the lines when lines are inserted or removed above the rendered row range", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
component.measureScrollView()
runSetImmediateCallbacks()
verticalScrollbarNode.scrollTop = 5 * lineHeightInPixels
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
buffer = editor.getBuffer()
buffer.insert([0, 0], '\n\n')
runSetImmediateCallbacks()
expect(component.lineNodeForScreenRow(3).textContent).toBe editor.lineForScreenRow(3).text
buffer.delete([[0, 0], [3, 0]])
runSetImmediateCallbacks()
expect(component.lineNodeForScreenRow(3).textContent).toBe editor.lineForScreenRow(3).text
it "updates the top position of lines when the line height changes", ->
initialLineHeightInPixels = editor.getLineHeightInPixels()
component.setLineHeight(2)
@@ -253,13 +269,11 @@ describe "EditorComponent", ->
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
expect(line2LeafNodes.length).toBe 3
expect(line2LeafNodes.length).toBe 2
expect(line2LeafNodes[0].textContent).toBe ' '
expect(line2LeafNodes[0].classList.contains('indent-guide')).toBe true
expect(line2LeafNodes[1].textContent).toBe ' '
expect(line2LeafNodes[1].classList.contains('indent-guide')).toBe true
expect(line2LeafNodes[2].textContent).toBe ' '
expect(line2LeafNodes[2].classList.contains('indent-guide')).toBe true
it "renders indent guides correctly on lines containing only whitespace", ->
editor.getBuffer().insert([1, Infinity], '\n ')
@@ -287,7 +301,7 @@ describe "EditorComponent", ->
it "updates the indent guides on empty lines preceding an indentation change", ->
editor.getBuffer().insert([12, 0], '\n')
runSetImmediateCallbacks()
editor.getBuffer().insert([13, 0], ' ')
editor.getBuffer().insert([13, 0], ' ')
runSetImmediateCallbacks()
line12LeafNodes = getLeafNodes(component.lineNodeForScreenRow(12))
@@ -299,7 +313,7 @@ describe "EditorComponent", ->
it "updates the indent guides on empty lines following an indentation change", ->
editor.getBuffer().insert([12, 2], '\n')
runSetImmediateCallbacks()
editor.getBuffer().insert([12, 0], ' ')
editor.getBuffer().insert([12, 0], ' ')
runSetImmediateCallbacks()
line13LeafNodes = getLeafNodes(component.lineNodeForScreenRow(13))
@@ -571,6 +585,33 @@ describe "EditorComponent", ->
expect(cursorRect.left).toBe rangeRect.left
expect(cursorRect.width).toBe rangeRect.width
it "positions cursors correctly after character widths are changed via a stylesheet change", ->
atom.config.set('editor.fontFamily', 'sans-serif')
editor.setCursorScreenPosition([0, 16])
runSetImmediateCallbacks()
atom.themes.applyStylesheet 'test', """
.function.js {
font-weight: bold;
}
"""
runSetImmediateCallbacks() # re-measure characters once for a synchronous set of stylesheet changes
runSetImmediateCallbacks() # update based on new measurements
cursor = node.querySelector('.cursor')
cursorRect = cursor.getBoundingClientRect()
cursorLocationTextNode = component.lineNodeForScreenRow(0).querySelector('.storage.type.function.js').firstChild
range = document.createRange()
range.setStart(cursorLocationTextNode, 0)
range.setEnd(cursorLocationTextNode, 1)
rangeRect = range.getBoundingClientRect()
expect(cursorRect.left).toBe rangeRect.left
expect(cursorRect.width).toBe rangeRect.width
atom.themes.removeStylesheet('test')
it "sets the cursor to the default character width at the end of a line", ->
editor.setCursorScreenPosition([0, Infinity])
runSetImmediateCallbacks()
@@ -727,13 +768,26 @@ describe "EditorComponent", ->
expect(selectionNode.offsetTop).toBe editor.getLineHeightInPixels()
expect(selectionNode.offsetLeft).toBe editor.pixelPositionForScreenPosition([1, 6]).left
it "will flash the selection when flash:true is passed to editor::setSelectedBufferRange", ->
editor.setSelectedBufferRange([[1, 6], [1, 10]], flash: true)
runSetImmediateCallbacks()
selectionNode = node.querySelector('.selection')
expect(selectionNode.classList.contains('flash')).toBe true
advanceClock editor.selectionFlashDuration
expect(selectionNode.classList.contains('flash')).toBe false
editor.setSelectedBufferRange([[1, 5], [1, 7]], flash: true)
runSetImmediateCallbacks()
expect(selectionNode.classList.contains('flash')).toBe true
describe "line decoration rendering", ->
[marker, decoration] = []
[marker, decoration, decorationParams] = []
beforeEach ->
marker = editor.displayBuffer.markBufferRange([[2, 13], [3, 15]], invalidate: 'inside')
decoration = {type: ['gutter', 'line'], class: 'a'}
editor.addDecorationForMarker(marker, decoration)
decorationParams = {type: ['gutter', 'line'], class: 'a'}
decoration = editor.decorateMarker(marker, decorationParams)
runSetImmediateCallbacks()
it "applies line decoration classes to lines and line numbers", ->
@@ -747,7 +801,7 @@ describe "EditorComponent", ->
# Add decorations that are out of range
marker2 = editor.displayBuffer.markBufferRange([[9, 0], [9, 0]])
editor.addDecorationForMarker(marker2, type: ['gutter', 'line'], class: 'b')
editor.decorateMarker(marker2, type: ['gutter', 'line'], class: 'b')
runSetImmediateCallbacks()
# Scroll decorations into view
@@ -770,7 +824,7 @@ describe "EditorComponent", ->
marker.destroy()
marker = editor.markBufferRange([[0, 0], [0, 2]])
editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'b')
editor.decorateMarker(marker, type: ['gutter', 'line'], class: 'b')
runSetImmediateCallbacks()
expect(lineNumberHasClass(0, 'b')).toBe true
expect(lineNumberHasClass(1, 'b')).toBe false
@@ -804,7 +858,7 @@ describe "EditorComponent", ->
it "remove decoration classes and unsubscribes from markers decorations are removed", ->
expect(marker.getSubscriptionCount('changed'))
editor.removeDecorationForMarker(marker, decoration)
decoration.destroy()
runSetImmediateCallbacks()
expect(lineNumberHasClass(1, 'a')).toBe false
expect(lineNumberHasClass(2, 'a')).toBe false
@@ -839,7 +893,7 @@ describe "EditorComponent", ->
describe "when the decoration's 'onlyHead' property is true", ->
it "only applies the decoration's class to lines containing the marker's head", ->
editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'only-head', onlyHead: true)
editor.decorateMarker(marker, type: ['gutter', 'line'], class: 'only-head', onlyHead: true)
runSetImmediateCallbacks()
expect(lineAndLineNumberHaveClass(1, 'only-head')).toBe false
expect(lineAndLineNumberHaveClass(2, 'only-head')).toBe false
@@ -848,7 +902,7 @@ describe "EditorComponent", ->
describe "when the decoration's 'onlyEmpty' property is true", ->
it "only applies the decoration when its marker is empty", ->
editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'only-empty', onlyEmpty: true)
editor.decorateMarker(marker, type: ['gutter', 'line'], class: 'only-empty', onlyEmpty: true)
runSetImmediateCallbacks()
expect(lineAndLineNumberHaveClass(2, 'only-empty')).toBe false
expect(lineAndLineNumberHaveClass(3, 'only-empty')).toBe false
@@ -860,7 +914,7 @@ describe "EditorComponent", ->
describe "when the decoration's 'onlyNonEmpty' property is true", ->
it "only applies the decoration when its marker is non-empty", ->
editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'only-non-empty', onlyNonEmpty: true)
editor.decorateMarker(marker, type: ['gutter', 'line'], class: 'only-non-empty', onlyNonEmpty: true)
runSetImmediateCallbacks()
expect(lineAndLineNumberHaveClass(2, 'only-non-empty')).toBe true
expect(lineAndLineNumberHaveClass(3, 'only-non-empty')).toBe true
@@ -871,12 +925,12 @@ describe "EditorComponent", ->
expect(lineAndLineNumberHaveClass(3, 'only-non-empty')).toBe false
describe "highlight decoration rendering", ->
[marker, decoration, scrollViewClientLeft] = []
[marker, decoration, decorationParams, scrollViewClientLeft] = []
beforeEach ->
scrollViewClientLeft = node.querySelector('.scroll-view').getBoundingClientRect().left
marker = editor.displayBuffer.markBufferRange([[2, 13], [3, 15]], invalidate: 'inside')
decoration = {type: 'highlight', class: 'test-highlight'}
editor.addDecorationForMarker(marker, decoration)
decorationParams = {type: 'highlight', class: 'test-highlight'}
decoration = editor.decorateMarker(marker, decorationParams)
runSetImmediateCallbacks()
it "does not render highlights for off-screen lines until they come on-screen", ->
@@ -885,7 +939,7 @@ describe "EditorComponent", ->
runSetImmediateCallbacks()
marker = editor.displayBuffer.markBufferRange([[9, 2], [9, 4]], invalidate: 'inside')
editor.addDecorationForMarker(marker, type: 'highlight', class: 'some-highlight')
editor.decorateMarker(marker, type: 'highlight', class: 'some-highlight')
runSetImmediateCallbacks()
# Should not be rendering range containing the marker
@@ -913,7 +967,7 @@ describe "EditorComponent", ->
expect(regions.length).toBe 2
it "removes highlights when a decoration is removed", ->
editor.removeDecorationForMarker(marker, decoration)
decoration.destroy()
runSetImmediateCallbacks()
regions = node.querySelectorAll('.test-highlight .region')
expect(regions.length).toBe 0
@@ -944,6 +998,39 @@ describe "EditorComponent", ->
regions = node.querySelectorAll('.test-highlight .region')
expect(regions.length).toBe 2
describe "when flashing a decoration via Decoration::flash()", ->
highlightNode = null
beforeEach ->
highlightNode = node.querySelector('.test-highlight')
it "adds and removes the flash class specified in ::flash", ->
expect(highlightNode.classList.contains('flash-class')).toBe false
decoration.flash('flash-class', 10)
expect(highlightNode.classList.contains('flash-class')).toBe true
advanceClock(10)
expect(highlightNode.classList.contains('flash-class')).toBe false
describe "when ::flash is called again before the first has finished", ->
it "removes the class from the decoration highlight before adding it for the second ::flash call", ->
delayAnimationFrames = true
decoration.flash('flash-class', 10)
nextAnimationFrame()
expect(highlightNode.classList.contains('flash-class')).toBe true
advanceClock(2)
decoration.flash('flash-class', 10)
# Removed for 1 frame to force CSS transition to restart
expect(highlightNode.classList.contains('flash-class')).toBe false
nextAnimationFrame()
expect(highlightNode.classList.contains('flash-class')).toBe true
advanceClock(10)
expect(highlightNode.classList.contains('flash-class')).toBe false
describe "when a decoration's marker moves", ->
it "moves rendered highlights when the buffer is changed", ->
regionStyle = node.querySelector('.test-highlight .region').style
@@ -967,6 +1054,16 @@ describe "EditorComponent", ->
regionStyle = node.querySelector('.test-highlight .region').style
expect(parseInt(regionStyle.top)).toBe 5 * lineHeightInPixels
describe "when a decoration is updated via Decoration::update", ->
it "renders the decoration's new params", ->
expect(node.querySelector('.test-highlight')).toBeTruthy()
decoration.update(type: 'highlight', class: 'new-test-highlight')
runSetImmediateCallbacks()
expect(node.querySelector('.test-highlight')).toBeFalsy()
expect(node.querySelector('.new-test-highlight')).toBeTruthy()
describe "hidden input field", ->
it "renders the hidden input field at the position of the last cursor if the cursor is on screen and the editor is focused", ->
editor.setVerticalScrollMargin(0)
@@ -1013,7 +1110,7 @@ describe "EditorComponent", ->
expect(inputNode.offsetTop).toBe 0
expect(inputNode.offsetLeft).toBe 0
describe "mouse interactions on the scrollView", ->
describe "mouse interactions on the lines", ->
linesNode = null
beforeEach ->
@@ -1049,34 +1146,61 @@ describe "EditorComponent", ->
expect(editor.getSelectedScreenRanges()).toEqual [[[3, 4], [3, 4]], [[5, 6], [5, 6]]]
describe "when a non-folded line is double-clicked", ->
it "selects the word containing the nearest screen position", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 2))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[5, 6], [5, 13]]
describe "when no modifier keys are held down", ->
it "selects the word containing the nearest screen position", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 1))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 2))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[5, 6], [5, 13]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([6, 6]), detail: 1))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[6, 6], [6, 6]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([6, 6]), detail: 1))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[6, 6], [6, 6]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([8, 8]), detail: 1, shiftKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[6, 6], [8, 8]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([8, 8]), detail: 1, shiftKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[6, 6], [8, 8]]
describe "when the command key is held down", ->
it "selects the word containing the newly-added cursor", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 1, metaKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 2, metaKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRanges()).toEqual [[[0, 0], [0, 0]], [[5, 6], [5, 13]]]
describe "when a non-folded line is triple-clicked", ->
it "selects the line containing the nearest screen position", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 3))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[5, 0], [6, 0]]
describe "when no modifier keys are held down", ->
it "selects the line containing the nearest screen position", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 1))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 2))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 3))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[5, 0], [6, 0]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([6, 6]), detail: 1, shiftKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[5, 0], [7, 0]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([6, 6]), detail: 1, shiftKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[5, 0], [7, 0]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([7, 5]), detail: 1))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([8, 8]), detail: 1, shiftKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[7, 5], [8, 8]]
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([7, 5]), detail: 1))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([8, 8]), detail: 1, shiftKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRange()).toEqual [[7, 5], [8, 8]]
describe "when the command key is held down", ->
it "selects the line containing the newly-added cursor", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 1, metaKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 2, metaKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([5, 10]), detail: 3, metaKey: true))
linesNode.dispatchEvent(buildMouseEvent('mouseup'))
expect(editor.getSelectedScreenRanges()).toEqual [[[0, 0], [0, 0]], [[5, 0], [6, 0]]]
describe "when the mouse is clicked and dragged", ->
it "selects to the nearest screen position until the mouse button is released", ->
@@ -1715,6 +1839,29 @@ describe "EditorComponent", ->
line0Right = node.querySelector('.line > span:last-child').getBoundingClientRect().right
expect(cursorLeft).toBe line0Right
describe "when stylesheets change while the editor is hidden", ->
afterEach ->
atom.themes.removeStylesheet('test')
it "does not re-measure character widths until the editor is shown again", ->
atom.config.set('editor.fontFamily', 'sans-serif')
wrapperView.hide()
atom.themes.applyStylesheet 'test', """
.function.js {
font-weight: bold;
}
"""
runSetImmediateCallbacks()
wrapperView.show()
editor.setCursorBufferPosition([0, Infinity])
runSetImmediateCallbacks()
cursorLeft = node.querySelector('.cursor').getBoundingClientRect().left
line0Right = node.querySelector('.line > span:last-child').getBoundingClientRect().right
expect(cursorLeft).toBe line0Right
describe "when lines are changed while the editor is hidden", ->
it "does not measure new characters until the editor is shown again", ->
editor.setText('')
@@ -1725,9 +1872,11 @@ describe "EditorComponent", ->
wrapperView.show()
expect(node.querySelector('.cursor').style['-webkit-transform']).toBe "translate3d(#{9 * charWidth}px, 0px, 0px)"
describe "when the editor component is resized", ->
it "updates the component based on a new size", ->
describe "soft wrapping", ->
beforeEach ->
editor.setSoftWrap(true)
it "updates the wrap location when the editor is resized", ->
newHeight = 4 * editor.getLineHeightInPixels() + "px"
expect(newHeight).toBeLessThan node.style.height
node.style.height = newHeight
@@ -1742,6 +1891,16 @@ describe "EditorComponent", ->
runSetImmediateCallbacks()
expect(node.querySelector('.line').textContent).toBe "var quicksort "
it "accounts for the scroll view's padding when determining the wrap location", ->
scrollViewNode = node.querySelector('.scroll-view')
scrollViewNode.style.paddingLeft = 20 + 'px'
node.style.width = 30 * charWidth + 'px'
advanceClock(component.scrollViewMeasurementInterval)
runSetImmediateCallbacks()
expect(component.lineNodeForScreenRow(0).textContent).toBe "var quicksort = "
describe "default decorations", ->
it "applies .cursor-line decorations for line numbers overlapping selections", ->
editor.setCursorScreenPosition([4, 4])
@@ -1804,6 +1963,7 @@ describe "EditorComponent", ->
buildMouseEvent = (type, properties...) ->
properties = extend({bubbles: true, cancelable: true}, properties...)
properties.detail ?= 1
event = new MouseEvent(type, properties)
Object.defineProperty(event, 'which', get: -> properties.which) if properties.which?
if properties.target?
+13
Ver Arquivo
@@ -785,6 +785,19 @@ describe "Editor", ->
editor.moveCursorLeft()
expect(editor.getScrollLeft()).toBe 58 * 10
it "scrolls down when inserting lines makes the document longer than the editor's height", ->
editor.setCursorScreenPosition([13, Infinity])
editor.insertNewline()
expect(editor.getScrollBottom()).toBe 14 * 10
editor.insertNewline()
expect(editor.getScrollBottom()).toBe 15 * 10
it "autoscrolls to the cursor when it moves due to undo", ->
editor.insertText('abc')
editor.setScrollTop(Infinity)
editor.undo()
expect(editor.getScrollTop()).toBe 0
describe "selection", ->
selection = null
+5 -2
Ver Arquivo
@@ -208,13 +208,16 @@ describe "Project", ->
describe "when a file doesn't exist", ->
it "calls back with an error", ->
errors = []
missingPath = path.resolve('/not-a-file.js')
expect(fs.existsSync(missingPath)).toBeFalsy()
waitsForPromise ->
atom.project.replace /items/gi, 'items', ['/not-a-file.js'], (result, error) ->
atom.project.replace /items/gi, 'items', [missingPath], (result, error) ->
errors.push(error)
runs ->
expect(errors).toHaveLength 1
expect(errors[0].path).toBe '/not-a-file.js'
expect(errors[0].path).toBe missingPath
describe "when called with unopened files", ->
it "replaces properly", ->
+1 -1
Ver Arquivo
@@ -37,7 +37,7 @@ jasmine.getEnv().addEqualityTester(_.isEqual) # Use underscore's definition of e
if process.platform is 'win32' and process.env.JANKY_SHA1
# Use longer timeout on Windows CI
jasmine.getEnv().defaultTimeoutInterval = 30000
jasmine.getEnv().defaultTimeoutInterval = 60000
else
jasmine.getEnv().defaultTimeoutInterval = 5000
+6 -6
Ver Arquivo
@@ -684,8 +684,8 @@ describe "TokenizedBuffer", ->
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 3
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 3
expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 3
expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 3
expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 2
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
@@ -693,12 +693,12 @@ describe "TokenizedBuffer", ->
buffer.setTextInRange([[7, 0], [8, 65]], ' one\n two\n three\n four')
delete changeHandler.argsForCall[0][0].bufferChange
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 8, delta: 2)
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: 2)
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 4
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 4
expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 4
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 4
expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2
it "updates the indentLevel of empty lines surrounding a change that removes lines", ->
@@ -711,7 +711,7 @@ describe "TokenizedBuffer", ->
buffer.setTextInRange([[7, 0], [8, 65]], ' ok')
delete changeHandler.argsForCall[0][0].bufferChange
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 8, delta: -1)
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: -1)
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 2
+1
Ver Arquivo
@@ -138,6 +138,7 @@ class AtomWindow
when 'window:reload' then @reload()
when 'window:toggle-dev-tools' then @toggleDevTools()
when 'window:close' then @close()
when 'window:update-available' then @sendCommandToBrowserWindow(command, args...) # For spec testing
else if @isWebViewFocused()
@sendCommandToBrowserWindow(command, args...)
else
+24 -4
Ver Arquivo
@@ -1,3 +1,4 @@
https = require 'https'
autoUpdater = require 'auto-updater'
dialog = require 'dialog'
_ = require 'underscore-plus'
@@ -16,11 +17,12 @@ class AutoUpdateManager
constructor: (@version) ->
@state = IDLE_STATE
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
# Only released versions should check for updates.
return if /\w{7}/.test(@version)
if process.platform is 'win32'
autoUpdater.checkForUpdates = => @checkForUpdatesShim()
autoUpdater.setFeedUrl "https://atom.io/api/updates?version=#{@version}"
autoUpdater.setFeedUrl @feedUrl
autoUpdater.on 'checking-for-update', =>
@setState(CHECKING_STATE)
@@ -39,7 +41,25 @@ class AutoUpdateManager
@setState(UPDATE_AVAILABLE_STATE)
@emitUpdateAvailableEvent(@getWindows()...)
@check(hidePopups: true)
# Only released versions should check for updates.
unless /\w{7}/.test(@version)
@check(hidePopups: true)
# Windows doesn't have an auto-updater, so use this method to shim the events.
checkForUpdatesShim: ->
autoUpdater.emit 'checking-for-update'
request = https.get @feedUrl, (response) ->
if response.statusCode == 200
body = ""
response.on 'data', (chunk) -> body += chunk
response.on 'end', ->
{notes, name} = JSON.parse(body)
autoUpdater.emit 'update-downloaded', null, notes, name
else
autoUpdater.emit 'update-not-available'
request.on 'error', (error) ->
autoUpdater.emit 'error', null, error.message
emitUpdateAvailableEvent: (windows...) ->
return unless @releaseVersion? and @releaseNotes
+1
Ver Arquivo
@@ -28,6 +28,7 @@ class Cursor extends Model
# Supports old editor view
@needsAutoscroll ?= @isLastCursor() and !textChanged
@autoscroll() if @editor.manageScrollPosition and @isLastCursor() and textChanged
@goalColumn = null
+57
Ver Arquivo
@@ -0,0 +1,57 @@
_ = require 'underscore-plus'
{Subscriber, Emitter} = require 'emissary'
idCounter = 0
nextId = -> idCounter++
module.exports =
class Decoration
Emitter.includeInto(this)
@isType: (decorationParams, type) ->
if _.isArray(decorationParams.type)
type in decorationParams.type
else
type is decorationParams.type
constructor: (@marker, @displayBuffer, @params) ->
@id = nextId()
@params.id = @id
@flashQueue = null
@isDestroyed = false
destroy: ->
return if @isDestroyed
@isDestroyed = true
@displayBuffer.removeDecoration(this)
@emit 'destoryed'
update: (newParams) ->
return if @isDestroyed
oldParams = @params
@params = newParams
@params.id = @id
@displayBuffer.decorationUpdated(this)
@emit 'updated', {oldParams, newParams}
getParams: ->
@params
isType: (type) ->
Decoration.isType(@params, type)
matchesPattern: (decorationPattern) ->
return false unless decorationPattern?
for key, value of decorationPattern
return false if @params[key] != value
true
flash: (klass, duration=500) ->
flashObject = {class: klass, duration}
@flashQueue ?= []
@flashQueue.push(flashObject)
@emit 'flash'
consumeNextFlash: ->
return @flashQueue.shift() if @flashQueue?.length > 0
null
+42 -38
Ver Arquivo
@@ -8,6 +8,7 @@ TokenizedBuffer = require './tokenized-buffer'
RowMap = require './row-map'
Fold = require './fold'
Token = require './token'
Decoration = require './decoration'
DisplayBufferMarker = require './display-buffer-marker'
class BufferToScreenConversionError extends Error
@@ -45,6 +46,7 @@ class DisplayBuffer extends Model
@charWidthsByScope = {}
@markers = {}
@foldsByMarkerId = {}
@decorationsById = {}
@decorationsByMarkerId = {}
@decorationMarkerChangedSubscriptions = {}
@decorationMarkerDestroyedSubscriptions = {}
@@ -202,6 +204,9 @@ class DisplayBuffer extends Model
else
@scrollLeft = Math.round(scrollLeft)
getMaxScrollLeft: ->
@getScrollWidth() - @getClientWidth()
getScrollRight: -> @scrollLeft + @width
setScrollRight: (scrollRight) ->
@setScrollLeft(scrollRight - @width)
@@ -593,6 +598,12 @@ class DisplayBuffer extends Model
getMaxLineLength: ->
@maxLineLength
# Gets the row number of the longest screen line.
#
# Return a {}
getLongestScreenRow: ->
@longestScreenRow
# Given a buffer position, this converts it into a screen position.
#
# bufferPosition - An object that represents a buffer position. It can be either
@@ -746,31 +757,17 @@ class DisplayBuffer extends Model
rangeForAllLines: ->
new Range([0, 0], @clipScreenPosition([Infinity, Infinity]))
decorationForId: (id) ->
@decorationsById[id]
decorationsForScreenRowRange: (startScreenRow, endScreenRow) ->
decorationsByMarkerId = {}
for marker in @findMarkers(intersectsScreenRowRange: [startScreenRow, endScreenRow])
if decorations = @decorationsByMarkerId[marker.id]
decorationsByMarkerId[marker.id] = decorations
decorationsByMarkerId
decorationMatchesType: (decoration, type) ->
if _.isArray(decoration.type)
type in decoration.type
else
type is decoration.type
decorationMatchesPattern: (decoration, decorationPattern) ->
return false unless decoration? and decorationPattern?
for key, value of decorationPattern
return false if decoration[key] != value
true
addDecorationForMarker: (marker, decoration) ->
unless marker?
console.warn 'A null marker cannot be decorated'
return
decorateMarker: (marker, decorationParams) ->
marker = @getMarker(marker.id)
@decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', =>
@@ -785,24 +782,23 @@ class DisplayBuffer extends Model
for decoration in decorations
@emit 'decoration-changed', marker, decoration, event
decoration = new Decoration(marker, this, decorationParams)
@decorationsByMarkerId[marker.id] ?= []
@decorationsByMarkerId[marker.id].push(decoration)
@decorationsById[decoration.id] = decoration
@emit 'decoration-added', marker, decoration
decoration
removeDecorationForMarker: (marker, decorationPattern) ->
unless marker?
console.warn 'A decoration cannot be removed from a null marker'
return
removeDecoration: (decoration) ->
{marker} = decoration
return unless decorations = @decorationsByMarkerId[marker.id]
index = decorations.indexOf(decoration)
for i in [decorations.length - 1..0]
decoration = decorations[i]
if @decorationMatchesPattern(decoration, decorationPattern)
decorations.splice(i, 1)
@emit 'decoration-removed', marker, decoration
@removedAllMarkerDecorations(marker) if decorations.length is 0
if index > -1
decorations.splice(index, 1)
delete @decorationsById[decoration.id]
@emit 'decoration-removed', marker, decoration
@removedAllMarkerDecorations(marker) if decorations.length is 0
removeAllDecorationsForMarker: (marker) ->
decorations = @decorationsByMarkerId[marker.id].slice()
@@ -818,6 +814,9 @@ class DisplayBuffer extends Model
delete @decorationMarkerChangedSubscriptions[marker.id]
delete @decorationMarkerDestroyedSubscriptions[marker.id]
decorationUpdated: (decoration) ->
@emit 'decoration-updated', decoration
# Retrieves a {DisplayBufferMarker} based on its id.
#
# id - A {Number} representing a marker id
@@ -991,18 +990,19 @@ class DisplayBuffer extends Model
endBufferRow = @rowMap.bufferRowRangeForBufferRow(endBufferRow - 1)[1]
startScreenRow = @rowMap.screenRowRangeForBufferRow(startBufferRow)[0]
endScreenRow = @rowMap.screenRowRangeForBufferRow(endBufferRow - 1)[1]
{screenLines, regions} = @buildScreenLines(startBufferRow, endBufferRow + bufferDelta)
screenDelta = screenLines.length - (endScreenRow - startScreenRow)
@screenLines[startScreenRow...endScreenRow] = screenLines
@rowMap.spliceRegions(startBufferRow, endBufferRow - startBufferRow, regions)
@findMaxLineLength(startScreenRow, endScreenRow, screenLines)
@findMaxLineLength(startScreenRow, endScreenRow, screenLines, screenDelta)
return if options.suppressChangeEvent
changeEvent =
start: startScreenRow
end: endScreenRow - 1
screenDelta: screenLines.length - (endScreenRow - startScreenRow)
screenDelta: screenDelta
bufferDelta: bufferDelta
if options.delayChangeEvent
@@ -1057,7 +1057,7 @@ class DisplayBuffer extends Model
{screenLines, regions}
findMaxLineLength: (startScreenRow, endScreenRow, newScreenLines) ->
findMaxLineLength: (startScreenRow, endScreenRow, newScreenLines, screenDelta) ->
oldMaxLineLength = @maxLineLength
if startScreenRow <= @longestScreenRow < endScreenRow
@@ -1066,19 +1066,23 @@ class DisplayBuffer extends Model
maxLengthCandidatesStartRow = 0
maxLengthCandidates = @screenLines
else
@longestScreenRow += screenDelta if endScreenRow < @longestScreenRow
maxLengthCandidatesStartRow = startScreenRow
maxLengthCandidates = newScreenLines
for screenLine, screenRow in maxLengthCandidates
for screenLine, i in maxLengthCandidates
screenRow = maxLengthCandidatesStartRow + i
length = screenLine.text.length
if length > @maxLineLength
@longestScreenRow = maxLengthCandidatesStartRow + screenRow
@longestScreenRow = screenRow
@maxLineLength = length
@computeScrollWidth() if oldMaxLineLength isnt @maxLineLength
computeScrollWidth: ->
@scrollWidth = @pixelPositionForScreenPosition([@longestScreenRow, @maxLineLength]).left + 1
@scrollWidth = @pixelPositionForScreenPosition([@longestScreenRow, @maxLineLength]).left
@scrollWidth += 1 unless @getSoftWrap()
@setScrollLeft(Math.min(@getScrollLeft(), @getMaxScrollLeft()))
handleBufferMarkersUpdated: =>
if event = @pendingChangeEvent
@@ -1090,7 +1094,7 @@ class DisplayBuffer extends Model
@emit 'marker-created', @getMarker(marker.id)
createFoldForMarker: (marker) ->
@addDecorationForMarker(marker, type: 'gutter', class: 'folded')
@decorateMarker(marker, type: 'gutter', class: 'folded')
new Fold(this, marker)
foldForMarker: (marker) ->
+30 -20
Ver Arquivo
@@ -42,7 +42,7 @@ EditorComponent = React.createClass
scrollSensitivity: 0.4
scrollViewMeasurementRequested: false
measureLineHeightAndDefaultCharWidthWhenShown: false
remeasureCharacterWidthsWhenShown: false
remeasureCharacterWidthsIfVisibleAfterNextUpdate: false
inputEnabled: true
scrollViewMeasurementInterval: 100
scopedCharacterWidthsChangeCount: null
@@ -280,21 +280,22 @@ EditorComponent = React.createClass
headScreenRow = null
if marker.isValid()
for decoration in decorations
if editor.decorationMatchesType(decoration, 'gutter') or editor.decorationMatchesType(decoration, 'line')
if decoration.isType('gutter') or decoration.isType('line')
decorationParams = decoration.getParams()
screenRange ?= marker.getScreenRange()
headScreenRow ?= marker.getHeadScreenPosition().row
startRow = screenRange.start.row
endRow = screenRange.end.row
endRow-- if not screenRange.isEmpty() and screenRange.end.column == 0
for screenRow in [startRow..endRow]
continue if decoration.onlyHead and screenRow isnt headScreenRow
continue if decorationParams.onlyHead and screenRow isnt headScreenRow
if screenRange.isEmpty()
continue if decoration.onlyNonEmpty
continue if decorationParams.onlyNonEmpty
else
continue if decoration.onlyEmpty
continue if decorationParams.onlyEmpty
decorationsByScreenRow[screenRow] ?= []
decorationsByScreenRow[screenRow].push decoration
decorationsByScreenRow[screenRow].push decorationParams
decorationsByScreenRow
@@ -306,13 +307,14 @@ EditorComponent = React.createClass
screenRange = marker.getScreenRange()
if marker.isValid() and not screenRange.isEmpty()
for decoration in decorations
if editor.decorationMatchesType(decoration, 'highlight')
if decoration.isType('highlight')
decorationParams = decoration.getParams()
filteredDecorations[markerId] ?=
id: markerId
startPixelPosition: editor.pixelPositionForScreenPosition(screenRange.start)
endPixelPosition: editor.pixelPositionForScreenPosition(screenRange.end)
decorations: []
filteredDecorations[markerId].decorations.push decoration
filteredDecorations[markerId].decorations.push decorationParams
# At least in Chromium 31, removing the last highlight causes a rendering
# artifact where chunks of the lines disappear, so we always leave this
@@ -330,6 +332,7 @@ EditorComponent = React.createClass
@subscribe editor, 'decoration-added', @onDecorationChanged
@subscribe editor, 'decoration-removed', @onDecorationChanged
@subscribe editor, 'decoration-changed', @onDecorationChanged
@subscribe editor, 'decoration-updated', @onDecorationChanged
@subscribe editor, 'character-widths-changed', @onCharacterWidthsChanged
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
@subscribe editor.$scrollLeft.changes, @requestUpdate
@@ -595,15 +598,18 @@ EditorComponent = React.createClass
editor.unfoldBufferRow(bufferRow)
return
if shiftKey
editor.selectToScreenPosition(screenPosition)
else if metaKey or (ctrlKey and process.platform isnt 'darwin')
editor.addCursorAtScreenPosition(screenPosition)
else
editor.setCursorScreenPosition(screenPosition)
switch detail
when 2 then editor.selectWord()
when 3 then editor.selectLine()
switch detail
when 1
if shiftKey
editor.selectToScreenPosition(screenPosition)
else if metaKey or (ctrlKey and process.platform isnt 'darwin')
editor.addCursorAtScreenPosition(screenPosition)
else
editor.setCursorScreenPosition(screenPosition)
when 2
editor.getLastSelection().selectWord()
when 3
editor.getLastSelection().selectLine()
@handleDragUntilMouseUp event, (screenPosition) ->
editor.selectToScreenPosition(screenPosition)
@@ -648,6 +654,8 @@ EditorComponent = React.createClass
onStylesheetsChanged: (stylesheet) ->
@refreshScrollbars() if @containsScrollbarSelector(stylesheet)
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = true
@requestUpdate() if @state.visible
onScreenLinesChanged: (change) ->
{editor} = @props
@@ -762,6 +770,8 @@ EditorComponent = React.createClass
if position is 'absolute' or width
clientWidth = scrollViewNode.clientWidth
paddingLeft = parseInt(getComputedStyle(scrollViewNode).paddingLeft)
clientWidth -= paddingLeft
editor.setWidth(clientWidth) if clientWidth > 0
measureLineHeightAndCharWidthsIfNeeded: (prevState) ->
@@ -782,12 +792,12 @@ EditorComponent = React.createClass
if @state.visible
@remeasureCharacterWidths()
else
@remeasureCharacterWidthsWhenShown = true
else if @remeasureCharacterWidthsWhenShown and @state.visible and not prevState.visible
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = true
else if @remeasureCharacterWidthsIfVisibleAfterNextUpdate and @state.visible
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = false
@remeasureCharacterWidths()
remeasureCharacterWidths: ->
@remeasureCharacterWidthsWhenShown = false
@refs.lines.remeasureCharacterWidths()
onGutterWidthChanged: (@gutterWidth) ->
+9 -39
Ver Arquivo
@@ -146,6 +146,7 @@ class Editor extends Model
selections: null
suppressSelectionMerging: false
updateBatchDepth: 0
selectionFlashDuration: 500
@delegatesMethods 'suggestedIndentForBufferRow', 'autoIndentBufferRow', 'autoIndentBufferRows',
'autoDecreaseIndentForBufferRow', 'toggleLineCommentForBufferRow', 'toggleLineCommentsForBufferRows',
@@ -218,6 +219,7 @@ class Editor extends Model
@subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args...
@subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args...
@subscribe @displayBuffer, "decoration-changed", (args...) => @emit 'decoration-changed', args...
@subscribe @displayBuffer, "decoration-updated", (args...) => @emit 'decoration-updated', args...
@subscribe @displayBuffer, "character-widths-changed", (changeCount) => @emit 'character-widths-changed', changeCount
getViewClass: ->
@@ -1108,42 +1110,11 @@ class Editor extends Model
# * onlyNonEmpty: If `true`, the decoration will only be applied if the
# associated marker is non-empty. Only applicable to the `line` and
# gutter types.
addDecorationForMarker: (marker, decoration) ->
@displayBuffer.addDecorationForMarker(marker, decoration)
decorateMarker: (marker, decoration) ->
@displayBuffer.decorateMarker(marker, decoration)
# Public: Removes all decorations associated with a {Marker} that match a
# `decorationPattern` and stop tracking the {Marker}.
#
# ```coffee
# marker = editor.markBufferRange([[4, 13], [5, 17]])
# editor.removeDecorationForMarker(marker, {type: 'gutter', class: 'linter-error'})
# ```
#
# All decorations matching a pattern will be removed. For example, you might
# have decorations with a namespace like this attached to a row:
#
# ```coffee
# [
# {type: 'gutter', namespace: 'myns', class: 'something'},
# {type: 'gutter', namespace: 'myns', class: 'something-else'}
# ]
# ```
#
# You can remove both with:
#
# ```coffee
# editor.removeDecorationForMarker(marker, {namespace: 'myns'})
# ```
#
# marker - the {Marker} to detach from
# decorationPattern - the {Object} decoration type to filter by eg. `{type: 'gutter', class: 'linter-error'}`
#
# Returns nothing
removeDecorationForMarker: (marker, decorationPattern) ->
@displayBuffer.removeDecorationForMarker(marker, decorationPattern)
decorationMatchesType: (decoration, type) ->
@displayBuffer.decorationMatchesType(decoration, type)
decorationForId: (id) ->
@displayBuffer.decorationForId(id)
# Public: Get the {DisplayBufferMarker} for the given marker id.
getMarker: (id) ->
@@ -1250,9 +1221,9 @@ class Editor extends Model
addCursor: (marker) ->
cursor = new Cursor(editor: this, marker: marker)
@cursors.push(cursor)
@addDecorationForMarker(marker, type: 'gutter', class: 'cursor-line')
@addDecorationForMarker(marker, type: 'gutter', class: 'cursor-line-no-selection', onlyHead: true, onlyEmpty: true)
@addDecorationForMarker(marker, type: 'line', class: 'cursor-line', onlyEmpty: true)
@decorateMarker(marker, type: 'gutter', class: 'cursor-line')
@decorateMarker(marker, type: 'gutter', class: 'cursor-line-no-selection', onlyHead: true, onlyEmpty: true)
@decorateMarker(marker, type: 'line', class: 'cursor-line', onlyEmpty: true)
@emit 'cursor-added', cursor
cursor
@@ -1279,7 +1250,6 @@ class Editor extends Model
if selection.intersectsBufferRange(selectionBufferRange)
return selection
else
@addDecorationForMarker(marker, type: 'highlight', class: 'selection')
@emit 'selection-added', selection
selection
+4 -3
Ver Arquivo
@@ -2,6 +2,7 @@ _ = require 'underscore-plus'
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
Decoration = require './decoration'
SubscriberMixin = require './subscriber-mixin'
WrapperDiv = document.createElement('div')
@@ -154,7 +155,7 @@ GutterComponent = React.createClass
classes = ''
if lineDecorations? and decorations = lineDecorations[screenRow]
for decoration in decorations
if editor.decorationMatchesType(decoration, 'gutter')
if Decoration.isType(decoration, 'gutter')
classes += decoration.class + ' '
classes += "foldable " if bufferRow >= 0 and editor.isFoldableAtBufferRow(bufferRow)
@@ -186,11 +187,11 @@ GutterComponent = React.createClass
if previousDecorations?
for decoration in previousDecorations
node.classList.remove(decoration.class) if editor.decorationMatchesType(decoration, 'gutter') and not _.deepContains(decorations, decoration)
node.classList.remove(decoration.class) if Decoration.isType(decoration, 'gutter') and not _.deepContains(decorations, decoration)
if decorations?
for decoration in decorations
if editor.decorationMatchesType(decoration, 'gutter') and not _.deepContains(previousDecorations, decoration)
if Decoration.isType(decoration, 'gutter') and not _.deepContains(previousDecorations, decoration)
node.classList.add(decoration.class)
unless @screenRowsByLineNumberId[lineNumberId] is screenRow
+23
Ver Arquivo
@@ -11,12 +11,35 @@ HighlightComponent = React.createClass
className = 'highlight'
className += " #{decoration.class}" if decoration.class?
div {className},
if endPixelPosition.top is startPixelPosition.top
@renderSingleLineRegions()
else
@renderMultiLineRegions()
componentDidMount: ->
{editor, decoration} = @props
if decoration.id?
@decoration = editor.decorationForId(decoration.id)
@decoration.on 'flash', @startFlashAnimation
@startFlashAnimation()
componentWillUnmount: ->
@decoration?.off 'flash', @startFlashAnimation
startFlashAnimation: ->
return unless flash = @decoration.consumeNextFlash()
node = @getDOMNode()
node.classList.remove(flash.class)
requestAnimationFrame =>
node.classList.add(flash.class)
clearTimeout(@flashTimeoutId)
removeFlashClass = -> node.classList.remove(flash.class)
@flashTimeoutId = setTimeout(removeFlashClass, flash.duration)
renderSingleLineRegions: ->
{startPixelPosition, endPixelPosition, lineHeightInPixels} = @props
+2 -2
Ver Arquivo
@@ -12,12 +12,12 @@ HighlightsComponent = React.createClass
@renderHighlights() if @isMounted()
renderHighlights: ->
{highlightDecorations, lineHeightInPixels} = @props
{editor, highlightDecorations, lineHeightInPixels} = @props
highlightComponents = []
for markerId, {startPixelPosition, endPixelPosition, decorations} of highlightDecorations
for decoration in decorations
highlightComponents.push(HighlightComponent({key: "#{markerId}-#{decoration.class}", startPixelPosition, endPixelPosition, decoration, lineHeightInPixels}))
highlightComponents.push(HighlightComponent({editor, key: "#{markerId}-#{decoration.class}", startPixelPosition, endPixelPosition, decoration, lineHeightInPixels}))
highlightComponents
+9 -5
Ver Arquivo
@@ -4,6 +4,7 @@ React = require 'react-atom-fork'
{debounce, isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
{$$} = require 'space-pen'
Decoration = require './decoration'
HighlightsComponent = require './highlights-component'
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
@@ -53,7 +54,10 @@ LinesComponent = React.createClass
{renderedRowRange, pendingChanges} = newProps
[renderedStartRow, renderedEndRow] = renderedRowRange
for change in pendingChanges
return true unless change.end < renderedStartRow or renderedEndRow <= change.start
if change.screenDelta is 0
return true unless change.end < renderedStartRow or renderedEndRow <= change.start
else
return true unless renderedEndRow <= change.start
false
@@ -132,7 +136,7 @@ LinesComponent = React.createClass
classes = ''
if decorations = lineDecorations[screenRow]
for decoration in decorations
if editor.decorationMatchesType(decoration, 'line')
if Decoration.isType(decoration, 'line')
classes += decoration.class + ' '
classes += 'line'
@@ -154,7 +158,7 @@ LinesComponent = React.createClass
if showIndentGuide and indentLevel > 0
indentSpan = "<span class='indent-guide'>#{multiplyString(' ', tabLength)}</span>"
multiplyString(indentSpan, indentLevel + 1)
multiplyString(indentSpan, indentLevel)
else
"&nbsp;"
@@ -220,11 +224,11 @@ LinesComponent = React.createClass
if previousDecorations?
for decoration in previousDecorations
lineNode.classList.remove(decoration.class) if editor.decorationMatchesType(decoration, 'line') and not _.deepContains(decorations, decoration)
lineNode.classList.remove(decoration.class) if Decoration.isType(decoration, 'line') and not _.deepContains(decorations, decoration)
if decorations?
for decoration in decorations
if editor.decorationMatchesType(decoration, 'line') and not _.deepContains(previousDecorations, decoration)
if Decoration.isType(decoration, 'line') and not _.deepContains(previousDecorations, decoration)
lineNode.classList.add(decoration.class)
lineNode.style.width = lineWidth + 'px' if updateWidth
+4
Ver Arquivo
@@ -8,6 +8,8 @@ class PaneContainer extends Model
atom.deserializers.add(this)
Serializable.includeInto(this)
@version: 1
@properties
root: -> new Pane
activePane: null
@@ -27,10 +29,12 @@ class PaneContainer extends Model
deserializeParams: (params) ->
params.root = atom.deserializers.deserialize(params.root, container: this)
params.destroyEmptyPanes = atom.config.get('core.destroyEmptyPanes')
params.activePane = params.root.getPanes().find (pane) -> pane.id is params.activePaneId
params
serializeParams: (params) ->
root: @root?.serialize()
activePaneId: @activePane.id
replaceChild: (oldChild, newChild) ->
throw new Error("Replacing non-existent child") if oldChild isnt @root
+1 -3
Ver Arquivo
@@ -40,14 +40,12 @@ class Pane extends Model
@subscribe @items.onRemoval (item, index) =>
@unsubscribe item if typeof item.on is 'function'
@activate() if params?.active
# Called by the Serializable mixin during serialization.
serializeParams: ->
id: @id
items: compact(@items.map((item) -> item.serialize?()))
activeItemUri: @activeItem?.getUri?()
focused: @focused
active: @active
# Called by the Serializable mixin during deserialization.
deserializeParams: (params) ->
+6 -1
Ver Arquivo
@@ -15,6 +15,8 @@ class Selection extends Model
constructor: ({@cursor, @marker, @editor, id}) ->
@assignId(id)
@cursor.selection = this
@decoration = @editor.decorateMarker(@marker, type: 'highlight', class: 'selection')
@marker.on 'changed', => @screenRangeChanged()
@marker.on 'destroyed', =>
@destroyed = true
@@ -76,9 +78,12 @@ class Selection extends Model
options.reversed ?= @isReversed()
@editor.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
@modifySelection =>
needsFlash = options.flash
delete options.flash if options.flash?
@cursor.needsAutoscroll = false if @needsAutoscroll?
@marker.setBufferRange(bufferRange, options)
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition
@decoration.flash('flash', @editor.selectionFlashDuration) if needsFlash
# Public: Returns the starting and ending buffer rows the selection is
# highlighting.
@@ -315,12 +320,12 @@ class Selection extends Model
wasReversed = @isReversed()
@clear()
@cursor.needsAutoscroll = @cursor.isLastCursor()
@cursor.autoscroll() if @editor.manageScrollPosition and @cursor.isLastCursor()
if options.indentBasis? and not options.autoIndent
text = @normalizeIndents(text, options.indentBasis)
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo'))
if options.select
@setBufferRange(newBufferRange, reversed: wasReversed)
else
+8 -3
Ver Arquivo
@@ -231,22 +231,27 @@ class TokenizedBuffer extends Model
indentLevelForRow: (row) ->
line = @buffer.lineForRow(row)
indentLevel = 0
if line is ''
nextRow = row + 1
lineCount = @getLineCount()
while nextRow < lineCount
nextLine = @buffer.lineForRow(nextRow)
return @indentLevelForLine(nextLine) unless nextLine is ''
unless nextLine is ''
indentLevel = Math.ceil(@indentLevelForLine(nextLine))
break
nextRow++
previousRow = row - 1
while previousRow >= 0
previousLine = @buffer.lineForRow(previousRow)
return @indentLevelForLine(previousLine) unless previousLine is ''
unless previousLine is ''
indentLevel = Math.max(Math.ceil(@indentLevelForLine(previousLine)), indentLevel)
break
previousRow--
0
indentLevel
else
@indentLevelForLine(line)
+7 -7
Ver Arquivo
@@ -64,15 +64,15 @@
}
.btn-toolbar {
> .btn-group {
> .btn-group + .btn-group, > .btn-group + .btn, > .btn + .btn {
float: none;
display: inline-block;
}
> * {
margin-right: 0;
margin-left: @component-padding/2;
}
> *:first-child {
margin-left: 0;
}
> * {
margin-right: @component-padding / 2;
}
> *:last-child {
margin-right: 0;
}
}
+14
Ver Arquivo
@@ -19,3 +19,17 @@
}
}
}
.define-selection-flash-color-if-not-defined() { @syntax-selection-flash-color: rgba(100, 255, 100, 0.7); }
.define-selection-flash-color-if-not-defined();
@-webkit-keyframes flash {
from { background-color: @syntax-selection-flash-color; }
to { background-color: null; }
}
.editor .flash.selection .region {
-webkit-animation-name: flash;
-webkit-animation-duration: .5s;
-webkit-animation-iteration-count: 1;
}
+1
Ver Arquivo
@@ -5,6 +5,7 @@
@syntax-text-color: #333;
@syntax-cursor-color: #333;
@syntax-selection-color: #69c;
@syntax-selection-flash-color: #00f; // Color the selection is 'flashed' when you run find next
@syntax-background-color: #fff;
// Guide colors