Comparar commits

...

384 Commits

Autor SHA1 Mensagem Data
Kevin Sawicki 92d16a9d0a Upgrade to apm@0.77 2014-07-11 09:23:31 -07:00
Ivan Žužak f224a6d5f0 Upgrade to fuzzy-finder@0.57.0 2014-07-11 18:14:56 +02:00
probablycorey 16f95a1420 Upgrade to metrics@v0.33.0 2014-07-11 09:02:53 -07:00
Kevin Sawicki 0231d02877 Upgrade to language-javascript@0.35 2014-07-11 08:47:10 -07:00
Kevin Sawicki 6d2b70b3d9 Check that args are present before mapping over
Closes #2925
2014-07-11 08:40:53 -07:00
Ben Ogle 49b825aeb3 Merge pull request #2927 from batjko/master
Change shift-delete to trigger core:cut in Win32 and Linux
2014-07-11 08:01:29 -07:00
Patrick Metzdorf 357299a700 Change shift-delete to trigger core:cut
Win32 and Linux keymaps
2014-07-11 10:14:56 +01:00
Kevin Sawicki 31afa0abd5 Merge pull request #2915 from atom/ks-32-bit-node-on-windows
Ship 32-bit node with apm on Windows
2014-07-10 17:40:50 -07:00
Kevin Sawicki b11accec6d 📝 Doc --arch=ia32 flag 2014-07-10 17:28:21 -07:00
Kevin Sawicki defa869d5c Upgrade to apm@0.76 2014-07-10 17:28:21 -07:00
Kevin Sawicki 8d4be6ab57 Install apm in 32-bit mode on Windows CI 2014-07-10 17:28:21 -07:00
Ben Ogle 9976166902 Render the line numbers after gutter mount
Fixes #2916
2014-07-10 17:25:58 -07:00
Kevin Sawicki 8ea277ef77 Upgrade to language-javascript@0.34 2014-07-10 17:22:13 -07:00
Kevin Sawicki d85b8bfaf3 Merge pull request #2889 from atom/ks-windows-dimensions-on-windows
Validate window dimensions
2014-07-10 14:30:01 -07:00
Daniel Hengeveld d9e15d937e Merge pull request #2895 from atom/dh-atom-io-package-rename-doc
Change some heading levels and add docs for package renames
2014-07-10 14:26:21 -07:00
Kevin Sawicki 908ff5d3cd 💄 Add space before -> 2014-07-10 14:21:02 -07:00
Kevin Sawicki 35b4ba3066 💄 2014-07-10 14:21:02 -07:00
Kevin Sawicki f90e47daef Handle invalid serialized window dimensions 2014-07-10 14:21:02 -07:00
Kevin Sawicki 5440dd68a7 Use instance method 2014-07-10 14:21:01 -07:00
Kevin Sawicki 11205d9eaa Don't store invalid window dimensions on Windows 2014-07-10 14:21:01 -07:00
Kevin Sawicki 34e37fce7c Upgrade to apm@0.75 2014-07-10 12:02:18 -07:00
Kevin Sawicki 3402c8dcd1 Dedupe request in apm folder
This prevents long path issues on Windows
2014-07-10 11:47:02 -07:00
Kevin Sawicki 3921a63f67 Just use variable in hash 2014-07-10 11:44:55 -07:00
Kevin Sawicki 5ecaf5dfc4 Upgrade to apm@0.74 2014-07-10 11:30:41 -07:00
Ben Ogle 475f92351f == -> is 2014-07-10 10:40:49 -07:00
Kevin Sawicki 0a5b378425 Upgrade to apm 0.73 2014-07-10 10:01:00 -07:00
Kevin Sawicki 157774f552 Map ctrl-f4 to core:close command on Windows
Closes #2903
2014-07-10 09:14:15 -07:00
Kevin Sawicki 320c12134a Upgrade to apm 0.72 2014-07-10 09:02:18 -07:00
Kevin Sawicki 280b451835 Merge pull request #2904 from maschs/ms-fixTypo
Fix typo
2014-07-10 08:25:20 -07:00
Maximilian Schüßler 4ee03fe590 Fix typo 2014-07-10 16:30:45 +02:00
Ben Ogle db1652f1ed Add return statement docs 2014-07-09 18:25:37 -07:00
Ben Ogle 8013ff7775 Update decoration API docs 2014-07-09 18:16:20 -07:00
Daniel Hengeveld c24475c2c8 Add error type to package version doc 2014-07-09 17:45:10 -07:00
Daniel Hengeveld 580c639265 Change some heading levels and add rename doc 2014-07-09 17:41:19 -07:00
Ben Ogle 4c33549371 Merge pull request #2888 from atom/bo-speedup-decoration-render
Index line-wise decorations by ids
2014-07-09 14:11:55 -07:00
Ben Ogle 7be5553ba1 Index line decorations by ids
And don’t use _.deepContains
2014-07-09 12:51:52 -07:00
Kevin Sawicki 43936a1faf Upgrade to find-and-replace@0.126 2014-07-09 12:24:34 -07:00
Kevin Sawicki e3c44bf551 📝 Add Windows installation instructions 2014-07-09 11:14:21 -07:00
Kevin Sawicki 6b0636d331 Upgrade to whitespace@0.24 2014-07-09 11:06:35 -07:00
Ben Ogle cb0ee735be Default cursor on scrollbars.
Fixes #2876
2014-07-09 08:46:48 -07:00
Kevin Sawicki 036dc06bac Upgrade to language-coffee-script@0.25 2014-07-09 08:23:14 -07:00
Nathan Sobo 7155ec4b73 Fix autoscroll specs for addSelectionForBufferRange 2014-07-09 08:06:14 -06:00
Nathan Sobo 86ea4d94bb Only autoscroll in model when adding selection in React editors
Fixes atom/find-and-replace#245
2014-07-09 07:46:44 -06:00
Nathan Sobo 6a2021ac98 Emit editor:will-be-removed event when unmounting the React editor 2014-07-08 21:29:53 -06:00
Nathan Sobo 6fe05064eb Use default implementation of ::destroy from theorist Model class
Move actions that need to happen on destruction to ::destroyed hook.
2014-07-08 21:29:32 -06:00
Nathan Sobo dd5c9ff6d4 Remove stray logging 2014-07-08 21:06:34 -06:00
Nathan Sobo 29179d0bbc Merge pull request #2867 from atom/ns-react-empty-line-invisibles
Render empty line invisibles in React editor
2014-07-08 20:54:41 -06:00
Kevin Sawicki f6400a4097 Upgrade to settings-view@0.133 2014-07-08 16:30:43 -07:00
Nathan Sobo e170b9f56b Render line-ending invisibles on empty lines
Fixes #2857

Including correct interleaving with indent guides.
2014-07-08 16:53:06 -06:00
probablycorey 2ea8418c66 Prepare 0.114.0 2014-07-08 15:38:08 -07:00
probablycorey c20a4a3084 Upgrade to release-notes@v0.35.0 2014-07-08 15:15:47 -07:00
Kevin Sawicki 0be64f9902 Upgrade to release-notes@0.34 2014-07-08 14:32:43 -07:00
Kevin Sawicki 5300fefef4 Prepare 0.113 2014-07-08 14:03:24 -07:00
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
Kevin Sawicki 758abf8c8a Clone grunt-coffeelint via https
Closes #2809
2014-07-03 09:12:48 -07:00
Kevin Sawicki 9e90d09428 Upgrade to language-yaml@0.11 2014-07-03 08:59:29 -07:00
Kevin Sawicki 092dac7625 Group build and install dir together 2014-07-02 14:33:44 -07:00
Kevin Sawicki c129842037 Support --install-dir option
This will install the build to a custom location

Closes #2688
2014-07-02 14:10:39 -07:00
Kevin Sawicki 4bb7e0f323 === not !== for no-quiet check 2014-07-02 13:55:58 -07:00
Kevin Sawicki 7b09fc04da Don't ignore stdout when --no-quiet is set 2014-07-02 13:51:52 -07:00
Kevin Sawicki 1090746cb1 Add --no-quiet option to script/bootstrap
This will run apm/npm commands without the --quiet flag to get more
output on failures.
2014-07-02 13:46:12 -07:00
Kevin Sawicki 294a7ce6d3 Upgrade to apm@0.70 2014-07-02 13:17:46 -07:00
Kevin Sawicki 26c1bf2075 Upgrade to bookmarks@0.26 2014-07-02 13:17:19 -07:00
Kevin Sawicki ec1d97a7c9 Prepare 0.108 2014-07-02 10:09:02 -07:00
Kevin Sawicki a92eed5107 Upgrade to background-tips@0.15 2014-07-02 09:51:09 -07:00
Nathan Sobo 66319ca9c0 Merge pull request #2801 from atom/ns-react-fix-jitter
Fix jitter in React editor
2014-07-02 10:34:01 -06:00
Nathan Sobo 17fa580ecd Ignore 'scroll' events when an update is pending
This prevents feedback loops where we handle stale 'scroll' events
for scrolls requested in the model layer. It prevents jitter when
autoscrolling with the cursor.
2014-07-02 10:11:35 -06:00
probablycorey 2585c10688 Upgrade to language-less@v0.11.0 2014-07-02 09:03:46 -07:00
Nathan Sobo 7202f497db Pause scroll view measurement in requestAnimationFrame helper method 2014-07-02 09:30:44 -06:00
Nathan Sobo 9508909a9f Don't defer updates with setImmediate in animation frames
I previously thought this was okay, but now I'm experiencing jitter when
scrolling with the trackpad when updates are deferred, and the frames
seem jagged. So this commit restores a synchronous approach to display
updates whenever we use animation frames.
2014-07-02 09:26:24 -06:00
Nathan Sobo e5ab2c6507 Pause scroll view measurement when requesting animation frames
We don't want any extra DOM reading that could introduce hitches in
the animation we're running.
2014-07-02 08:47:32 -06:00
Nathan Sobo 8add5ccd7e Remove unused EditorComponent::componentWillUpdate hook 2014-07-02 08:46:56 -06:00
Kevin Sawicki d3829e2fc6 Merge pull request #2792 from atom/document-atom-io-stargazers
Document stargazers endpoint for atom.io
2014-07-01 16:08:32 -07:00
Kevin Sawicki c26f6cc7f7 Add the 2014-07-01 16:08:18 -07:00
Kevin Sawicki 3250888e05 Add missing comma 2014-07-01 15:55:13 -07:00
Kevin Sawicki 2e6ef6848a Fence blocks as JSON 2014-07-01 15:55:02 -07:00
Ben Ogle 74bcbf6291 Upgrade themes to fix blurry tabs
Refs atom/tabs#62
2014-07-01 15:46:47 -07:00
Daniel Hengeveld ab947082dc add stargazers docs for apm 2014-07-01 15:29:04 -07:00
probablycorey 9e31bc5179 Remove runs description 2014-07-01 14:26:44 -07:00
Corey Johnson be1a2f9e30 Merge pull request #2784 from maschs/ms-writingSpecsMD
writing-specs.md: Add examples for async/promise specs
2014-07-01 14:22:12 -07:00
Kevin Sawicki 9fe887191d Upgrade to whitespace@0.23 2014-07-01 13:55:04 -07:00
Ben Ogle b0031e493e Merge pull request #2737 from atom/bo-fix-indent-guide
Fix indent guide
2014-07-01 13:46:25 -07:00
Ben Ogle 1fa6661efd Remove the awkward _.pick 2014-07-01 11:48:36 -07:00
Nathan Sobo 8b57bb3309 Merge pull request #2789 from atom/ns-react-disable-gpu-option
Add editor.gpuDisabled option to prevent React editor from using layers
2014-07-01 12:48:34 -06:00
Kevin Sawicki 8b2e1b088a Merge pull request #2788 from atom/ks-add-chocolatey-ignores
Add chocolatey ignores
2014-07-01 11:48:12 -07:00
Ben Ogle dcb0d9b039 Update editor component specs 2014-07-01 11:41:44 -07:00
Nathan Sobo 4efabd2b5e 💄 method name 2014-07-01 12:34:00 -06:00
Nathan Sobo 18d17b55b5 Pass useHardwareAcceleration property down to CursorComponent instances 2014-07-01 12:33:45 -06:00
Ben Ogle 718e1228bd Add checks for the change event 2014-07-01 11:32:04 -07:00
Kevin Sawicki 22b0a35dba Add comment mentioning chocoloatey 2014-07-01 11:29:33 -07:00
Kevin Sawicki e395b1416a Add chocolatey gui for atom.exe 2014-07-01 11:19:54 -07:00
Nathan Sobo 0edfbaebeb Rename editor option to useHardwareAcceleration 2014-07-01 12:17:43 -06:00
Ben Ogle 3e57fb8e9a 💄 naming 2014-07-01 10:59:42 -07:00
Nathan Sobo 512d4da587 Add editor.gpuDisabled option to prevent React editor from using layers
When gpuDisabled is true, we use `translate` instead of `translate3d`
to position various elements, preventing the creation of GPU layers.
2014-07-01 11:56:05 -06:00
Ben Ogle de0e945c5c More specs in tokenized buffer testing empty line retokenizing 2014-07-01 10:54:37 -07:00
Ben Ogle & Nathan Sobo 4642d96f39 Tokenize empty lines with a changed indent level synchronously 2014-07-01 10:54:37 -07:00
Ben Ogle de2930fe99 💄 2014-07-01 10:54:37 -07:00
Ben Ogle 65c2f26656 Little note 📝 2014-07-01 10:54:36 -07:00
Ben Ogle 8ca709eb6a Fix spec name 2014-07-01 10:54:36 -07:00
Ben Ogle 43e88f6515 Invalidate whitespace lines when their indent level changes
Refs #2376
2014-07-01 10:54:36 -07:00
Ben Ogle d97eacc2f9 Add isOnlyWhitespace() 2014-07-01 10:54:36 -07:00
Kevin Sawicki a70367c70b Add chocolatey ignore for ctags-win32.exe 2014-07-01 10:45:32 -07:00
Ben Ogle d60c718fe2 Merge pull request #2783 from atom/bo-up-scandal
Upgrade scandal to handle file read errors
2014-07-01 10:45:27 -07:00
Kevin Sawicki fe838375a1 Add chocolatey ignore for node.exe 2014-07-01 10:45:25 -07:00
Ben Ogle 06d06d10e0 💄 2014-07-01 10:45:13 -07:00
Ben Ogle de9f070f53 Upgrade find-and-replace
It will display errors from scandal.
2014-07-01 10:45:13 -07:00
Ben Ogle a6e437b9d3 Upgrade scandal
This version emits events when errors are encountered with file reading.
2014-07-01 10:44:30 -07:00
Ben Ogle 44b95fc637 Emit errors from the out of process searches 2014-07-01 10:44:30 -07:00
Nathan Sobo e93e4e9333 Autoscroll to the last cursor in model when inserting text
Fixes #2787
2014-07-01 11:37:17 -06:00
Nathan Sobo d4a7bff525 Merge pull request #2608 from philschatz/ps-dedupe-context-menu
remove duplicate context menu entries
2014-07-01 11:08:18 -06:00
Nathan Sobo 5e78bbf471 Upgrade fuzzy finder to support traversing symlinked directories 2014-07-01 10:53:59 -06:00
Kevin Sawicki 873abd68af Merge pull request #2767 from smashwilson/ignore-desktop
Ignore generated files in resources/linux.
2014-07-01 09:50:11 -07:00
Nathan Sobo d42a064a44 Merge pull request #2773 from atom/ns-react-fix-delete-line-jitter
Fix scroll jitter when deleting a line reduces the maximum allowed scrollTop
2014-07-01 09:27:58 -06:00
Nathan Sobo 32c8a3ce99 Only adjust scrollTop when deleting lines when using the React editor 2014-07-01 09:16:29 -06:00
Nathan Sobo a99bde4e2d Reassign scrollTop if deleting lines decreases the max scrollTop
Fixes #2725
2014-07-01 09:01:04 -06:00
Maximilian Schüßler 5753680b58 Minor changes 2014-07-01 13:26:47 +02:00
Maximilian Schüßler 68ddbd9e75 📝 Add examples for async/promise specs 2014-07-01 02:51:47 +02:00
probablycorey e6725c9fcb Fix prepare docs 2014-06-30 11:48:10 -07:00
Corey Johnson b14317cf50 Merge pull request #2753 from atom/cj-dh-publish-docs
Build and publish API docs
2014-06-30 11:09:05 -07:00
Nathan Sobo bb6a44a757 Hard code node-runas to 0.5.4 trying to fix the build 2014-06-30 17:32:01 +01:00
Nathan Sobo 431fc725ff Interpret editor clicks relative to lines div, not the scrollView div
Fixes #2668

If the scroll view has padding, using it as the basis for locating
clicks relative to the lines is problematic.
2014-06-30 16:24:07 +01:00
Ash Wilson 72d5a4cdae Ignore generated files in resources/linux. 2014-06-29 09:34:24 -04:00
Nathan Sobo f5517bad66 Merge pull request #2757 from atom/ns-better-default-decorations
Improve default decorations for cursor and selection lines in React editor
2014-06-28 16:04:12 +01:00
Kevin Sawicki a63797019d Upgrade to language-less@0.10 2014-06-28 15:57:28 +01:00
Nathan Sobo 324f1392a3 Revert changes related to the .selection-line class
We will introduce .selection-line as part of a separate effort, not the
React switchover.
2014-06-28 15:52:10 +01:00
Nathan Sobo 21ae33f749 Merge pull request #2763 from atom/ns-react-fix-autoscroll
Autoscroll cursor when attempting to move it, even if it doesn't move
2014-06-28 15:42:31 +01:00
Nathan Sobo 15ca3e2a40 Match existing editor's behavior for .cursor-line class 2014-06-28 15:39:22 +01:00
Nathan Sobo ea9f5eb1c7 💄 Unify specs for all line decorations 2014-06-28 15:39:22 +01:00
Nathan Sobo 7f70b41696 Update the specs for .cursor/selection-line decorations 2014-06-28 15:39:22 +01:00
Nathan Sobo 9a6510c938 Add .cursor-line-no-selection decoration for backward compatibility 2014-06-28 15:39:22 +01:00
Nathan Sobo 825910dc1d Add onlyEmpty and onlyNonEmpty decoration options 2014-06-28 15:39:22 +01:00
Nathan Sobo bd238d6885 Add specs for gutter decoration options
- onlyHead
- onlyEmpty
- onlyNonEmpty
2014-06-28 15:39:22 +01:00
Nathan Sobo 8435e0176b Add selection-line class to old editor gutter for forward-compatibility
The React editor does not apply the .cursor-line-no-selection class,
but instead relies on a combination of .cursor-line and .selection-line
for selectors that want to target the cursor line when there is no
selection.

This allows themes to be upgraded to support the React editor and the
old editor at the same time.
2014-06-28 15:39:21 +01:00
Nathan Sobo 5bdaf3cbe4 Make both .cursor-line and .selection-line opaque 2014-06-28 15:39:21 +01:00
Nathan Sobo f5e54b0ba6 Only add 'selection-line' decoration when marker is non-empty 2014-06-28 15:39:21 +01:00
Nathan Sobo fa7e388352 Add 'onlyEmpty' and 'onlyNonEmpty' decoration options 2014-06-28 15:39:21 +01:00
Nathan Sobo 70f352251e Only apply cursor-line decoration to head; Add selected-line decoration.
The cursor-line decoration shouldn't be applied to every line that's
selected. It should only be applied to the location of the cursor. We'll
need to update themes to reflect this.
2014-06-28 15:39:21 +01:00
Nathan Sobo 1b05708d7a Update addDecorationForMarker docs to talk about 'onlyHead' option 2014-06-28 15:39:21 +01:00
Nathan Sobo a2b90cd501 Add 'onlyHead' option for decorations
It only decorates the head position of the decoration's marker.
2014-06-28 15:39:21 +01:00
Nathan Sobo 61c7e797b9 Upgrade markdown-preview to hopefully fix flaky spec 2014-06-28 15:38:59 +01:00
Nathan Sobo b689ffd402 Autoscroll cursor when attempting to move it, even if it doesn't move 2014-06-28 15:26:02 +01:00
Nathan Sobo 71fb063a67 Un-f 2014-06-28 15:24:24 +01:00
Nathan Sobo b376bd8688 Fix scrollbar dragging in React editor
Fixes #2751
2014-06-28 11:33:41 +01:00
probablycorey e068d3d293 Merge remote-tracking branch 'origin/master' into cj-dh-publish-docs 2014-06-27 11:04:23 -07:00
probablycorey a49221e359 Upgrade to language-go@v0.13.0 2014-06-27 10:32:14 -07:00
probablycorey e7aef25f1f Update tokenized buffer specs 2014-06-27 10:18:04 -07:00
probablycorey 071b391994 Describe surrogate pair as UTF-8 surrogate pair 2014-06-27 10:17:28 -07:00
probablycorey 7b11343ea8 Remove semi-colon 2014-06-27 09:37:05 -07:00
probablycorey d25f432400 Upgrade to tree-view@v0.108.0 2014-06-27 09:36:12 -07:00
probablycorey 2e16f2dc3f Upgrade to first-mate@1.7.1 2014-06-27 09:31:19 -07:00
probablycorey f828b91686 Only prepare docs on darwin platforms. 2014-06-27 08:53:43 -07:00
probablycorey 3f4210c293 Only publish build if on janky and using the master branch 2014-06-27 08:52:12 -07:00
Kevin Sawicki 0f7b97821b Upgrade ot markdown-preview@0.85 2014-06-27 12:44:20 +01:00
Kevin Sawicki efa457bade Upgrade to settings-view@0.129 2014-06-27 12:33:06 +01:00
Kevin Sawicki 61188cb05f Upgrade to image-view@0.36 2014-06-27 09:42:26 +01:00
Kevin Sawicki 69c3001836 Upgrade to language-javascript@0.30 2014-06-27 09:35:01 +01:00
probablycorey 81afb89d27 Copy API docs to the build dir 2014-06-26 16:14:54 -07:00
Corey Johnson & Daniel Hengeveld 2107b10778 Add upload-assets grunt task 2014-06-26 15:02:18 -07:00
Corey Johnson & Daniel Hengeveld bc31f94833 Add getAssets method 2014-06-26 15:01:26 -07:00
Corey Johnson & Daniel Hengeveld 58c2cec787 Rename sourceName to sourcePath 2014-06-26 14:37:21 -07:00
Corey Johnson & Daniel Hengeveld 2c95af63e6 Rename zipApp to zipAssets 2014-06-26 14:33:09 -07:00
Corey Johnson & Daniel Hengeveld 8a377c9339 Make docs output dir a config var 2014-06-26 14:30:43 -07:00
Corey Johnson & Daniel Hengeveld e21f561af5 Add Daniel to pairs file 2014-06-26 14:25:40 -07:00
probablycorey ccb01c23d2 💄 Add spacing between packages and languages packages 2014-06-26 11:53:37 -07:00
probablycorey 3bc50c9b2c Upgrade to language-javascript@v0.29.0 2014-06-26 11:52:52 -07:00
probablycorey 18c5f9c8de Upgrade to tree-view@0.107.0 2014-06-26 11:52:06 -07:00
Ben Ogle 7179bc5af1 Merge pull request #2738 from atom/bo-fix-max-scroll-width
Fix max scroll width in react editor
2014-06-25 18:16:32 -07:00
Nathan Sobo 3bf0c73170 Assign line width explicitly to prevent full screen repaints
Fixes #2746
2014-06-25 19:13:50 -06:00
Nathan Sobo 95242c8c82 Merge pull request #2747 from atom/ns-set-immediate
Use setImmediate instead of nextTick to batch React editor updates
2014-06-25 18:48:47 -06:00
Nathan Sobo eb84737109 Fix specs for use of setImmediate instead of nextTick in requestUpdate 2014-06-25 18:38:06 -06:00
Nathan Sobo 2b54c9bebe Use setImmediate to batch all editor updates, even in animation frames
When I was using nextTick to batch updates, there were issues with
flicker. So I was attempting to always update synchronously in animation
frames, which was complicated. setImmediate doesn't cause the flicker
however, so I'm able to remove the special logic for sync updates in
animation frames and just use it across the board.
2014-06-25 18:20:49 -06:00
Nathan Sobo 63e8099088 Allow successive accented characters to be inserted in React editor
Refs #2732

Because we're only checking the length of the input element's selection
in the React editor on textinput events and not also its content, we
were mistaking some IME compositions as accented character menu
insertions. Clearing the content of the input on 'compositionend'
prevents this issue.
2014-06-25 18:19:53 -06:00
Ben Ogle & Nathan Sobo f739dce210 Only recompute scroll width once for each batch of measured chars 2014-06-25 15:26:13 -07:00
Ben Ogle & Nathan Sobo 77389b0518 Update scrollWidth when the max line length / default char width changes 2014-06-25 15:26:13 -07:00
Ben Ogle 809804d0cc 💄 2014-06-25 15:26:13 -07:00
Ben Ogle 8054b769d6 Default scrollWidth to 0 2014-06-25 15:26:13 -07:00
Ben Ogle e3c3779a73 Don’t need to return the list. So just return 2014-06-25 15:26:13 -07:00
Ben Ogle 196f64d846 Fix specs 2014-06-25 15:26:13 -07:00
Ben Ogle 9cc1244f32 Compute the longest line width based on the longest line 2014-06-25 15:26:13 -07:00
Ben Ogle 1c69995bb6 Upgrade command-palette with better description 2014-06-25 15:04:26 -07:00
Kevin Sawicki 7c4cbd8bf9 Upgrade to open-on-github@0.29.0 2014-06-25 13:04:51 -07:00
probablycorey 570f59a7e2 Upgrade to tree-view@0.106.0 2014-06-25 10:06:33 -07:00
Nathan Sobo 8d71e3f69a Merge pull request #2740 from atom/bo-round-scroll-vars
Never allow partial pixel values for scroll
2014-06-25 09:45:47 -06:00
Kevin Sawicki 0263d72551 Upgrade to language-gfm@0.42 2014-06-25 08:30:37 -07:00
Kevin Sawicki 9299ff3404 📝 Remove observeConfig
Replaced with subscribe/atom.config.observe

Closes #2742
2014-06-25 08:11:30 -07:00
Cheng Zhao 7c79643b89 Upgrade to atom-shell@0.13.3 2014-06-25 09:52:51 +08:00
Kevin Sawicki 6a4b4d2efd Upgrade to language-gfm@0.41 2014-06-24 18:24:47 -07:00
Ben Ogle d6f217f80a Never allow partial pixel values for scroll 2014-06-24 18:09:03 -07:00
Nathan Sobo 1f94e89e56 Merge pull request #2739 from atom/ns-react-raf-vs-next-tick
Only perform a single synchronous update inside animation frames
2014-06-24 19:08:10 -06:00
Nathan Sobo 27a959ec16 Combine all updates that occur in an animation frame 2014-06-24 18:48:59 -06:00
Kevin Sawicki 0369d77c85 Ensure grammars are only activated once 2014-06-24 16:21:56 -07:00
Ben Ogle 866bc02d68 💄 Inline the gutter component 2014-06-24 14:47:26 -07:00
Ivan Žužak ae96d9aeaa Upgrade to tree-view@0.105.0 2014-06-24 22:15:42 +02:00
Nathan Sobo 5481b37d01 Merge pull request #2735 from atom/ns-react-precompute-pixel-rects
Compute pixel rects of cursors and highlights in EditorComponent
2014-06-24 13:34:56 -06:00
Nathan Sobo b127155805 Only pause cursor blink when cursors actually move
Not when they are just repositioned due to lineHeight/charWidth changes
2014-06-24 13:26:21 -06:00
Nathan Sobo 74dbfbc956 Add HighlightComponent::shouldComponentUpdate 2014-06-24 13:04:48 -06:00
Nathan Sobo f41a9739ac 💄 2014-06-24 13:02:41 -06:00
Nathan Sobo b75e748ec5 Restore pausing of cursor blink on cursor movement 2014-06-24 12:59:13 -06:00
Nathan Sobo 3f9fdad478 Precompute pixel rects for highlight decorations in EditorComponent 2014-06-24 12:56:52 -06:00
Nathan Sobo 0150b40376 Implement CursorComponent::shouldComponentUpdate
This prevents re-rendering cursors on blink, since only the class on
the outer component changes.
2014-06-24 12:42:58 -06:00
Nathan Sobo d3e6bd038f Precompute cursor pixel rects in EditorComponent and pass them down 2014-06-24 12:40:56 -06:00
Ben Ogle b7d8e581ee Merge pull request #2727 from atom/bo-subscribe-to-marker-changes
Subscribe to marker changes
2014-06-24 11:15:47 -07:00
Kevin Sawicki daaf9be4bf Upgrade to language-java@0.11 2014-06-24 10:50:10 -07:00
Ben Ogle 396b21bc04 Fix specs failures caused by making lines 100% width 2014-06-24 10:32:48 -06:00
Kevin Sawicki d4617f1036 Upgrade to timecop@0.21 2014-06-24 09:04:09 -07:00
Kevin Sawicki 6cb5af0bfc Map ctrl-pageup/down to pane:show-next/previous-item
Closes #2724
2014-06-24 08:44:26 -07:00
Kevin Sawicki 1c2e997415 Merge pull request #2700 from atom/bo-grammar-preload
Preload grammars on deserialization
2014-06-24 08:26:57 -07:00
Kevin Sawicki 148b691734 Test grammars included across multiple packages 2014-06-24 08:14:11 -07:00
Ben Ogle 9b577ecbf8 Make lines 100% of the width of their container
This is part of the solution to #2701. Lines need to be 100% wide in
case a class styles their background.
2014-06-23 22:46:27 -06:00
Ben Ogle d57119793b Properly disable nextTick when calling requestAnimationFrame
My previous commit was nonsense because it set the ::performSyncUpdates
flag back to false before the animation frame callback ever got fired.

/cc again @benogle
2014-06-23 22:35:40 -06:00
Ben Ogle ccada33d57 Remove nextTick in spec 2014-06-23 22:27:40 -06:00
Ben Ogle 1d9514ca81 Don't call nextTick within requestAnimationFrame
This seems to be causing stutter when scrolling on the GPU. When I don't
use nextTick when requesting animation frames, the problem seems to go
away. Maybe there's some issue with the integration between the Node
and Chromium event loops plus sending things to the compositor.

/cc @benogle
2014-06-23 22:21:28 -06:00
Ben Ogle 5ebb17c2e8 Be defensive when iterating through decorations 2014-06-23 18:03:19 -07:00
Kevin Sawicki f741b1d6a6 Store timings for deserializing project and workspace 2014-06-23 17:46:44 -07:00
Ben Ogle 36280bb3a7 Add noop for resetDisplay
fixes #2674
2014-06-23 17:46:35 -07:00
Kevin Sawicki 15ccfac75a 💄 2014-06-23 17:46:31 -07:00
Kevin Sawicki 2e424baf2a Use correct expected call count 2014-06-23 17:41:33 -07:00
Kevin Sawicki 0547d5a78b Assert grammars are sync loaded on deserialize 2014-06-23 17:36:14 -07:00
Kevin Sawicki 5529f13cc6 Only create grammar load promise once 2014-06-23 17:33:05 -07:00
Ben Ogle 058ab7d486 Upgrade find-and-replace to clean up specs 2014-06-23 17:16:07 -07:00
Kevin Sawicki 0a54233ef0 Merge branch 'master' into bo-grammar-preload 2014-06-23 17:05:48 -07:00
Ben Ogle b4f4ef8ec4 💄
Make it not suck.
2014-06-23 17:04:32 -07:00
Kevin Sawicki e11785ce98 Serialize packages names in Workspace 2014-06-23 16:56:46 -07:00
Kevin Sawicki b1d7de8d43 Add spec for serializing active grammars 2014-06-23 16:41:46 -07:00
Kevin Sawicki becdca0858 Store grammars in Atom::unloadEditorWindow 2014-06-23 16:30:02 -07:00
Kevin Sawicki c9e3ca3d69 Remove logging 2014-06-23 16:23:07 -07:00
Kevin Sawicki 6336ffbf44 Store included grammar scopes 2014-06-23 16:22:37 -07:00
Kevin Sawicki 6aeca79d1b Return empty promise when already loaded 2014-06-23 16:13:13 -07:00
Kevin Sawicki e76b24f8ad Catch error 2014-06-23 16:04:25 -07:00
Kevin Sawicki 0304f187dd Remove preload request from deserializeParams 2014-06-23 16:03:56 -07:00
Kevin Sawicki 968ab0e41d Remove unused methods 2014-06-23 16:02:45 -07:00
Kevin Sawicki ea6feddd7b Track duration of grammar preload 2014-06-23 16:00:58 -07:00
Ben Ogle f381abcbad Re-render when a marker changes
fixes #2705
2014-06-23 16:00:36 -07:00
Kevin Sawicki bb5d628397 Track packages to preload in Atom class 2014-06-23 15:59:26 -07:00
Kevin Sawicki f3d87b1653 Set packageName property on Grammar objects 2014-06-23 15:58:06 -07:00
Ben Ogle & Nathan Sobo 76a911f17a Render highlights immediately to support underlayer shim 2014-06-23 16:23:45 -06:00
Ben Ogle 7139fd9f98 Conditionally render the gutter for the showLineNumbers option
Fixes #2707
2014-06-23 15:22:16 -07:00
Kevin Sawicki 64e2b53baa Add cursor with ctrl-click on Windows/Linux
Closes #2105
2014-06-23 14:43:00 -07:00
Kevin Sawicki 78630a14fd Upgrade to language-yaml@0.10 2014-06-23 14:12:50 -07:00
Kevin Sawicki 38fbcbdf89 Upgrade to symbols-view@0.59 2014-06-23 14:11:14 -07:00
probablycorey 6e102c7e1e Rename regex var to a more appropriate name 2014-06-23 10:51:58 -07:00
Kevin Sawicki f40c8a97c0 Upgrade to markdown-preview@0.84 2014-06-23 10:43:40 -07:00
Nathan Sobo b9a3eca091 Correcly handle folds that end where other folds begin
Fixes #2247
2014-06-23 11:29:14 -06:00
Kevin Sawicki f9fcb1767b Upgrade to symbols-view@0.58.0 2014-06-23 10:00:17 -07:00
Kevin Sawicki 433843ba23 📝 Wrap line and use single backticks 2014-06-23 09:36:44 -07:00
Kevin Sawicki 598e752a9d Merge pull request #2713 from Theswweet/patch-1
Update linux.md to accomadate build issues
2014-06-23 09:32:01 -07:00
probablycorey c1142f6c6a Merge branch 'cj-make-sure-editor-events-are-called-in-the-correct-order' 2014-06-23 09:31:12 -07:00
Kevin Sawicki 937ff194b6 Upgrade to language-ruby-on-rails@0.15 2014-06-23 09:18:34 -07:00
probablycorey 9a5da3c27e Add next tick call 2014-06-23 09:13:39 -07:00
probablycorey 43cb9af4a4 Add editor-event spec 2014-06-23 08:51:17 -07:00
James Galizio 843c075779 Fixed typo's for proposed commit. 2014-06-22 11:59:11 -07:00
Ivan Žužak e13cf19daa Upgrade to welcome@0.17.0 2014-06-22 17:52:48 +02:00
Cheng Zhao 0eecf49e61 Merge pull request #2653 from deprint/desktop-file-fix
Fix for installation of desktop file
2014-06-22 11:42:21 +08:00
James Galizio 748d189079 Update linux.md to accomadate build issues
I ran into this when I installed today, and the inscribed method allowed me to complete my atom install on CrunchBang. I've seen a few issues having to do with this, so it might be advisable to have it in the troubleshooting section!
2014-06-21 20:36:55 -07:00
Kevin Sawicki 9d4c4a190f Upgrade to snippets@0.47 2014-06-21 07:14:22 -07:00
Kevin Sawicki ac2b84f21e Upgrade to timecop@0.20 2014-06-21 07:10:25 -07:00
Kevin Sawicki 610f515f68 Upgrade to language-yaml@0.9 2014-06-21 07:06:18 -07:00
Ben Ogle 0dadce1047 Serialize all included grammar scopes 2014-06-20 17:04:21 -07:00
Ben Ogle 8c3bfaa3a2 Return when grammars are already loaded 2014-06-20 17:04:21 -07:00
Ben Ogle f8b8b22b75 Preload grammars on deserialization 2014-06-20 17:04:21 -07:00
Philip Schatz 67a1ed92db 💄 context menu tests 2014-06-19 19:14:34 -04:00
Fabian Stiewitz 87aae13c80 Prevent double slash in Atom.desktop 2014-06-18 20:28:38 +02:00
Fabian Stiewitz c735432163 Install with respect to INSTALL_PREFIX 2014-06-18 20:07:29 +02:00
Philip Schatz 624c0bf9f1 allow multiple labels for the same command 2014-06-17 23:36:59 -04:00
Philip Schatz 2fdcf7a124 remove duplicate context menu entries 2014-06-13 21:30:55 -04:00
67 arquivos alterados com 2069 adições e 856 exclusões
+2
Ver Arquivo
@@ -13,3 +13,5 @@ debug.log
docs/output
docs/includes
spec/fixtures/evil-files/
resources/linux/Atom.desktop
resources/linux/debian/control
+1
Ver Arquivo
@@ -11,6 +11,7 @@ pairs:
bo: Ben Ogle; benogle
jr: Jason Rudolph; jasonrudolph
jl: Jessica Lord; jlord
dh: Daniel Hengeveld; danielh
email:
domain: github.com
#global: true
+12
Ver Arquivo
@@ -6,10 +6,21 @@ Visit [atom.io](https://atom.io) to learn more.
## Installing
### Mac OS X
Download the latest [Atom release](https://github.com/atom/atom/releases/latest).
Atom will automatically update when a new release is available.
### Windows
Install the [Atom chocolatey package](https://chocolatey.org/packages/Atom).
1. Install [chocolatey](https://chocolatey.org).
2. Close and reopen your command prompt or PowerShell window.
3. Run `cinst Atom`
4. In the future run `cup Atom` to upgrade to the latest release.
## Building
* [Linux](docs/build-instructions/linux.md)
@@ -18,4 +29,5 @@ Atom will automatically update when a new release is available.
* [Windows](docs/build-instructions/windows.md)
## Developing
Check out the [guides](https://atom.io/docs/latest) and the [API reference](https://atom.io/docs/api).
+1 -1
Ver Arquivo
@@ -6,6 +6,6 @@
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "0.69.0"
"atom-package-manager": "0.77.0"
}
}
+10 -4
Ver Arquivo
@@ -39,21 +39,25 @@ module.exports = (grunt) ->
tmpDir = os.tmpdir()
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
installDir = grunt.option('install-dir')
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
shellAppDir = path.join(buildDir, appName)
if process.platform is 'win32'
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
installDir = path.join(process.env.ProgramFiles, appName)
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)
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'
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
killCommand ='pkill -9 Atom'
coffeeConfig =
glob_to_multiple:
@@ -121,6 +125,8 @@ module.exports = (grunt) ->
atom: {appDir, appName, symbolsDir, buildDir, contentsDir, installDir, shellAppDir}
docsOutputDir: 'docs/output/api'
coffee: coffeeConfig
less: lessConfig
@@ -210,7 +216,7 @@ module.exports = (grunt) ->
shell:
'kill-atom':
command: 'pkill -9 Atom'
command: killCommand
options:
stdout: false
stderr: false
+1 -1
Ver Arquivo
@@ -13,7 +13,7 @@
"github-releases": "~0.2.0",
"grunt": "~0.4.1",
"grunt-cli": "~0.1.9",
"grunt-coffeelint": "git://github.com/atom/grunt-coffeelint.git",
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git",
"grunt-contrib-csslint": "~0.1.2",
"grunt-contrib-coffee": "~0.9.0",
"grunt-contrib-less": "~0.8.0",
+15
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')
@@ -90,6 +100,11 @@ module.exports = (grunt) ->
cp path.join('resources', 'win', 'msvcp100.dll'), path.join(shellAppDir, 'msvcp100.dll')
cp path.join('resources', 'win', 'msvcr100.dll'), path.join(shellAppDir, 'msvcr100.dll')
# Set up chocolatey ignore and gui files
fs.writeFileSync path.join(appDir, 'apm', 'node_modules', 'atom-package-manager', 'bin', 'node.exe.ignore'), ''
fs.writeFileSync path.join(appDir, 'node_modules', 'symbols-view', 'vendor', 'ctags-win32.exe.ignore'), ''
fs.writeFileSync path.join(shellAppDir, 'atom.exe.gui'), ''
dependencies = ['compile', "generate-license:save"]
dependencies.push('copy-info-plist') if process.platform is 'darwin'
dependencies.push('set-exe-icon') if process.platform is 'win32'
+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()
+4 -2
Ver Arquivo
@@ -15,15 +15,17 @@ module.exports = (grunt) ->
grunt.registerTask 'build-docs', 'Builds the API docs in src', ->
done = @async()
docsOutputDir = grunt.config.get('docsOutputDir')
downloadIncludes (error, includePaths) ->
if error?
done(error)
else
rm('docs/output/api')
rm(docsOutputDir)
args = [
commonArgs...
'--title', 'Atom API Documentation'
'-o', 'docs/output/api'
'-o', docsOutputDir
'-r', 'docs/README.md'
'--stability', '1'
'src/'
+6 -4
Ver Arquivo
@@ -40,13 +40,15 @@ module.exports = (grunt) ->
mkdir path.dirname(shareDir)
cp shellAppDir, shareDir
# Create Atom.desktop if installation in '/usr/local'
applicationsDir = path.join('/usr','share','applications')
# Create Atom.desktop if installation not in temporary folder
tmpDir = if process.env.TMPDIR? then process.env.TMPDIR else '/tmp'
if installDir.indexOf(tmpDir) isnt 0 and fs.isDirectorySync(applicationsDir)
desktopInstallFile = path.join(installDir,'share','applications','Atom.desktop')
if installDir.indexOf(tmpDir) isnt 0
mkdir path.dirname(desktopInstallFile)
{description} = grunt.file.readJSON('package.json')
installDir = path.join(installDir,'.') # To prevent "Exec=/usr/local//share/atom/atom"
fillTemplate(desktopFile, {description, installDir, iconName})
cp desktopFile, path.join(applicationsDir,'Atom.desktop')
cp desktopFile, desktopInstallFile
# Create relative symbol link for apm.
process.chdir(binDir)
+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}"
+29 -19
Ver Arquivo
@@ -9,16 +9,6 @@ request = require 'request'
grunt = null
if process.platform is 'darwin'
assets = [
{assetName: 'atom-mac.zip', sourceName: 'Atom.app'}
{assetName: 'atom-mac-symbols.zip', sourceName: 'Atom.breakpad.syms'}
]
else
assets = [
{assetName: 'atom-windows.zip', sourceName: 'Atom'}
]
commitSha = process.env.JANKY_SHA1
token = process.env.ATOM_ACCESS_TOKEN
defaultHeaders =
@@ -30,11 +20,19 @@ module.exports = (gruntObject) ->
grunt.registerTask 'publish-build', 'Publish the built app', ->
return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'master'
tasks = ['upload-assets']
tasks.unshift('build-docs', 'prepare-docs') if process.platform is 'darwin'
grunt.task.run(tasks)
grunt.registerTask 'prepare-docs', 'Move the build docs to the build dir', ->
fs.copySync(grunt.config.get('docsOutputDir'), path.join(grunt.config.get('atom.buildDir'), 'atom-docs'))
grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', ->
done = @async()
buildDir = grunt.config.get('atom.buildDir')
assets = getAssets()
zipApps buildDir, assets, (error) ->
zipAssets buildDir, assets, (error) ->
return done(error) if error?
getAtomDraftRelease (error, release) ->
return done(error) if error?
@@ -43,26 +41,38 @@ module.exports = (gruntObject) ->
return done(error) if error?
uploadAssets(release, buildDir, assets, done)
getAssets = ->
if process.platform is 'darwin'
[
{assetName: 'atom-mac.zip', sourcePath: 'Atom.app'}
{assetName: 'atom-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'}
{assetName: 'atom-docs.zip', sourcePath: 'atom-docs'}
]
else
[
{assetName: 'atom-windows.zip', sourcePath: 'Atom'}
]
logError = (message, error, details) ->
grunt.log.error(message)
grunt.log.error(error.message ? error) if error?
grunt.log.error(details) if details
zipApps = (buildDir, assets, callback) ->
zip = (directory, sourceName, assetName, callback) ->
zipAssets = (buildDir, assets, callback) ->
zip = (directory, sourcePath, assetName, callback) ->
if process.platform is 'win32'
zipCommand = "C:/psmodules/7z.exe a -r #{assetName} #{sourceName}"
zipCommand = "C:/psmodules/7z.exe a -r #{assetName} #{sourcePath}"
else
zipCommand = "zip -r --symlinks #{assetName} #{sourceName}"
zipCommand = "zip -r --symlinks #{assetName} #{sourcePath}"
options = {cwd: directory, maxBuffer: Infinity}
child_process.exec zipCommand, options, (error, stdout, stderr) ->
logError("Zipping #{sourceName} failed", error, stderr) if error?
logError("Zipping #{sourcePath} failed", error, stderr) if error?
callback(error)
tasks = []
for {assetName, sourceName} in assets
for {assetName, sourcePath} in assets
fs.removeSync(path.join(buildDir, assetName))
tasks.push(zip.bind(this, buildDir, sourceName, assetName))
tasks.push(zip.bind(this, buildDir, sourcePath, assetName))
async.parallel(tasks, callback)
getAtomDraftRelease = (callback) ->
@@ -127,7 +137,7 @@ uploadAssets = (release, buildDir, assets, callback) ->
fs.createReadStream(assetPath).pipe(assetRequest)
tasks = []
for {assetName, sourceName} in assets
for {assetName} in assets
assetPath = path.join(buildDir, assetName)
tasks.push(upload.bind(this, release, assetName, assetPath))
async.parallel(tasks, callback)
+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)
+12 -22
Ver Arquivo
@@ -11,41 +11,31 @@ value of a namespaced config key with `atom.config.get`:
@showInvisibles() if atom.config.get "editor.showInvisibles"
```
Or you can use the `::observeConfig` to track changes from any view object.
Or you can use the `::subscribe` with `atom.config.observe` to track changes
from any view object.
```coffeescript
class MyView extends View
initialize: ->
@observeConfig 'editor.fontSize', () =>
@subscribe atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
@adjustFontSize()
```
The `::observeConfig` method will call the given callback immediately with the
current value for the specified key path, and it will also call it in the future
whenever the value of that key path changes.
The `atom.config.observe` method will call the given callback immediately with
the current value for the specified key path, and it will also call it in the
future whenever the value of that key path changes.
Subscriptions made with `observeConfig` are automatically canceled when the
Subscriptions made with `::subscribe` are automatically canceled when the
view is removed. You can cancel config subscriptions manually via the
`unobserveConfig` method.
`off` method on the subscription object that `atom.config.observe` returns.
```coffeescript
view1.unobserveConfig() # unobserve all properties
```
fontSizeSubscription = atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
@adjustFontSize()
You can add the ability to observe config values to non-view classes by
extending their prototype with the `ConfigObserver` mixin:
# ... later on
```coffeescript
{ConfigObserver} = require 'atom'
class MyClass
ConfigObserver.includeInto(this)
constructor: ->
@observeConfig 'editor.showInvisibles', -> # ...
destroy: ->
@unobserveConfig()
fontSizeSubscription.off() # Stop observing
```
### Writing Config Settings
+50 -10
Ver Arquivo
@@ -1,4 +1,4 @@
## Atom.io package and update API
# Atom.io package and update API
This guide describes the web API used by [apm](https://github.com/atom/apm) and
Atom. The vast majority of use cases are met by the `apm` command-line tool,
@@ -17,9 +17,11 @@ For calls to the API that require authentication, provide a valid token from you
All requests that take parameters require `application/json`.
## Resources
# API Resources
### Packages
## Packages
### Listing packages
#### GET /api/packages
@@ -40,6 +42,8 @@ Returns a list of all packages in the following format:
]
```
### Showing package details
#### GET /api/packages/:package_name
Returns package details and versions for a single package
@@ -68,6 +72,8 @@ Returns:
}
```
### Creating a package
#### POST /api/packages
Create a new package; requires authentication.
@@ -92,6 +98,7 @@ Returns:
- The package.json at owner/repo isn't valid
- **409** - A package by that name already exists
### Deleting a package
#### DELETE /api/packages/:package_name
@@ -103,6 +110,13 @@ Returns:
- **400** - Repository is inaccessible
- **401** - Unauthorized
### Renaming a package
Packages are renamed by publishing a new version with the name changed in `package.json`
See [Creating a new package version](#creating-a-new-package-version) for details.
Requests made to the previous name will forward to the new name.
### Package Versions
#### GET /api/packages/:package_name/versions/:version_name
@@ -144,7 +158,9 @@ Returns `package.json` with `dist` key added for e.g. tarball download:
#### POST /api/packages/:package_name/versions
Creates a new package version from a git tag; requires authentication.
Creates a new package version from a git tag; requires authentication. If `rename`
is not `true`, the `name` field in `package.json` *must* match the current package
name.
#### Parameters
@@ -152,14 +168,15 @@ Creates a new package version from a git tag; requires authentication.
that the version name will not be taken from the tag, but from the `version`
key in the `package.json` file at that ref. The authenticating user *must* have
access to the package repository.
- **rename** - Boolean indicating whether this version contains a new name for the package.
#### Returns
- **201** - Successfully created. Returns created version.
- **400** - Git tag not found / Repository inaccessible
- **400** - Git tag not found / Repository inaccessible / package.json invalid
- **409** - Version exists
### Delete a version
### Deleting a version
#### DELETE /api/packages/:package_name/versions/:version_name
@@ -172,7 +189,9 @@ you'll need to increment the version when republishing.
Returns 204 No Content
### Stars
## Stars
### Listing user stars
#### GET /api/users/:login/stars
@@ -186,19 +205,40 @@ List the authenticated user's starred packages; requires authentication.
Return value is similar to **GET /api/packages**
### Starring a package
#### POST /api/packages/:name/star
Star a package; requires authentication.
Returns a package.
### Unstarring a package
#### DELETE /api/packages/:name/star
Unstar a package; requires authentication.
Returns 204 No Content.
### Atom updates
### Listing a package's stargazers
#### GET /api/packages/:name/stargazers
List the users that have starred a package.
Returns a list of user objects:
```json
[
{"login":"aperson"},
{"login":"anotherperson"},
]
```
## Atom updates
### Listing Atom updates
#### GET /api/updates
@@ -206,10 +246,10 @@ Atom update feed, following the format expected by [Squirrel](https://github.com
Returns:
```
```json
{
"name": "0.96.0",
"notes": "[HTML release notes]"
"notes": "[HTML release notes]",
"pub_date": "2014-05-19T15:52:06.000Z",
"url": "https://www.atom.io/api/updates/download"
}
+7
Ver Arquivo
@@ -61,6 +61,13 @@ and restart Atom. If Atom now works fine, you can make this setting permanent:
See also https://github.com/atom/atom/issues/2082.
### /usr/bin/env: node: No such file or directory
If you get this notice when attempting to `script/build`, you either do not
have nodejs installed, or node isn't identified as nodejs on your machine.
If it's the latter, entering `sudo ln -s /usr/bin/nodejs /usr/bin/node` into
your terminal may fix the issue.
### Linux build error reports in atom/atom
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Alinux&type=Issues)
to get a list of reports about build errors on Linux.
+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;
}
```
+69 -1
Ver Arquivo
@@ -38,7 +38,7 @@ Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec
0. Add one or more expectations
The best way to learn about expectations is to read the [jasmine documentation](http://jasmine.github.io/2.0/introduction.html#section-Expectations) about them. Below is a simple example.
The best way to learn about expectations is to read the [jasmine documentation](http://jasmine.github.io/1.3/introduction.html#section-Expectations) about them. Below is a simple example.
```coffee
describe "when a test is written", ->
@@ -47,6 +47,74 @@ Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec
expect("oranges").not.toEqual("apples")
```
## Asynchronous specs
Writing Asynchronous specs can be tricky at first. Some examples.
0. Promises
Working with promises is rather easy in Atom. You can use our `waitsForPromise` function.
```coffee
describe "when we open a file", ->
it "should be opened in an editor", ->
waitsForPromise ->
atom.workspace.open('c.coffee').then (editor) ->
expect(editor.getPath()).toContain 'c.coffee'
```
This method can be used in the `describe`, `it`, `beforeEach` and `afterEach` functions.
```coffee
describe "when we open a file", ->
beforeEach ->
waitsForPromise ->
atom.workspace.open 'c.coffee'
it "should be opened in an editor", ->
expect(atom.workspace.getActiveEditor().getPath()).toContain 'c.coffee'
```
If you need to wait for multiple promises use a new `waitsForPromise` function for each promise. (Caution: Without `beforeEach` this example will fail!)
```coffee
describe "waiting for the packages to load", ->
beforeEach ->
waitsForPromise ->
atom.workspace.open('sample.js')
waitsForPromise ->
atom.packages.activatePackage('tabs')
waitsForPromise ->
atom.packages.activatePackage('tree-view')
it 'should have waited long enough', ->
expect(atom.packages.isPackageActive('tabs')).toBe true
expect(atom.packages.isPackageActive('tree-view')).toBe true
```
0. Asynchronous functions with callbacks
Specs for asynchronous functions can be done using the `waitsFor` and `runs` functions. A simple example.
```coffee
describe "fs.readdir(path, cb)", ->
it "is async", ->
spy = jasmine.createSpy('fs.readdirSpy')
fs.readdir('/tmp/example', spy)
waitsFor ->
spy.callCount > 0
runs ->
exp = [null, ['example.coffee']]
expect(spy.mostRecentCall.args).toEqual exp
expect(spy).toHaveBeenCalledWith(null, ['example.coffee'])
```
For a more detailed documentation on asynchronous tests please visit the [jasmine documentation](http://jasmine.github.io/1.3/introduction.html#section-Asynchronous_Support).
## Running specs
Most of the time you'll want to run specs by triggering the `window:run-package-specs` command. This command is not only to run package specs, it is also for Atom core specs. This will run all the specs in the current project's spec directory. If you want to run the Atom core specs and **all** the default package specs trigger the `window:run-all-specs` command.
+2
Ver Arquivo
@@ -69,6 +69,8 @@
'cmd-}': 'pane:show-next-item'
'cmd-alt-left': 'pane:show-previous-item'
'cmd-alt-right': 'pane:show-next-item'
'ctrl-pageup': 'pane:show-previous-item'
'ctrl-pagedown': 'pane:show-next-item'
'ctrl-tab': 'pane:show-next-item'
'ctrl-shift-tab': 'pane:show-previous-item'
'cmd-=': 'window:increase-font-size'
+3 -1
Ver Arquivo
@@ -38,13 +38,15 @@
'shift-pageup': 'core:select-page-up'
'shift-pagedown': 'core:select-page-down'
'delete': 'core:delete'
'shift-delete': 'core:delete'
'shift-delete': 'core:cut'
'pageup': 'core:page-up'
'pagedown': 'core:page-down'
'backspace': 'core:backspace'
'shift-backspace': 'core:backspace'
'ctrl-tab': 'pane:show-next-item'
'ctrl-shift-tab': 'pane:show-previous-item'
'ctrl-pageup': 'pane:show-previous-item'
'ctrl-pagedown': 'pane:show-next-item'
'ctrl-shift-up': 'core:move-up'
'ctrl-shift-down': 'core:move-down'
'ctrl-=': 'window:increase-font-size'
+4 -1
Ver Arquivo
@@ -26,6 +26,7 @@
'ctrl-s': 'core:save'
'ctrl-S': 'core:save-as'
'ctrl-w': 'core:close'
'ctrl-f4': 'core:close'
'ctrl-z': 'core:undo'
'ctrl-y': 'core:redo'
'ctrl-x': 'core:cut'
@@ -40,13 +41,15 @@
'shift-pageup': 'core:select-page-up'
'shift-pagedown': 'core:select-page-down'
'delete': 'core:delete'
'shift-delete': 'core:delete'
'shift-delete': 'core:cut'
'pageup': 'core:page-up'
'pagedown': 'core:page-down'
'backspace': 'core:backspace'
'shift-backspace': 'core:backspace'
'ctrl-tab': 'pane:show-next-item'
'ctrl-shift-tab': 'pane:show-previous-item'
'ctrl-pageup': 'pane:show-previous-item'
'ctrl-pagedown': 'pane:show-next-item'
'ctrl-shift-up': 'core:move-up'
'ctrl-shift-down': 'core:move-down'
'ctrl-alt-up': 'editor:add-selection-above'
+44 -43
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "0.107.0",
"version": "0.114.0",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/browser/main.js",
"repository": {
@@ -17,7 +17,7 @@
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
}
],
"atomShellVersion": "0.13.2",
"atomShellVersion": "0.13.3",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "^0.27.0",
@@ -27,7 +27,7 @@
"coffeestack": "0.7.0",
"delegato": "^1",
"emissary": "^1.2.1",
"first-mate": "^1.7",
"first-mate": "^1.7.1",
"fs-plus": "^2.2.3",
"fstream": "0.1.24",
"fuzzaldrin": "^1.1",
@@ -47,8 +47,8 @@
"random-words": "0.0.1",
"react-atom-fork": "^0.10.0",
"reactionary-atom-fork": "^0.9.0",
"runas": "^0.5",
"scandal": "0.15.3",
"runas": "0.5.4",
"scandal": "0.16.0",
"scoped-property-store": "^0.9.0",
"scrollbar-style": "^0.4.0",
"season": "^1.0.2",
@@ -62,80 +62,81 @@
"vm-compatibility-layer": "0.1.0"
},
"packageDependencies": {
"atom-dark-syntax": "0.17.0",
"atom-dark-ui": "0.29.0",
"atom-light-syntax": "0.18.0",
"atom-light-ui": "0.25.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.14.0",
"bookmarks": "0.25.0",
"bracket-matcher": "0.47.0",
"command-palette": "0.23.0",
"background-tips": "0.15.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.120.0",
"fuzzy-finder": "0.55.0",
"git-diff": "0.34.0",
"find-and-replace": "0.126.0",
"fuzzy-finder": "0.57.0",
"git-diff": "0.35.0",
"go-to-line": "0.23.0",
"grammar-selector": "0.27.0",
"image-view": "0.35.0",
"image-view": "0.36.0",
"keybinding-resolver": "0.18.0",
"link": "0.24.0",
"markdown-preview": "0.83.0",
"metrics": "0.32.0",
"open-on-github": "0.28.0",
"markdown-preview": "0.90.0",
"metrics": "0.33.0",
"open-on-github": "0.29.0",
"package-generator": "0.31.0",
"release-notes": "0.32.0",
"settings-view": "0.128.0",
"snippets": "0.46.0",
"release-notes": "0.35.0",
"settings-view": "0.133.0",
"snippets": "0.47.0",
"spell-check": "0.38.0",
"status-bar": "0.41.0",
"styleguide": "0.29.0",
"symbols-view": "0.56.0",
"tabs": "0.42.0",
"timecop": "0.19.0",
"tree-view": "0.104.0",
"symbols-view": "0.59.0",
"tabs": "0.44.0",
"timecop": "0.21.0",
"tree-view": "0.108.0",
"update-package-dependencies": "0.6.0",
"welcome": "0.16.0",
"whitespace": "0.22.0",
"wrap-guide": "0.19.0",
"welcome": "0.17.0",
"whitespace": "0.24.0",
"wrap-guide": "0.21.0",
"language-c": "0.21.0",
"language-coffee-script": "0.22.0",
"language-coffee-script": "0.25.0",
"language-css": "0.17.0",
"language-gfm": "0.40.0",
"language-gfm": "0.42.0",
"language-git": "0.9.0",
"language-go": "0.12.0",
"language-go": "0.13.0",
"language-html": "0.22.0",
"language-hyperlink": "0.10.0",
"language-java": "0.10.0",
"language-javascript": "0.28.0",
"language-java": "0.11.0",
"language-javascript": "0.35.0",
"language-json": "0.8.0",
"language-less": "0.9.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-on-rails": "0.14.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",
"language-xml": "0.15.0",
"language-yaml": "0.7.0"
"language-yaml": "0.11.0"
},
"private": true,
"scripts": {
+43 -6
Ver Arquivo
@@ -31,7 +31,7 @@ function bootstrap() {
fs.mkdirSync(path.join(apmInstallPath, 'node_modules'));
var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm')
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? ' --no-color' : '';
var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm');
var initialNpmCommand = fs.existsSync(npmPath) ? npmPath : 'npm';
@@ -39,12 +39,49 @@ function bootstrap() {
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season', 'grim'];
var buildInstallCommand = initialNpmCommand + npmFlags + 'install';
var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')};
var apmInstallCommand = npmPath + npmFlags + 'install';
var apmInstallOptions = {cwd: apmInstallPath};
var moduleInstallCommand = apmPath + ' install' + apmFlags;
var dedupeApmCommand = apmPath + ' dedupe' + apmFlags;
var dedupeNpmCommand = npmPath + npmFlags + 'dedupe';
if (process.argv.indexOf('--no-quiet') === -1) {
buildInstallCommand += ' --quiet';
apmInstallCommand += ' --quiet';
moduleInstallCommand += ' --quiet';
dedupeApmCommand += ' --quiet';
dedupeNpmCommand += ' --quiet';
buildInstallOptions.ignoreStdout = true;
apmInstallOptions.ignoreStdout = true;
}
// apm ships with 32-bit node so make sure its native modules are compiled
// for a 32-bit target architecture
if (process.env.JANKY_SHA1 && process.platform === 'win32')
apmInstallCommand += ' --arch=ia32';
var commands = [
{command: initialNpmCommand + npmFlags + 'install --quiet', message: 'Installing build modules...', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
{command: npmPath + npmFlags + 'install --quiet', message: 'Installing apm...', options: {cwd: apmInstallPath, ignoreStdout: true}},
apmPath + ' clean ' + apmFlags,
apmPath + ' install --quiet ' + apmFlags,
apmPath + ' dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '),
{
command: buildInstallCommand,
message: 'Installing build modules...',
options: buildInstallOptions
},
{
command: apmInstallCommand,
message: 'Installing apm...',
options: apmInstallOptions
},
apmPath + ' clean' + apmFlags,
moduleInstallCommand,
dedupeApmCommand + ' ' + packagesToDedupe.join(' '),
{
command: dedupeNpmCommand + ' request',
options: {
cwd: path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager')
}
},
];
process.chdir(path.dirname(__dirname));
+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'
+27
Ver Arquivo
@@ -17,6 +17,33 @@ describe "ContextMenuManager", ->
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
it 'does not add duplicate menu items', ->
contextMenu.add 'file-path',
'.selector':
'label': 'command'
contextMenu.add 'file-path',
'.selector':
'label': 'command'
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
expect(contextMenu.definitions['.selector'].length).toBe 1
it 'allows duplicate commands with different labels', ->
contextMenu.add 'file-path',
'.selector':
'label': 'command'
contextMenu.add 'file-path',
'.selector':
'another label': 'command'
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
expect(contextMenu.definitions['.selector'][1].label).toEqual 'another label'
expect(contextMenu.definitions['.selector'][1].command).toEqual 'command'
it "loads submenus", ->
contextMenu.add 'file-path',
'.selector':
+105 -5
Ver Arquivo
@@ -47,6 +47,15 @@ describe "DisplayBuffer", ->
buffer.insert([0,0], oneHundredLines)
expect(displayBuffer.getLineCount()).toBe 100 + originalLineCount
it "reassigns the scrollTop if it exceeds the max possible value after lines are removed", ->
displayBuffer.manageScrollPosition = true
displayBuffer.setHeight(50)
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setScrollTop(80)
buffer.delete([[8, 0], [10, 0]])
expect(displayBuffer.getScrollTop()).toBe 60
describe "soft wrapping", ->
beforeEach ->
displayBuffer.setSoftWrap(true)
@@ -206,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()
@@ -315,6 +337,14 @@ describe "DisplayBuffer", ->
expect(line0.fold).toBe outerFold
expect(line1.fold).toBeUndefined()
describe "when a fold ends where another fold begins", ->
it "continues to hide the lines inside the second fold", ->
fold2 = displayBuffer.createFold(4, 9)
fold1 = displayBuffer.createFold(0, 4)
expect(displayBuffer.lineForRow(0).text).toMatch /^0/
expect(displayBuffer.lineForRow(1).text).toMatch /^10/
describe "when there is another display buffer pointing to the same buffer", ->
it "does not create folds in the other display buffer", ->
otherDisplayBuffer = new DisplayBuffer({buffer, tabLength})
@@ -624,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])
@@ -986,22 +1029,44 @@ describe "DisplayBuffer", ->
displayBuffer.setLineHeightInPixels(20)
displayBuffer.setDefaultCharWidth(10)
displayBuffer.setScopedCharWidths(["source.js", "keyword.control.js"], r: 11, e: 11, t: 11, u: 11, n: 11)
for char in ['r', 'e', 't', 'u', 'r', 'n']
displayBuffer.setScopedCharWidth(["source.js", "keyword.control.js"], char, 11)
{start, end} = marker.getPixelRange()
expect(start.top).toBe 5 * 20
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 ->
@@ -1067,3 +1132,38 @@ describe "DisplayBuffer", ->
it "does not scroll vertically if the position is already in view", ->
displayBuffer.scrollToScreenPosition([4, 20], center: true)
expect(displayBuffer.getScrollTop()).toBe 0
describe "scroll width", ->
cursorWidth = 1
beforeEach ->
displayBuffer.setDefaultCharWidth(10)
it "recomputes the scroll width when the default character width changes", ->
expect(displayBuffer.getScrollWidth()).toBe 10 * 65 + cursorWidth
displayBuffer.setDefaultCharWidth(12)
expect(displayBuffer.getScrollWidth()).toBe 12 * 65 + cursorWidth
it "recomputes the scroll width when the max line length changes", ->
buffer.insert([6, 12], ' ')
expect(displayBuffer.getScrollWidth()).toBe 10 * 66 + cursorWidth
buffer.delete([[6, 10], [6, 12]], ' ')
expect(displayBuffer.getScrollWidth()).toBe 10 * 64 + cursorWidth
it "recomputes the scroll width when the scoped character widths change", ->
operatorWidth = 20
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth)
expect(displayBuffer.getScrollWidth()).toBe 10 * 64 + operatorWidth + cursorWidth
it "recomputes the scroll width when the scoped character widths change in a batch", ->
operatorWidth = 20
displayBuffer.on 'character-widths-changed', changedSpy = jasmine.createSpy()
displayBuffer.batchCharacterMeasurement ->
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth)
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '?', operatorWidth)
expect(displayBuffer.getScrollWidth()).toBe 10 * 63 + operatorWidth * 2 + cursorWidth
expect(changedSpy.callCount).toBe 1
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+27
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
@@ -1196,6 +1209,7 @@ describe "Editor", ->
editor.setHeight(50)
editor.setWidth(50)
editor.setHorizontalScrollbarHeight(0)
expect(editor.getScrollTop()).toBe 0
editor.setSelectedBufferRange([[5, 6], [6, 8]], autoscroll: true)
@@ -1226,6 +1240,8 @@ describe "Editor", ->
expect(editor.getSelectedBufferRanges()).toEqual [[[0, 0], [0, 0]], [[3, 4], [5, 6]]]
it "autoscrolls to the added selection if needed", ->
editor.manageScrollPosition = true
editor.setLineHeightInPixels(10)
editor.setDefaultCharWidth(10)
editor.setHeight(50)
@@ -1482,6 +1498,17 @@ describe "Editor", ->
expect(cursor1.getBufferPosition()).toEqual [1, 5]
expect(cursor2.getBufferPosition()).toEqual [2, 7]
it "autoscrolls to the last cursor", ->
editor.manageScrollPosition = true
editor.setCursorScreenPosition([1, 2])
editor.addCursorAtScreenPosition([10, 4])
editor.setLineHeightInPixels(10)
editor.setHeight(50)
expect(editor.getScrollTop()).toBe 0
editor.insertText('a')
expect(editor.getScrollTop()).toBe 80
describe "when there are multiple non-empty selections", ->
describe "when the selections are on the same line", ->
it "replaces each selection range with the inserted characters", ->
+14
Ver Arquivo
@@ -205,6 +205,20 @@ describe "Project", ->
fs.writeFileSync(filePath, sampleContent)
fs.writeFileSync(commentFilePath, sampleCommentContent)
describe "when a file doesn't exist", ->
it "calls back with an error", ->
errors = []
missingPath = path.resolve('/not-a-file.js')
expect(fs.existsSync(missingPath)).toBeFalsy()
waitsForPromise ->
atom.project.replace /items/gi, 'items', [missingPath], (result, error) ->
errors.push(error)
runs ->
expect(errors).toHaveLength 1
expect(errors[0].path).toBe missingPath
describe "when called with unopened files", ->
it "replaces properly", ->
results = []
+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
+68 -4
Ver Arquivo
@@ -335,12 +335,13 @@ describe "TokenizedBuffer", ->
expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}"
{ tokens } = screenLine0
expect(tokens.length).toBe 3
expect(tokens.length).toBe 4
expect(tokens[0].value).toBe "#"
expect(tokens[1].value).toBe " Econ 101"
expect(tokens[2].value).toBe tabAsSpaces
expect(tokens[2].scopes).toEqual tokens[1].scopes
expect(tokens[2].isAtomic).toBeTruthy()
expect(tokens[3].value).toBe ""
expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "#{tabAsSpaces} buy()#{tabAsSpaces}while supply > demand"
@@ -411,7 +412,7 @@ describe "TokenizedBuffer", ->
expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].bufferDelta).toBe 1
expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].screenDelta).toBe 1
describe "when the buffer contains surrogate pairs", ->
describe "when the buffer contains UTF-8 surrogate pairs", ->
beforeEach ->
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
@@ -429,7 +430,7 @@ describe "TokenizedBuffer", ->
tokenizedBuffer.destroy()
buffer.release()
it "renders each surrogate pair as its own atomic token", ->
it "renders each UTF-8 surrogate pair as its own atomic token", ->
screenLine0 = tokenizedBuffer.lineForScreenRow(0)
expect(screenLine0.text).toBe "'abc\uD835\uDF97def'"
{ tokens } = screenLine0
@@ -446,11 +447,12 @@ describe "TokenizedBuffer", ->
expect(screenLine1.text).toBe "//\uD835\uDF97xyz"
{ tokens } = screenLine1
expect(tokens.length).toBe 3
expect(tokens.length).toBe 4
expect(tokens[0].value).toBe '//'
expect(tokens[1].value).toBe '\uD835\uDF97'
expect(tokens[1].value).toBeTruthy()
expect(tokens[2].value).toBe 'xyz'
expect(tokens[3].value).toBe ''
describe "when the grammar is tokenized", ->
it "emits the `tokenized` event", ->
@@ -655,3 +657,65 @@ describe "TokenizedBuffer", ->
buffer.setText('\n\n\n')
expect(tokenizedBuffer.lineForScreenRow(1).indentLevel).toBe 0
describe "when the changed lines are surrounded by whitespace-only lines", ->
it "updates the indentLevel of empty lines that precede the change", ->
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 0
buffer.insert([12, 0], '\n')
buffer.insert([13, 0], ' ')
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 1
it "updates empty line indent guides when the empty line is the last line", ->
buffer.insert([12, 2], '\n')
# The newline and he tab need to be in two different operations to surface the bug
buffer.insert([12, 0], ' ')
expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 1
buffer.insert([12, 0], ' ')
expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(14)).not.toBeDefined()
it "updates the indentLevel of empty lines surrounding a change that inserts lines", ->
# create some new lines
buffer.insert([7, 0], '\n\n')
buffer.insert([5, 0], '\n\n')
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 3
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 3
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')
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: 10, delta: 2)
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 4
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 4
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", ->
# create some new lines
buffer.insert([7, 0], '\n\n')
buffer.insert([5, 0], '\n\n')
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
buffer.setTextInRange([[7, 0], [8, 65]], ' ok')
delete changeHandler.argsForCall[0][0].bufferChange
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: -1)
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(7).indentLevel).toBe 2 # new text
expect(tokenizedBuffer.lineForScreenRow(8).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 2
expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 2 # }
+14
Ver Arquivo
@@ -4,6 +4,20 @@ describe "TokenizedLine", ->
beforeEach ->
waitsForPromise -> atom.packages.activatePackage('language-coffee-script')
describe "::isOnlyWhitespace()", ->
beforeEach ->
waitsForPromise ->
atom.project.open('coffee.coffee').then (o) -> editor = o
it "returns true when the line is only whitespace", ->
expect(editor.lineForScreenRow(3).isOnlyWhitespace()).toBe true
expect(editor.lineForScreenRow(7).isOnlyWhitespace()).toBe true
expect(editor.lineForScreenRow(23).isOnlyWhitespace()).toBe true
it "returns false when the line is not only whitespace", ->
expect(editor.lineForScreenRow(0).isOnlyWhitespace()).toBe false
expect(editor.lineForScreenRow(2).isOnlyWhitespace()).toBe false
describe "::getScopeTree()", ->
it "returns a tree whose inner nodes are scopes and whose leaf nodes are tokens in those scopes", ->
[tokens, tokenIndex] = []
+25
Ver Arquivo
@@ -309,3 +309,28 @@ describe "Workspace", ->
expect(handler.callCount).toBe 1
editorCopy = editor.copy()
expect(handler.callCount).toBe 2
it "stores the active grammars used by all the open editors", ->
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
waitsForPromise ->
atom.workspace.open('sample.coffee')
runs ->
atom.workspace.getActiveEditor().setText('i = /test/;')
state = atom.workspace.serialize()
expect(state.packagesWithActiveGrammars).toEqual ['language-coffee-script', 'language-javascript']
jsPackage = atom.packages.getLoadedPackage('language-javascript')
coffeePackage = atom.packages.getLoadedPackage('language-coffee-script')
spyOn(jsPackage, 'loadGrammarsSync')
spyOn(coffeePackage, 'loadGrammarsSync')
workspace2 = Workspace.deserialize(state)
expect(jsPackage.loadGrammarsSync.callCount).toBe 1
expect(coffeePackage.loadGrammarsSync.callCount).toBe 1
+27 -7
Ver Arquivo
@@ -225,9 +225,15 @@ class Atom extends Model
else
@center()
# Returns true if the dimensions are useable, false if they should be ignored.
# Work around for https://github.com/atom/atom-shell/issues/473
isValidDimensions: ({x, y, width, height}={}) ->
width > 0 and height > 0 and x + width > 0 and y + height > 0
storeDefaultWindowDimensions: ->
dimensions = JSON.stringify(atom.getWindowDimensions())
localStorage.setItem("defaultWindowDimensions", dimensions)
dimensions = @getWindowDimensions()
if @isValidDimensions(dimensions)
localStorage.setItem("defaultWindowDimensions", JSON.stringify(dimensions))
getDefaultWindowDimensions: ->
{windowDimensions} = @getLoadSettings()
@@ -240,15 +246,21 @@ class Atom extends Model
console.warn "Error parsing default window dimensions", error
localStorage.removeItem("defaultWindowDimensions")
{width, height} = screen.getPrimaryDisplay().workAreaSize
dimensions ? {x: 0, y: 0, width: Math.min(1024, width), height: height}
if @isValidDimensions(dimensions)
dimensions
else
{width, height} = screen.getPrimaryDisplay().workAreaSize
{x: 0, y: 0, width: Math.min(1024, width), height}
restoreWindowDimensions: ->
windowDimensions = @state.windowDimensions ? @getDefaultWindowDimensions()
@setWindowDimensions(windowDimensions)
dimensions = @state.windowDimensions
unless @isValidDimensions(dimensions)
dimensions = @getDefaultWindowDimensions()
@setWindowDimensions(dimensions)
storeWindowDimensions: ->
@state.windowDimensions = @getWindowDimensions()
dimensions = @getWindowDimensions()
@state.windowDimensions = dimensions if @isValidDimensions(dimensions)
# Public: Get the load settings for the current window.
#
@@ -258,13 +270,20 @@ class Atom extends Model
deserializeProject: ->
Project = require './project'
startTime = Date.now()
@project ?= @deserializers.deserialize(@state.project) ? new Project(path: @getLoadSettings().initialPath)
@deserializeTimings.project = Date.now() - startTime
deserializeWorkspaceView: ->
Workspace = require './workspace'
WorkspaceView = require './workspace-view'
startTime = Date.now()
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
@workspaceView = new WorkspaceView(@workspace)
@deserializeTimings.workspace = Date.now() - startTime
@keymaps.defaultTarget = @workspaceView[0]
$(@workspaceViewParentSelector).append(@workspaceView)
@@ -273,6 +292,7 @@ class Atom extends Model
delete @state.packageStates
deserializeEditorWindow: ->
@deserializeTimings = {}
@deserializePackageStates()
@deserializeProject()
@deserializeWorkspaceView()
+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
+4 -1
Ver Arquivo
@@ -45,7 +45,10 @@ class BufferedProcess
# Related to joyent/node#2318
if process.platform is "win32"
# Quote all arguments and escapes inner quotes
cmdArgs = args.map (arg) -> "\"#{arg.replace(/"/g, '\\"')}\""
if args?
cmdArgs = args.map (arg) -> "\"#{arg.replace(/"/g, '\\"')}\""
else
cmdArgs = []
cmdArgs.unshift("\"#{command}\"")
cmdArgs = ['/s', '/c', "\"#{cmdArgs.join(' ')}\""]
cmdOptions = _.clone(options)
+2 -1
Ver Arquivo
@@ -60,7 +60,8 @@ class ContextMenuManager
# editor is in dev mode.
addBySelector: (selector, definition, {devMode}={}) ->
definitions = if devMode then @devModeDefinitions else @definitions
(definitions[selector] ?= []).push(definition)
unless _.findWhere(definitions[selector], definition)
(definitions[selector] ?= []).push(definition)
# Returns definitions which match the element and devMode.
definitionsForElement: (element, {devMode}={}) ->
+18 -5
Ver Arquivo
@@ -1,16 +1,29 @@
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{isEqualForProperties} = require 'underscore-plus'
module.exports =
CursorComponent = React.createClass
displayName: 'CursorComponent'
render: ->
{editor, screenRange, scrollTop, scrollLeft, defaultCharWidth} = @props
{top, left, height, width} = editor.pixelRectForScreenRange(screenRange)
top -= scrollTop
left -= scrollLeft
{pixelRect, defaultCharWidth} = @props
{height, width} = pixelRect
width = defaultCharWidth if width is 0
WebkitTransform = "translate3d(#{left}px, #{top}px, 0px)"
WebkitTransform = @getTransform()
div className: 'cursor', style: {height, width, WebkitTransform}
getTransform: ->
{pixelRect, scrollTop, scrollLeft, useHardwareAcceleration} = @props
{top, left} = pixelRect
top -= scrollTop
left -= scrollLeft
if useHardwareAcceleration
"translate3d(#{left}px, #{top}px, 0px)"
else
"translate(#{left}px, #{top}px)"
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(newProps, @props, 'pixelRect', 'scrollTop', 'scrollLeft', 'defaultCharWidth')
+5 -5
Ver Arquivo
@@ -28,9 +28,7 @@ class Cursor extends Model
# Supports old editor view
@needsAutoscroll ?= @isLastCursor() and !textChanged
# Supports react editor view
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition
@autoscroll() if @editor.manageScrollPosition and @isLastCursor() and textChanged
@goalColumn = null
@@ -55,8 +53,10 @@ class Cursor extends Model
changePosition: (options, fn) ->
@clearSelection()
@needsAutoscroll = options.autoscroll ? @isLastCursor()
unless fn()
@emit 'autoscrolled' if @needsAutoscroll
fn()
if @needsAutoscroll
@emit 'autoscrolled' # Support legacy editor
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition # Support react editor view
getPixelRect: ->
@editor.pixelRectForScreenRange(@getScreenRange())
+9 -8
Ver Arquivo
@@ -12,7 +12,7 @@ CursorsComponent = React.createClass
cursorBlinkIntervalHandle: null
render: ->
{editor, cursorScreenRanges, scrollTop, scrollLeft, defaultCharWidth} = @props
{cursorPixelRects, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration} = @props
{blinkOff} = @state
className = 'cursors'
@@ -20,8 +20,8 @@ CursorsComponent = React.createClass
div {className},
if @isMounted()
for key, screenRange of cursorScreenRanges
CursorComponent({key, editor, screenRange, scrollTop, scrollLeft, defaultCharWidth})
for key, pixelRect of cursorPixelRects
CursorComponent({key, pixelRect, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration})
getInitialState: ->
blinkOff: false
@@ -34,13 +34,14 @@ CursorsComponent = React.createClass
shouldComponentUpdate: (newProps, newState) ->
not newState.blinkOff is @state.blinkOff or
not isEqualForProperties(newProps, @props,
'cursorScreenRanges', 'scrollTop', 'scrollLeft', 'lineHeightInPixels',
'defaultCharWidth', 'scopedCharacterWidthsChangeCount'
)
not isEqualForProperties(newProps, @props, 'cursorPixelRects', 'scrollTop', 'scrollLeft', 'defaultCharWidth', 'useHardwareAcceleration')
componentWillUpdate: (newProps) ->
@pauseCursorBlinking() if @props.cursorScreenRanges and not isEqual(newProps.cursorScreenRanges, @props.cursorScreenRanges)
cursorsMoved = @props.cursorPixelRects? and
isEqualForProperties(newProps, @props, 'defaultCharWidth', 'scopedCharacterWidthsChangeCount') and
not isEqual(newProps.cursorPixelRects, @props.cursorPixelRects)
@pauseCursorBlinking() if cursorsMoved
startBlinkingCursors: ->
@toggleCursorBlinkHandle = setInterval(@toggleCursorBlink, @props.cursorBlinkPeriod / 2) if @isMounted()
+107
Ver Arquivo
@@ -0,0 +1,107 @@
_ = require 'underscore-plus'
{Subscriber, Emitter} = require 'emissary'
idCounter = 0
nextId = -> idCounter++
# Public: Represents a decoration that follows a {Marker}. A decoration is
# basically a visual representation of a marker. It allows you to add CSS
# classes to line numbers in the gutter, lines, and add selection-line regions
# around marked ranges of text.
#
# {Decoration} objects are not meant to be created directly, but created with
# {Editor::decorateMarker}. eg.
#
# ```coffee
# range = editor.getSelectedBufferRange() # any range you like
# marker = editor.markBufferRange(range)
# decoration = editor.decorateMarker(marker, {type: 'line', class: 'my-line-class'})
# ```
#
# Best practice for destorying the decoration is by destroying the {Marker}.
#
# ```
# marker.destroy()
# ```
#
# You should only use {Decoration::destroy} when you still need or do not own
# the marker.
#
# ### IDs
# Each {Decoration} has a unique ID available via `decoration.id`.
#
# ### Events
# A couple of events are emitted:
#
# * `destroyed`: When the {Decoration} is destroyed
# * `updated`: When the {Decoration} is updated via {Decoration::update}.
# Event object has properties `oldParams` and `newParams`
#
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
# Public: Destroy this marker.
#
# If you own the marker, you should use {Marker:destroy} which will destroy
# this decoration.
destroy: ->
return if @isDestroyed
@isDestroyed = true
@displayBuffer.removeDecoration(this)
@emit 'destoryed'
# Public: Update the marker with new params. Allows you to change the decoration's class.
#
# ```
# decoration.update({type: 'gutter', class: 'my-new-class'})
# ```
update: (newParams) ->
return if @isDestroyed
oldParams = @params
@params = newParams
@params.id = @id
@displayBuffer.decorationUpdated(this)
@emit 'updated', {oldParams, newParams}
# Public: Returns the marker associated with this {Decoration}
getMarker: -> @marker
# Public: Returns the {Decoration}'s params.
getParams: -> @params
# Public: Check if this decoration is of type `type`
#
# type - A {String} type like `'gutter'`
#
# Returns a {Boolean}
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
+96 -54
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
@@ -29,6 +30,7 @@ class DisplayBuffer extends Model
width: null
scrollTop: 0
scrollLeft: 0
scrollWidth: 0
verticalScrollMargin: 2
horizontalScrollMargin: 6
@@ -44,8 +46,10 @@ class DisplayBuffer extends Model
@charWidthsByScope = {}
@markers = {}
@foldsByMarkerId = {}
@decorationsById = {}
@decorationsByMarkerId = {}
@decorationMarkerSubscriptions = {}
@decorationMarkerChangedSubscriptions = {}
@decorationMarkerDestroyedSubscriptions = {}
@updateAllScreenLines()
@createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes())
@subscribe @tokenizedBuffer, 'grammar-changed', (grammar) => @emit 'grammar-changed', grammar
@@ -180,9 +184,12 @@ class DisplayBuffer extends Model
getScrollTop: -> @scrollTop
setScrollTop: (scrollTop) ->
if @manageScrollPosition
@scrollTop = Math.max(0, Math.min(@getScrollHeight() - @getClientHeight(), scrollTop))
@scrollTop = Math.round(Math.max(0, Math.min(@getMaxScrollTop(), scrollTop)))
else
@scrollTop = scrollTop
@scrollTop = Math.round(scrollTop)
getMaxScrollTop: ->
@getScrollHeight() - @getClientHeight()
getScrollBottom: -> @scrollTop + @height
setScrollBottom: (scrollBottom) ->
@@ -192,10 +199,13 @@ class DisplayBuffer extends Model
getScrollLeft: -> @scrollLeft
setScrollLeft: (scrollLeft) ->
if @manageScrollPosition
@scrollLeft = Math.max(0, Math.min(@getScrollWidth() - @getClientWidth(), scrollLeft))
@scrollLeft = Math.round(Math.max(0, Math.min(@getScrollWidth() - @getClientWidth(), scrollLeft)))
@scrollLeft
else
@scrollLeft = scrollLeft
@scrollLeft = Math.round(scrollLeft)
getMaxScrollLeft: ->
@getScrollWidth() - @getClientWidth()
getScrollRight: -> @scrollLeft + @width
setScrollRight: (scrollRight) ->
@@ -206,7 +216,11 @@ class DisplayBuffer extends Model
setLineHeightInPixels: (@lineHeightInPixels) -> @lineHeightInPixels
getDefaultCharWidth: -> @defaultCharWidth
setDefaultCharWidth: (@defaultCharWidth) -> @defaultCharWidth
setDefaultCharWidth: (defaultCharWidth) ->
if defaultCharWidth isnt @defaultCharWidth
@defaultCharWidth = defaultCharWidth
@computeScrollWidth()
defaultCharWidth
getCursorWidth: -> 1
@@ -221,13 +235,21 @@ class DisplayBuffer extends Model
scope.charWidths ?= {}
scope.charWidths
batchCharacterMeasurement: (fn) ->
oldChangeCount = @scopedCharacterWidthsChangeCount
@batchingCharacterMeasurement = true
fn()
@batchingCharacterMeasurement = false
@characterWidthsChanged() if oldChangeCount isnt @scopedCharacterWidthsChangeCount
setScopedCharWidth: (scopeNames, char, width) ->
@getScopedCharWidths(scopeNames)[char] = width
@emit 'character-widths-changed', @scopedCharacterWidthsChangeCount++
@scopedCharacterWidthsChangeCount++
@characterWidthsChanged() unless @batchingCharacterMeasurement
setScopedCharWidths: (scopeNames, charWidths) ->
_.extend(@getScopedCharWidths(scopeNames), charWidths)
@emit 'character-widths-changed', @scopedCharacterWidthsChangeCount++
characterWidthsChanged: ->
@computeScrollWidth()
@emit 'character-widths-changed', @scopedCharacterWidthsChangeCount
clearScopedCharWidths: ->
@charWidthsByScope = {}
@@ -238,7 +260,7 @@ class DisplayBuffer extends Model
@getLineCount() * @getLineHeightInPixels()
getScrollWidth: ->
(@getMaxLineLength() * @getDefaultCharWidth()) + @getCursorWidth()
@scrollWidth
getVisibleRowRange: ->
return [0, 0] unless @getLineHeightInPixels() > 0
@@ -576,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
@@ -729,53 +757,48 @@ 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)
@decorationMarkerSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', => @removeAllDecorationsForMarker(marker)
@decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', =>
@removeAllDecorationsForMarker(marker)
@decorationMarkerChangedSubscriptions[marker.id] ?= @subscribe marker, 'changed', (event) =>
decorations = @decorationsByMarkerId[marker.id]
# Why check existence? Markers may get destroyed or decorations removed
# in the change handler. Bookmarks does this.
if decorations?
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)
return unless @decorationMarkerSubscriptions[marker.id]?
decorations = @decorationsByMarkerId[marker.id]
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()
@@ -784,9 +807,15 @@ class DisplayBuffer extends Model
@removedAllMarkerDecorations(marker)
removedAllMarkerDecorations: (marker) ->
@decorationMarkerSubscriptions[marker.id].off()
@decorationMarkerChangedSubscriptions[marker.id].off()
@decorationMarkerDestroyedSubscriptions[marker.id].off()
delete @decorationsByMarkerId[marker.id]
delete @decorationMarkerSubscriptions[marker.id]
delete @decorationMarkerChangedSubscriptions[marker.id]
delete @decorationMarkerDestroyedSubscriptions[marker.id]
decorationUpdated: (decoration) ->
@emit 'decoration-updated', decoration
# Retrieves a {DisplayBufferMarker} based on its id.
#
@@ -941,7 +970,7 @@ class DisplayBuffer extends Model
for marker in @getMarkers()
marker.notifyObservers(textChanged: false)
destroy: ->
destroyed: ->
marker.unsubscribe() for marker in @getMarkers()
@tokenizedBuffer.destroy()
@unsubscribe()
@@ -954,24 +983,26 @@ class DisplayBuffer extends Model
handleTokenizedBufferChange: (tokenizedBufferChange) =>
{start, end, delta, bufferChange} = tokenizedBufferChange
@updateScreenLines(start, end + 1, delta, delayChangeEvent: bufferChange?)
@setScrollTop(Math.min(@getScrollTop(), @getMaxScrollTop())) if @manageScrollPosition and delta < 0
updateScreenLines: (startBufferRow, endBufferRow, bufferDelta=0, options={}) ->
startBufferRow = @rowMap.bufferRowRangeForBufferRow(startBufferRow)[0]
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
@@ -1026,22 +1057,33 @@ class DisplayBuffer extends Model
{screenLines, regions}
findMaxLineLength: (startScreenRow, endScreenRow, newScreenLines) ->
findMaxLineLength: (startScreenRow, endScreenRow, newScreenLines, screenDelta) ->
oldMaxLineLength = @maxLineLength
if startScreenRow <= @longestScreenRow < endScreenRow
@longestScreenRow = 0
@maxLineLength = 0
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
@scrollWidth += 1 unless @getSoftWrap()
@setScrollLeft(Math.min(@getScrollLeft(), @getMaxScrollLeft()))
handleBufferMarkersUpdated: =>
if event = @pendingChangeEvent
@pendingChangeEvent = null
@@ -1052,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) ->
+130 -53
Ver Arquivo
@@ -12,7 +12,7 @@ ScrollbarComponent = require './scrollbar-component'
ScrollbarCornerComponent = require './scrollbar-corner-component'
SubscriberMixin = require './subscriber-mixin'
DummyHighlightDecoration = {id: 'dummy', screenRange: new Range(new Point(0, 0), new Point(0, 0)), decorations: [{class: 'dummy'}]}
DummyHighlightDecoration = {id: 'dummy', startPixelPosition: {top: 0, left: 0}, endPixelPosition: {top: 0, left: 0}, decorations: [{class: 'dummy'}]}
module.exports =
EditorComponent = React.createClass
@@ -26,6 +26,8 @@ EditorComponent = React.createClass
pendingScrollLeft: null
selectOnMouseMove: false
updateRequested: false
updatesPaused: false
updateRequestedWhilePaused: false
cursorsMoved: false
selectionChanged: false
selectionAdded: false
@@ -40,13 +42,14 @@ EditorComponent = React.createClass
scrollSensitivity: 0.4
scrollViewMeasurementRequested: false
measureLineHeightAndDefaultCharWidthWhenShown: false
remeasureCharacterWidthsWhenShown: false
remeasureCharacterWidthsIfVisibleAfterNextUpdate: false
inputEnabled: true
scrollViewMeasurementInterval: 100
scopedCharacterWidthsChangeCount: null
scrollViewMeasurementPaused: false
render: ->
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, visible} = @state
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, showLineNumbers, visible} = @state
{editor, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
maxLineNumberDigits = editor.getLineCount().toString().length
invisibles = if showInvisibles then @state.invisibles else {}
@@ -55,7 +58,7 @@ EditorComponent = React.createClass
if @isMounted()
renderedRowRange = @getRenderedRowRange()
[renderedStartRow, renderedEndRow] = renderedRowRange
cursorScreenRanges = @getCursorScreenRanges(renderedRowRange)
cursorPixelRects = @getCursorPixelRects(renderedRowRange)
decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
highlightDecorations = @getHighlightDecorations(decorations)
@@ -68,12 +71,13 @@ EditorComponent = React.createClass
lineHeightInPixels = editor.getLineHeightInPixels()
defaultCharWidth = editor.getDefaultCharWidth()
scrollViewHeight = editor.getHeight()
lineWidth = Math.max(scrollWidth, editor.getWidth())
horizontalScrollbarHeight = editor.getHorizontalScrollbarHeight()
verticalScrollbarWidth = editor.getVerticalScrollbarWidth()
verticallyScrollable = editor.verticallyScrollable()
horizontallyScrollable = editor.horizontallyScrollable()
hiddenInputStyle = @getHiddenInputPosition()
hiddenInputStyle.WebkitTransform = 'translateZ(0)'
hiddenInputStyle.WebkitTransform = 'translateZ(0)' if @useHardwareAcceleration
if @mouseWheelScreenRow? and not (renderedStartRow <= @mouseWheelScreenRow < renderedEndRow)
mouseWheelScreenRow = @mouseWheelScreenRow
@@ -82,11 +86,12 @@ EditorComponent = React.createClass
className += ' has-selection' if hasSelection
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1,
GutterComponent {
ref: 'gutter', onMouseDown: @onGutterMouseDown, onWidthChanged: @onGutterWidthChanged,
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow
}
if showLineNumbers
GutterComponent {
ref: 'gutter', onMouseDown: @onGutterMouseDown, onWidthChanged: @onGutterWidthChanged,
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow, @useHardwareAcceleration
}
div ref: 'scrollView', className: 'scroll-view', onMouseDown: @onMouseDown,
InputComponent
@@ -97,15 +102,15 @@ EditorComponent = React.createClass
onBlur: @onInputBlurred
CursorsComponent {
editor, scrollTop, scrollLeft, cursorScreenRanges, cursorBlinkPeriod, cursorBlinkResumeDelay,
lineHeightInPixels, defaultCharWidth, @scopedCharacterWidthsChangeCount
scrollTop, scrollLeft, cursorPixelRects, cursorBlinkPeriod, cursorBlinkResumeDelay,
lineHeightInPixels, defaultCharWidth, @scopedCharacterWidthsChangeCount, @useHardwareAcceleration
}
LinesComponent {
ref: 'lines',
editor, lineHeightInPixels, defaultCharWidth, lineDecorations, highlightDecorations,
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration
}
ScrollbarComponent
@@ -161,7 +166,7 @@ EditorComponent = React.createClass
componentDidMount: ->
{editor} = @props
@scrollViewMeasurementIntervalId = setInterval(@requestScrollViewMeasurement, @scrollViewMeasurementInterval)
@scrollViewMeasurementIntervalId = setInterval(@measureScrollView, @scrollViewMeasurementInterval)
@observeEditor()
@listenForDOMEvents()
@@ -177,12 +182,11 @@ EditorComponent = React.createClass
@measureScrollbars()
componentWillUnmount: ->
@props.parentView.trigger 'editor:will-be-removed', [@props.parentView]
@unsubscribe()
clearInterval(@scrollViewMeasurementIntervalId)
@scrollViewMeasurementIntervalId = null
componentWillUpdate: ->
componentDidUpdate: (prevProps, prevState) ->
cursorsMoved = @cursorsMoved
selectionChanged = @selectionChanged
@@ -202,14 +206,28 @@ EditorComponent = React.createClass
@remeasureCharacterWidthsIfNeeded(prevState)
requestUpdate: ->
if @updatesPaused
@updateRequestedWhilePaused = true
return
if @performSyncUpdates ? EditorComponent.performSyncUpdates
@forceUpdate()
else unless @updateRequested
@updateRequested = true
process.nextTick =>
setImmediate =>
@updateRequested = false
@forceUpdate() if @isMounted()
requestAnimationFrame: (fn) ->
@updatesPaused = true
@pauseScrollViewMeasurement()
requestAnimationFrame =>
fn()
@updatesPaused = false
if @updateRequestedWhilePaused and @isMounted()
@updateRequestedWhilePaused = false
@forceUpdate()
getRenderedRowRange: ->
{editor, lineOverdrawMargin} = @props
[visibleStartRow, visibleEndRow] = editor.getVisibleRowRange()
@@ -242,22 +260,43 @@ EditorComponent = React.createClass
cursorScreenRanges[cursor.id] = screenRange
cursorScreenRanges
getCursorPixelRects: (renderedRowRange) ->
{editor} = @props
[renderedStartRow, renderedEndRow] = renderedRowRange
cursorPixelRects = {}
for selection in editor.getSelections() when selection.isEmpty()
{cursor} = selection
screenRange = cursor.getScreenRange()
if renderedStartRow <= screenRange.start.row < renderedEndRow
cursorPixelRects[cursor.id] = editor.pixelRectForScreenRange(screenRange)
cursorPixelRects
getLineDecorations: (decorationsByMarkerId) ->
{editor} = @props
decorationsByScreenRow = {}
for markerId, decorations of decorationsByMarkerId
marker = editor.getMarker(markerId)
screenRange = null
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]
decorationsByScreenRow[screenRow] ?= []
decorationsByScreenRow[screenRow].push decoration
continue if decorationParams.onlyHead and screenRow isnt headScreenRow
if screenRange.isEmpty()
continue if decorationParams.onlyNonEmpty
else
continue if decorationParams.onlyEmpty
decorationsByScreenRow[screenRow] ?= {}
decorationsByScreenRow[screenRow][decoration.id] = decorationParams
decorationsByScreenRow
@@ -266,11 +305,17 @@ EditorComponent = React.createClass
filteredDecorations = {}
for markerId, decorations of decorationsByMarkerId
marker = editor.getMarker(markerId)
if marker.isValid() and not marker.getScreenRange().isEmpty()
screenRange = marker.getScreenRange()
if marker.isValid() and not screenRange.isEmpty()
for decoration in decorations
if editor.decorationMatchesType(decoration, 'highlight')
filteredDecorations[markerId] ?= {id: markerId, screenRange: marker.getScreenRange(), decorations: []}
filteredDecorations[markerId].decorations.push decoration
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 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
@@ -287,6 +332,8 @@ EditorComponent = React.createClass
@subscribe editor, 'selection-added', @onSelectionAdded
@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
@@ -325,12 +372,13 @@ EditorComponent = React.createClass
# 5. textInput fired; event.data == the completion string
selectedText = null
node.addEventListener 'compositionstart', =>
node.addEventListener 'compositionstart', ->
selectedText = editor.getSelectedText()
node.addEventListener 'compositionupdate', (event) =>
node.addEventListener 'compositionupdate', (event) ->
editor.insertText(event.data, select: true, undo: 'skip')
node.addEventListener 'compositionend', =>
node.addEventListener 'compositionend', (event) ->
editor.insertText(selectedText, select: true, undo: 'skip')
event.target.value = ''
listenForCommands: ->
{parentView, editor, mini} = @props
@@ -414,7 +462,7 @@ EditorComponent = React.createClass
'editor:unfold-all': => editor.unfoldAll()
'editor:fold-current-row': => editor.foldCurrentRow()
'editor:unfold-current-row': => editor.unfoldCurrentRow()
'editor:fold-selection': => neditor.foldSelectedLines()
'editor:fold-selection': => editor.foldSelectedLines()
'editor:fold-at-indent-level-1': => editor.foldAllAtIndentLevel(0)
'editor:fold-at-indent-level-2': => editor.foldAllAtIndentLevel(1)
'editor:fold-at-indent-level-3': => editor.foldAllAtIndentLevel(2)
@@ -450,7 +498,9 @@ EditorComponent = React.createClass
@subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide
@subscribe atom.config.observe 'editor.invisibles', @setInvisibles
@subscribe atom.config.observe 'editor.showInvisibles', @setShowInvisibles
@subscribe atom.config.observe 'editor.showLineNumbers', @setShowLineNumbers
@subscribe atom.config.observe 'editor.scrollSensitivity', @setScrollSensitivity
@subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration
onFocus: ->
@refs.input.focus()
@@ -484,24 +534,25 @@ EditorComponent = React.createClass
onVerticalScroll: (scrollTop) ->
{editor} = @props
return if scrollTop is editor.getScrollTop()
return if @updateRequested or scrollTop is editor.getScrollTop()
animationFramePending = @pendingScrollTop?
@pendingScrollTop = scrollTop
unless animationFramePending
requestAnimationFrame =>
@props.editor.setScrollTop(@pendingScrollTop)
@requestAnimationFrame =>
pendingScrollTop = @pendingScrollTop
@pendingScrollTop = null
@props.editor.setScrollTop(pendingScrollTop)
onHorizontalScroll: (scrollLeft) ->
{editor} = @props
return if scrollLeft is editor.getScrollLeft()
return if @updateRequested or scrollLeft is editor.getScrollLeft()
animationFramePending = @pendingScrollLeft?
@pendingScrollLeft = scrollLeft
unless animationFramePending
requestAnimationFrame =>
@requestAnimationFrame =>
@props.editor.setScrollLeft(@pendingScrollLeft)
@pendingScrollLeft = null
@@ -522,7 +573,7 @@ EditorComponent = React.createClass
@clearMouseWheelScreenRowAfterDelay()
unless animationFramePending
requestAnimationFrame =>
@requestAnimationFrame =>
{editor} = @props
editor.setScrollTop(editor.getScrollTop() + @pendingVerticalScrollDelta)
editor.setScrollLeft(editor.getScrollLeft() + @pendingHorizontalScrollDelta)
@@ -540,7 +591,7 @@ EditorComponent = React.createClass
return unless event.button is 0 # only handle the left mouse button
{editor} = @props
{detail, shiftKey, metaKey} = event
{detail, shiftKey, metaKey, ctrlKey} = event
screenPosition = @screenPositionForMouseEvent(event)
if event.target?.classList.contains('fold-marker')
@@ -548,15 +599,18 @@ EditorComponent = React.createClass
editor.unfoldBufferRow(bufferRow)
return
if shiftKey
editor.selectToScreenPosition(screenPosition)
else if metaKey
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)
@@ -601,6 +655,8 @@ EditorComponent = React.createClass
onStylesheetsChanged: (stylesheet) ->
@refreshScrollbars() if @containsScrollbarSelector(stylesheet)
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = true
@requestUpdate() if @state.visible
onScreenLinesChanged: (change) ->
{editor} = @props
@@ -623,7 +679,7 @@ EditorComponent = React.createClass
onScrollTopChanged: ->
@scrollingVertically = true
@requestUpdate()
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 100)
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 200)
@onStoppedScrollingAfterDelay()
onStoppedScrolling: ->
@@ -650,7 +706,7 @@ EditorComponent = React.createClass
dragging = false
lastMousePosition = {}
animationLoop = =>
requestAnimationFrame =>
@requestAnimationFrame =>
if dragging
screenPosition = @screenPositionForMouseEvent(lastMousePosition)
dragHandler(screenPosition)
@@ -677,8 +733,18 @@ EditorComponent = React.createClass
window.addEventListener('mousemove', onMouseMove)
window.addEventListener('mouseup', onMouseUp)
pauseScrollViewMeasurement: ->
@scrollViewMeasurementPaused = true
@resumeScrollViewMeasurementAfterDelay ?= debounce(@resumeScrollViewMeasurement, 100)
@resumeScrollViewMeasurementAfterDelay()
resumeScrollViewMeasurement: ->
@scrollViewMeasurementPaused = false
resumeScrollViewMeasurementAfterDelay: null # created lazily
requestScrollViewMeasurement: ->
return if @measurementPending
return if @scrollViewMeasurementRequested
@scrollViewMeasurementRequested = true
requestAnimationFrame =>
@@ -690,6 +756,7 @@ EditorComponent = React.createClass
# and use the scrollHeight / scrollWidth as its height and width in
# calculations.
measureScrollView: ->
return if @scrollViewMeasurementPaused
return unless @isMounted()
{editor} = @props
@@ -704,6 +771,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) ->
@@ -724,12 +793,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) ->
@@ -835,10 +904,18 @@ EditorComponent = React.createClass
setShowInvisibles: (showInvisibles) ->
@setState({showInvisibles})
setShowLineNumbers: (showLineNumbers) ->
@setState({showLineNumbers})
setScrollSensitivity: (scrollSensitivity) ->
if scrollSensitivity = parseInt(scrollSensitivity)
@scrollSensitivity = Math.abs(scrollSensitivity) / 100
setUseHardwareAcceleration: (useHardwareAcceleration=true) ->
unless @useHardwareAcceleration is useHardwareAcceleration
@useHardwareAcceleration = useHardwareAcceleration
@requestUpdate()
screenPositionForMouseEvent: (event) ->
pixelPosition = @pixelPositionForMouseEvent(event)
@props.editor.screenPositionForPixelPosition(pixelPosition)
@@ -847,9 +924,9 @@ EditorComponent = React.createClass
{editor} = @props
{clientX, clientY} = event
scrollViewClientRect = @refs.scrollView.getDOMNode().getBoundingClientRect()
top = clientY - scrollViewClientRect.top + editor.getScrollTop()
left = clientX - scrollViewClientRect.left + editor.getScrollLeft()
linesClientRect = @refs.lines.getDOMNode().getBoundingClientRect()
top = clientY - linesClientRect.top
left = clientX - linesClientRect.left
{top, left}
getModel: ->
+1
Ver Arquivo
@@ -57,6 +57,7 @@ class EditorView extends View
softTabs: true
softWrapAtPreferredLineLength: false
scrollSensitivity: 40
useHardwareAcceleration: true
@nextEditorId: 1
+56 -49
Ver Arquivo
@@ -131,6 +131,10 @@ TextMateScopeSelector = require('first-mate').ScopeSelector
# - {::markScreenRange}
# - {::getMarker}
# - {::findMarkers}
#
# ### Decorations
# - {::decorateMarker}
# - {::decorationsForScreenRowRange}
module.exports =
class Editor extends Model
Serializable.includeInto(this)
@@ -146,6 +150,7 @@ class Editor extends Model
selections: null
suppressSelectionMerging: false
updateBatchDepth: 0
selectionFlashDuration: 500
@delegatesMethods 'suggestedIndentForBufferRow', 'autoIndentBufferRow', 'autoIndentBufferRows',
'autoDecreaseIndentForBufferRow', 'toggleLineCommentForBufferRow', 'toggleLineCommentsForBufferRows',
@@ -217,6 +222,8 @@ class Editor extends Model
@subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args...
@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: ->
@@ -1077,60 +1084,57 @@ class Editor extends Model
# startScreenRow - the {Number} beginning screen row
# endScreenRow - the {Number} end screen row (inclusive)
#
# Returns an {Object} of decorations in the form `{1: [{type: 'gutter', class: 'someclass'}], 2: ...}`
# where the keys are markerIds, and the values are an array of decoration objects attached to the marker.
# Returns an {Object} of decorations in the form
# `{1: [{id: 10, type: 'gutter', class: 'someclass'}], 2: ...}`
# where the keys are {Marker} IDs, and the values are an array of decoration
# params objects attached to the marker.
# Returns an empty object when no decorations are found
decorationsForScreenRowRange: (startScreenRow, endScreenRow) ->
@displayBuffer.decorationsForScreenRowRange(startScreenRow, endScreenRow)
# Public: Adds a decoration that tracks a {Marker}. When the marker moves,
# is invalidated, or is destroyed, the decoration will be updated to reflect the marker's state.
# is invalidated, or is destroyed, the decoration will be updated to reflect
# the marker's state.
#
# There are a few supported decoration types:
# * `gutter`: `{type: 'gutter', class: 'linter-error'}` Will add a class to the gutter rows associated with the marker.
# * `line`: `{type: 'line', class: 'linter-error'}` Will add a class to the editor lines associated with the marker.
# * `highlight`: `{type: 'highlight', class: 'linter-error'}` Will highlight the region of the buffer associated with the marker. Your specified class will be added to the highlight.
# There are three types of supported decorations:
# * `line`: Adds your CSS `class` to the line nodes within the range
# marked by the marker
# * `gutter`: Adds your CSS `class` to the line number nodes within the
# range marked by the marker
# * `highlight`: Adds a new highlight div to the editor surrounding the
# range marked by the marker. When the user selects text, the selection is
# visualized with a highlight decoration internally. The structure of this
# highlight will be:
# ```html
# <div class="highlight <your-class>">
# <!-- Will be one region for each row in the range. Spans 2 lines? There will be 2 regions. -->
# <div class="region"></div>
# </div>
# ```
#
# marker - the {Marker} you want this decoration to follow
# decoration - the {Object} decoration eg. `{type: 'gutter', class: 'linter-error'}`
# marker - A {Marker} you want this decoration to follow.
# decorationParams - An {Object} representing the decoration eg. `{type: 'gutter', class: 'linter-error'}`
# :type - There are a few supported decoration types:
# * `gutter`: Applies the decoration to the line numbers spanned by the marker.
# * `line`: Applies the decoration to the lines spanned by the marker.
# * `highlight`: Applies the decoration to a "highlight" behind the marked range.
# :class - This CSS class will be applied to the decorated line number,
# line, or highlight.
# :onlyHead - If `true`, the decoration will only be applied to the head
# of the marker. Only applicable to the `line` and `gutter` types.
# :onlyEmpty - If `true`, the decoration will only be applied if the
# associated marker is empty. Only applicable to the `line` and
# `gutter` types.
# :onlyNonEmpty - If `true`, the decoration will only be applied if the
# associated marker is non-empty. Only applicable to the `line` and
# gutter types.
#
# Returns nothing
addDecorationForMarker: (marker, decoration) ->
@displayBuffer.addDecorationForMarker(marker, decoration)
# Returns a {Decoration} object
decorateMarker: (marker, decorationParams) ->
@displayBuffer.decorateMarker(marker, decorationParams)
# 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) ->
@@ -1237,7 +1241,9 @@ class Editor extends Model
addCursor: (marker) ->
cursor = new Cursor(editor: this, marker: marker)
@cursors.push(cursor)
@addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'cursor-line')
@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
@@ -1264,7 +1270,6 @@ class Editor extends Model
if selection.intersectsBufferRange(selectionBufferRange)
return selection
else
@addDecorationForMarker(marker, type: 'highlight', class: 'selection')
@emit 'selection-added', selection
selection
@@ -1279,7 +1284,7 @@ class Editor extends Model
addSelectionForBufferRange: (bufferRange, options={}) ->
@markBufferRange(bufferRange, _.defaults(@getSelectionMarkerAttributes(), options))
selection = @getLastSelection()
selection.autoscroll()
selection.autoscroll() if @manageScrollPosition
selection
# Public: Set the selected range in buffer coordinates. If there are multiple
@@ -1487,7 +1492,7 @@ class Editor extends Model
# text - A {String}
#
# Returns the {Range} of the newly-inserted text.
setTextInBufferRange: (range, text) -> @getBuffer().setTextInRange(range, text)
setTextInBufferRange: (range, text, normalizeLineEndings) -> @getBuffer().setTextInRange(range, text, normalizeLineEndings)
# Public: Get the {Range} of the paragraph surrounding the most recently added
# cursor.
@@ -1974,6 +1979,8 @@ class Editor extends Model
getLineHeightInPixels: -> @displayBuffer.getLineHeightInPixels()
setLineHeightInPixels: (lineHeightInPixels) -> @displayBuffer.setLineHeightInPixels(lineHeightInPixels)
batchCharacterMeasurement: (fn) -> @displayBuffer.batchCharacterMeasurement(fn)
getScopedCharWidth: (scopeNames, char) -> @displayBuffer.getScopedCharWidth(scopeNames, char)
setScopedCharWidth: (scopeNames, char, width) -> @displayBuffer.setScopedCharWidth(scopeNames, char, width)
+5
Ver Arquivo
@@ -35,6 +35,11 @@ class Fold
# Returns a {Range}.
getBufferRange: ({includeNewline}={}) ->
range = @marker.getRange()
if range.end.row > range.start.row and nextFold = @displayBuffer.largestFoldStartingAtBufferRow(range.end.row)
nextRange = nextFold.getBufferRange()
range = new Range(range.start, nextRange.end)
if includeNewline
range = range.copy()
range.end.row++
+23 -9
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')
@@ -15,14 +16,22 @@ GutterComponent = React.createClass
measuredWidth: null
render: ->
{scrollHeight, scrollViewHeight, scrollTop, onMouseDown} = @props
{scrollHeight, scrollViewHeight, onMouseDown} = @props
div className: 'gutter', onClick: @onClick, onMouseDown: onMouseDown,
# The line-numbers div must have the 'editor-colors' class so it has an
# opaque background to avoid sub-pixel anti-aliasing problems on the GPU
div className: 'gutter line-numbers editor-colors', ref: 'lineNumbers', style:
height: Math.max(scrollHeight, scrollViewHeight)
WebkitTransform: "translate3d(0px, #{-scrollTop}px, 0px)"
WebkitTransform: @getTransform()
getTransform: ->
{scrollTop, useHardwareAcceleration} = @props
if useHardwareAcceleration
"translate3d(0px, #{-scrollTop}px, 0px)"
else
"translate(0px, #{-scrollTop}px)"
componentWillMount: ->
@lineNumberNodesById = {}
@@ -32,6 +41,7 @@ GutterComponent = React.createClass
componentDidMount: ->
@appendDummyLineNumber()
@updateLineNumbers() if @props.renderedRowRange?
# 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
@@ -39,7 +49,7 @@ GutterComponent = React.createClass
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'mouseWheelScreenRow', 'lineDecorations',
'scrollViewHeight'
'scrollViewHeight', 'useHardwareAcceleration'
)
{renderedRowRange, pendingChanges, lineDecorations} = newProps
@@ -145,8 +155,8 @@ GutterComponent = React.createClass
classes = ''
if lineDecorations? and decorations = lineDecorations[screenRow]
for decoration in decorations
if editor.decorationMatchesType(decoration, 'gutter')
for id, decoration of decorations
if Decoration.isType(decoration, 'gutter')
classes += decoration.class + ' '
classes += "foldable " if bufferRow >= 0 and editor.isFoldableAtBufferRow(bufferRow)
@@ -177,12 +187,13 @@ GutterComponent = React.createClass
previousDecorations = @renderedDecorationsByLineNumberId[lineNumberId]
if previousDecorations?
for decoration in previousDecorations
node.classList.remove(decoration.class) if editor.decorationMatchesType(decoration, 'gutter') and not _.deepContains(decorations, decoration)
for id, decoration of previousDecorations
if Decoration.isType(decoration, 'gutter') and not @hasDecoration(decorations, decoration)
node.classList.remove(decoration.class)
if decorations?
for decoration in decorations
if editor.decorationMatchesType(decoration, 'gutter') and not _.deepContains(previousDecorations, decoration)
for id, decoration of decorations
if Decoration.isType(decoration, 'gutter') and not @hasDecoration(previousDecorations, decoration)
node.classList.add(decoration.class)
unless @screenRowsByLineNumberId[lineNumberId] is screenRow
@@ -192,6 +203,9 @@ GutterComponent = React.createClass
@screenRowsByLineNumberId[lineNumberId] = screenRow
@lineNumberIdsByScreenRow[screenRow] = lineNumberId
hasDecoration: (decorations, decoration) ->
decorations? and decorations[decoration.id] is decoration
hasLineNumberNode: (lineNumberId) ->
@lineNumberNodesById.hasOwnProperty(lineNumberId)
+39 -16
Ver Arquivo
@@ -1,27 +1,47 @@
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{isEqualForProperties} = require 'underscore-plus'
module.exports =
HighlightComponent = React.createClass
displayName: 'HighlightComponent'
render: ->
{editor, screenRange, decoration} = @props
{start, end} = screenRange
rowCount = end.row - start.row + 1
startPixelPosition = editor.pixelPositionForScreenPosition(start)
endPixelPosition = editor.pixelPositionForScreenPosition(end)
{startPixelPosition, endPixelPosition, decoration} = @props
className = 'highlight'
className += " #{decoration.class}" if decoration.class?
div {className},
if rowCount is 1
@renderSingleLineRegions(startPixelPosition, endPixelPosition)
else
@renderMultiLineRegions(startPixelPosition, endPixelPosition, rowCount)
renderSingleLineRegions: (startPixelPosition, endPixelPosition) ->
{lineHeightInPixels} = @props
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
[
div className: 'region', key: 0, style:
@@ -31,8 +51,8 @@ HighlightComponent = React.createClass
width: endPixelPosition.left - startPixelPosition.left
]
renderMultiLineRegions: (startPixelPosition, endPixelPosition, rowCount) ->
{lineHeightInPixels} = @props
renderMultiLineRegions: ->
{startPixelPosition, endPixelPosition, lineHeightInPixels} = @props
regions = []
index = 0
@@ -46,11 +66,11 @@ HighlightComponent = React.createClass
)
# Middle rows, extending from left side to right side of screen
if rowCount > 2
if endPixelPosition.top - startPixelPosition.top > lineHeightInPixels
regions.push(
div className: 'region', key: index++, style:
top: startPixelPosition.top + lineHeightInPixels
height: (rowCount - 2) * lineHeightInPixels
height: endPixelPosition.top - startPixelPosition.top - lineHeightInPixels
left: 0
right: 0
)
@@ -65,3 +85,6 @@ HighlightComponent = React.createClass
)
regions
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(newProps, @props, 'startPixelPosition', 'endPixelPosition', 'lineHeightInPixels')
+4 -3
Ver Arquivo
@@ -8,15 +8,16 @@ HighlightsComponent = React.createClass
displayName: 'HighlightsComponent'
render: ->
div className: 'highlights', @renderHighlights()
div className: 'highlights',
@renderHighlights() if @isMounted()
renderHighlights: ->
{editor, highlightDecorations, lineHeightInPixels} = @props
highlightComponents = []
for markerId, {screenRange, decorations} of highlightDecorations
for markerId, {startPixelPosition, endPixelPosition, decorations} of highlightDecorations
for decoration in decorations
highlightComponents.push(HighlightComponent({key: "#{markerId}-#{decoration.class}", screenRange, decoration, editor, lineHeightInPixels}))
highlightComponents.push(HighlightComponent({editor, key: "#{markerId}-#{decoration.class}", startPixelPosition, endPixelPosition, decoration, lineHeightInPixels}))
highlightComponents
+65 -28
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]
@@ -16,17 +17,25 @@ LinesComponent = React.createClass
render: ->
if @isMounted()
{editor, highlightDecorations, scrollTop, scrollLeft, scrollHeight, scrollWidth} = @props
{editor, highlightDecorations, scrollHeight, scrollWidth} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
style =
height: Math.max(scrollHeight, scrollViewHeight)
width: scrollWidth
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
WebkitTransform: @getTransform()
# The lines div must have the 'editor-colors' class so it has an opaque
# background to avoid sub-pixel anti-aliasing problems on the GPU
div {className: 'lines editor-colors', style},
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount}) if @isMounted()
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount})
getTransform: ->
{scrollTop, scrollLeft, useHardwareAcceleration} = @props
if useHardwareAcceleration
"translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
else
"translate(#{-scrollLeft}px, #{-scrollTop}px)"
componentWillMount: ->
@measuredLines = new WeakSet
@@ -39,13 +48,16 @@ LinesComponent = React.createClass
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount'
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration'
)
{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
@@ -54,20 +66,20 @@ LinesComponent = React.createClass
@clearScreenRowCaches() unless prevProps.lineHeightInPixels is @props.lineHeightInPixels
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide', 'invisibles')
@updateLines()
@updateLines(@props.lineWidth isnt prevProps.lineWidth)
@measureCharactersInNewLines() if visible and not scrollingVertically
clearScreenRowCaches: ->
@screenRowsByLineId = {}
@lineIdsByScreenRow = {}
updateLines: ->
updateLines: (updateWidth) ->
{editor, renderedRowRange, showIndentGuide, selectionChanged, lineDecorations} = @props
[startRow, endRow] = renderedRowRange
visibleLines = editor.linesForScreenRows(startRow, endRow - 1)
@removeLineNodes(visibleLines)
@appendOrUpdateVisibleLineNodes(visibleLines, startRow)
@appendOrUpdateVisibleLineNodes(visibleLines, startRow, updateWidth)
removeLineNodes: (visibleLines=[]) ->
{mouseWheelScreenRow} = @props
@@ -83,7 +95,7 @@ LinesComponent = React.createClass
delete @renderedDecorationsByLineId[lineId]
node.removeChild(lineNode)
appendOrUpdateVisibleLineNodes: (visibleLines, startRow) ->
appendOrUpdateVisibleLineNodes: (visibleLines, startRow, updateWidth) ->
{lineDecorations} = @props
newLines = null
@@ -93,7 +105,7 @@ LinesComponent = React.createClass
screenRow = startRow + index
if @hasLineNode(line.id)
@updateLineNode(line, screenRow)
@updateLineNode(line, screenRow, updateWidth)
else
newLines ?= []
newLinesHTML ?= ""
@@ -118,18 +130,18 @@ LinesComponent = React.createClass
@lineNodesByLineId.hasOwnProperty(lineId)
buildLineHTML: (line, screenRow) ->
{editor, mini, showIndentGuide, lineHeightInPixels, lineDecorations} = @props
{editor, mini, showIndentGuide, lineHeightInPixels, lineDecorations, lineWidth} = @props
{tokens, text, lineEnding, fold, isSoftWrapped, indentLevel} = line
classes = ''
if decorations = lineDecorations[screenRow]
for decoration in decorations
if editor.decorationMatchesType(decoration, 'line')
for id, decoration of decorations
if Decoration.isType(decoration, 'line')
classes += decoration.class + ' '
classes += 'line'
top = screenRow * lineHeightInPixels
lineHTML = "<div class=\"#{classes}\" style=\"position: absolute; top: #{top}px;\" data-screen-row=\"#{screenRow}\">"
lineHTML = "<div class=\"#{classes}\" style=\"position: absolute; top: #{top}px; width: #{lineWidth}px;\" data-screen-row=\"#{screenRow}\">"
if text is ""
lineHTML += @buildEmptyLineInnerHTML(line)
@@ -141,14 +153,31 @@ LinesComponent = React.createClass
lineHTML
buildEmptyLineInnerHTML: (line) ->
{showIndentGuide} = @props
{showIndentGuide, invisibles} = @props
{cr, eol} = invisibles
{indentLevel, tabLength} = line
if showIndentGuide and indentLevel > 0
indentSpan = "<span class='indent-guide'>#{multiplyString(' ', tabLength)}</span>"
multiplyString(indentSpan, indentLevel + 1)
invisiblesToRender = []
invisiblesToRender.push(cr) if cr? and line.lineEnding is '\r\n'
invisiblesToRender.push(eol) if eol?
lineHTML = ''
for i in [0...indentLevel]
lineHTML += "<span class='indent-guide'>"
for j in [0...tabLength]
if invisible = invisiblesToRender.shift()
lineHTML += "<span class='invisible-character'>#{invisible}</span>"
else
lineHTML += ' '
lineHTML += "</span>"
while invisiblesToRender.length
lineHTML += "<span class='invisible-character'>#{invisiblesToRender.shift()}</span>"
lineHTML
else
"&nbsp;"
@buildEndOfLineHTML(line, @props.invisibles)
buildLineInnerHTML: (line) ->
{invisibles, mini, showIndentGuide, invisibles} = @props
@@ -203,28 +232,34 @@ LinesComponent = React.createClass
scopeStack.push(scope)
"<span class=\"#{scope.replace(/\.+/g, ' ')}\">"
updateLineNode: (line, screenRow) ->
{editor, lineHeightInPixels, lineDecorations} = @props
updateLineNode: (line, screenRow, updateWidth) ->
{editor, lineHeightInPixels, lineDecorations, lineWidth} = @props
lineNode = @lineNodesByLineId[line.id]
decorations = lineDecorations[screenRow]
previousDecorations = @renderedDecorationsByLineId[line.id]
if previousDecorations?
for decoration in previousDecorations
lineNode.classList.remove(decoration.class) if editor.decorationMatchesType(decoration, 'line') and not _.deepContains(decorations, decoration)
for id, decoration of previousDecorations
if Decoration.isType(decoration, 'line') and not @hasDecoration(decorations, decoration)
lineNode.classList.remove(decoration.class)
if decorations?
for decoration in decorations
if editor.decorationMatchesType(decoration, 'line') and not _.deepContains(previousDecorations, decoration)
for id, decoration of decorations
if Decoration.isType(decoration, 'line') and not @hasDecoration(previousDecorations, decoration)
lineNode.classList.add(decoration.class)
lineNode.style.width = lineWidth + 'px' if updateWidth
unless @screenRowsByLineId[line.id] is screenRow
lineNode.style.top = screenRow * lineHeightInPixels + 'px'
lineNode.dataset.screenRow = screenRow
@screenRowsByLineId[line.id] = screenRow
@lineIdsByScreenRow[screenRow] = line.id
hasDecoration: (decorations, decoration) ->
decorations? and decorations[decoration.id] is decoration
lineNodeForScreenRow: (screenRow) ->
@lineNodesByLineId[@lineIdsByScreenRow[screenRow]]
@@ -248,10 +283,12 @@ LinesComponent = React.createClass
[visibleStartRow, visibleEndRow] = @props.renderedRowRange
node = @getDOMNode()
for tokenizedLine in editor.linesForScreenRows(visibleStartRow, visibleEndRow - 1)
unless @measuredLines.has(tokenizedLine)
lineNode = @lineNodesByLineId[tokenizedLine.id]
@measureCharactersInLine(tokenizedLine, lineNode)
editor.batchCharacterMeasurement =>
for tokenizedLine in editor.linesForScreenRows(visibleStartRow, visibleEndRow - 1)
unless @measuredLines.has(tokenizedLine)
lineNode = @lineNodesByLineId[tokenizedLine.id]
@measureCharactersInLine(tokenizedLine, lineNode)
return
measureCharactersInLine: (tokenizedLine, lineNode) ->
{editor} = @props
+24 -4
Ver Arquivo
@@ -67,7 +67,6 @@ class Package
@loadKeymaps()
@loadMenus()
@loadStylesheets()
@grammarsPromise = @loadGrammars()
@scopedPropertiesPromise = @loadScopedProperties()
@requireMainModule() unless @hasActivationEvents()
@@ -83,6 +82,8 @@ class Package
@scopedProperties = []
activate: ->
@grammarsPromise ?= @loadGrammars()
unless @activationDeferred?
@activationDeferred = Q.defer()
@measure 'activateTime', =>
@@ -128,8 +129,9 @@ class Package
atom.contextMenu.add(menuPath, map['context-menu']) for [menuPath, map] in @menus
atom.menu.add(map.menu) for [menuPath, map] in @menus when map.menu
grammar.activate() for grammar in @grammars
@grammarsActivated = true
unless @grammarsActivated
grammar.activate() for grammar in @grammars
@grammarsActivated = true
scopedProperties.activate() for scopedProperties in @scopedProperties
@scopedPropertiesActivated = true
@@ -173,14 +175,32 @@ class Package
else
fs.listSync(stylesheetDirPath, ['css', 'less'])
loadGrammarsSync: ->
return if @grammarsLoaded
grammarsDirPath = path.join(@path, 'grammars')
grammarPaths = fs.listSync(grammarsDirPath, ['json', 'cson'])
for grammarPath in grammarPaths
try
grammar = atom.syntax.readGrammarSync(grammarPath)
grammar.packageName = @name
@grammars.push(grammar)
grammar.activate()
catch error
console.warn("Failed to load grammar: #{grammarPath}", error.stack ? error)
@grammarsLoaded = true
@grammarsActivated = true
loadGrammars: ->
@grammars = []
return Q() if @grammarsLoaded
loadGrammar = (grammarPath, callback) =>
atom.syntax.readGrammar grammarPath, (error, grammar) =>
if error?
console.warn("Failed to load grammar: #{grammarPath}", error.stack ? error)
else
grammar.packageName = @name
@grammars.push(grammar)
grammar.activate() if @grammarsActivated
callback()
+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) ->
+4
Ver Arquivo
@@ -239,6 +239,9 @@ class Project extends Model
task.on 'scan:result-found', (result) =>
iterator(result) unless @isPathModified(result.filePath)
task.on 'scan:file-error', (error) ->
iterator(null, error)
if _.isFunction(options.onPathsSearched)
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
options.onPathsSearched(numberOfPathsSearched)
@@ -283,6 +286,7 @@ class Project extends Model
checkFinished()
task.on 'replace:path-replaced', iterator
task.on 'replace:file-error', (error) -> iterator(null, error)
for buffer in @getBuffers()
continue unless buffer.getPath() in filePaths
+2
Ver Arquivo
@@ -202,4 +202,6 @@ class ReactEditorView extends View
updateDisplay: -> # No-op shim for package specs
resetDisplay: -> # No-op shim for package specs
redraw: -> # No-op shim
+4 -2
Ver Arquivo
@@ -6,8 +6,10 @@ module.exports = (filePaths, regexSource, regexFlags, replacementText) ->
replacer = new PathReplacer()
regex = new RegExp(regexSource, regexFlags)
replacer.on 'file-error', ({code, path, message}) ->
emit('replace:file-error', {code, path, message})
replacer.on 'path-replaced', (result) ->
emit('replace:path-replaced', result)
replacer.replacePaths regex, replacementText, filePaths, ->
callback()
replacer.replacePaths(regex, replacementText, filePaths, -> callback())
+3
Ver Arquivo
@@ -9,6 +9,9 @@ module.exports = (rootPath, regexSource, options) ->
searcher = new PathSearcher()
scanner = new PathScanner(rootPath, options)
searcher.on 'file-error', ({code, path, message}) ->
emit('scan:file-error', {code, path, message})
searcher.on 'results-found', (result) ->
emit('scan:result-found', result)
+6
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.
@@ -320,6 +325,7 @@ class Selection extends Model
text = @normalizeIndents(text, options.indentBasis)
newBufferRange = @editor.buffer.setTextInRange(oldBufferRange, text, pick(options, 'undo'))
if options.select
@setBufferRange(newBufferRange, reversed: wasReversed)
else
+4 -4
Ver Arquivo
@@ -2,8 +2,8 @@ _ = require 'underscore-plus'
textUtils = require './text-utils'
WhitespaceRegexesByTabLength = {}
LeadingWhitespaceRegex = /^[ ]+/
TrailingWhitespaceRegex = /[ ]+$/
LeadingSpaceRegex = /^[ ]+/
TrailingSpaceRegex = /[ ]+$/
EscapeRegex = /[&"'<>]/g
CharacterRegex = /./g
StartCharacterRegex = /^./
@@ -151,7 +151,7 @@ class Token
leadingHtml = ''
trailingHtml = ''
if @hasLeadingWhitespace and match = LeadingWhitespaceRegex.exec(@value)
if @hasLeadingWhitespace and match = LeadingSpaceRegex.exec(@value)
classes = 'leading-whitespace'
classes += ' indent-guide' if hasIndentGuide
classes += ' invisible-character' if invisibles.space
@@ -161,7 +161,7 @@ class Token
startIndex = match[0].length
if @hasTrailingWhitespace and match = TrailingWhitespaceRegex.exec(@value)
if @hasTrailingWhitespace and match = TrailingSpaceRegex.exec(@value)
tokenIsOnlyWhitespace = match[0].length is @value.length
classes = 'trailing-whitespace'
classes += ' indent-guide' if hasIndentGuide and not @hasLeadingWhitespace and tokenIsOnlyWhitespace
+22 -4
Ver Arquivo
@@ -161,13 +161,26 @@ class TokenizedBuffer extends Model
previousEndStack = @stackForRow(end) # used in spill detection below
newTokenizedLines = @buildTokenizedLinesForRows(start, end + delta, @stackForRow(start - 1))
_.spliceWithArray(@tokenizedLines, start, end - start + 1, newTokenizedLines)
newEndStack = @stackForRow(end + delta)
start = @retokenizeWhitespaceRowsIfIndentLevelChanged(start - 1, -1)
end = @retokenizeWhitespaceRowsIfIndentLevelChanged(newRange.end.row + 1, 1) - delta
newEndStack = @stackForRow(end + delta)
if newEndStack and not _.isEqual(newEndStack, previousEndStack)
@invalidateRow(end + delta + 1)
@emit "changed", { start, end, delta, bufferChange: e }
retokenizeWhitespaceRowsIfIndentLevelChanged: (row, increment) ->
line = @tokenizedLines[row]
if line?.isOnlyWhitespace() and @indentLevelForRow(row) isnt line.indentLevel
while line?.isOnlyWhitespace()
@tokenizedLines[row] = @buildTokenizedTokenizedLineForRow(row, @stackForRow(row - 1))
row += increment
line = @tokenizedLines[row]
row - increment
buildTokenizedLinesForRows: (startRow, endRow, startingStack) ->
ruleStack = startingStack
stopTokenizingAt = startRow + @chunkSize
@@ -218,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)
+8
Ver Arquivo
@@ -152,6 +152,14 @@ class TokenizedLine
break
false
isOnlyWhitespace: ->
if @text == ''
true
else
for token in @tokens
return false unless token.isOnlyWhitespace()
true
tokenAtIndex: (index) ->
@tokens[index]
+18
Ver Arquivo
@@ -46,6 +46,9 @@ class Workspace extends Model
# Called by the Serializable mixin during deserialization
deserializeParams: (params) ->
for packageName in params.packagesWithActiveGrammars ? []
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
params
@@ -53,6 +56,21 @@ class Workspace extends Model
serializeParams: ->
paneContainer: @paneContainer.serialize()
fullScreen: atom.isFullScreen()
packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars()
getPackageNamesWithActiveGrammars: ->
packageNames = []
addGrammar = ({includedGrammarScopes, packageName}={}) ->
return unless packageName
# Prevent cycles
return if packageNames.indexOf(packageName) isnt -1
packageNames.push(packageName)
for scopeName in includedGrammarScopes ? []
addGrammar(atom.syntax.grammarForScopeName(scopeName))
addGrammar(editor.getGrammar()) for editor in @getEditors()
_.uniq(packageNames)
editorAdded: (editor) ->
@emit 'editor-created', editor
+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;
}
}
+5
Ver Arquivo
@@ -179,6 +179,11 @@
box-shadow: inset 1px 0;
}
.editor .vertical-scrollbar,
.editor .horizontal-scrollbar {
cursor: default;
}
.editor .vertical-scrollbar {
position: absolute;
top: 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