Comparar commits

...

603 Commits

Autor SHA1 Mensagem Data
Nathan Sobo 0eb44e06d4 Render lines inline instead of with separate components 2014-05-23 15:30:08 -06:00
Nathan Sobo 94b7fc8a75 Use inline line numbers instead of components 2014-05-23 13:19:47 -06:00
Nathan Sobo 0fde4382d2 Remove duplicated code 2014-05-23 12:59:21 -06:00
Nathan Sobo 4e1434eafa Preserve line numbers that are the target of mousewheel events 2014-05-22 16:05:54 -06:00
Nathan Sobo 7cffe77efa Render line numbers with React components 2014-05-22 16:05:54 -06:00
Nathan Sobo f9e94e9779 Keep lines on the DOM if they are the target of mousewheel events 2014-05-22 16:05:54 -06:00
Nathan Sobo 59a4cbafcf Use React components to render individual lines 2014-05-22 16:05:53 -06:00
Nathan Sobo 9c066d93fa Run react perf in scroll benchmark if NODE_ENV isn't production 2014-05-22 16:01:48 -06:00
Nathan Sobo e754689014 Add displayName to ScrollbarComponent and ScrollbarCornerComponent 2014-05-22 16:01:48 -06:00
Kevin Sawicki 6d89c893b7 Upgrade to grammar-selector@0.27.0 2014-05-22 14:56:41 -07:00
Kevin Sawicki 16df6a32d6 📝 Use TomDoc in Atom class 2014-05-22 14:06:17 -07:00
Kevin Sawicki cdb6de05b3 Update broken Keymap class reference 2014-05-22 13:27:45 -07:00
Kevin Sawicki 1b262eadaa Prepare 0.98.0 release 2014-05-22 13:23:59 -07:00
Nathan Sobo fe31d2d28a Add scrolling benchmark to React editor 2014-05-22 13:25:47 -06:00
Kevin Sawicki 71e83962ac Merge pull request #2356 from klorenz/master
📝 Add solution for "TypeError: Unable to watch path"
2014-05-22 11:34:50 -07:00
Kevin Sawicki f79039e4f7 Upgrade to apm 0.57.0 2014-05-22 11:17:14 -07:00
Kevin Sawicki 08e6dc20e1 Upgrade to settings-view@0.116.0 2014-05-22 09:57:33 -07:00
Nathan Sobo 4f14d8a64f Merge pull request #2344 from atom/ns-ks-react-dont-measure-when-hidden
React: Don't measure line height / char width when editor is hidden
2014-05-22 10:56:43 -06:00
Nathan Sobo da53dfc903 Upgrade atom-keymap for numpad fixes on Linux/Windows 2014-05-22 10:54:19 -06:00
Nathan Sobo 875cfefd36 Merge branch 'master' into ns-ks-react-dont-measure-when-hidden
Conflicts:
	spec/editor-component-spec.coffee
	src/editor-component.coffee
	src/editor-scroll-view-component.coffee
	src/lines-component.coffee
2014-05-22 10:48:21 -06:00
Nathan Sobo b6fb996ceb Merge pull request #2327 from atom/ns-react-fork
Use Atom-specific fork of React allowing selection restoration opt out
2014-05-22 10:41:26 -06:00
Nathan Sobo 316559ae09 Merge pull request #2345 from atom/ns-ks-lines-div-height
Ensure .lines div is always at least the height of the scroll view
2014-05-22 10:35:44 -06:00
Nathan Sobo 08d28d7ed4 Upgrade space-pen so $.fn.views doesn't return undefined values 2014-05-22 10:34:15 -06:00
probablycorey 3a3adf43a4 Merge remote-tracking branch 'origin/master' into zelon-master
Conflicts:
	docs/build-instructions/windows.md
2014-05-22 09:29:53 -07:00
Kevin Sawicki & Nathan Sobo 0951305962 Wire editor.lineHeight config value 2014-05-22 10:17:22 -06:00
Kevin Sawicki & Nathan Sobo 481935c880 Add specs for updating lineHeightInPixels when changing font size/family 2014-05-22 10:17:22 -06:00
Kevin Sawicki & Nathan Sobo 8ffcdad89a Re-measure the line height in pixels when the CSS line-height changes 2014-05-22 10:17:21 -06:00
Kevin Sawicki & Nathan Sobo 9e3ce09658 Rename lineHeight to lineHeightInPixels to distinguish from CSS value
CSS has a line-height property with values like '1.3', but we also have
a measured pixel value for line height. It's important to keep these
separate conceptually.
2014-05-22 10:17:12 -06:00
Corey Johnson 8c5d0775bc Merge pull request #2339 from atom/cj-add-spec-documentation
Add spec documentation
2014-05-22 08:51:02 -07:00
Kay-Uwe (Kiwi) Lorenz 36e8b10917 Merge branch 'master' of https://github.com/klorenz/atom 2014-05-22 17:43:03 +02:00
Kay-Uwe (Kiwi) Lorenz b2b048994c added a solution for an issue in linux troubleshooting section 2014-05-22 17:41:18 +02:00
Ivan Žužak 6db23e67e8 Merge pull request #2353 from aaronraimist/master
Updates Jasmine link in CONTRIBUTING.md
2014-05-22 17:13:18 +02:00
Aaron Raimist 7872e95561 Updates Jasmine link in CONTRIBUTING.md 2014-05-22 10:03:45 -05:00
Kevin Sawicki & Nathan Sobo 45eeee9aea Ensure .lines div is always at least the height of the scroll view
This ensures that the wrap guide extends the entire height of the
editor.
2014-05-21 19:07:03 -06:00
Kevin Sawicki & Nathan Sobo 9cbc693c77 Avoid measuring lineHeight/defaultCharWidth on show unless needed
We only need to re-measure if the fontSize, fontFamily, or lineHeight
changed while the editor was hidden.
2014-05-21 17:35:57 -06:00
Kevin Sawicki & Nathan Sobo ee9d4ab70e Don't measure lineHeight/defaultCharWidth when editor is hidden 2014-05-21 17:15:47 -06:00
Kevin Sawicki & Nathan Sobo 68c3113b75 Call hide on the views instead of the jQuery collection
This ensures that views with custom ::hide methods can invoke special
behavior.
2014-05-21 17:11:36 -06:00
probablycorey 3a71b0470b Add links to writing specs doc 2014-05-21 14:47:30 -07:00
probablycorey 421cdb41b9 Add spec documentation 2014-05-21 14:45:36 -07:00
Corey Johnson a8538a1361 Merge pull request #2295 from lee-dohm/contributing
📝 Unify the two contributing documents
2014-05-21 12:38:23 -07:00
Lee Dohm c3cedd2dc9 Split out the package-specific information
Per PR feedback, splitting out package-specific development information
into its own document.
2014-05-21 11:35:23 -07:00
Kevin Sawicki da38218941 Upgrade to bracket-matcher@0.38.0 2014-05-21 09:29:05 -07:00
Kevin Sawicki c700ca0430 Remove unused sync option 2014-05-21 08:55:40 -07:00
KIM, JINWOOK 0fe3f2d03c Use 'with' instead of 'and'
Using 'with' instead of 'and' could prevent some people to think that SP1 is an other program, or is Windows SP1
2014-05-21 22:11:59 +09:00
Nathan Sobo 65b1e13b83 Use Atom-specific fork of React allowing selection restoration opt out
This fork of React allows data-react-skip-selection-restoration to be
defined on input elements, skipping costly selection restoration that
occurs when the input element is focused during reconciliation.
2014-05-20 23:05:13 -06:00
Nathan Sobo 2acb387446 Merge pull request #2317 from atom/cj-add-invisibles-to-react-editor
Add invisibles to react editor
2014-05-20 22:10:12 -06:00
probablycorey 746273a2ef Merge remote-tracking branch 'origin/master' into cj-add-invisibles-to-react-editor 2014-05-20 16:30:18 -07:00
Nathan Sobo 778beba901 Remove editor-colors class from line numbers 2014-05-20 17:10:55 -06:00
Nathan Sobo 9278920093 Merge branch 'master' into cj-add-invisibles-to-react-editor
Conflicts:
	src/editor-component.coffee
2014-05-20 17:03:14 -06:00
probablycorey ece868c9de Concat strings instead of joining an Array 2014-05-20 15:16:07 -07:00
Kevin Sawicki 651ed9b91e Upgrade to apm 0.56.0 2014-05-20 15:08:23 -07:00
Nathan Sobo ac993680db Remove stray logging 2014-05-20 15:27:28 -06:00
Nathan Sobo 48b33ed07d 💄 2014-05-20 15:17:19 -06:00
Nathan Sobo 724953206f Merge pull request #2319 from atom/ns-react-no-cursor-animation
Don't use CSS animations to blink cursor in the React editor
2014-05-20 15:09:50 -06:00
Nathan Sobo c4e3b90201 Upgrade atom-keymap for Linux support and 'unset!' on partial matches 2014-05-20 15:07:43 -06:00
probablycorey a722d1aa36 Make editor component spec pass 2014-05-20 14:07:36 -07:00
probablycorey 25e3ae0325 Re-render the lines when the showInvisible config option is triggered 2014-05-20 13:58:22 -07:00
Ivan Žužak e26da5887d Upgrade to markdown-preview@0.72.0 2014-05-20 22:37:25 +02:00
Kevin Sawicki 31037797e4 Upgrade to bracket-matcher@0.37.0 2014-05-20 13:27:27 -07:00
Nathan Sobo 2ae7cba452 Don't blink cursors with CSS animation
It seems to create intermittent lags when moving the cursor and typing.
2014-05-20 14:04:59 -06:00
Nathan Sobo fa3ebc8c0f Fix interval cancellation in specs 2014-05-20 14:03:44 -06:00
probablycorey ff36781c98 Add failing spec for toggling showInvisibles config option 2014-05-20 12:34:43 -07:00
probablycorey 2f038cbe66 Update lines component when invisibles changes 2014-05-20 12:34:18 -07:00
probablycorey f962888b35 Remove unnecessary spec 2014-05-20 11:49:40 -07:00
probablycorey 6880368a79 Add soft wrap support to invisibles 2014-05-20 11:49:31 -07:00
Kevin Sawicki 13ba6883b4 Upgrade to apm 0.55.0 2014-05-20 11:42:45 -07:00
probablycorey 1e6e804ebb Use screen line count to determine renderedEndRow 2014-05-20 11:37:32 -07:00
Kevin Sawicki 5690d9fe81 Upgrade to symbols-view@0.53.0 2014-05-20 10:55:01 -07:00
Nathan Sobo 6fef8de63e Merge pull request #2284 from pritambaral/react-paste
Ignore paste in react editor, Fixes #2186
2014-05-20 11:50:26 -06:00
Nathan Sobo e29185ef11 Upgrade atom-keymap for dvorak-qwerty and better linux support 2014-05-20 11:40:32 -06:00
probablycorey c999a6e0e4 Show carriage return invisibles 2014-05-20 10:38:01 -07:00
probablycorey 2bbf5c7800 Remove unnecessary spec 2014-05-20 10:37:24 -07:00
probablycorey 273203e4c9 Fix typo 2014-05-20 10:37:02 -07:00
Lee Dohm 1211680998 📝 Unify the two contributing documents
Both documents had some really great stuff to them, but there was too much
overlap. I did my best to unify them into one document, taking the best
features of each.
2014-05-20 10:35:18 -07:00
Nathan Sobo 84e76556da Try to fix flaky spec 2014-05-20 11:11:35 -06:00
Corey Johnson 55881d594b Merge pull request #2239 from atom/cj-windows-build-instructions-update
Update windows build instructions and requirements
2014-05-20 09:58:45 -07:00
probablycorey 6f0882a098 Merge remote-tracking branch 'origin/master' into cj-windows-build-instructions-update
Conflicts:
	docs/build-instructions/windows.md
2014-05-20 09:51:08 -07:00
Kevin Sawicki dda465d08a Upgrade to language-ruby@0.25.0 2014-05-20 09:49:19 -07:00
KIM, JINWOOK 124c517056 Add Visual Studio 2010 SP1 download URL
Many people are confused by indicating just Visual Studio 2010 Express without SP1
2014-05-20 23:50:12 +09:00
Cheng Zhao 6fa6863244 Don't popup context menu with no items, fixes #2032.
On OS X popuping an empty context menu would have no effect but on Linux
an empty menu container would still be showed.
2014-05-20 22:36:51 +08:00
Nathan Sobo 0ad26c337a Don't use _.pluck when building TokenizedLines 2014-05-19 22:20:57 -06:00
Nathan Sobo 353eb27d2e Update dataset screenRow of gutter nodes when updating them 2014-05-19 21:34:06 -06:00
Nathan Sobo 6edb0b7a3d Delete dead method 2014-05-19 21:32:26 -06:00
Nathan Sobo cd5f0c0047 Update the screenRow on the line element's dataset in ::updateLineNode 2014-05-19 21:32:26 -06:00
Nathan Sobo 5716c7c574 Upgrade underscore-plus for multiplyString optimization 2014-05-19 21:31:10 -06:00
Kevin Sawicki ce30299122 Upgrade to find-and-replace@0.106.0 2014-05-19 17:39:34 -07:00
probablycorey 9b5593d020 Put EOL invisibles into their own scope 2014-05-19 17:27:59 -07:00
probablycorey 4d642b91ef Only pass invisibles through to the line component if needed 2014-05-19 17:10:36 -07:00
probablycorey 8b4cff474f Spec 💄 2014-05-19 17:10:04 -07:00
probablycorey 73ce81d597 Pass invisibles down to lines component 2014-05-19 16:56:53 -07:00
probablycorey 09e4c585aa Add setInvisibles method 2014-05-19 16:56:17 -07:00
Kevin Sawicki 2c5af98cca Upgrade to bracket-matcher@0.36.0 2014-05-19 16:45:04 -07:00
probablycorey cbe07b49aa Add basic invisible specs 2014-05-19 16:20:51 -07:00
Kevin Sawicki aa557a7bdf Upgrade to bracket-matcher@0.35.0 2014-05-19 15:47:11 -07:00
Kevin Sawicki 65cafdda03 Upgrade to language-gfm@0.38.0 2014-05-19 15:39:14 -07:00
Kevin Sawicki 9a18ff5954 Update atom.ico in resources directory 2014-05-19 14:04:34 -07:00
Nathan Sobo d2bc7ab192 Merge pull request #2258 from atom/ns-react-scroll-perf
Improve scroll performance of the React editor
2014-05-19 14:42:18 -06:00
Kevin Sawicki bf7d2defd6 Upgrade to grunt-download-atom-shell@0.7.2 2014-05-19 13:35:44 -07:00
Kevin Sawicki c4e4429744 Upgrade to language-python@0.17.0 2014-05-19 13:34:44 -07:00
Nathan Sobo bfc382c398 Add specs for line/line-number preservation 2014-05-19 14:33:17 -06:00
Nathan Sobo 795399e184 Preserve the target when scrolling w/ mousewheel on editor lines 2014-05-19 14:17:09 -06:00
Nathan Sobo 37bdfb716b Preserve the target when scrolling w/ mousewheel in gutter
Removing the target of a mouseweel event messes up velocity scrolling
with the track pad, so it needs to be preserved until scrolling ceases.
2014-05-19 14:03:34 -06:00
Corey Johnson 405afca1c6 Merge pull request #2269 from pritambaral/tmpdir
Use os.tmpdir() insted of /tmp
2014-05-19 12:20:50 -07:00
Pritam Baral 7627e0b0f0 Minor fix + Remove last references to /tmp 2014-05-19 23:57:48 +05:30
Pritam Baral 25d2206471 Consolidate redundant code 2014-05-19 23:57:48 +05:30
Pritam Baral 2d96444e21 Use os.tmpdir() on OS X 2014-05-19 23:57:48 +05:30
Pritam Baral f5c3bdb845 Use os.tmpdir() on Linux
/tmp isn't always available, is on precious RAM-backed fs or simply not
what the user has set his $TMPDIR to. According to the specification, we
should use $TMPDIR, which node lets us find through os.tmpdir().

Also, contributing.md isn't in favour of using platform-dependent code.

This commit focusses only on Linux, and leaves OS X as is with /tmp for
discussion.
2014-05-19 23:57:48 +05:30
Corey Johnson 22b932ebee Merge pull request #2290 from varesa/master
Make instructions for manual VS path more accurate
2014-05-19 10:06:15 -07:00
probablycorey ad157fe423 💄 2014-05-19 09:38:59 -07:00
Kevin Sawicki 50a6d251d6 Prepare 0.97.0 release 2014-05-19 09:18:36 -07:00
probablycorey f3d36a9726 Move instructions out of requirements 2014-05-19 09:06:45 -07:00
probablycorey c2b8cedef1 💄 2014-05-19 09:06:26 -07:00
Kevin Sawicki 314833bbac Add missing parens on indent guide check
Previously the indent guide was always showing on the whitespace only lines

Closes #2274
2014-05-19 08:52:06 -07:00
Kevin Sawicki e643fe7e7d Upgrade to language-go@0.12.0 2014-05-19 08:39:45 -07:00
Cheng Zhao 0d8a05bdb1 Upgrade to atom-shell@0.12.5 2014-05-19 22:52:32 +08:00
Esa Varemo 21fd2b8f1d Make instructions for manual VS path more accurate
Move the line number for the variable close to the actual current location.
Add a note to not to include unescaped backward slashes as they would appear in normal Windows paths.
2014-05-18 17:37:36 +03:00
Pritam Baral c7461f476e Ignore paste in react editor, Fixes #2186 2014-05-18 04:17:21 +05:30
Corey Johnson 7410f9a90d Merge pull request #2278 from GeoffreyFrogeye/fixTypo-cmdInLinuxKeyMaps
Fixed a typo where cmd would appear in linux.cson
2014-05-17 12:39:55 -07:00
Geoffrey Frogeye 3d98f66330 Fixed a typo where cmd would appear in linux.cson
Fixes #2251 again
2014-05-17 17:53:17 +02:00
Nathan Sobo 8e65d30a84 Compute rendered row range once in EditorComponent and pass it down 2014-05-16 20:58:40 -06:00
probablycorey b4977ff617 Upgrade to release-notes@0.31.0 2014-05-16 15:52:59 -07:00
Kevin Sawicki d397001c33 Merge pull request #2198 from hkdobrev/commits-emoji
Add more Emoji to the contributing guide
2014-05-16 15:37:00 -07:00
Kevin Sawicki bd7de18c7a Upgrade to settings-view@0.115.0 2014-05-16 15:20:21 -07:00
Corey Johnson 9ca506de4b Merge pull request #2173 from Locke23rus/issue-1791
💄 Deprecate backspaceToBeginningOf{Word,Line}
2014-05-16 15:13:44 -07:00
Nathan Sobo 626964f15b Upgrade go-to-line to fix double toggle on react editor 2014-05-16 16:07:35 -06:00
probablycorey 532f119b9d Add application:install-update to workspaceView 2014-05-16 15:05:19 -07:00
Haralan Dobrev 187cf2a710 Change security emoji to 🔒 2014-05-17 01:01:21 +03:00
Nathan Sobo c058483422 Update the gutter width when the number of digits changes 2014-05-16 15:56:18 -06:00
Kevin Sawicki a83a6e5127 Explicitly set permissions on temp folder
Refs #2129
2014-05-16 14:47:55 -07:00
Nathan Sobo 57e6419d1d Restore conditional loading of react editor renderer 2014-05-16 15:31:16 -06:00
Nathan Sobo 9b7547cbe0 Get indent guide specs passing again 2014-05-16 15:31:16 -06:00
Nathan Sobo e74dfe3438 Fix gutter specs and update lines when digit counts change 2014-05-16 15:31:16 -06:00
Nathan Sobo fe82e3e30f Only clear screen row caches on lines component if lineHeight changes 2014-05-16 15:31:16 -06:00
Nathan Sobo b000e8e4a2 Get selection specs passing again 2014-05-16 15:31:16 -06:00
Nathan Sobo 64c82f1c87 Update cursor positioning text for simplified token markup 2014-05-16 15:31:15 -06:00
Nathan Sobo 0ad2730353 Update specs for new line node rendering approach
Lines are no longer translated on the GPU, and they aren't inserted into
the DOM in an order that reflects their order in the buffer.
2014-05-16 15:31:15 -06:00
Nathan Sobo 6017b73acf Add ability to look up line nodes by screen row 2014-05-16 15:31:15 -06:00
Nathan Sobo 0334177696 Make lineOverdrawMargin a property 2014-05-16 15:31:15 -06:00
Nathan Sobo 54cec0a5ff Hold the gutter's width with a dummy line number 2014-05-16 15:31:15 -06:00
Nathan Sobo c5fa2bf12d Attach views to .lines instead of defunct .scroll-view-content 2014-05-16 15:31:15 -06:00
Nathan Sobo bc8a1756f3 Use the .selections layer as the underlayer 2014-05-16 15:31:15 -06:00
Corey Johnson & Nathan Sobo 3f01e2f748 Implement shouldComponentUpdate for SelectionsComponent 2014-05-16 15:31:15 -06:00
Nathan Sobo 7dfe829fc8 Style lines with inline styles for performance 2014-05-16 15:31:15 -06:00
Nathan Sobo c87bc57f9e Don't update top positions of lines/lineNodes unless they have changed 2014-05-16 15:31:15 -06:00
Nathan Sobo 89bd241a78 Always run react in dev mode for now 2014-05-16 15:31:14 -06:00
Nathan Sobo d15fd34f7a Render selections on lines layer; don't put each line number on GPU 2014-05-16 15:31:14 -06:00
Nathan Sobo a118cdd32b Put selections and lines on the GPU together in sibling divs 2014-05-16 15:31:14 -06:00
Nathan Sobo 3a2de9c698 Don't render every line on the GPU
Opaque lines are turning out to be a total pain, plus they ruin absolute
positioning on the lines div. The slight speed boost isn't seeming worth
it anymore.
2014-05-16 15:31:14 -06:00
Nathan Sobo c60e5d90fd 💄 2014-05-16 15:31:14 -06:00
Nathan Sobo e9bff37e06 Render line numbers manually 2014-05-16 15:31:14 -06:00
Nathan Sobo 695f8da3c3 💄 extract buildLineInnerHTML method 2014-05-16 15:31:14 -06:00
Nathan Sobo ea5c5c9e84 Move line HTML generation into lines component 2014-05-16 15:31:14 -06:00
Nathan Sobo 4f9108980f WIP: Manually update line nodes when scrolling 2014-05-16 15:31:14 -06:00
Nathan Sobo 8148e4e50d Skip selection restoration on our fork of react 2014-05-16 15:31:14 -06:00
Nathan Sobo f07a832c83 Sync cursor animations when cursors are added 2014-05-16 15:31:14 -06:00
Nathan Sobo 070d239f41 Blink cursors with a CSS animation
Now that they're on their own layer, I don't think it affects the
repaint timing when typing on lines (if it ever did).
2014-05-16 15:31:13 -06:00
Nathan Sobo 9b02055db9 Move selection background region calculation into React component 2014-05-16 15:31:13 -06:00
Nathan Sobo 0162247bd7 Precompute selection regions for all lines
This is easer to reason about and probably more efficient than computing
everything on a per-line basis.
2014-05-16 15:31:13 -06:00
Nathan Sobo 9001d34ddf Change selection specs to match new rendering scheme 2014-05-16 15:31:13 -06:00
Nathan Sobo cbcc30b384 Don't render empty selections 2014-05-16 15:31:13 -06:00
Nathan Sobo ce9fe90217 Make multi-line selections appear to span the screen with a single div
Because lines are opaque and any area of a selection that overlaps a
line is actually rendered on the line itself, the screen-spanning
background of a multi-line selection can actually be rendered as a
single div spanning the entire screen from the first row to the
penultimate row of the selection.
2014-05-16 15:31:13 -06:00
Nathan Sobo 7a9278e6a7 Render selection fragments on opaque lines
Because lines are opaque on the GPU for sub pixel antialiasing, the
lines obscure the selections which were formerly rendered behind the
lines. This commit renders selection fragments *on* each opaque line
layer so the selections look correct again. Still needs cleanup and
optimization.
2014-05-16 15:31:13 -06:00
Nathan Sobo 01622140e3 Rename renderedRowRange to visibleRowRange
We only render visible rows now, so this makes more sense.
2014-05-16 15:31:13 -06:00
Nathan Sobo e44027b186 Fix the height/width of the editor in spec
Now that everything is absolutely position, the editor no longer assumes
a "natural" height and width. This can be addressed later if we want to
allow editors to expand based on their content.
2014-05-16 15:31:13 -06:00
Nathan Sobo d53f97ecfe Fix horizontal scrolling spec 2014-05-16 15:31:13 -06:00
Nathan Sobo f3efd7d60b Position cursors relative to scrollLeft and fix specs 2014-05-16 15:31:12 -06:00
Nathan Sobo 8d25da9474 Update line number rendering specs for new layer scheme 2014-05-16 15:31:12 -06:00
Nathan Sobo 1aee276b45 Update line rendering specs for new layer scheme 2014-05-16 15:31:12 -06:00
Nathan Sobo 191bc115cf Use explicit descendant selector for styling lines 2014-05-16 15:31:12 -06:00
Nathan Sobo 63488997ee Give lines and line numbers an opaque background to support sub-pixel AA
Since lines and line numbers are now on the GPU, their text won't be
properly anti-aliased on low-resolution displays unless their layers
have a solid background.
2014-05-16 15:31:12 -06:00
Nathan Sobo a22480d857 Don't give lines a negative z-index
Removing the z-index makes them accessible via mouse in the inspector.
2014-05-16 15:31:12 -06:00
Nathan Sobo 757ae6de39 Position selections relative to viewport
This is getting closer, but lines still need to be opaque. Multi-line
selections will still need to be rendered behind the line layers so they
can extend to the edge of the viewport, so this code still has value.
2014-05-16 15:31:12 -06:00
Nathan Sobo cfc08e8b98 Allow horizontal scrolling 2014-05-16 15:31:12 -06:00
Nathan Sobo c8e9282557 Position cursors as layers relative to the viewport 2014-05-16 15:31:11 -06:00
Nathan Sobo a36163ce86 Manually set the gutter width to the width of a line number
We need to absolutely position line numbers to minimize repaints, but
the gutter needs to be wide enough to show them.
2014-05-16 15:31:11 -06:00
Nathan Sobo e3d1a6aef8 Render each line number on its own layer 2014-05-16 15:31:11 -06:00
Nathan Sobo 7d8256d343 Drop lineOverdraw and scroll-view-content div 2014-05-16 15:31:11 -06:00
Nathan Sobo bf9f8597a7 Give each line its own layer on the GPU 2014-05-16 15:31:11 -06:00
Nathan Sobo 9f2c8c1756 Measure characters in new lines when vertically scrolling stops 2014-05-16 15:31:11 -06:00
Nathan Sobo 0ae8765a8a Update scroll position directly on mousewheel events
Previously, we were updating the scrollbars and relying on an async
scroll events to fire. But updating the scrollbars is expensive, so this
updates the model directly when the next animation frame fires instead.
2014-05-16 15:31:11 -06:00
Nathan Sobo 308960309d Overdraw lines to discourage Blink from repainting the entire editor 2014-05-16 15:31:11 -06:00
Nathan Sobo b8ac8516fe Don't preserve rows when scrolling 2014-05-16 15:31:11 -06:00
Nathan Sobo 3f1ce617a7 Try to fix flaky spec 2014-05-16 15:05:49 -06:00
Kevin Sawicki 10e609ba27 Upgrade to tabs@0.40.0 2014-05-16 13:31:58 -07:00
Kevin Sawicki 6cae6981d8 Recommend cloning to shallow path
Prevents path length issues
2014-05-16 13:29:39 -07:00
Kevin Sawicki bff396ab1a Upgrade to language-xml@0.13.0 2014-05-16 13:00:46 -07:00
Kevin Sawicki 7f442d045b Check for errors in script/mkdeb
Refs #2129
2014-05-16 12:54:24 -07:00
Kirill Nikitin 8918eb4758 Bug #1791 Fix typo in example group name and function names. 2014-05-16 23:05:05 +04:00
Kevin Sawicki 628ea72943 Check if selector matches parents of test element
Previously a menu for a keybinding with a .workspace selector would not
display the shortcut because the selector wasn't matching the test editor
element directly.

Now the parent elements of the test editor are checked as well.

Closes #2089
2014-05-16 11:57:04 -07:00
Kevin Sawicki fc2830bacb Use div for test workspace element 2014-05-16 11:53:40 -07:00
Kevin Sawicki b5bff9f8b8 Upgrade to language-python@0.16.0 2014-05-16 10:38:48 -07:00
Kevin Sawicki 5e2181e665 🐧 Add keybindings for select-to-top/bottom
ctrl-shift-home/end are now mapped

Closes #2251
2014-05-16 10:05:33 -07:00
Kevin Sawicki b0e91f8b33 Upgrade to tree-view@0.93.0 2014-05-16 09:47:44 -07:00
Kevin Sawicki 635af7f838 Upgrade to apm 0.54.0 2014-05-16 09:27:16 -07:00
Kevin Sawicki e537080b64 Upgrade to autocomplete@0.28.0 2014-05-16 08:36:02 -07:00
Nathan Sobo f2c7d171bf Fix another subscription leakage associated with theme manager specs 2014-05-16 09:14:21 -06:00
Nathan Sobo 7a4a85cb20 Fix failures running config specs locally 2014-05-16 09:00:01 -06:00
Nathan Sobo 2952f4c2ad Merge pull request #2213 from dyross/dyr-hide-cursor-nicely
Hide the cursor with cursor-hidden class rather than element.style
2014-05-16 08:36:27 -06:00
Nathan Sobo ce668e7139 Fix subscription leak when ~/.atom/styles.less is present running specs 2014-05-16 08:33:49 -06:00
Kirill Nikitin 917b223c6c merge conflict 2014-05-16 11:45:43 +04:00
David Y. Ross e3302b3f73 hide the cursor with cursor-hidden class rather than element.style 2014-05-15 19:20:32 -07:00
probablycorey 38a347ddab Upgrade to grunt-download-atom-shell@0.7.2 2014-05-15 16:41:07 -07:00
Kevin Sawicki e3dbd412e1 Upgrade to find-and-replace@0.105.0 2014-05-15 15:34:50 -07:00
Kevin Sawicki fc9a11959c Upgrade to language-html@0.22.0 2014-05-15 15:33:37 -07:00
Kevin Sawicki 71155abf57 Upgrade to find-and-replace@0.104.0 2014-05-15 15:19:54 -07:00
Kevin Sawicki d5458c1865 Upgrade to fuzzy-finder@0.51.0 2014-05-15 15:14:51 -07:00
Kevin Sawicki 56af2ca4d7 Upgrade to bracket-matcher@0.34.0 2014-05-15 15:10:01 -07:00
Corey Johnson f30c56c237 Don't require 32bit node 2014-05-15 14:55:58 -07:00
Kevin Sawicki cc1e6e2a1f Upgrade to find-and-replace@0.103.0 2014-05-15 14:48:24 -07:00
Kevin Sawicki d7c98cb394 Upgrade to language-sass@0.11.0 2014-05-15 14:44:36 -07:00
Kevin Sawicki 4ff5f96fd4 Upgrade to go-to-line@0.20.0 2014-05-15 14:41:33 -07:00
Kevin Sawicki 1c1c3617e9 Upgrade to find-and-replace@0.102.0 2014-05-15 14:40:16 -07:00
Corey Johnson bb9d67a1b1 Merge remote-tracking branch 'origin/master' into cj-windows-build-instructions-update
Conflicts:
	script/bootstrap
2014-05-15 14:34:07 -07:00
Kevin Sawicki 187e264445 Upgrade to language-ruby-on-rails@0.14.0 2014-05-15 14:08:41 -07:00
Kevin Sawicki 493cd24059 Upgrade to apm 0.53.0 2014-05-15 13:54:36 -07:00
Kevin Sawicki 3c766d87c2 Upgrade to symbols-view@0.52.0 2014-05-15 13:46:28 -07:00
Kevin Sawicki f360ca2cb7 Upgrade to fs-plus 2.2.3 2014-05-15 12:15:12 -07:00
Haralan Dobrev ba8bd80173 Remove ♻️ from the emoji in CONTRIBUTING.md 2014-05-15 22:02:29 +03:00
Haralan Dobrev 6102143faf Use 🔥 emoji for general deleting of code 2014-05-15 21:50:06 +03:00
Kevin Sawicki 3eadc61a3b 💄 Use trailing if 2014-05-15 10:48:02 -07:00
Kevin Sawicki 2bef7e26d7 Merge pull request #2246 from Flannelhead/master
Make ctrl+click add a new cursor in Linux and Windows, fixes #2105
2014-05-15 10:24:15 -07:00
Kevin Sawicki 7d655bf840 📝 Mention previous value is in second argument object 2014-05-15 10:16:29 -07:00
Kevin Sawicki 42c4dc6937 Merge pull request #2243 from lee-dohm/doc-fix
📝 Clean up Config::observe
2014-05-15 10:13:35 -07:00
Kevin Sawicki a4059110f9 Merge pull request #2232 from atom/TOS-help
Include Terms of Use in the help menu
2014-05-15 10:12:06 -07:00
Haralan Dobrev 952c96d03b Use 🍎 for Mac OS specific bugs 2014-05-15 20:10:40 +03:00
Kevin Sawicki 4c73f4e968 Upgrade to language-javascript@0.26.0 2014-05-15 09:57:26 -07:00
Kevin Sawicki 5f36406b52 Upgrade to archive-view@0.31.0 2014-05-15 09:52:45 -07:00
Kevin Sawicki 385cf0f3df Upgrade to language-gfm@0.37.0 2014-05-15 09:46:33 -07:00
Kevin Sawicki e70ad97273 Upgrade to language-ruby@0.24.0 2014-05-15 09:32:56 -07:00
Kevin Sawicki 0b7bf34a0f Upgrade to language-gfm@0.36.0 2014-05-15 09:29:39 -07:00
Kevin Sawicki 713bce7f0b Upgrade to autoflow@0.17.0 2014-05-15 09:25:19 -07:00
Flannelhead 534704a32c Check for e.ctrlKey instead of e.metaKey if not on Mac. 2014-05-15 10:09:50 +03:00
Lee Dohm 37241a7919 📝 Clean up Config::observe 2014-05-14 21:15:17 -07:00
Corey Johnson 333c5b66d1 Merge pull request #2240 from lee-dohm/node-module-doc
📝 Document process for hacking node module components
2014-05-14 20:05:41 -07:00
Lee Dohm a47d55f016 📝 Document process for hacking node module components
See: http://discuss.atom.io/t/how-to-setup-development-for-core-modules-like-atom-keymap/9221/18?u=leedohm
2014-05-14 18:25:12 -07:00
Corey Johnson 58c55cdf81 Troubleshooting message no longer needed because of
50a616d91c
2014-05-14 16:22:35 -07:00
Corey Johnson 50a616d91c Upgrade to grunt-download-atom-shell@0.7.1 2014-05-14 16:20:34 -07:00
Corey Johnson a2be86d15a Require fs in bootstrap 2014-05-14 15:42:05 -07:00
Corey Johnson 73f8c28add Update windows build instructions 2014-05-14 15:34:19 -07:00
Corey Johnson d015793851 Remove unnecessary instructions 2014-05-14 15:31:58 -07:00
Corey Johnson 0b5b741db4 Make sure python2.7 is installed on win32
Closes #2193 
Closes #2167
Closes atom/node-runas#5
2014-05-14 15:29:21 -07:00
Corey Johnson aeac32ae47 Ensure that node is 32bit on win32 2014-05-14 14:49:35 -07:00
Corey Johnson fab60e7faa Create separate instruction
I'm not sure if this step is needed, but it existed before. If it is 
needed we should include WHY you have to do this.
2014-05-14 14:04:56 -07:00
Corey Johnson 6296665f46 Removed unnecessary instruction. 2014-05-14 14:00:13 -07:00
Cameron McEfee 7882ac60d8 Include Terms of Use in the help menu 2014-05-14 10:44:33 -07:00
probablycorey 4fa0b6e783 Upgrade to welcome@0.14.0 2014-05-13 20:57:17 -07:00
Corey Johnson 3a8ddc0cd6 Merge pull request #1977 from 1ace/patch-1
Is atom really incompatible with the newer version of nodejs?
2014-05-13 17:33:40 -07:00
Corey Johnson 3803b473c5 Merge pull request #2176 from Locke23rus/more-naitive-linux-keymaps
🐧 Fix #2166 Add commands for ctrl-home and ctrl-end.
2014-05-13 17:18:30 -07:00
Corey Johnson 93d993d876 Merge pull request #2171 from avdg/fullscreen
Map key for full screen on windows
2014-05-13 17:12:53 -07:00
Corey Johnson 2b3a3ac3c0 Merge pull request #2185 from jugglingnutcase/win32-bindings
Improve some Win32 ctrl keybindings
2014-05-13 17:10:27 -07:00
probablycorey c8b2e6ed2a Prepare 0.96.0 release 2014-05-13 16:53:39 -07:00
James R Sconfitto 58fa414c21 💄 Move bindings under platform header 2014-05-13 16:13:30 -04:00
James R Sconfitto 8872b0bc9b Add ctrl-pageup and ctrl-pagedown Win32 bindings 2014-05-13 16:09:01 -04:00
probablycorey c77a6b10de Upgrade to language-html@0.21.0 2014-05-13 07:55:05 -07:00
Corey Johnson f86280a77b Merge pull request #2170 from skardach/fix-filename-string
Cast opened paths to string
2014-05-12 22:49:24 -07:00
Corey Johnson 65ae582d96 Merge pull request #2194 from aureliojargas/patch-3
Fix link for TextMate's GitHub Organization
2014-05-12 22:46:22 -07:00
probablycorey 5694f9c703 Upgrade to language-html@0.20.0 2014-05-12 18:38:21 -07:00
Haralan Dobrev 6c4d1be004 📝 Add more Emoji to the contributing guide
Suggest Emoji for:
 - Fixing something on Mac OS
 - Fixing a bug
 - Burning whitespace
 - Fixing the CI build
 - Adding tests
 - Refactoring
 - Security
2014-05-13 03:05:31 +03:00
Corey Johnson 9cfa46ea37 Upgrade to node-pathwatcher@1.3.1 2014-05-12 15:20:37 -07:00
Corey Johnson 11d5dfee3a Upgrade to markdown-preview@0.71.0 2014-05-12 14:51:19 -07:00
Corey Johnson 864f61c430 Upgrade to node-pathwatcher@1.3.0 2014-05-12 14:49:30 -07:00
Aurelio Jargas ca164a0b0b Fix link for TextMate's GitHub Organization 2014-05-12 15:56:06 -03:00
Corey Johnson e011becc1a Upgrade to language-ruby-on-rails@0.13.0 2014-05-12 11:26:14 -07:00
Corey Johnson 25f5717ccf Merge pull request #1971 from abe33/feature_proper_multiselections_copy_paste
Implements multiple selections clipboard paste
2014-05-12 11:10:37 -07:00
Ivan Žužak 3f0640f4c3 Merge pull request #2162 from teddybradford/development
Remove duplicate . from default nonWordCharacters
2014-05-12 16:31:04 +01:00
James R Sconfitto 65e8de9db8 Improve ctrl-delete binding for Win32 2014-05-12 11:22:34 -04:00
Cheng Zhao c1ed25d5dc Merge pull request #2189 from atom/atom-shell-v0.12.4
Upgrade to atom-shell@0.12.4
2014-05-12 23:10:38 +08:00
Cheng Zhao f731769afd 📝 No more need of libudev hack on Linux. 2014-05-12 22:28:03 +08:00
Cheng Zhao c466cef7d1 Upgrade to atom-shell@0.12.4 2014-05-12 22:27:22 +08:00
Stan Kardach b4cb92af99 Fix #2152: Cast opened paths to string
path.resolve() was throwing an exception if given path was not a string.
When iterating through all given paths, each entry is casted by JS to
most suitable type and paths in form of a number (i.e. '1234') were
cast to Number, hence the bug.
2014-05-12 15:59:33 +02:00
James Sconfitto 5e7cbbf506 Add ctrl-home and ctrl-end Win32 bindings 2014-05-11 23:03:18 -04:00
Kirill Nikitin 397e0a8ac2 🐧 Add commands for ctrl-home and ctrl-end. 2014-05-12 05:02:16 +04:00
Kirill Nikitin 111b5d1fbe 💄 Deprecate backspaceToBeginningOf{Word,Line}
Rename functions `backspaceToBeginningOfWord` to `deleteToBeginningOfWord` and
`backspaceToBeginningOfLine to `deleteToBeginningOfLine`.
Rename commands `editor:backspace-to-beginning-of-word` to
`delete-to-beginning-of-word` and `editor:backspace-to-beginning-of-line` to
`editor:delete-to-beginning-of-line`.

Fix #1791
2014-05-12 02:50:20 +04:00
abe33 b2e86c80c4 Change test to cover all Selection::copy branches 2014-05-12 00:06:13 +02:00
abe33 b77ea04056 💄 Remove unnecessary double conditions 2014-05-12 00:06:01 +02:00
Anthony Van de Gejuchte ba94f38166 Map key for full screen on windows 2014-05-11 23:12:45 +02:00
probablycorey 7cdaaf2f78 Upgrade markdown packages 2014-05-11 13:52:36 -07:00
Corey Johnson 6caf60bd6b Merge pull request #2160 from dyross/dyr-dev-builds
append git hash to version for dev builds
2014-05-11 12:58:39 -07:00
Stan Kardach 19c7086200 Fix #2152: Cast opened paths to string
path.resolve() was throwing an exception if given path was not a string.
When iterating through all given paths, each entry is casted by JS to
most suitable type and paths in form of a number (i.e. '1234') were
cast to Number, hence the bug.
2014-05-11 17:29:24 +02:00
Teddy Bradford 1519dda294 Remove duplicate . from default nonWordCharacters 2014-05-11 02:10:30 -04:00
David Y. Ross a7efca8bb4 append git hash to version for dev builds 2014-05-10 20:50:20 -07:00
Corey Johnson dbe15f7dda Merge pull request #2142 from aureliojargas/patch-1
Remove unused 's' option from getopts
2014-05-10 15:53:21 -07:00
Corey Johnson c81a6737ad Merge pull request #2144 from aureliojargas/patch-2
Use $(...) for command substitution, not backticks
2014-05-10 13:06:42 -07:00
Paul Betts 5b0d974b43 Merge pull request #2074 from dertuxmalwieder/master
+FreeBSD, -bullshit
2014-05-10 08:37:16 -07:00
Aurelio Jargas 2b73dff0f4 Use $(...) for command substitution, not backticks
Currently both \`...\` and `$(...)` are used for command substitution. It's better to chose just one and stick to it, to avoid confusion.

Some arguments favoring `$(...)`:

* **Easier to read.** The backtick is easily confused with apostrophes and quotes.
* **Easier to nest.** Nesting backticks commands is an escaping nightmare. Using parenthesis is natural: `$(foo $(bar))`
2014-05-10 09:15:53 -03:00
Aurelio Jargas adf0ff0a67 Remove unused 's' option from getopts
This option is not handled by the next `case` command.
2014-05-10 08:41:30 -03:00
Corey Johnson c79ef0473d Merge pull request #2133 from aaronhalford/updatedocs
Update docs and fix typos
2014-05-09 17:19:07 -07:00
Aaron Halford d51b955e09 Update linux.md 2014-05-09 15:22:43 -07:00
Aaron Halford 774d7ec0af Update docs and fix typos 2014-05-09 15:16:13 -07:00
probablycorey d6f4b00e16 🔥 whitespace 2014-05-09 11:40:27 -07:00
probablycorey 9d81df8670 Remove x86 instructions because they aren't supported.
Based on comment by https://github.com/atom/atom/pull/2117/files#r12489527
2014-05-09 11:40:18 -07:00
Corey Johnson 14a430b939 Merge pull request #2128 from alfredxing/body-fullscreen-class
Add `fullscreen` class to body when in full screen
2014-05-09 11:36:39 -07:00
Corey Johnson 07de4a70a1 Merge pull request #2117 from sophearak/master
Add troubleshoot document libudev in Ubuntu 14.04
2014-05-09 11:30:39 -07:00
Corey Johnson eb84ac829b Merge pull request #2114 from Someguy123/master
Add troubleshooting to Windows build instructions
2014-05-09 11:29:50 -07:00
Corey Johnson b8db56a77b Merge pull request #2113 from MitchelSBlake/patch-1
Add more sublime parity keybindings
2014-05-09 11:25:46 -07:00
Corey Johnson 1036f16d1e Merge pull request #2111 from Locke23rus/update-linux-keymaps
🐧 Fix #2103, #2100 Update platform bindings for linux/win.
2014-05-09 11:13:13 -07:00
Nathan Sobo 5ed1cfc259 Merge pull request #1923 from atom/ns-fix-scrollbar-overlap
Refine scrollbar interactions
2014-05-09 11:46:35 -06:00
Nathan Sobo ce5c29fb47 Base the visible lines on the height instead of the clientHeight
Because overlay scrollbars are invisible unless scrolling and even
regular scrollbars can be transparent.
2014-05-09 11:33:04 -06:00
Nathan Sobo f0fd48202c Refresh scrollbars when overlay/classic style preferences changes 2014-05-09 11:33:04 -06:00
Nathan Sobo d5eb8c21b2 Only refresh editor scrollbars on stylesheet changes that require it
If a stylesheet is added or removed, we check if it contains a selector
for scrollbars before refreshing anything.
2014-05-09 11:33:04 -06:00
Nathan Sobo 76b9982e04 Emit stylesheet-added/removed from ThemeManager w/ CSSStyleSheet objects
This enables subscribers to detect not just that stylesheets have
changed, but specifically how they have changed. This is used by the
React editor component to only refresh scrollbars when a stylesheet
that actually contains selectors for scrollbar elements is added or
removed.
2014-05-09 11:33:04 -06:00
Nathan Sobo ca7f11f7d0 Default scrollbar height/width to 15 when it's measure as 0
A 0 measurement indicates that overlay scrollbars are enabled, so we
just fall back to 15px in that case so the user can hover directly over
the scrollbar to scroll.
2014-05-09 11:33:04 -06:00
Nathan Sobo 1c1ace90db Hide and show scrollbars before measuring them after stylesheet changes
We measure the scrollbar-corner node when there's a stylesheet change,
but Chromium won't apply the new style if it was already visible before
the change. This commit hides and shows it before measuring so we get
accurate values.
2014-05-09 11:33:04 -06:00
Nathan Sobo bdd605e85b Explicitly assign dummy scrollbars to the correct width/height
Previously, dummy scrollbars were always 15px wide/tall. This caused
them to obscure the ability to click for the entire 15px region, even if
the actual scrollbar was styled to be much thinner. Now we explicitly
measure the size of scrollbars on mount and when the stylesheets change
and set the height/width explicitly.
2014-05-09 11:33:04 -06:00
Nathan Sobo e1b4b921ba Hide scrollbar when not scrollable in a given direction 2014-05-09 11:33:04 -06:00
Nathan Sobo ab1ede5fe6 Add a dummy scrollbar corner
Horizontal / vertical scrollbars render a 'corner' on the lower right
when they would otherwise overlap. I previously relied on drawing both
dummy scrollbars at their full width/height so the corner got rendered,
but that interfered with the display of the horizontal scrollbar in
certain circumstances because it was too wide to scroll. This commit
provides that behavior with an absolutely positioned div with the same
dimensions as the intersection of scrollbars when both are visible.
2014-05-09 11:33:04 -06:00
Nathan Sobo 5e6d91d66c Don't allow spec window size to interfere with the size of the editor 2014-05-09 11:33:04 -06:00
Nathan Sobo dbd271f70a Don't obscure last character of long lines with vertical scrollbar
This entailed quite a few changes to dial in scrollbars. The scrollbars
are now adjusted in size to account for the width of the opposite
scrollbar. If the width or height are not explicitly constrained and we
are scrollable in the opposite direction that is constrained, we account
for the width of the opposite scrollbar in assigning a natural height
or width based on the content.
2014-05-09 11:33:04 -06:00
Nathan Sobo 527ada47f9 Account for gutter width in scrollWidth of horizontal scrollbar
Because the scrollbar now spans the entire editor but the scrollable
area does not include the gutter, we need to add the current width of
the gutter to the scroll width of the horizontal scrollbar to allow
it to scroll to the end of the longest lines.
2014-05-09 11:33:03 -06:00
Nathan Sobo afb70d0a95 Remove stray return in spec 2014-05-09 11:33:03 -06:00
Nathan Sobo b5f910ad06 Update line number padding when max digits changes 2014-05-09 11:33:03 -06:00
Nathan Sobo e412371b88 Remove logging 2014-05-09 11:33:03 -06:00
Nathan Sobo 7b4bc16531 Fix specs that broke when accounting for horizontal scrollbar height 2014-05-09 11:33:03 -06:00
Nathan Sobo e6df30e94c Respect horizontal scrollbar when rendering the vertical, and vice versa
We set overflow to hidden in the opposite scroll direction only if we
can't actually scroll in that direction, causing the white square where
neither scrollbar overlaps to appear at the lower right corner.
2014-05-09 11:33:03 -06:00
Nathan Sobo d9ba9262bf Update scrollTop to valid position when scrollbar disappears 2014-05-09 11:33:03 -06:00
Nathan Sobo c4be32a5dd Revert "Revert "Don't obscure the last line of the editor with the horizontal scrollbar""
This reverts commit 1d634e471e.
2014-05-09 11:33:03 -06:00
Corey Johnson 0a32f6b5f0 Merge pull request #2050 from Spice-King/win-cmd-spawn-fix
Fix running .cmd stubs through BufferedProcess
2014-05-09 09:12:31 -07:00
Kyle Filz f9fe5efbb0 Fix running .cmd stubs through BufferedProcess
ChildProcess.spawn only will run .exe files on Windows, not .cmd, .bat,
.anythingElse.

See joyent/node#2318 for more information.
2014-05-09 09:04:36 -05:00
Kirill Nikitin 87e723e33b 🐧 Fix #2103, #2100 Update platform bindings for linux/win. 2014-05-09 17:57:55 +04:00
Kevin Sawicki 3f0302b256 Upgrade to apm@0.52.0 2014-05-09 13:52:31 +02:00
Ivan Žužak 88d024e73b Upgrade to feedback@0.33.0 2014-05-09 12:23:06 +01:00
Sophearak THA 47a2e57633 📝 Add troubleshoot document libudev in Ubuntu 14.04 2014-05-09 14:44:57 +07:00
abe33 e7acbb314e 😕 Forgot to replace most references to clipboardMetadata
Never attempt to fix a PR right before going to sleep!
2014-05-09 09:33:35 +02:00
Cthulhux d6a4c70929 FreeBSD
Signed-off-by: Cthulhux <zeug@tuxproject.de>
2014-05-09 09:28:50 +02:00
Alfred Xing 839cad0c2a Add fullscreen class to body when in full screen
Add a `fullscreen` class to body when full screen is triggered, as suggested
by @orderedlist in #1694
2014-05-08 20:36:46 -07:00
Chris S d3845db403 Add troubleshooting to Windows build instructions 2014-05-09 04:04:43 +01:00
Scott Blake 3d68bdf126 Add more sublime parity keybindings 2014-05-08 22:57:32 -04:00
Daniel Hengeveld 0d190d2cd4 Merge pull request #2112 from atom/why-ghfw
Explain why GH4W
2014-05-08 19:21:53 -07:00
Paul Betts 4afae028ec Explain why GH4W 2014-05-08 19:00:53 -07:00
Paul Betts 5165f0df88 Merge remote-tracking branch 'origin/master' into winreadme
Conflicts:
	README.md
2014-05-08 18:06:05 -07:00
Corey Johnson 5b7b3501a6 Merge pull request #2081 from xcvd/master
Shift backspace keymap
2014-05-08 17:03:25 -07:00
Corey Johnson c3937d0c4c Merge pull request #2073 from captn3m0/master
Make atom build behind firewalls
2014-05-08 16:53:31 -07:00
Corey Johnson 6e27208c5c Merge pull request #2108 from atom/cj-update-build-docs
Update build docs
2014-05-08 16:42:34 -07:00
Corey Johnson 91342db0ba Tweak build instruction content 2014-05-08 16:34:54 -07:00
Corey Johnson 8f7123ae12 Update build instruction links 2014-05-08 16:31:10 -07:00
Corey Johnson 3a22b3d4b8 Move build instructions to separate files 2014-05-08 16:30:44 -07:00
Corey Johnson 919ca82ccd Update building section of docs 2014-05-08 16:16:31 -07:00
Corey Johnson d35baac054 Add build instructions section to docs folder 2014-05-08 16:16:13 -07:00
Eric Engeström 9302242299 Allowing node > 1.0 (no reason not to already do that, I guess) 2014-05-09 00:45:13 +02:00
Eric Engeström ed90a78ea5 Replacing string comparison with actual int comparison 2014-05-09 00:42:40 +02:00
Corey Johnson 9aa2df7cee Merge pull request #2059 from bradgearon/master
append .cmd to apm in package-manager.coffee if platform is win32
2014-05-08 15:14:36 -07:00
Corey Johnson 41ea18a8f1 Merge pull request #2047 from cameronmcefee/master
Wordsmith the Atom readme
2014-05-08 15:10:39 -07:00
Corey Johnson 5cf37fd13e Merge pull request #2045 from atom/cj-tabs-be-weird
Make Atom smarter about guessing if a file uses soft or hard tabs
2014-05-08 15:09:32 -07:00
abe33 3e12695914 💄 Clear object deconstruction in Selection::copy 2014-05-09 00:07:46 +02:00
abe33 ed1c8897ec 😅 Forgot to remove the test focus 2014-05-09 00:07:00 +02:00
abe33 75eb0182e9 💄 Use skinny arrow instead 2014-05-09 00:03:40 +02:00
abe33 554165ca48 💄 Harmonize lineForRow calls in specs 2014-05-09 00:02:31 +02:00
abe33 5a5cb869e2 💄 Replace have with has in spec description 2014-05-08 23:59:55 +02:00
Corey Johnson a649d75ab8 Merge remote-tracking branch 'origin/master' into cj-tabs-be-weird
Conflicts:
	package.json
2014-05-08 14:36:50 -07:00
Corey Johnson 255cdbb60a Avoid problems with version pattern ^X.Y.Z
Older versions of npm don't recognize that pattern
2014-05-08 14:14:26 -07:00
Corey Johnson bd4e56fd08 Upgrade to text-buffer@2.2.2 2014-05-08 14:01:30 -07:00
Corey Johnson 5246d784db Upgrade to text-buffer@2.2.1 2014-05-08 13:50:54 -07:00
Brad Gearon e945b83318 remove os require use process.platform instead 2014-05-08 12:38:35 -05:00
Kevin Sawicki 38bd996996 Merge pull request #2052 from AngelEzquerra/ignore_mercurial_files
Add mercurial directories to default list of ignored names
2014-05-08 19:23:40 +02:00
Kevin Sawicki 8f3a72e11b Merge pull request #2071 from lee-dohm/doc-fix
📝 Some simple documentation fixes
2014-05-08 19:21:00 +02:00
Kevin Sawicki ddc62efb44 Upgrade to pathwatcher@1.2.4 2014-05-08 19:17:17 +02:00
Kevin Sawicki 8f08e497a0 Upgrade to scrollbar-style@0.4.0 2014-05-08 19:16:47 +02:00
xcvd 8048f8af5f Shift backspace keymap
Within windows build shift-backspace currently does nothing. Behaviour
untested in linux (perhaps linux.cson should be modified too?)
2014-05-08 11:53:47 +01:00
Cthulhux 4fc4e36902 +FreeBSD, -bullshit
Signed-off-by: Cthulhux <zeug@tuxproject.de>
2014-05-08 09:38:16 +02:00
Abhay Rana c66d3fdba0 Make atom build behind firewalls
This is to get `npm install` to work behind firewalls where `git://` is blocked.
2014-05-08 12:24:34 +05:30
Lee Dohm 9b49c2f987 📝 Some simple documentation fixes 2014-05-07 22:38:51 -07:00
Paul Betts bceed13606 Fix Windows build instructions 2014-05-07 20:08:09 -07:00
Brad Gearon d99c9edc43 append .cmd to apm in package-manager.coffee if platform is win32
avoids NOENT error when searching for packages
2014-05-07 18:35:05 -05:00
Cameron McEfee 31306a3243 Apply @probablycorey's suggestions 2014-05-07 15:04:39 -07:00
Angel Ezquerra 67de17e0c3 Add mercurial directories to default list of ignored names
atom already ignored git and svn directories. It makes sense to ignore
mercurial (.hg) directories as well.
2014-05-07 23:56:29 +02:00
Corey Johnson 3371252656 Merge pull request #1995 from dpen2000/patch-1
Update README.md
2014-05-07 14:37:53 -07:00
Nathan Sobo a7e9037e5b Upgrade language-go for grammar improvements in atom/language-go#18 2014-05-07 14:44:30 -06:00
Cameron McEfee b3e376ce7c This doesn't need to change. 2014-05-07 13:03:59 -07:00
Cameron McEfee d24b664873 fix io typo 2014-05-07 13:00:30 -07:00
Cameron McEfee b8394830a0 Wordsmith the readme 2014-05-07 12:59:58 -07:00
probablycorey 7d76105530 Merge remote-tracking branch 'origin/master' into cj-tabs-be-weird 2014-05-07 12:59:23 -07:00
probablycorey bbe399196f Upgrade to find-and-replace@0.101.0 2014-05-07 12:49:45 -07:00
probablycorey 8c6cdf7358 Upgrade to text-buffer@2.2.1 2014-05-07 12:34:34 -07:00
dpen2000 f71bb9349b Update README.md
Change 2010 express edition link because old one redirects to a general page about Visual Studio
2014-05-07 14:26:40 -05:00
probablycorey 6bb260140b Don't use comment lines to determine soft/hard tabs.
Closes atom/language-php#24
Closes #1733
2014-05-07 12:18:05 -07:00
Nathan Sobo 88aec85f92 Upgrade pathwatcher to support windows builds 2014-05-07 12:24:02 -06:00
Kevin Sawicki 61cdee9743 Upgrade to language-less@0.9.0 2014-05-07 09:20:30 -07:00
Kevin Sawicki 15c3efa6e4 💄 Add variable names for clarity 2014-05-07 09:14:42 -07:00
Kevin Sawicki a1835efb4e Merge pull request #1988 from Ferk/master
Fix for source tarballs error on 'set-version' (not a git repository)
2014-05-07 09:12:49 -07:00
Kevin Sawicki 5e0f132d33 Merge pull request #1991 from evinugur/master
ignore Thumbs.db in workspace-view and in actual atom gitignore
2014-05-07 09:05:56 -07:00
Kevin Sawicki 2c7c4c95f2 Merge pull request #2013 from pborreli/typos
Fixed typos
2014-05-07 08:56:19 -07:00
Kevin Sawicki 81f115d3db Merge pull request #2006 from Heather/patch-1
Visual C++ 2010 should be SP1
2014-05-07 08:48:48 -07:00
Kevin Sawicki c4f872acff Upgrade to apm 0.51.0 2014-05-07 08:43:25 -07:00
Nathan Sobo b3dbb18889 Upgrade reactionary for cleanup / removal of unused 'class' feature 2014-05-07 09:23:51 -06:00
Cheng Zhao 02a278d80c Mention the mkdeb task, closes #1969. 2014-05-07 22:54:20 +08:00
Nathan Sobo c7954a4c5e Upgrade path watcher for variable name fix on windows 2014-05-07 08:15:51 -06:00
Cheng Zhao 61fff23be2 Upgrade to atom-shell@0.12.3 2014-05-07 16:31:37 +08:00
Pascal Borreli 7070ed8ae4 Fixed typos 2014-05-07 08:52:58 +01:00
Heather 101b18e408 Visual C++ 2010 should be SP1
else-way there will be "failure during conversion to COFF"
description on StackOverflow: http://stackoverflow.com/questions/10888391/error-link-fatal-error-lnk1123-failure-during-conversion-to-coff-file-inval
2014-05-06 22:15:45 -07:00
Cheng Zhao f0bd3b1c20 Ignore the "paste" event, fixes #1945.
Somehow on Linux the "paste" event is emitted when user presses ctrl-v,
even if the ctrl-v has been captured by window event handler. This
should be a bug of Chromium.
2014-05-07 10:39:01 +08:00
Corey Johnson 921bf8501f Merge pull request #1993 from mattbelland/docs-grammar-fix
Remove unnecessary conjunction and spaces
2014-05-06 19:30:08 -07:00
Matt Belland 594a2d201b Remove unnecessary conjunction and spaces 2014-05-06 19:19:43 -07:00
Evin Ugur cb0ba55871 ignore Thumbs.db in workspace-view and in actual atom gitignore 2014-05-06 21:24:11 -04:00
Fernando C.V 27bcf046b1 Take version from package.json also when there's no .git directory (source releases) 2014-05-07 02:55:07 +02:00
Kevin Sawicki 44f19610b6 Add grunt.cmd 2014-05-06 17:03:19 -07:00
Kevin Sawicki a1d2e253ea Upgrade to apm 0.50.0 2014-05-06 16:53:33 -07:00
Kevin Sawicki a961a8f644 Upgrade to apm@0.49.0 2014-05-06 16:14:52 -07:00
probablycorey 86b7fec0bb Update build requirements in readme 2014-05-06 15:55:10 -07:00
Kevin Sawicki 6060e0d8a9 Upgrade to symbols-view@0.51.0 2014-05-06 15:37:41 -07:00
Kevin Sawicki c160601a9d Upgrade to spell-check@0.35.0 2014-05-06 15:15:32 -07:00
abe33 56a1ecf6c1 Adds specs for multi selections clipboard handling 2014-05-07 00:13:04 +02:00
Kevin Sawicki 648441ee5c Update to scrollbar-style@0.3.0 2014-05-06 15:04:59 -07:00
Kevin Sawicki 03f0e084e1 Merge pull request #1978 from kelunik/master
Use headings to enable links
2014-05-06 15:03:49 -07:00
Niklas Keller ab57dc840f Use headings to enable links 2014-05-07 00:01:59 +02:00
Eric Engeström 2ff5309d54 Allow newer version of nodejs 2014-05-07 00:00:44 +02:00
Kevin Sawicki a308903735 Merge pull request #1975 from giodamelio/patch-1
Add message about 64bit to the Linux requirements fixes #1973
2014-05-06 14:53:24 -07:00
Gio d'Amelio b6cb604330 Add message about 64bit to the Linux requirements fixes #1973 2014-05-06 14:52:22 -07:00
Kevin Sawicki fb557e9b90 Merge pull request #1972 from dsine-de/patch-1
fixed Windows path slash
2014-05-06 14:32:17 -07:00
dsine-de 3180ab067c fixed Windows path slash 2014-05-06 23:31:31 +02:00
abe33 4b7d982eb4 💄 Fix typo in pasteText method comments 2014-05-06 23:26:13 +02:00
abe33 fbabc6f455 Implements multiple selections clipboard paste
Includes:

  - Passing the selection index in the `Editor::mutateSelectedText`
method callback
  - Storing all the selections content on many calls of
`Selection::copy` with `maintainClipboard = true` in a metadata
`selections` array
  - Handling clipboard with a `selections` metadata in
the`Editor::pasteText` method
2014-05-06 23:19:39 +02:00
Kevin Sawicki fa759d8128 Upgrade to apm 0.48.0 2014-05-06 14:10:56 -07:00
Kevin Sawicki e9ed45671f Merge pull request #1935 from tombh/1814-linux-compat-show-error-on-startup
If atom.sh has non-zero exit show errors captured by nohup. Refers to #1814
2014-05-06 13:32:17 -07:00
Kevin Sawicki 8cc871f326 Merge pull request #1957 from bogdan-kulynych/master
Add node and npm versions to Linux build instructions, as mentioned in #1814
2014-05-06 12:48:16 -07:00
Corey Johnson 3651adbefd Upgrade to language-javascript@v0.25.0 2014-05-06 12:24:09 -07:00
Bogdan ff70ded25b Correct npm version 2014-05-06 22:04:12 +03:00
Bogdan 244c06b524 Add node and npm versions to Linux build instructions, as mentioned in #1814 2014-05-06 21:44:17 +03:00
Kevin Sawicki e7309b254c Merge pull request #1951 from bonh/master
Make sure gyp uses Python 2 (#1933)
2014-05-06 11:16:36 -07:00
Jeff Bonhag 0cdce9c665 Make sure gyp uses Python 2 (#1933)
gyp/npm uses /usr/bin/python to build, which is a problem on systems where
/usr/bin/python is Python 3 or higher.  Fortunately, you can tell npm which
Python to use.
2014-05-06 14:10:40 -04:00
Kevin Sawicki 7a10bf1c33 Indent install option 2014-05-06 10:35:53 -07:00
Kevin Sawicki a6d5a4ab5d Merge pull request #1941 from qJake/master
Add Git for Windows as Windows build requirement
2014-05-06 10:34:38 -07:00
Kevin Sawicki 68f3c98872 Upgrade to apm@0.47.0 2014-05-06 10:32:39 -07:00
qJake 0b8c0cc431 Add Git for Windows as Windows build requirement 2014-05-06 12:28:16 -05:00
Kevin Sawicki d9eaf8d334 Update to scrollbar-style@0.2.0 2014-05-06 10:24:58 -07:00
Corey Johnson 8d29ec4116 Prepare 0.95.0 release 2014-05-06 10:19:14 -07:00
Kevin Sawicki 806ff4e141 Resolve path to apm
Refs #1936
2014-05-06 09:56:03 -07:00
Corey Johnson 4b0ddbf2ab Upgrade to feedback@0.32.0 2014-05-06 09:55:45 -07:00
Thomas Buckley-Houston 1ea54f8c92 🐧 If atom.sh has non-zero exit show errors captured by nohup. Refers to #1814 2014-05-06 17:21:01 +01:00
Kevin Sawicki 31cb4c58c2 Upgrade to apm@0.46.0 2014-05-06 09:15:07 -07:00
Kevin Sawicki b9bffc32b0 Upgrade to release-notes@0.29.0 2014-05-06 09:15:07 -07:00
Corey Johnson b267a781da Upgrade to welcom@0.13.0 2014-05-06 09:11:24 -07:00
Corey Johnson 6f7209c68b Upgrade to feedback@0.31.0 2014-05-06 09:06:24 -07:00
Corey Johnson fb6782ef31 Update clone url in readme 2014-05-06 08:42:18 -07:00
Kevin Sawicki fae8aafc17 Merge pull request #1929 from pierredup/patch-1
Fix link to API in README
2014-05-06 08:31:18 -07:00
Pierre du Plessis ba38dddf4d Fix link to API in README 2014-05-06 17:29:37 +02:00
Kevin Sawicki 0a4600409a Merge pull request #1927 from aaronraimist/master
Updates Jasmine link
2014-05-06 08:26:38 -07:00
Aaron Raimist 706e4476d5 Updates Jasmine link
📝
Updates Jasmine link in CONTRIBUTING.md
2014-05-06 10:25:35 -05:00
Kevin Sawicki c113a0a217 Merge pull request #1926 from bfrohs/patch-1
Show code necessary to create emoji
2014-05-06 08:24:00 -07:00
Brandon Frohs ef05278537 Show code necessary to create emoji
Touch screens without `:hover` are unable to see the tooltip.
2014-05-06 11:22:01 -04:00
Kevin Sawicki 1254425ba8 Fix windows links 2014-05-06 08:11:32 -07:00
Corey Johnson e3641286e7 Merge pull request #1924 from atom/cj-readme-requirements
Update build requirements
2014-05-06 07:48:05 -07:00
Corey Johnson 3a03f470c7 Use .bat fence instead of .sh 2014-05-06 07:43:08 -07:00
Kevin Sawicki 4ea44d9612 Prepare 0.94.0 release 2014-05-06 07:03:21 -07:00
Kevin Sawicki 15c2540c29 Merge branch 'master' into cj-readme-requirements 2014-05-06 06:49:58 -07:00
Kevin Sawicki 112f90979c Upgrade to language-xml@0.12.0 2014-05-06 06:39:10 -07:00
Kevin Sawicki cbe73fd916 Read LICENSE.md as UTF8 2014-05-06 06:39:10 -07:00
Ivan Žužak 3ea28c8ed6 Upgrade to language-gfm@0.34.0 2014-05-06 15:33:58 +02:00
Cheng Zhao 5a219a9087 Upgrade to atom-shell@0.12.2 2014-05-06 10:22:39 +08:00
Kevin Sawicki 11eae4d5db Upgrade to language-gfm@0.33.0 2014-05-05 17:43:28 -07:00
Kevin Sawicki fe4016a49d 🐧 Mention separate build/install 2014-05-05 17:37:38 -07:00
Kevin Sawicki 0b786427f4 Set CFBundleTypeIconFile to file.icns
Closes #1726
2014-05-05 17:22:33 -07:00
Kevin Sawicki 4900dc6bcd Set LSHandlerRank to Alternate
This should prevent Atom from being the default editor for all these file
types and instead make it opt-in.

Closes #1808
2014-05-05 17:22:33 -07:00
Corey Johnson 31b06b2e47 Update script/build directions 2014-05-05 17:15:59 -07:00
Corey Johnson cf6d83a896 Update windows version requirement 2014-05-05 17:13:10 -07:00
Corey Johnson 637410a8c5 Upgrade to grunt-download-atom-shell@0.7.0 2014-05-05 17:10:35 -07:00
Corey Johnson 084e4ab830 Use previous windows readme directions 2014-05-05 16:18:32 -07:00
Corey Johnson 5a53b34697 Add more specific node details 2014-05-05 16:15:10 -07:00
Corey Johnson 8f3b76d3c9 Update Windows requirements 2014-05-05 16:13:38 -07:00
Kevin Sawicki f5df111b5c Add Linux platform note and keyring install command 2014-05-05 16:05:24 -07:00
Kevin Sawicki 1d31a10dc4 Include original LICENSE.md in generated file 2014-05-05 16:01:05 -07:00
Kevin Sawicki db61de6cf3 Add .md extension to generated license 2014-05-05 15:55:34 -07:00
Kevin Sawicki c75d36ef93 Implement application:open-license in AtomWindow
Allows the LICENSE.md file to be opened even when no windows are
open.

Closes #1624
2014-05-05 15:54:47 -07:00
Corey Johnson bb2527bbb8 Add stub linux and windows requirements 2014-05-05 15:49:29 -07:00
Corey Johnson eb31c6c85f Add OS X build requirements 2014-05-05 15:33:20 -07:00
Corey Johnson 546f81f2d0 Fix spacing 2014-05-05 15:33:03 -07:00
Kevin Sawicki 7bb6cd99eb Tweak README copy 2014-05-05 13:04:22 -07:00
Kevin Sawicki 3dbdaee25c Merge pull request #1898 from atom/open-source-release
Open Source Atom
2014-05-05 12:59:19 -07:00
Kevin Sawicki b458de0f2d Merge pull request #1921 from atom/ks-split-option-errors
Fix split option errors
2014-05-05 11:36:24 -07:00
Kevin Sawicki 240747ed76 💄 Tweak spec descriptions 2014-05-05 11:28:36 -07:00
Kevin Sawicki 8b5fd64dd4 Guard against PaneAxis as first child
Pane::findLeftmostSibling expected to return a Pane, not a PaneAxis
2014-05-05 11:28:36 -07:00
Kevin Sawicki 1c514bdc6b Split right when rightmost sibling is an axis
This was previously throwing an error when Workspace::open was called
with a split: right option and the rightmost sibling was a PaneAxis
since it was assuming findOrCreateRightmostSibling was always returning
a Pane, not a PaneAxis.
2014-05-05 11:28:36 -07:00
Kevin Sawicki f4d9abc789 Use ~ instead of ^ to support older npm versions 2014-05-05 11:07:43 -07:00
Kevin Sawicki e5197f6f0f Fench code block as sh 2014-05-05 11:06:36 -07:00
Kevin Sawicki 8f57246571 Upgrade to settings-view@0.114.0 2014-05-05 11:03:55 -07:00
Kevin Sawicki 7658107e3b Merge pull request #1920 from atom/new-brand-assets
New brand assets
2014-05-05 10:29:27 -07:00
Kevin Sawicki c33227830e Add file icon for all sizes 2014-05-05 10:22:28 -07:00
Kevin Sawicki 43f2153c86 Add icons for all sizes 2014-05-05 10:14:47 -07:00
Kevin Sawicki 084d84660a Update atom.icns with single 2x 512x512 2014-05-05 09:58:12 -07:00
Cameron McEfee 4120b34d22 larger icon graphic 2014-05-05 09:51:01 -07:00
Kevin Sawicki c4a0bce92f Upgrade to tabs@0.39.0 2014-05-05 09:49:44 -07:00
Kevin Sawicki 858c18114b Update file and app icons 2014-05-05 09:39:24 -07:00
Cameron McEfee 91f9302fc4 improve aliasing on the new icon 2014-05-05 09:33:02 -07:00
Kevin Sawicki 4f3bf04668 Update atom.icns with new icon 2014-05-05 09:19:17 -07:00
Kevin Sawicki 11c9417e8d Upgrade to scope-property-store@0.9.0 2014-05-05 08:51:59 -07:00
Kevin Sawicki db141d9d7f Upgrade to markdown-preview@0.69.0 2014-05-05 08:49:01 -07:00
Cameron McEfee 5624596c88 Update the icon png 2014-05-04 15:51:41 -07:00
Cameron McEfee cda7ca047c Logo in the docs 2014-05-04 15:48:25 -07:00
Cameron McEfee ac25ad3985 Logo in the readme 2014-05-04 15:42:45 -07:00
Kevin Sawicki 1bf4e7ab96 Upgrade to first-mate 1.5.3 2014-05-02 18:08:01 -07:00
Kevin Sawicki 49587ace05 Upgrade to tree-view@0.92.0 2014-05-02 11:12:10 -07:00
Ivan Žužak 54fb06d4b0 Upgrade to release-notes@0.28.0 2014-05-02 20:02:24 +02:00
Ivan Žužak 8f81b5dc63 Upgrade to find-and-replace@0.100.0 2014-05-02 20:00:47 +02:00
Kevin Sawicki d5e1649607 Upgrade to settings-view@0.113.0 2014-05-02 10:50:46 -07:00
Kevin Sawicki e2c1f6c0e2 Upgrade to markdown-preview@0.68.0 2014-05-02 10:16:01 -07:00
Kevin Sawicki 8ec7d1273c Cache handlerPath 2014-05-01 17:05:47 -07:00
Kevin Sawicki 7ffc5cc02b Terminate task before recreating 2014-05-01 17:05:28 -07:00
Kevin Sawicki aac27db552 Upgrade to grammar-selector@0.26.0 2014-05-01 16:04:45 -07:00
Kevin Sawicki 03acb1c40a Upgrade to markdown-preview@0.67.0 2014-05-01 15:38:38 -07:00
Kevin Sawicki 5eb332042e Merge pull request #1915 from atom/ks-safe-mode
Safe mode
2014-05-01 15:30:44 -07:00
Kevin Sawicki 66943c4820 Add application:open-safe command
This opens a new "safe mode" window similar to the application:open-dev
command
2014-05-01 15:20:22 -07:00
Kevin Sawicki 4ed9e34893 Tweak option description 2014-05-01 15:20:22 -07:00
Kevin Sawicki 4f4da78e54 Add --safe argument
This will launch Atom in "safe" mode where packages from ~/.atom
will not be loaded automatically or be resolveable by name.
2014-05-01 15:20:22 -07:00
Kevin Sawicki 832dfd057e Upgrade to tabs@0.38.0 2014-05-01 15:14:39 -07:00
Kevin Sawicki dd74280146 Set status to 0 if it is ignored
The statuses obtained via the background task do not include ignored
entries so don't put ignored entries into the cache when checking the
status individually.

This was causing the fuzzy finder to show ignored paths in the status
list view after an ignored file was saved.
2014-05-01 14:20:46 -07:00
Kevin Sawicki a7d1a68fb8 Upgrade to git-utils 1.3 2014-05-01 14:13:19 -07:00
Kevin Sawicki 6b8b454625 Upgrade to symbols-view@0.50.0 2014-05-01 13:12:05 -07:00
Kevin Sawicki 5c5b7df70d Upgrade to tree-view@0.91.0 2014-04-30 16:54:32 -07:00
Corey Johnson 7d3abda86f Fix Workspace::openLicense 2014-04-30 16:38:44 -07:00
Kevin Sawicki 7f824ffbb3 Merge pull request #1914 from atom/ks-open-to-column
Open to initial column
2014-04-30 16:21:49 -07:00
Corey Johnson 0b7475a4c1 Merge remote-tracking branch 'origin/master' into open-source-release
Conflicts:
	package.json
2014-04-30 16:11:44 -07:00
Kevin Sawicki cf62d3212c Use path.join instead of hard-coded separator 2014-04-30 16:07:26 -07:00
Kevin Sawicki b260cbb43a Call open on model instead of view 2014-04-30 16:07:26 -07:00
Kevin Sawicki 1367f08de8 Parse initial column from path to open argument 2014-04-30 16:07:26 -07:00
Kevin Sawicki 27b02a7981 Add initialColumn options to Workspace::open
This options works similarly to the existing initialLine option
2014-04-30 16:07:26 -07:00
Corey Johnson e62ae02c00 Update file.icns 2014-04-30 16:04:58 -07:00
Corey Johnson 233402dd33 Update atom icon 2014-04-30 15:52:13 -07:00
Corey Johnson 69821b7a6b Add .gitignore file to dot-atom.
This will help users who want to push their .atom directory to GitHub

Closes #1094
2014-04-30 14:41:23 -07:00
Kevin Sawicki efcffe5205 Remove unused grunt task 2014-04-30 14:31:43 -07:00
Kevin Sawicki 802e651b6e 📝 Link to apm repo 2014-04-30 14:18:11 -07:00
Kevin Sawicki 0e8b951050 Upper case pane to match File menu item 2014-04-30 14:10:41 -07:00
Corey Johnson 8ef97bd78e Add menu items for pane management on windows 2014-04-30 13:59:49 -07:00
Corey Johnson 6749988de1 Add menu items for pane management
Closes #1897
2014-04-30 13:57:37 -07:00
Kevin Sawicki 4a26f8f28b Merge pull request #1912 from atom/ks-whitespace-double-click
Whitespace double click
2014-04-30 10:10:26 -07:00
Kevin Sawicki a4ee412e96 Remove Math.max corrections to range
Editor::getTextInBufferRange will clip the specified range instead.
2014-04-30 09:58:37 -07:00
Kevin Sawicki 4f655d7de5 📝 Update comment to match behavior 2014-04-30 09:58:37 -07:00
Kevin Sawicki 33c02ef3e1 Mention double clicking in spec description 2014-04-30 09:58:37 -07:00
Kevin Sawicki aa4749f175 Select all adjacent whitespace on double click
Cursor::isSurroundedByWhitespace was use column 0 instead of the
position right before the cursor.
2014-04-30 09:58:37 -07:00
Kevin Sawicki 6ace49b0e8 Merge pull request #1911 from atom/ks-preserve-indentation-when-commenting
Preserve indentation when commenting
2014-04-30 09:58:17 -07:00
Kevin Sawicki 9cf642e910 Preserve indentation when commenting
Previously this happened only when the language did not have a
comment end pattern.
2014-04-30 09:50:11 -07:00
Kevin Sawicki 2990f36595 Remove unused publish release step 2014-04-30 09:43:01 -07:00
Kevin Sawicki 032fc86a4d Merge pull request #1913 from atom/ks-no-more-atom-master-builds
Stop uploading to atom-master-builds
2014-04-30 09:35:41 -07:00
Kevin Sawicki 868cbb680c Stop uploading to atom-master-builds
Packages using Travis now build against a release build
2014-04-30 09:29:05 -07:00
Kevin Sawicki 98d2aaf10e Upgrade to language-java@0.10.0 2014-04-30 09:17:00 -07:00
Kevin Sawicki f7dead17c0 Upgrade to markdown-preview@0.66.0 2014-04-30 09:09:15 -07:00
Cheng Zhao f3168b2672 Use "closed" event instead of "destroyed".
The meaning of "destroyed" event has changed since atom-shell v0.12.0,
fixes #1910.
2014-04-30 12:25:59 +08:00
Corey Johnson e8c62b501f Fix workspaceView spec 2014-04-29 16:59:15 -07:00
Nathan Sobo 6ff2b2a01e Fix undefined variables in tokenized-line-spec 2014-04-29 17:24:16 -06:00
Kevin Sawicki 960285a270 Unfocus EditorComponent spec 2014-04-29 16:11:20 -07:00
Kevin Sawicki 17cd979299 Upgrade to apm@0.45.0 2014-04-29 15:32:00 -07:00
Kevin Sawicki b5846f9755 Upgrade to atom-keymap@0.19.0
Closes #1908
2014-04-29 09:01:54 -07:00
Kevin Sawicki dd39ffdf3b Upgrade to settings-view@0.112.0 2014-04-29 08:25:04 -07:00
Cheng Zhao 368b871270 Merge pull request #1907 from atom/atom-shell-v0.12.0
Upgrade to atom-shell@0.12.0
2014-04-29 15:49:45 +08:00
Cheng Zhao 9c06b4d344 Some events of browser-window have changed. 2014-04-29 15:25:36 +08:00
Cheng Zhao f48241bc5e Use new IPC API of atom-shell. 2014-04-29 15:16:27 +08:00
Cheng Zhao a7b94e1709 Upgrade to atom-shell@0.12.0 2014-04-29 15:09:47 +08:00
probablycorey 3d2dedb49f Update the readme 2014-04-28 14:42:31 -07:00
probablycorey dd5ab8098e Use consistent version pattern
Use `^Z` `^Z.Z` or `^Z.Z.Z`
2014-04-28 14:27:11 -07:00
Kevin Sawicki f5b833c49c Upgrade to apm 0.43.0 2014-04-28 14:06:32 -07:00
Kevin Sawicki ba032be402 Upgrade to apm@0.42.0 2014-04-28 13:20:14 -07:00
Kevin Sawicki a96a448063 Upgrade to language-go@0.10.0 2014-04-28 10:52:12 -07:00
Kevin Sawicki faeed9f604 Upgrade to snippets@0.43.0 2014-04-25 14:57:07 -07:00
probablycorey 0a8f2422d3 Use public grunt-download-atom-shell 2014-04-24 17:37:24 -07:00
Kevin Sawicki 24dbe19a82 Upgrade to language-c@0.15.0 2014-04-24 16:45:44 -07:00
Kevin Sawicki 7d8901072c Upgrade to snippets@0.42.0 2014-04-24 16:23:23 -07:00
Kevin Sawicki 848a4e2052 Merge pull request #1904 from atom/ks-remove-apm-submodule
Remove apm submodule
2014-04-24 16:21:49 -07:00
Kevin Sawicki e8090b16f3 Move apm version to apm/package.json 2014-04-24 15:43:35 -07:00
Kevin Sawicki 950964eee3 Remove directory that no longer exists 2014-04-24 15:43:35 -07:00
Kevin Sawicki b403f76d81 Remove .gitmodules 2014-04-24 15:43:35 -07:00
Kevin Sawicki 8f2cdae0eb Install apm from npmjs.org 2014-04-24 15:43:35 -07:00
Corey Johnson fa4b3c8dea Merge pull request #1903 from atom/cj-add-deprecation-warning-to-specs
Remove all deprecated calls from core
2014-04-24 15:36:53 -07:00
Kevin Sawicki e76bbc0f13 Guard against deleted submodule 2014-04-24 15:12:08 -07:00
Corey Johnson c9a377d4ac Deprecate reopenItemSync 2014-04-24 14:28:09 -07:00
Corey Johnson c7e308bca0 Remove use of OpenSync from specs 2014-04-24 14:14:10 -07:00
Corey Johnson 5193e6e46b Upgrade to text-buffer@2.2.0 2014-04-24 14:13:57 -07:00
Kevin Sawicki 66628e8c52 Update broken link to publish doc 2014-04-24 13:56:14 -07:00
Corey Johnson bec65cf2ac Only fail on deprecations when core specs are run 2014-04-24 13:47:01 -07:00
Corey Johnson 606b249430 Upgrade to grim@0.10.0 2014-04-24 13:34:56 -07:00
Kevin Sawicki 8bc1b7e955 Prepare 0.93.0 release 2014-04-24 12:07:35 -07:00
Corey Johnson c03dec2783 Merge remote-tracking branch 'origin/master' into cj-add-deprecation-warning-to-specs 2014-04-23 16:51:14 -07:00
Corey Johnson 9d92a27ccf Remove deprecated method calls from project spec 2014-04-23 16:50:25 -07:00
Corey Johnson b652dc8fd8 Use workspace.open instead of project.open 2014-04-23 16:36:44 -07:00
Corey Johnson c1929540a3 Remove deprecated calls in pane view spec 2014-04-23 16:35:51 -07:00
Corey Johnson 1601423f30 Update deprecated calls in language mode spec 2014-04-23 16:31:00 -07:00
Corey Johnson 1de2c14e50 Use TextBuffer::getEndPosition 2014-04-23 16:30:38 -07:00
Corey Johnson c1907054b7 Remove deprecated methods from display buffer spec 2014-04-23 16:24:10 -07:00
Corey Johnson 5f524c1181 Remove deprecated calls from git spec 2014-04-23 16:22:44 -07:00
Corey Johnson b897603b66 Remove deprecated option from selection spec 2014-04-23 16:22:34 -07:00
Corey Johnson 0e5c530006 Remove rogue focused spec 2014-04-23 16:19:43 -07:00
Corey Johnson 4a60b5787a Remove deprecated calls from editor view spec 2014-04-23 16:18:48 -07:00
Corey Johnson 88cc69f87a Update enableKeymap spec helper 2014-04-23 16:18:36 -07:00
Corey Johnson 42e91defb9 Rename getEofPosition to getEndPosition 2014-04-23 16:06:32 -07:00
Kevin Sawicki 832cc40a7f Add .md extension 2014-04-23 15:36:57 -07:00
Corey Johnson d89b4534f1 Update the year 2014-04-23 15:35:33 -07:00
Corey Johnson 725f6f7cf2 Use MIT license 2014-04-23 15:34:29 -07:00
Corey Johnson 38c25feee0 Remove deprecated calls to editor spec 2014-04-23 11:27:23 -07:00
Corey Johnson a15bb260c0 Update call to TextBuffer::rangeForRow 2014-04-22 17:52:07 -07:00
Corey Johnson 6b833043db Removed references to the isReversed option 2014-04-22 17:51:44 -07:00
Corey Johnson b30a2c9442 Remove deprecated calls from workspace view spec 2014-04-22 16:51:50 -07:00
Corey Johnson 3eb99c9391 Remove deprecated call from spec helper 2014-04-22 16:51:38 -07:00
Corey Johnson 10636b96bc buildBufferSync can't be deprecated because TokenizedBuffer uses it 2014-04-22 16:48:01 -07:00
Corey Johnson b5ac7c89a3 Update spec to match its description 2014-04-22 16:47:17 -07:00
Corey Johnson 01298bb470 Fix deprecation message 2014-04-22 16:22:23 -07:00
Corey Johnson 3bd7bfcbf1 Merge remote-tracking branch 'origin/master' into cj-add-deprecation-warning-to-specs 2014-04-22 16:06:04 -07:00
Corey Johnson 3e94c0be22 Remove deprecated methods from window spec 2014-04-22 14:19:13 -07:00
Corey Johnson db0cce6234 Remove focused spec 2014-04-22 14:19:01 -07:00
Corey Johnson f3d4cbbd8f Remove unnecessary fat arrows 2014-04-22 14:15:56 -07:00
Corey Johnson 81df4ed238 Change Workspace::reopenItemSync to use promises 2014-04-22 14:15:07 -07:00
Corey Johnson 7b756ec3f3 Remove calls to openSync from the workspace-spec 2014-04-22 11:24:27 -07:00
Corey Johnson 0d95718d1f Remove focused spec 2014-04-22 11:04:14 -07:00
Corey Johnson 1da23e8d04 Remove deprecations from atom-spec 2014-04-22 11:01:21 -07:00
Corey Johnson 43792d019a Output deprecation message 2014-04-22 11:01:05 -07:00
Corey Johnson ec0b4a2dc6 Move deprecation output to its own function 2014-04-22 10:44:25 -07:00
Corey Johnson 1083136dec Don't allow specs that call deprecated methods to pass 2014-04-22 10:11:52 -07:00
110 arquivos alterados com 3213 adições e 1677 exclusões
+1 -1
Ver Arquivo
@@ -1,6 +1,7 @@
*.swp
*~
.DS_Store
Thumbs.db
.project
.svn
.nvm-version
@@ -12,4 +13,3 @@ debug.log
docs/output
docs/includes
spec/fixtures/evil-files/
/apm
-3
Ver Arquivo
@@ -1,3 +0,0 @@
[submodule "vendor/apm"]
path = vendor/apm
url = https://github.com/atom/apm.git
+69 -46
Ver Arquivo
@@ -1,77 +1,100 @@
# :tada: Contributing to Atom :tada:
These are just guidelines, not rules, use your best judgement and feel free
to propose changes to this document in a pull request.
The following is a set of guidelines for contributing to Atom and its packages,
which are hosted in the [Atom Organization](https://github.com/atom) on GitHub.
If you're unsure which package is causing your problem or if you're having an
issue with Atom core, please use the feedback form in the application or email
[atom@github.com](mailto:atom@github.com). These are just guidelines, not rules,
use your best judgement and feel free to propose changes to this document in a
pull request.
## Issues
* Include screenshots and animated GIFs whenever possible, they are immensely
helpful.
* Include the behavior you expected to happen and other places you've seen
that behavior such as Emacs, vi, Xcode, etc.
* Check the Console app for stack traces to include if reporting a crash.
* Check the Dev tools (`alt-cmd-i`) for errors and stack traces to include.
## Submitting Issues
* Include screenshots and animated GIFs whenever possible; they are immensely
helpful.
* Include the behavior you expected and other places you've seen that behavior
such as Emacs, vi, Xcode, etc.
* Check the dev tools (`alt-cmd-i`) for errors and stack traces to include.
* On Mac, check Console.app for stack traces to include if reporting a crash.
* Perform a cursory search to see if a similar issue has already been submitted.
### Package Repositories
This is the repository for the core Atom editor only. Atom comes bundled with
many packages and themes that are stored in other repos under the
[atom organization](https://github.com/atom) such as [tabs](https://github.com/atom/tabs),
[Atom organization](https://github.com/atom) such as
[tabs](https://github.com/atom/tabs),
[find-and-replace](https://github.com/atom/find-and-replace),
[language-javascript](https://github.com/atom/language-javascript),
and [atom-light-ui](http://github.com/atom/atom-light-ui).
[language-javascript](https://github.com/atom/language-javascript), and
[atom-light-ui](http://github.com/atom/atom-light-ui).
If you think you know which package is causing the issue you are reporting, feel
free to open up the issue in that specific repository instead. When in doubt
just open the issue here but be aware that it may get closed here and reopened
in the proper package's repository.
For more information on how to work with Atom's official packages, see
[Contributing to Atom Packages](https://atom.io/docs/latest/contributing-to-packages.html)
## Pull Requests
* Include screenshots and animated GIFs whenever possible.
* Follow the [CoffeeScript](#coffeescript-styleguide),
[JavaScript](https://github.com/styleguide/javascript),
and [CSS](https://github.com/styleguide/css) styleguides
* Include thoughtfully worded [Jasmine](http://pivotal.github.com/jasmine)
specs
* Avoid placing files in `vendor`. 3rd-party packages should be added as a
`package.json` dependency.
* Files end with a newline.
* Requires should be in the following order:
* Include screenshots and animated GIFs in your pull request whenever possible.
* Follow the [CoffeeScript](#coffeescript-styleguide),
[JavaScript](https://github.com/styleguide/javascript),
and [CSS](https://github.com/styleguide/css) styleguides.
* Include thoughtfully-worded, well-structured
[Jasmine](http://jasmine.github.io/) specs.
* Document new code based on the
[Documentation Styleguide](#documentation-styleguide)
* End files with a newline.
* Place requires in the following order:
* Built in Node Modules (such as `path`)
* Built in Atom and Atom Shell Modules (such as `atom`, `shell`)
* Local Modules (using relative paths)
* Class variables and methods should be in the following order:
* Class methods (methods starting with a `@`)
* Instance methods
* Beware of platform differences
* Place class properties in the following order:
* Class methods and properties (methods starting with a `@`)
* Instance methods and properties
* Avoid platform-dependent code:
* Use `require('atom').fs.getHomeDirectory()` to get the home directory.
* Use `path.join()` to concatenate filenames.
* Temporary directory is not `/tmp` on Windows, use `os.tmpdir()` when
possible
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
temporary directory.
## Git Commit Messages
* Use the present tense
* Reference issues and pull requests liberally
* Consider starting the commit message with an applicable emoji:
* :lipstick: when improving the format/structure of the code
* :racehorse: when improving performance
* :non-potable_water: when plugging memory leaks
* :memo: when writing docs
* :penguin: when fixing something on Linux
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Reference issues and pull requests liberally
* Consider starting the commit message with an applicable emoji:
* :lipstick: `:lipstick:` when improving the format/structure of the code
* :racehorse: `:racehorse:` when improving performance
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
* :memo: `:memo:` when writing docs
* :penguin: `:penguin:` when fixing something on Linux
* :apple: `:apple:` when fixing something on Mac OS
* :bug: `:bug:` when fixing a bug
* :fire: `:fire:` when removing code or files
* :green_heart: `:green_heart:` when fixing the CI build
* :white_check_mark: `:white_check_mark:` when adding tests
* :lock: `:lock:` when dealing with security
## CoffeeScript Styleguide
* Set parameter defaults without spaces around the equal sign
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
* Use parentheses if it improves code clarity.
* Prefer alphabetic keywords to symbolic keywords:
* `a is b` instead of `a == b`
* Avoid spaces inside the curly-braces of hash literals:
* `{a: 1, b: 2}` instead of `{ a: 1, b: 2 }`
* Include a single line of whitespace between methods.
## Documentation Styleguide
* Use [TomDoc](http://tomdoc.org).
* Use [Markdown](https://daringfireball.net/projects/markdown).
* Reference classes with `{ClassName}`.
* Reference instance methods with `{ClassName::methodName}`.
* Reference class methods with `{ClassName.methodName}`.
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
style notation.
* Reference methods and classes in markdown with the custom `{}` notation:
* Reference classes with `{ClassName}`
* Reference instance methods with `{ClassName::methodName}`
* Reference class methods with `{ClassName.methodName}`
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
style notation.
### Example
-1
Ver Arquivo
@@ -1 +0,0 @@
Copyright 2014 GitHub, Inc.
+20
Ver Arquivo
@@ -0,0 +1,20 @@
Copyright (c) 2014 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+9 -5
Ver Arquivo
@@ -1,8 +1,8 @@
# Atom — The hackable editor
![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png)
![Atom](http://i.imgur.com/OrTvUAD.png)
Atom is a hackable text editor for the 21st century, built on [atom-shell](http://github.com/atom/atom-shell), and based on everything we love about our favorite editors. We designed it to be deeply customizable, but still approachable using the default configuration.
Check out our [guides and API documentation](https://atom.io/docs/latest).
Visit [atom.io](https://atom.io) to learn more.
## Installing
@@ -12,6 +12,10 @@ Atom will automatically update when a new release is available.
## Building
Follow the instructions in the [build docs][building].
* [Linux](docs/build-instructions/linux.md)
* [OS X](docs/build-instructions/os-x.md)
* [FreeBSD](docs/build-instructions/freebsd.md)
* [Windows](docs/build-instructions/windows.md)
[building]: https://github.com/atom/atom/blob/master/docs/building-atom.md
## Developing
Check out the [guides](https://atom.io/docs/latest) and the [API reference](https://atom.io/docs/api).
+2
Ver Arquivo
@@ -0,0 +1,2 @@
This folder is where [apm](https://github.com/atom/apm) is installed to so that
it is bundled with Atom.
+11
Ver Arquivo
@@ -0,0 +1,11 @@
{
"name": "atom-bundled-apm",
"description": "Atom's bundled APM",
"repository": {
"type": "git",
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "0.57.0"
}
}
+17 -9
Ver Arquivo
@@ -1,17 +1,17 @@
#!/bin/bash
if [ "`uname`" == 'Darwin' ]; then
if [ "$(uname)" == 'Darwin' ]; then
OS='Mac'
elif [ "`expr substr $(uname -s) 1 5`" == 'Linux' ]; then
elif [ "$(expr substr $(uname -s) 1 5)" == 'Linux' ]; then
OS='Linux'
elif [ "`expr substr $(uname -s) 1 10`" == 'MINGW32_NT' ]; then
elif [ "$(expr substr $(uname -s) 1 10)" == 'MINGW32_NT' ]; then
OS='Cygwin'
else
echo "Your platform (`uname -a`) is not supported."
echo "Your platform ($(uname -a)) is not supported."
exit 1
fi
while getopts ":wtfvhs-:" opt; do
while getopts ":wtfvh-:" opt; do
case "$opt" in
-)
case "${OPTARG}" in
@@ -66,17 +66,25 @@ if [ $OS == 'Mac' ]; then
open -a "$ATOM_PATH/$ATOM_APP_NAME" -n --args --executed-from="$(pwd)" --pid=$$ "$@"
fi
elif [ $OS == 'Linux' ]; then
SCRIPT=`readlink -f "$0"`
USR_DIRECTORY=`readlink -f $(dirname $SCRIPT)/..`
SCRIPT=$(readlink -f "$0")
USR_DIRECTORY=$(readlink -f $(dirname $SCRIPT)/..)
ATOM_PATH="$USR_DIRECTORY/share/atom/atom"
[ -x "$ATOM_PATH" ] || ATOM_PATH='/tmp/atom-build/Atom/atom'
: ${TMPDIR:=/tmp}
[ -x "$ATOM_PATH" ] || ATOM_PATH="$TMPDIR/atom-build/Atom/atom"
if [ $EXPECT_OUTPUT ]; then
"$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@"
exit $?
else
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > /dev/null 2>&1 &
(
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$TMPDIR/atom-nohup.out" 2>&1
if [ $? -ne 0 ]; then
cat "$TMPDIR/atom-nohup.out"
exit $?
fi
) &
fi
fi
+6 -18
Ver Arquivo
@@ -36,35 +36,23 @@ module.exports = (grunt) ->
grunt.log.write = (args...) -> grunt.log
[major, minor, patch] = packageJson.version.split('.')
tmpDir = os.tmpdir()
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
shellAppDir = path.join(buildDir, appName)
if process.platform is 'win32'
appName = 'Atom'
tmpDir = os.tmpdir()
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
shellAppDir = path.join(buildDir, appName)
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
installDir = path.join(process.env.ProgramFiles, appName)
else if process.platform is 'darwin'
appName = 'Atom.app'
tmpDir = '/tmp'
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
shellAppDir = path.join(buildDir, appName)
contentsDir = path.join(shellAppDir, 'Contents')
appDir = path.join(contentsDir, 'Resources', 'app')
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
installDir = path.join('/Applications', appName)
else
appName = 'Atom'
tmpDir = '/tmp'
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
shellAppDir = path.join(buildDir, appName)
contentsDir = shellAppDir
appDir = path.join(shellAppDir, 'resources', 'app')
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
installDir = process.env.INSTALL_PREFIX ? '/usr/local'
coffeeConfig =
+3 -1
Ver Arquivo
@@ -18,7 +18,7 @@
"grunt-contrib-coffee": "~0.9.0",
"grunt-contrib-less": "~0.8.0",
"grunt-cson": "0.8.0",
"grunt-download-atom-shell": "git+https://atom-bot:467bac80a0017b96fb5be5cfc686f5e0cc607b10@github.com/atom/grunt-download-atom-shell#v0.6.1",
"grunt-download-atom-shell": "~0.7.2",
"grunt-lesslint": "0.13.0",
"grunt-markdown": "~0.4.0",
"grunt-peg": "~1.1.0",
@@ -27,6 +27,8 @@
"json-front-matter": "~0.1.3",
"legal-eagle": "~0.4.0",
"minidump": "0.5.x",
"read-package-json": "1.1.8",
"normalize-package-data": "0.2.12",
"rcedit": "~0.1.2",
"request": "~2.27.0",
"rimraf": "~2.2.2",
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ module.exports = (grunt) ->
{rm} = require('./task-helpers')(grunt)
grunt.registerTask 'partial-clean', 'Delete some of the build files', ->
tmpdir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
tmpdir = os.tmpdir()
rm grunt.config.get('atom.buildDir')
rm require('../src/coffee-cache').cacheDir
+1 -1
Ver Arquivo
@@ -143,7 +143,7 @@ downloadFileFromRepo = ({repo, file}, callback) ->
downloadIncludes = (callback) ->
includes = [
{repo: 'atom-keymap', file: 'src/keymap.coffee'}
{repo: 'atom-keymap', file: 'src/keymap-manager.coffee'}
{repo: 'atom-keymap', file: 'src/key-binding.coffee'}
{repo: 'first-mate', file: 'src/grammar.coffee'}
{repo: 'first-mate', file: 'src/grammar-registry.coffee'}
+2 -2
Ver Arquivo
@@ -17,7 +17,7 @@ module.exports = (grunt) ->
licenseText = getLicenseText(dependencyLicenses)
if mode is 'save'
targetPath = path.join(grunt.config.get('atom.appDir'), 'LICENSE')
targetPath = path.join(grunt.config.get('atom.appDir'), 'LICENSE.md')
fs.writeFileSync(targetPath, licenseText)
else
console.log licenseText
@@ -26,7 +26,7 @@ module.exports = (grunt) ->
getLicenseText = (dependencyLicenses) ->
{keys} = require 'underscore-plus'
text = """
Copyright 2014 GitHub, Inc.
#{fs.readFileSync('LICENSE.md', 'utf8')}
This application bundles the following third-party packages in accordance
with the following licenses:\n\n
+5 -74
Ver Arquivo
@@ -29,21 +29,14 @@ module.exports = (gruntObject) ->
done = @async()
buildDir = grunt.config.get('atom.buildDir')
createBuildRelease (error, release) ->
zipApps buildDir, assets, (error) ->
return done(error) if error?
zipApps buildDir, assets, (error) ->
getAtomDraftRelease (error, release) ->
return done(error) if error?
uploadAssets release, buildDir, assets, (error) ->
assetNames = (asset.assetName for asset in assets)
deleteExistingAssets release, assetNames, (error) ->
return done(error) if error?
publishRelease release, (error) ->
return done(error) if error?
getAtomDraftRelease (error, release) ->
return done(error) if error?
assetNames = (asset.assetName for asset in assets)
deleteExistingAssets release, assetNames, (error) ->
return done(error) if error?
uploadAssets(release, buildDir, assets, done)
uploadAssets(release, buildDir, assets, done)
logError = (message, error, details) ->
grunt.log.error(message)
@@ -64,25 +57,6 @@ zipApps = (buildDir, assets, callback) ->
tasks.push(zip.bind(this, buildDir, sourceName, assetName))
async.parallel(tasks, callback)
getRelease = (callback) ->
options =
uri: 'https://api.github.com/repos/atom/atom-master-builds/releases'
method: 'GET'
headers: defaultHeaders
json: true
request options, (error, response, releases=[]) ->
if error? or response.statusCode isnt 200
logError('Fetching releases failed', error, releases)
callback(error ? new Error(response.statusCode))
else
if releases.length > maxReleases
deleteRelease(release) for release in releases[maxReleases..]
for release in releases when release.name is commitSha
callback(null, release)
return
callback()
getAtomDraftRelease = (callback) ->
atomRepo = new GitHub({repo: 'atom/atom', token})
atomRepo.getReleases (error, releases=[]) ->
@@ -125,35 +99,6 @@ deleteExistingAssets = (release, assetNames, callback) ->
tasks.push(deleteAsset.bind(this, asset.url))
async.parallel(tasks, callback)
createBuildRelease = (callback) ->
getRelease (error, release) ->
if error?
callback(error)
return
if release?
deleteExistingAssets release, (error) ->
callback(error, release)
return
options =
uri: 'https://api.github.com/repos/atom/atom-master-builds/releases'
method: 'POST'
headers: defaultHeaders
json:
tag_name: "v#{commitSha}"
target_commitish: 'master'
name: commitSha
body: "Build of [atom@#{commitSha.substring(0, 7)}](https://github.com/atom/atom/commits/#{commitSha})"
draft: true
prerelease: true
request options, (error, response, release={}) ->
if error? or response.statusCode isnt 201
logError('Creating release failed', error, release)
callback(error ? new Error(response.statusCode))
else
callback(null, release)
uploadAssets = (release, buildDir, assets, callback) ->
upload = (release, assetName, assetPath, callback) ->
options =
@@ -178,17 +123,3 @@ uploadAssets = (release, buildDir, assets, callback) ->
assetPath = path.join(buildDir, assetName)
tasks.push(upload.bind(this, release, assetName, assetPath))
async.parallel(tasks, callback)
publishRelease = (release, callback) ->
options =
uri: release.url
method: 'POST'
headers: defaultHeaders
json:
draft: false
request options, (error, response, body={}) ->
if error? or response.statusCode isnt 200
logError('Creating release failed', error, body)
callback(error ? new Error(response.statusCode))
else
callback()
-108
Ver Arquivo
@@ -1,108 +0,0 @@
async = require 'async'
request = require 'request'
# Configure and publish all packages in package.json to atom.io
#
# This task should be run whenever you want to be sure that atom.io contains
# all the packages and versions referenced in Atom's package.json file.
module.exports = (grunt) ->
{spawn} = require('./task-helpers')(grunt)
baseUrl = "https://atom.io/api/packages"
packageExists = (packageName, token, callback) ->
requestSettings =
url: "#{baseUrl}/#{packageName}"
json: true
headers:
authorization: token
request.get requestSettings, (error, response, body={}) ->
if error?
callback(error)
else
callback(null, response.statusCode is 404)
createPackage = (packageName, token, callback) ->
requestSettings =
url: baseUrl
json: true
headers:
authorization: token
method: 'POST'
body:
repository: "atom/#{packageName}"
request.get requestSettings, (error, response, body={}) ->
if error?
callback(error)
else if response.statusCode isnt 201
message = body.message ? body.error ? body
callback(new Error("Creating package failed: #{message}"))
else
callback()
createPackageVersion = (packageName, tag, token, callback) ->
requestSettings =
url: "#{baseUrl}/#{packageName}/versions"
json: true
method: 'POST'
headers:
authorization: token
body:
tag: tag
request.get requestSettings, (error, response, body={}) ->
if error?
callback(error)
else if response.statusCode isnt 201
message = body.message ? body.error ? body
if message is 'Version exists'
callback()
else
callback(new Error("Creating new version failed: #{message}"))
else
callback()
getToken = (callback) ->
if token = process.env.ATOM_ACCESS_TOKEN
callback(null, token)
else
spawn {cmd: 'security', args: ['-q', 'find-generic-password', '-ws', 'GitHub API Token']}, (error, result, code) ->
token = result.toString() unless error?
callback(error, token)
grunt.registerTask 'publish-packages', 'Publish all bundled packages', ->
done = @async()
getToken (error, token) ->
unless token
grunt.log.error('Token not found in keychain or ATOM_ACCESS_TOKEN environment variable')
done(false)
{packageDependencies} = grunt.file.readJSON('package.json') ? {}
tasks = []
for name, version of packageDependencies
do (name, version) ->
tasks.push (callback) ->
grunt.verbose.writeln("Publishing #{name}@#{version}")
tag = "v#{version}"
packageExists name, token, (error, exists) ->
if error?
callback(error)
return
if exists
createPackage name, token, (error) ->
if error?
callback(error)
else
createPackageVersion(name, tag, token, callback)
else
createPackageVersion(name, tag, token, callback)
async.waterfall tasks, (error) ->
if error?
grunt.log.error(error.message)
done(false)
else
done()
+7 -3
Ver Arquivo
@@ -5,14 +5,18 @@ module.exports = (grunt) ->
{spawn} = require('./task-helpers')(grunt)
getVersion = (callback) ->
if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
{version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json'))
onBuildMachine = process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
inRepository = fs.existsSync(path.resolve(__dirname, '..', '..', '.git'))
{version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json'))
if onBuildMachine or not inRepository
callback(null, version)
else
cmd = 'git'
args = ['rev-parse', '--short', 'HEAD']
spawn {cmd, args}, (error, {stdout}={}, code) ->
callback(error, stdout?.trim?())
commitHash = stdout?.trim?()
combinedVersion = "#{version}-#{commitHash}"
callback(error, combinedVersion)
grunt.registerTask 'set-version', 'Set the version in the plist and package.json', ->
done = @async()
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
# Welcome to the Atom API Documentation
![Atom](http://i.imgur.com/OrTvUAD.png)
![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png)
## FAQ
+3 -3
Ver Arquivo
@@ -10,8 +10,8 @@ keystrokes pass through elements with the class `.editor`:
```coffee
'.editor':
'cmd-delete': 'editor:backspace-to-beginning-of-line'
'alt-backspace': 'editor:backspace-to-beginning-of-word'
'cmd-delete': 'editor:delete-to-beginning-of-line'
'alt-backspace': 'editor:delete-to-beginning-of-word'
'ctrl-A': 'editor:select-to-first-character-of-line'
'ctrl-shift-e': 'editor:select-to-end-of-line'
'cmd-left': 'editor:move-to-first-character-of-line'
@@ -24,7 +24,7 @@ keystrokes pass through elements with the class `.editor`:
Beneath the first selector are several bindings, mapping specific *keystroke
patterns* to *commands*. When an element with the `.editor` class is focused and
`cmd-delete` is pressed, an custom DOM event called
`editor:backspace-to-beginning-of-line` is emitted on the `.editor` element.
`editor:delete-to-beginning-of-line` is emitted on the `.editor` element.
The second selector group also targets editors, but only if they don't have the
`.mini` class. In this example, the commands for code folding don't really make
+24
Ver Arquivo
@@ -0,0 +1,24 @@
## Developing Node Modules
Atom contains a number of packages that are Node modules instead of Atom packages. If you want to
make changes to the Node modules, for instance `atom-keymap`, you have to link them into the
development environment differently than you would a normal Atom package.
### Linking a Node Module Into Your Atom Dev Environment
Here are the steps to run a local version of a node module *not an apm* within Atom. We're using
`atom-keymap` as an example:
```bash
$ git clone https://github.com/atom/atom-keymap.git
$ cd atom-keymap
$ npm install
$ npm link
$ apm rebuild # This is the special step, it makes the npm work with Atom's version of Node
$ cd WHERE-YOU-CLONED-ATOM
$ npm link atom-keymap
$ atom # Should work!
```
After this, you'll have to `npm install` and `apm rebuild` when you make a change to the node
module's code.
+22
Ver Arquivo
@@ -0,0 +1,22 @@
# FreeBSD
FreeBSD -RELEASE 64-bit is the recommended platform.
## Requirements
* FreeBSD
* `pkg install node`
* `pkg install npm`
* `pkg install libgnome-keyring`
* `npm config set python /usr/local/bin/python2 -g` to ensure that gyp uses Python 2
## Instructions
```sh
git clone https://github.com/atom/atom
cd atom
script/build # Creates application at $TMPDIR/atom-build/Atom
sudo script/grunt install # Installs command to /usr/local/bin/atom
```
## Troubleshooting
+49
Ver Arquivo
@@ -0,0 +1,49 @@
# Linux
Ubuntu LTS 12.04 64-bit is the recommended platform.
## Requirements
* OS with 64-bit architecture
* [node.js](http://nodejs.org/download/) v0.10.x
* [npm](http://www.npmjs.org/) v1.4.x
* libgnome-keyring-dev `sudo apt-get install libgnome-keyring-dev` (refer to your distribution's manual on how to install packages if you are not on Debian or Ubuntu-based systems)
* `npm config set python /usr/bin/python2 -g` to ensure that gyp uses Python 2
## Instructions
```sh
git clone https://github.com/atom/atom
cd atom
script/build # Creates application at $TMPDIR/atom-build/Atom
sudo script/grunt install # Installs command to /usr/local/bin/atom
script/grunt mkdeb # Generates a .deb package at $TMPDIR/atom-build
```
## Troubleshooting
### Exception: "TypeError: Unable to watch path"
If you get following error with a big traceback right after Atom starts:
```
TypeError: Unable to watch path
```
you have to increase number of watched files by inotify. For testing if
this is the reason for this error you can issue
```sh
sudo sysctl fs.inotify.max_user_watches=32768
```
and restart Atom. If Atom now works fine, you can make this setting permanent:
```sh
echo 32768 > /proc/sys/fs/inotify/max_user_watches
```
See also https://github.com/atom/atom/issues/2082.
+17
Ver Arquivo
@@ -0,0 +1,17 @@
# OS X
## Requirements
* OS X 10.8 or later
* [node.js](http://nodejs.org/download/) v0.10.x
* Command Line Tools for [Xcode](https://developer.apple.com/xcode/downloads/) (run `xcode-select --install` to install)
## Instructions
```sh
git clone https://github.com/atom/atom
cd atom
script/build # Creates application at /Applications/Atom.app
```
## Troubleshooting
+35
Ver Arquivo
@@ -0,0 +1,35 @@
# Windows
## Requirements
* Windows 7 or later
* [Visual C++ 2010 Express](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs#DownloadFamilies_4) with [SP1](http://www.microsoft.com/en-us/download/details.aspx?id=23691)
* [node.js](http://nodejs.org/download/) v0.10.x
* [Python](http://www.python.org/download/) v2.7.x
* [GitHub for Windows](http://windows.github.com/)
## Instructions
```bat
# Use the `Git Shell` app which was installed by GitHub for Windows. Also Make
# sure you have logged into the GitHub for Windows GUI App.
cd C:\
git clone https://github.com/atom/atom/
cd atom
script\build
```
## Why do I have to use GitHub for Windows?
You don't, You can use your existing Git! GitHub for Windows's Git Shell is just
easier to set up. You need to have Posix tools in your `%PATH%` (i.e. `grep`,
`sed`, et al.), which isn't the default configuration when you install Git. To
fix this, you probably need to fiddle with your system PATH.
## Troubleshooting
### Common Errors
* `node is not recognized`
* If you just installed node you need to restart your computer before node is
available on your Path.
+52
Ver Arquivo
@@ -0,0 +1,52 @@
# Contributing to Official Atom Packages
If you think you know which package is causing the issue you are reporting, feel
free to open up the issue in that specific repository instead. When in doubt
just open the issue here but be aware that it may get closed here and reopened
in the proper package's repository.
## Hacking on Packages
### Cloning
The first step is creating your own clone. You can of course do this manually
with git, or you can use the `apm develop` command to create a clone based on
the package's `repository` field in the `package.json`.
For example, if you want to make changes to the `tree-view` package, run the
following command:
```
> apm develop tree-view
Cloning https://github.com/atom/tree-view ✓
Installing modules ✓
~/.atom/dev/packages/tree-view -> ~/github/tree-view
```
This clones the `tree-view` repository to `~/github`. If you prefer a different
path, specify it via the `ATOM_REPOS_HOME` environment variable.
### Running in Development Mode
Editing a package in Atom is a bit of a circular experience: you're using Atom
to modify itself. What happens if you temporarily break something? You don't
want the version of Atom you're using to edit to become useless in the process.
For this reason, you'll only want to load packages in **development mode** while
you are working on them. You'll perform your editing in **stable mode**, only
switching to development mode to test your changes.
To open a development mode window, use the "Application: Open Dev" command,
which is normally bound to `cmd-shift-o`. You can also run dev mode from the
command line with `atom --dev`.
To load your package in development mode, create a symlink to it in
`~/.atom/dev/packages`. This occurs automatically when you clone the package
with `apm develop`. You can also run `apm link --dev` and `apm unlink --dev`
from the package directory to create and remove dev-mode symlinks.
### Installing Dependencies
Finally, you need to install the cloned package's dependencies by running
`apm install` within the package directory. This step is also performed
automatically the first time you run `apm develop`, but you'll want to keep
dependencies up to date by running `apm update` after pulling upstream changes.
-142
Ver Arquivo
@@ -1,142 +0,0 @@
# Contributing to Atom Packages
The following is a set of guidelines for contributing to Atom packages, which
are hosted in the [Atom Organization](https://github.com/atom) on GitHub. If
you're unsure which package is causing your problem or if you're having an issue
with Atom core, please use the feedback form in the application or email
[atom@github.com](mailto:atom@github.com).
## Submitting Issues
* Include screenshots and animated GIFs whenever possible; they are immensely
helpful.
* Include the behavior you expected and other places you've seen that behavior
such as Emacs, vi, Xcode, etc.
* Check the dev tools (`alt-cmd-i`) for errors and stack traces to include.
* Check Console.app for stack traces to include if reporting a crash.
* Perform a cursory search to see if a similar issue has already been submitted.
## Hacking on Packages
### Cloning
The first step is creating your own clone. You can of course do this manually
with git, or you can use the `apm develop` command to create a clone based on
the package's `repository` field in the `package.json`.
For example, if you want to make changes to the `tree-view` package, run the
following command:
```
> apm develop tree-view
Cloning https://github.com/atom/tree-view ✓
Installing modules ✓
~/.atom/dev/packages/tree-view -> ~/github/tree-view
```
This clones the `tree-view` repository to `~/github`. If you prefer a different
path, specify it via the `ATOM_REPOS_HOME` environment variable.
### Running in Development Mode
Editing a package in Atom is a bit of a circular experience: you're using Atom
to modify itself. What happens if you temporarily break something? You don't
want the version of Atom you're using to edit to become useless in the process.
For this reason, you'll only want to load packages in **development mode** while
you are working on them. You'll perform your editing in **stable mode**, only
switching to development mode to test your changes.
To open a development mode window, use the "Application: Open Dev" command,
which is normally bound to `cmd-shift-o`. You can also run dev mode from the
command line with `atom --dev`.
To load your package in development mode, create a symlink to it in
`~/.atom/dev/packages`. This occurs automatically when you clone the package
with `apm develop`. You can also run `apm link --dev` and `apm unlink --dev`
from the package directory to create and remove dev-mode symlinks.
### Installing Dependencies
Finally, you need to install the cloned package's dependencies by running
`apm install` within the package directory. This step is also performed
automatically the first time you run `apm develop`, but you'll want to keep
dependencies up to date by running `apm update` after pulling upstream changes.
## Submitting Pull Requests
### Code Guidelines
* Include screenshots and animated GIFs in your pull request whenever possible.
* Follow the [CoffeeScript](#coffeescript-styleguide),
[JavaScript](https://github.com/styleguide/javascript),
and [CSS](https://github.com/styleguide/css) styleguides.
* Include thoughtfully-worded, well-structured
[Jasmine](http://pivotal.github.com/jasmine) specs.
* Document new code based on the
[Documentation Styleguide](#documentation-styleguide)
* End files with a newline.
* Place requires in the following order:
* Built in Node Modules (such as `path`)
* Built in Atom and Atom Shell Modules (such as `atom`, `shell`)
* Local Modules (using relative paths)
* Place class properties in the following order:
* Class methods and properties (methods starting with a `@`)
* Instance methods and properties
* Avoid platform-dependent code:
* Use `require('atom').fs.getHomeDirectory()` to get the home directory.
* Use `path.join()` to concatenate filenames.
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
temporary directory.
### Commit Message Guidelines
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Reference issues and pull requests liberally
* Consider starting the commit message with an applicable emoji:
* :lipstick: when improving the format/structure of the code
* :racehorse: when improving performance
* :non-potable_water: when plugging memory leaks
* :memo: when writing docs
* :bulb: Check out the [Emoji Cheat Sheet](http://www.emoji-cheat-sheet.com)
for more ideas.
## CoffeeScript Styleguide
* Use parentheses if it improves code clarity.
* Prefer alphabetic keywords to symbolic keywords:
* `a is b` instead of `a == b`
* Avoid spaces inside the curly-braces of hash literals:
* `{a: 1, b: 2}` instead of `{ a: 1, b: 2 }`
* Set parameter defaults without spaces around the equal sign:
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
* Include a single line of whitespace between methods.
## Documentation Styleguide
* Use [TomDoc](http://tomdoc.org).
* Use [Markdown](https://daringfireball.net/projects/markdown).
* Reference methods and classes in markdown with the custom `{}` notation:
* Reference classes with `{ClassName}`
* Reference instance methods with `{ClassName::methodName}`
* Reference class methods with `{ClassName.methodName}`
### Example
```coffee
# Public: Disable the package with the given name.
#
# This method emits multiple events:
#
# * `package-will-be-disabled` - before the package is disabled.
# * `package-disabled` - after the package is disabled.
#
# name - The {String} name of the package to disable.
# options - The {Object} with disable options (default: {}):
# :trackTime - `true` to track the amount of time disabling took.
# :ignoreErrors - `true` to catch and ignore errors thrown.
# callback - The {Function} to call after the package has been disabled.
#
# Returns `undefined`.
disablePackage: (name, options, callback) ->
```
Link simbólico
+1
Ver Arquivo
@@ -0,0 +1 @@
../CONTRIBUTING.md
+2 -2
Ver Arquivo
@@ -20,7 +20,7 @@ apm help init
You should see a message print out with details about the `apm init` command.
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
to install the `apm` and `atom` commands.
### Convert the Package
@@ -49,4 +49,4 @@ the editor to see it in action!
[plist]: http://en.wikipedia.org/wiki/Property_list
[R]: http://en.wikipedia.org/wiki/R_(programming_language)
[TextMate]: http://macromates.com
[TextMateOrg]: https://github.com/textmate/r.tmbundle
[TextMateOrg]: https://github.com/textmate
+1 -1
Ver Arquivo
@@ -25,7 +25,7 @@ apm help init
You should see a message print out with details about the `apm init` command.
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
to install the `apm` and `atom` commands.
You can now run `apm help init` to see all the options for initializing new
+1 -1
Ver Arquivo
@@ -34,7 +34,7 @@ apm help install
You should see a message print out with details about the `apm install` command.
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
to install the `apm` and `atom` commands.
You can also install packages by using the `apm install` command:
+2
Ver Arquivo
@@ -5,6 +5,7 @@
* [Creating a Package](creating-a-package.md)
* [Creating a Theme](creating-a-theme.md)
* [Publishing a Package](publishing-a-package.md)
* [Writing Specs](writing-specs.md)
* [Converting a TextMate Bundle](converting-a-text-mate-bundle.md)
* [Converting a TextMate Theme](converting-a-text-mate-theme.md)
* [Contributing](contributing.md)
@@ -12,6 +13,7 @@
### Advanced Topics
* [Configuration](advanced/configuration.md)
* [Developing Node Modules](advanced/node-modules.md)
* [Keymaps](advanced/keymaps.md)
* [Serialization](advanced/serialization.md)
* [View System](advanced/view-system.md)
+5 -5
Ver Arquivo
@@ -7,7 +7,7 @@ Publishing a package allows other people to install it and use it in Atom. It
is a great way to share what you've made and get feedback and contributions from
others.
This guide assumes your package's name is `my-package` and but you should pick a
This guide assumes your package's name is `my-package` but you should pick a
better name.
### Install apm
@@ -24,7 +24,7 @@ apm help publish
You should see a message print out with details about the `apm publish` command.
If you do not, launch Atom and run the _Atom > Install Shell Commmands_ menu
If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
to install the `apm` and `atom` commands.
### Prepare Your Package
@@ -42,7 +42,7 @@ If not, there are a few things you should check before publishing:
* Your package is in a Git repository that has been pushed to
[GitHub][github]. Follow [this guide][repo-guide] if your package isn't
already on GitHub.
### Publish Your Package
Before you publish a package it is a good idea to check ahead of time if
@@ -59,7 +59,7 @@ Now let's review what the `apm publish` command does:
3. Creates a new [Git tag][git-tag] for the version being published.
4. Pushes the tag and current branch up to GitHub.
5. Updates atom.io with the new version being published.
Now run the following commands to publish your package:
```sh
@@ -80,7 +80,7 @@ digit of the version before publishing so the published version will be `0.1.0`
and the Git tag created will be `v0.1.0`.
In the future you can run `apm publish major` to publish the `1.0.0` version but
since this was the first version being published it is a good idead to start
since this was the first version being published it is a good idea to start
with a minor release.
### Further Reading
+61
Ver Arquivo
@@ -0,0 +1,61 @@
# Writting specs
Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec framework. Any new functionality should have specs to guard against regressions.
## Create a new spec
[Atom specs](https://github.com/atom/atom/tree/master/spec) and [package specs](https://github.com/atom/markdown-preview/tree/master/spec) are added to their respective `spec` directory. The example below creates a spec for Atom core.
0. Create a spec file
Spec files **must** end with `-spec` so add `sample-spec.coffee` to `atom/spec`.
0. Add one or more `describe` method
The `describe` method takes two arguments, a description and a function. If the description explains a behavior it typically begins with `when` if it is more like a unit test it begins with the method name.
```coffee
describe "when a test is written", ->
# contents
```
or
```coffee
describe "Editor::moveUp", ->
# contents
```
0. Add one or more `it` method
The `it` method also takes two arugments, a description and a function. Try and make the description flow with the `it` method. For example, a description of `this should work` doesn't read well as `it this should work`. But a description of `should work` sounds great as `it should work`.
```coffee
describe "when a test is written", ->
it "has some expectations that should pass", ->
# Expectations
```
0. Add one or more expectations
The best way to learn about expectations is to read the [jamsine documentation](http://jasmine.github.io/2.0/introduction.html#section-Expectations) about them. Below is a simple example.
```coffee
describe "when a test is written", ->
it "has some expectations that should pass", ->
expect("apples").toEqual("apples")
expect("oranges").not.toEqual("apples")
```
## Runnings specs
Most of the time you'll want to run specs by triggering the `window:run-package-specs` command. This command is not only to run package specs, it is also for Atom core specs. This will run all the specs in the current project's spec directory. If you want to run the Atom core specs and **all** the default package specs trigger the `window:run-all-specs` command.
To run a limited subset of specs use the `fdescribe` or `fit` methods. You can use those to focus a single spec or several specs. In the example above, focusing an individual spec looks like this:
```coffee
describe "when a test is written", ->
fit "has some expectations that should pass", ->
expect("apples").toEqual("apples")
expect("oranges").not.toEqual("apples")
```
+4 -2
Ver Arquivo
@@ -21,7 +21,7 @@ To begin, press `cmd-shift-P` to bring up the [Command
Palette](https://github.com/atom/command-palette). Type "generate package" and
select the "Package Generator: Generate Package" command. Now we need to name
the package. Try to avoid naming your package with the *atom-* prefix, for
example we are going to call this package _ascii-art_.
example we are going to call this package _ascii-art_.
Atom will open a new window with the contents of our new _ascii-art_ package
displayed in the Tree View. Because this window is opened **after** the package
@@ -149,8 +149,10 @@ ASCII art professional!
* [Getting your project on GitHub guide](http://guides.github.com/overviews/desktop)
* [Writing specs](writing-specs.md) for your package
* [Creating a package guide](creating-a-package.html) for more information
on the mechanics of packages
* [Publishing a package guide](publish-a-package.html) for more information
* [Publishing a package guide](publishing-a-package.html) for more information
on publishing your package to [atom.io](https://atom.io)
+5
Ver Arquivo
@@ -0,0 +1,5 @@
storage
compile-cache
dev
.npm
.node-gyp
-4
Ver Arquivo
@@ -1,9 +1,5 @@
'.editor':
# Platform Bindings
'alt-left': 'editor:move-to-beginning-of-word'
'alt-right': 'editor:move-to-end-of-word'
'alt-shift-left': 'editor:select-to-beginning-of-word'
'alt-shift-right': 'editor:select-to-end-of-word'
'home': 'editor:move-to-first-character-of-line'
'end': 'editor:move-to-end-of-screen-line'
'shift-home': 'editor:select-to-first-character-of-line'
+12 -4
Ver Arquivo
@@ -65,6 +65,8 @@
'cmd-}': 'pane:show-next-item'
'cmd-alt-left': 'pane:show-previous-item'
'cmd-alt-right': 'pane:show-next-item'
'ctrl-tab': 'pane:show-next-item'
'ctrl-shift-tab': 'pane:show-previous-item'
'cmd-=': 'window:increase-font-size'
'cmd-+': 'window:increase-font-size'
'cmd--': 'window:decrease-font-size'
@@ -94,17 +96,23 @@
'cmd-9': 'pane:show-item-9'
'.editor':
# Platform Bindings
'alt-left': 'editor:move-to-beginning-of-word'
'alt-right': 'editor:move-to-end-of-word'
'alt-shift-left': 'editor:select-to-beginning-of-word'
'alt-shift-right': 'editor:select-to-end-of-word'
# Apple Specific
'cmd-backspace': 'editor:backspace-to-beginning-of-line'
'cmd-shift-backspace': 'editor:backspace-to-beginning-of-line'
'cmd-delete': 'editor:backspace-to-beginning-of-line'
'cmd-backspace': 'editor:delete-to-beginning-of-line'
'cmd-shift-backspace': 'editor:delete-to-beginning-of-line'
'cmd-delete': 'editor:delete-to-beginning-of-line'
'ctrl-A': 'editor:select-to-first-character-of-line'
'ctrl-E': 'editor:select-to-end-of-line'
'cmd-left': 'editor:move-to-first-character-of-line'
'cmd-right': 'editor:move-to-end-of-screen-line'
'cmd-shift-left': 'editor:select-to-first-character-of-line'
'cmd-shift-right': 'editor:select-to-end-of-line'
'alt-backspace': 'editor:backspace-to-beginning-of-word'
'alt-backspace': 'editor:delete-to-beginning-of-word'
'alt-delete': 'editor:delete-to-end-of-word'
'ctrl-a': 'editor:move-to-beginning-of-line'
'ctrl-e': 'editor:move-to-end-of-line'
+1 -1
Ver Arquivo
@@ -3,5 +3,5 @@
'alt-F': 'editor:select-to-end-of-word'
'alt-b': 'editor:move-to-beginning-of-word'
'alt-B': 'editor:select-to-beginning-of-word'
'alt-h': 'editor:backspace-to-beginning-of-word'
'alt-h': 'editor:delete-to-beginning-of-word'
'alt-d': 'editor:delete-to-end-of-word'
+11 -2
Ver Arquivo
@@ -60,8 +60,17 @@
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
'.workspace .editor':
# Windows specific
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
# Platform Bindings
'ctrl-left': 'editor:move-to-beginning-of-word'
'ctrl-right': 'editor:move-to-end-of-word'
'ctrl-shift-left': 'editor:select-to-beginning-of-word'
'ctrl-shift-right': 'editor:select-to-end-of-word'
'ctrl-backspace': 'editor:delete-to-beginning-of-word'
'ctrl-delete': 'editor:delete-to-end-of-word'
'ctrl-home': 'core:move-to-top'
'ctrl-end': 'core:move-to-bottom'
'ctrl-shift-home': 'core:select-to-top'
'ctrl-shift-end': 'core:select-to-bottom'
# Sublime Parity
'ctrl-a': 'core:select-all'
+15 -2
Ver Arquivo
@@ -1,4 +1,8 @@
'body':
# Platform Bindings
'ctrl-pageup': 'pane:show-previous-item'
'ctrl-pagedown': 'pane:show-next-item'
# Atom Specific
'enter': 'core:confirm'
'escape': 'core:cancel'
@@ -10,6 +14,7 @@
'ctrl-alt-i': 'window:toggle-dev-tools'
'ctrl-alt-p': 'window:run-package-specs'
'ctrl-alt-s': 'application:run-all-specs'
'F11': 'window:toggle-full-screen'
# Sublime Parity
'ctrl-N': 'application:new-window'
@@ -33,6 +38,7 @@
'pageup': 'core:page-up'
'pagedown': 'core:page-down'
'backspace': 'core:backspace'
'shift-backspace': 'core:backspace'
'ctrl-tab': 'pane:show-next-item'
'ctrl-shift-tab': 'pane:show-previous-item'
'ctrl-shift-up': 'core:move-up'
@@ -57,8 +63,15 @@
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
'.workspace .editor':
# Windows specific
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
# Platform Bindings
'ctrl-left': 'editor:move-to-beginning-of-word'
'ctrl-right': 'editor:move-to-end-of-word'
'ctrl-shift-left': 'editor:select-to-beginning-of-word'
'ctrl-shift-right': 'editor:select-to-end-of-word'
'ctrl-backspace': 'editor:delete-to-beginning-of-word'
'ctrl-delete': 'editor:delete-to-end-of-word'
'ctrl-home': 'core:move-to-top'
'ctrl-end': 'core:move-to-bottom'
# Sublime Parity
'ctrl-a': 'core:select-all'
+20
Ver Arquivo
@@ -134,6 +134,25 @@
submenu: [
{ label: 'Reload', command: 'window:reload' }
{ label: 'Toggle Full Screen', command: 'window:toggle-full-screen' }
{
label: 'Panes'
submenu: [
{ label: 'Split Up', command: 'pane:split-up' }
{ label: 'Split Down', command: 'pane:split-down' }
{ label: 'Split Left', command: 'pane:split-left' }
{ label: 'Split Right', command: 'pane:split-right' }
{ type: 'separator' }
{ label: 'Focus Next Pane', command: 'window:focus-next-pane' }
{ label: 'Focus Previous Pane', command: 'window:focus-previous-pane' }
{ type: 'separator' }
{ label: 'Focus Pane Above', command: 'window:focus-pane-above' }
{ label: 'Focus Pane Below', command: 'window:focus-pane-below' }
{ label: 'Focus Pane On Left', command: 'window:focus-pane-on-left' }
{ label: 'Focus Pane On Right', command: 'window:focus-pane-on-right' }
{ type: 'separator' }
{ label: 'Close Pane', command: 'pane:close' }
]
}
{
label: 'Developer'
submenu: [
@@ -166,6 +185,7 @@
{
label: 'Help'
submenu: [
{ label: 'Terms of Use', command: 'application:open-terms-of-use' }
{ label: 'Documentation', command: 'application:open-documentation' }
{ type: 'separator' }
]
+1
Ver Arquivo
@@ -145,6 +145,7 @@
{
label: '&Help'
submenu: [
{ label: 'View &Terms of Use', command: 'application:open-terms-of-use' }
{ label: 'View &License', command: 'application:open-license' }
{ label: "VERSION", enabled: false }
{ type: 'separator' }
+20
Ver Arquivo
@@ -88,6 +88,25 @@
submenu: [
{ label: '&Reload', command: 'window:reload' }
{ label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' }
{
label: 'Panes'
submenu: [
{ label: 'Split Up', command: 'pane:split-up' }
{ label: 'Split Down', command: 'pane:split-down' }
{ label: 'Split Left', command: 'pane:split-left' }
{ label: 'Split Right', command: 'pane:split-right' }
{ type: 'separator' }
{ label: 'Focus Next Pane', command: 'window:focus-next-pane' }
{ label: 'Focus Previous Pane', command: 'window:focus-previous-pane' }
{ type: 'separator' }
{ label: 'Focus Pane Above', command: 'window:focus-pane-above' }
{ label: 'Focus Pane Below', command: 'window:focus-pane-below' }
{ label: 'Focus Pane On Left', command: 'window:focus-pane-on-left' }
{ label: 'Focus Pane On Right', command: 'window:focus-pane-on-right' }
{ type: 'separator' }
{ label: 'Close pane', command: 'pane:close' }
]
}
{
label: 'Developer'
submenu: [
@@ -146,6 +165,7 @@
label: '&Help'
submenu: [
{ label: '&About Atom...', command: 'application:about' }
{ label: 'View &Terms of Use', command: 'application:open-terms-of-use' }
{ label: 'View &License', command: 'application:open-license' }
{ label: "VERSION", enabled: false }
{ label: "Install &update", command: 'application:install-update', visible: false }
+59 -54
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "0.92.0",
"version": "0.98.0",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/browser/main.js",
"repository": {
@@ -11,49 +11,54 @@
"bugs": {
"url": "https://github.com/atom/atom/issues"
},
"license": "All Rights Reserved",
"atomShellVersion": "0.11.10",
"licenses": [
{
"type": "MIT",
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
}
],
"atomShellVersion": "0.12.5",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "^0.18.0",
"bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
"atom-keymap": "^0.22.0",
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
"clear-cut": "0.4.0",
"coffee-script": "1.7.0",
"coffeestack": "0.7.0",
"delegato": "1.x",
"delegato": "^1",
"emissary": "^1.2.1",
"first-mate": "^1.5.2",
"fs-plus": "^2.2.2",
"first-mate": "^1.5.3",
"fs-plus": "^2.2.3",
"fstream": "0.1.24",
"fuzzaldrin": "~1.1",
"git-utils": "^1.2.2",
"grim": "0.9.0",
"fuzzaldrin": "^1.1",
"git-utils": "^1.3",
"grim": "0.10.0",
"guid": "0.0.10",
"jasmine-tagged": "^1.1.1",
"less-cache": "0.12.0",
"mixto": "1.x",
"mixto": "^1",
"mkdirp": "0.3.5",
"nslog": "0.5.0",
"oniguruma": "^1.0.6",
"optimist": "0.4.0",
"pathwatcher": "^1.2.1",
"property-accessors": "1.x",
"pathwatcher": "^1.3.1",
"property-accessors": "^1",
"q": "^1.0.1",
"random-words": "0.0.1",
"react": "^0.10.0",
"reactionary": "^0.8.0",
"runas": "0.5.x",
"react-atom-fork": "^0.10.0",
"reactionary-atom-fork": "^0.9.0",
"runas": "^0.5",
"scandal": "0.15.2",
"scoped-property-store": "^0.8.0",
"scrollbar-style": "^0.1.0",
"scoped-property-store": "^0.9.0",
"scrollbar-style": "^0.4.0",
"season": "^1.0.2",
"semver": "1.1.4",
"serializable": "1.x",
"space-pen": "3.1.1",
"serializable": "^1",
"space-pen": "3.2.0",
"temp": "0.5.0",
"text-buffer": "^2.1.0",
"theorist": "1.x",
"underscore-plus": "^1.2.1",
"text-buffer": "^2.2.2",
"theorist": "^1",
"underscore-plus": "^1.3.0",
"vm-compatibility-layer": "0.1.0"
},
"packageDependencies": {
@@ -64,72 +69,72 @@
"base16-tomorrow-dark-theme": "0.15.0",
"solarized-dark-syntax": "0.14.0",
"solarized-light-syntax": "0.7.0",
"archive-view": "0.30.0",
"autocomplete": "0.27.0",
"autoflow": "0.16.0",
"archive-view": "0.31.0",
"autocomplete": "0.28.0",
"autoflow": "0.17.0",
"autosave": "0.13.0",
"background-tips": "0.13.0",
"bookmarks": "0.22.0",
"bracket-matcher": "0.33.0",
"bracket-matcher": "0.38.0",
"command-palette": "0.21.0",
"deprecation-cop": "0.5.0",
"dev-live-reload": "0.30.0",
"exception-reporting": "0.17.0",
"feedback": "0.30.0",
"find-and-replace": "0.99.0",
"fuzzy-finder": "0.50.0",
"feedback": "0.33.0",
"find-and-replace": "0.106.0",
"fuzzy-finder": "0.51.0",
"git-diff": "0.28.0",
"go-to-line": "0.19.0",
"grammar-selector": "0.24.0",
"go-to-line": "0.21.0",
"grammar-selector": "0.27.0",
"image-view": "0.33.0",
"keybinding-resolver": "0.17.0",
"link": "0.22.0",
"markdown-preview": "0.65.0",
"markdown-preview": "0.72.0",
"metrics": "0.32.0",
"open-on-github": "0.28.0",
"package-generator": "0.30.0",
"release-notes": "0.27.0",
"settings-view": "0.111.0",
"snippets": "0.41.0",
"spell-check": "0.34.0",
"release-notes": "0.31.0",
"settings-view": "0.116.0",
"snippets": "0.43.0",
"spell-check": "0.35.0",
"status-bar": "0.40.0",
"styleguide": "0.29.0",
"symbols-view": "0.49.0",
"tabs": "0.37.0",
"symbols-view": "0.53.0",
"tabs": "0.40.0",
"timecop": "0.18.0",
"tree-view": "0.90.0",
"tree-view": "0.93.0",
"update-package-dependencies": "0.6.0",
"welcome": "0.12.0",
"welcome": "0.14.0",
"whitespace": "0.22.0",
"wrap-guide": "0.18.0",
"language-c": "0.14.0",
"language-c": "0.15.0",
"language-coffee-script": "0.22.0",
"language-css": "0.16.0",
"language-gfm": "0.31.0",
"language-gfm": "0.38.0",
"language-git": "0.9.0",
"language-go": "0.9.0",
"language-html": "0.19.0",
"language-go": "0.12.0",
"language-html": "0.22.0",
"language-hyperlink": "0.9.0",
"language-java": "0.9.0",
"language-javascript": "0.24.0",
"language-java": "0.10.0",
"language-javascript": "0.26.0",
"language-json": "0.8.0",
"language-less": "0.8.0",
"language-less": "0.9.0",
"language-make": "0.10.0",
"language-objective-c": "0.11.0",
"language-perl": "0.8.0",
"language-php": "0.14.0",
"language-property-list": "0.7.0",
"language-python": "0.15.0",
"language-ruby": "0.23.0",
"language-ruby-on-rails": "0.12.0",
"language-sass": "0.10.0",
"language-python": "0.17.0",
"language-ruby": "0.25.0",
"language-ruby-on-rails": "0.14.0",
"language-sass": "0.11.0",
"language-shellscript": "0.8.0",
"language-source": "0.7.0",
"language-sql": "0.8.0",
"language-text": "0.6.0",
"language-todo": "0.10.0",
"language-toml": "0.12.0",
"language-xml": "0.11.0",
"language-xml": "0.13.0",
"language-yaml": "0.6.0"
},
"private": true,
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 191 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 284 KiB

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 361 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 141 KiB

+15 -9
Ver Arquivo
@@ -1,8 +1,18 @@
#!/usr/bin/env node
var nodeMinorVersion = process.versions.node.split('.')[1]
if (nodeMinorVersion !== '10') {
console.warn("You must run script/bootstrap and script/build with node v0.10.x");
var fs = require('fs');
var nodeVersion = process.versions.node.split('.')
var nodeMajorVersion = +nodeVersion[0]
var nodeMinorVersion = +nodeVersion[1]
if (nodeMajorVersion === 0 && nodeMinorVersion < 10) {
console.warn("You must run script/bootstrap and script/build with node v0.10 or above");
process.exit(1);
}
// Make sure python2.7 is installed
if (process.platform == 'win32' && !fs.existsSync('C:\\Python27\\')) {
console.warn("You must have Python 2.7 installed at 'C:\\Python27\\'");
process.exit(1);
}
@@ -25,14 +35,13 @@ function executeCommands(commands, done, index) {
done(null);
}
var apmVendorPath = path.resolve(__dirname, '..', 'vendor', 'apm');
var apmInstallPath = path.resolve(__dirname, '..', 'apm');
if (!fs.existsSync(apmInstallPath))
fs.mkdirSync(apmInstallPath);
if (!fs.existsSync(path.join(apmInstallPath, 'node_modules')))
fs.mkdirSync(path.join(apmInstallPath, 'node_modules'));
var apmPath = 'apm/node_modules/atom-package-manager/bin/apm'
var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm')
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm');
@@ -42,11 +51,8 @@ var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'sea
var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo';
var commands = [
'git submodule --quiet sync',
'git submodule --quiet update --recursive --init',
{command: 'npm' + npmFlags + 'install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
{command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmVendorPath, ignoreStdout: true}},
{command: npmPath + npmFlags + 'install --quiet ' + apmVendorPath, options: {cwd: apmInstallPath, ignoreStdout: true}},
{command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmInstallPath, ignoreStdout: true}},
echoNewLine,
apmPath + ' clean ' + apmFlags,
apmPath + ' install --quiet ' + apmFlags,
+1 -2
Ver Arquivo
@@ -8,7 +8,7 @@ var productName = require('../package.json').productName;
process.chdir(path.dirname(__dirname));
var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
var tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp';
var tmpdir = os.tmpdir();
// Windows: Use START as a way to ignore error if Atom.exe isnt running
var killatom = process.platform === 'win32' ? 'START taskkill /F /IM ' + productName + '.exe' : 'pkill -9 ' + productName + ' || true';
@@ -18,7 +18,6 @@ var commands = [
[__dirname, '..', 'node_modules'],
[__dirname, '..', 'build', 'node_modules'],
[__dirname, '..', 'apm', 'node_modules'],
[__dirname, '..', 'vendor', 'apm', 'node_modules'],
[__dirname, '..', 'atom-shell'],
[home, '.atom', '.node-gyp'],
[home, '.atom', 'storage'],
+5
Ver Arquivo
@@ -0,0 +1,5 @@
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\grunt" %*
) ELSE (
node "%~dp0\grunt" %*
)
+3
Ver Arquivo
@@ -1,6 +1,8 @@
#!/bin/bash
# mkdeb version control-file-path deb-file-path
set -e
SCRIPT=`readlink -f "$0"`
ROOT=`readlink -f $(dirname $SCRIPT)/..`
cd $ROOT
@@ -12,6 +14,7 @@ ICON_FILE="$4"
DEB_PATH="$5"
TARGET_ROOT="`mktemp -d`"
chmod 755 "$TARGET_ROOT"
TARGET="$TARGET_ROOT/atom-$VERSION-amd64"
mkdir -p "$TARGET/usr"
+33 -30
Ver Arquivo
@@ -113,18 +113,21 @@ describe "the `atom` global", ->
promise
it "triggers the activation event on all handlers registered during activation", ->
atom.workspaceView.openSync()
editorView = atom.workspaceView.getActiveView()
eventHandler = jasmine.createSpy("activation-event")
editorView.command 'activation-event', eventHandler
editorView.trigger 'activation-event'
expect(mainModule.activate.callCount).toBe 1
expect(mainModule.activationEventCallCount).toBe 1
expect(eventHandler.callCount).toBe 1
editorView.trigger 'activation-event'
expect(mainModule.activationEventCallCount).toBe 2
expect(eventHandler.callCount).toBe 2
expect(mainModule.activate.callCount).toBe 1
waitsForPromise ->
atom.workspaceView.open()
runs ->
editorView = atom.workspaceView.getActiveView()
eventHandler = jasmine.createSpy("activation-event")
editorView.command 'activation-event', eventHandler
editorView.trigger 'activation-event'
expect(mainModule.activate.callCount).toBe 1
expect(mainModule.activationEventCallCount).toBe 1
expect(eventHandler.callCount).toBe 1
editorView.trigger 'activation-event'
expect(mainModule.activationEventCallCount).toBe 2
expect(eventHandler.callCount).toBe 2
expect(mainModule.activate.callCount).toBe 1
it "activates the package immediately when the events are empty", ->
mainModule = require './fixtures/packages/package-with-empty-activation-events/index'
@@ -170,28 +173,28 @@ describe "the `atom` global", ->
element2 = $$ -> @div class: 'test-2'
element3 = $$ -> @div class: 'test-3'
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)).toHaveLength 0
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
atom.packages.activatePackage("package-with-keymaps")
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe "test-1"
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)[0].command).toBe "test-2"
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe "test-1"
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element2[0])[0].command).toBe "test-2"
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element3[0])).toHaveLength 0
describe "when the metadata contains a 'keymaps' manifest", ->
it "loads only the keymaps specified by the manifest, in the specified order", ->
element1 = $$ -> @div class: 'test-1'
element3 = $$ -> @div class: 'test-3'
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])).toHaveLength 0
atom.packages.activatePackage("package-with-keymaps-manifest")
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe 'keymap-1'
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-n', element1)[0].command).toBe 'keymap-2'
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-y', element3)).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:element1[0])[0].command).toBe 'keymap-1'
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-n', target:element1[0])[0].command).toBe 'keymap-2'
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-y', target:element3[0])).toHaveLength 0
describe "menu loading", ->
beforeEach ->
@@ -377,8 +380,8 @@ describe "the `atom` global", ->
runs ->
atom.packages.deactivatePackage('package-with-keymaps')
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
expect(atom.keymaps.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:$$ -> @div class: 'test-1'[0])).toHaveLength 0
expect(atom.keymaps.findKeyBindings(keystrokes:'ctrl-z', target:$$ -> @div class: 'test-2'[0])).toHaveLength 0
it "removes the package's stylesheets", ->
waitsForPromise ->
@@ -507,20 +510,20 @@ describe "the `atom` global", ->
# enabling of theme
pack = atom.packages.enablePackage(packageName)
activatedPackages = null
waitsFor ->
activatedPackages = atom.packages.getActivePackages()
activatedPackages.length > 0
pack in atom.packages.getActivePackages()
runs ->
expect(activatedPackages).toContain(pack)
expect(atom.config.get('core.themes')).toContain packageName
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
# disabling of theme
pack = atom.packages.disablePackage(packageName)
activatedPackages = atom.packages.getActivePackages()
expect(activatedPackages).not.toContain(pack)
waitsFor ->
not (pack in atom.packages.getActivePackages())
runs ->
expect(atom.config.get('core.themes')).not.toContain packageName
expect(atom.config.get('core.themes')).not.toContain packageName
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
+7 -1
Ver Arquivo
@@ -5,6 +5,10 @@ fs = require 'fs-plus'
describe "Config", ->
dotAtomPath = path.join(temp.dir, 'dot-atom-dir')
dotAtomPath = null
beforeEach ->
dotAtomPath = temp.path('dot-atom-dir')
describe ".get(keyPath)", ->
it "allows a key path's value to be read", ->
@@ -258,8 +262,10 @@ describe "Config", ->
describe ".initializeConfigDirectory()", ->
beforeEach ->
if fs.existsSync(dotAtomPath)
fs.removeSync(dotAtomPath)
atom.config.configDirPath = dotAtomPath
expect(fs.existsSync(atom.config.configDirPath)).toBeFalsy()
afterEach ->
fs.removeSync(dotAtomPath)
+6 -4
Ver Arquivo
@@ -21,7 +21,7 @@ describe "DisplayBuffer", ->
describe "::copy()", ->
it "creates a new DisplayBuffer with the same initial state", ->
marker1 = displayBuffer.markBufferRange([[1, 2], [3, 4]], id: 1)
marker2 = displayBuffer.markBufferRange([[2, 3], [4, 5]], isReversed: true, id: 2)
marker2 = displayBuffer.markBufferRange([[2, 3], [4, 5]], reversed: true, id: 2)
marker3 = displayBuffer.markBufferPosition([5, 6], id: 3)
displayBuffer.createFold(3, 5)
@@ -948,7 +948,7 @@ describe "DisplayBuffer", ->
it "returns the start and end positions of the marker based on the line height and character widths assigned to the DisplayBuffer", ->
marker = displayBuffer.markScreenRange([[5, 10], [6, 4]])
displayBuffer.setLineHeight(20)
displayBuffer.setLineHeightInPixels(20)
displayBuffer.setDefaultCharWidth(10)
displayBuffer.setScopedCharWidths(["source.js", "keyword.control.js"], r: 11, e: 11, t: 11, u: 11, n: 11)
@@ -959,7 +959,7 @@ describe "DisplayBuffer", ->
describe "::setScrollTop", ->
beforeEach ->
displayBuffer.manageScrollPosition = true
displayBuffer.setLineHeight(10)
displayBuffer.setLineHeightInPixels(10)
it "disallows negative values", ->
displayBuffer.setHeight(displayBuffer.getScrollHeight() + 100)
@@ -979,6 +979,7 @@ describe "DisplayBuffer", ->
describe "::setScrollLeft", ->
beforeEach ->
displayBuffer.manageScrollPosition = true
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setDefaultCharWidth(10)
it "disallows negative values", ->
@@ -999,8 +1000,9 @@ describe "DisplayBuffer", ->
describe "::scrollToScreenPosition(position)", ->
it "sets the scroll top and scroll left so the given screen position is in view", ->
displayBuffer.manageScrollPosition = true
displayBuffer.setLineHeight(10)
displayBuffer.setLineHeightInPixels(10)
displayBuffer.setDefaultCharWidth(10)
displayBuffer.setHorizontalScrollbarHeight(0)
displayBuffer.setHeight(50)
displayBuffer.setWidth(50)
+370 -126
Ver Arquivo
@@ -1,12 +1,16 @@
{extend, flatten, toArray} = require 'underscore-plus'
_ = require 'underscore-plus'
{extend, flatten, toArray, last} = _
ReactEditorView = require '../src/react-editor-view'
nbsp = String.fromCharCode(160)
describe "EditorComponent", ->
[editor, wrapperView, component, node, verticalScrollbarNode, horizontalScrollbarNode] = []
[lineHeightInPixels, charWidth, delayAnimationFrames, nextAnimationFrame] = []
[contentNode, editor, wrapperView, component, node, verticalScrollbarNode, horizontalScrollbarNode] = []
[lineHeightInPixels, charWidth, delayAnimationFrames, nextAnimationFrame, lineOverdrawMargin] = []
beforeEach ->
lineOverdrawMargin = 2
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
@@ -22,67 +26,163 @@ describe "EditorComponent", ->
else
fn()
editor = atom.project.openSync('sample.js')
wrapperView = new ReactEditorView(editor)
waitsForPromise ->
atom.project.open('sample.js').then (o) -> editor = o
runs ->
contentNode = document.querySelector('#jasmine-content')
contentNode.style.width = '1000px'
wrapperView = new ReactEditorView(editor, {lineOverdrawMargin})
wrapperView.attachToDom()
{component} = wrapperView
component.setLineHeight(1.3)
component.setFontSize(20)
lineHeightInPixels = editor.getLineHeight()
lineHeightInPixels = editor.getLineHeightInPixels()
charWidth = editor.getDefaultCharWidth()
node = component.getDOMNode()
verticalScrollbarNode = node.querySelector('.vertical-scrollbar')
horizontalScrollbarNode = node.querySelector('.horizontal-scrollbar')
node.style.height = editor.getLineCount() * lineHeightInPixels + 'px'
node.style.width = '1000px'
component.measureHeightAndWidth()
afterEach ->
contentNode.style.width = ''
describe "line rendering", ->
it "renders only the currently-visible lines", ->
it "renders the currently-visible lines plus the overdraw margin", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
component.measureHeightAndWidth()
lines = node.querySelectorAll('.line')
expect(lines.length).toBe 6
expect(lines[0].textContent).toBe editor.lineForScreenRow(0).text
expect(lines[5].textContent).toBe editor.lineForScreenRow(5).text
linesNode = node.querySelector('.lines')
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
expect(node.querySelectorAll('.line').length).toBe 6 + 2 # no margin above
expect(component.lineNodeForScreenRow(0).textContent).toBe editor.lineForScreenRow(0).text
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0
expect(component.lineNodeForScreenRow(5).textContent).toBe editor.lineForScreenRow(5).text
expect(component.lineNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
expect(node.querySelector('.scroll-view-content').style['-webkit-transform']).toBe "translate3d(0px, #{-2.5 * lineHeightInPixels}px, 0)"
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, #{-4.5 * lineHeightInPixels}px, 0px)"
expect(node.querySelectorAll('.line').length).toBe 6 + 4 # margin above and below
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNodeForScreenRow(2).textContent).toBe editor.lineForScreenRow(2).text
expect(component.lineNodeForScreenRow(9).offsetTop).toBe 9 * lineHeightInPixels
expect(component.lineNodeForScreenRow(9).textContent).toBe editor.lineForScreenRow(9).text
lineNodes = node.querySelectorAll('.line')
expect(lineNodes.length).toBe 6
expect(lineNodes[0].offsetTop).toBe 2 * lineHeightInPixels
expect(lineNodes[0].textContent).toBe editor.lineForScreenRow(2).text
expect(lineNodes[5].textContent).toBe editor.lineForScreenRow(7).text
it "updates absolute positions of subsequent lines when lines are inserted or removed", ->
it "updates the top position of subsequent lines when lines are inserted or removed", ->
editor.getBuffer().deleteRows(0, 1)
lineNodes = node.querySelectorAll('.line')
expect(lineNodes[0].offsetTop).toBe 0
expect(lineNodes[1].offsetTop).toBe 1 * lineHeightInPixels
expect(lineNodes[2].offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
editor.getBuffer().insert([0, 0], '\n\n')
lineNodes = node.querySelectorAll('.line')
expect(lineNodes[0].offsetTop).toBe 0
expect(lineNodes[1].offsetTop).toBe 1 * lineHeightInPixels
expect(lineNodes[2].offsetTop).toBe 2 * lineHeightInPixels
expect(lineNodes[3].offsetTop).toBe 3 * lineHeightInPixels
expect(lineNodes[4].offsetTop).toBe 4 * lineHeightInPixels
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0 * lineHeightInPixels
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
expect(component.lineNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
it "updates the top position of lines when the line height changes", ->
initialLineHeightInPixels = editor.getLineHeightInPixels()
component.setLineHeight(2)
newLineHeightInPixels = editor.getLineHeightInPixels()
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
it "updates the top position of lines when the font size changes", ->
initialLineHeightInPixels = editor.getLineHeightInPixels()
component.setFontSize(10)
newLineHeightInPixels = editor.getLineHeightInPixels()
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
it "updates the top position of lines when the font family changes", ->
# Can't find a font that changes the line height, but we think one might exist
linesComponent = component.refs.scrollView.refs.lines
spyOn(linesComponent, 'measureLineHeightInPixelsAndCharWidth').andCallFake -> editor.setLineHeightInPixels(10)
initialLineHeightInPixels = editor.getLineHeightInPixels()
component.setFontFamily('sans-serif')
expect(linesComponent.measureLineHeightInPixelsAndCharWidth).toHaveBeenCalled()
newLineHeightInPixels = editor.getLineHeightInPixels()
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
it "renders the .lines div at the full height of the editor if there aren't enough lines to scroll vertically", ->
editor.setText('')
node.style.height = '300px'
component.measureHeightAndWidth()
linesNode = node.querySelector('.lines')
expect(linesNode.offsetHeight).toBe 300
describe "when showInvisibles is enabled", ->
invisibles = null
beforeEach ->
invisibles =
eol: 'E'
space: 'S'
tab: 'T'
cr: 'C'
atom.config.set("editor.showInvisibles", true)
atom.config.set("editor.invisibles", invisibles)
it "re-renders the lines when the showInvisibles config option changes", ->
editor.setText " a line with tabs\tand spaces "
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}"
atom.config.set("editor.showInvisibles", false)
expect(component.lineNodeForScreenRow(0).textContent).toBe " a line with tabs and spaces "
atom.config.set("editor.showInvisibles", true)
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}"
it "displays spaces, tabs, and newlines as visible characters", ->
editor.setText " a line with tabs\tand spaces "
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}"
it "displays newlines as their own token outside of the other tokens' scopes", ->
editor.setText "var"
expect(component.lineNodeForScreenRow(0).innerHTML).toBe "<span class=\"source js\"><span class=\"storage modifier js\">var</span></span><span class=\"invisible-character\">#{invisibles.eol}</span>"
it "displays trailing carriage returns using a visible, non-empty value", ->
editor.setText "a line that ends with a carriage return\r\n"
expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that ends with a carriage return#{invisibles.cr}#{invisibles.eol}"
describe "when soft wrapping is enabled", ->
beforeEach ->
editor.setText "a line that wraps "
editor.setSoftWrap(true)
node.style.width = 15 * charWidth + 'px'
component.measureHeightAndWidth()
it "doesn't show end of line invisibles at the end of wrapped lines", ->
expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that "
expect(component.lineNodeForScreenRow(1).textContent).toBe "wraps#{invisibles.space}#{invisibles.eol}"
describe "when indent guides are enabled", ->
beforeEach ->
component.setShowIndentGuide(true)
it "adds an 'indent-guide' class to spans comprising the leading whitespace", ->
lines = node.querySelectorAll('.line')
line1LeafNodes = getLeafNodes(lines[1])
line1LeafNodes = getLeafNodes(component.lineNodeForScreenRow(1))
expect(line1LeafNodes[0].textContent).toBe ' '
expect(line1LeafNodes[0].classList.contains('indent-guide')).toBe true
expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false
line2LeafNodes = getLeafNodes(lines[2])
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
expect(line2LeafNodes[0].textContent).toBe ' '
expect(line2LeafNodes[0].classList.contains('indent-guide')).toBe true
expect(line2LeafNodes[1].textContent).toBe ' '
@@ -92,8 +192,7 @@ describe "EditorComponent", ->
it "renders leading whitespace spans with the 'indent-guide' class for empty lines", ->
editor.getBuffer().insert([1, Infinity], '\n')
lines = node.querySelectorAll('.line')
line2LeafNodes = getLeafNodes(lines[2])
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
expect(line2LeafNodes.length).toBe 3
expect(line2LeafNodes[0].textContent).toBe ' '
@@ -105,8 +204,7 @@ describe "EditorComponent", ->
it "renders indent guides correctly on lines containing only whitespace", ->
editor.getBuffer().insert([1, Infinity], '\n ')
lines = node.querySelectorAll('.line')
line2LeafNodes = getLeafNodes(lines[2])
line2LeafNodes = getLeafNodes(component.lineNodeForScreenRow(2))
expect(line2LeafNodes.length).toBe 3
expect(line2LeafNodes[0].textContent).toBe ' '
expect(line2LeafNodes[0].classList.contains('indent-guide')).toBe true
@@ -116,9 +214,8 @@ describe "EditorComponent", ->
expect(line2LeafNodes[2].classList.contains('indent-guide')).toBe true
it "does not render indent guides in trailing whitespace for lines containing non whitespace characters", ->
editor.getBuffer().setText (" hi ")
lines = node.querySelectorAll('.line')
line0LeafNodes = getLeafNodes(lines[0])
editor.getBuffer().setText " hi "
line0LeafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(line0LeafNodes[0].textContent).toBe ' '
expect(line0LeafNodes[0].classList.contains('indent-guide')).toBe true
expect(line0LeafNodes[1].textContent).toBe ' '
@@ -135,40 +232,39 @@ describe "EditorComponent", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
component.measureHeightAndWidth()
lines = node.querySelectorAll('.line-number')
expect(lines.length).toBe 6
expect(lines[0].textContent).toBe "#{nbsp}1"
expect(lines[5].textContent).toBe "#{nbsp}6"
expect(node.querySelectorAll('.line-number').length).toBe 6 + 2 + 1 # line overdraw margin below + dummy line number
expect(component.lineNumberNodeForScreenRow(0).textContent).toBe "#{nbsp}1"
expect(component.lineNumberNodeForScreenRow(5).textContent).toBe "#{nbsp}6"
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
expect(node.querySelector('.line-numbers').style['-webkit-transform']).toBe "translate3d(0, #{-2.5 * lineHeightInPixels}px, 0)"
expect(node.querySelectorAll('.line-number').length).toBe 6 + 4 + 1 # line overdraw margin above/below + dummy line number
lineNumberNodes = node.querySelectorAll('.line-number')
expect(lineNumberNodes.length).toBe 6
expect(lineNumberNodes[0].offsetTop).toBe 2 * lineHeightInPixels
expect(lineNumberNodes[5].offsetTop).toBe 7 * lineHeightInPixels
expect(lineNumberNodes[0].textContent).toBe "#{nbsp}3"
expect(lineNumberNodes[5].textContent).toBe "#{nbsp}8"
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}3"
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
return
expect(component.lineNumberNodeForScreenRow(7).textContent).toBe "#{nbsp}8"
expect(component.lineNumberNodeForScreenRow(7).offsetTop).toBe 7 * lineHeightInPixels
it "updates absolute positions of subsequent line numbers when lines are inserted or removed", ->
it "updates the translation of subsequent line numbers when lines are inserted or removed", ->
editor.getBuffer().insert([0, 0], '\n\n')
lineNumberNodes = node.querySelectorAll('.line-number')
expect(lineNumberNodes[0].offsetTop).toBe 0
expect(lineNumberNodes[1].offsetTop).toBe 1 * lineHeightInPixels
expect(lineNumberNodes[2].offsetTop).toBe 2 * lineHeightInPixels
expect(lineNumberNodes[3].offsetTop).toBe 3 * lineHeightInPixels
expect(lineNumberNodes[4].offsetTop).toBe 4 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0
expect(component.lineNumberNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
editor.getBuffer().insert([0, 0], '\n\n')
lineNumberNodes = node.querySelectorAll('.line-number')
expect(lineNumberNodes[0].offsetTop).toBe 0
expect(lineNumberNodes[1].offsetTop).toBe 1 * lineHeightInPixels
expect(lineNumberNodes[2].offsetTop).toBe 2 * lineHeightInPixels
expect(lineNumberNodes[3].offsetTop).toBe 3 * lineHeightInPixels
expect(lineNumberNodes[4].offsetTop).toBe 4 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0
expect(component.lineNumberNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(6).offsetTop).toBe 6 * lineHeightInPixels
it "renders • characters for soft-wrapped lines", ->
editor.setSoftWrap(true)
@@ -176,29 +272,50 @@ describe "EditorComponent", ->
node.style.width = 30 * charWidth + 'px'
component.measureHeightAndWidth()
lines = node.querySelectorAll('.line-number')
expect(lines.length).toBe 6
expect(lines[0].textContent).toBe "#{nbsp}1"
expect(lines[1].textContent).toBe "#{nbsp}"
expect(lines[2].textContent).toBe "#{nbsp}2"
expect(lines[3].textContent).toBe "#{nbsp}"
expect(lines[4].textContent).toBe "#{nbsp}3"
expect(lines[5].textContent).toBe "#{nbsp}"
expect(node.querySelectorAll('.line-number').length).toBe 6 + lineOverdrawMargin + 1 # 1 dummy line node
expect(component.lineNumberNodeForScreenRow(0).textContent).toBe "#{nbsp}1"
expect(component.lineNumberNodeForScreenRow(1).textContent).toBe "#{nbsp}"
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}2"
expect(component.lineNumberNodeForScreenRow(3).textContent).toBe "#{nbsp}"
expect(component.lineNumberNodeForScreenRow(4).textContent).toBe "#{nbsp}3"
expect(component.lineNumberNodeForScreenRow(5).textContent).toBe "#{nbsp}"
it "pads line numbers to be right-justified based on the maximum number of line number digits", ->
editor.getBuffer().setText([1..10].join('\n'))
for screenRow in [0..8]
expect(component.lineNumberNodeForScreenRow(screenRow).textContent).toBe "#{nbsp}#{screenRow + 1}"
expect(component.lineNumberNodeForScreenRow(9).textContent).toBe "10"
gutterNode = node.querySelector('.gutter')
initialGutterWidth = gutterNode.offsetWidth
# Removes padding when the max number of digits goes down
editor.getBuffer().delete([[1, 0], [2, 0]])
for screenRow in [0..8]
expect(component.lineNumberNodeForScreenRow(screenRow).textContent).toBe "#{screenRow + 1}"
expect(gutterNode.offsetWidth).toBeLessThan initialGutterWidth
# Increases padding when the max number of digits goes up
editor.getBuffer().insert([0, 0], '\n\n')
for screenRow in [0..8]
expect(component.lineNumberNodeForScreenRow(screenRow).textContent).toBe "#{nbsp}#{screenRow + 1}"
expect(component.lineNumberNodeForScreenRow(9).textContent).toBe "10"
expect(gutterNode.offsetWidth).toBe initialGutterWidth
describe "cursor rendering", ->
it "renders the currently visible cursors", ->
it "renders the currently visible cursors, translated relative to the scroll position", ->
cursor1 = editor.getCursor()
cursor1.setScreenPosition([0, 5])
node.style.height = 4.5 * lineHeightInPixels + 'px'
node.style.width = 20 * lineHeightInPixels + 'px'
component.measureHeightAndWidth()
cursorNodes = node.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 1
expect(cursorNodes[0].offsetHeight).toBe lineHeightInPixels
expect(cursorNodes[0].offsetWidth).toBe charWidth
expect(cursorNodes[0].offsetTop).toBe 0
expect(cursorNodes[0].offsetLeft).toBe 5 * charWidth
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{5 * charWidth}px, #{0 * lineHeightInPixels}px, 0px)"
cursor2 = editor.addCursorAtScreenPosition([6, 11])
cursor3 = editor.addCursorAtScreenPosition([4, 10])
@@ -206,25 +323,23 @@ describe "EditorComponent", ->
cursorNodes = node.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 2
expect(cursorNodes[0].offsetTop).toBe 0
expect(cursorNodes[0].offsetLeft).toBe 5 * charWidth
expect(cursorNodes[1].offsetTop).toBe 4 * lineHeightInPixels
expect(cursorNodes[1].offsetLeft).toBe 10 * charWidth
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{5 * charWidth}px, #{0 * lineHeightInPixels}px, 0px)"
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate3d(#{10 * charWidth}px, #{4 * lineHeightInPixels}px, 0px)"
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
horizontalScrollbarNode.scrollLeft = 3.5 * charWidth
horizontalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
cursorNodes = node.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 2
expect(cursorNodes[0].offsetTop).toBe 6 * lineHeightInPixels
expect(cursorNodes[0].offsetLeft).toBe 11 * charWidth
expect(cursorNodes[1].offsetTop).toBe 4 * lineHeightInPixels
expect(cursorNodes[1].offsetLeft).toBe 10 * charWidth
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{(11 - 3.5) * charWidth}px, #{(6 - 2.5) * lineHeightInPixels}px, 0px)"
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate3d(#{(10 - 3.5) * charWidth}px, #{(4 - 2.5) * lineHeightInPixels}px, 0px)"
cursor3.destroy()
cursorNodes = node.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 1
expect(cursorNodes[0].offsetTop).toBe 6 * lineHeightInPixels
expect(cursorNodes[0].offsetLeft).toBe 11 * charWidth
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{(11 - 3.5) * charWidth}px, #{(6 - 2.5) * lineHeightInPixels}px, 0px)"
it "accounts for character widths when positioning cursors", ->
atom.config.set('editor.fontFamily', 'sans-serif')
@@ -233,7 +348,7 @@ describe "EditorComponent", ->
cursor = node.querySelector('.cursor')
cursorRect = cursor.getBoundingClientRect()
cursorLocationTextNode = node.querySelector('.storage.type.function.js').firstChild.firstChild
cursorLocationTextNode = component.lineNodeForScreenRow(0).querySelector('.storage.type.function.js').firstChild
range = document.createRange()
range.setStart(cursorLocationTextNode, 0)
range.setEnd(cursorLocationTextNode, 1)
@@ -243,44 +358,22 @@ describe "EditorComponent", ->
expect(cursorRect.width).toBe rangeRect.width
it "blinks cursors when they aren't moving", ->
editor.addCursorAtScreenPosition([1, 0])
[cursorNode1, cursorNode2] = node.querySelectorAll('.cursor')
expect(cursorNode1.classList.contains('blink-off')).toBe false
expect(cursorNode2.classList.contains('blink-off')).toBe false
spyOn(_._, 'now').andCallFake -> window.now # Ensure _.debounce is based on our fake spec timeline
cursorsNode = node.querySelector('.cursors')
expect(cursorsNode.classList.contains('blink-off')).toBe false
advanceClock(component.props.cursorBlinkPeriod / 2)
expect(cursorNode1.classList.contains('blink-off')).toBe true
expect(cursorNode2.classList.contains('blink-off')).toBe true
expect(cursorsNode.classList.contains('blink-off')).toBe true
advanceClock(component.props.cursorBlinkPeriod / 2)
expect(cursorNode1.classList.contains('blink-off')).toBe false
expect(cursorNode2.classList.contains('blink-off')).toBe false
expect(cursorsNode.classList.contains('blink-off')).toBe false
advanceClock(component.props.cursorBlinkPeriod / 2)
expect(cursorNode1.classList.contains('blink-off')).toBe true
expect(cursorNode2.classList.contains('blink-off')).toBe true
# Stop blinking immediately when cursors move
advanceClock(component.props.cursorBlinkPeriod / 4)
expect(cursorNode1.classList.contains('blink-off')).toBe true
expect(cursorNode2.classList.contains('blink-off')).toBe true
# Stop blinking for one full period after moving the cursor
# Stop blinking after moving the cursor
editor.moveCursorRight()
expect(cursorNode1.classList.contains('blink-off')).toBe false
expect(cursorNode2.classList.contains('blink-off')).toBe false
advanceClock(component.props.cursorBlinkResumeDelay / 2)
expect(cursorNode1.classList.contains('blink-off')).toBe false
expect(cursorNode2.classList.contains('blink-off')).toBe false
advanceClock(component.props.cursorBlinkResumeDelay / 2)
expect(cursorNode1.classList.contains('blink-off')).toBe true
expect(cursorNode2.classList.contains('blink-off')).toBe true
expect(cursorsNode.classList.contains('blink-off')).toBe false
advanceClock(component.props.cursorBlinkResumeDelay)
advanceClock(component.props.cursorBlinkPeriod / 2)
expect(cursorNode1.classList.contains('blink-off')).toBe false
expect(cursorNode2.classList.contains('blink-off')).toBe false
expect(cursorsNode.classList.contains('blink-off')).toBe true
it "renders the hidden input field at the position of the last cursor if it is on screen", ->
inputNode = node.querySelector('.hidden-input')
@@ -307,13 +400,13 @@ describe "EditorComponent", ->
cursorNodes = node.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 1
expect(cursorNodes[0].offsetTop).toBe 6 * lineHeightInPixels
expect(cursorNodes[0].offsetLeft).toBe 8 * charWidth
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{8 * charWidth}px, #{6 * lineHeightInPixels}px, 0px)"
describe "selection rendering", ->
scrollViewClientLeft = null
[scrollViewNode, scrollViewClientLeft] = []
beforeEach ->
scrollViewNode = node.querySelector('.scroll-view')
scrollViewClientLeft = node.querySelector('.scroll-view').getBoundingClientRect().left
it "renders 1 region for 1-line selections", ->
@@ -337,7 +430,7 @@ describe "EditorComponent", ->
expect(region1Rect.top).toBe 1 * lineHeightInPixels
expect(region1Rect.height).toBe 1 * lineHeightInPixels
expect(region1Rect.left).toBe scrollViewClientLeft + 6 * charWidth
expect(Math.ceil(region1Rect.right)).toBe node.clientWidth # TODO: Remove ceiling when react-wrapper is removed
expect(region1Rect.right).toBe scrollViewNode.getBoundingClientRect().right
region2Rect = regions[1].getBoundingClientRect()
expect(region2Rect.top).toBe 2 * lineHeightInPixels
@@ -354,13 +447,13 @@ describe "EditorComponent", ->
expect(region1Rect.top).toBe 1 * lineHeightInPixels
expect(region1Rect.height).toBe 1 * lineHeightInPixels
expect(region1Rect.left).toBe scrollViewClientLeft + 6 * charWidth
expect(Math.ceil(region1Rect.right)).toBe node.clientWidth # TODO: Remove ceiling when react-wrapper is removed
expect(region1Rect.right).toBe scrollViewNode.getBoundingClientRect().right
region2Rect = regions[1].getBoundingClientRect()
expect(region2Rect.top).toBe 2 * lineHeightInPixels
expect(region2Rect.height).toBe 3 * lineHeightInPixels
expect(region2Rect.left).toBe scrollViewClientLeft + 0
expect(Math.ceil(region2Rect.right)).toBe node.clientWidth # TODO: Remove ceiling when react-wrapper is removed
expect(region2Rect.right).toBe scrollViewNode.getBoundingClientRect().right
region3Rect = regions[2].getBoundingClientRect()
expect(region3Rect.top).toBe 5 * lineHeightInPixels
@@ -368,9 +461,12 @@ describe "EditorComponent", ->
expect(region3Rect.left).toBe scrollViewClientLeft + 0
expect(region3Rect.width).toBe 10 * charWidth
it "does not render empty selections", ->
expect(editor.getSelection().isEmpty()).toBe true
expect(node.querySelectorAll('.selection').length).toBe 0
it "does not render empty selections unless they are the first selection (to prevent a Chromium rendering artifact caused by removing it)", ->
editor.addSelectionForBufferRange([[2, 2], [2, 2]])
expect(editor.getSelection(0).isEmpty()).toBe true
expect(editor.getSelection(1).isEmpty()).toBe true
expect(node.querySelectorAll('.selection').length).toBe 1
describe "mouse interactions", ->
linesNode = null
@@ -504,16 +600,16 @@ describe "EditorComponent", ->
editor.setScrollTop(10)
expect(verticalScrollbarNode.scrollTop).toBe 10
it "updates the horizontal scrollbar and scroll view content x transform based on the scrollLeft of the model", ->
it "updates the horizontal scrollbar and the x transform of the lines based on the scrollLeft of the model", ->
node.style.width = 30 * charWidth + 'px'
component.measureHeightAndWidth()
scrollViewContentNode = node.querySelector('.scroll-view-content')
expect(scrollViewContentNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0)"
linesNode = node.querySelector('.lines')
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
expect(horizontalScrollbarNode.scrollLeft).toBe 0
editor.setScrollLeft(100)
expect(scrollViewContentNode.style['-webkit-transform']).toBe "translate3d(-100px, 0px, 0)"
expect(linesNode.style['-webkit-transform']).toBe "translate3d(-100px, 0px, 0px)"
expect(horizontalScrollbarNode.scrollLeft).toBe 100
it "updates the scrollLeft of the model when the scrollLeft of the horizontal scrollbar changes", ->
@@ -526,6 +622,107 @@ describe "EditorComponent", ->
expect(editor.getScrollLeft()).toBe 100
it "does not obscure the last line with the horizontal scrollbar", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
editor.setScrollBottom(editor.getScrollHeight())
lastLineNode = component.lineNodeForScreenRow(editor.getLastScreenRow())
bottomOfLastLine = lastLineNode.getBoundingClientRect().bottom
topOfHorizontalScrollbar = horizontalScrollbarNode.getBoundingClientRect().top
expect(bottomOfLastLine).toBe topOfHorizontalScrollbar
# Scroll so there's no space below the last line when the horizontal scrollbar disappears
node.style.width = 100 * charWidth + 'px'
component.measureHeightAndWidth()
bottomOfLastLine = lastLineNode.getBoundingClientRect().bottom
bottomOfEditor = node.getBoundingClientRect().bottom
expect(bottomOfLastLine).toBe bottomOfEditor
it "does not obscure the last character of the longest line with the vertical scrollbar", ->
node.style.height = 7 * lineHeightInPixels + 'px'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
editor.setScrollLeft(Infinity)
rightOfLongestLine = component.lineNodeForScreenRow(6).getBoundingClientRect().right
leftOfVerticalScrollbar = verticalScrollbarNode.getBoundingClientRect().left
expect(Math.round(rightOfLongestLine)).toBe leftOfVerticalScrollbar - 1 # Leave 1 px so the cursor is visible on the end of the line
it "only displays dummy scrollbars when scrollable in that direction", ->
expect(verticalScrollbarNode.style.display).toBe 'none'
expect(horizontalScrollbarNode.style.display).toBe 'none'
node.style.height = 4.5 * lineHeightInPixels + 'px'
node.style.width = '1000px'
component.measureHeightAndWidth()
expect(verticalScrollbarNode.style.display).toBe ''
expect(horizontalScrollbarNode.style.display).toBe 'none'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
expect(verticalScrollbarNode.style.display).toBe ''
expect(horizontalScrollbarNode.style.display).toBe ''
node.style.height = 20 * lineHeightInPixels + 'px'
component.measureHeightAndWidth()
expect(verticalScrollbarNode.style.display).toBe 'none'
expect(horizontalScrollbarNode.style.display).toBe ''
it "makes the dummy scrollbar divs only as tall/wide as the actual scrollbars", ->
node.style.height = 4 * lineHeightInPixels + 'px'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
atom.themes.applyStylesheet "test", """
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
"""
scrollbarCornerNode = node.querySelector('.scrollbar-corner')
expect(verticalScrollbarNode.offsetWidth).toBe 8
expect(horizontalScrollbarNode.offsetHeight).toBe 8
expect(scrollbarCornerNode.offsetWidth).toBe 8
expect(scrollbarCornerNode.offsetHeight).toBe 8
it "assigns the bottom/right of the scrollbars to the width of the opposite scrollbar if it is visible", ->
scrollbarCornerNode = node.querySelector('.scrollbar-corner')
expect(verticalScrollbarNode.style.bottom).toBe ''
expect(horizontalScrollbarNode.style.right).toBe ''
node.style.height = 4.5 * lineHeightInPixels + 'px'
node.style.width = '1000px'
component.measureHeightAndWidth()
expect(verticalScrollbarNode.style.bottom).toBe ''
expect(horizontalScrollbarNode.style.right).toBe verticalScrollbarNode.offsetWidth + 'px'
expect(scrollbarCornerNode.style.display).toBe 'none'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
expect(verticalScrollbarNode.style.bottom).toBe horizontalScrollbarNode.offsetHeight + 'px'
expect(horizontalScrollbarNode.style.right).toBe verticalScrollbarNode.offsetWidth + 'px'
expect(scrollbarCornerNode.style.display).toBe ''
node.style.height = 20 * lineHeightInPixels + 'px'
component.measureHeightAndWidth()
expect(verticalScrollbarNode.style.bottom).toBe horizontalScrollbarNode.offsetHeight + 'px'
expect(horizontalScrollbarNode.style.right).toBe ''
expect(scrollbarCornerNode.style.display).toBe 'none'
it "accounts for the width of the gutter in the scrollWidth of the horizontal scrollbar", ->
gutterNode = node.querySelector('.gutter')
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
expect(horizontalScrollbarNode.scrollWidth).toBe gutterNode.offsetWidth + editor.getScrollWidth()
describe "when a mousewheel event occurs on the editor", ->
it "updates the horizontal or vertical scrollbar depending on which delta is greater (x or y)", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
@@ -543,6 +740,32 @@ describe "EditorComponent", ->
expect(verticalScrollbarNode.scrollTop).toBe 10
expect(horizontalScrollbarNode.scrollLeft).toBe 15
describe "when the mousewheel event's target is a line", ->
it "keeps the line on the DOM if it is scrolled off-screen", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
node.style.width = 20 * charWidth + 'px'
component.measureHeightAndWidth()
lineNode = node.querySelector('.line')
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: -500)
Object.defineProperty(wheelEvent, 'target', get: -> lineNode)
node.dispatchEvent(wheelEvent)
expect(node.contains(lineNode)).toBe true
describe "when the mousewheel event's target is a line number", ->
it "keeps the line number on the DOM if it is scrolled off-screen", ->
node.style.height = 4.5 * lineHeightInPixels + 'px'
node.style.width = 20 * charWidth + 'px'
component.measureHeightAndWidth()
lineNumberNode = node.querySelectorAll('.line-number')[1]
wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: -500)
Object.defineProperty(wheelEvent, 'target', get: -> lineNumberNode)
node.dispatchEvent(wheelEvent)
expect(node.contains(lineNumberNode)).toBe true
describe "input events", ->
inputNode = null
@@ -578,3 +801,24 @@ describe "EditorComponent", ->
expect(editor.consolidateSelections).toHaveBeenCalled()
expect(event.abortKeyBinding).toHaveBeenCalled()
describe "hiding and showing the editor", ->
describe "when fontSize, fontFamily, or lineHeight changes while the editor is hidden", ->
it "does not attempt to measure the lineHeight and defaultCharWidth until the editor becomes visible again", ->
wrapperView.hide()
initialLineHeightInPixels = editor.getLineHeightInPixels()
initialCharWidth = editor.getDefaultCharWidth()
component.setLineHeight(2)
expect(editor.getLineHeightInPixels()).toBe initialLineHeightInPixels
expect(editor.getDefaultCharWidth()).toBe initialCharWidth
component.setFontSize(22)
expect(editor.getLineHeightInPixels()).toBe initialLineHeightInPixels
expect(editor.getDefaultCharWidth()).toBe initialCharWidth
component.setFontFamily('monospace')
expect(editor.getLineHeightInPixels()).toBe initialLineHeightInPixels
expect(editor.getDefaultCharWidth()).toBe initialCharWidth
wrapperView.show()
expect(editor.getLineHeightInPixels()).not.toBe initialLineHeightInPixels
expect(editor.getDefaultCharWidth()).not.toBe initialCharWidth
+165 -73
Ver Arquivo
@@ -7,9 +7,12 @@ describe "Editor", ->
buffer.setText(buffer.getText().replace(/[ ]{2}/g, "\t"))
beforeEach ->
editor = atom.project.openSync('sample.js', autoIndent: false)
buffer = editor.buffer
lineLengths = buffer.getLines().map (line) -> line.length
waitsForPromise ->
atom.project.open('sample.js', autoIndent: false).then (o) -> editor = o
runs ->
buffer = editor.buffer
lineLengths = buffer.getLines().map (line) -> line.length
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
@@ -17,7 +20,7 @@ describe "Editor", ->
describe "when the editor is deserialized", ->
it "restores selections and folds based on markers in the buffer", ->
editor.setSelectedBufferRange([[1, 2], [3, 4]])
editor.addSelectionForBufferRange([[5, 6], [7, 5]], isReversed: true)
editor.addSelectionForBufferRange([[5, 6], [7, 5]], reversed: true)
editor.foldBufferRow(4)
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
@@ -31,15 +34,33 @@ describe "Editor", ->
editor2.destroy()
describe "when the editor is constructed with an initialLine option", ->
it "and positions the cursor on the specified line", ->
editor = atom.project.openSync('sample.js', initialLine: 2)
buffer = editor.buffer
expect(editor.getCursor().getBufferPosition().row).toEqual 2
it "positions the cursor on the specified line", ->
editor = null
waitsForPromise ->
atom.workspace.open('sample.less', initialLine: 5).then (o) -> editor = o
runs ->
buffer = editor.buffer
expect(editor.getCursor().getBufferPosition().row).toEqual 5
expect(editor.getCursor().getBufferPosition().column).toEqual 0
describe "when the editor is constructed with an initialColumn option", ->
it "positions the cursor on the specified column", ->
editor = null
waitsForPromise ->
atom.workspace.open('sample.less', initialColumn: 8).then (o) -> editor = o
runs ->
buffer = editor.buffer
expect(editor.getCursor().getBufferPosition().row).toEqual 0
expect(editor.getCursor().getBufferPosition().column).toEqual 8
describe ".copy()", ->
it "returns a different edit session with the same initial state", ->
editor.setSelectedBufferRange([[1, 2], [3, 4]])
editor.addSelectionForBufferRange([[5, 6], [7, 8]], isReversed: true)
editor.addSelectionForBufferRange([[5, 6], [7, 8]], reversed: true)
editor.foldBufferRow(4)
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
@@ -57,21 +78,31 @@ describe "Editor", ->
describe "config defaults", ->
it "uses the `editor.tabLength`, `editor.softWrap`, and `editor.softTabs` config values", ->
editor1 = null
editor2 = null
atom.config.set('editor.tabLength', 4)
atom.config.set('editor.softWrap', true)
atom.config.set('editor.softTabs', false)
editor1 = atom.project.openSync('a')
expect(editor1.getTabLength()).toBe 4
expect(editor1.getSoftWrap()).toBe true
expect(editor1.getSoftTabs()).toBe false
atom.config.set('editor.tabLength', 100)
atom.config.set('editor.softWrap', false)
atom.config.set('editor.softTabs', true)
editor2 = atom.project.openSync('b')
expect(editor2.getTabLength()).toBe 100
expect(editor2.getSoftWrap()).toBe false
expect(editor2.getSoftTabs()).toBe true
waitsForPromise ->
atom.workspace.open('a').then (o) -> editor1 = o
runs ->
expect(editor1.getTabLength()).toBe 4
expect(editor1.getSoftWrap()).toBe true
expect(editor1.getSoftTabs()).toBe false
atom.config.set('editor.tabLength', 100)
atom.config.set('editor.softWrap', false)
atom.config.set('editor.softTabs', true)
waitsForPromise ->
atom.workspace.open('b').then (o) -> editor2 = o
runs ->
expect(editor2.getTabLength()).toBe 100
expect(editor2.getSoftWrap()).toBe false
expect(editor2.getSoftTabs()).toBe true
describe "title", ->
describe ".getTitle()", ->
@@ -665,8 +696,9 @@ describe "Editor", ->
editor.manageScrollPosition = true
editor.setVerticalScrollMargin(2)
editor.setHorizontalScrollMargin(2)
editor.setLineHeight(10)
editor.setLineHeightInPixels(10)
editor.setDefaultCharWidth(10)
editor.setHorizontalScrollbarHeight(0)
editor.setHeight(5.5 * 10)
editor.setWidth(5.5 * 10)
@@ -759,7 +791,7 @@ describe "Editor", ->
expect(selection1.isReversed()).toBeFalsy()
it "merges selections when they intersect when moving up", ->
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]]], isReversed: true)
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]]], reversed: true)
[selection1, selection2] = editor.getSelections()
editor.selectUp()
@@ -770,7 +802,7 @@ describe "Editor", ->
expect(selection1.isReversed()).toBeTruthy()
it "merges selections when they intersect when moving left", ->
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], isReversed: true)
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], reversed: true)
[selection1, selection2] = editor.getSelections()
editor.selectLeft()
@@ -1103,10 +1135,11 @@ describe "Editor", ->
describe "when the 'autoscroll' option is true", ->
it "autoscrolls to the selection", ->
editor.manageScrollPosition = true
editor.setLineHeight(10)
editor.setLineHeightInPixels(10)
editor.setDefaultCharWidth(10)
editor.setHeight(50)
editor.setWidth(50)
editor.setHorizontalScrollbarHeight(0)
expect(editor.getScrollTop()).toBe 0
editor.setSelectedBufferRange([[5, 6], [6, 8]], autoscroll: true)
@@ -1339,10 +1372,14 @@ describe "Editor", ->
expect(selection.isEmpty()).toBeTruthy()
it "does not share selections between different edit sessions for the same buffer", ->
editor2 = atom.project.openSync('sample.js')
editor.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
editor2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]])
expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges()
editor2 = null
waitsForPromise ->
atom.project.open('sample.js').then (o) -> editor2 = o
runs ->
editor.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
editor2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]])
expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges()
describe "buffer manipulation", ->
describe ".insertText(text)", ->
@@ -1694,26 +1731,26 @@ describe "Editor", ->
editor.backspace()
expect(editor.lineForBufferRow(0)).toBe 'var = () {'
describe ".backspaceToBeginningOfWord()", ->
describe ".deleteToBeginningOfWord()", ->
describe "when no text is selected", ->
it "deletes all text between the cursor and the beginning of the word", ->
editor.setCursorBufferPosition([1, 24])
editor.addCursorAtBufferPosition([3, 5])
[cursor1, cursor2] = editor.getCursors()
editor.backspaceToBeginningOfWord()
editor.deleteToBeginningOfWord()
expect(buffer.lineForRow(1)).toBe ' var sort = function(ems) {'
expect(buffer.lineForRow(3)).toBe ' ar pivot = items.shift(), current, left = [], right = [];'
expect(cursor1.getBufferPosition()).toEqual [1, 22]
expect(cursor2.getBufferPosition()).toEqual [3, 4]
editor.backspaceToBeginningOfWord()
editor.deleteToBeginningOfWord()
expect(buffer.lineForRow(1)).toBe ' var sort = functionems) {'
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return itemsar pivot = items.shift(), current, left = [], right = [];'
expect(cursor1.getBufferPosition()).toEqual [1, 21]
expect(cursor2.getBufferPosition()).toEqual [2, 39]
editor.backspaceToBeginningOfWord()
editor.deleteToBeginningOfWord()
expect(buffer.lineForRow(1)).toBe ' var sort = ems) {'
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return ar pivot = items.shift(), current, left = [], right = [];'
expect(cursor1.getBufferPosition()).toEqual [1, 13]
@@ -1721,24 +1758,24 @@ describe "Editor", ->
editor.setText(' var sort')
editor.setCursorBufferPosition([0, 2])
editor.backspaceToBeginningOfWord()
editor.deleteToBeginningOfWord()
expect(buffer.lineForRow(0)).toBe 'var sort'
describe "when text is selected", ->
it "deletes only selected text", ->
editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]])
editor.backspaceToBeginningOfWord()
editor.deleteToBeginningOfWord()
expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {'
expect(buffer.lineForRow(2)).toBe 'if (items.length <= 1) return items;'
describe ".backspaceToBeginningOfLine()", ->
describe ".deleteToBeginningOfLine()", ->
describe "when no text is selected", ->
it "deletes all text between the cursor and the beginning of the line", ->
editor.setCursorBufferPosition([1, 24])
editor.addCursorAtBufferPosition([2, 5])
[cursor1, cursor2] = editor.getCursors()
editor.backspaceToBeginningOfLine()
editor.deleteToBeginningOfLine()
expect(buffer.lineForRow(1)).toBe 'ems) {'
expect(buffer.lineForRow(2)).toBe 'f (items.length <= 1) return items;'
expect(cursor1.getBufferPosition()).toEqual [1, 0]
@@ -1747,13 +1784,13 @@ describe "Editor", ->
describe "when at the beginning of the line", ->
it "deletes the newline", ->
editor.setCursorBufferPosition([2])
editor.backspaceToBeginningOfLine()
editor.deleteToBeginningOfLine()
expect(buffer.lineForRow(1)).toBe ' var sort = function(items) { if (items.length <= 1) return items;'
describe "when text is selected", ->
it "still deletes all text to begginning of the line", ->
editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]])
editor.backspaceToBeginningOfLine()
editor.deleteToBeginningOfLine()
expect(buffer.lineForRow(1)).toBe 'ems) {'
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return items;'
@@ -2026,17 +2063,44 @@ describe "Editor", ->
describe ".copySelectedText()", ->
it "copies selected text onto the clipboard", ->
editor.setSelectedBufferRanges([[[0,4], [0,13]], [[1,6], [1, 10]], [[2,8], [2, 13]]])
editor.copySelectedText()
expect(buffer.lineForRow(0)).toBe "var quicksort = function () {"
expect(buffer.lineForRow(1)).toBe " var sort = function(items) {"
expect(clipboard.readText()).toBe 'quicksort\nsort'
expect(buffer.lineForRow(2)).toBe " if (items.length <= 1) return items;"
expect(clipboard.readText()).toBe 'quicksort\nsort\nitems'
expect(atom.clipboard.readWithMetadata().metadata.selections).toEqual([
'quicksort'
'sort'
'items'
])
describe ".pasteText()", ->
it "pastes text into the buffer", ->
atom.clipboard.write('first')
editor.pasteText()
expect(editor.buffer.lineForRow(0)).toBe "var first = function () {"
expect(buffer.lineForRow(1)).toBe " var first = function(items) {"
expect(editor.lineForBufferRow(0)).toBe "var first = function () {"
expect(editor.lineForBufferRow(1)).toBe " var first = function(items) {"
describe 'when the clipboard has many selections', ->
it "pastes each selection separately into the buffer", ->
atom.clipboard.write('first\nsecond', {selections: ['first', 'second'] })
editor.pasteText()
expect(editor.lineForBufferRow(0)).toBe "var first = function () {"
expect(editor.lineForBufferRow(1)).toBe " var second = function(items) {"
describe 'and the selections count does not match', ->
it "pastes the whole text into the buffer", ->
atom.clipboard.write('first\nsecond\nthird', {selections: ['first', 'second', 'third'] })
editor.pasteText()
expect(editor.lineForBufferRow(0)).toBe "var first"
expect(editor.lineForBufferRow(1)).toBe "second"
expect(editor.lineForBufferRow(2)).toBe "third = function () {"
expect(editor.lineForBufferRow(3)).toBe " var first"
expect(editor.lineForBufferRow(4)).toBe "second"
expect(editor.lineForBufferRow(5)).toBe "third = function(items) {"
describe ".indentSelectedRows()", ->
describe "when nothing is selected", ->
@@ -2225,10 +2289,14 @@ describe "Editor", ->
it "does not explode if the current language mode has no comment regex", ->
editor.destroy()
editor = atom.project.openSync(null, autoIndent: false)
editor.setSelectedBufferRange([[4, 5], [4, 5]])
editor.toggleLineCommentsInSelection()
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
waitsForPromise ->
atom.workspace.open(null, autoIndent: false).then (o) -> editor = o
runs ->
editor.setSelectedBufferRange([[4, 5], [4, 5]])
editor.toggleLineCommentsInSelection()
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
it "uncomments when the line lacks the trailing whitespace in the comment regex", ->
editor.setCursorBufferPosition([10, 0])
@@ -2547,14 +2615,21 @@ describe "Editor", ->
describe "soft-tabs detection", ->
it "assigns soft / hard tabs based on the contents of the buffer, or uses the default if unknown", ->
editor = atom.project.openSync('sample.js', softTabs: false)
expect(editor.getSoftTabs()).toBeTruthy()
waitsForPromise ->
atom.workspace.open('sample.js', softTabs: false).then (editor) ->
expect(editor.getSoftTabs()).toBeTruthy()
editor = atom.project.openSync('sample-with-tabs.coffee', softTabs: true)
expect(editor.getSoftTabs()).toBeFalsy()
waitsForPromise ->
atom.workspace.open('sample-with-tabs.coffee', softTabs: true).then (editor) ->
expect(editor.getSoftTabs()).toBeFalsy()
editor = atom.project.openSync(null, softTabs: false)
expect(editor.getSoftTabs()).toBeFalsy()
waitsForPromise ->
atom.workspace.open('sample-with-tabs-and-initial-comment.js', softTabs: true).then (editor) ->
expect(editor.getSoftTabs()).toBeFalsy()
waitsForPromise ->
atom.workspace.open(null, softTabs: false).then (editor) ->
expect(editor.getSoftTabs()).toBeFalsy()
describe ".indentLevelForLine(line)", ->
it "returns the indent level when the line has only leading whitespace", ->
@@ -2578,16 +2653,21 @@ describe "Editor", ->
describe "when a better-matched grammar is added to syntax", ->
it "switches to the better-matched grammar and re-tokenizes the buffer", ->
editor.destroy()
jsGrammar = atom.syntax.selectGrammar('a.js')
atom.syntax.removeGrammar(jsGrammar)
editor2 = atom.project.openSync('sample.js', autoIndent: false)
expect(editor2.getGrammar()).toBe atom.syntax.nullGrammar
expect(editor2.lineForScreenRow(0).tokens.length).toBe 1
waitsForPromise ->
atom.workspace.open('sample.js', autoIndent: false).then (o) -> editor = o
atom.syntax.addGrammar(jsGrammar)
expect(editor2.getGrammar()).toBe jsGrammar
expect(editor2.lineForScreenRow(0).tokens.length).toBeGreaterThan 1
runs ->
expect(editor.getGrammar()).toBe atom.syntax.nullGrammar
expect(editor.lineForScreenRow(0).tokens.length).toBe 1
atom.syntax.addGrammar(jsGrammar)
expect(editor.getGrammar()).toBe jsGrammar
expect(editor.lineForScreenRow(0).tokens.length).toBeGreaterThan 1
describe "auto-indent", ->
copyText = (text, {startColumn}={}) ->
@@ -2874,10 +2954,15 @@ describe "Editor", ->
expect(editor.shouldPromptToSave()).toBeFalsy()
buffer.setText('changed')
expect(editor.shouldPromptToSave()).toBeTruthy()
editor2 = atom.project.openSync('sample.js', autoIndent: false)
expect(editor.shouldPromptToSave()).toBeFalsy()
editor2.destroy()
expect(editor.shouldPromptToSave()).toBeTruthy()
editor2 = null
waitsForPromise ->
atom.project.open('sample.js', autoIndent: false).then (o) -> editor2 = o
runs ->
expect(editor.shouldPromptToSave()).toBeFalsy()
editor2.destroy()
expect(editor.shouldPromptToSave()).toBeTruthy()
describe "when the edit session contains surrogate pair characters", ->
it "correctly backspaces over them", ->
@@ -2973,12 +3058,15 @@ describe "Editor", ->
describe "when the grammar is added", ->
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
editor = atom.project.openSync('sample.js')
editor.setText("// http://github.com")
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor = o
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " http://github.com"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
runs ->
editor.setText("// http://github.com")
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " http://github.com"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
waitsForPromise ->
atom.packages.activatePackage('language-hyperlink')
@@ -2990,12 +3078,15 @@ describe "Editor", ->
describe "when the grammar is updated", ->
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
editor = atom.project.openSync('sample.js')
editor.setText("// SELECT * FROM OCTOCATS")
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor = o
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
runs ->
editor.setText("// SELECT * FROM OCTOCATS")
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
waitsForPromise ->
atom.packages.activatePackage('package-with-injection-selector')
@@ -3032,10 +3123,11 @@ describe "Editor", ->
describe ".scrollToCursorPosition()", ->
it "scrolls the last cursor into view", ->
editor.setCursorScreenPosition([8, 8])
editor.setLineHeight(10)
editor.setLineHeightInPixels(10)
editor.setDefaultCharWidth(10)
editor.setHeight(50)
editor.setWidth(50)
editor.setHorizontalScrollbarHeight(0)
expect(editor.getScrollTop()).toBe 0
expect(editor.getScrollLeft()).toBe 0
@@ -3047,7 +3139,7 @@ describe "Editor", ->
it "scrolls one screen height up or down", ->
editor.manageScrollPosition = true
editor.setLineHeight(10)
editor.setLineHeightInPixels(10)
editor.setHeight(50)
expect(editor.getScrollHeight()).toBe 130
+183 -96
Ver Arquivo
@@ -7,28 +7,36 @@ path = require 'path'
temp = require 'temp'
describe "EditorView", ->
[buffer, editorView, editor, cachedLineHeight, cachedCharWidth] = []
[buffer, editorView, editor, cachedEditor, cachedLineHeight, cachedCharWidth, fart] = []
beforeEach ->
editor = atom.project.openSync('sample.js')
buffer = editor.buffer
editorView = new EditorView(editor)
editorView.lineOverdraw = 2
editorView.isFocused = true
editorView.enableKeymap()
editorView.calculateHeightInLines = ->
Math.ceil(@height() / @lineHeight)
editorView.attachToDom = ({ heightInLines, widthInChars } = {}) ->
heightInLines ?= @getEditor().getBuffer().getLineCount()
@height(getLineHeight() * heightInLines)
@width(getCharWidth() * widthInChars) if widthInChars
$('#jasmine-content').append(this)
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor = o
waitsForPromise ->
atom.packages.activatePackage('language-text', sync: true)
atom.workspace.open('sample.less').then (o) -> cachedEditor = o
runs ->
buffer = editor.buffer
editorView = new EditorView(editor)
editorView.lineOverdraw = 2
editorView.isFocused = true
editorView.enableKeymap()
editorView.calculateHeightInLines = ->
Math.ceil(@height() / @lineHeight)
editorView.attachToDom = ({ heightInLines, widthInChars } = {}) ->
heightInLines ?= @getEditor().getBuffer().getLineCount()
@height(getLineHeight() * heightInLines)
@width(getCharWidth() * widthInChars) if widthInChars
$('#jasmine-content').append(this)
waitsForPromise ->
atom.packages.activatePackage('language-javascript', sync: true)
atom.packages.activatePackage('language-text')
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
getLineHeight = ->
return cachedLineHeight if cachedLineHeight?
@@ -41,7 +49,7 @@ describe "EditorView", ->
cachedCharWidth
calcDimensions = ->
editorForMeasurement = new EditorView(editor: atom.project.openSync('sample.js'))
editorForMeasurement = new EditorView({editor: cachedEditor})
editorForMeasurement.attachToDom()
cachedLineHeight = editorForMeasurement.lineHeight
cachedCharWidth = editorForMeasurement.charWidth
@@ -105,18 +113,23 @@ describe "EditorView", ->
describe "when the editor's file is modified on disk", ->
it "triggers an alert", ->
fileChangeHandler = null
filePath = path.join(temp.dir, 'atom-changed-file.txt')
fs.writeFileSync(filePath, "")
editor = atom.project.openSync(filePath)
editorView.edit(editor)
editor.insertText("now the buffer is modified")
fileChangeHandler = jasmine.createSpy('fileChange')
editor.buffer.file.on 'contents-changed', fileChangeHandler
waitsForPromise ->
atom.workspace.open(filePath).then (o) -> editor = o
spyOn(atom, "confirm")
runs ->
editorView.edit(editor)
editor.insertText("now the buffer is modified")
fs.writeFileSync(filePath, "a file change")
fileChangeHandler = jasmine.createSpy('fileChange')
editor.buffer.file.on 'contents-changed', fileChangeHandler
spyOn(atom, "confirm")
fs.writeFileSync(filePath, "a file change")
waitsFor "file to trigger contents-changed event", ->
fileChangeHandler.callCount > 0
@@ -133,8 +146,11 @@ describe "EditorView", ->
[newEditor, newBuffer] = []
beforeEach ->
newEditor = atom.project.openSync('two-hundred.txt')
newBuffer = newEditor.buffer
waitsForPromise ->
atom.workspace.open('two-hundred.txt').then (o) -> newEditor = o
runs ->
newBuffer = newEditor.buffer
it "updates the rendered lines, cursors, selections, scroll position, and event subscriptions to match the given edit session", ->
editorView.attachToDom(heightInLines: 5, widthInChars: 30)
@@ -170,17 +186,24 @@ describe "EditorView", ->
expect(editorView.lineElementForScreenRow(6).text()).toMatch /^ currentgoodbye/
it "triggers alert if edit session's buffer goes into conflict with changes on disk", ->
contentsConflictedHandler = null
filePath = path.join(temp.dir, 'atom-changed-file.txt')
fs.writeFileSync(filePath, "")
tempEditor = atom.project.openSync(filePath)
editorView.edit(tempEditor)
tempEditor.insertText("a buffer change")
tempEditor = null
spyOn(atom, "confirm")
waitsForPromise ->
atom.workspace.open(filePath).then (o) -> tempEditor = o
runs ->
editorView.edit(tempEditor)
tempEditor.insertText("a buffer change")
spyOn(atom, "confirm")
contentsConflictedHandler = jasmine.createSpy("contentsConflictedHandler")
tempEditor.on 'contents-conflicted', contentsConflictedHandler
fs.writeFileSync(filePath, "a file change")
contentsConflictedHandler = jasmine.createSpy("contentsConflictedHandler")
tempEditor.on 'contents-conflicted', contentsConflictedHandler
fs.writeFileSync(filePath, "a file change")
waitsFor ->
contentsConflictedHandler.callCount > 0
@@ -281,26 +304,34 @@ describe "EditorView", ->
it "emits event when editor view view receives a new buffer", ->
eventHandler = jasmine.createSpy('eventHandler')
editorView.on 'editor:path-changed', eventHandler
editorView.edit(atom.project.openSync(filePath))
expect(eventHandler).toHaveBeenCalled()
waitsForPromise ->
atom.workspace.open(filePath).then (editor) ->
editorView.edit(editor)
runs ->
expect(eventHandler).toHaveBeenCalled()
it "stops listening to events on previously set buffers", ->
eventHandler = jasmine.createSpy('eventHandler')
oldBuffer = editor.getBuffer()
newEditor = atom.project.openSync(filePath)
editorView.on 'editor:path-changed', eventHandler
newEditor = null
waitsForPromise ->
atom.workspace.open(filePath).then (o) -> newEditor = o
editorView.edit(newEditor)
expect(eventHandler).toHaveBeenCalled()
runs ->
editorView.on 'editor:path-changed', eventHandler
eventHandler.reset()
oldBuffer.saveAs(path.join(temp.dir, 'atom-bad.txt'))
expect(eventHandler).not.toHaveBeenCalled()
editorView.edit(newEditor)
expect(eventHandler).toHaveBeenCalled()
eventHandler.reset()
newEditor.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt'))
expect(eventHandler).toHaveBeenCalled()
eventHandler.reset()
oldBuffer.saveAs(path.join(temp.dir, 'atom-bad.txt'))
expect(eventHandler).not.toHaveBeenCalled()
eventHandler.reset()
newEditor.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt'))
expect(eventHandler).toHaveBeenCalled()
it "loads the grammar for the new path", ->
expect(editor.getGrammar().name).toBe 'JavaScript'
@@ -478,7 +509,7 @@ describe "EditorView", ->
expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]]
describe "when clicking between a word and a non-word", ->
describe "when double-clicking between a word and a non-word", ->
it "selects the word", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 21], originalEvent: {detail: 1})
@@ -501,6 +532,30 @@ describe "EditorView", ->
editorView.renderedLines.trigger 'mouseup'
expect(editor.getSelectedText()).toBe "{"
describe "when double-clicking on whitespace", ->
it "selects all adjacent whitespace", ->
editor.setText(" some text ")
editor.setCursorBufferPosition([0, 2])
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 2], originalEvent: {detail: 1})
editorView.renderedLines.trigger 'mouseup'
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 2], originalEvent: {detail: 2})
editorView.renderedLines.trigger 'mouseup'
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 3]]
editor.setCursorBufferPosition([0, 8])
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 1})
editorView.renderedLines.trigger 'mouseup'
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 2})
editorView.renderedLines.trigger 'mouseup'
expect(editor.getSelectedBufferRange()).toEqual [[0, 7], [0, 9]]
editor.setCursorBufferPosition([0, 14])
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 14], originalEvent: {detail: 1})
editorView.renderedLines.trigger 'mouseup'
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 14], originalEvent: {detail: 2})
editorView.renderedLines.trigger 'mouseup'
expect(editor.getSelectedBufferRange()).toEqual [[0, 13], [0, 17]]
describe "triple/quardruple/etc-click", ->
it "selects the line under the cursor", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
@@ -1529,14 +1584,18 @@ describe "EditorView", ->
describe "when autoscrolling at the end of the document", ->
it "renders lines properly", ->
editorView.edit(atom.project.openSync('two-hundred.txt'))
editorView.attachToDom(heightInLines: 5.5)
waitsForPromise ->
atom.workspace.open('two-hundred.txt').then (editor) ->
editorView.edit(editor)
expect(editorView.renderedLines.find('.line').length).toBe 8
runs ->
editorView.attachToDom(heightInLines: 5.5)
editor.moveCursorToBottom()
expect(editorView.renderedLines.find('.line').length).toBe 8
expect(editorView.renderedLines.find('.line').length).toBe 8
editor.moveCursorToBottom()
expect(editorView.renderedLines.find('.line').length).toBe 8
describe "when line has a character that could push it to be too tall (regression)", ->
it "does renders the line at a consistent height", ->
@@ -1744,6 +1803,13 @@ describe "EditorView", ->
expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} "
expect(editorView.renderedLines.find('.line:eq(10) .invisible-character').text()).toBe eol
describe "when editor.showIndentGuide is set to false", ->
it "does not render the indent guide on whitespace only lines (regression)", ->
editorView.attachToDom()
editor.setText(' ')
atom.config.set('editor.showIndentGuide', false)
expect(editorView.renderedLines.find('.line:eq(0) .indent-guide').length).toBe 0
describe "when soft-wrap is enabled", ->
beforeEach ->
jasmine.unspy(window, 'setTimeout')
@@ -1784,10 +1850,14 @@ describe "EditorView", ->
expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60]
it "does not wrap the lines of any newly assigned buffers", ->
otherEditor = atom.project.openSync()
otherEditor.buffer.setText([1..100].join(''))
editorView.edit(otherEditor)
expect(editorView.renderedLines.find('.line').length).toBe(1)
otherEditor = null
waitsForPromise ->
atom.workspace.open().then (o) -> otherEditor = o
runs ->
otherEditor.buffer.setText([1..100].join(''))
editorView.edit(otherEditor)
expect(editorView.renderedLines.find('.line').length).toBe(1)
it "unwraps lines when softwrap is disabled", ->
editorView.toggleSoftWrap()
@@ -1816,15 +1886,15 @@ describe "EditorView", ->
expect(editor.getCursorScreenPosition()).toEqual [11, 0]
it "calls .setWidthInChars() when the editor view is attached because now its dimensions are available to calculate it", ->
otherEditor = new EditorView(editor: atom.project.openSync('sample.js'))
spyOn(otherEditor, 'setWidthInChars')
otherEditorView = new EditorView(editor)
spyOn(otherEditorView, 'setWidthInChars')
otherEditor.editor.setSoftWrap(true)
expect(otherEditor.setWidthInChars).not.toHaveBeenCalled()
otherEditorView.editor.setSoftWrap(true)
expect(otherEditorView.setWidthInChars).not.toHaveBeenCalled()
otherEditor.simulateDomAttachment()
expect(otherEditor.setWidthInChars).toHaveBeenCalled()
otherEditor.remove()
otherEditorView.simulateDomAttachment()
expect(otherEditorView.setWidthInChars).toHaveBeenCalled()
otherEditorView.remove()
describe "when the editor view's width changes", ->
it "updates the width in characters on the edit session", ->
@@ -1975,15 +2045,19 @@ describe "EditorView", ->
describe "when the switching from an edit session for a long buffer to an edit session for a short buffer", ->
it "updates the line numbers to reflect the shorter buffer", ->
emptyEditor = atom.project.openSync(null)
editorView.edit(emptyEditor)
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
emptyEditor = null
waitsForPromise ->
atom.workspace.open().then (o) -> emptyEditor = o
editorView.edit(editor)
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1
runs ->
editorView.edit(emptyEditor)
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
editorView.edit(emptyEditor)
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
editorView.edit(editor)
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1
editorView.edit(emptyEditor)
expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1
describe "when the editor view is mini", ->
it "hides the gutter", ->
@@ -2203,10 +2277,13 @@ describe "EditorView", ->
describe "folding", ->
beforeEach ->
editor = atom.project.openSync('two-hundred.txt')
buffer = editor.buffer
editorView.edit(editor)
editorView.attachToDom()
waitsForPromise ->
atom.workspace.open('two-hundred.txt').then (o) -> editor = o
runs ->
buffer = editor.buffer
editorView.edit(editor)
editorView.attachToDom()
describe "when a fold-selection event is triggered", ->
it "folds the lines covered by the selection into a single line with a fold class and marker", ->
@@ -2260,7 +2337,7 @@ describe "EditorView", ->
it "adds/removes the 'fold-selected' class to the fold's line element and hides the cursor if it is on the fold line", ->
editor.createFold(2, 4)
editor.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, isReversed: true)
editor.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, reversed: true)
expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected')
editor.setSelectedBufferRange([[1, 0], [1, 1]], preserveFolds: true)
@@ -2341,8 +2418,11 @@ describe "EditorView", ->
beforeEach ->
filePath = atom.project.resolve('git/working-dir/file.txt')
originalPathText = fs.readFileSync(filePath, 'utf8')
editor = atom.project.openSync(filePath)
editorView.edit(editor)
waitsForPromise ->
atom.workspace.open(filePath).then (o) -> editor = o
runs ->
editorView.edit(editor)
afterEach ->
fs.writeFileSync(filePath, originalPathText)
@@ -2816,7 +2896,7 @@ describe "EditorView", ->
describe "when the escape key is pressed on the editor view", ->
it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", ->
atom.keymaps.bindKeys 'name', '.editor', {'escape': 'test-event'}
atom.keymaps.add 'name', '.editor': {'escape': 'test-event'}
testEventHandler = jasmine.createSpy("testEventHandler")
editorView.on 'test-event', testEventHandler
@@ -2833,22 +2913,26 @@ describe "EditorView", ->
describe "when the editor view is attached but invisible", ->
describe "when the editor view's text is changed", ->
it "redraws the editor view when it is next shown", ->
displayUpdatedHandler = null
atom.workspaceView = new WorkspaceView
atom.workspaceView.openSync('sample.js')
atom.workspaceView.attachToDom()
editorView = atom.workspaceView.getActiveView()
waitsForPromise ->
atom.workspaceView.open('sample.txt').then (o) -> editor = o
view = $$ -> @div id: 'view', tabindex: -1, 'View'
editorView.getPane().activateItem(view)
expect(editorView.isVisible()).toBeFalsy()
runs ->
atom.workspaceView.attachToDom()
editorView = atom.workspaceView.getActiveView()
editor.setText('hidden changes')
editor.setCursorBufferPosition([0,4])
view = $$ -> @div id: 'view', tabindex: -1, 'View'
editorView.getPane().activateItem(view)
expect(editorView.isVisible()).toBeFalsy()
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
editorView.on 'editor:display-updated', displayUpdatedHandler
editorView.getPane().activateItem(editorView.getModel())
expect(editorView.isVisible()).toBeTruthy()
editor.setText('hidden changes')
editor.setCursorBufferPosition([0,4])
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
editorView.on 'editor:display-updated', displayUpdatedHandler
editorView.getPane().activateItem(editorView.getModel())
expect(editorView.isVisible()).toBeTruthy()
waitsFor ->
displayUpdatedHandler.callCount is 1
@@ -2888,14 +2972,17 @@ describe "EditorView", ->
describe "when the editor view is removed", ->
it "fires a editor:will-be-removed event", ->
atom.workspaceView = new WorkspaceView
atom.workspaceView.openSync('sample.js')
atom.workspaceView.attachToDom()
editorView = atom.workspaceView.getActiveView()
waitsForPromise ->
atom.workspace.open('sample.js')
willBeRemovedHandler = jasmine.createSpy('willBeRemovedHandler')
editorView.on 'editor:will-be-removed', willBeRemovedHandler
editorView.getPane().destroyActiveItem()
expect(willBeRemovedHandler).toHaveBeenCalled()
runs ->
atom.workspaceView.attachToDom()
editorView = atom.workspaceView.getActiveView()
willBeRemovedHandler = jasmine.createSpy('willBeRemovedHandler')
editorView.on 'editor:will-be-removed', willBeRemovedHandler
editorView.getPane().destroyActiveItem()
expect(willBeRemovedHandler).toHaveBeenCalled()
describe "when setInvisibles is toggled (regression)", ->
it "renders inserted newlines properly", ->
+8
Ver Arquivo
@@ -0,0 +1,8 @@
/**
* Look, this is a comment. Don't go making assumtions that I want soft tabs
* because this block comment has leading spaces, Geez.
*/
if (beNice) {
console.log('Thank you for being nice.');
}
+11 -5
Ver Arquivo
@@ -229,8 +229,11 @@ describe "Git", ->
[originalContent, editor] = []
beforeEach ->
editor = atom.project.openSync('sample.js')
originalContent = editor.getText()
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor = o
runs ->
originalContent = editor.getText()
afterEach ->
fs.writeFileSync(editor.getPath(), originalContent)
@@ -274,9 +277,12 @@ describe "Git", ->
project2?.destroy()
it "subscribes to all the serialized buffers in the project", ->
atom.project.openSync('sample.js')
project2 = atom.project.testSerialization()
buffer = project2.getBuffers()[0]
waitsForPromise ->
atom.workspace.open('sample.js')
runs ->
project2 = atom.project.testSerialization()
buffer = project2.getBuffers()[0]
waitsFor ->
buffer.loaded
+35 -18
Ver Arquivo
@@ -6,8 +6,10 @@ describe "LanguageMode", ->
describe "javascript", ->
beforeEach ->
editor = atom.project.openSync('sample.js', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('sample.js', autoIndent: false).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
@@ -112,8 +114,10 @@ describe "LanguageMode", ->
describe "coffeescript", ->
beforeEach ->
editor = atom.project.openSync('coffee.coffee', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('coffee.coffee', autoIndent: false).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
@@ -161,8 +165,10 @@ describe "LanguageMode", ->
describe "css", ->
beforeEach ->
editor = atom.project.openSync('css.css', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('css.css', autoIndent: false).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-css')
@@ -178,13 +184,13 @@ describe "LanguageMode", ->
languageMode.toggleLineCommentsForBufferRows(2, 2)
expect(buffer.lineForRow(0)).toBe "/*body {"
expect(buffer.lineForRow(1)).toBe " font-size: 1234px;*/"
expect(buffer.lineForRow(2)).toBe "/* width: 110%;*/"
expect(buffer.lineForRow(2)).toBe " /*width: 110%;*/"
expect(buffer.lineForRow(3)).toBe " font-weight: bold !important;"
languageMode.toggleLineCommentsForBufferRows(0, 1)
expect(buffer.lineForRow(0)).toBe "body {"
expect(buffer.lineForRow(1)).toBe " font-size: 1234px;"
expect(buffer.lineForRow(2)).toBe "/* width: 110%;*/"
expect(buffer.lineForRow(2)).toBe " /*width: 110%;*/"
expect(buffer.lineForRow(3)).toBe " font-weight: bold !important;"
it "uncomments lines with leading whitespace", ->
@@ -204,8 +210,10 @@ describe "LanguageMode", ->
describe "less", ->
beforeEach ->
editor = atom.project.openSync('sample.less', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('sample.less', autoIndent: false).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-less')
@@ -220,9 +228,11 @@ describe "LanguageMode", ->
describe "xml", ->
beforeEach ->
editor = atom.project.openSync('sample.xml', autoIndent: false)
editor.setText("<!-- test -->")
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('sample.xml', autoIndent: false).then (o) ->
editor = o
editor.setText("<!-- test -->")
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-xml')
@@ -234,8 +244,10 @@ describe "LanguageMode", ->
describe "folding", ->
beforeEach ->
editor = atom.project.openSync('sample.js', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('sample.js', autoIndent: false).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
@@ -319,8 +331,10 @@ describe "LanguageMode", ->
describe "folding with comments", ->
beforeEach ->
editor = atom.project.openSync('sample-with-comments.js', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.workspace.open('sample-with-comments.js', autoIndent: false).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
@@ -385,7 +399,10 @@ describe "LanguageMode", ->
describe "css", ->
beforeEach ->
editor = atom.project.openSync('css.css', autoIndent: true)
waitsForPromise ->
atom.workspace.open('css.css', autoIndent: true).then (o) ->
editor = o
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-source')
+21 -10
Ver Arquivo
@@ -21,11 +21,16 @@ describe "PaneView", ->
container = new PaneContainerView
view1 = new TestView(id: 'view-1', text: 'View 1')
view2 = new TestView(id: 'view-2', text: 'View 2')
editor1 = atom.project.openSync('sample.js')
editor2 = atom.project.openSync('sample.txt')
pane = container.getRoot()
paneModel = pane.model
paneModel.addItems([view1, editor1, view2, editor2])
waitsForPromise ->
atom.workspace.open('sample.js').then (o) -> editor1 = o
waitsForPromise ->
atom.workspace.open('sample.txt').then (o) -> editor2 = o
runs ->
pane = container.getRoot()
paneModel = pane.model
paneModel.addItems([view1, editor1, view2, editor2])
afterEach ->
atom.deserializers.remove(TestView)
@@ -159,14 +164,20 @@ describe "PaneView", ->
describe "when an unmodifed buffer's path is deleted", ->
it "removes the pane item", ->
editor = null
jasmine.unspy(window, 'setTimeout')
filePath = temp.openSync('atom').path
editor = atom.project.openSync(filePath)
pane.activateItem(editor)
expect(pane.items).toHaveLength(5)
fs.removeSync(filePath)
waitsFor -> pane.items.length == 4
waitsForPromise ->
atom.workspace.open(filePath).then (o) -> editor = o
runs ->
pane.activateItem(editor)
expect(pane.items).toHaveLength(5)
fs.removeSync(filePath)
waitsFor ->
pane.items.length == 4
describe "when a pane is destroyed", ->
[pane2, pane2Model] = []
+67 -75
Ver Arquivo
@@ -18,62 +18,39 @@ describe "Project", ->
deserializedProject?.destroy()
it "does not include unretained buffers in the serialized state", ->
atom.project.bufferForPathSync('a')
expect(atom.project.getBuffers().length).toBe 1
waitsForPromise ->
atom.project.bufferForPath('a')
deserializedProject = atom.project.testSerialization()
expect(deserializedProject.getBuffers().length).toBe 0
runs ->
expect(atom.project.getBuffers().length).toBe 1
deserializedProject = atom.project.testSerialization()
expect(deserializedProject.getBuffers().length).toBe 0
it "listens for destroyed events on deserialized buffers and removes them when they are destroyed", ->
atom.project.openSync('a')
expect(atom.project.getBuffers().length).toBe 1
deserializedProject = atom.project.testSerialization()
waitsForPromise ->
atom.project.open('a')
expect(deserializedProject.getBuffers().length).toBe 1
deserializedProject.getBuffers()[0].destroy()
expect(deserializedProject.getBuffers().length).toBe 0
runs ->
expect(atom.project.getBuffers().length).toBe 1
deserializedProject = atom.project.testSerialization()
expect(deserializedProject.getBuffers().length).toBe 1
deserializedProject.getBuffers()[0].destroy()
expect(deserializedProject.getBuffers().length).toBe 0
describe "when an editor is saved and the project has no path", ->
it "sets the project's path to the saved file's parent directory", ->
tempFile = temp.openSync().path
atom.project.setPath(undefined)
expect(atom.project.getPath()).toBeUndefined()
editor = atom.project.openSync()
editor.saveAs(tempFile)
expect(atom.project.getPath()).toBe path.dirname(tempFile)
editor = null
describe ".openSync(path)", ->
[absolutePath, newBufferHandler] = []
beforeEach ->
absolutePath = require.resolve('./fixtures/dir/a')
newBufferHandler = jasmine.createSpy('newBufferHandler')
atom.project.on 'buffer-created', newBufferHandler
waitsForPromise ->
atom.project.open().then (o) -> editor = o
describe "when given an absolute path that hasn't been opened previously", ->
it "returns a new edit session for the given path and emits 'buffer-created'", ->
editor = atom.project.openSync(absolutePath)
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
describe "when given a relative path that hasn't been opened previously", ->
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created'", ->
editor = atom.project.openSync('a')
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
describe "when passed the path to a buffer that has already been opened", ->
it "returns a new edit session containing previously opened buffer", ->
editor = atom.project.openSync(absolutePath)
newBufferHandler.reset()
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
expect(atom.project.openSync('a').buffer).toBe editor.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created'", ->
editor = atom.project.openSync()
expect(editor.buffer.getPath()).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
runs ->
editor.saveAs(tempFile)
expect(atom.project.getPath()).toBe path.dirname(tempFile)
describe ".open(path)", ->
[absolutePath, newBufferHandler] = []
@@ -106,14 +83,21 @@ describe "Project", ->
describe "when passed the path to a buffer that is currently opened", ->
it "returns a new edit session containing currently opened buffer", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
newBufferHandler.reset()
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
expect(atom.project.openSync('a').buffer).toBe editor.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
waitsForPromise ->
atom.project.open(absolutePath).then ({buffer}) ->
expect(buffer).toBe editor.buffer
waitsForPromise ->
atom.project.open('a').then ({buffer}) ->
expect(buffer).toBe editor.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created'", ->
@@ -137,20 +121,6 @@ describe "Project", ->
runs ->
expect(totalBytes).toBe fs.statSync(filePath).size
describe ".bufferForPathSync(path)", ->
describe "when opening a previously opened path", ->
it "does not create a new buffer", ->
buffer = atom.project.bufferForPathSync("a").retain()
expect(atom.project.bufferForPathSync("a")).toBe buffer
alternativeBuffer = atom.project.bufferForPathSync("b").retain().release()
expect(alternativeBuffer).not.toBe buffer
buffer.release()
it "creates a new buffer if the previous buffer was destroyed", ->
buffer = atom.project.bufferForPathSync("a").retain().release()
expect(atom.project.bufferForPathSync("a").retain().release()).not.toBe buffer
describe ".bufferForPath(path)", ->
[buffer] = []
beforeEach ->
@@ -240,10 +210,15 @@ describe "Project", ->
describe "when a buffer is already open", ->
it "replaces properly and saves when not modified", ->
editor = atom.project.openSync('sample.js')
expect(editor.isModified()).toBeFalsy()
editor = null
results = []
waitsForPromise ->
atom.project.open('sample.js').then (o) -> editor = o
runs ->
expect(editor.isModified()).toBeFalsy()
waitsForPromise ->
atom.project.replace /items/gi, 'items', [filePath], (result) ->
results.push(result)
@@ -256,10 +231,12 @@ describe "Project", ->
expect(editor.isModified()).toBeFalsy()
it "does not replace when the path is not specified", ->
editor = atom.project.openSync('sample.js')
editor = atom.project.openSync('sample-with-comments.js')
editor = null
results = []
waitsForPromise ->
atom.project.open('sample-with-comments.js').then (o) -> editor = o
waitsForPromise ->
atom.project.replace /items/gi, 'items', [commentFilePath], (result) ->
results.push(result)
@@ -269,11 +246,16 @@ describe "Project", ->
expect(results[0].filePath).toBe commentFilePath
it "does NOT save when modified", ->
editor = atom.project.openSync('sample.js')
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
expect(editor.isModified()).toBeTruthy()
editor = null
results = []
waitsForPromise ->
atom.project.open('sample.js').then (o) -> editor = o
runs ->
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
expect(editor.isModified()).toBeTruthy()
waitsForPromise ->
atom.project.replace /items/gi, 'okthen', [filePath], (result) ->
results.push(result)
@@ -437,9 +419,14 @@ describe "Project", ->
expect(resultHandler).not.toHaveBeenCalled()
it "scans buffer contents if the buffer is modified", ->
editor = atom.project.openSync("a")
editor.setText("Elephant")
editor = null
results = []
waitsForPromise ->
atom.project.open('a').then (o) ->
editor = o
editor.setText("Elephant")
waitsForPromise ->
atom.project.scan /a|Elephant/, (result) -> results.push result
@@ -450,9 +437,14 @@ describe "Project", ->
expect(resultForA.matches[0].matchText).toBe 'Elephant'
it "ignores buffers outside the project", ->
editor = atom.project.openSync(temp.openSync().path)
editor.setText("Elephant")
editor = null
results = []
waitsForPromise ->
atom.project.open(temp.openSync().path).then (o) ->
editor = o
editor.setText("Elephant")
waitsForPromise ->
atom.project.scan /Elephant/, (result) -> results.push result
+1 -1
Ver Arquivo
@@ -58,7 +58,7 @@ describe "Selection", ->
describe "when only the selection's tail is moved (regression)", ->
it "emits the 'screen-range-changed' event", ->
selection.setBufferRange([[2, 0], [2, 10]], isReversed: true)
selection.setBufferRange([[2, 0], [2, 10]], reversed: true)
changeScreenRangeHandler = jasmine.createSpy('changeScreenRangeHandler')
selection.on 'screen-range-changed', changeScreenRangeHandler
+39 -4
Ver Arquivo
@@ -6,6 +6,7 @@ require '../vendor/jasmine-jquery'
path = require 'path'
_ = require 'underscore-plus'
fs = require 'fs-plus'
Grim = require 'grim'
KeymapManager = require '../src/keymap-extensions'
{$, WorkspaceView, Workspace} = require 'atom'
Config = require '../src/config'
@@ -37,6 +38,7 @@ jasmine.getEnv().defaultTimeoutInterval = 5000
specPackageName = null
specPackagePath = null
specProjectPath = null
isCoreSpec = false
{specDirectory, resourcePath} = atom.getLoadSettings()
@@ -46,7 +48,10 @@ if specDirectory
specPackageName = JSON.parse(fs.readFileSync(path.join(specPackagePath, 'package.json')))?.name
specProjectPath = path.join(specDirectory, 'fixtures')
isCoreSpec = specDirectory == fs.realpathSync(__dirname)
beforeEach ->
Grim.clearDeprecations() if isCoreSpec
$.fx.off = true
projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures')
atom.project = new Project(path: projectPath)
@@ -124,6 +129,7 @@ afterEach ->
jasmine.unspy(atom, 'saveSync')
ensureNoPathSubscriptions()
atom.syntax.off()
ensureNoDeprecatedFunctionsCalled() if isCoreSpec
waits(0) # yield to ui thread to make screen update more frequently
ensureNoPathSubscriptions = ->
@@ -132,6 +138,27 @@ ensureNoPathSubscriptions = ->
if watchedPaths.length > 0
throw new Error("Leaking subscriptions for paths: " + watchedPaths.join(", "))
ensureNoDeprecatedFunctionsCalled = ->
deprecations = Grim.getDeprecations()
if deprecations.length > 0
originalPrepareStackTrace = Error.prepareStackTrace
Error.prepareStackTrace = (error, stack) ->
output = []
for deprecation in deprecations
output.push "#{deprecation.originName} is deprecated. #{deprecation.message}"
output.push _.multiplyString("-", output[output.length - 1].length)
for stack in deprecation.getStacks()
for {functionName, location} in stack
output.push "#{functionName} -- #{location}"
output.push ""
output.join("\n")
error = new Error("Deprecated function(s) #{deprecations.map(({originName}) -> originName).join ', '}) were called.")
error.stack
Error.prepareStackTrace = originalPrepareStackTrace
throw error
emitObject = jasmine.StringPrettyPrinter.prototype.emitObject
jasmine.StringPrettyPrinter.prototype.emitObject = (obj) ->
if obj.inspect
@@ -234,7 +261,9 @@ window.waitsForPromise = (args...) ->
window.resetTimeouts = ->
window.now = 0
window.timeoutCount = 0
window.intervalCount = 0
window.timeouts = []
window.intervalTimeouts = {}
window.fakeSetTimeout = (callback, ms) ->
id = ++window.timeoutCount
@@ -245,13 +274,15 @@ window.fakeClearTimeout = (idToClear) ->
window.timeouts = window.timeouts.filter ([id]) -> id != idToClear
window.fakeSetInterval = (callback, ms) ->
id = ++window.intervalCount
action = ->
callback()
window.fakeSetTimeout(action, ms)
window.fakeSetTimeout(action, ms)
window.intervalTimeouts[id] = window.fakeSetTimeout(action, ms)
window.intervalTimeouts[id] = window.fakeSetTimeout(action, ms)
id
window.fakeClearInterval = (idToClear) ->
window.fakeClearTimeout(idToClear)
window.fakeClearTimeout(@intervalTimeouts[idToClear])
window.advanceClock = (delta=1) ->
window.now += delta
@@ -289,7 +320,11 @@ $.fn.resultOfTrigger = (type) ->
event.result
$.fn.enableKeymap = ->
@on 'keydown', (e) => atom.keymaps.handleKeyEvent(e)
@on 'keydown', (e) ->
originalEvent = e.originalEvent ? e
Object.defineProperty(originalEvent, 'target', get: -> e.target) unless originalEvent.target?
atom.keymaps.handleKeyboardEvent(originalEvent)
not e.originalEvent.defaultPrevented
$.fn.attachToDom = ->
@appendTo($('#jasmine-content'))
+40 -6
Ver Arquivo
@@ -20,7 +20,7 @@ describe "ThemeManager", ->
describe "theme getters and setters", ->
beforeEach ->
atom.packages.loadPackages(sync: true)
atom.packages.loadPackages()
it 'getLoadedThemes get all the loaded themes', ->
themes = themeManager.getLoadedThemes()
@@ -131,15 +131,21 @@ describe "ThemeManager", ->
describe "requireStylesheet(path)", ->
it "synchronously loads css at the given path and installs a style tag for it in the head", ->
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
themeManager.on 'stylesheet-added', stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler")
cssPath = atom.project.resolve('css.css')
lengthBefore = $('head style').length
themeManager.requireStylesheet(cssPath)
expect($('head style').length).toBe lengthBefore + 1
expect(stylesheetAddedHandler).toHaveBeenCalled()
expect(stylesheetsChangedHandler).toHaveBeenCalled()
element = $('head style[id*="css.css"]')
expect(element.attr('id')).toBe themeManager.stringToId(cssPath)
expect(element.text()).toBe fs.readFileSync(cssPath, 'utf8')
expect(element[0].sheet).toBe stylesheetAddedHandler.argsForCall[0][0]
# doesn't append twice
themeManager.requireStylesheet(cssPath)
@@ -187,9 +193,18 @@ describe "ThemeManager", ->
themeManager.requireStylesheet(cssPath)
expect($(document.body).css('font-weight')).toBe("bold")
themeManager.on 'stylesheet-removed', stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler")
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
themeManager.removeStylesheet(cssPath)
expect($(document.body).css('font-weight')).not.toBe("bold")
expect(stylesheetRemovedHandler).toHaveBeenCalled()
stylesheet = stylesheetRemovedHandler.argsForCall[0][0]
expect(stylesheet instanceof CSSStyleSheet).toBe true
expect(stylesheet.cssRules[0].selectorText).toBe 'body'
expect(stylesheetsChangedHandler).toHaveBeenCalled()
describe "base stylesheet loading", ->
@@ -219,20 +234,21 @@ describe "ThemeManager", ->
describe "when the user stylesheet changes", ->
it "reloads it", ->
[stylesheetRemovedHandler, stylesheetAddedHandler, stylesheetsChangedHandler] = []
userStylesheetPath = path.join(temp.mkdirSync("atom"), 'styles.less')
fs.writeFileSync(userStylesheetPath, 'body {border-style: dotted !important;}')
spyOn(themeManager, 'getUserStylesheetPath').andReturn userStylesheetPath
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
waitsForPromise ->
themeManager.activateThemes()
runs ->
expect($(document.body).css('border-style')).toBe 'dotted'
expect(stylesheetsChangedHandler).toHaveBeenCalled()
stylesheetsChangedHandler.reset()
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
themeManager.on 'stylesheet-removed', stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler")
themeManager.on 'stylesheet-added', stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler")
spyOn(themeManager, 'loadUserStylesheet').andCallThrough()
expect($(document.body).css('border-style')).toBe 'dotted'
fs.writeFileSync(userStylesheetPath, 'body {border-style: dashed}')
waitsFor ->
@@ -240,7 +256,16 @@ describe "ThemeManager", ->
runs ->
expect($(document.body).css('border-style')).toBe 'dashed'
expect(stylesheetRemovedHandler).toHaveBeenCalled()
expect(stylesheetRemovedHandler.argsForCall[0][0].cssRules[0].style.border).toBe 'dotted'
expect(stylesheetAddedHandler).toHaveBeenCalled()
expect(stylesheetAddedHandler.argsForCall[0][0].cssRules[0].style.border).toBe 'dashed'
expect(stylesheetsChangedHandler).toHaveBeenCalled()
stylesheetRemovedHandler.reset()
stylesheetsChangedHandler.reset()
fs.removeSync(userStylesheetPath)
@@ -248,16 +273,25 @@ describe "ThemeManager", ->
themeManager.loadUserStylesheet.callCount is 2
runs ->
expect(stylesheetRemovedHandler).toHaveBeenCalled()
expect(stylesheetRemovedHandler.argsForCall[0][0].cssRules[0].style.border).toBe 'dashed'
expect($(document.body).css('border-style')).toBe 'none'
expect(stylesheetsChangedHandler).toHaveBeenCalled()
describe "when a non-existent theme is present in the config", ->
it "logs a warning but does not throw an exception (regression)", ->
reloaded = false
waitsForPromise ->
themeManager.activateThemes()
runs ->
themeManager.once 'reloaded', -> reloaded = true
spyOn(console, 'warn')
expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow()
waitsFor -> reloaded
runs ->
expect(console.warn.callCount).toBe 1
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
+9 -5
Ver Arquivo
@@ -6,7 +6,7 @@ describe "TokenizedLine", ->
describe "::getScopeTree()", ->
it "returns a tree whose inner nodes are scopes and whose leaf nodes are tokens in those scopes", ->
editor = atom.project.openSync('coffee.coffee')
[tokens, tokenIndex] = []
ensureValidScopeTree = (scopeTree, scopes=[]) ->
if scopeTree.children?
@@ -16,7 +16,11 @@ describe "TokenizedLine", ->
expect(scopeTree).toBe tokens[tokenIndex++]
expect(scopes).toEqual scopeTree.scopes
tokenIndex = 0
tokens = editor.lineForScreenRow(1).tokens
scopeTree = editor.lineForScreenRow(1).getScopeTree()
ensureValidScopeTree(scopeTree)
waitsForPromise ->
atom.project.open('coffee.coffee').then (o) -> editor = o
runs ->
tokenIndex = 0
tokens = editor.lineForScreenRow(1).tokens
scopeTree = editor.lineForScreenRow(1).getScopeTree()
ensureValidScopeTree(scopeTree)
+37 -20
Ver Arquivo
@@ -64,27 +64,41 @@ describe "Window", ->
describe "when pane items are are modified", ->
it "prompts user to save and and calls workspaceView.confirmClose", ->
editor = null
spyOn(atom.workspaceView, 'confirmClose').andCallThrough()
spyOn(atom, "confirm").andReturn(2)
editor = atom.workspaceView.openSync("sample.js")
editor.insertText("I look different, I feel different.")
$(window).trigger(beforeUnloadEvent)
expect(atom.workspaceView.confirmClose).toHaveBeenCalled()
expect(atom.confirm).toHaveBeenCalled()
waitsForPromise ->
atom.workspace.open("sample.js").then (o) -> editor = o
runs ->
editor.insertText("I look different, I feel different.")
$(window).trigger(beforeUnloadEvent)
expect(atom.workspaceView.confirmClose).toHaveBeenCalled()
expect(atom.confirm).toHaveBeenCalled()
it "prompts user to save and handler returns true if don't save", ->
editor = null
spyOn(atom, "confirm").andReturn(2)
editor = atom.workspaceView.openSync("sample.js")
editor.insertText("I look different, I feel different.")
$(window).trigger(beforeUnloadEvent)
expect(atom.confirm).toHaveBeenCalled()
waitsForPromise ->
atom.workspace.open("sample.js").then (o) -> editor = o
runs ->
editor.insertText("I look different, I feel different.")
$(window).trigger(beforeUnloadEvent)
expect(atom.confirm).toHaveBeenCalled()
it "prompts user to save and handler returns false if dialog is canceled", ->
editor = null
spyOn(atom, "confirm").andReturn(1)
editor = atom.workspaceView.openSync("sample.js")
editor.insertText("I look different, I feel different.")
$(window).trigger(beforeUnloadEvent)
expect(atom.confirm).toHaveBeenCalled()
waitsForPromise ->
atom.workspace.open("sample.js").then (o) -> editor = o
runs ->
editor.insertText("I look different, I feel different.")
$(window).trigger(beforeUnloadEvent)
expect(atom.confirm).toHaveBeenCalled()
describe ".unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", ->
@@ -100,15 +114,18 @@ describe "Window", ->
expect(atom.saveSync).toHaveBeenCalled()
it "unsubscribes from all buffers", ->
atom.workspaceView.openSync('sample.js')
buffer = atom.workspaceView.getActivePaneItem().buffer
pane = atom.workspaceView.getActivePaneView()
pane.splitRight(pane.copyActiveItem())
expect(atom.workspaceView.find('.editor').length).toBe 2
waitsForPromise ->
atom.workspace.open("sample.js")
atom.unloadEditorWindow()
runs ->
buffer = atom.workspace.getActivePaneItem().buffer
pane = atom.workspaceView.getActivePaneView()
pane.splitRight(pane.copyActiveItem())
expect(atom.workspaceView.find('.editor').length).toBe 2
expect(buffer.getSubscriptionCount()).toBe 0
atom.unloadEditorWindow()
expect(buffer.getSubscriptionCount()).toBe 0
describe "drag and drop", ->
buildDragEvent = (type, files) ->
+109 -80
Ver Arquivo
@@ -37,12 +37,17 @@ describe "Workspace", ->
describe "when called with a uri", ->
describe "when the active pane already has an editor for the given uri", ->
it "activates the existing editor on the active pane", ->
editor1 = workspace.openSync('a')
editor2 = workspace.openSync('b')
editor = null
editor1 = null
editor2 = null
waitsForPromise ->
workspace.open('a').then (o) -> editor = o
workspace.open('a').then (o) ->
editor1 = o
workspace.open('b').then (o) ->
editor2 = o
workspace.open('a').then (o) ->
editor = o
runs ->
expect(editor).toBe editor1
@@ -64,11 +69,21 @@ describe "Workspace", ->
describe "when the 'searchAllPanes' option is true", ->
describe "when an editor for the given uri is already open on an inactive pane", ->
it "activates the existing editor on the inactive pane, then activates that pane", ->
editor1 = workspace.openSync('a')
pane1 = workspace.activePane
pane2 = workspace.activePane.splitRight()
editor2 = workspace.openSync('b')
expect(workspace.activePaneItem).toBe editor2
editor1 = null
editor2 = null
pane1 = workspace.getActivePane()
pane2 = workspace.getActivePane().splitRight()
waitsForPromise ->
pane1.activate()
workspace.open('a').then (o) -> editor1 = o
waitsForPromise ->
pane2.activate()
workspace.open('b').then (o) -> editor2 = o
runs ->
expect(workspace.activePaneItem).toBe editor2
waitsForPromise ->
workspace.open('a', searchAllPanes: true)
@@ -112,6 +127,22 @@ describe "Workspace", ->
expect(pane1.items).toEqual [editor]
expect(pane2.items).toEqual []
describe "when a pane axis is the leftmost sibling of the current pane", ->
it "opens the new item in the current pane", ->
editor = null
pane1 = workspace.activePane
pane2 = pane1.splitLeft()
pane3 = pane2.splitDown()
pane1.activate()
expect(workspace.activePane).toBe pane1
waitsForPromise ->
workspace.open('a', split: 'left').then (o) -> editor = o
runs ->
expect(workspace.activePane).toBe pane1
expect(pane1.items).toEqual [editor]
describe "when the 'split' option is 'right'", ->
it "opens the editor in the rightmost pane of the current pane axis", ->
editor = null
@@ -136,6 +167,26 @@ describe "Workspace", ->
expect(pane1.items).toEqual []
expect(pane2.items).toEqual [editor]
describe "when a pane axis is the rightmost sibling of the current pane", ->
it "opens the new item in a new pane split to the right of the current pane", ->
editor = null
pane1 = workspace.activePane
pane2 = pane1.splitRight()
pane3 = pane2.splitDown()
pane1.activate()
expect(workspace.activePane).toBe pane1
pane4 = null
waitsForPromise ->
workspace.open('a', split: 'right').then (o) -> editor = o
runs ->
pane4 = workspace.getPanes().filter((p) -> p != pane1)[0]
expect(workspace.activePane).toBe pane4
expect(pane4.items).toEqual [editor]
expect(workspace.paneContainer.root.children[0]).toBe pane1
expect(workspace.paneContainer.root.children[1]).toBe pane4
describe "when passed a path that matches a custom opener", ->
it "returns the resource returned by the custom opener", ->
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
@@ -164,80 +215,55 @@ describe "Workspace", ->
runs ->
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "::openSync(uri, options)", ->
[activePane, initialItemCount] = []
beforeEach ->
activePane = workspace.activePane
spyOn(activePane, 'activate')
initialItemCount = activePane.items.length
describe "when called without a uri", ->
it "adds and activates an empty editor on the active pane", ->
editor = workspace.openSync()
expect(activePane.items.length).toBe initialItemCount + 1
expect(activePane.activeItem).toBe editor
expect(editor.getPath()).toBeUndefined()
expect(activePane.activate).toHaveBeenCalled()
describe "when called with a uri", ->
describe "when the active pane already has an editor for the given uri", ->
it "activates the existing editor on the active pane", ->
editor1 = workspace.openSync('a')
editor2 = workspace.openSync('b')
expect(activePane.activeItem).toBe editor2
expect(activePane.items.length).toBe 2
editor = workspace.openSync(editor1.getPath())
expect(editor).toBe editor1
expect(activePane.activeItem).toBe editor
expect(activePane.activate).toHaveBeenCalled()
expect(activePane.items.length).toBe 2
describe "when the active pane does not have an editor for the given uri", ->
it "adds and activates a new editor for the given path on the active pane", ->
editor = workspace.openSync('a')
expect(activePane.items.length).toBe 1
expect(activePane.activeItem).toBe editor
expect(activePane.activate).toHaveBeenCalled()
describe "when the 'activatePane' option is false", ->
it "does not activate the active pane", ->
workspace.openSync('b', activatePane: false)
expect(activePane.activate).not.toHaveBeenCalled()
describe "::reopenItemSync()", ->
describe "::reopenItem()", ->
it "opens the uri associated with the last closed pane that isn't currently open", ->
pane = workspace.activePane
workspace.openSync('a')
workspace.openSync('b')
workspace.openSync('file1')
workspace.openSync()
waitsForPromise ->
workspace.open('a').then ->
workspace.open('b').then ->
workspace.open('file1').then ->
workspace.open()
# does not reopen items with no uri
expect(workspace.activePaneItem.getUri()).toBeUndefined()
pane.destroyActiveItem()
workspace.reopenItemSync()
expect(workspace.activePaneItem.getUri()).not.toBeUndefined()
runs ->
# does not reopen items with no uri
expect(workspace.activePaneItem.getUri()).toBeUndefined()
pane.destroyActiveItem()
# destroy all items
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
pane.destroyActiveItem()
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
pane.destroyActiveItem()
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
pane.destroyActiveItem()
waitsForPromise ->
workspace.reopenItem()
# reopens items with uris
expect(workspace.activePaneItem).toBeUndefined()
workspace.reopenItemSync()
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
runs ->
expect(workspace.activePaneItem.getUri()).not.toBeUndefined()
# destroy all items
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
pane.destroyActiveItem()
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
pane.destroyActiveItem()
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
pane.destroyActiveItem()
# reopens items with uris
expect(workspace.activePaneItem).toBeUndefined()
waitsForPromise ->
workspace.reopenItem()
runs ->
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a')
# does not reopen items that are already open
workspace.openSync('b')
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
workspace.reopenItemSync()
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
waitsForPromise ->
workspace.open('b')
runs ->
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b')
waitsForPromise ->
workspace.reopenItem()
runs ->
expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1')
describe "::increase/decreaseFontSize()", ->
it "increases/decreases the font size without going below 1", ->
@@ -272,11 +298,14 @@ describe "Workspace", ->
describe "when an editor is copied", ->
it "emits an 'editor-created' event", ->
editor = null
handler = jasmine.createSpy('editorCreatedHandler')
workspace.on 'editor-created', handler
editor1 = workspace.openSync("a")
expect(handler.callCount).toBe 1
waitsForPromise ->
workspace.open("a").then (o) -> editor = o
editor2 = editor1.copy()
expect(handler.callCount).toBe 2
runs ->
expect(handler.callCount).toBe 1
editorCopy = editor.copy()
expect(handler.callCount).toBe 2
+82 -48
Ver Arquivo
@@ -15,9 +15,12 @@ describe "WorkspaceView", ->
atom.workspace = new Workspace
atom.workspaceView = new WorkspaceView(atom.workspace)
atom.workspaceView.enableKeymap()
atom.workspaceView.openSync(pathToOpen)
atom.workspaceView.focus()
waitsForPromise ->
atom.workspace.open(pathToOpen)
describe "@deserialize()", ->
viewState = null
@@ -33,17 +36,21 @@ describe "WorkspaceView", ->
describe "when the serialized WorkspaceView has an unsaved buffer", ->
it "constructs the view with the same panes", ->
atom.workspaceView.attachToDom()
atom.workspaceView.openSync()
editorView1 = atom.workspaceView.getActiveView()
buffer = editorView1.getEditor().getBuffer()
editorView1.splitRight()
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
simulateReload()
waitsForPromise ->
atom.workspace.open()
expect(atom.workspaceView.getEditorViews().length).toBe 2
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
expect(atom.workspaceView.title).toBe "untitled - #{atom.project.getPath()}"
runs ->
editorView1 = atom.workspaceView.getActiveView()
buffer = editorView1.getEditor().getBuffer()
editorView1.splitRight()
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
simulateReload()
expect(atom.workspaceView.getEditorViews().length).toBe 2
expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1]
expect(atom.workspaceView.title).toBe "untitled - #{atom.project.getPath()}"
describe "when there are open editors", ->
it "constructs the view with the same panes", ->
@@ -51,42 +58,56 @@ describe "WorkspaceView", ->
pane1 = atom.workspaceView.getActivePaneView()
pane2 = pane1.splitRight()
pane3 = pane2.splitRight()
pane4 = pane2.splitDown()
pane2.activateItem(atom.project.openSync('b'))
pane3.activateItem(atom.project.openSync('../sample.js'))
pane3.activeItem.setCursorScreenPosition([2, 4])
pane4.activateItem(atom.project.openSync('../sample.txt'))
pane4.activeItem.setCursorScreenPosition([0, 2])
pane2.focus()
pane4 = null
simulateReload()
waitsForPromise ->
atom.workspace.open('b').then (editor) ->
pane2.activateItem(editor)
expect(atom.workspaceView.getEditorViews().length).toBe 4
editorView1 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(0)').view()
editorView3 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(1)').view()
editorView2 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(0)').view()
editorView4 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(1)').view()
waitsForPromise ->
atom.workspace.open('../sample.js').then (editor) ->
pane3.activateItem(editor)
expect(editorView1.getEditor().getPath()).toBe atom.project.resolve('a')
expect(editorView2.getEditor().getPath()).toBe atom.project.resolve('b')
expect(editorView3.getEditor().getPath()).toBe atom.project.resolve('../sample.js')
expect(editorView3.getEditor().getCursorScreenPosition()).toEqual [2, 4]
expect(editorView4.getEditor().getPath()).toBe atom.project.resolve('../sample.txt')
expect(editorView4.getEditor().getCursorScreenPosition()).toEqual [0, 2]
runs ->
pane3.activeItem.setCursorScreenPosition([2, 4])
pane4 = pane2.splitDown()
# ensure adjust pane dimensions is called
expect(editorView1.width()).toBeGreaterThan 0
expect(editorView2.width()).toBeGreaterThan 0
expect(editorView3.width()).toBeGreaterThan 0
expect(editorView4.width()).toBeGreaterThan 0
waitsForPromise ->
atom.workspace.open('../sample.txt').then (editor) ->
pane4.activateItem(editor)
# ensure correct editorView is focused again
expect(editorView2.isFocused).toBeTruthy()
expect(editorView1.isFocused).toBeFalsy()
expect(editorView3.isFocused).toBeFalsy()
expect(editorView4.isFocused).toBeFalsy()
runs ->
pane4.activeItem.setCursorScreenPosition([0, 2])
pane2.focus()
expect(atom.workspaceView.title).toBe "#{path.basename(editorView2.getEditor().getPath())} - #{atom.project.getPath()}"
simulateReload()
expect(atom.workspaceView.getEditorViews().length).toBe 4
editorView1 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(0)').view()
editorView3 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(1)').view()
editorView2 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(0)').view()
editorView4 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(1)').view()
expect(editorView1.getEditor().getPath()).toBe atom.project.resolve('a')
expect(editorView2.getEditor().getPath()).toBe atom.project.resolve('b')
expect(editorView3.getEditor().getPath()).toBe atom.project.resolve('../sample.js')
expect(editorView3.getEditor().getCursorScreenPosition()).toEqual [2, 4]
expect(editorView4.getEditor().getPath()).toBe atom.project.resolve('../sample.txt')
expect(editorView4.getEditor().getCursorScreenPosition()).toEqual [0, 2]
# ensure adjust pane dimensions is called
expect(editorView1.width()).toBeGreaterThan 0
expect(editorView2.width()).toBeGreaterThan 0
expect(editorView3.width()).toBeGreaterThan 0
expect(editorView4.width()).toBeGreaterThan 0
# ensure correct editorView is focused again
expect(editorView2).toHaveFocus()
expect(editorView1).not.toHaveFocus()
expect(editorView3).not.toHaveFocus()
expect(editorView4).not.toHaveFocus()
expect(atom.workspaceView.title).toBe "#{path.basename(editorView2.getEditor().getPath())} - #{atom.project.getPath()}"
describe "where there are no open editors", ->
it "constructs the view with no open editors", ->
@@ -102,9 +123,9 @@ describe "WorkspaceView", ->
it "hands off focus to the active pane", ->
activePane = atom.workspaceView.getActivePaneView()
$('body').focus()
expect(activePane.hasFocus()).toBe false
expect(activePane).not.toHaveFocus()
atom.workspaceView.focus()
expect(activePane.hasFocus()).toBe true
expect(activePane).toHaveFocus()
describe "keymap wiring", ->
commandHandler = null
@@ -112,7 +133,7 @@ describe "WorkspaceView", ->
commandHandler = jasmine.createSpy('commandHandler')
atom.workspaceView.on('foo-command', commandHandler)
atom.keymaps.bindKeys('name', '*', 'x': 'foo-command')
atom.keymaps.add('name', '*': {'x': 'foo-command'})
describe "when a keydown event is triggered in the WorkspaceView", ->
it "triggers matching keybindings for that event", ->
@@ -129,7 +150,8 @@ describe "WorkspaceView", ->
describe "when the project has a path", ->
beforeEach ->
atom.workspaceView.openSync('b')
waitsForPromise ->
atom.workspace.open('b')
describe "when there is an active pane item", ->
it "sets the title to the pane item's title plus the project path", ->
@@ -144,7 +166,7 @@ describe "WorkspaceView", ->
describe "when the active pane's item changes", ->
it "updates the title to the new item's title plus the project path", ->
atom.workspaceView.getActivePaneView().showNextItem()
atom.workspaceView.getActivePaneView().activateNextItem()
item = atom.workspace.getActivePaneItem()
expect(atom.workspaceView.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
@@ -159,7 +181,7 @@ describe "WorkspaceView", ->
pane = atom.workspaceView.getActivePaneView()
pane.splitRight()
initialTitle = atom.workspaceView.title
pane.showNextItem()
pane.activateNextItem()
expect(atom.workspaceView.title).toBe initialTitle
describe "when the root view is deserialized", ->
@@ -246,10 +268,22 @@ describe "WorkspaceView", ->
describe "core:close", ->
it "closes the active pane item until all that remains is a single empty pane", ->
atom.config.set('core.destroyEmptyPanes', true)
atom.project.openSync('../sample.txt')
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 1
paneView1 = atom.workspaceView.getActivePaneView()
editorView = atom.workspaceView.getActiveView()
editorView.splitRight()
paneView2 = atom.workspaceView.getActivePaneView()
expect(paneView1).not.toBe paneView2
expect(atom.workspaceView.getPaneViews()).toHaveLength 2
atom.workspaceView.trigger('core:close')
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 1
expect(atom.workspaceView.getPaneViews()).toHaveLength 1
atom.workspaceView.trigger('core:close')
expect(atom.workspaceView.getActivePaneView().getItems()).toHaveLength 0
expect(atom.workspaceView.getPaneViews()).toHaveLength 1
describe "the scrollbar visibility class", ->
it "has a class based on the style of the scrollbar", ->
+26 -23
Ver Arquivo
@@ -24,7 +24,7 @@ WindowEventHandler = require './window-event-handler'
# * `atom.config` - A {Config} instance
# * `atom.contextMenu` - A {ContextMenuManager} instance
# * `atom.deserializers` - A {DeserializerManager} instance
# * `atom.keymaps` - A {Keymap} instance
# * `atom.keymaps` - A {KeymapManager} instance
# * `atom.menu` - A {MenuManager} instance
# * `atom.packages` - A {PackageManager} instance
# * `atom.project` - A {Project} instance
@@ -38,8 +38,8 @@ class Atom extends Model
# Public: Load or create the Atom environment in the given mode.
#
# - mode: Pass 'editor' or 'spec' depending on the kind of environment you
# want to build.
# mode - Pass 'editor' or 'spec' depending on the kind of environment you
# want to build.
#
# Returns an Atom instance, fully initialized
@loadOrCreate: (mode) ->
@@ -148,7 +148,7 @@ class Atom extends Model
ThemeManager = require './theme-manager'
ContextMenuManager = require './context-menu-manager'
MenuManager = require './menu-manager'
{devMode, resourcePath} = @getLoadSettings()
{devMode, safeMode, resourcePath} = @getLoadSettings()
configDirPath = @getConfigDirPath()
# Add 'src/exports' to module search path.
@@ -163,7 +163,7 @@ class Atom extends Model
@config = new Config({configDirPath, resourcePath})
@keymaps = new KeymapManager({configDirPath, resourcePath})
@keymap = @keymaps # Deprecated
@packages = new PackageManager({devMode, configDirPath, resourcePath})
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath})
@contextMenu = new ContextMenuManager(devMode)
@menu = new MenuManager({resourcePath})
@@ -212,11 +212,11 @@ class Atom extends Model
# in the dimensions parameter. If x or y are omitted the window will be
# centered. If height or width are omitted only the position will be changed.
#
# * dimensions:
# + x: The new x coordinate.
# + y: The new y coordinate.
# + width: The new width.
# + height: The new height.
# dimensions - An {Object} with the following keys:
# :x - The new x coordinate.
# :y - The new y coordinate.
# :width - The new width.
# :height - The new height.
setWindowDimensions: ({x, y, width, height}) ->
if width? and height?
@setSize(width, height)
@@ -340,7 +340,7 @@ class Atom extends Model
# options - An {Object} with the following keys:
# :pathsToOpen - An {Array} of {String} paths to open.
open: (options) ->
ipc.sendChannel('open', options)
ipc.send('open', options)
# Public: Open a confirm dialog.
#
@@ -394,50 +394,50 @@ class Atom extends Model
# Public: Open the dev tools for the current window.
openDevTools: ->
ipc.sendChannel('call-window-method', 'openDevTools')
ipc.send('call-window-method', 'openDevTools')
# Public: Toggle the visibility of the dev tools for the current window.
toggleDevTools: ->
ipc.sendChannel('call-window-method', 'toggleDevTools')
ipc.send('call-window-method', 'toggleDevTools')
# Public: Execute code in dev tools.
executeJavaScriptInDevTools: (code) ->
ipc.sendChannel('call-window-method', 'executeJavaScriptInDevTools', code)
ipc.send('call-window-method', 'executeJavaScriptInDevTools', code)
# Public: Reload the current window.
reload: ->
ipc.sendChannel('call-window-method', 'restart')
ipc.send('call-window-method', 'restart')
# Public: Focus the current window.
focus: ->
ipc.sendChannel('call-window-method', 'focus')
ipc.send('call-window-method', 'focus')
$(window).focus()
# Public: Show the current window.
show: ->
ipc.sendChannel('call-window-method', 'show')
ipc.send('call-window-method', 'show')
# Public: Hide the current window.
hide: ->
ipc.sendChannel('call-window-method', 'hide')
ipc.send('call-window-method', 'hide')
# Public: Set the size of current window.
#
# width - The {Number} of pixels.
# height - The {Number} of pixels.
setSize: (width, height) ->
ipc.sendChannel('call-window-method', 'setSize', width, height)
ipc.send('call-window-method', 'setSize', width, height)
# Public: Set the position of current window.
#
# x - The {Number} of pixels.
# y - The {Number} of pixels.
setPosition: (x, y) ->
ipc.sendChannel('call-window-method', 'setPosition', x, y)
ipc.send('call-window-method', 'setPosition', x, y)
# Public: Move current window to the center of the screen.
center: ->
ipc.sendChannel('call-window-method', 'center')
ipc.send('call-window-method', 'center')
# Schedule the window to be shown and focused on the next tick.
#
@@ -472,13 +472,16 @@ class Atom extends Model
# Public: Set the full screen state of the current window.
setFullScreen: (fullScreen=false) ->
ipc.sendChannel('call-window-method', 'setFullScreen', fullScreen)
ipc.send('call-window-method', 'setFullScreen', fullScreen)
if fullScreen then document.body.classList.add("fullscreen") else document.body.classList.remove("fullscreen")
# Public: Is the current window in full screen mode?
isFullScreen: ->
@getCurrentWindow().isFullScreen()
# Public: Get the version of the Atom application.
#
# Returns the version text {String}.
getVersion: ->
@constructor.getVersion()
@@ -488,7 +491,7 @@ class Atom extends Model
# Public: Get the directory path to Atom's configuration area.
#
# Returns the absolute path to ~/.atom
# Returns the absolute path to `~/.atom`.
getConfigDirPath: ->
@constructor.getConfigDirPath()
+39 -28
Ver Arquivo
@@ -59,7 +59,7 @@ class AtomApplication
exit: (status) -> app.exit(status)
constructor: (options) ->
{@resourcePath, @version, @devMode} = options
{@resourcePath, @version, @devMode, @safeMode} = options
global.atomApplication = this
@pidsToOpenWindows = {}
@@ -77,15 +77,15 @@ class AtomApplication
@openWithOptions(options)
# Opens a new window based on the options provided.
openWithOptions: ({pathsToOpen, urlsToOpen, test, pidToKillWhenClosed, devMode, newWindow, specDirectory, logFile}) ->
openWithOptions: ({pathsToOpen, urlsToOpen, test, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile}) ->
if test
@runSpecs({exitWhenDone: true, @resourcePath, specDirectory, logFile})
else if pathsToOpen.length > 0
@openPaths({pathsToOpen, pidToKillWhenClosed, newWindow, devMode})
@openPaths({pathsToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode})
else if urlsToOpen.length > 0
@openUrl({urlToOpen, devMode}) for urlToOpen in urlsToOpen
@openUrl({urlToOpen, devMode, safeMode}) for urlToOpen in urlsToOpen
else
@openPath({pidToKillWhenClosed, newWindow, devMode}) # Always open a editor window if this is the first instance of Atom.
@openPath({pidToKillWhenClosed, newWindow, devMode, safeMode}) # Always open a editor window if this is the first instance of Atom.
# Public: Removes the {AtomWindow} from the global window list.
removeWindow: (window) ->
@@ -140,11 +140,13 @@ class AtomApplication
@on 'application:open-file', -> @promptForPath(type: 'file')
@on 'application:open-folder', -> @promptForPath(type: 'folder')
@on 'application:open-dev', -> @promptForPath(devMode: true)
@on 'application:open-safe', -> @promptForPath(safeMode: true)
@on 'application:inspect', ({x,y, atomWindow}) ->
atomWindow ?= @focusedWindow()
atomWindow?.browserWindow.inspectElement(x, y)
@on 'application:open-documentation', -> shell.openExternal('https://atom.io/docs/latest/?app')
@on 'application:open-terms-of-use', -> shell.openExternal('https://atom.io/terms')
@on 'application:install-update', -> @autoUpdateManager.install()
@on 'application:check-for-update', => @autoUpdateManager.check()
@@ -166,6 +168,7 @@ class AtomApplication
@openPathOnEvent('application:open-your-keymap', 'atom://.atom/keymap')
@openPathOnEvent('application:open-your-snippets', 'atom://.atom/snippets')
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
@openPathOnEvent('application:open-license', path.join(@resourcePath, 'LICENSE.md'))
app.on 'window-all-closed', ->
app.quit() if process.platform in ['win32', 'linux']
@@ -184,14 +187,14 @@ class AtomApplication
app.on 'open-url', (event, urlToOpen) =>
event.preventDefault()
@openUrl({urlToOpen, @devMode})
@openUrl({urlToOpen, @devMode, @safeMode})
app.on 'activate-with-no-open-windows', (event) =>
event.preventDefault()
@emit('application:new-window')
# A request from the associated render process to open a new render process.
ipc.on 'open', (processId, routingId, options) =>
ipc.on 'open', (event, options) =>
if options?
if options.pathsToOpen?.length > 0
@openPaths(options)
@@ -200,21 +203,21 @@ class AtomApplication
else
@promptForPath()
ipc.on 'update-application-menu', (processId, routingId, template, keystrokesByCommand) =>
ipc.on 'update-application-menu', (event, template, keystrokesByCommand) =>
@applicationMenu.update(template, keystrokesByCommand)
ipc.on 'run-package-specs', (processId, routingId, specDirectory) =>
ipc.on 'run-package-specs', (event, specDirectory) =>
@runSpecs({resourcePath: global.devResourcePath, specDirectory: specDirectory, exitWhenDone: false})
ipc.on 'command', (processId, routingId, command) =>
ipc.on 'command', (event, command) =>
@emit(command)
ipc.on 'window-command', (processId, routingId, command, args...) ->
win = BrowserWindow.fromProcessIdAndRoutingId(processId, routingId)
ipc.on 'window-command', (event, command, args...) ->
win = BrowserWindow.fromWebContents(event.sender)
win.emit(command, args...)
ipc.on 'call-window-method', (processId, routingId, method, args...) ->
win = BrowserWindow.fromProcessIdAndRoutingId(processId, routingId)
ipc.on 'call-window-method', (event, method, args...) ->
win = BrowserWindow.fromWebContents(event.sender)
win[method](args...)
# Public: Executes the given command.
@@ -288,8 +291,10 @@ class AtomApplication
# :pidToKillWhenClosed - The integer of the pid to kill
# :newWindow - Boolean of whether this should be opened in a new window.
# :devMode - Boolean to control the opened window's dev mode.
openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode}) ->
@openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode}) for pathToOpen in pathsToOpen ? []
# :safeMode - Boolean to control the opened window's safe mode.
openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode}) ->
for pathToOpen in pathsToOpen ? []
@openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode})
# Public: Opens a single path, in an existing window if possible.
#
@@ -298,13 +303,16 @@ class AtomApplication
# :pidToKillWhenClosed - The integer of the pid to kill
# :newWindow - Boolean of whether this should be opened in a new window.
# :devMode - Boolean to control the opened window's dev mode.
# :safeMode - Boolean to control the opened window's safe mode.
# :windowDimensions - Object with height and width keys.
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, windowDimensions}={}) ->
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions}={}) ->
if pathToOpen
[basename, initialLine] = path.basename(pathToOpen).split(':')
if initialLine
pathToOpen = "#{path.dirname(pathToOpen)}/#{basename}"
initialLine -= 1 # Convert line numbers to a base of 0
[basename, initialLine, initialColumn] = path.basename(pathToOpen).split(':')
pathToOpen = path.join(path.dirname(pathToOpen), basename) if initialLine
# Convert line numbers to a base of 0
initialLine -= 1 if initialLine
initialColumn -= 1 if initialColumn
unless devMode
existingWindow = @windowForPath(pathToOpen) unless pidToKillWhenClosed or newWindow
@@ -320,12 +328,12 @@ class AtomApplication
bootstrapScript ?= require.resolve('../window-bootstrap')
resourcePath ?= @resourcePath
openedWindow = new AtomWindow({pathToOpen, initialLine, bootstrapScript, resourcePath, devMode, windowDimensions})
openedWindow = new AtomWindow({pathToOpen, initialLine, initialColumn, bootstrapScript, resourcePath, devMode, safeMode, windowDimensions})
if pidToKillWhenClosed?
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
openedWindow.browserWindow.on 'destroyed', =>
openedWindow.browserWindow.on 'closed', =>
@killProcessForWindow(openedWindow)
# Kill all processes associated with opened windows.
@@ -355,7 +363,8 @@ class AtomApplication
# options -
# :urlToOpen - The atom:// url to open.
# :devMode - Boolean to control the opened window's dev mode.
openUrl: ({urlToOpen, devMode}) ->
# :safeMode - Boolean to control the opened window's safe mode.
openUrl: ({urlToOpen, devMode, safeMode}) ->
unless @packages?
PackageManager = require '../package-manager'
fs = require 'fs-plus'
@@ -371,7 +380,7 @@ class AtomApplication
packagePath = @packages.resolvePackagePath(packageName)
bootstrapScript = path.resolve(packagePath, pack.urlMain)
windowDimensions = @focusedWindow()?.getDimensions()
new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen, windowDimensions})
new AtomWindow({bootstrapScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions})
else
console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}"
else
@@ -414,8 +423,10 @@ class AtomApplication
# :type - A String which specifies the type of the dialog, could be 'file',
# 'folder' or 'all'. The 'all' is only available on OS X.
# :devMode - A Boolean which controls whether any newly opened windows
# should be in dev mode or not.
promptForPath: ({type, devMode}={}) ->
# should be in dev mode or not.
# :safeMode - A Boolean which controls whether any newly opened windows
# should be in safe mode or not.
promptForPath: ({type, devMode, safeMode}={}) ->
type ?= 'all'
properties =
switch type
@@ -424,4 +435,4 @@ class AtomApplication
when 'all' then ['openFile', 'openDirectory']
else throw new Error("#{type} is an invalid type for promptForPath")
dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) =>
@openPaths({pathsToOpen, devMode})
@openPaths({pathsToOpen, devMode, safeMode})
+8 -9
Ver Arquivo
@@ -2,7 +2,6 @@ BrowserWindow = require 'browser-window'
ContextMenu = require './context-menu'
app = require 'app'
dialog = require 'dialog'
ipc = require 'ipc'
path = require 'path'
fs = require 'fs'
url = require 'url'
@@ -21,7 +20,7 @@ class AtomWindow
isSpec: null
constructor: (settings={}) ->
{@resourcePath, pathToOpen, initialLine, @isSpec, @exitWhenDone} = settings
{@resourcePath, pathToOpen, initialLine, initialColumn, @isSpec, @exitWhenDone} = settings
global.atomApplication.addWindow(this)
@browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath
@@ -48,7 +47,7 @@ class AtomWindow
@browserWindow.loadUrl @getUrl(loadSettings)
@browserWindow.focusOnWebView() if @isSpec
@openPath(pathToOpen, initialLine)
@openPath(pathToOpen, initialLine, initialColumn)
getUrl: (loadSettingsObj) ->
# Ignore the windowState when passing loadSettings via URL, since it could
@@ -81,7 +80,7 @@ class AtomWindow
false
handleEvents: ->
@browserWindow.on 'destroyed', =>
@browserWindow.on 'closed', =>
global.atomApplication.removeWindow(this)
@browserWindow.on 'unresponsive', =>
@@ -94,7 +93,7 @@ class AtomWindow
detail: 'The editor is not responding. Would you like to force close it or just keep waiting?'
@browserWindow.destroy() if chosen is 0
@browserWindow.on 'crashed', =>
@browserWindow.webContents.on 'crashed', =>
global.atomApplication.exit(100) if @exitWhenDone
chosen = dialog.showMessageBox @browserWindow,
@@ -114,12 +113,12 @@ class AtomWindow
@browserWindow.on 'blur', =>
@browserWindow.focusOnWebView()
openPath: (pathToOpen, initialLine) ->
openPath: (pathToOpen, initialLine, initialColumn) ->
if @loaded
@focus()
@sendCommand('window:open-path', {pathToOpen, initialLine})
@sendCommand('window:open-path', {pathToOpen, initialLine, initialColumn})
else
@browserWindow.once 'window:loaded', => @openPath(pathToOpen, initialLine)
@browserWindow.once 'window:loaded', => @openPath(pathToOpen, initialLine, initialColumn)
sendCommand: (command, args...) ->
if @isSpecWindow()
@@ -136,7 +135,7 @@ class AtomWindow
sendCommandToBrowserWindow: (command, args...) ->
action = if args[0]?.contextCommand then 'context-command' else 'command'
ipc.sendChannel @browserWindow.getProcessId(), @browserWindow.getRoutingId(), action, command, args...
@browserWindow.webContents.send action, command, args...
getDimensions: ->
[x, y] = @browserWindow.getPosition()
+4 -2
Ver Arquivo
@@ -42,7 +42,7 @@ start = ->
app.removeListener 'open-url', addUrlToOpen
args.pathsToOpen = args.pathsToOpen.map (pathToOpen) ->
path.resolve(args.executedFrom ? process.cwd(), pathToOpen)
path.resolve(args.executedFrom ? process.cwd(), pathToOpen.toString())
require('coffee-script').register()
if args.devMode
@@ -73,6 +73,7 @@ parseCommandLine = ->
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the spec directory (default: Atom\'s spec directory).')
options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.')
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
@@ -88,6 +89,7 @@ parseCommandLine = ->
executedFrom = args['executed-from']
devMode = args['dev']
safeMode = args['safe']
pathsToOpen = args._
pathsToOpen = [executedFrom] if executedFrom and pathsToOpen.length is 0
test = args['test']
@@ -107,6 +109,6 @@ parseCommandLine = ->
catch
resourcePath = path.dirname(path.dirname(__dirname))
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, newWindow, specDirectory, logFile}
{resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile}
start()
+9 -2
Ver Arquivo
@@ -12,7 +12,7 @@ ChildProcess = require 'child_process'
# args = ['-ef']
# stdout = (output) -> console.log(output)
# exit = (code) -> console.log("ps -ef exited with #{code}")
# process = new BufferredProcess({command, args, stdout, exit})
# process = new BufferedProcess({command, args, stdout, exit})
# ```
module.exports =
class BufferedProcess
@@ -39,7 +39,14 @@ class BufferedProcess
# containing the exit status (optional).
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
options ?= {}
@process = ChildProcess.spawn(command, args, options)
# Quick hack. Killing @process will only kill cmd.exe, and not the child
# process and will just orphan it. Does not escape ^ (cmd's escape symbol).
# Related to joyent/node#2318
if process.platform is "win32"
@process = ChildProcess.spawn(process.env.comspec || "cmd.exe",
[ "/c", command ].concat(args), options)
else
@process = ChildProcess.spawn(command, args, options)
@killed = false
stdoutClosed = true
+5 -3
Ver Arquivo
@@ -222,11 +222,13 @@ class Config
#
# keyPath - The {String} name of the key to observe
# options - An optional {Object} containing the `callNow` key.
# callback - The {Function} that fires when the. It is given a single argument, `value`,
# which is the new value of `keyPath`.
# callback - The {Function} to call when the value of the key changes.
# The first argument will be the new value of the key and the
#   second argument will be an {Object} with a `previous` property
# that is the prior value of the key.
#
# Returns an {Object} with the following keys:
# :off - A {Function} that unobserves the `keyPath` with called.
# :off - A {Function} that unobserves the `keyPath` when called.
observe: (keyPath, options={}, callback) ->
if _.isFunction(options)
callback = options
+1
Ver Arquivo
@@ -98,5 +98,6 @@ class ContextMenuManager
showForEvent: (event) ->
@activeElement = event.target
menuTemplate = @combinedMenuTemplateForElement(event.target)
return unless menuTemplate?.length > 0
@executeBuildHandlers(event, menuTemplate)
remote.getCurrentWindow().emit('context-menu', menuTemplate)
+8 -6
Ver Arquivo
@@ -1,13 +1,15 @@
React = require 'react'
{div} = require 'reactionary'
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
module.exports =
CursorComponent = React.createClass
displayName: 'CursorComponent'
render: ->
{top, left, height, width} = @props.cursor.getPixelRect()
className = 'cursor'
className += ' blink-off' if @props.blinkOff
{cursor, scrollTop, scrollLeft} = @props
{top, left, height, width} = cursor.getPixelRect()
top -= scrollTop
left -= scrollLeft
WebkitTransform = "translate3d(#{left}px, #{top}px, 0px)"
div className: className, style: {top, left, height, width}
div className: 'cursor', style: {height, width, WebkitTransform}
+5 -1
Ver Arquivo
@@ -78,7 +78,11 @@ class CursorView extends View
setVisible: (visible) ->
unless @visible is visible
@visible = visible
@toggle(@visible)
hiddenCursor = 'hidden-cursor'
if visible
@removeClass hiddenCursor
else
@addClass hiddenCursor
stopBlinking: ->
@constructor.stopBlinking(this) if @blinking
+4 -4
Ver Arquivo
@@ -138,13 +138,13 @@ class Cursor extends Model
# Public: Identifies if the cursor is surrounded by whitespace.
#
# "Surrounded" here means that all characters before and after the cursor is
# whitespace.
# "Surrounded" here means that the character directly before and after the
# cursor are both whitespace.
#
# Returns a {Boolean}.
isSurroundedByWhitespace: ->
{row, column} = @getBufferPosition()
range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]]
range = [[row, column - 1], [row, column + 1]]
/^\s+$/.test @editor.getTextInBufferRange(range)
# Public: Returns whether the cursor is currently between a word and non-word
@@ -465,7 +465,7 @@ class Cursor extends Model
getCurrentParagraphBufferRange: ->
@editor.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow())
# Public: Returns the characters preceeding the cursor in the current word.
# Public: Returns the characters preceding the cursor in the current word.
getCurrentWordPrefix: ->
@editor.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()])
+20 -15
Ver Arquivo
@@ -1,10 +1,9 @@
React = require 'react'
{div} = require 'reactionary'
{debounce} = require 'underscore-plus'
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{debounce, toArray} = require 'underscore-plus'
SubscriberMixin = require './subscriber-mixin'
CursorComponent = require './cursor-component'
module.exports =
CursorsComponent = React.createClass
displayName: 'CursorsComponent'
@@ -13,38 +12,44 @@ CursorsComponent = React.createClass
cursorBlinkIntervalHandle: null
render: ->
{editor} = @props
blinkOff = @state.blinkCursorsOff
{editor, scrollTop, scrollLeft} = @props
{blinkOff} = @state
div className: 'cursors',
className = 'cursors'
className += ' blink-off' if blinkOff
div {className},
if @isMounted()
for selection in editor.getSelections()
if selection.isEmpty() and editor.selectionIntersectsVisibleRowRange(selection)
{cursor} = selection
CursorComponent({key: cursor.id, cursor, blinkOff})
CursorComponent({key: cursor.id, cursor, scrollTop, scrollLeft})
getInitialState: ->
blinkCursorsOff: false
blinkOff: false
componentDidMount: ->
{editor} = @props
@startBlinkingCursors()
componentWillUnmount: ->
clearInterval(@cursorBlinkIntervalHandle)
@stopBlinkingCursors()
componentWillUpdate: ({cursorsMoved}) ->
@pauseCursorBlinking() if cursorsMoved
startBlinkingCursors: ->
@cursorBlinkIntervalHandle = setInterval(@toggleCursorBlink, @props.cursorBlinkPeriod / 2)
@toggleCursorBlinkHandle = setInterval(@toggleCursorBlink, @props.cursorBlinkPeriod / 2) if @isMounted()
startBlinkingCursorsAfterDelay: null # Created lazily
toggleCursorBlink: -> @setState(blinkCursorsOff: not @state.blinkCursorsOff)
stopBlinkingCursors: ->
clearInterval(@toggleCursorBlinkHandle)
toggleCursorBlink: ->
@setState(blinkOff: not @state.blinkOff)
pauseCursorBlinking: ->
@state.blinkCursorsOff = false
clearInterval(@cursorBlinkIntervalHandle)
@state.blinkOff = false
@stopBlinkingCursors()
@startBlinkingCursorsAfterDelay ?= debounce(@startBlinkingCursors, @props.cursorBlinkResumeDelay)
@startBlinkingCursorsAfterDelay()
+78 -22
Ver Arquivo
@@ -23,7 +23,7 @@ class DisplayBuffer extends Model
manageScrollPosition: false
softWrap: null
editorWidthInChars: null
lineHeight: null
lineHeightInPixels: null
defaultCharWidth: null
height: null
width: null
@@ -32,6 +32,8 @@ class DisplayBuffer extends Model
verticalScrollMargin: 2
horizontalScrollMargin: 6
horizontalScrollbarHeight: 15
verticalScrollbarWidth: 15
constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer}={}) ->
super
@@ -111,32 +113,83 @@ class DisplayBuffer extends Model
getHorizontalScrollMargin: -> @horizontalScrollMargin
setHorizontalScrollMargin: (@horizontalScrollMargin) -> @horizontalScrollMargin
getHeight: -> @height ? @getScrollHeight()
getHorizontalScrollbarHeight: -> @horizontalScrollbarHeight
setHorizontalScrollbarHeight: (@horizontalScrollbarHeight) -> @horizontalScrollbarHeight
getVerticalScrollbarWidth: -> @verticalScrollbarWidth
setVerticalScrollbarWidth: (@verticalScrollbarWidth) -> @verticalScrollbarWidth
getHeight: ->
if @height?
@height
else
if @horizontallyScrollable()
@getScrollHeight() + @getHorizontalScrollbarHeight()
else
@getScrollHeight()
setHeight: (@height) -> @height
getWidth: -> @width ? @getScrollWidth()
getClientHeight: (reentrant) ->
if @horizontallyScrollable(reentrant)
@getHeight() - @getHorizontalScrollbarHeight()
else
@getHeight()
getClientWidth: (reentrant) ->
if @verticallyScrollable(reentrant)
@getWidth() - @getVerticalScrollbarWidth()
else
@getWidth()
horizontallyScrollable: (reentrant) ->
return false unless @width?
return false if @getSoftWrap()
if reentrant
@getScrollWidth() > @getWidth()
else
@getScrollWidth() > @getClientWidth(true)
verticallyScrollable: (reentrant) ->
return false unless @height?
if reentrant
@getScrollHeight() > @getHeight()
else
@getScrollHeight() > @getClientHeight(true)
getWidth: ->
if @width?
@width
else
if @verticallyScrollable()
@getScrollWidth() + @getVerticalScrollbarWidth()
else
@getScrollWidth()
setWidth: (newWidth) ->
oldWidth = @width
@width = newWidth
@updateWrappedScreenLines() if newWidth isnt oldWidth and @softWrap
@setScrollTop(@getScrollTop()) # Ensure scrollTop is still valid in case horizontal scrollbar disappeared
@width
getScrollTop: -> @scrollTop
setScrollTop: (scrollTop) ->
if @manageScrollPosition
@scrollTop = Math.max(0, Math.min(@getScrollHeight() - @getHeight(), scrollTop))
@scrollTop = Math.max(0, Math.min(@getScrollHeight() - @getClientHeight(), scrollTop))
else
@scrollTop = scrollTop
getScrollBottom: -> @scrollTop + @height
setScrollBottom: (scrollBottom) ->
@setScrollTop(scrollBottom - @height)
@setScrollTop(scrollBottom - @getClientHeight())
@getScrollBottom()
getScrollLeft: -> @scrollLeft
setScrollLeft: (scrollLeft) ->
if @manageScrollPosition
@scrollLeft = Math.max(0, Math.min(@getScrollWidth() - @getWidth(), scrollLeft))
@scrollLeft = Math.max(0, Math.min(@getScrollWidth() - @getClientWidth(), scrollLeft))
@scrollLeft
else
@scrollLeft = scrollLeft
@@ -145,12 +198,14 @@ class DisplayBuffer extends Model
@setScrollLeft(scrollRight - @width)
@getScrollRight()
getLineHeight: -> @lineHeight
setLineHeight: (@lineHeight) -> @lineHeight
getLineHeightInPixels: -> @lineHeightInPixels
setLineHeightInPixels: (@lineHeightInPixels) -> @lineHeightInPixels
getDefaultCharWidth: -> @defaultCharWidth
setDefaultCharWidth: (@defaultCharWidth) -> @defaultCharWidth
getCursorWidth: -> 1
getScopedCharWidth: (scopeNames, char) ->
@getScopedCharWidths(scopeNames)[char]
@@ -172,21 +227,22 @@ class DisplayBuffer extends Model
@charWidthsByScope = {}
getScrollHeight: ->
unless @getLineHeight() > 0
throw new Error("You must assign lineHeight before calling ::getScrollHeight()")
unless @getLineHeightInPixels() > 0
throw new Error("You must assign lineHeightInPixels before calling ::getScrollHeight()")
@getLineCount() * @getLineHeight()
@getLineCount() * @getLineHeightInPixels()
getScrollWidth: ->
@getMaxLineLength() * @getDefaultCharWidth()
(@getMaxLineLength() * @getDefaultCharWidth()) + @getCursorWidth()
getVisibleRowRange: ->
unless @getLineHeight() > 0
throw new Error("You must assign a non-zero lineHeight before calling ::getVisibleRowRange()")
unless @getLineHeightInPixels() > 0
throw new Error("You must assign a non-zero lineHeightInPixels before calling ::getVisibleRowRange()")
heightInLines = Math.ceil(@getHeight() / @getLineHeightInPixels()) + 1
startRow = Math.floor(@getScrollTop() / @getLineHeightInPixels())
endRow = Math.min(@getLineCount(), startRow + heightInLines)
heightInLines = Math.ceil(@getHeight() / @getLineHeight()) + 1
startRow = Math.floor(@getScrollTop() / @getLineHeight())
endRow = Math.min(@getLineCount(), Math.ceil(startRow + heightInLines))
[startRow, endRow]
intersectsVisibleRowRange: (startRow, endRow) ->
@@ -198,7 +254,7 @@ class DisplayBuffer extends Model
@intersectsVisibleRowRange(start.row, end.row + 1)
scrollToScreenRange: (screenRange) ->
verticalScrollMarginInPixels = @getVerticalScrollMargin() * @getLineHeight()
verticalScrollMarginInPixels = @getVerticalScrollMargin() * @getLineHeightInPixels()
horizontalScrollMarginInPixels = @getHorizontalScrollMargin() * @getDefaultCharWidth()
{top, left, height, width} = @pixelRectForScreenRange(screenRange)
@@ -229,11 +285,11 @@ class DisplayBuffer extends Model
if screenRange.end.row > screenRange.start.row
top = @pixelPositionForScreenPosition(screenRange.start).top
left = 0
height = (screenRange.end.row - screenRange.start.row + 1) * @getLineHeight()
height = (screenRange.end.row - screenRange.start.row + 1) * @getLineHeightInPixels()
width = @getScrollWidth()
else
{top, left} = @pixelPositionForScreenPosition(screenRange.start)
height = @getLineHeight()
height = @getLineHeightInPixels()
width = @pixelPositionForScreenPosition(screenRange.end).left - left
{top, left, width, height}
@@ -456,7 +512,7 @@ class DisplayBuffer extends Model
targetColumn = screenPosition.column
defaultCharWidth = @defaultCharWidth
top = targetRow * @lineHeight
top = targetRow * @lineHeightInPixels
left = 0
column = 0
for token in @lineForRow(targetRow).tokens
@@ -471,7 +527,7 @@ class DisplayBuffer extends Model
targetTop = pixelPosition.top
targetLeft = pixelPosition.left
defaultCharWidth = @defaultCharWidth
row = Math.floor(targetTop / @getLineHeight())
row = Math.floor(targetTop / @getLineHeightInPixels())
row = Math.min(row, @getLastRow())
row = Math.max(0, row)
+215 -39
Ver Arquivo
@@ -1,10 +1,12 @@
React = require 'react'
{div, span} = require 'reactionary'
{debounce} = require 'underscore-plus'
React = require 'react-atom-fork'
{div, span} = require 'reactionary-atom-fork'
{debounce, defaults} = require 'underscore-plus'
scrollbarStyle = require 'scrollbar-style'
GutterComponent = require './gutter-component'
EditorScrollViewComponent = require './editor-scroll-view-component'
ScrollbarComponent = require './scrollbar-component'
ScrollbarCornerComponent = require './scrollbar-corner-component'
SubscriberMixin = require './subscriber-mixin'
module.exports =
@@ -18,34 +20,52 @@ EditorComponent = React.createClass
batchingUpdates: false
updateRequested: false
cursorsMoved: false
preservedRowRange: null
selectionChanged: false
selectionAdded: false
scrollingVertically: false
gutterWidth: 0
refreshingScrollbars: false
measuringScrollbars: true
pendingVerticalScrollDelta: 0
pendingHorizontalScrollDelta: 0
mouseWheelScreenRow: null
render: ->
{focused, fontSize, lineHeight, fontFamily, showIndentGuide} = @state
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, visible} = @state
{editor, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
maxLineNumberDigits = editor.getScreenLineCount().toString().length
invisibles = if showInvisibles then @state.invisibles else {}
if @isMounted()
renderedRowRange = @getRenderedRowRange()
scrollHeight = editor.getScrollHeight()
scrollWidth = editor.getScrollWidth()
scrollTop = editor.getScrollTop()
scrollLeft = editor.getScrollLeft()
lineHeightInPixels = editor.getLineHeight()
lineHeightInPixels = editor.getLineHeightInPixels()
scrollViewHeight = editor.getHeight()
horizontalScrollbarHeight = editor.getHorizontalScrollbarHeight()
verticalScrollbarWidth = editor.getVerticalScrollbarWidth()
verticallyScrollable = editor.verticallyScrollable()
horizontallyScrollable = editor.horizontallyScrollable()
className = 'editor editor-colors react'
className += ' is-focused' if focused
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1,
GutterComponent {
editor, renderedRowRange, scrollTop, scrollHeight,
lineHeight: lineHeightInPixels, @pendingChanges
ref: 'gutter', editor, renderedRowRange, maxLineNumberDigits,
scrollTop, scrollHeight, lineHeight, lineHeightInPixels, fontSize, fontFamily,
@pendingChanges, onWidthChanged: @onGutterWidthChanged, @mouseWheelScreenRow
}
EditorScrollViewComponent {
ref: 'scrollView', editor, fontSize, fontFamily, showIndentGuide
scrollHeight, scrollWidth, lineHeight: lineHeightInPixels,
renderedRowRange, @pendingChanges, @scrollingVertically, @cursorsMoved,
cursorBlinkPeriod, cursorBlinkResumeDelay, @onInputFocused, @onInputBlurred
ref: 'scrollView', editor, fontSize, fontFamily, showIndentGuide,
lineHeight, lineHeightInPixels, renderedRowRange, @pendingChanges,
scrollTop, scrollLeft, scrollHeight, scrollWidth, @scrollingVertically,
@cursorsMoved, @selectionChanged, @selectionAdded, cursorBlinkPeriod,
cursorBlinkResumeDelay, @onInputFocused, @onInputBlurred, @mouseWheelScreenRow,
invisibles, visible, scrollViewHeight
}
ScrollbarComponent
@@ -55,6 +75,10 @@ EditorComponent = React.createClass
onScroll: @onVerticalScroll
scrollTop: scrollTop
scrollHeight: scrollHeight
visible: verticallyScrollable and not @refreshingScrollbars and not @measuringScrollbars
scrollableInOppositeDirection: horizontallyScrollable
verticalScrollbarWidth: verticalScrollbarWidth
horizontalScrollbarHeight: horizontalScrollbarHeight
ScrollbarComponent
ref: 'horizontalScrollbar'
@@ -62,20 +86,34 @@ EditorComponent = React.createClass
orientation: 'horizontal'
onScroll: @onHorizontalScroll
scrollLeft: scrollLeft
scrollWidth: scrollWidth
scrollWidth: scrollWidth + @gutterWidth
visible: horizontallyScrollable and not @refreshingScrollbars and not @measuringScrollbars
scrollableInOppositeDirection: verticallyScrollable
verticalScrollbarWidth: verticalScrollbarWidth
horizontalScrollbarHeight: horizontalScrollbarHeight
# Also used to measure the height/width of scrollbars after the initial render
ScrollbarCornerComponent
ref: 'scrollbarCorner'
visible: not @refreshingScrollbars and (@measuringScrollbars or horizontallyScrollable and verticallyScrollable)
measuringScrollbars: @measuringScrollbars
height: horizontalScrollbarHeight
width: verticalScrollbarWidth
getRenderedRowRange: ->
renderedRowRange = @props.editor.getVisibleRowRange()
if @preservedRowRange?
renderedRowRange[0] = Math.min(@preservedRowRange[0], renderedRowRange[0])
renderedRowRange[1] = Math.max(@preservedRowRange[1], renderedRowRange[1])
renderedRowRange
{editor, lineOverdrawMargin} = @props
[visibleStartRow, visibleEndRow] = editor.getVisibleRowRange()
renderedStartRow = Math.max(0, visibleStartRow - lineOverdrawMargin)
renderedEndRow = Math.min(editor.getScreenLineCount(), visibleEndRow + lineOverdrawMargin)
[renderedStartRow, renderedEndRow]
getInitialState: -> {}
getInitialState: ->
visible: true
getDefaultProps: ->
cursorBlinkPeriod: 800
cursorBlinkResumeDelay: 200
cursorBlinkResumeDelay: 100
lineOverdrawMargin: 8
componentWillMount: ->
@pendingChanges = []
@@ -86,6 +124,9 @@ EditorComponent = React.createClass
@observeEditor()
@listenForDOMEvents()
@listenForCommands()
@measureScrollbars()
@subscribe atom.themes, 'stylesheet-added stylsheet-removed', @onStylesheetsChanged
@subscribe scrollbarStyle.changes, @refreshScrollbars
@props.editor.setVisible(true)
@requestUpdate()
@@ -99,6 +140,10 @@ EditorComponent = React.createClass
componentDidUpdate: ->
@pendingChanges.length = 0
@cursorsMoved = false
@selectionChanged = false
@selectionAdded = false
@refreshingScrollbars = false
@measureScrollbars() if @measuringScrollbars
@props.parentView.trigger 'editor:display-updated'
observeEditor: ->
@@ -107,15 +152,14 @@ EditorComponent = React.createClass
@subscribe editor, 'batched-updates-ended', @onBatchedUpdatesEnded
@subscribe editor, 'screen-lines-changed', @onScreenLinesChanged
@subscribe editor, 'cursors-moved', @onCursorsMoved
@subscribe editor, 'selection-screen-range-changed', @requestUpdate
@subscribe editor, 'selection-removed selection-screen-range-changed', @onSelectionChanged
@subscribe editor, 'selection-added', @onSelectionAdded
@subscribe editor, 'selection-removed', @onSelectionAdded
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
@subscribe editor.$scrollLeft.changes, @requestUpdate
@subscribe editor.$height.changes, @requestUpdate
@subscribe editor.$width.changes, @requestUpdate
@subscribe editor.$defaultCharWidth.changes, @requestUpdate
@subscribe editor.$lineHeight.changes, @requestUpdate
@subscribe editor.$lineHeightInPixels.changes, @requestUpdate
listenForDOMEvents: ->
node = @getDOMNode()
@@ -141,8 +185,8 @@ EditorComponent = React.createClass
'editor:move-to-previous-word': => editor.moveCursorToPreviousWord()
'editor:select-word': => editor.selectWord()
'editor:consolidate-selections': @consolidateSelections
'editor:backspace-to-beginning-of-word': => editor.backspaceToBeginningOfWord()
'editor:backspace-to-beginning-of-line': => editor.backspaceToBeginningOfLine()
'editor:delete-to-beginning-of-word': => editor.deleteToBeginningOfWord()
'editor:delete-to-beginning-of-line': => editor.deleteToBeginningOfLine()
'editor:delete-to-end-of-word': => editor.deleteToEndOfWord()
'editor:delete-line': => editor.deleteLine()
'editor:cut-to-end-of-line': => editor.cutToEndOfLine()
@@ -218,6 +262,7 @@ EditorComponent = React.createClass
'editor:scroll-to-cursor': => editor.scrollToCursorPosition()
'core:page-up': => editor.pageUp()
'core:page-down': => editor.pageDown()
'benchmark:scroll': @runScrollBenchmark
addCommandListeners: (listenersByCommandName) ->
{parentView} = @props
@@ -228,7 +273,20 @@ EditorComponent = React.createClass
observeConfig: ->
@subscribe atom.config.observe 'editor.fontFamily', @setFontFamily
@subscribe atom.config.observe 'editor.fontSize', @setFontSize
@subscribe atom.config.observe 'editor.lineHeight', @setLineHeight
@subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide
@subscribe atom.config.observe 'editor.invisibles', @setInvisibles
@subscribe atom.config.observe 'editor.showInvisibles', @setShowInvisibles
measureScrollbars: ->
@measuringScrollbars = false
{editor} = @props
scrollbarCornerNode = @refs.scrollbarCorner.getDOMNode()
width = (scrollbarCornerNode.offsetWidth - scrollbarCornerNode.clientWidth) or 15
height = (scrollbarCornerNode.offsetHeight - scrollbarCornerNode.clientHeight) or 15
editor.setVerticalScrollbarWidth(width)
editor.setHorizontalScrollbarHeight(height)
setFontSize: (fontSize) ->
@setState({fontSize})
@@ -242,6 +300,25 @@ EditorComponent = React.createClass
setShowIndentGuide: (showIndentGuide) ->
@setState({showIndentGuide})
# Public: Defines which characters are invisible.
#
# invisibles - An {Object} defining the invisible characters:
# :eol - The end of line invisible {String} (default: `\u00ac`).
# :space - The space invisible {String} (default: `\u00b7`).
# :tab - The tab invisible {String} (default: `\u00bb`).
# :cr - The carriage return invisible {String} (default: `\u00a4`).
setInvisibles: (invisibles={}) ->
defaults invisibles,
eol: '\u00ac'
space: '\u00b7'
tab: '\u00bb'
cr: '\u00a4'
@setState({invisibles})
setShowInvisibles: (showInvisibles) ->
@setState({showInvisibles})
onFocus: ->
@refs.scrollView.focus()
@@ -276,21 +353,61 @@ EditorComponent = React.createClass
@pendingScrollLeft = null
onMouseWheel: (event) ->
event.preventDefault()
screenRow = @screenRowForNode(event.target)
@mouseWheelScreenRow = screenRow if screenRow?
animationFramePending = @pendingHorizontalScrollDelta isnt 0 or @pendingVerticalScrollDelta isnt 0
# Only scroll in one direction at a time
{wheelDeltaX, wheelDeltaY} = event
if Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY)
@refs.horizontalScrollbar.getDOMNode().scrollLeft -= wheelDeltaX
@pendingHorizontalScrollDelta -= wheelDeltaX
else
@refs.verticalScrollbar.getDOMNode().scrollTop -= wheelDeltaY
@pendingVerticalScrollDelta -= wheelDeltaY
event.preventDefault()
unless animationFramePending
requestAnimationFrame =>
{editor} = @props
editor.setScrollTop(editor.getScrollTop() + @pendingVerticalScrollDelta)
editor.setScrollLeft(editor.getScrollLeft() + @pendingHorizontalScrollDelta)
@pendingVerticalScrollDelta = 0
@pendingHorizontalScrollDelta = 0
clearPreservedRowRange: ->
@preservedRowRange = null
@scrollingVertically = false
screenRowForNode: (node) ->
while node isnt document
if screenRow = node.dataset.screenRow
return parseInt(screenRow)
node = node.parentNode
null
onStylesheetsChanged: (stylesheet) ->
@refreshScrollbars() if @containsScrollbarSelector(stylesheet)
containsScrollbarSelector: (stylesheet) ->
for rule in stylesheet.cssRules
if rule.selectorText?.indexOf('scrollbar') > -1
return true
false
refreshScrollbars: ->
# Believe it or not, proper handling of changes to scrollbar styles requires
# three DOM updates.
# Scrollbar style changes won't apply to scrollbars that are already
# visible, so first we need to hide scrollbars so we can redisplay them and
# force Chromium to apply updates.
@refreshingScrollbars = true
@requestUpdate()
clearPreservedRowRangeAfterDelay: null # Created lazily
# Next, we display only the scrollbar corner so we can measure the new
# scrollbar dimensions. The ::measuringScrollbars property will be set back
# to false after the scrollbars are measured.
@measuringScrollbars = true
@requestUpdate()
# Finally, we restore the scrollbars based on the newly-measured dimensions
# if the editor's content and dimensions require them to be visible.
@requestUpdate()
onBatchedUpdatesStarted: ->
@batchingUpdates = true
@@ -307,24 +424,38 @@ EditorComponent = React.createClass
@pendingChanges.push(change)
@requestUpdate() if editor.intersectsVisibleRowRange(change.start, change.end + 1) # TODO: Use closed-open intervals for change events
onSelectionChanged: (selection) ->
{editor} = @props
if editor.selectionIntersectsVisibleRowRange(selection)
@selectionChanged = true
@requestUpdate()
onSelectionAdded: (selection) ->
{editor} = @props
@requestUpdate() if editor.selectionIntersectsVisibleRowRange(selection)
if editor.selectionIntersectsVisibleRowRange(selection)
@selectionChanged = true
@selectionAdded = true
@requestUpdate()
onScrollTopChanged: ->
@preservedRowRange = @getRenderedRowRange()
@scrollingVertically = true
@clearPreservedRowRangeAfterDelay ?= debounce(@clearPreservedRowRange, 200)
@clearPreservedRowRangeAfterDelay()
@requestUpdate()
@stopScrollingAfterDelay ?= debounce(@onStoppedScrolling, 100)
@stopScrollingAfterDelay()
onStoppedScrolling: ->
@scrollingVertically = false
@mouseWheelScreenRow = null
@requestUpdate()
onSelectionRemoved: (selection) ->
{editor} = @props
@requestUpdate() if editor.selectionIntersectsVisibleRowRange(selection)
stopScrollingAfterDelay: null # created lazily
onCursorsMoved: ->
@cursorsMoved = true
onGutterWidthChanged: (@gutterWidth) ->
@requestUpdate()
requestUpdate: ->
if @batchingUpdates
@updateRequested = true
@@ -336,3 +467,48 @@ EditorComponent = React.createClass
consolidateSelections: (e) ->
e.abortKeyBinding() unless @props.editor.consolidateSelections()
lineNodeForScreenRow: (screenRow) -> @refs.scrollView.lineNodeForScreenRow(screenRow)
lineNumberNodeForScreenRow: (screenRow) -> @refs.gutter.lineNumberNodeForScreenRow(screenRow)
hide: ->
@setState(visible: false)
show: ->
@setState(visible: true)
runScrollBenchmark: ->
unless process.env.NODE_ENV is 'production'
ReactPerf = require 'react-atom-fork/lib/ReactDefaultPerf'
ReactPerf.start()
node = @getDOMNode()
scroll = (delta, done) ->
dispatchMouseWheelEvent = ->
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -0, wheelDeltaY: -delta))
stopScrolling = ->
clearInterval(interval)
done?()
interval = setInterval(dispatchMouseWheelEvent, 10)
setTimeout(stopScrolling, 500)
console.timeline('scroll')
scroll 50, ->
scroll 100, ->
scroll 200, ->
scroll 400, ->
scroll 800, ->
scroll 1600, ->
console.timelineEnd('scroll')
unless process.env.NODE_ENV is 'production'
ReactPerf.stop()
console.log "Inclusive"
ReactPerf.printInclusive()
console.log "Exclusive"
ReactPerf.printExclusive()
console.log "Wasted"
ReactPerf.printWasted()
+23 -25
Ver Arquivo
@@ -1,5 +1,5 @@
React = require 'react'
{div} = require 'reactionary'
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{debounce} = require 'underscore-plus'
InputComponent = require './input-component'
@@ -16,20 +16,15 @@ EditorScrollViewComponent = React.createClass
overflowChangedWhilePaused: false
render: ->
{editor, fontSize, fontFamily, lineHeight, showIndentGuide} = @props
{scrollHeight, scrollWidth, renderedRowRange, pendingChanges, scrollingVertically} = @props
{cursorBlinkPeriod, cursorBlinkResumeDelay, cursorsMoved, onInputFocused, onInputBlurred} = @props
{editor, fontSize, fontFamily, lineHeight, lineHeightInPixels, showIndentGuide, invisibles, visible} = @props
{renderedRowRange, pendingChanges, scrollTop, scrollLeft, scrollHeight, scrollWidth, scrollViewHeight, scrollingVertically, mouseWheelScreenRow} = @props
{selectionChanged, selectionAdded, cursorBlinkPeriod, cursorBlinkResumeDelay, cursorsMoved, onInputFocused, onInputBlurred} = @props
if @isMounted()
inputStyle = @getHiddenInputPosition()
inputStyle.WebkitTransform = 'translateZ(0)'
contentStyle =
height: scrollHeight
minWidth: scrollWidth
WebkitTransform: "translate3d(#{-editor.getScrollLeft()}px, #{-editor.getScrollTop()}px, 0)"
div className: 'scroll-view',
div className: 'scroll-view', onMouseDown: @onMouseDown,
InputComponent
ref: 'input'
className: 'hidden-input'
@@ -38,14 +33,13 @@ EditorScrollViewComponent = React.createClass
onFocus: onInputFocused
onBlur: onInputBlurred
div className: 'scroll-view-content', style: contentStyle, onMouseDown: @onMouseDown,
CursorsComponent({editor, cursorsMoved, cursorBlinkPeriod, cursorBlinkResumeDelay})
LinesComponent {
ref: 'lines', editor, fontSize, fontFamily, lineHeight, showIndentGuide,
renderedRowRange, pendingChanges, scrollingVertically
}
div className: 'underlayer',
SelectionsComponent({editor})
CursorsComponent({editor, scrollTop, scrollLeft, cursorsMoved, selectionAdded, cursorBlinkPeriod, cursorBlinkResumeDelay})
LinesComponent {
ref: 'lines', editor, fontSize, fontFamily, lineHeight, lineHeightInPixels,
showIndentGuide, renderedRowRange, pendingChanges, scrollTop, scrollLeft, scrollingVertically,
selectionChanged, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
visible, scrollViewHeight
}
componentDidMount: ->
@getDOMNode().addEventListener 'overflowchanged', @onOverflowChanged
@@ -182,17 +176,21 @@ EditorScrollViewComponent = React.createClass
measureHeightAndWidth: ->
return unless @isMounted()
node = @getDOMNode()
computedStyle = getComputedStyle(node)
{editor} = @props
node = @getDOMNode()
editorNode = node.parentNode
{position} = getComputedStyle(editorNode)
{width, height} = editorNode.style
unless computedStyle.height is '0px'
clientHeight = node.clientHeight
if position is 'absolute' or height
clientHeight = node.clientHeight
editor.setHeight(clientHeight) if clientHeight > 0
unless computedStyle.width is '0px'
if position is 'absolute' or width
clientWidth = node.clientWidth
editor.setWidth(clientWidth) if clientHeight > 0
editor.setWidth(clientWidth) if clientWidth > 0
focus: ->
@refs.input.focus()
lineNodeForScreenRow: (screenRow) -> @refs.lines.lineNodeForScreenRow(screenRow)
+9 -6
Ver Arquivo
@@ -50,7 +50,7 @@ class EditorView extends View
showLineNumbers: true
autoIndent: true
normalizeIndentOnPaste: true
nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
nonWordCharacters: "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
preferredLineLength: 80
tabLength: 2
softWrap: false
@@ -154,8 +154,8 @@ class EditorView extends View
'editor:move-to-previous-word': => @editor.moveCursorToPreviousWord()
'editor:select-word': => @editor.selectWord()
'editor:consolidate-selections': (event) => @consolidateSelections(event)
'editor:backspace-to-beginning-of-word': => @editor.backspaceToBeginningOfWord()
'editor:backspace-to-beginning-of-line': => @editor.backspaceToBeginningOfLine()
'editor:delete-to-beginning-of-word': => @editor.deleteToBeginningOfWord()
'editor:delete-to-beginning-of-line': => @editor.deleteToBeginningOfLine()
'editor:delete-to-end-of-word': => @editor.deleteToEndOfWord()
'editor:delete-line': => @editor.deleteLine()
'editor:cut-to-end-of-line': => @editor.cutToEndOfLine()
@@ -387,7 +387,7 @@ class EditorView extends View
screenPosition = @screenPositionFromMouseEvent(e)
if clickCount == 1
if e.metaKey
if e.metaKey or (process.platform isnt 'darwin' and e.ctrlKey)
@editor.addCursorAtScreenPosition(screenPosition)
else if e.shiftKey
@editor.selectToScreenPosition(screenPosition)
@@ -460,6 +460,9 @@ class EditorView extends View
@hiddenInput.val(lastInput)
false
# Ignore paste event, on Linux is wrongly emitted when user presses ctrl-v.
@on "paste", -> false
bringHiddenInputIntoView: ->
@hiddenInput.css(top: @scrollTop(), left: @scrollLeft())
@@ -472,7 +475,7 @@ class EditorView extends View
$(document).off 'mouseup', finalizeSelections
unless @editor.isDestroyed()
@editor.mergeIntersectingSelections(isReversed: @editor.getLastSelection().isReversed())
@editor.mergeIntersectingSelections(reversed: @editor.getLastSelection().isReversed())
@editor.finalizeSelections()
@syncCursorAnimations()
@@ -1487,7 +1490,7 @@ class EditorView extends View
position = 0
for token in tokens
@updateScopeStack(line, scopeStack, token.scopes)
hasIndentGuide = not mini and showIndentGuide and token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly)
hasIndentGuide = not mini and showIndentGuide and (token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly))
line.push(token.getValueAsHtml({invisibles, hasIndentGuide}))
position += token.value.length
+81 -34
Ver Arquivo
@@ -109,8 +109,8 @@ TextMateScopeSelector = require('first-mate').ScopeSelector
# - {::insertNewlineAbove}
# - {::insertNewlineBelow}
# - {::backspace}
# - {::backspaceToBeginningOfWord}
# - {::backspaceToBeginningOfLine}
# - {::deleteToBeginningOfWord}
# - {::deleteToBeginningOfLine}
# - {::delete}
# - {::deleteToEndOfWord}
# - {::deleteLine}
@@ -149,10 +149,10 @@ class Editor extends Model
'autoDecreaseIndentForBufferRow', 'toggleLineCommentForBufferRow', 'toggleLineCommentsForBufferRows',
toProperty: 'languageMode'
@delegatesProperties '$lineHeight', '$defaultCharWidth', '$height', '$width',
@delegatesProperties '$lineHeightInPixels', '$defaultCharWidth', '$height', '$width',
'$scrollTop', '$scrollLeft', 'manageScrollPosition', toProperty: 'displayBuffer'
constructor: ({@softTabs, initialLine, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation}) ->
constructor: ({@softTabs, initialLine, initialColumn, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation}) ->
super
@cursors = []
@@ -160,7 +160,7 @@ class Editor extends Model
@displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrap})
@buffer = @displayBuffer.buffer
@softTabs = @buffer.usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true
@softTabs = @usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true
for marker in @findMarkers(@getSelectionMarkerAttributes())
marker.setAttributes(preserveFolds: true)
@@ -170,11 +170,9 @@ class Editor extends Model
@subscribeToDisplayBuffer()
if @getCursors().length is 0 and not suppressCursorCreation
if initialLine
position = [initialLine, 0]
else
position = [0, 0]
@addCursorAtBufferPosition(position)
initialLine = Math.max(parseInt(initialLine) or 0, 0)
initialColumn = Math.max(parseInt(initialColumn) or 0, 0)
@addCursorAtBufferPosition([initialLine, initialColumn])
@languageMode = new LanguageMode(this)
@@ -266,7 +264,7 @@ class Editor extends Model
else
'untitled'
# Controls visiblity based on the given {Boolean}.
# Controls visibility based on the given {Boolean}.
setVisible: (visible) -> @displayBuffer.setVisible(visible)
# Set the number of characters that can be displayed horizontally in the
@@ -277,7 +275,7 @@ class Editor extends Model
setEditorWidthInChars: (editorWidthInChars) ->
@displayBuffer.setEditorWidthInChars(editorWidthInChars)
# Public: Sets the column at which columsn will soft wrap
# Public: Sets the column at which column will soft wrap
getSoftWrapColumn: -> @displayBuffer.getSoftWrapColumn()
# Public: Returns a {Boolean} indicating whether softTabs are enabled for this
@@ -319,6 +317,19 @@ class Editor extends Model
# Public: Set the on-screen length of tab characters.
setTabLength: (tabLength) -> @displayBuffer.setTabLength(tabLength)
# Public: Determine if the buffer uses hard or soft tabs.
#
# Returns `true` if the first non-comment line with leading whitespace starts
# with a space character. Returns `false` if it starts with a hard tab (`\t`).
#
# Returns a {Boolean},
usesSoftTabs: ->
for bufferRow in [0..@buffer.getLastRow()]
continue if @displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment()
if match = @buffer.lineForRow(bufferRow).match(/^\s/)
return match[0][0] != '\t'
undefined
# Public: Clip the given {Point} to a valid position in the buffer.
#
# If the given {Point} describes a position that is actually reachable by the
@@ -466,7 +477,7 @@ class Editor extends Model
# options - An options hash with an `includeNewline` key.
#
# Returns a {Range}.
bufferRangeForBufferRow: (row, options) -> @buffer.rangeForRow(row, options)
bufferRangeForBufferRow: (row, {includeNewline}={}) -> @buffer.rangeForRow(row, includeNewline)
# Public: Returns a {String} representing the contents of the line at the
# given buffer row.
@@ -565,8 +576,8 @@ class Editor extends Model
bufferRowForScreenRow: (row) -> @displayBuffer.bufferRowForScreenRow(row)
# Public: Get the syntactic scopes for the most the given position in buffer
# coorditanates.
# Public: Get the syntactic scopes for the given position in buffer
# coordinates.
#
# For example, if called with a position inside the parameter list of an
# anonymous CoffeeScript function, the method returns the following array:
@@ -647,17 +658,27 @@ class Editor extends Model
backspace: ->
@mutateSelectedText (selection) -> selection.backspace()
# Deprecated: Use {::deleteToBeginningOfWord} instead.
backspaceToBeginningOfWord: ->
deprecate("Use Editor::deleteToBeginningOfWord() instead")
@deleteToBeginningOfWord()
# Deprecated: Use {::deleteToBeginningOfLine} instead.
backspaceToBeginningOfLine: ->
deprecate("Use Editor::deleteToBeginningOfLine() instead")
@deleteToBeginningOfLine()
# Public: For each selection, if the selection is empty, delete all characters
# of the containing word that precede the cursor. Otherwise delete the
# selected text.
backspaceToBeginningOfWord: ->
@mutateSelectedText (selection) -> selection.backspaceToBeginningOfWord()
deleteToBeginningOfWord: ->
@mutateSelectedText (selection) -> selection.deleteToBeginningOfWord()
# Public: For each selection, if the selection is empty, delete all characters
# of the containing line that precede the cursor. Otherwise delete the
# selected text.
backspaceToBeginningOfLine: ->
@mutateSelectedText (selection) -> selection.backspaceToBeginningOfLine()
deleteToBeginningOfLine: ->
@mutateSelectedText (selection) -> selection.deleteToBeginningOfLine()
# Public: For each selection, if the selection is empty, delete the character
# preceding the cursor. Otherwise delete the selected text.
@@ -727,13 +748,24 @@ class Editor extends Model
# Public: For each selection, replace the selected text with the contents of
# the clipboard.
#
# If the clipboard contains the same number of selections as the current
# editor, each selection will be replaced with the content of the
# corresponding clipboard selection text.
#
# options - See {Selection::insertText}.
pasteText: (options={}) ->
{text, metadata} = atom.clipboard.readWithMetadata()
containsNewlines = text.indexOf('\n') isnt -1
if atom.config.get('editor.normalizeIndentOnPaste') and metadata
if metadata?.selections? and metadata.selections.length is @getSelections().length
@mutateSelectedText (selection, index) ->
text = metadata.selections[index]
selection.insertText(text, options)
return
else if atom.config.get("editor.normalizeIndentOnPaste") and metadata?.indentBasis?
if !@getCursor().hasPrecedingCharactersOnLine() or containsNewlines
options.indentBasis ?= metadata.indentBasis
@@ -895,7 +927,7 @@ class Editor extends Model
endRow = row
insertPosition = Point.fromObject([startRow - insertDelta])
endPosition = Point.min([endRow + 1], @buffer.getEofPosition())
endPosition = Point.min([endRow + 1], @buffer.getEndPosition())
lines = @buffer.getTextInRange([[startRow], endPosition])
if endPosition.row is lastRow and endPosition.column > 0 and not @buffer.lineEndingForRow(endPosition.row)
lines = "#{lines}\n"
@@ -954,7 +986,7 @@ class Editor extends Model
lines = @buffer.getTextInRange([[startRow], endPosition])
@buffer.deleteRows(startRow, endRow)
insertPosition = Point.min([startRow + insertDelta], @buffer.getEofPosition())
insertPosition = Point.min([startRow + insertDelta], @buffer.getEndPosition())
if insertPosition.row is @buffer.getLastRow() and insertPosition.column > 0
lines = "\n#{lines}"
@@ -1009,7 +1041,7 @@ class Editor extends Model
#
# fn - A {Function} that will be called with each {Selection}.
mutateSelectedText: (fn) ->
@transact => fn(selection) for selection in @getSelections()
@transact => fn(selection,index) for selection,index in @getSelections()
replaceSelectedText: (options={}, fn) ->
{selectWordIfEmpty} = options
@@ -1237,6 +1269,9 @@ class Editor extends Model
# Returns: An {Array} of {Selection}s.
getSelections: -> new Array(@selections...)
selectionsForScreenRows: (startRow, endRow) ->
@getSelections().filter (selection) -> selection.intersectsScreenRowRange(startRow, endRow)
# Public: Get the most recent {Selection} or the selection at the given
# index.
#
@@ -1271,7 +1306,7 @@ class Editor extends Model
# Public: Determine if a given range in buffer coordinates intersects a
# selection.
#
# bufferRange - A {Range} or range-comptatible {Array}.
# bufferRange - A {Range} or range-compatible {Array}.
#
# Returns a {Boolean}.
selectionIntersectsBufferRange: (bufferRange) ->
@@ -1483,7 +1518,7 @@ class Editor extends Model
selectToScreenPosition: (position) ->
lastSelection = @getLastSelection()
lastSelection.selectToScreenPosition(position)
@mergeIntersectingSelections(isReversed: lastSelection.isReversed())
@mergeIntersectingSelections(reversed: lastSelection.isReversed())
# Public: Move the cursor of each selection one character rightward while
# preserving the selection's tail position.
@@ -1545,28 +1580,28 @@ class Editor extends Model
# cursor is already on the first character of the line, move it to the
# beginning of the line.
#
# This method may merge selections that end up intesecting.
# This method may merge selections that end up intersecting.
selectToFirstCharacterOfLine: ->
@expandSelectionsBackward (selection) => selection.selectToFirstCharacterOfLine()
# Public: Move the cursor of each selection to the end of its line while
# preserving the selection's tail position.
#
# This method may merge selections that end up intesecting.
# This method may merge selections that end up intersecting.
selectToEndOfLine: ->
@expandSelectionsForward (selection) => selection.selectToEndOfLine()
# Public: For each selection, move its cursor to the preceding word boundary
# while maintaining the selection's tail position.
#
# This method may merge selections that end up intesecting.
# This method may merge selections that end up intersecting.
selectToPreviousWordBoundary: ->
@expandSelectionsBackward (selection) => selection.selectToPreviousWordBoundary()
# Public: For each selection, move its cursor to the next word boundary while
# maintaining the selection's tail position.
#
# This method may merge selections that end up intesecting.
# This method may merge selections that end up intersecting.
selectToNextWordBoundary: ->
@expandSelectionsForward (selection) => selection.selectToNextWordBoundary()
@@ -1576,7 +1611,7 @@ class Editor extends Model
selectLine: ->
@expandSelectionsForward (selection) => selection.selectLine()
# Public: Add a similarly-shaped selection to the next elibible line below
# Public: Add a similarly-shaped selection to the next eligible line below
# each selection.
#
# Operates on all selections. If the selection is empty, adds an empty
@@ -1587,7 +1622,7 @@ class Editor extends Model
addSelectionBelow: ->
@expandSelectionsForward (selection) => selection.addSelectionBelow()
# Public: Add a similarly-shaped selection to the next elibible line above
# Public: Add a similarly-shaped selection to the next eligible line above
# each selection.
#
# Operates on all selections. If the selection is empty, adds an empty
@@ -1710,7 +1745,7 @@ class Editor extends Model
# Calls the given function with each selection, then merges selections in the
# reversed orientation
expandSelectionsBackward: (fn) ->
@mergeIntersectingSelections isReversed: true, =>
@mergeIntersectingSelections reversed: true, =>
fn(selection) for selection in @getSelections()
finalizeSelections: ->
@@ -1824,8 +1859,8 @@ class Editor extends Model
getHorizontalScrollMargin: -> @displayBuffer.getHorizontalScrollMargin()
setHorizontalScrollMargin: (horizontalScrollMargin) -> @displayBuffer.setHorizontalScrollMargin(horizontalScrollMargin)
getLineHeight: -> @displayBuffer.getLineHeight()
setLineHeight: (lineHeight) -> @displayBuffer.setLineHeight(lineHeight)
getLineHeightInPixels: -> @displayBuffer.getLineHeightInPixels()
setLineHeightInPixels: (lineHeightInPixels) -> @displayBuffer.setLineHeightInPixels(lineHeightInPixels)
getScopedCharWidth: (scopeNames, char) -> @displayBuffer.getScopedCharWidth(scopeNames, char)
setScopedCharWidth: (scopeNames, char, width) -> @displayBuffer.setScopedCharWidth(scopeNames, char, width)
@@ -1840,6 +1875,8 @@ class Editor extends Model
setHeight: (height) -> @displayBuffer.setHeight(height)
getHeight: -> @displayBuffer.getHeight()
getClientHeight: -> @displayBuffer.getClientHeight()
setWidth: (width) -> @displayBuffer.setWidth(width)
getWidth: -> @displayBuffer.getWidth()
@@ -1878,6 +1915,16 @@ class Editor extends Model
scrollToBufferPosition: (bufferPosition) -> @displayBuffer.scrollToBufferPosition(bufferPosition)
horizontallyScrollable: -> @displayBuffer.horizontallyScrollable()
verticallyScrollable: -> @displayBuffer.verticallyScrollable()
getHorizontalScrollbarHeight: -> @displayBuffer.getHorizontalScrollbarHeight()
setHorizontalScrollbarHeight: (height) -> @displayBuffer.setHorizontalScrollbarHeight(height)
getVerticalScrollbarWidth: -> @displayBuffer.getVerticalScrollbarWidth()
setVerticalScrollbarWidth: (width) -> @displayBuffer.setVerticalScrollbarWidth(width)
# Deprecated: Call {::joinLines} instead.
joinLine: ->
deprecate("Use Editor::joinLines() instead")
+7 -4
Ver Arquivo
@@ -13,7 +13,7 @@ Task = require './task'
# `atom.project` global and calling `getRepo()`. Note that this will only be
# available when the project is backed by a Git repository.
#
# This class handles submodules automically by taking a `path` argument to many
# This class handles submodules automatically by taking a `path` argument to many
# of the methods. This `path` argument will determine which underlying
# repository is used.
#
@@ -135,6 +135,7 @@ class Git
relativePath = @relativize(path)
currentPathStatus = @statuses[relativePath] ? 0
pathStatus = repo.getStatus(repo.relativize(path)) ? 0
pathStatus = 0 if repo.isStatusIgnored(pathStatus)
if pathStatus > 0
@statuses[relativePath] = pathStatus
else
@@ -344,8 +345,10 @@ class Git
# Refreshes the current git status in an outside process and asynchronously
# updates the relevant properties.
refreshStatus: ->
handlerPath = require.resolve('./repository-status-handler')
@statusTask = Task.once handlerPath, @getPath(), ({statuses, upstream, branch, submodules}) =>
@handlerPath ?= require.resolve('./repository-status-handler')
@statusTask?.terminate()
@statusTask = Task.once @handlerPath, @getPath(), ({statuses, upstream, branch, submodules}) =>
statusesUnchanged = _.isEqual(statuses, @statuses) and
_.isEqual(upstream, @upstream) and
_.isEqual(branch, @branch) and
@@ -357,6 +360,6 @@ class Git
@submodules = submodules
for submodulePath, submoduleRepo of @getRepo().submodules
submoduleRepo.upstream = submodules[submodulePath].upstream
submoduleRepo.upstream = submodules[submodulePath]?.upstream ? {ahead: 0, behind: 0}
@emit 'statuses-changed' unless statusesUnchanged
+93 -48
Ver Arquivo
@@ -1,79 +1,124 @@
React = require 'react'
{div} = require 'reactionary'
{isEqual, isEqualForProperties, multiplyString} = require 'underscore-plus'
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
SubscriberMixin = require './subscriber-mixin'
WrapperDiv = document.createElement('div')
Nbsp = String.fromCharCode(160)
module.exports =
GutterComponent = React.createClass
displayName: 'GutterComponent'
mixins: [SubscriberMixin]
lastMeasuredWidth: null
wrapCountsByScreenRow: null
render: ->
{scrollHeight, scrollTop} = @props
style =
height: scrollHeight
WebkitTransform: "translate3d(0px, #{-scrollTop}px, 0px)"
div className: 'gutter',
@renderLineNumbers() if @isMounted()
div className: 'line-numbers', ref: 'lineNumbers', style: style,
@renderDummyLineNode()
@renderLineNumbers() if @isMounted()
renderDummyLineNode: ->
{editor} = @props
@renderLineNumber('dummy', null, editor.getLastBufferRow(), false)
renderLineNumbers: ->
{editor, renderedRowRange, scrollTop, scrollHeight} = @props
{editor, renderedRowRange, maxLineNumberDigits, lineHeightInPixels, mouseWheelScreenRow} = @props
[startRow, endRow] = renderedRowRange
charWidth = editor.getDefaultCharWidth()
lineHeight = editor.getLineHeight()
maxDigits = editor.getLastBufferRow().toString().length
style =
width: charWidth * (maxDigits + 1.5)
height: scrollHeight
WebkitTransform: "translate3d(0, #{-scrollTop}px, 0)"
lineNumbers = []
tokenizedLines = editor.linesForScreenRows(startRow, endRow - 1)
tokenizedLines.push({id: 0}) if tokenizedLines.length is 0
for bufferRow, i in editor.bufferRowsForScreenRows(startRow, endRow - 1)
if bufferRow is lastBufferRow
lineNumber = ''
lastBufferRow = null
wrapCount = 0
wrapCountsByScreenRow = {}
lineNumberComponents =
for bufferRow, i in editor.bufferRowsForScreenRows(startRow, endRow - 1)
if bufferRow is lastBufferRow
softWrapped = true
key = "#{bufferRow}-#{++wrapCount}"
else
softWrapped = false
key = bufferRow.toString()
lastBufferRow = bufferRow
wrapCount = 0
screenRow = startRow + i
wrapCountsByScreenRow[screenRow] = wrapCount
@renderLineNumber(key, screenRow, bufferRow, softWrapped)
# Preserve the mouse wheel target's screen row if it exists
if mouseWheelScreenRow? and not (startRow <= mouseWheelScreenRow < endRow)
screenRow = mouseWheelScreenRow
bufferRow = editor.bufferRowForScreenRow(screenRow)
wrapCount = @wrapCountsByScreenRow[screenRow]
wrapCountsByScreenRow[screenRow] = wrapCount
if softWrapped = (wrapCount > 0)
key = "#{bufferRow}-#{wrapCount}"
else
lastBufferRow = bufferRow
lineNumber = (bufferRow + 1).toString()
key = bufferRow.toString()
key = tokenizedLines[i].id
screenRow = startRow + i
lineNumbers.push(LineNumberComponent({key, lineNumber, maxDigits, bufferRow, screenRow, lineHeight}))
lastBufferRow = bufferRow
lineNumberComponents.push(@renderLineNumber(key, screenRow, bufferRow, false, endRow))
div className: 'line-numbers', style: style,
lineNumbers
@wrapCountsByScreenRow = wrapCountsByScreenRow
lineNumberComponents
renderLineNumber: (key, screenRow, bufferRow, softWrapped, screenRowOverride) ->
{lineHeightInPixels, maxLineNumberDigits} = @props
if screenRow?
style =
position: 'absolute'
top: (screenRowOverride ? screenRow) * lineHeightInPixels
else
style =
visibility: 'hidden'
if softWrapped
lineNumber = ""
else
lineNumber = (bufferRow + 1).toString()
if lineNumber.length < maxLineNumberDigits
padding = multiplyString(Nbsp, maxLineNumberDigits - lineNumber.length)
lineNumber = padding + lineNumber
div key: key, className: 'line-number', 'data-screen-row': screenRow, style: style,
lineNumber,
div className: 'icon-right'
# Only update the gutter if the visible row range has changed or if a
# non-zero-delta change to the screen lines has occurred within the current
# visible row range.
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props, 'renderedRowRange', 'scrollTop', 'lineHeight')
return true unless isEqualForProperties(newProps, @props, 'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'fontSize', 'maxLineNumberDigits', 'mouseWheelScreenRow')
{renderedRowRange, pendingChanges} = newProps
for change in pendingChanges when change.screenDelta > 0 or change.bufferDelta > 0
for change in pendingChanges when Math.abs(change.screenDelta) > 0 or Math.abs(change.bufferDelta) > 0
return true unless change.end <= renderedRowRange.start or renderedRowRange.end <= change.start
false
LineNumberComponent = React.createClass
displayName: 'LineNumberComponent'
componentDidUpdate: (oldProps) ->
@measureWidth() unless @lastMeasuredWidth? and isEqualForProperties(oldProps, @props, 'maxLineNumberDigits', 'fontSize', 'fontFamily')
render: ->
{bufferRow, screenRow, lineHeight} = @props
div
className: "line-number line-number-#{bufferRow}"
style: {top: screenRow * lineHeight}
'data-buffer-row': bufferRow
'data-screen-row': screenRow
dangerouslySetInnerHTML: {__html: @buildInnerHTML()}
measureWidth: ->
lineNumberNode = @refs.lineNumbers.getDOMNode().firstChild
width = lineNumberNode.offsetWidth
if width isnt @lastMeasuredWidth
@props.onWidthChanged(@lastMeasuredWidth = width)
buildInnerHTML: ->
{lineNumber, maxDigits} = @props
if lineNumber.length < maxDigits
padding = multiplyString('&nbsp;', maxDigits - lineNumber.length)
padding + lineNumber + @iconDivHTML
else
lineNumber + @iconDivHTML
lineNumberNodeForScreenRow: (screenRow) ->
{renderedRowRange} = @props
[startRow, endRow] = renderedRowRange
iconDivHTML: '<div class="icon-right"></div>'
unless startRow <= screenRow < endRow
throw new Error("Requested screenRow #{screenRow} is not currently rendered")
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(newProps, @props, 'lineHeight', 'screenRow')
@refs.lineNumbers.getDOMNode().children[screenRow - startRow + 1]
+7 -3
Ver Arquivo
@@ -1,7 +1,7 @@
punycode = require 'punycode'
{last, isEqual} = require 'underscore-plus'
React = require 'react'
{input} = require 'reactionary'
React = require 'react-atom-fork'
{input} = require 'reactionary-atom-fork'
module.exports =
InputComponent = React.createClass
@@ -10,12 +10,13 @@ InputComponent = React.createClass
render: ->
{className, style, onFocus, onBlur} = @props
input {className, style, onFocus, onBlur}
input {className, style, onFocus, onBlur, 'data-react-skip-selection-restoration': true}
getInitialState: ->
{lastChar: ''}
componentDidMount: ->
@getDOMNode().addEventListener 'paste', @onPaste
@getDOMNode().addEventListener 'input', @onInput
@getDOMNode().addEventListener 'compositionupdate', @onCompositionUpdate
@@ -32,6 +33,9 @@ InputComponent = React.createClass
shouldComponentUpdate: (newProps) ->
not isEqual(newProps.style, @props.style)
onPaste: (e) ->
e.preventDefault()
onInput: (e) ->
e.stopPropagation()
valueCharCodes = punycode.ucs2.decode(@getDOMNode().value)
+2 -1
Ver Arquivo
@@ -60,7 +60,8 @@ class LanguageMode
buffer.setTextInRange([[end, endColumn], [end, endLength]], "")
else
buffer.transact ->
buffer.insert([start, 0], commentStartString)
indentLength = buffer.lineForRow(start).match(/^\s*/)?[0].length ? 0
buffer.insert([start, indentLength], commentStartString)
buffer.insert([end, buffer.lineLengthForRow(end)], commentEndString)
else
if shouldUncomment and start isnt end
+147 -56
Ver Arquivo
@@ -1,34 +1,142 @@
React = require 'react'
{div, span} = require 'reactionary'
{debounce, isEqual, isEqualForProperties, multiplyString} = require 'underscore-plus'
React = require 'react-atom-fork'
{div, span} = require 'reactionary-atom-fork'
{debounce, isEqual, isEqualForProperties, multiplyString, toArray, clone} = require 'underscore-plus'
{$$} = require 'space-pen'
SelectionsComponent = require './selections-component'
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
AcceptFilter = {acceptNode: -> NodeFilter.FILTER_ACCEPT}
WrapperDiv = document.createElement('div')
module.exports =
LinesComponent = React.createClass
displayName: 'LinesComponent'
measureWhenShown: false
render: ->
{editor, scrollTop, scrollLeft, scrollHeight, scrollWidth, lineHeightInPixels, scrollViewHeight} = @props
if @isMounted()
{editor, renderedRowRange, lineHeight, showIndentGuide} = @props
[startRow, endRow] = renderedRowRange
style =
height: Math.max(scrollHeight, scrollViewHeight)
width: scrollWidth
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
lines =
for tokenizedLine, i in editor.linesForScreenRows(startRow, endRow - 1)
LineComponent({key: tokenizedLine.id, tokenizedLine, showIndentGuide, lineHeight, screenRow: startRow + i})
div {className: 'lines', style},
@renderLines() if @isMounted()
SelectionsComponent({key: 'selections', editor, lineHeightInPixels})
div {className: 'lines'}, lines
renderLines: ->
{editor, renderedRowRange, lineHeightInPixels, showIndentGuide, mini, invisibles, mouseWheelScreenRow} = @props
[startRow, endRow] = renderedRowRange
lineComponents =
for line, i in editor.linesForScreenRows(startRow, endRow - 1)
@renderLine(line, startRow + i)
if mouseWheelScreenRow? and not (startRow <= mouseWheelScreenRow < endRow)
lineComponents.push(@renderLine(editor.lineForScreenRow(mouseWheelScreenRow), mouseWheelScreenRow, endRow))
lineComponents
renderLine: (line, screenRow, screenRowOverride) ->
{lineHeightInPixels} = @props
style =
position: "absolute"
top: (screenRowOverride ? screenRow) * lineHeightInPixels
@lineInnerHTMLByLineId[line.id] ?= @buildLineInnerHTML(line)
innerHTML = @lineInnerHTMLByLineId[line.id]
div key: line.id, className: "line", style: style, 'data-screen-row': screenRow, dangerouslySetInnerHTML: {__html: innerHTML}
buildLineInnerHTML: (line) ->
if line.text is ""
@buildEmptyLineInnerHTML(line)
else
@buildNonEmptyLineInnerHTML(line)
buildEmptyLineInnerHTML: (line) ->
{showIndentGuide} = @props
{indentLevel, tabLength} = line
if showIndentGuide and indentLevel > 0
indentSpan = "<span class='indent-guide'>#{multiplyString(' ', tabLength)}</span>"
multiplyString(indentSpan, indentLevel + 1)
else
"&nbsp;"
buildNonEmptyLineInnerHTML: (line) ->
{invisibles, mini, showIndentGuide, invisibles} = @props
{tokens, text} = line
innerHTML = ""
scopeStack = []
firstTrailingWhitespacePosition = text.search(/\s*$/)
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
for token in tokens
innerHTML += @updateScopeStack(scopeStack, token.scopes)
hasIndentGuide = not mini and showIndentGuide and token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly)
innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide})
innerHTML += @popScope(scopeStack) while scopeStack.length > 0
innerHTML += @buildEndOfLineHTML(line)
innerHTML
buildEndOfLineHTML: (line) ->
{invisibles, mini} = @props
return '' if mini or line.isSoftWrapped()
html = ''
if invisibles.cr? and line.lineEnding is '\r\n'
html += "<span class='invisible-character'>#{invisibles.cr}</span>"
if invisibles.eol?
html += "<span class='invisible-character'>#{invisibles.eol}</span>"
html
updateScopeStack: (scopeStack, desiredScopes) ->
html = ""
# Find a common prefix
for scope, i in desiredScopes
break unless scopeStack[i]?.scope is desiredScopes[i]
# Pop scopes until we're at the common prefx
until scopeStack.length is i
html += @popScope(scopeStack)
# Push onto common prefix until scopeStack equals desiredScopes
for j in [i...desiredScopes.length]
html += @pushScope(scopeStack, desiredScopes[j])
html
popScope: (scopeStack) ->
scopeStack.pop()
"</span>"
pushScope: (scopeStack, scope) ->
scopeStack.push(scope)
"<span class=\"#{scope.replace(/\.+/g, ' ')}\">"
componentWillMount: ->
@measuredLines = new WeakSet
@lineInnerHTMLByLineId = {}
componentDidMount: ->
@measureLineHeightAndCharWidth()
@measureLineHeightInPixelsAndCharWidth()
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props, 'renderedRowRange', 'fontSize', 'fontFamily', 'lineHeight', 'showIndentGuide')
return true if newProps.selectionChanged
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'fontSize', 'fontFamily', 'lineHeight', 'lineHeightInPixels',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles',
'visible', 'scrollViewHeight', 'mouseWheelScreenRow'
)
{renderedRowRange, pendingChanges} = newProps
for change in pendingChanges
@@ -36,20 +144,44 @@ LinesComponent = React.createClass
false
componentWillUpdate: (newProps) ->
unless isEqualForProperties(newProps, @props, 'invisibles', 'showIndentGuide')
@lineInnerHTMLByLineId = {}
componentDidUpdate: (prevProps) ->
@measureLineHeightAndCharWidth() unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily', 'lineHeight')
@measureLineHeightInPixelsAndCharWidthIfNeeded(prevProps)
@clearScopedCharWidths() unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily')
@measureCharactersInNewLines() unless @props.scrollingVertically
measureLineHeightAndCharWidth: ->
lineNodeForScreenRow: (screenRow) ->
{renderedRowRange} = @props
[startRow, endRow] = renderedRowRange
unless startRow <= screenRow < endRow
throw new Error("Requested screenRow #{screenRow} is not currently rendered")
@getDOMNode().children[screenRow - startRow]
measureLineHeightInPixelsAndCharWidthIfNeeded: (prevProps) ->
{visible} = @props
unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily', 'lineHeight')
if visible
@measureLineHeightInPixelsAndCharWidth()
else
@measureWhenShown = true
@measureLineHeightInPixelsAndCharWidth() if visible and not prevProps.visible and @measureWhenShown
measureLineHeightInPixelsAndCharWidth: ->
@measureWhenShown = false
node = @getDOMNode()
node.appendChild(DummyLineNode)
lineHeight = DummyLineNode.getBoundingClientRect().height
lineHeightInPixels = DummyLineNode.getBoundingClientRect().height
charWidth = DummyLineNode.firstChild.getBoundingClientRect().width
node.removeChild(DummyLineNode)
{editor} = @props
editor.setLineHeight(lineHeight)
editor.setLineHeightInPixels(lineHeightInPixels)
editor.setDefaultCharWidth(charWidth)
measureCharactersInNewLines: ->
@@ -97,44 +229,3 @@ LinesComponent = React.createClass
clearScopedCharWidths: ->
@measuredLines.clear()
@props.editor.clearScopedCharWidths()
LineComponent = React.createClass
displayName: 'LineComponent'
render: ->
{screenRow, lineHeight} = @props
style =
top: screenRow * lineHeight
position: 'absolute'
div className: 'line', style: style, 'data-screen-row': screenRow, dangerouslySetInnerHTML: {__html: @buildInnerHTML()}
buildInnerHTML: ->
if @props.tokenizedLine.text.length is 0
@buildEmptyLineHTML()
else
@buildScopeTreeHTML(@props.tokenizedLine.getScopeTree())
buildEmptyLineHTML: ->
{showIndentGuide, tokenizedLine} = @props
{indentLevel, tabLength} = tokenizedLine
if showIndentGuide and indentLevel > 0
indentSpan = "<span class='indent-guide'>#{multiplyString(' ', tabLength)}</span>"
multiplyString(indentSpan, indentLevel + 1)
else
"&nbsp;"
buildScopeTreeHTML: (scopeTree) ->
if scopeTree.children?
html = "<span class='#{scopeTree.scope.replace(/\./g, ' ')}'>"
html += @buildScopeTreeHTML(child) for child in scopeTree.children
html += "</span>"
html
else
"<span>#{scopeTree.getValueAsHtml({hasIndentGuide: @props.showIndentGuide})}</span>"
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(newProps, @props, 'showIndentGuide', 'lineHeight', 'screenRow')
+8 -3
Ver Arquivo
@@ -58,7 +58,7 @@ class MenuManager
testBody = document.createElement('body')
testBody.classList.add(@classesForElement(document.body)...)
testWorkspace = document.createElement('body')
testWorkspace = document.createElement('div')
workspaceClasses = @classesForElement(document.body.querySelector('.workspace'))
workspaceClasses = ['workspace'] if workspaceClasses.length is 0
testWorkspace.classList.add(workspaceClasses...)
@@ -69,7 +69,12 @@ class MenuManager
@testEditor.classList.add('editor')
testWorkspace.appendChild(@testEditor)
@testEditor.webkitMatchesSelector(selector)
element = @testEditor
while element
return true if element.webkitMatchesSelector(selector)
element = element.parentElement
false
# Public: Refreshes the currently visible menu.
update: ->
@@ -112,7 +117,7 @@ class MenuManager
sendToBrowserProcess: (template, keystrokesByCommand) ->
keystrokesByCommand = @filterMultipleKeystroke(keystrokesByCommand)
ipc.sendChannel 'update-application-menu', template, keystrokesByCommand
ipc.send 'update-application-menu', template, keystrokesByCommand
normalizeLabel: (label) ->
return undefined unless label?
+9 -5
Ver Arquivo
@@ -27,10 +27,12 @@ module.exports =
class PackageManager
Emitter.includeInto(this)
constructor: ({configDirPath, devMode, @resourcePath}) ->
@packageDirPaths = [path.join(configDirPath, "packages")]
if devMode
@packageDirPaths.unshift(path.join(configDirPath, "dev", "packages"))
constructor: ({configDirPath, devMode, safeMode, @resourcePath}) ->
@packageDirPaths = []
unless safeMode
if devMode
@packageDirPaths.push(path.join(configDirPath, "dev", "packages"))
@packageDirPaths.push(path.join(configDirPath, "packages"))
@loadedPackages = {}
@activePackages = {}
@@ -41,7 +43,9 @@ class PackageManager
# Public: Get the path to the apm command
getApmPath: ->
@apmPath ?= path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm')
commandName = 'apm'
commandName += '.cmd' if process.platform is 'win32'
@apmPath ?= path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', commandName)
# Public: Get the paths being used to look for packages.
#
+3 -3
Ver Arquivo
@@ -10,7 +10,7 @@ Pane = require './pane'
# Items can be almost anything however most commonly they're {EditorView}s.
#
# Most packages won't need to use this class, unless you're interested in
# building a package that deals with switching between panes or tiems.
# building a package that deals with switching between panes or items.
module.exports =
class PaneView extends View
Delegator.includeInto(this)
@@ -103,7 +103,7 @@ class PaneView extends View
# Deprecated: Use ::activateNextItem
showNextItem: ->
deprecate("Use PaneView::destroyItem instead")
deprecate("Use PaneView::activateNextItem instead")
@activateNextItem()
# Deprecated: Use ::activatePreviousItem
@@ -149,7 +149,7 @@ class PaneView extends View
hasFocus = @hasFocus()
item.on? 'title-changed', @activeItemTitleChanged
view = @viewForItem(item)
@itemViews.children().not(view).hide()
otherView.hide() for otherView in @itemViews.children().not(view).views()
@itemViews.append(view) unless view.parent().is(@itemViews)
view.show() if @attached
view.focus() if hasFocus
+13 -5
Ver Arquivo
@@ -339,18 +339,26 @@ class Pane extends Model
newPane.activate()
newPane
# If the parent is a horizontal axis, returns its first child;
# otherwise this pane.
# If the parent is a horizontal axis, returns its first child if it is a pane;
# otherwise returns this pane.
findLeftmostSibling: ->
if @parent.orientation is 'horizontal'
@parent.children[0]
[leftmostSibling] = @parent.children
if leftmostSibling instanceof PaneAxis
this
else
leftmostSibling
else
this
# If the parent is a horizontal axis, returns its last child;
# If the parent is a horizontal axis, returns its last child if it is a pane;
# otherwise returns a new pane created by splitting this pane rightward.
findOrCreateRightmostSibling: ->
if @parent.orientation is 'horizontal'
last(@parent.children)
rightmostSibling = last(@parent.children)
if rightmostSibling instanceof PaneAxis
@splitRight()
else
rightmostSibling
else
@splitRight()
+1 -2
Ver Arquivo
@@ -165,9 +165,8 @@ class Project extends Model
bufferForId: (id) ->
_.find @buffers, (buffer) -> buffer.id is id
# DEPRECATED
# Still needed when deserializing a tokenized buffer
buildBufferSync: (absoluteFilePath) ->
deprecate("Use Project::buildBuffer instead")
buffer = new TextBuffer({filePath: absoluteFilePath})
@addBuffer(buffer)
buffer.loadSync()
+17 -6
Ver Arquivo
@@ -1,6 +1,7 @@
{View, $} = require 'space-pen'
React = require 'react'
React = require 'react-atom-fork'
EditorComponent = require './editor-component'
{defaults} = require 'underscore-plus'
module.exports =
class ReactEditorView extends View
@@ -8,12 +9,12 @@ class ReactEditorView extends View
focusOnAttach: false
constructor: (@editor) ->
constructor: (@editor, @props) ->
super
getEditor: -> @editor
Object.defineProperty @::, 'lineHeight', get: -> @editor.getLineHeight()
Object.defineProperty @::, 'lineHeight', get: -> @editor.getLineHeightInPixels()
Object.defineProperty @::, 'charWidth', get: -> @editor.getDefaultCharWidth()
scrollTop: (scrollTop) ->
@@ -37,11 +38,12 @@ class ReactEditorView extends View
afterAttach: (onDom) ->
return unless onDom
@attached = true
@component = React.renderComponent(EditorComponent({@editor, parentView: this}), @element)
props = defaults({@editor, parentView: this}, @props)
@component = React.renderComponent(EditorComponent(props), @element)
node = @component.getDOMNode()
@underlayer = $(node).find('.underlayer')
@underlayer = $(node).find('.selections')
@gutter = $(node).find('.gutter')
@gutter.removeClassFromAllLines = (klass) =>
@@ -64,7 +66,8 @@ class ReactEditorView extends View
appendToLinesView: (view) ->
view.css('position', 'absolute')
@find('.scroll-view-content').prepend(view)
view.css('z-index', 1)
@find('.lines').prepend(view)
beforeRemove: ->
React.unmountComponentAtNode(@element)
@@ -79,3 +82,11 @@ class ReactEditorView extends View
@component.onFocus()
else
@focusOnAttach = true
hide: ->
super
@component.hide()
show: ->
super
@component.show()
+23 -8
Ver Arquivo
@@ -1,13 +1,26 @@
React = require 'react'
{div} = require 'reactionary'
{isEqualForProperties} = require 'underscore-plus'
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{extend, isEqualForProperties} = require 'underscore-plus'
module.exports =
ScrollbarComponent = React.createClass
render: ->
{orientation, className, scrollHeight, scrollWidth} = @props
displayName: 'ScrollbarComponent'
div {className, @onScroll},
render: ->
{orientation, className, scrollHeight, scrollWidth, visible} = @props
{scrollableInOppositeDirection, horizontalScrollbarHeight, verticalScrollbarWidth} = @props
style = {}
style.display = 'none' unless visible
switch orientation
when 'vertical'
style.width = verticalScrollbarWidth
style.bottom = horizontalScrollbarHeight if scrollableInOppositeDirection
when 'horizontal'
style.height = horizontalScrollbarHeight
style.right = verticalScrollbarWidth if scrollableInOppositeDirection
div {className, style, @onScroll},
switch orientation
when 'vertical'
div className: 'scrollbar-content', style: {height: scrollHeight}
@@ -21,11 +34,13 @@ ScrollbarComponent = React.createClass
throw new Error("Must specify an orientation property of 'vertical' or 'horizontal'")
shouldComponentUpdate: (newProps) ->
return true if newProps.visible isnt @props.visible
switch @props.orientation
when 'vertical'
not isEqualForProperties(newProps, @props, 'scrollHeight', 'scrollTop')
not isEqualForProperties(newProps, @props, 'scrollHeight', 'scrollTop', 'scrollableInOppositeDirection')
when 'horizontal'
not isEqualForProperties(newProps, @props, 'scrollWidth', 'scrollLeft')
not isEqualForProperties(newProps, @props, 'scrollWidth', 'scrollLeft', 'scrollableInOppositeDirection')
componentDidUpdate: ->
{orientation, scrollTop, scrollLeft} = @props
+20
Ver Arquivo
@@ -0,0 +1,20 @@
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
module.exports =
ScrollbarCornerComponent = React.createClass
displayName: 'ScrollbarCornerComponent'
render: ->
{visible, measuringScrollbars, width, height} = @props
if measuringScrollbars
height = 25
width = 25
display = 'none' unless visible
div className: 'scrollbar-corner', style: {display, width, height},
div style:
height: height + 1
width: width + 1

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais