Comparar commits

...

372 Commits

Autor SHA1 Mensagem Data
Kevin Sawicki 371e25af69 Disable deprecations unless in dev/spec mode
These are currently adding ~200ms to startup so temporarily disable
until the grim performance is improved and/or core and bundled packages
are updated to not call deprecated APIs.
2014-09-24 10:24:27 -07:00
Nathan Sobo 7fdffdd201 Upgrade atom-keymap 2014-09-24 11:04:56 -06:00
Kevin Sawicki 475fd07790 Resolve buildDir before it is used in other join calls 2014-09-24 09:48:56 -07:00
Kevin Sawicki 9e99cf03ea Upgrade to bracket-matcher@0.59 2014-09-24 09:18:58 -07:00
Kevin Sawicki b2c74ac249 Upgrade to apm 0.97 2014-09-23 17:24:51 -07:00
Kevin Sawicki daa2c77321 Merge pull request #3610 from postcasio/master
Don't override antialiasing in markdown
2014-09-23 17:07:37 -07:00
Kevin Sawicki 3f15338cad Upgrade to language-todo@0.12 2014-09-23 15:47:22 -07:00
Kevin Sawicki 00f67122c4 📝 Mark atom.commands experimental
The CommandRegistry class is still experimental and 404-ing in the
API docs on atom.io
2014-09-23 14:19:10 -07:00
Kevin Sawicki df3f884ada Resolve build and install directory paths
Closes #3600
2014-09-23 13:09:22 -07:00
Kevin Sawicki 85bf163f76 Merge pull request #3599 from atom/ks-remove-lintian-errors
Remove lintian errors
2014-09-23 12:59:35 -07:00
Kevin Sawicki c6d6fb3b7a Add libc6 to Depends section 2014-09-23 12:19:54 -07:00
Kevin Sawicki 26f3bde0e6 Add more lintian overrides 2014-09-23 12:19:54 -07:00
Kevin Sawicki 97b742cb1d Add initial lintian overrides 2014-09-23 12:19:54 -07:00
Kevin Sawicki 4c3ac8e6ec Add python dependency 2014-09-23 12:19:54 -07:00
Kevin Sawicki 0be03c8d9c Copy LICENSE.md to /usr/share/doc/atom/copyright 2014-09-23 12:19:54 -07:00
Kevin Sawicki 0bdddc955f Remove executable bit from .node files 2014-09-23 12:19:54 -07:00
Kevin Sawicki ad9b5e5b8d Add extended description 2014-09-23 12:19:54 -07:00
Kevin Sawicki c178ac3aa6 Run dpkg-deb using fakeroot 2014-09-23 12:19:54 -07:00
Kevin Sawicki 6b23479c3f Use FILE_MODE variable 2014-09-23 12:19:54 -07:00
Kevin Sawicki c4e3b76070 Quote deleted directory 2014-09-23 12:19:53 -07:00
Nathan Sobo 3dbaa0679b Merge pull request #3587 from atom/ns-workspace-view-providers
Add view provider API to Workspace
2014-09-23 13:08:00 -06:00
Nathan Sobo 366714aa3d Upgrade atom-keymap for dvorak-qwerty fix 2014-09-23 13:00:53 -06:00
Nathan Sobo 1077a59450 Upgrade snippets to support multiple cursors 2014-09-23 12:38:47 -06:00
Ben Ogle 3bc115a7a0 Merge pull request #3606 from atom/bo-model-placeholder-text
Model EditorView::setPlaceholderText
2014-09-23 11:20:23 -07:00
Kevin Sawicki 71b3ab3ae6 Prepare 0.131 2014-09-23 10:51:23 -07:00
Ben Ogle 169a5de6a3 not.toBeDefined -> toBeUndefined 2014-09-23 10:38:38 -07:00
Kevin Sawicki 90ff3f585d Always pass specs on Windows CI 2014-09-23 10:03:14 -07:00
Kevin Sawicki 2a7b73898e Upgrade to bracket-matcher@0.58 2014-09-23 09:08:26 -07:00
Kevin Sawicki 7375b32fb3 Upgrade to bracket-matcher@0.57 2014-09-23 08:51:34 -07:00
postcasio a615c3e081 Don't override antialiasing in markdown 2014-09-23 15:35:54 +01:00
Ben Ogle d4f7e710f4 Reorder properties by usage 2014-09-22 17:28:20 -07:00
Ben Ogle 4606ce2d50 Model setPlaceholderText
Less dependence on the editorView!
2014-09-22 17:21:42 -07:00
Kevin Sawicki 32143cfbdb Upgrade to symbols-view@0.66 2014-09-22 16:58:25 -07:00
Ben Ogle 2e4fda323e Merge pull request #3605 from atom/bo-fix-cursor-events
Make cursor / selection events consistent
2014-09-22 16:44:42 -07:00
Ben Ogle 021208d933 Update Cursor::onDidChangePosition doc string 2014-09-22 16:12:51 -07:00
Ben Ogle 688b209000 Update doc string in Selection::onDidChangeRange 2014-09-22 16:12:19 -07:00
Ben Ogle 91a443e7cb Update onDidChangeSelectionRange doc string 2014-09-22 16:09:32 -07:00
Ben Ogle c62fb26001 onDidChangeSelectionRange emits object with ranges + selection 2014-09-22 16:08:12 -07:00
Ben Ogle 3134364362 Add cursor to the docs 2014-09-22 15:50:47 -07:00
Ben Ogle e5c03e139a Only pass event to the editor 2014-09-22 15:50:40 -07:00
Ben Ogle 5083c18c84 Add cursor to onDidChangeCursorPosition event object 2014-09-22 15:37:41 -07:00
Kevin Sawicki 4260eaa329 Merge pull request #3585 from deiga/patch-1
Add matching of Atom.app more stable
2014-09-22 15:06:50 -07:00
Kevin Sawicki dc3a3225b3 Remove logging from specs 2014-09-22 15:00:06 -07:00
Kevin Sawicki 95087b8996 Git -> GitRepository 2014-09-22 14:54:01 -07:00
Kevin Sawicki a06fba75b8 Upgrade to bracket-matcher@0.56 2014-09-22 14:50:25 -07:00
Ben Ogle d727e440aa Merge pull request #3601 from atom/bo-rename-git
Rename Git -> GitRepository
2014-09-22 13:43:04 -07:00
Ben Ogle 6e8cfba440 nof 2014-09-22 11:07:53 -07:00
Ben Ogle 7a429b024e Use GitRepository rather than Git 2014-09-22 11:07:41 -07:00
Ben Ogle 84425f238a Rename git -> git-repository 2014-09-22 11:07:19 -07:00
Ben Ogle c62b7cc710 Deprecate requiring Git 2014-09-22 11:01:14 -07:00
Kevin Sawicki 39d3724860 Handle error events in spawned processes
Refs #3600
2014-09-22 10:57:42 -07:00
Kevin Sawicki 9eed8a206a Upgrade to first-mate@2.1.2 2014-09-22 10:47:56 -07:00
Kevin Sawicki ec0bcd90a6 Upload correct verison of .deb file 2014-09-22 10:38:56 -07:00
Kevin Sawicki 08871989e2 Correct process arch value 2014-09-22 10:35:52 -07:00
Kevin Sawicki c94b03f13d Run mkdeb task right before publishing 2014-09-22 10:33:29 -07:00
Kevin Sawicki 481653ff60 🍎 Insert newline with alt-enter and shift-enter
Closes #3588
2014-09-22 10:26:24 -07:00
Nathan Sobo ddb85abe77 Don’t add the same editor to two different panes in spec 2014-09-19 16:30:37 -06:00
Nathan Sobo 55cce48af1 Throw an exception if the same pane item is added twice in the workspace 2014-09-19 16:24:13 -06:00
Nathan Sobo d3239473b3 📝 Document Workspace::addViewProvider 2014-09-19 16:24:13 -06:00
Nathan Sobo fa103d42d0 Delegate Workspace::addViewProvider to its ::viewRegistry 2014-09-19 16:24:13 -06:00
Nathan Sobo ecbf2b708c Make ::getView essential because otherwise the section is empty 2014-09-19 16:24:13 -06:00
Nathan Sobo d344adc21e Allow view providers to specify a createView factory method
If present, it will be called with the model object instead of
instantiating the view constructor directly and assigning a model on it.
This gives users more flexibility when constructing views.
2014-09-19 16:24:13 -06:00
Nathan Sobo 74d772f069 Rename view/modelClass to view/modelConstructor in view provider specs
It’s a more technically correct term. You use a class keyword to declare
these things, but the actual objects you pass around to talk about them
are constructor functions.
2014-09-19 16:24:13 -06:00
Nathan Sobo e2e804483f Return disposable from ViewRegistry::addViewProvider 2014-09-19 16:24:13 -06:00
Nathan Sobo e084e13ea3 📝 Document Workspace::getView 2014-09-19 16:24:13 -06:00
Nathan Sobo b5499247b3 Use view providers to build views if a matching provider is available 2014-09-19 16:24:13 -06:00
Nathan Sobo 54378b11d4 Isolate ViewRegistry specs 2014-09-19 16:24:12 -06:00
Nathan Sobo 21802ddb7c Upgrade background-tips to fix spec failure 2014-09-19 16:24:12 -06:00
Nathan Sobo 20e08323c1 Use the ViewRegistry to construct pane item views 2014-09-19 16:24:12 -06:00
Nathan Sobo 0877721ce9 Construct PaneAxisViews and PaneViews via ViewRegistry 2014-09-19 16:24:12 -06:00
Nathan Sobo 2b86297a0b Extract a ViewRegistry that can be shared amongst Workspace objects 2014-09-19 16:24:12 -06:00
Nathan Sobo 53bd1c8958 Use Workspace::getView to build PaneContainerView 2014-09-19 16:24:12 -06:00
Nathan Sobo 7f41be3103 Use atom.workspace.getView to construct WorkspaceViews
It returns the root DOM node of the workspace. Eventually this will
be a custom element but for now it’s just a DOM node with a
__spacePenView reference on it.
2014-09-19 16:24:12 -06:00
Nathan Sobo 7baa3b6f09 Start on Workspace::getView 2014-09-19 16:24:12 -06:00
Nathan Sobo bac99222f3 Force scrollbars to be GPU layers when acceleration is enabled
Fixes #3559

For some reason, Chromium 37 is not compositing scrollbars correctly on
secondary monitors in OS X. They’re invisible when the lines layer
extends beneath the scrollbars unless we apply this style.
2014-09-19 15:10:04 -06:00
Kevin Sawicki d6842dc8a2 Upgrade to language-xml@0.21 2014-09-19 09:56:11 -07:00
Kevin Sawicki 8b651328d2 Upgrade to settings-view@0.145 2014-09-19 09:45:25 -07:00
Kevin Sawicki 17838f832d 📝 Add installing on debian steps 2014-09-19 09:36:30 -07:00
Kevin Sawicki 9e686c11e4 Upgrade to apm 0.96 2014-09-19 09:29:45 -07:00
Timo Sand 8932eba0bf Add matching of Atom.app more stable
I have this file on my Mac `/Users/timosand/Library/Application Support/com.github.atom.ShipIt/update.85PyXs3/Atom.app` and my `mdfind` returns it. It seems to be a common one, so I thought to remove it from the list to be sure that it selects the right Atom.app
2014-09-19 07:48:21 +03:00
Ben Ogle 5cc62b2429 Merge pull request #3583 from atom/bo-final-docs-pass
Final docs pass
2014-09-18 18:45:18 -07:00
Ben Ogle e5096d8190 Data -> Details 2014-09-18 18:40:46 -07:00
Ben Ogle 2af699f35e Rename cursor sections 2014-09-18 17:27:08 -07:00
Kevin Sawicki b1f48338cd Upgrade to apm 0.95 2014-09-18 17:26:46 -07:00
Ben Ogle 7632e5dd40 Reorg decoration 2014-09-18 17:24:24 -07:00
Ben Ogle 9f1aabed0a Reorg Editor a bit based on conversations
Move heavier used sections near the top of the file. Make some of the
single extended methods public.
2014-09-18 17:20:18 -07:00
Ben Ogle 33827d1dc8 Upgrade text-buffer for better docs 2014-09-18 16:59:06 -07:00
Ben Ogle 29f53d4432 PaneView is private 2014-09-18 16:52:56 -07:00
Ben Ogle f407ca3a0c saveAll is private 2014-09-18 16:52:11 -07:00
Ben Ogle 2d3ea244ee Opener stuff is essential 2014-09-18 16:51:59 -07:00
Ben Ogle 97931ff259 Move observePaneItems and onDidChangePaneItem to essential 2014-09-18 16:51:30 -07:00
Ben Ogle d02c3e0d62 WorkspaceView is extended 2014-09-18 16:45:13 -07:00
Ben Ogle e2d9e5bd74 Make focusing other pane views from workspaceView private 2014-09-18 16:44:49 -07:00
Kevin Sawicki 0b03c89010 Upgrade to settings-view@0.144 2014-09-18 16:43:47 -07:00
Ben Ogle 69f54b90dc Clean up atom details section 2014-09-18 16:43:13 -07:00
Ben Ogle 7c483f989f Clean up marker 2014-09-18 16:43:00 -07:00
Kevin Sawicki c89bafb66e Refresh horizontal scrollbar DOM node
Previously the vertical scrollbar's DOM node was used as the
horizontal node causing the horizontal scrollbar to not refresh
properly

Closes #3511
2014-09-18 16:26:40 -07:00
Kevin Sawicki ee093d1709 Merge pull request #3582 from atom/ks-dont-allow-focused-specs-on-ci
Fail focused specs on CI
2014-09-18 16:16:17 -07:00
Ben Ogle 155d4ce733 Merge pull request #3569 from atom/bo-proper-doc-marker
Rename DisplayBufferMarker to Marker
2014-09-18 16:14:35 -07:00
Kevin Sawicki 021278e902 Always auto indent at least one hard tab
Previously when the delta between the suggested and current indent level
was greater than zero but less than one, no text would be inserted since
Editor::buildIndentString returns an empty string for levels less than one
when using hard tabs.

Closes #3575
2014-09-18 15:36:31 -07:00
Kevin Sawicki 597942c4ac Fail focused specs on CI
This ensures focused specs never end up as green builds
2014-09-18 15:18:42 -07:00
Kevin Sawicki 7f3279e789 Unfocus spec 2014-09-18 14:50:36 -07:00
Ben Ogle 325cc95f48 Fix specs 2014-09-18 13:53:13 -07:00
Ben Ogle 068c2c359f displayBufferMarker -> marker 2014-09-18 13:53:13 -07:00
Ben Ogle 39343b0c52 Fix reference to display-buffer-marker 2014-09-18 13:53:13 -07:00
Ben Ogle 6121147fc1 Upgrade text-buffer to have a private marker 2014-09-18 13:53:12 -07:00
Ben Ogle 65b41fa502 Move buffer-display-marker -> marker 2014-09-18 13:53:12 -07:00
Ben Ogle 9af2325f17 Rename DisplayBufferMarker -> Marker
Gnar!! 😎
2014-09-18 13:53:12 -07:00
Ben Ogle fb7b9041ab Shore up the docs around marker creation and invalidation 2014-09-18 13:53:12 -07:00
Ben Ogle bf44cf89db DisplayBufferMarker::matchesAttributes -> ::matchesProperties 2014-09-18 13:53:12 -07:00
Ben Ogle cef8b95ef3 Deprecate s|getAttributes for s|getProperties 2014-09-18 13:53:12 -07:00
Ben Ogle bd19899dd8 Add DisplayBufferMarker::getInvalidationStrategy 2014-09-18 13:53:12 -07:00
Ben Ogle e3ce6f8a20 Organize DisplayBufferMarker into sections. Add docs from Marker 2014-09-18 13:53:12 -07:00
Kevin Sawicki a88299284e Upgrade to language-ruby@0.38 2014-09-18 13:51:34 -07:00
Kevin Sawicki 0bf0829e77 Upgrade to settings-view@0.143 2014-09-18 13:40:16 -07:00
Kevin Sawicki 46adbea0c2 Merge pull request #3567 from atom/ks-deprecate-custom-dom-events
Deprecate custom DOM events
2014-09-18 13:30:59 -07:00
Kevin Sawicki 62a5c1c58d Don't dispose emitter, specs fail 2014-09-18 11:51:45 -07:00
Kevin Sawicki c291c705ec Add missing support to deprecation message 2014-09-18 11:51:45 -07:00
Kevin Sawicki 95253758f3 Dispose emitter after emitting did-destroy 2014-09-18 11:51:45 -07:00
Kevin Sawicki 1a24c79c7f Deprecate beep event 2014-09-18 11:51:45 -07:00
Kevin Sawicki 522a66c876 📝 Wrap ::onDidAddPaneItem in {} 2014-09-18 11:51:45 -07:00
Kevin Sawicki 67610829f4 Add Atom::onDidBeep 2014-09-18 11:51:44 -07:00
Kevin Sawicki fe30cf2135 Deprecate editor:detached 2014-09-18 11:51:44 -07:00
Kevin Sawicki 280a3c30e6 Deprecate editor:attached 2014-09-18 11:51:44 -07:00
Kevin Sawicki 0b82e83806 Move deprecatedViewEvents to deprecated section 2014-09-18 11:51:44 -07:00
Kevin Sawicki 6d2719c783 Deprecate editor:will-be-removed 2014-09-18 11:51:44 -07:00
Kevin Sawicki 31dd109343 Add Editor::onDidDestroy 2014-09-18 11:51:44 -07:00
Kevin Sawicki a5b7764b38 Deprecate pane:attached 2014-09-18 11:51:44 -07:00
Kevin Sawicki ddc88ec3ed Deprecate when pane:active-item-modified-status-changed 2014-09-18 11:51:44 -07:00
Kevin Sawicki 088d4f439f Deprecate pane:active-item-title-changed on PaneView 2014-09-18 11:51:44 -07:00
Kevin Sawicki b1994b28b3 Deprecate pane:active-item-title-changed 2014-09-18 11:51:44 -07:00
Kevin Sawicki cf303a73b7 Deprecate custom events on PaneView 2014-09-18 11:51:44 -07:00
Kevin Sawicki 1b25ea8a8d Deprecate custom events on EditorView 2014-09-18 11:51:44 -07:00
Kevin Sawicki 291b989ff0 Deprecate pane:item-moved 2014-09-18 11:51:43 -07:00
Kevin Sawicki 1850197f55 Deprecate pane:item-removed 2014-09-18 11:51:43 -07:00
Kevin Sawicki c2c0962e3b Deprecate pane:item-added 2014-09-18 11:51:43 -07:00
Kevin Sawicki 099953c58b Deprecate uri-opened 2014-09-18 11:51:43 -07:00
Kevin Sawicki 33fdb0b518 Deprecate pane:became-inactive 2014-09-18 11:51:43 -07:00
Kevin Sawicki 5148deded1 Deprecate pane:became-active 2014-09-18 11:51:43 -07:00
Kevin Sawicki fdddccf094 💄 2014-09-18 11:51:43 -07:00
Kevin Sawicki 4521eeaeb1 Deprecate pane:active-item-changed 2014-09-18 11:51:43 -07:00
Kevin Sawicki 7344ba644e Deprecate pane-container:active-pane-item-changed 2014-09-18 11:51:43 -07:00
Kevin Sawicki ce887fe877 Deprecate selection:changed 2014-09-18 11:51:43 -07:00
Kevin Sawicki ee701f3b8b Deprecate cursor:moved 2014-09-18 11:51:43 -07:00
Kevin Sawicki c5f593cf08 deprecatedViewEvents -> setupViewEventDeprecations 2014-09-18 11:51:43 -07:00
Kevin Sawicki 4b4dc7224e Deprecate pane:removed event 2014-09-18 11:51:42 -07:00
Kevin Sawicki 31dd9bed6a Map over cmdArgs when quoting 2014-09-18 11:37:37 -07:00
Kevin Sawicki 44860ba572 Filter null/undefined arguments on Windows
These won't be able to be properly quoted
2014-09-18 11:36:41 -07:00
Kevin Sawicki c37e4649b5 Only call replace on string arguments
Prevents errors being thrown when trying to call replace on non-string
arguments.
2014-09-18 11:31:29 -07:00
Kevin Sawicki 3fb22f123a Don't throw errors when folding comments
Previously trying to fold single line comments at the start/end
of files would throw errors since the +1 and -1 used in the
index ranges would cause the loop to advance past the last row
or before the first row.
2014-09-18 11:06:25 -07:00
Kevin Sawicki 616dae2f22 Upgrade to tree-view@0.126 2014-09-18 10:33:08 -07:00
Kevin Sawicki e300677da0 Upgrade to less-cache@0.15 2014-09-18 10:03:33 -07:00
Kevin Sawicki ca9d05f6fa Remove notification stylesheet
These were currently undocumented in the styleguide, had hard-coded colors,
weren't being styled by the default light/dark UI themes, and were unused.

They were also causing conflicts with the notification token scope that
the Objective-C grammar uses.
2014-09-18 09:26:46 -07:00
Kevin Sawicki ba49f5d0b8 Upgrade to symbols-view@0.65 2014-09-18 09:22:56 -07:00
Kevin Sawicki 5d22f96f7b Upgrade to language-coffee-script@0.34 2014-09-18 08:52:19 -07:00
Kevin Sawicki afd6f6144c Upgrade to symbols-view@0.64 2014-09-17 18:16:09 -07:00
Kevin Sawicki 14b3bd5b39 Upgrade to language-coffee-script@0.33 2014-09-17 17:03:33 -07:00
Ben Ogle 7bf60a09dd Make ScrollView Extended 2014-09-17 17:02:41 -07:00
Ben Ogle 8448b265d5 Merge pull request #3549 from atom/bo-visibility-split
Add sections and split methods into essential / extended API
2014-09-17 16:51:50 -07:00
Ben Ogle a85a5e8495 Add public back for the deserializers 2014-09-17 16:20:08 -07:00
Ben Ogle 736342b527 Fix the title duplication 2014-09-17 15:59:22 -07:00
Ben Ogle fad83fff1c Change name of section in cursor 2014-09-17 15:57:24 -07:00
Ben Ogle 6f2b1a4b21 Reorganize Selection into sections 2014-09-17 15:57:13 -07:00
Ben Ogle 37ddf096a7 Reorganize ThemeManager into sections 2014-09-17 15:39:16 -07:00
Kevin Sawicki 27584cf069 Upgrade to grammar-selector@0.34 2014-09-17 15:20:31 -07:00
Kevin Sawicki 12181bcb02 Upgrade to language-coffee-script@0.32 2014-09-17 14:44:26 -07:00
Ben Ogle 0963077a32 Reorganize Project class into sections 2014-09-17 14:26:15 -07:00
Kevin Sawicki a476bb220a Upgrade to language-coffee-script@0.31 2014-09-17 14:26:12 -07:00
Ben Ogle cfffae936c Deprecate pathForRepositoryUrl for eventual removal 2014-09-17 14:23:46 -07:00
Nathan Sobo aa8bfd8e5f Remove stray console.log 2014-09-17 15:03:04 -06:00
Nathan Sobo d36c738b07 Merge pull request #3469 from atom/ns-command-registry
Add command registry
2014-09-17 14:55:19 -06:00
Kevin Sawicki bfdb5bd150 Upgrade to tabs@0.52 2014-09-17 13:52:21 -07:00
Kevin Sawicki 8b34f85f34 Upgrade to grammar-selector@0.33 2014-09-17 13:45:55 -07:00
Kevin Sawicki ad17b2d1c3 Upgrade to apm 0.94 2014-09-17 11:29:24 -07:00
Kevin Sawicki e4d50f4b38 Merge pull request #3565 from atom/ks-support-variation-sequences
Support variation sequences
2014-09-17 10:58:43 -07:00
Kevin Sawicki 146e8c2a0b 💄 Remove extra newline 2014-09-17 10:40:12 -07:00
Kevin Sawicki f1fd13b0b2 Return as soon as first paired character is found
Previously the character count of the entire string was taken even
though it was only checking for the presence of a paired character.

Now hasPairedCharacter returns as early as possible and the now
unused getCharacterCount has been removed.
2014-09-17 10:35:33 -07:00
Kevin Sawicki e343b0e0fc Don't treat consecutive variation selectors as a sequence 2014-09-17 10:17:27 -07:00
Kevin Sawicki c1aa5c9e48 📝 Mention variation sequence in comment 2014-09-17 10:17:27 -07:00
Kevin Sawicki 3acddf3e71 📝 Drop text 2014-09-17 10:17:26 -07:00
Kevin Sawicki df68ae26a2 Add specs for variation sequences 2014-09-17 10:17:26 -07:00
Kevin Sawicki fb7061f500 📝 Mention variation sequence in specs 2014-09-17 10:17:26 -07:00
Kevin Sawicki 878da262d2 Add support for Unicode variation sequences
These are character pairs that should be treated as tokens with a
buffer delta of 2 and a screen delta of 1.
2014-09-17 10:17:26 -07:00
Kevin Sawicki b6faffe2db Merge pull request #3555 from atom/ks-include-leading-trailing-classes-for-hard-tabs
Add leading/trailing whitespace classes to hard tab tokens
2014-09-17 10:15:34 -07:00
Kevin Sawicki 36f60c517e Assert other whitespace class is not present 2014-09-17 09:50:55 -07:00
Kevin Sawicki 348f865cab Add spec for all whitespace lines 2014-09-17 09:47:49 -07:00
Kevin Sawicki 18f54e6780 💄 Put leading spec first 2014-09-17 09:42:31 -07:00
Kevin Sawicki b281737838 Add leading/trailing classes to hard tab tokens
Previously the leading-whitespace and trailing-whitespace classes
were never added to tokens that were hard tabs.
2014-09-17 09:42:31 -07:00
Kevin Sawicki 72b92fc3e5 Only add command on platforms where it can be run
Closes #3561
2014-09-17 08:54:16 -07:00
Kevin Sawicki 03fcda8807 Upgrade to grammar-selector@0.32 2014-09-16 18:49:31 -07:00
Kevin Sawicki b6b7ce31a8 Upgrade to language-javascript@0.40 2014-09-16 18:10:32 -07:00
Ben Ogle 13cc97e44f Reorganize PackageManager into sections 2014-09-16 17:05:23 -07:00
Kevin Sawicki 3794cb606f Upgrade to grammar-selector@0.31 2014-09-16 16:56:36 -07:00
Kevin Sawicki 2dbaa52417 Upgrade to grammar-selector@0.30 2014-09-16 16:53:25 -07:00
Ben Ogle 6467f3c425 Reorganize cursor into sections 2014-09-16 16:50:17 -07:00
Kevin Sawicki ad288478d5 Upgrade to language-sql@0.11 2014-09-16 16:46:04 -07:00
Kevin Sawicki dd063c09d0 Upgrade to pathwatcher@2.1.3 2014-09-16 16:41:37 -07:00
Ben Ogle 5252b5314b WorkspaceView Public -> Essential 2014-09-16 16:30:46 -07:00
Ben Ogle 4c93045384 Reorganize WorkspaceView into sections 2014-09-16 16:30:13 -07:00
Ben Ogle fb1ac72b6e installShellCommands is not public 2014-09-16 16:23:30 -07:00
Kevin Sawicki 51aaffb2e5 Upgrade to status-bar@0.45 2014-09-16 16:22:07 -07:00
Ben Ogle 7ff5938454 Convert visibility in SelectListView 2014-09-16 16:18:47 -07:00
Ben Ogle 053d483b2b Rearrange SelectListView with sections 2014-09-16 16:06:37 -07:00
Ben Ogle b444fbd22c Git module is extended 2014-09-16 14:44:49 -07:00
Ben Ogle f1a5e8e1a8 Reorganize Git into sections 2014-09-16 14:41:23 -07:00
Kevin Sawicki 0098ac67ef Upgrade to markdown-preview@0.103 2014-09-16 14:23:38 -07:00
Ben Ogle cc64a2c3b4 Move things into the construction and destruction section 2014-09-16 14:10:49 -07:00
Ben Ogle b9a63d5030 Add bit about editorView being sparse 2014-09-16 14:07:04 -07:00
Kevin Sawicki c747ab411c Upgrade to tabs@0.51 2014-09-16 14:04:01 -07:00
Ben Ogle f80334d617 Task has better examples 2014-09-16 14:03:33 -07:00
Ben Ogle 679c52ffd1 Task is extended 2014-09-16 14:03:17 -07:00
Ben Ogle 1ee1eb3580 Syntax is extended 2014-09-16 13:43:56 -07:00
Ben Ogle 050ec6ca64 MenuManager is extended 2014-09-16 13:42:55 -07:00
Ben Ogle 69ba6e3e7e DeserializerManager is extended 2014-09-16 13:42:26 -07:00
Ben Ogle 6379f87b8a ContextMenuManager is Extended 2014-09-16 13:40:37 -07:00
Ben Ogle f3f4e8f7a3 Config is Essential 2014-09-16 13:39:43 -07:00
Ben Ogle dbca4f1b8c Clipboard is extended 2014-09-16 13:36:48 -07:00
Ben Ogle 1933488914 Buffered process classes are extended 2014-09-16 13:35:19 -07:00
Ben Ogle 6e7dae032d All dev tool methods are extended 2014-09-16 13:34:11 -07:00
Ben Ogle 88d0d291d4 Convert visibility in the messaging the user section 2014-09-16 13:31:53 -07:00
Ben Ogle 488b1819ae Convert visibility in the managing the window section 2014-09-16 13:31:18 -07:00
Ben Ogle b1df925d02 Convert visibility in metadata section 2014-09-16 13:30:47 -07:00
Ben Ogle dbf8094fdb Reorder the sections so public methods are closer to the top 2014-09-16 13:26:58 -07:00
Ben Ogle cf927e6405 Create Messaging the user + Deserializing sections 2014-09-16 13:23:09 -07:00
Ben Ogle 6a16a9b83f move Atom::open to the window management section 2014-09-16 13:22:21 -07:00
Ben Ogle ebb6ebca2a Move windowloadTime into metadata section 2014-09-16 13:21:35 -07:00
Ben Ogle 816bb9b38d Deserializers are private 2014-09-16 13:21:19 -07:00
Ben Ogle e260064df2 Add getLoadSettings to atom metadata section 2014-09-16 11:52:59 -07:00
Ben Ogle a3e4ccbb83 Create atom metadata section 2014-09-16 11:52:11 -07:00
Ben Ogle e84eba058a Move deprecated methods to the bottom of the file 2014-09-16 11:44:00 -07:00
Ben Ogle c25a04fd53 Move fullscreen stuff into the managing window section 2014-09-16 11:42:07 -07:00
Ben Ogle 9e68e47432 💄 2014-09-16 11:37:30 -07:00
Ben Ogle 53806d7d63 Managing the dev tool section 2014-09-16 11:37:21 -07:00
Ben Ogle c0dd53104a Make a managing the atom window section
de-public the get/setWindowDimensions in favor of 
the (get|set)(Size|Position)
2014-09-16 11:37:11 -07:00
Ben Ogle 39d7e12ebb Fix deprecation method calls 2014-09-16 11:35:14 -07:00
Ben Ogle 779619a4f2 Construction and destruction section 2014-09-16 10:58:36 -07:00
Ben Ogle b3ec8ed03f Make Atom::initialize private 2014-09-16 10:58:27 -07:00
Ben Ogle f84666943c Properties section 2014-09-16 10:58:08 -07:00
Ben Ogle 9eb51dfd0a Make Atom.loadOrCreate Private 2014-09-16 10:56:48 -07:00
Ben Ogle ac516102ca Atom is Essential 2014-09-16 10:56:26 -07:00
Ben Ogle 5b8e30580d Reorg Event Subscription section 2014-09-16 10:52:33 -07:00
Ben Ogle 44fd6cc335 Workspace is Essential 2014-09-16 10:51:34 -07:00
Ben Ogle e01d96862f Update docs in decoration 2014-09-16 10:51:34 -07:00
Ben Ogle d349ec55f9 Use new methods 2014-09-16 10:51:34 -07:00
Ben Ogle bbe69347ee Clean up the syntax scopes section 2014-09-16 10:51:34 -07:00
Ben Ogle 6270f2ff55 Add missing argument to docs 2014-09-16 10:51:33 -07:00
Ben Ogle 1ef2aa63d6 Clean up visibilities where I made an error 2014-09-16 10:51:33 -07:00
Ben Ogle ff188723cd Create a saving section 2014-09-16 10:51:33 -07:00
Ben Ogle b661cdd229 💄 2014-09-16 10:51:33 -07:00
Ben Ogle 499888a386 Reorg marker section 2014-09-16 10:51:33 -07:00
Ben Ogle 86bbf4276b Reorg the Decorations section 2014-09-16 10:51:33 -07:00
Ben Ogle 48d02cf934 Reorganize the Folds section 2014-09-16 10:51:33 -07:00
Ben Ogle 9dacdaf2ef Reorganize the Syntatic Queries section 2014-09-16 10:51:33 -07:00
Ben Ogle af184fe2ff Convert visibility on the grammars section 2014-09-16 10:51:33 -07:00
Ben Ogle d827d4ad34 Change visibility on the Editor Coordinates section 2014-09-16 10:51:33 -07:00
Ben Ogle 4238052dc3 Move text mutation transactions into the mutating text section 2014-09-16 10:51:33 -07:00
Ben Ogle 5790221c15 Reorg undo section 2014-09-16 10:51:32 -07:00
Ben Ogle 5f807df1b0 Reorganize the indentation section 2014-09-16 10:51:32 -07:00
Ben Ogle 30ced48d23 Reorganize Soft Wrap Behavior section 2014-09-16 10:51:32 -07:00
Ben Ogle d17c6e409f Reorganize Tab Behavior section 2014-09-16 10:51:32 -07:00
Ben Ogle 81165e0e41 Add docs for the Editor::scan methods 2014-09-16 10:51:32 -07:00
Ben Ogle 49f5817b87 Convert visibility of the removing text section 2014-09-16 10:51:32 -07:00
Ben Ogle 6b71ea1875 Convert visibility in the Inserting Text section 2014-09-16 10:51:32 -07:00
Ben Ogle 6287f90a39 Convert visibility in the Mutating text section 2014-09-16 10:51:32 -07:00
Ben Ogle 783c1dd449 Convert visibility in the mutating text section 2014-09-16 10:51:32 -07:00
Ben Ogle 719ab078cc Convert file details section to essential extended 2014-09-16 10:51:32 -07:00
Ben Ogle 2491090c91 Move Essential methods above the extended versions 2014-09-16 10:51:32 -07:00
Ben Ogle f12b70e3b7 Editor::onDidChangeScreenLines -> onDidChange 2014-09-16 10:51:32 -07:00
Ben Ogle 4a20f13162 Upgrade scandal to handle negate syntax
!*.coffee
2014-09-16 10:25:25 -07:00
Kevin Sawicki 73253d37bc Prepare 0.130 2014-09-16 10:19:32 -07:00
Kevin Sawicki 16c9c41978 Upgrade to tree-view@0.125 2014-09-16 10:02:45 -07:00
Kevin Sawicki c7ca3e66fd Prepare 0.129 2014-09-16 09:27:02 -07:00
Nathan Sobo eb97154c94 Merge remote-tracking branch 'origin/master' into ns-command-registry 2014-09-16 10:27:00 -06:00
Nathan Sobo 1f95d8069a Document CommandRegistry 2014-09-16 10:08:17 -06:00
Kevin Sawicki dc88f080a3 Upgrade to tree-view@0.124 2014-09-16 09:00:30 -07:00
Nathan Sobo a069f34ad6 Fix CommandRegistry::findCommands spec
Don’t assert against commands registered on the window with jQuery
2014-09-16 09:23:52 -06:00
Nathan Sobo 33ad0a9b93 Delegate ::onDidChangeActivePane and ::observeActivePane 2014-09-16 09:19:07 -06:00
Kevin Sawicki 5c77b06d2a Add Editor:onDidSave 2014-09-15 18:25:29 -07:00
Kevin Sawicki 82a906cce5 Add Workspace::onDidChangeActivePaneItem
Closes #3546
2014-09-15 16:39:53 -07:00
Kevin Sawicki 94e285611c getActiveItem -> getActivePaneItem 2014-09-15 16:31:01 -07:00
Nathan Sobo ebe116d724 Update parent view is-focused and mini classes on editor mount
Fixes #3526
2014-09-15 16:03:36 -06:00
Nathan Sobo 647f6c5b24 Upgrade keybinding resolver to fix deprecation warnings in specs 2014-09-15 15:44:17 -06:00
Nathan Sobo 01a3e0cfba Merge pull request #3545 from atom/ns-revert-soft-wrapped
Rename soft-wrapped back to soft-wrap
2014-09-15 14:49:10 -06:00
Nathan Sobo 3faf566a48 Rename editor:toggle-soft-wrapped back to editor:toggle-soft-wrap 2014-09-15 14:34:35 -06:00
Nathan Sobo a0edb92e16 Rename editor.softWrapped config option back to editor.softWrap 2014-09-15 14:34:35 -06:00
Kevin Sawicki 69480385e6 Upgrade to tree-view@0.123 2014-09-15 13:02:21 -07:00
Kevin Sawicki 804f290cd3 Memoize comment scope selector 2014-09-15 13:01:37 -07:00
Ben Ogle 274a36e263 Upgrade UI themes to fix tabs 2014-09-15 11:18:51 -07:00
Nathan Sobo 4a14580429 Merge pull request #3338 from atom/ns-change-ctrl-a-binding
Change ctrl-a binding to editor:move-to-first-character-of-line on Mac
2014-09-15 12:15:59 -06:00
Kevin Sawicki 17a6256483 Upgrade to find-and-replace@0.138 2014-09-15 11:10:35 -07:00
Kevin Sawicki 7d61330b9f Upgrade to tree-view@0.122 2014-09-15 11:07:49 -07:00
Kevin Sawicki 5e52357674 Upgrade to markdown-preview@0.102 2014-09-15 11:05:39 -07:00
Kevin Sawicki 6ee82d4937 Upgrade to tree-view@0.121 2014-09-15 10:56:01 -07:00
Kevin Sawicki 863362ffed 📝 Outdent ordered list 2014-09-15 08:51:10 -07:00
Kevin Sawicki cea7d89129 📝 🐧 Tweak Linux instructions 2014-09-15 08:50:16 -07:00
Kevin Sawicki 5e65339332 Merge pull request #3535 from Bengt/patch-1
Elaborate getting a current working copy.
2014-09-15 08:44:06 -07:00
Kevin Sawicki 8c2bcf3943 Catch and log deactivate errors
Closes #3538
2014-09-15 08:34:54 -07:00
Kevin Sawicki 10762d6440 Upgrade to language-gfm@0.50 2014-09-15 08:21:19 -07:00
Kevin Sawicki f872583c81 Upgrade to tree-view@0.120 2014-09-14 09:37:26 -07:00
Bengt Lüers ca8153b56b Elaborate getting a current working copy.
The `git checkout` step from #3098 got removed by some merge, so here it is again.
2014-09-14 15:15:52 +02:00
Kevin Sawicki 54c1dd5225 Upgrade to language-php@0.16 2014-09-12 15:10:04 -07:00
Kevin Sawicki d858c6c357 Merge pull request #3528 from atom/ks-add-debian-asset
Add Debian asset to releases
2014-09-12 13:45:47 -07:00
Kevin Sawicki 6d1d6de8ff Restore only uploading from master 2014-09-12 13:28:10 -07:00
Kevin Sawicki 97e7d24f43 Add missing task helpers require 2014-09-12 13:22:15 -07:00
Kevin Sawicki 1bfda1fc61 Copy .deb file to proper upload path 2014-09-12 13:22:15 -07:00
Kevin Sawicki b1a6772105 Don't include version in .deb asset name 2014-09-12 13:22:15 -07:00
Kevin Sawicki bf76a3f1e7 Only publish on Linux for now 2014-09-12 13:22:15 -07:00
Kevin Sawicki 8dcd454401 Remove token logging 2014-09-12 13:22:15 -07:00
Kevin Sawicki 3a2c155afc Log token 2014-09-12 13:22:15 -07:00
Kevin Sawicki e00ff30cd7 Extensions should be an array 2014-09-12 13:22:14 -07:00
Kevin Sawicki 38eda4ca14 Remove duplidate tasks in CI tasks array 2014-09-12 13:22:14 -07:00
Kevin Sawicki dc0bdef36c Don't run specs on Linux CI for now 2014-09-12 13:22:14 -07:00
Kevin Sawicki 9717d973a7 Upload .deb asset during publish 2014-09-12 13:22:14 -07:00
Kevin Sawicki 24206d45a7 Run mkdeb task on Linux CI 2014-09-12 13:22:14 -07:00
Kevin Sawicki a1e177c7dc Set ATOM_ACCESS_TOKEN 2014-09-12 13:22:14 -07:00
Kevin Sawicki 735d1a912e Log debug output 2014-09-12 13:22:14 -07:00
Kevin Sawicki e060d0b562 Add initial Linux CI build script 2014-09-12 13:22:14 -07:00
Kevin Sawicki 68e11fed11 Add .node-version file with 0.10.21 2014-09-12 13:22:14 -07:00
Kevin Sawicki c72ce45820 Log installed node version 2014-09-12 13:22:14 -07:00
Kevin Sawicki 04cc11fa81 Don't read env var files on Linux 2014-09-12 13:22:14 -07:00
Kevin Sawicki f14ad99558 Remove linux check 2014-09-12 13:22:14 -07:00
Kevin Sawicki a060eff478 Use skinny arrows 2014-09-12 11:23:15 -07:00
Ben Ogle 1c57a8b0cd Update event-kit with better organization in docs 2014-09-12 11:19:37 -07:00
Ben Ogle 7c1cab7789 Don’t recurse into dependencies of dependencies.
We always want the top level module!
2014-09-12 10:49:53 -07:00
Kevin Sawicki 591d9068d8 Upgrade to tree-view@0.119 2014-09-12 10:43:15 -07:00
Kevin Sawicki c24bf5bd0c Upgrade to find-and-replace@0.137 2014-09-12 10:34:59 -07:00
Kevin Sawicki 050a79e5b9 Upgrade to find-and-replace@0.136 2014-09-12 10:29:01 -07:00
Kevin Sawicki ee8b01e46a Upgrade to find-and-replace@0.135 2014-09-12 10:10:04 -07:00
Kevin Sawicki ceb48b7f4f Upgrade to tree-view@0.118 2014-09-12 09:51:01 -07:00
Kevin Sawicki 61e01c3984 Upgrade to language-ruby@0.37 2014-09-12 09:11:42 -07:00
Cheng Zhao 901ba72557 Show the open dialog as child window on Windows and Linux.
On Mac the open dialog is still showed as independent dialog, this matches
most native apps' behavior.

Fixes #3401.
2014-09-12 21:43:01 +08:00
Kevin Sawicki 8cffb8006a Upgrade to language-gfm@0.49 2014-09-11 21:41:15 -07:00
Ben Ogle 0643aa66c9 Upgrade atom-keymap for new docs organization 2014-09-11 18:23:39 -07:00
Ben Ogle d0033b2d40 Upgrade tello for bugfix 2014-09-11 18:23:39 -07:00
Kevin Sawicki 8847b35931 Upgrade to tree-view@0.117 2014-09-11 18:11:16 -07:00
Kevin Sawicki 9a534f0b6d Upgrade to tree-view@0.116 2014-09-11 17:35:07 -07:00
Kevin Sawicki 137b926f54 Upgrade to archive-view@0.37 2014-09-11 17:15:49 -07:00
Ben Ogle 24d1a45fd9 Upgrade to pathwather with better doc organization 2014-09-11 16:29:52 -07:00
Kevin Sawicki ea6f124724 Merge pull request #3519 from atom/ks-remeasure-after-themes-load
Wait for themes to load before measuring
2014-09-11 16:22:07 -07:00
Kevin Sawicki c161e93b96 💄 Add ? 2014-09-11 16:08:04 -07:00
Kevin Sawicki e6252546c4 Set initialLoadComplete to true in specs 2014-09-11 15:49:44 -07:00
Kevin Sawicki 4a1f048d52 Refresh scrollbars when no stylesheet is specified 2014-09-11 15:44:30 -07:00
Kevin Sawicki dc5eb95a39 Wait for initial stylesheet load to complete
Instead of measuring on each stylesheet load at startup,
wait for the initial load of all the stylesheets to complete
and then do the necessary measurments.
2014-09-11 15:32:02 -07:00
Kevin Sawicki 844fd29dad Remove unused param 2014-09-11 15:32:02 -07:00
Kevin Sawicki 7b1a38bf8b Upgrade to wrap-guide@0.22 2014-09-11 15:31:47 -07:00
Ben Ogle 54ef5acdc6 Upgrade first-mate with new docs 2014-09-11 14:59:24 -07:00
Ben Ogle c8ccf1e0d7 Merge pull request #3518 from atom/bo-font-settings-in-model
Deprecate font-size, font-family, line-height, invisibles, indent guide methods on EditorView
2014-09-11 14:21:34 -07:00
Kevin Sawicki aee496346b Prepare 0.128 2014-09-11 14:10:44 -07:00
Ben Ogle 6a2c161bf2 Deprecate setShowInvisibles 2014-09-11 14:10:33 -07:00
Ben Ogle 5ef31e00a2 Deprecate EditorView::setShowIndentGuide 2014-09-11 14:10:17 -07:00
Ben Ogle f8ba40bcfe Deprecate font-size, font-family, line-height methods on EditorView. 2014-09-11 14:00:34 -07:00
Nathan Sobo 98a51005c3 Upgrade command-palette to use atom.commands global 2014-09-11 14:25:53 -06:00
Nathan Sobo fb6a184b0e Include commands registered via jQuery in CommandRegistry::findCommands 2014-09-11 14:18:57 -06:00
Nathan Sobo 8b7b946429 Set root node to workspace view when it’s constructed
Makes it easier to deal with specs
2014-09-11 14:18:57 -06:00
Nathan Sobo e4264035d8 fixup! Clear atom.commands after each spec 2014-09-11 14:18:00 -06:00
Nathan Sobo 8f9cf3c790 Set the atom.commands root node to document.body in beforeEach 2014-09-11 14:17:45 -06:00
Nathan Sobo 99cf8fabc0 Clear atom.commands after each spec 2014-09-11 14:13:48 -06:00
Nathan Sobo 3e0e19d51b Add CommandRegistry::findCommands 2014-09-11 13:48:35 -06:00
Nathan Sobo 155fb675ec 💄 group dispatch specs 2014-09-11 13:48:35 -06:00
Nathan Sobo ab8ac369df Move a few workspace commands to the command registry 2014-09-11 13:48:35 -06:00
Nathan Sobo a348ecf034 Allow CommandRegistry::rootNode to be reassigned 2014-09-11 13:48:35 -06:00
Nathan Sobo dac127c30b Assign atom.commands to a CommandRegistry instance 2014-09-11 13:48:35 -06:00
Nathan Sobo 7580d64d2e Allow CommandRegistry::rootNode to be assigned after construction 2014-09-11 13:48:35 -06:00
Nathan Sobo 43d3082d4e Allow multiple commands to be registered by passing an object 2014-09-11 13:48:35 -06:00
Nathan Sobo aee33fc126 Pass selector first to CommandRegistry::add 2014-09-11 13:48:35 -06:00
Nathan Sobo 4de0865d28 Allow listeners to be removed via a Disposable returned from ::add 2014-09-11 13:48:34 -06:00
Nathan Sobo fe27ebec1b Handle .stopImmediatePropagation() being called on command events 2014-09-11 13:48:34 -06:00
Nathan Sobo fbaf956e1f Handle .stopPropagation() being called on command events 2014-09-11 13:48:34 -06:00
Nathan Sobo 5eb22520f1 Order multiple matching listeners by selector specificity 2014-09-11 13:48:34 -06:00
Nathan Sobo a075aa2b07 Perform synthetic bubbling through event target ancestors 2014-09-11 13:48:34 -06:00
Nathan Sobo decc983420 Start on CommandRegistry 2014-09-11 13:48:34 -06:00
Nathan Sobo 7a0a808af1 Change ctrl-a binding to editor:move-to-first-character-of-line
Considering that the entire Atom core team has ctrl-a bound to move to
the first character and it's also the the default behavior of Sublime,
this seems like a more sensible and useful default option even though
it deviates from text editing norms on OS X.
2014-08-19 12:14:16 -06:00
87 arquivos alterados com 4296 adições e 2766 exclusões
+1
Ver Arquivo
@@ -0,0 +1 @@
v0.10.21
+11
Ver Arquivo
@@ -25,6 +25,17 @@ You can also download a `.zip` file from the [releases page](https://github.com/
The Windows version does not currently automatically update so you will need to
manually upgrade to future releases by re-downloading the `.zip` file.
### Debian Linux (Ubuntu)
Currently only a 64-bit version is available.
1. Download `atom-amd64.deb` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
2. Run `sudo dpkg --install atom-amd64.deb` on the downloaded package.
3. Launch Atom using the installed `atom` command.
The Linux version does not currently automatically update so you will need to
repeat these steps to upgrade to future releases.
## Building
* [Linux](docs/build-instructions/linux.md)
+2 -2
Ver Arquivo
@@ -1,11 +1,11 @@
{
"name": "atom-bundled-apm",
"description": "Atom's bundled APM",
"description": "Atom's bundled apm",
"repository": {
"type": "git",
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "0.93.2"
"atom-package-manager": "0.97.0"
}
}
+1 -1
Ver Arquivo
@@ -50,7 +50,7 @@ if [ $OS == 'Mac' ]; then
# If ATOM_PATH isn't a executable file, use spotlight to search for Atom
if [ ! -x "$ATOM_PATH/$ATOM_APP_NAME" ]; then
ATOM_PATH=$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | head -1 | xargs dirname)
ATOM_PATH=$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | grep -v ShipIt | head -1 | xargs dirname)
fi
# Exit if Atom can't be found
+1 -1
Ver Arquivo
@@ -7,7 +7,7 @@ describe "editorView.", ->
beforeEach ->
atom.workspaceViewParentSelector = '#jasmine-content'
atom.workspaceView = new WorkspaceView
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
atom.workspaceView.attachToDom()
atom.workspaceView.width(1024)
+8 -3
Ver Arquivo
@@ -39,6 +39,7 @@ module.exports = (grunt) ->
tmpDir = os.tmpdir()
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
buildDir = path.resolve(buildDir)
installDir = grunt.option('install-dir')
home = if process.platform is 'win32' then process.env.USERPROFILE else process.env.HOME
@@ -62,6 +63,8 @@ module.exports = (grunt) ->
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
killCommand ='pkill -9 atom'
installDir = path.resolve(installDir)
coffeeConfig =
glob_to_multiple:
expand: true
@@ -227,10 +230,12 @@ module.exports = (grunt) ->
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
ciTasks = ['output-disk-space', 'download-atom-shell', 'build']
ciTasks.push('dump-symbols') unless process.platform is 'win32'
ciTasks.push('set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build')
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
ciTasks.push('set-version', 'check-licenses', 'lint')
ciTasks.push('mkdeb') if process.platform is 'linux'
ciTasks.push('test') if process.platform isnt 'linux'
ciTasks.push('codesign', 'publish-build')
grunt.registerTask('ci', ciTasks)
defaultTasks = ['download-atom-shell', 'build', 'set-version']
+1 -1
Ver Arquivo
@@ -8,7 +8,7 @@
"dependencies": {
"async": "~0.2.9",
"donna": "1.0.1",
"tello": "1.0.2",
"tello": "1.0.3",
"formidable": "~1.0.14",
"fs-plus": "2.x",
"github-releases": "~0.2.0",
+1
Ver Arquivo
@@ -11,6 +11,7 @@ module.exports = (grunt) ->
modulesPath = path.resolve(__dirname, '..', '..', 'node_modules')
classes = {}
fs.traverseTreeSync modulesPath, (modulePath) ->
return false if modulePath.match(/node_modules/g).length > 1 # dont need the dependencies of the dependencies
return true unless path.basename(modulePath) is 'package.json'
return true unless fs.isFileSync(modulePath)
+28 -11
Ver Arquivo
@@ -28,7 +28,7 @@ module.exports = (gruntObject) ->
grunt.registerTask 'prepare-docs', 'Move api.json to atom-api.json', ->
docsOutputDir = grunt.config.get('docsOutputDir')
buildDir = grunt.config.get('atom.buildDir')
cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json')
cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json')
grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', ->
done = @async()
@@ -45,16 +45,33 @@ module.exports = (gruntObject) ->
uploadAssets(release, buildDir, assets, done)
getAssets = ->
if process.platform is 'darwin'
[
{assetName: 'atom-mac.zip', sourcePath: 'Atom.app'}
{assetName: 'atom-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'}
{assetName: 'atom-api.json', sourcePath: 'atom-api.json'}
]
else
[
{assetName: 'atom-windows.zip', sourcePath: 'Atom'}
]
switch process.platform
when 'darwin'
[
{assetName: 'atom-mac.zip', sourcePath: 'Atom.app'}
{assetName: 'atom-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'}
{assetName: 'atom-api.json', sourcePath: 'atom-api.json'}
]
when 'win32'
[
{assetName: 'atom-windows.zip', sourcePath: 'Atom'}
]
when 'linux'
buildDir = grunt.config.get('atom.buildDir')
if process.arch is 'ia32'
arch = 'i386'
else
arch = 'amd64'
{version} = grunt.file.readJSON('package.json')
sourcePath = "#{buildDir}/atom-#{version}-#{arch}.deb"
assetName = "atom-#{arch}.deb"
{cp} = require('./task-helpers')(grunt)
cp sourcePath, path.join(buildDir, assetName)
[
{assetName, sourcePath}
]
logError = (message, error, details) ->
grunt.log.error(message)
+1 -2
Ver Arquivo
@@ -109,7 +109,6 @@ module.exports = (grunt) ->
grunt.log.error("[Error]".red + " #{failures.join(', ')} spec(s) failed") if failures.length > 0
if process.platform is 'win32' and process.env.JANKY_SHA1
# Package specs are still flaky on Windows CI
done(!coreSpecFailed)
done()
else
done(!coreSpecFailed and failedPackages.length == 0)
+2 -1
Ver Arquivo
@@ -53,8 +53,9 @@ module.exports = (grunt) ->
proc = childProcess.spawn(options.cmd, options.args, options.opts)
proc.stdout.on 'data', (data) -> stdout.push(data.toString())
proc.stderr.on 'data', (data) -> stderr.push(data.toString())
proc.on 'error', (processError) -> error ?= processError
proc.on 'close', (exitCode, signal) ->
error = new Error(signal) if exitCode != 0
error ?= new Error(signal) if exitCode != 0
results = {stderr: stderr.join(''), stdout: stdout.join(''), code: exitCode}
grunt.log.error results.stderr if exitCode != 0
callback(error, results, exitCode)
+30 -15
Ver Arquivo
@@ -33,26 +33,41 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
If you have problems with permissions don't forget to prefix with `sudo`
From the cloned repository directory:
1. Clone the Atom repository:
1. Build:
```sh
git clone https://github.com/atom/atom
cd atom
```
```sh
$ script/build
```
This will create the atom application at `$TMPDIR/atom-build/Atom`.
2. Install the `atom` and `apm` commands to `/usr/local/bin` by executing:
2. Checkout the latest Atom release:
```sh
$ sudo script/grunt install
```
3. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`:
```sh
git fetch
git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
```
```sh
$ script/grunt mkdeb
```
3. Build Atom:
Use the newly installed atom by restarting any running atom instances.
```sh
script/build
```
This will create the atom application at `$TMPDIR/atom-build/Atom`.
4. Install the `atom` and `apm` commands to `/usr/local/bin` by executing:
```sh
sudo script/grunt install
```
5. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`:
```sh
script/grunt mkdeb
```
Use the newly installed Atom by fully quitting Atom and then reopening.
## Advanced Options
+1 -1
Ver Arquivo
@@ -123,7 +123,7 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu.
- `showInvisibles`: Whether to render placeholders for invisible characters (defaults to `false`)
- `showIndentGuide`: Show/hide indent indicators within the editor
- `showLineNumbers`: Show/hide line numbers within the gutter
- `softWrapped`: Enable/disable soft wrapping of text within the editor
- `softWrap`: Enable/disable soft wrapping of text within the editor
- `softWrapAtPreferredLineLength`: Enable/disable soft line wrapping at `preferredLineLength`
- `tabLength`: Number of spaces within a tab (defaults to `2`)
- `fuzzyFinder`
+6 -1
Ver Arquivo
@@ -1,12 +1,17 @@
{Point, Range} = require 'text-buffer'
{deprecate} = require 'grim'
module.exports =
BufferedNodeProcess: require '../src/buffered-node-process'
BufferedProcess: require '../src/buffered-process'
Git: require '../src/git'
GitRepository: require '../src/git-repository'
Point: Point
Range: Range
Object.defineProperty module.exports, 'Git', get: ->
deprecate "Please require `GitRepository` instead of `Git`: `{GitRepository} = require 'atom'`"
module.exports.GitRepository
# The following classes can't be used from a Task handler and should therefore
# only be exported when not running as a child node process
unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
+3 -1
Ver Arquivo
@@ -119,7 +119,7 @@
'cmd-shift-right': 'editor:select-to-end-of-line'
'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-a': 'editor:move-to-first-character-of-line'
'ctrl-e': 'editor:move-to-end-of-line'
'ctrl-k': 'editor:cut-to-end-of-line'
@@ -143,6 +143,8 @@
# Sublime Parity
'cmd-enter': 'editor:newline-below'
'cmd-shift-enter': 'editor:newline-above'
'alt-enter': 'editor:newline'
'shift-enter': 'editor:newline'
'cmd-]': 'editor:indent-selected-rows'
'cmd-[': 'editor:outdent-selected-rows'
'ctrl-cmd-up': 'editor:move-line-up'
+1 -1
Ver Arquivo
@@ -166,7 +166,7 @@
]
}
{ type: 'separator' }
{ label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrapped' }
{ label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrap' }
]
}
+1 -1
Ver Arquivo
@@ -104,7 +104,7 @@
]
}
{ type: 'separator' }
{ label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrapped' }
{ label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' }
]
}
+1 -1
Ver Arquivo
@@ -122,7 +122,7 @@
]
}
{ type: 'separator' }
{ label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrapped' }
{ label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' }
]
}
+33 -33
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "0.127.0",
"version": "0.131.0",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/browser/main.js",
"repository": {
@@ -20,15 +20,15 @@
"atomShellVersion": "0.16.2",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "^2.1.0",
"atom-keymap": "^2.1.3",
"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",
"emissary": "^1.3.1",
"event-kit": "0.7.1",
"first-mate": "^2.1.0",
"event-kit": "0.7.2",
"first-mate": "^2.1.2",
"fs-plus": "^2.2.6",
"fstream": "0.1.24",
"fuzzaldrin": "^2.1",
@@ -36,20 +36,20 @@
"grim": "0.12.0",
"guid": "0.0.10",
"jasmine-tagged": "^1.1.2",
"less-cache": "0.14.0",
"less-cache": "0.15.0",
"mixto": "^1",
"mkdirp": "0.3.5",
"nslog": "^1.0.1",
"oniguruma": "^3.0.4",
"optimist": "0.4.0",
"pathwatcher": "^2.1.1",
"pathwatcher": "^2.1.3",
"property-accessors": "^1",
"q": "^1.0.1",
"random-words": "0.0.1",
"react-atom-fork": "^0.11.1",
"reactionary-atom-fork": "^1.0.0",
"runas": "1.0.1",
"scandal": "1.0.0",
"scandal": "1.0.2",
"scoped-property-store": "^0.9.0",
"scrollbar-style": "^1.0.2",
"season": "^1.0.2",
@@ -57,88 +57,88 @@
"serializable": "^1",
"space-pen": "3.4.7",
"temp": "0.7.0",
"text-buffer": "^3.2.4",
"text-buffer": "^3.2.6",
"theorist": "^1.0.2",
"underscore-plus": "^1.5.1",
"vm-compatibility-layer": "0.1.0"
},
"packageDependencies": {
"atom-dark-syntax": "0.19.0",
"atom-dark-ui": "0.34.0",
"atom-dark-ui": "0.35.0",
"atom-light-syntax": "0.20.0",
"atom-light-ui": "0.29.0",
"atom-light-ui": "0.30.0",
"base16-tomorrow-dark-theme": "0.21.0",
"base16-tomorrow-light-theme": "0.4.0",
"solarized-dark-syntax": "0.22.0",
"solarized-light-syntax": "0.12.0",
"archive-view": "0.36.0",
"archive-view": "0.37.0",
"autocomplete": "0.32.0",
"autoflow": "0.18.0",
"autosave": "0.17.0",
"background-tips": "0.16.0",
"background-tips": "0.17.0",
"bookmarks": "0.28.0",
"bracket-matcher": "0.55.0",
"command-palette": "0.24.0",
"bracket-matcher": "0.59.0",
"command-palette": "0.25.0",
"deprecation-cop": "0.10.0",
"dev-live-reload": "0.34.0",
"exception-reporting": "0.20.0",
"feedback": "0.33.0",
"find-and-replace": "0.134.0",
"find-and-replace": "0.138.0",
"fuzzy-finder": "0.58.0",
"git-diff": "0.39.0",
"go-to-line": "0.25.0",
"grammar-selector": "0.29.0",
"grammar-selector": "0.34.0",
"image-view": "0.36.0",
"incompatible-packages": "0.9.0",
"keybinding-resolver": "0.19.0",
"keybinding-resolver": "0.20.0",
"link": "0.25.0",
"markdown-preview": "0.101.0",
"markdown-preview": "0.103.0",
"metrics": "0.34.0",
"open-on-github": "0.30.0",
"package-generator": "0.31.0",
"release-notes": "0.36.0",
"settings-view": "0.142.0",
"snippets": "0.52.0",
"settings-view": "0.145.0",
"snippets": "0.53.0",
"spell-check": "0.42.0",
"status-bar": "0.44.0",
"status-bar": "0.45.0",
"styleguide": "0.30.0",
"symbols-view": "0.63.0",
"tabs": "0.50.0",
"symbols-view": "0.66.0",
"tabs": "0.52.0",
"timecop": "0.22.0",
"tree-view": "0.115.0",
"tree-view": "0.126.0",
"update-package-dependencies": "0.6.0",
"welcome": "0.18.0",
"whitespace": "0.25.0",
"wrap-guide": "0.21.0",
"wrap-guide": "0.22.0",
"language-c": "0.28.0",
"language-coffee-script": "0.30.0",
"language-coffee-script": "0.34.0",
"language-css": "0.17.0",
"language-gfm": "0.48.0",
"language-gfm": "0.50.0",
"language-git": "0.9.0",
"language-go": "0.17.0",
"language-html": "0.26.0",
"language-hyperlink": "0.12.0",
"language-java": "0.11.0",
"language-javascript": "0.39.0",
"language-javascript": "0.40.0",
"language-json": "0.8.0",
"language-less": "0.15.0",
"language-make": "0.12.0",
"language-mustache": "0.10.0",
"language-objective-c": "0.11.0",
"language-perl": "0.9.0",
"language-php": "0.15.0",
"language-php": "0.16.0",
"language-property-list": "0.7.0",
"language-python": "0.19.0",
"language-ruby": "0.36.0",
"language-ruby": "0.38.0",
"language-ruby-on-rails": "0.18.0",
"language-sass": "0.21.0",
"language-shellscript": "0.8.0",
"language-source": "0.8.0",
"language-sql": "0.10.0",
"language-sql": "0.11.0",
"language-text": "0.6.0",
"language-todo": "0.11.0",
"language-todo": "0.12.0",
"language-toml": "0.12.0",
"language-xml": "0.20.0",
"language-xml": "0.21.0",
"language-yaml": "0.17.0"
},
"private": true,
+2
Ver Arquivo
@@ -1,8 +1,10 @@
Package: <%= name %>
Version: <%= version %>
Depends: python (>= 2.6), libc6
Section: <%= section %>
Priority: optional
Architecture: <%= arch %>
Installed-Size: <%= installedSize %>
Maintainer: <%= maintainer %>
Description: <%= description %>
Atom is a free and open source text editor that is modern, approachable, and hackable to the core.
+7
Ver Arquivo
@@ -0,0 +1,7 @@
atom: arch-dependent-file-in-usr-share
atom: changelog-file-missing-in-native-package
atom: copyright-file-contains-full-apache-2-license
atom: copyright-should-refer-to-common-license-file-for-apache-2
atom: embedded-library
atom: package-installs-python-bytecode
atom: unstripped-binary-or-object
+1 -4
Ver Arquivo
@@ -5,9 +5,6 @@ var path = require('path');
process.chdir(path.dirname(__dirname));
if (process.platform == 'linux')
throw new Error('cibuild can not run on linux yet!');
var homeDir = process.platform == 'win32' ? process.env.USERPROFILE : process.env.HOME;
function loadEnvironmentVariables(filePath) {
@@ -27,7 +24,7 @@ function loadEnvironmentVariables(filePath) {
function readEnvironmentVariables() {
if (process.platform === 'win32')
loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials'));
else {
else if (process.platform === 'darwin') {
loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials');
loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain');
}
Arquivo executável
+13
Ver Arquivo
@@ -0,0 +1,13 @@
#!/bin/bash
set -e
export ATOM_ACCESS_TOKEN=$BUILD_ATOM_LINUX_ACCESS_TOKEN
if [ -d /usr/local/share/nodenv ]; then
export NODENV_ROOT=/usr/local/share/nodenv
export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH
export NODENV_VERSION="v0.10.21"
fi
script/cibuild
+14 -3
Ver Arquivo
@@ -16,7 +16,7 @@ DEB_PATH="$6"
FILE_MODE=755
TARGET_ROOT="`mktemp -d`"
chmod 755 "$TARGET_ROOT"
chmod $FILE_MODE "$TARGET_ROOT"
TARGET="$TARGET_ROOT/atom-$VERSION-$ARCH"
mkdir -m $FILE_MODE -p "$TARGET/usr"
@@ -31,6 +31,17 @@ cp "$DESKTOP_FILE" "$TARGET/usr/share/applications"
mkdir -m $FILE_MODE -p "$TARGET/usr/share/pixmaps"
cp "$ICON_FILE" "$TARGET/usr/share/pixmaps"
dpkg-deb -b "$TARGET"
# Copy generated LICENSE.md to /usr/share/doc/atom/copyright
mkdir -m $FILE_MODE -p "$TARGET/usr/share/doc/atom"
cp "$TARGET/usr/share/atom/resources/app/LICENSE.md" "$TARGET/usr/share/doc/atom/copyright"
# Add lintian overrides
mkdir -m $FILE_MODE -p "$TARGET/usr/share/lintian/overrides"
cp "$ROOT/resources/linux/debian/lintian-overrides" "$TARGET/usr/share/lintian/overrides/atom"
# Remove executable bit from .node files
find "$TARGET" -type f -name "*.node" -exec chmod a-x {} \;
fakeroot dpkg-deb -b "$TARGET"
mv "$TARGET_ROOT/atom-$VERSION-$ARCH.deb" "$DEB_PATH"
rm -rf $TARGET_ROOT
rm -rf "$TARGET_ROOT"
+1 -1
Ver Arquivo
@@ -31,7 +31,7 @@ function verifyNode(cb) {
var nodeMajorVersion = +versionArray[0];
var nodeMinorVersion = +versionArray[1];
if (nodeMajorVersion === 0 && nodeMinorVersion < 10) {
error = "node v0.10 is required to build Atom.";
error = "node v0.10 is required to build Atom, node " + nodeVersion + " is installed.";
cb(error);
}
else {
+29 -2
Ver Arquivo
@@ -6,7 +6,24 @@ ThemeManager = require '../src/theme-manager'
describe "the `atom` global", ->
beforeEach ->
atom.workspaceView = new WorkspaceView
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
describe 'window sizing methods', ->
describe '::getPosition and ::setPosition', ->
it 'sets the position of the window, and can retrieve the position just set', ->
atom.setPosition(22, 45)
expect(atom.getPosition()).toEqual x: 22, y: 45
describe '::getSize and ::setSize', ->
originalSize = null
beforeEach ->
originalSize = atom.getSize()
afterEach ->
atom.setSize(originalSize.width, originalSize.height)
it 'sets the size of the window, and can retrieve the size just set', ->
atom.setSize(100, 400)
expect(atom.getSize()).toEqual width: 100, height: 400
describe "package lifecycle methods", ->
describe ".loadPackage(name)", ->
@@ -350,7 +367,7 @@ describe "the `atom` global", ->
atom.packages.deactivatePackage("package-that-throws-on-activate")
expect(badPack.mainModule.serialize).not.toHaveBeenCalled()
it "absorbs exceptions that are thrown by the package module's serialize methods", ->
it "absorbs exceptions that are thrown by the package module's serialize method", ->
spyOn(console, 'error')
waitsForPromise ->
@@ -365,6 +382,16 @@ describe "the `atom` global", ->
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
it "absorbs exceptions that are thrown by the package module's deactivate method", ->
spyOn(console, 'error')
waitsForPromise ->
atom.packages.activatePackage("package-that-throws-on-deactivate")
runs ->
expect(-> atom.packages.deactivatePackage("package-that-throws-on-deactivate")).not.toThrow()
expect(console.error).toHaveBeenCalled()
it "removes the package's grammars", ->
waitsForPromise ->
atom.packages.activatePackage('package-with-grammars')
+126
Ver Arquivo
@@ -0,0 +1,126 @@
CommandRegistry = require '../src/command-registry'
describe "CommandRegistry", ->
[registry, parent, child, grandchild] = []
beforeEach ->
parent = document.createElement("div")
child = document.createElement("div")
grandchild = document.createElement("div")
parent.classList.add('parent')
child.classList.add('child')
grandchild.classList.add('grandchild')
child.appendChild(grandchild)
parent.appendChild(child)
document.querySelector('#jasmine-content').appendChild(parent)
registry = new CommandRegistry(parent)
describe "command dispatch", ->
it "invokes callbacks with selectors matching the target", ->
called = false
registry.add '.grandchild', 'command', (event) ->
expect(this).toBe grandchild
expect(event.type).toBe 'command'
expect(event.eventPhase).toBe Event.BUBBLING_PHASE
expect(event.target).toBe grandchild
expect(event.currentTarget).toBe grandchild
called = true
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(called).toBe true
it "invokes callbacks with selectors matching ancestors of the target", ->
calls = []
registry.add '.child', 'command', (event) ->
expect(this).toBe child
expect(event.target).toBe grandchild
expect(event.currentTarget).toBe child
calls.push('child')
registry.add '.parent', 'command', (event) ->
expect(this).toBe parent
expect(event.target).toBe grandchild
expect(event.currentTarget).toBe parent
calls.push('parent')
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(calls).toEqual ['child', 'parent']
it "orders multiple matching listeners for an element by selector specificity", ->
child.classList.add('foo', 'bar')
calls = []
registry.add '.foo.bar', 'command', -> calls.push('.foo.bar')
registry.add '.foo', 'command', -> calls.push('.foo')
registry.add '.bar', 'command', -> calls.push('.bar') # specificity ties favor commands added later, like CSS
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(calls).toEqual ['.foo.bar', '.bar', '.foo']
it "stops bubbling through ancestors when .stopPropagation() is called on the event", ->
calls = []
registry.add '.parent', 'command', -> calls.push('parent')
registry.add '.child', 'command', -> calls.push('child-2')
registry.add '.child', 'command', (event) -> calls.push('child-1'); event.stopPropagation()
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(calls).toEqual ['child-1', 'child-2']
it "stops invoking callbacks when .stopImmediatePropagation() is called on the event", ->
calls = []
registry.add '.parent', 'command', -> calls.push('parent')
registry.add '.child', 'command', -> calls.push('child-2')
registry.add '.child', 'command', (event) -> calls.push('child-1'); event.stopImmediatePropagation()
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(calls).toEqual ['child-1']
it "allows listeners to be removed via a disposable returned by ::add", ->
calls = []
disposable1 = registry.add '.parent', 'command', -> calls.push('parent')
disposable2 = registry.add '.child', 'command', -> calls.push('child')
disposable1.dispose()
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(calls).toEqual ['child']
calls = []
disposable2.dispose()
grandchild.dispatchEvent(new CustomEvent('command', bubbles: true))
expect(calls).toEqual []
it "allows multiple commands to be registered under one selector when called with an object", ->
calls = []
disposable = registry.add '.child',
'command-1': -> calls.push('command-1')
'command-2': -> calls.push('command-2')
grandchild.dispatchEvent(new CustomEvent('command-1', bubbles: true))
grandchild.dispatchEvent(new CustomEvent('command-2', bubbles: true))
expect(calls).toEqual ['command-1', 'command-2']
calls = []
disposable.dispose()
grandchild.dispatchEvent(new CustomEvent('command-1', bubbles: true))
grandchild.dispatchEvent(new CustomEvent('command-2', bubbles: true))
expect(calls).toEqual []
describe "::findCommands({target})", ->
it "returns commands that can be invoked on the target or its ancestors", ->
registry.add '.parent', 'namespace:command-1', ->
registry.add '.child', 'namespace:command-2', ->
registry.add '.grandchild', 'namespace:command-3', ->
registry.add '.grandchild.no-match', 'namespace:command-4', ->
expect(registry.findCommands(target: grandchild)[0..2]).toEqual [
{name: 'namespace:command-3', displayName: 'Namespace: Command 3'}
{name: 'namespace:command-2', displayName: 'Namespace: Command 2'}
{name: 'namespace:command-1', displayName: 'Namespace: Command 1'}
]
+4 -4
Ver Arquivo
@@ -1011,7 +1011,7 @@ describe "DisplayBuffer", ->
buffer.getMarker(marker2.id).destroy()
expect(destroyedHandler).toHaveBeenCalled()
describe "DisplayBufferMarker::copy(attributes)", ->
describe "Marker::copy(attributes)", ->
it "creates a copy of the marker with the given attributes merged in", ->
initialMarkerCount = displayBuffer.getMarkerCount()
marker1 = displayBuffer.markScreenRange([[5, 4], [5, 10]], a: 1, b: 2)
@@ -1020,10 +1020,10 @@ describe "DisplayBuffer", ->
marker2 = marker1.copy(b: 3)
expect(marker2.getBufferRange()).toEqual marker1.getBufferRange()
expect(displayBuffer.getMarkerCount()).toBe initialMarkerCount + 2
expect(marker1.getAttributes()).toEqual a: 1, b: 2
expect(marker2.getAttributes()).toEqual a: 1, b: 3
expect(marker1.getProperties()).toEqual a: 1, b: 2
expect(marker2.getProperties()).toEqual a: 1, b: 3
describe "DisplayBufferMarker::getPixelRange()", ->
describe "Marker::getPixelRange()", ->
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]])
+46 -2
Ver Arquivo
@@ -197,6 +197,50 @@ describe "EditorComponent", ->
nextAnimationFrame()
expect(linesNode.style.backgroundColor).toBe 'rgb(255, 0, 0)'
it "applies .leading-whitespace for lines with leading spaces and/or tabs", ->
editor.setText(' a')
nextAnimationFrame()
leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(leafNodes[0].classList.contains('leading-whitespace')).toBe true
expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe false
editor.setText('\ta')
nextAnimationFrame()
leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(leafNodes[0].classList.contains('leading-whitespace')).toBe true
expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe false
it "applies .trailing-whitespace for lines with trailing spaces and/or tabs", ->
editor.setText(' ')
nextAnimationFrame()
leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe true
expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false
editor.setText('\t')
nextAnimationFrame()
leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe true
expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false
editor.setText('a ')
nextAnimationFrame()
leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe true
expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false
editor.setText('a\t')
nextAnimationFrame()
leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe true
expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false
describe "when showInvisibles is enabled", ->
invisibles = null
@@ -2181,7 +2225,7 @@ describe "EditorComponent", ->
describe "when placholderText is specified", ->
it "renders the placeholder text when the buffer is empty", ->
component.setProps(placeholderText: 'Hello World')
editor.setPlaceholderText('Hello World')
expect(componentNode.querySelector('.placeholder-text')).toBeNull()
editor.setText('')
nextAnimationFrame()
@@ -2195,7 +2239,7 @@ describe "EditorComponent", ->
editor.setSoftWrapped(true)
callingOrder = []
editor.onDidChangeScreenLines -> callingOrder.push 'screen-lines-changed'
editor.onDidChange -> callingOrder.push 'screen-lines-changed'
wrapperView.on 'editor:display-updated', -> callingOrder.push 'editor:display-updated'
editor.insertText("HELLO! HELLO!\n HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! ")
nextAnimationFrame()
+110 -4
Ver Arquivo
@@ -98,11 +98,11 @@ describe "Editor", ->
expect(editor2.isFoldedAtBufferRow(4)).not.toBe editor.isFoldedAtBufferRow(4)
describe "config defaults", ->
it "uses the `editor.tabLength`, `editor.softWrapped`, and `editor.softTabs` config values", ->
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.softWrapped', true)
atom.config.set('editor.softWrap', true)
atom.config.set('editor.softTabs', false)
waitsForPromise ->
@@ -114,7 +114,7 @@ describe "Editor", ->
expect(editor1.getSoftTabs()).toBe false
atom.config.set('editor.tabLength', 100)
atom.config.set('editor.softWrapped', false)
atom.config.set('editor.softWrap', false)
atom.config.set('editor.softTabs', true)
waitsForPromise ->
@@ -174,6 +174,20 @@ describe "Editor", ->
editor.moveDown()
expect(editor.getCursorBufferPosition()).toEqual [1, 1]
it "emits an event with the old position, new position, and the cursor that moved", ->
editor.onDidChangeCursorPosition positionChangedHandler = jasmine.createSpy()
editor.setCursorBufferPosition([2, 4])
expect(positionChangedHandler).toHaveBeenCalled()
eventObject = positionChangedHandler.mostRecentCall.args[0]
expect(eventObject.oldBufferPosition).toEqual [0, 0]
expect(eventObject.oldScreenPosition).toEqual [0, 0]
expect(eventObject.newBufferPosition).toEqual [2, 4]
expect(eventObject.newScreenPosition).toEqual [2, 4]
expect(eventObject.cursor).toBe editor.getLastCursor()
describe ".setCursorScreenPosition(screenPosition)", ->
it "clears a goal column established by vertical movement", ->
# set a goal column by moving down
@@ -887,6 +901,22 @@ describe "Editor", ->
beforeEach ->
selection = editor.getLastSelection()
describe "when the selection range changes", ->
it "emits an event with the old range, new range, and the selection that moved", ->
editor.setSelectedBufferRange([[3, 0], [4, 5]])
editor.onDidChangeSelectionRange rangeChangedHandler = jasmine.createSpy()
editor.selectToBufferPosition([6, 2])
expect(rangeChangedHandler).toHaveBeenCalled()
eventObject = rangeChangedHandler.mostRecentCall.args[0]
expect(eventObject.oldBufferRange).toEqual [[3, 0], [4, 5]]
expect(eventObject.oldScreenRange).toEqual [[3, 0], [4, 5]]
expect(eventObject.newBufferRange).toEqual [[3, 0], [6, 2]]
expect(eventObject.newScreenRange).toEqual [[3, 0], [6, 2]]
expect(eventObject.selection).toBe selection
describe ".selectUp/Down/Left/Right()", ->
it "expands each selection to its cursor's new location", ->
editor.setSelectedBufferRanges([[[0,9], [0,13]], [[3,16], [3,21]]])
@@ -2330,6 +2360,16 @@ describe "Editor", ->
expect(buffer.lineForRow(5)).toMatch /^\t\t\t$/
expect(editor.getCursorBufferPosition()).toEqual [5, 3]
describe "when the difference between the suggested level of indentation and the current level of indentation is greater than 0 but less than 1", ->
it "inserts one tab", ->
editor.setSoftTabs(false)
buffer.setText(" \ntest")
editor.setCursorBufferPosition [1, 0]
editor.indent(autoIndent: true)
expect(buffer.lineForRow(1)).toBe '\ttest'
expect(editor.getCursorBufferPosition()).toEqual [1, 1]
describe "when the line's indent level is greater than the suggested level of indentation", ->
describe "when 'softTabs' is true (the default)", ->
it "moves the cursor to the end of the leading whitespace and inserts 'tabLength' spaces into the buffer", ->
@@ -3229,6 +3269,13 @@ describe "Editor", ->
editor.destroy()
expect(buffer.getMarkerCount()).toBe 0
it "notifies ::onDidDestroy observers when the editor is destroyed", ->
destroyObserverCalled = false
editor.onDidDestroy -> destroyObserverCalled = true
editor.destroy()
expect(destroyObserverCalled).toBe true
describe ".joinLines()", ->
describe "when no text is selected", ->
describe "when the line below isn't empty", ->
@@ -3343,7 +3390,7 @@ describe "Editor", ->
editor2.destroy()
expect(editor.shouldPromptToSave()).toBeTruthy()
describe "when the edit session contains surrogate pair characters", ->
describe "when the editor contains surrogate pair characters", ->
it "correctly backspaces over them", ->
editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97')
editor.moveToBottom()
@@ -3384,6 +3431,47 @@ describe "Editor", ->
editor.moveLeft()
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
describe "when the editor contains variation sequence character pairs", ->
it "correctly backspaces over them", ->
editor.setText('\u2714\uFE0E\u2714\uFE0E\u2714\uFE0E')
editor.moveToBottom()
editor.backspace()
expect(editor.getText()).toBe '\u2714\uFE0E\u2714\uFE0E'
editor.backspace()
expect(editor.getText()).toBe '\u2714\uFE0E'
editor.backspace()
expect(editor.getText()).toBe ''
it "correctly deletes over them", ->
editor.setText('\u2714\uFE0E\u2714\uFE0E\u2714\uFE0E')
editor.moveToTop()
editor.delete()
expect(editor.getText()).toBe '\u2714\uFE0E\u2714\uFE0E'
editor.delete()
expect(editor.getText()).toBe '\u2714\uFE0E'
editor.delete()
expect(editor.getText()).toBe ''
it "correctly moves over them", ->
editor.setText('\u2714\uFE0E\u2714\uFE0E\u2714\uFE0E\n')
editor.moveToTop()
editor.moveRight()
expect(editor.getCursorBufferPosition()).toEqual [0, 2]
editor.moveRight()
expect(editor.getCursorBufferPosition()).toEqual [0, 4]
editor.moveRight()
expect(editor.getCursorBufferPosition()).toEqual [0, 6]
editor.moveRight()
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
editor.moveLeft()
expect(editor.getCursorBufferPosition()).toEqual [0, 6]
editor.moveLeft()
expect(editor.getCursorBufferPosition()).toEqual [0, 4]
editor.moveLeft()
expect(editor.getCursorBufferPosition()).toEqual [0, 2]
editor.moveLeft()
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
describe ".setIndentationForBufferRow", ->
describe "when the editor uses soft tabs but the row has hard tabs", ->
it "only replaces whitespace characters", ->
@@ -3577,3 +3665,21 @@ describe "Editor", ->
editor.selectPageUp()
expect(editor.getScrollTop()).toBe 0
expect(editor.getSelectedBufferRanges()).toEqual [[[0,0], [12,2]]]
describe '.get/setPlaceholderText()', ->
it 'can be created with placeholderText', ->
TextBuffer = require 'text-buffer'
newEditor = new Editor
buffer: new TextBuffer
mini: true
placeholderText: 'yep'
expect(newEditor.getPlaceholderText()).toBe 'yep'
it 'models placeholderText and emits an event when changed', ->
editor.onDidChangePlaceholderText handler = jasmine.createSpy()
expect(editor.getPlaceholderText()).toBeUndefined()
editor.setPlaceholderText('OK')
expect(handler).toHaveBeenCalledWith 'OK'
expect(editor.getPlaceholderText()).toBe 'OK'
@@ -0,0 +1,4 @@
module.exports =
activate: ->
deactivate: -> throw new Error('Top that')
serialize: ->
+17 -17
Ver Arquivo
@@ -1,5 +1,5 @@
temp = require 'temp'
Git = require '../src/git'
GitRepository = require '../src/git-repository'
fs = require 'fs-plus'
path = require 'path'
Task = require '../src/task'
@@ -10,7 +10,7 @@ copyRepository = ->
fs.renameSync(path.join(workingDirPath, 'git.git'), path.join(workingDirPath, '.git'))
workingDirPath
describe "Git", ->
describe "GitRepository", ->
repo = null
beforeEach ->
@@ -22,28 +22,28 @@ describe "Git", ->
describe "@open(path)", ->
it "returns null when no repository is found", ->
expect(Git.open(path.join(temp.dir, 'nogit.txt'))).toBeNull()
expect(GitRepository.open(path.join(temp.dir, 'nogit.txt'))).toBeNull()
describe "new Git(path)", ->
describe "new GitRepository(path)", ->
it "throws an exception when no repository is found", ->
expect(-> new Git(path.join(temp.dir, 'nogit.txt'))).toThrow()
expect(-> new GitRepository(path.join(temp.dir, 'nogit.txt'))).toThrow()
describe ".getPath()", ->
it "returns the repository path for a .git directory path", ->
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'master.git', 'HEAD'))
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'master.git', 'HEAD'))
expect(repo.getPath()).toBe path.join(__dirname, 'fixtures', 'git', 'master.git')
it "returns the repository path for a repository path", ->
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'master.git'))
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'master.git'))
expect(repo.getPath()).toBe path.join(__dirname, 'fixtures', 'git', 'master.git')
describe ".isPathIgnored(path)", ->
it "returns true for an ignored path", ->
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'ignore.git'))
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'ignore.git'))
expect(repo.isPathIgnored('a.txt')).toBeTruthy()
it "returns false for a non-ignored path", ->
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'ignore.git'))
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'ignore.git'))
expect(repo.isPathIgnored('b.txt')).toBeFalsy()
describe ".isPathModified(path)", ->
@@ -51,7 +51,7 @@ describe "Git", ->
beforeEach ->
workingDirPath = copyRepository()
repo = new Git(workingDirPath)
repo = new GitRepository(workingDirPath)
filePath = path.join(workingDirPath, 'a.txt')
newPath = path.join(workingDirPath, 'new-path.txt')
@@ -75,7 +75,7 @@ describe "Git", ->
beforeEach ->
workingDirPath = copyRepository()
repo = new Git(workingDirPath)
repo = new GitRepository(workingDirPath)
filePath = path.join(workingDirPath, 'a.txt')
newPath = path.join(workingDirPath, 'new-path.txt')
fs.writeFileSync(newPath, "i'm new here")
@@ -92,7 +92,7 @@ describe "Git", ->
beforeEach ->
workingDirPath = copyRepository()
repo = new Git(workingDirPath)
repo = new GitRepository(workingDirPath)
filePath = path.join(workingDirPath, 'a.txt')
it "no longer reports a path as modified after checkout", ->
@@ -124,7 +124,7 @@ describe "Git", ->
beforeEach ->
workingDirPath = copyRepository()
repo = new Git(workingDirPath)
repo = new GitRepository(workingDirPath)
filePath = path.join(workingDirPath, 'a.txt')
fs.writeFileSync(filePath, 'ch ch changes')
@@ -153,7 +153,7 @@ describe "Git", ->
describe ".destroy()", ->
it "throws an exception when any method is called after it is called", ->
repo = new Git(require.resolve('./fixtures/git/master.git/HEAD'))
repo = new GitRepository(require.resolve('./fixtures/git/master.git/HEAD'))
repo.destroy()
expect(-> repo.getShortHead()).toThrow()
@@ -162,7 +162,7 @@ describe "Git", ->
beforeEach ->
workingDirectory = copyRepository()
repo = new Git(workingDirectory)
repo = new GitRepository(workingDirectory)
filePath = path.join(workingDirectory, 'file.txt')
it "trigger a status-changed event when the new status differs from the last cached one", ->
@@ -182,7 +182,7 @@ describe "Git", ->
beforeEach ->
workingDirectory = copyRepository()
repo = new Git(workingDirectory)
repo = new GitRepository(workingDirectory)
directoryPath = path.join(workingDirectory, 'dir')
filePath = path.join(directoryPath, 'b.txt')
@@ -197,7 +197,7 @@ describe "Git", ->
beforeEach ->
workingDirectory = copyRepository()
repo = new Git(workingDirectory)
repo = new GitRepository(workingDirectory)
modifiedPath = path.join(workingDirectory, 'file.txt')
newPath = path.join(workingDirectory, 'untracked.txt')
cleanPath = path.join(workingDirectory, 'other.txt')
+9
Ver Arquivo
@@ -7,6 +7,8 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
{TerminalReporter} = require 'jasmine-tagged'
disableFocusMethods() if process.env.JANKY_SHA1
TimeReporter = require './time-reporter'
timeReporter = new TimeReporter()
@@ -38,3 +40,10 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
$('body').append $$ -> @div id: 'jasmine-content'
jasmineEnv.execute()
disableFocusMethods = ->
['fdescribe', 'ffdescribe', 'fffdescribe', 'fit', 'ffit', 'fffit'].forEach (methodName) ->
focusMethod = window[methodName]
window[methodName] = (description) ->
error = new Error('Focused spec is running on CI')
focusMethod description, -> throw error
+22
Ver Arquivo
@@ -70,6 +70,28 @@ describe "LanguageMode", ->
expect(languageMode.rowRangeForCodeFoldAtBufferRow(2)).toBeNull()
expect(languageMode.rowRangeForCodeFoldAtBufferRow(4)).toEqual [4, 7]
describe ".rowRangeForCommentAtBufferRow(bufferRow)", ->
it "returns the start/end rows of the foldable comment starting at the given row", ->
buffer.setText("//this is a multi line comment\n//another line")
expect(languageMode.rowRangeForCommentAtBufferRow(0)).toEqual [0, 1]
expect(languageMode.rowRangeForCommentAtBufferRow(1)).toEqual [0, 1]
buffer.setText("//this is a multi line comment\n//another line\n//and one more")
expect(languageMode.rowRangeForCommentAtBufferRow(0)).toEqual [0, 2]
expect(languageMode.rowRangeForCommentAtBufferRow(1)).toEqual [0, 2]
buffer.setText("//this is a multi line comment\n\n//with an empty line")
expect(languageMode.rowRangeForCommentAtBufferRow(0)).toBeUndefined()
expect(languageMode.rowRangeForCommentAtBufferRow(1)).toBeUndefined()
expect(languageMode.rowRangeForCommentAtBufferRow(2)).toBeUndefined()
buffer.setText("//this is a single line comment\n")
expect(languageMode.rowRangeForCommentAtBufferRow(0)).toBeUndefined()
expect(languageMode.rowRangeForCommentAtBufferRow(1)).toBeUndefined()
buffer.setText("//this is a single line comment")
expect(languageMode.rowRangeForCommentAtBufferRow(0)).toBeUndefined()
describe "suggestedIndentForBufferRow", ->
it "returns the suggested indentation based on auto-indent/outdent rules", ->
expect(languageMode.suggestedIndentForBufferRow(0)).toBe 0
+7
Ver Arquivo
@@ -99,6 +99,13 @@ describe "Pane", ->
pane.addItem(item, 1)
expect(events).toEqual [{item, index: 1}]
it "throws an exception if the item is already present on a pane", ->
item = new Item("A")
pane1 = new Pane(items: [item])
container = new PaneContainer(root: pane1)
pane2 = pane1.splitRight()
expect(-> pane2.addItem(item)).toThrow()
describe "::activateItem(item)", ->
pane = null
+6 -4
Ver Arquivo
@@ -7,7 +7,7 @@ path = require 'path'
temp = require 'temp'
describe "PaneView", ->
[container, view1, view2, editor1, editor2, pane, paneModel] = []
[container, containerModel, view1, view2, editor1, editor2, pane, paneModel] = []
class TestView extends View
@deserialize: ({id, text}) -> new TestView({id, text})
@@ -25,6 +25,7 @@ describe "PaneView", ->
beforeEach ->
atom.deserializers.add(TestView)
container = new PaneContainerView
containerModel = container.model
view1 = new TestView(id: 'view-1', text: 'View 1')
view2 = new TestView(id: 'view-2', text: 'View 2')
waitsForPromise ->
@@ -216,7 +217,7 @@ describe "PaneView", ->
beforeEach ->
pane2Model = paneModel.splitRight() # Can't destroy the last pane, so we add another
pane2 = pane2Model._view
pane2 = containerModel.getView(pane2Model).__spacePenView
it "triggers a 'pane:removed' event with the pane", ->
removedHandler = jasmine.createSpy("removedHandler")
@@ -249,7 +250,7 @@ describe "PaneView", ->
beforeEach ->
pane2Model = paneModel.splitRight(items: [pane.copyActiveItem()])
pane2 = pane2Model._view
pane2 = containerModel.getView(pane2Model).__spacePenView
expect(pane2Model.isActive()).toBe true
it "adds or removes the .active class as appropriate", ->
@@ -296,7 +297,8 @@ describe "PaneView", ->
pane2Model = pane1Model.splitRight(items: [pane1Model.copyActiveItem()])
pane3Model = pane2Model.splitDown(items: [pane2Model.copyActiveItem()])
pane2 = pane2Model._view
pane3 = pane3Model._view
pane2 = containerModel.getView(pane2Model).__spacePenView
pane3 = containerModel.getView(pane3Model).__spacePenView
expect(container.find('> .pane-row > .pane').toArray()).toEqual [pane1[0]]
expect(container.find('> .pane-row > .pane-column > .pane').toArray()).toEqual [pane2[0], pane3[0]]
+4
Ver Arquivo
@@ -21,6 +21,7 @@ clipboard = require 'clipboard'
atom.themes.loadBaseStylesheets()
atom.themes.requireStylesheet '../static/jasmine'
atom.themes.initialLoadComplete = true
fixturePackagesPath = path.resolve(__dirname, './fixtures/packages')
atom.packages.packageDirPaths.unshift(fixturePackagesPath)
@@ -63,6 +64,7 @@ beforeEach ->
atom.project = new Project(path: projectPath)
atom.workspace = new Workspace()
atom.keymaps.keyBindings = _.clone(keyBindingsToRestore)
atom.commands.setRootNode(document.body)
window.resetTimeouts()
atom.packages.packageStates = {}
@@ -119,6 +121,8 @@ beforeEach ->
addCustomMatchers(this)
afterEach ->
atom.commands.clear()
atom.packages.deactivatePackages()
atom.menu.template = []
+28 -26
Ver Arquivo
@@ -1,30 +1,32 @@
textUtils = require '../src/text-utils'
describe 'text utilities', ->
describe '.getCharacterCount(string)', ->
it 'returns the number of full characters in the string', ->
expect(textUtils.getCharacterCount('abc')).toBe 3
expect(textUtils.getCharacterCount('a\uD835\uDF97b\uD835\uDF97c')).toBe 5
expect(textUtils.getCharacterCount('\uD835\uDF97')).toBe 1
expect(textUtils.getCharacterCount('\uD835')).toBe 1
expect(textUtils.getCharacterCount('\uDF97')).toBe 1
describe '.hasPairedCharacter(string)', ->
it 'returns true when the string contains a surrogate pair or variation sequence', ->
expect(textUtils.hasPairedCharacter('abc')).toBe false
expect(textUtils.hasPairedCharacter('a\uD835\uDF97b\uD835\uDF97c')).toBe true
expect(textUtils.hasPairedCharacter('\uD835\uDF97')).toBe true
expect(textUtils.hasPairedCharacter('\u2714\uFE0E')).toBe true
expect(textUtils.hasPairedCharacter('\uD835')).toBe false
expect(textUtils.hasPairedCharacter('\uDF97')).toBe false
expect(textUtils.hasPairedCharacter('\uFE0E')).toBe false
expect(textUtils.hasPairedCharacter('\uFE0E\uFE0E')).toBe false
describe '.hasSurrogatePair(string)', ->
it 'returns true when the string contains a surrogate pair', ->
expect(textUtils.hasSurrogatePair('abc')).toBe false
expect(textUtils.hasSurrogatePair('a\uD835\uDF97b\uD835\uDF97c')).toBe true
expect(textUtils.hasSurrogatePair('\uD835\uDF97')).toBe true
expect(textUtils.hasSurrogatePair('\uD835')).toBe false
expect(textUtils.hasSurrogatePair('\uDF97')).toBe false
describe '.isSurrogatePair(string, index)', ->
it 'returns true when the index is the start of a high/low surrogate pair', ->
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 0)).toBe false
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 1)).toBe true
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 2)).toBe false
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 3)).toBe false
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 4)).toBe true
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 5)).toBe false
expect(textUtils.isSurrogatePair('a\uD835\uDF97b\uD835\uDF97c', 6)).toBe false
expect(textUtils.isSurrogatePair('\uD835')).toBe false
expect(textUtils.isSurrogatePair('\uDF97')).toBe false
describe '.isPairedCharacter(string, index)', ->
it 'returns true when the index is the start of a high/low surrogate pair or variation sequence', ->
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 0)).toBe false
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 1)).toBe true
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 2)).toBe false
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 3)).toBe false
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 4)).toBe true
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 5)).toBe false
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 6)).toBe false
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 0)).toBe false
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 1)).toBe true
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 2)).toBe false
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 3)).toBe false
expect(textUtils.isPairedCharacter('\uD835')).toBe false
expect(textUtils.isPairedCharacter('\uDF97')).toBe false
expect(textUtils.isPairedCharacter('\uFE0E')).toBe false
expect(textUtils.isPairedCharacter('\uFE0E')).toBe false
expect(textUtils.isPairedCharacter('\uFE0E\uFE0E')).toBe false
+1 -1
Ver Arquivo
@@ -209,7 +209,7 @@ describe "ThemeManager", ->
describe "base stylesheet loading", ->
beforeEach ->
atom.workspaceView = new WorkspaceView
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
atom.workspaceView.append $$ -> @div class: 'editor'
atom.workspaceView.attachToDom()
+107
Ver Arquivo
@@ -0,0 +1,107 @@
ViewRegistry = require '../src/view-registry'
{View} = require '../src/space-pen-extensions'
describe "ViewRegistry", ->
registry = null
beforeEach ->
registry = new ViewRegistry
describe "::getView(object)", ->
describe "when passed a DOM node", ->
it "returns the given DOM node", ->
node = document.createElement('div')
expect(registry.getView(node)).toBe node
describe "when passed a SpacePen view", ->
it "returns the root node of the view with a __spacePenView property pointing at the SpacePen view", ->
class TestView extends View
@content: -> @div "Hello"
view = new TestView
node = registry.getView(view)
expect(node.textContent).toBe "Hello"
expect(node.__spacePenView).toBe view
describe "when passed a model object", ->
describe "when a view provider is registered matching the object's constructor", ->
describe "when the provider has a viewConstructor property", ->
it "constructs a view element and assigns the model on it", ->
class TestModel
class TestModelSubclass extends TestModel
class TestView
setModel: (@model) ->
model = new TestModel
registry.addViewProvider
modelConstructor: TestModel
viewConstructor: TestView
view = registry.getView(model)
expect(view instanceof TestView).toBe true
expect(view.model).toBe model
subclassModel = new TestModelSubclass
view2 = registry.getView(subclassModel)
expect(view2 instanceof TestView).toBe true
expect(view2.model).toBe subclassModel
describe "when the provider has a createView method", ->
it "constructs a view element by calling the createView method with the model", ->
class TestModel
class TestView
setModel: (@model) ->
registry.addViewProvider
modelConstructor: TestModel
createView: (model) ->
view = new TestView
view.setModel(model)
view
model = new TestModel
view = registry.getView(model)
expect(view instanceof TestView).toBe true
expect(view.model).toBe model
describe "when no view provider is registered for the object's constructor", ->
describe "when the object has a .getViewClass() method", ->
it "builds an instance of the view class with the model, then returns its root node with a __spacePenView property pointing at the view", ->
class TestView extends View
@content: (model) -> @div model.name
initialize: (@model) ->
class TestModel
constructor: (@name) ->
getViewClass: -> TestView
model = new TestModel("hello")
node = registry.getView(model)
expect(node.textContent).toBe "hello"
view = node.__spacePenView
expect(view instanceof TestView).toBe true
expect(view.model).toBe model
# returns the same DOM node for repeated calls
expect(registry.getView(model)).toBe node
describe "when the object has no .getViewClass() method", ->
it "throws an exception", ->
expect(-> registry.getView(new Object)).toThrow()
describe "::addViewProvider(providerSpec)", ->
it "returns a disposable that can be used to remove the provider", ->
class TestModel
class TestView
setModel: (@model) ->
disposable = registry.addViewProvider
modelConstructor: TestModel
viewConstructor: TestView
expect(registry.getView(new TestModel) instanceof TestView).toBe true
disposable.dispose()
expect(-> registry.getView(new TestModel)).toThrow()
+1
Ver Arquivo
@@ -1,4 +1,5 @@
Workspace = require '../src/workspace'
{View} = require '../src/space-pen-extensions'
describe "Workspace", ->
workspace = null
+5 -4
Ver Arquivo
@@ -13,7 +13,7 @@ describe "WorkspaceView", ->
atom.project.setPath(atom.project.resolve('dir'))
pathToOpen = atom.project.resolve('a')
atom.workspace = new Workspace
atom.workspaceView = new WorkspaceView(atom.workspace)
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
atom.workspaceView.enableKeymap()
atom.workspaceView.focus()
@@ -29,7 +29,7 @@ describe "WorkspaceView", ->
atom.workspaceView.remove()
atom.project = atom.deserializers.deserialize(projectState)
atom.workspace = Workspace.deserialize(workspaceState)
atom.workspaceView = new WorkspaceView(atom.workspace)
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
atom.workspaceView.attachToDom()
describe "when the serialized WorkspaceView has an unsaved buffer", ->
@@ -61,7 +61,7 @@ describe "WorkspaceView", ->
waitsForPromise ->
atom.workspace.open('b').then (editor) ->
pane2.activateItem(editor)
pane2.activateItem(editor.copy())
waitsForPromise ->
atom.workspace.open('../sample.js').then (editor) ->
@@ -185,7 +185,8 @@ describe "WorkspaceView", ->
describe "when the root view is deserialized", ->
it "updates the title to contain the project's path", ->
workspaceView2 = new WorkspaceView(atom.workspace.testSerialization())
workspace2 = atom.workspace.testSerialization()
workspaceView2 = workspace2.getView(workspace2).__spacePenView
item = atom.workspace.getActivePaneItem()
expect(workspaceView2.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
workspaceView2.remove()
+273 -202
Ver Arquivo
@@ -7,21 +7,22 @@ screen = require 'screen'
shell = require 'shell'
_ = require 'underscore-plus'
{deprecated} = require 'grim'
{deprecate} = require 'grim'
{Emitter} = require 'event-kit'
{Model} = require 'theorist'
fs = require 'fs-plus'
{$} = require './space-pen-extensions'
WindowEventHandler = require './window-event-handler'
# Public: Atom global for dealing with packages, themes, menus, and the window.
# Essential: Atom global for dealing with packages, themes, menus, and the window.
#
# An instance of this class is always available as the `atom` global.
module.exports =
class Atom extends Model
@version: 1 # Increment this when the serialization format changes
# Public: Load or create the Atom environment in the given mode.
# Load or create the Atom environment in the given mode.
#
# * `mode` A {String} mode that is either 'editor' or 'spec' depending on the
# kind of environment you want to build.
@@ -98,26 +99,27 @@ class Atom extends Model
workspaceViewParentSelector: 'body'
lastUncaughtError: null
# Public: A {Clipboard} instance
clipboard: null
###
Section: Properties
###
# Experimental: A {CommandRegistry} instance
commands: null
# Public: A {Config} instance
config: null
# Public: A {Clipboard} instance
clipboard: null
# Public: A {ContextMenuManager} instance
contextMenu: null
# Public: A {DeserializerManager} instance
deserializers: null
# Public: A {KeymapManager} instance
keymaps: null
# Public: A {MenuManager} instance
menu: null
# Public: A {PackageManager} instance
packages: null
# Public: A {KeymapManager} instance
keymaps: null
# Public: A {Project} instance
project: null
@@ -125,26 +127,43 @@ class Atom extends Model
# Public: A {Syntax} instance
syntax: null
# Public: A {PackageManager} instance
packages: null
# Public: A {ThemeManager} instance
themes: null
# Public: A {DeserializerManager} instance
deserializers: null
# Public: A {Workspace} instance
workspace: null
# Public: A {WorkspaceView} instance
workspaceView: null
###
Section: Construction and Destruction
###
# Call .loadOrCreate instead
constructor: (@state) ->
@emitter = new Emitter
{@mode} = @state
DeserializerManager = require './deserializer-manager'
@deserializers = new DeserializerManager()
# Public: Sets up the basic services that should be available in all modes
# Sets up the basic services that should be available in all modes
# (both spec and application).
#
# Call after this instance has been assigned to the `atom` global.
initialize: ->
# Disable deprecations unless in dev mode or spec mode so that regular
# editor performance isn't impacted by generating stack traces for
# deprecated calls.
unless @inDevMode() or @inSpecMode()
require('grim').deprecate = ->
window.onerror = =>
@openDevTools()
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
@@ -158,6 +177,7 @@ class Atom extends Model
Config = require './config'
KeymapManager = require './keymap-extensions'
CommandRegistry = require './command-registry'
PackageManager = require './package-manager'
Clipboard = require './clipboard'
Syntax = require './syntax'
@@ -179,6 +199,7 @@ class Atom extends Model
@config = new Config({configDirPath, resourcePath})
@keymaps = new KeymapManager({configDirPath, resourcePath})
@keymap = @keymaps # Deprecated
@commands = new CommandRegistry
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode})
@contextMenu = new ContextMenuManager({resourcePath, devMode})
@@ -198,22 +219,172 @@ class Atom extends Model
@windowEventHandler = new WindowEventHandler
# Deprecated: Callers should be converted to use atom.deserializers
registerRepresentationClass: ->
deprecated("Callers should be converted to use atom.deserializers")
###
Section: Event Subscription
###
# Deprecated: Callers should be converted to use atom.deserializers
registerRepresentationClasses: ->
deprecated("Callers should be converted to use atom.deserializers")
# Extended: Invoke the given callback whenever {::beep} is called.
#
# * `callback` {Function} to be called whenever {::beep} is called.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidBeep: (callback) ->
@emitter.on 'did-beep', callback
setBodyPlatformClass: ->
document.body.classList.add("platform-#{process.platform}")
###
Section: Atom Details
###
# Public: Get the current window
# Public: Is the current window in development mode?
inDevMode: ->
@getLoadSettings().devMode
# Public: Is the current window running specs?
inSpecMode: ->
@getLoadSettings().isSpec
# Public: Get the version of the Atom application.
#
# Returns the version text {String}.
getVersion: ->
@appVersion ?= @getLoadSettings().appVersion
# Public: Determine whether the current version is an official release.
isReleasedVersion: ->
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
# Public: Get the directory path to Atom's configuration area.
#
# Returns the absolute path to `~/.atom`.
getConfigDirPath: ->
@constructor.getConfigDirPath()
# Public: Get the time taken to completely load the current window.
#
# This time include things like loading and activating packages, creating
# DOM elements for the editor, and reading the config.
#
# Returns the {Number} of milliseconds taken to load the window or null
# if the window hasn't finished loading yet.
getWindowLoadTime: ->
@loadTime
# Public: Get the load settings for the current window.
#
# Returns an {Object} containing all the load setting key/value pairs.
getLoadSettings: ->
@constructor.getLoadSettings()
###
Section: Managing The Atom Window
###
# Essential: Open a new Atom window using the given options.
#
# Calling this method without an options parameter will open a prompt to pick
# a file/folder to open in the new window.
#
# * `options` An {Object} with the following keys:
# * `pathsToOpen` An {Array} of {String} paths to open.
# * `newWindow` A {Boolean}, true to always open a new window instead of
# reusing existing windows depending on the paths to open.
# * `devMode` A {Boolean}, true to open the window in development mode.
# Development mode loads the Atom source from the locally cloned
# repository and also loads all the packages in ~/.atom/dev/packages
# * `safeMode` A {Boolean}, true to open the window in safe mode. Safe
# mode prevents all packages installed to ~/.atom/packages from loading.
open: (options) ->
ipc.send('open', options)
# Essential: Close the current window.
close: ->
@getCurrentWindow().close()
# Essential: Get the size of current window.
#
# Returns an {Object} in the format `{width: 1000, height: 700}`
getSize: ->
[width, height] = @getCurrentWindow().getSize()
{width, height}
# Essential: Set the size of current window.
#
# * `width` The {Number} of pixels.
# * `height` The {Number} of pixels.
setSize: (width, height) ->
@getCurrentWindow().setSize(width, height)
# Essential: Get the position of current window.
#
# Returns an {Object} in the format `{x: 10, y: 20}`
getPosition: ->
[x, y] = @getCurrentWindow().getPosition()
{x, y}
# Essential: Set the position of current window.
#
# * `x` The {Number} of pixels.
# * `y` The {Number} of pixels.
setPosition: (x, y) ->
ipc.send('call-window-method', 'setPosition', x, y)
# Extended: Get the current window
getCurrentWindow: ->
@constructor.getCurrentWindow()
# Public: Get the dimensions of this window.
# Extended: Move current window to the center of the screen.
center: ->
ipc.send('call-window-method', 'center')
# Extended: Focus the current window.
focus: ->
ipc.send('call-window-method', 'focus')
$(window).focus()
# Extended: Show the current window.
show: ->
ipc.send('call-window-method', 'show')
# Extended: Hide the current window.
hide: ->
ipc.send('call-window-method', 'hide')
# Extended: Reload the current window.
reload: ->
ipc.send('call-window-method', 'restart')
# Extended: Returns a {Boolean} true when the current window is maximized.
isMaximixed: ->
@getCurrentWindow().isMaximized()
maximize: ->
ipc.send('call-window-method', 'maximize')
# Extended: Is the current window in full screen mode?
isFullScreen: ->
@getCurrentWindow().isFullScreen()
# Extended: Set the full screen state of the current window.
setFullScreen: (fullScreen=false) ->
ipc.send('call-window-method', 'setFullScreen', fullScreen)
if fullScreen then document.body.classList.add("fullscreen") else document.body.classList.remove("fullscreen")
# Extended: Toggle the full screen state of the current window.
toggleFullScreen: ->
@setFullScreen(!@isFullScreen())
# Schedule the window to be shown and focused on the next tick.
#
# This is done in a next tick to prevent a white flicker from occurring
# if called synchronously.
displayWindow: ({maximize}={}) ->
setImmediate =>
@show()
@focus()
@setFullScreen(true) if @workspace.fullScreen
@maximize() if maximize
# Get the dimensions of this window.
#
# Returns an {Object} with the following keys:
# * `x` The window's x-position {Number}.
@@ -227,7 +398,7 @@ class Atom extends Model
maximized = browserWindow.isMaximized()
{x, y, width, height, maximized}
# Public: Set the dimensions of the window.
# Set the dimensions of the window.
#
# The window will be centered if either the x or y coordinate is not set
# in the dimensions parameter. If x or y are omitted the window will be
@@ -284,41 +455,6 @@ class Atom extends Model
dimensions = @getWindowDimensions()
@state.windowDimensions = dimensions if @isValidDimensions(dimensions)
# Public: Get the load settings for the current window.
#
# Returns an {Object} containing all the load setting key/value pairs.
getLoadSettings: ->
@constructor.getLoadSettings()
deserializeProject: ->
Project = require './project'
startTime = Date.now()
@project ?= @deserializers.deserialize(@state.project) ? new Project(path: @getLoadSettings().initialPath)
@deserializeTimings.project = Date.now() - startTime
deserializeWorkspaceView: ->
Workspace = require './workspace'
WorkspaceView = require './workspace-view'
startTime = Date.now()
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
@workspaceView = new WorkspaceView(@workspace)
@deserializeTimings.workspace = Date.now() - startTime
@keymaps.defaultTarget = @workspaceView[0]
$(@workspaceViewParentSelector).append(@workspaceView)
deserializePackageStates: ->
@packages.packageStates = @state.packageStates ? {}
delete @state.packageStates
deserializeEditorWindow: ->
@deserializeTimings = {}
@deserializePackageStates()
@deserializeProject()
@deserializeWorkspaceView()
# Call this method when establishing a real application window.
startEditorWindow: ->
{resourcePath, safeMode} = @getLoadSettings()
@@ -369,41 +505,17 @@ class Atom extends Model
@windowEventHandler?.unsubscribe()
loadThemes: ->
@themes.load()
###
Section: Messaging the User
###
watchThemes: ->
@themes.onDidReloadAll =>
# Only reload stylesheets from non-theme packages
for pack in @packages.getActivePackages() when pack.getType() isnt 'theme'
pack.reloadStylesheets?()
null
# Essential: Visually and audibly trigger a beep.
beep: ->
shell.beep() if @config.get('core.audioBeep')
@workspaceView.trigger 'beep'
@emitter.emit 'did-beep'
# Notify the browser project of the window's current project path
watchProjectPath: ->
onProjectPathChanged = =>
ipc.send('window-command', 'project-path-changed', @project.getPath())
@subscribe @project, 'path-changed', onProjectPathChanged
onProjectPathChanged()
# Public: Open a new Atom window using the given options.
#
# Calling this method without an options parameter will open a prompt to pick
# a file/folder to open in the new window.
#
# * `options` An {Object} with the following keys:
# * `pathsToOpen` An {Array} of {String} paths to open.
# * `newWindow` A {Boolean}, true to always open a new window instead of
# reusing existing windows depending on the paths to open.
# * `devMode` A {Boolean}, true to open the window in development mode.
# Development mode loads the Atom source from the locally cloned
# repository and also loads all the packages in ~/.atom/dev/packages
# * `safeMode` A {Boolean}, true to open the window in safe mode. Safe
# mode prevents all packages installed to ~/.atom/packages from loading.
open: (options) ->
ipc.send('open', options)
# Public: Open a confirm dialog.
# Essential: A flexible way to open a dialog akin to an alert dialog.
#
# ## Examples
#
@@ -413,13 +525,13 @@ class Atom extends Model
# detailedMessage: 'Be honest.'
# buttons:
# Good: -> window.alert('good to hear')
# Bad: -> window.alert('bummer')
# Bad: -> window.alert('bummer')
# ```
#
# * `options` An {Object} with the following keys:
# * `message` The {String} message to display.
# * `detailedMessage` The {String} detailed message to display.
# * `buttons` Either an array of strings or an object where keys are
# * `detailedMessage` (optional) The {String} detailed message to display.
# * `buttons` (optional) Either an array of strings or an object where keys are
# button names and the values are callbacks to invoke when clicked.
#
# Returns the chosen button index {Number} if the buttons option was an array.
@@ -443,77 +555,71 @@ class Atom extends Model
callback = buttons[buttonLabels[chosen]]
callback?()
showSaveDialog: (callback) ->
callback(showSaveDialogSync())
###
Section: Managing the Dev Tools
###
showSaveDialogSync: (defaultPath) ->
defaultPath ?= @project?.getPath()
currentWindow = @getCurrentWindow()
dialog = remote.require('dialog')
dialog.showSaveDialog currentWindow, {title: 'Save File', defaultPath}
# Public: Open the dev tools for the current window.
# Extended: Open the dev tools for the current window.
openDevTools: ->
ipc.send('call-window-method', 'openDevTools')
# Public: Toggle the visibility of the dev tools for the current window.
# Extended: Toggle the visibility of the dev tools for the current window.
toggleDevTools: ->
ipc.send('call-window-method', 'toggleDevTools')
# Public: Execute code in dev tools.
# Extended: Execute code in dev tools.
executeJavaScriptInDevTools: (code) ->
ipc.send('call-window-method', 'executeJavaScriptInDevTools', code)
# Public: Reload the current window.
reload: ->
ipc.send('call-window-method', 'restart')
###
Section: Private
###
# Public: Focus the current window.
focus: ->
ipc.send('call-window-method', 'focus')
$(window).focus()
deserializeProject: ->
Project = require './project'
# Public: Show the current window.
show: ->
ipc.send('call-window-method', 'show')
startTime = Date.now()
@project ?= @deserializers.deserialize(@state.project) ? new Project(path: @getLoadSettings().initialPath)
@deserializeTimings.project = Date.now() - startTime
# Public: Hide the current window.
hide: ->
ipc.send('call-window-method', 'hide')
deserializeWorkspaceView: ->
Workspace = require './workspace'
WorkspaceView = require './workspace-view'
# Public: Set the size of current window.
#
# * `width` The {Number} of pixels.
# * `height` The {Number} of pixels.
setSize: (width, height) ->
@getCurrentWindow().setSize(width, height)
startTime = Date.now()
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
@workspaceView = @workspace.getView(@workspace).__spacePenView
@deserializeTimings.workspace = Date.now() - startTime
# Public: Set the position of current window.
#
# * `x` The {Number} of pixels.
# * `y` The {Number} of pixels.
setPosition: (x, y) ->
ipc.send('call-window-method', 'setPosition', x, y)
@keymaps.defaultTarget = @workspaceView[0]
$(@workspaceViewParentSelector).append(@workspaceView)
# Public: Move current window to the center of the screen.
center: ->
ipc.send('call-window-method', 'center')
deserializePackageStates: ->
@packages.packageStates = @state.packageStates ? {}
delete @state.packageStates
deserializeEditorWindow: ->
@deserializeTimings = {}
@deserializePackageStates()
@deserializeProject()
@deserializeWorkspaceView()
# Schedule the window to be shown and focused on the next tick.
#
# This is done in a next tick to prevent a white flicker from occurring
# if called synchronously.
displayWindow: ({maximize}={}) ->
setImmediate =>
@show()
@focus()
@setFullScreen(true) if @workspace.fullScreen
@maximize() if maximize
loadThemes: ->
@themes.load()
# Public: Close the current window.
close: ->
@getCurrentWindow().close()
watchThemes: ->
@themes.onDidReloadAll =>
# Only reload stylesheets from non-theme packages
for pack in @packages.getActivePackages() when pack.getType() isnt 'theme'
pack.reloadStylesheets?()
null
# Notify the browser project of the window's current project path
watchProjectPath: ->
onProjectPathChanged = =>
ipc.send('window-command', 'project-path-changed', @project.getPath())
@subscribe @project, 'path-changed', onProjectPathChanged
onProjectPathChanged()
exit: (status) ->
app = remote.require('app')
@@ -526,45 +632,14 @@ class Atom extends Model
setRepresentedFilename: (filename) ->
ipc.send('call-window-method', 'setRepresentedFilename', filename)
# Public: Is the current window in development mode?
inDevMode: ->
@getLoadSettings().devMode
showSaveDialog: (callback) ->
callback(showSaveDialogSync())
# Public: Is the current window running specs?
inSpecMode: ->
@getLoadSettings().isSpec
# Public: Toggle the full screen state of the current window.
toggleFullScreen: ->
@setFullScreen(!@isFullScreen())
# Public: Set the full screen state of the current window.
setFullScreen: (fullScreen=false) ->
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()
maximize: ->
ipc.send('call-window-method', 'maximize')
# Public: Get the version of the Atom application.
#
# Returns the version text {String}.
getVersion: ->
@appVersion ?= @getLoadSettings().appVersion
# Public: Determine whether the current version is an official release.
isReleasedVersion: ->
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
# Public: Get the directory path to Atom's configuration area.
#
# Returns the absolute path to `~/.atom`.
getConfigDirPath: ->
@constructor.getConfigDirPath()
showSaveDialogSync: (defaultPath) ->
defaultPath ?= @project?.getPath()
currentWindow = @getCurrentWindow()
dialog = remote.require('dialog')
dialog.showSaveDialog currentWindow, {title: 'Save File', defaultPath}
saveSync: ->
stateString = JSON.stringify(@state)
@@ -573,27 +648,12 @@ class Atom extends Model
else
@getCurrentWindow().loadSettings.windowState = stateString
# Public: Get the time taken to completely load the current window.
#
# This time include things like loading and activating packages, creating
# DOM elements for the editor, and reading the config.
#
# Returns the {Number} of milliseconds taken to load the window or null
# if the window hasn't finished loading yet.
getWindowLoadTime: ->
@loadTime
crashMainProcess: ->
remote.process.crash()
crashRenderProcess: ->
process.crash()
# Public: Visually and audibly trigger a beep.
beep: ->
shell.beep() if @config.get('core.audioBeep')
@workspaceView.trigger 'beep'
getUserInitScriptPath: ->
initScriptPath = fs.resolve(@getConfigDirPath(), 'init', ['js', 'coffee'])
initScriptPath ? path.join(@getConfigDirPath(), 'init.coffee')
@@ -605,7 +665,7 @@ class Atom extends Model
catch error
console.error "Failed to load `#{userInitScriptPath}`", error.stack, error
# Public: Require the module with the given globals.
# Require the module with the given globals.
#
# The globals will be set on the `window` object and removed after the
# require completes.
@@ -625,3 +685,14 @@ class Atom extends Model
delete window[key]
else
window[key] = value
# Deprecated: Callers should be converted to use atom.deserializers
registerRepresentationClass: ->
deprecate("Callers should be converted to use atom.deserializers")
# Deprecated: Callers should be converted to use atom.deserializers
registerRepresentationClasses: ->
deprecate("Callers should be converted to use atom.deserializers")
setBodyPlatformClass: ->
document.body.classList.add("platform-#{process.platform}")
+9 -1
Ver Arquivo
@@ -484,6 +484,14 @@ class AtomApplication
when 'all' then ['openFile', 'openDirectory']
else throw new Error("#{type} is an invalid type for promptForPath")
# Show the open dialog as child window on Windows and Linux, and as
# independent dialog on OS X. This matches most native apps.
parentWindow =
if process.platform is 'darwin'
null
else
BrowserWindow.getFocusedWindow()
dialog = require 'dialog'
dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) =>
dialog.showOpenDialog parentWindow, title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) =>
@openPaths({pathsToOpen, devMode, safeMode, window})
+1 -1
Ver Arquivo
@@ -1,7 +1,7 @@
BufferedProcess = require './buffered-process'
path = require 'path'
# Public: Like {BufferedProcess}, but accepts a Node script as the command
# Extended: Like {BufferedProcess}, but accepts a Node script as the command
# to run.
#
# This is necessary on Windows since it doesn't support shebang `#!` lines.
+4 -3
Ver Arquivo
@@ -1,7 +1,7 @@
_ = require 'underscore-plus'
ChildProcess = require 'child_process'
# Public: A wrapper which provides standard error/output line buffering for
# Extended: A wrapper which provides standard error/output line buffering for
# Node's ChildProcess.
#
# ## Examples
@@ -44,13 +44,14 @@ class BufferedProcess
if process.platform is "win32"
# Quote all arguments and escapes inner quotes
if args?
cmdArgs = args.map (arg) ->
cmdArgs = args.filter (arg) -> arg?
cmdArgs = cmdArgs.map (arg) ->
if command in ['explorer.exe', 'explorer'] and /^\/[a-zA-Z]+,.*$/.test(arg)
# Don't wrap /root,C:\folder style arguments to explorer calls in
# quotes since they will not be interpreted correctly if they are
arg
else
"\"#{arg.replace(/"/g, '\\"')}\""
"\"#{arg.toString().replace(/"/g, '\\"')}\""
else
cmdArgs = []
if /\s/.test(command)
+1 -1
Ver Arquivo
@@ -1,7 +1,7 @@
clipboard = require 'clipboard'
crypto = require 'crypto'
# Public: Represents the clipboard used for copying and pasting in Atom.
# Extended: Represents the clipboard used for copying and pasting in Atom.
#
# An instance of this class is always available as the `atom.clipboard` global.
#
+176
Ver Arquivo
@@ -0,0 +1,176 @@
{Disposable, CompositeDisposable} = require 'event-kit'
{specificity} = require 'clear-cut'
_ = require 'underscore-plus'
{$} = require './space-pen-extensions'
SequenceCount = 0
SpecificityCache = {}
module.exports =
# Experimental: Associates listener functions with commands in a
# context-sensitive way using CSS selectors. You can access a global instance of
# this class via `atom.commands`, and commands registered there will be
# presented in the command palette.
#
# The global command registry facilitates a style of event handling known as
# *event delegation* that was popularized by jQuery. Atom commands are expressed
# as custom DOM events that can be invoked on the currently focused element via
# a key binding or manually via the command palette. Rather than binding
# listeners for command events directly to DOM nodes, you instead register
# command event listeners globally on `atom.commands` and constrain them to
# specific kinds of elements with CSS selectors.
#
# As the event bubbles upward through the DOM, all registered event listeners
# with matching selectors are invoked in order of specificity. In the event of a
# specificity tie, the most recently registered listener is invoked first. This
# mirrors the "cascade" semantics of CSS. Event listeners are invoked in the
# context of the current DOM node, meaning `this` always points at
# `event.currentTarget`. As is normally the case with DOM events,
# `stopPropagation` and `stopImmediatePropagation` can be used to terminate the
# bubbling process and prevent invocation of additional listeners.
#
# ## Example
#
# Here is a command that inserts the current date in an editor:
#
# ```coffee
# atom.commands.add '.editor',
# 'user:insert-date': (event) ->
# editor = $(this).view().getModel()
# # soon the above above line will be:
# # editor = @getModel()
# editor.insertText(new Date().toLocaleString())
# ```
class CommandRegistry
constructor: (@rootNode) ->
@listenersByCommandName = {}
setRootNode: (newRootNode) ->
oldRootNode = @rootNode
@rootNode = newRootNode
for commandName of @listenersByCommandName
oldRootNode?.removeEventListener(commandName, @dispatchCommand, true)
newRootNode?.addEventListener(commandName, @dispatchCommand, true)
# Public: Add one or more command listeners associated with a selector.
#
# ## Arguments: Registering One Command
#
# * `selector` A {String} containing a CSS selector matching elements on which
# you want to handle the commands. The `,` combinator is not currently
# supported.
# * `commandName` A {String} containing the name of a command you want to
# handle such as `user:insert-date`.
# * `callback` A {Function} to call when the given command is invoked on an
# element matching the selector. It will be called with `this` referencing
# the matching DOM node.
# * `event` A standard DOM event instance. Call `stopPropagation` or
# `stopImmediatePropagation` to terminate bubbling early.
#
# ## Arguments: Registering Multiple Commands
#
# * `selector` A {String} containing a CSS selector matching elements on which
# you want to handle the commands. The `,` combinator is not currently
# supported.
# * `commands` An {Object} mapping command names like `user:insert-date` to
# listener {Function}s.
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added command handler(s).
add: (selector, commandName, callback) ->
if typeof commandName is 'object'
commands = commandName
disposable = new CompositeDisposable
for commandName, callback of commands
disposable.add @add(selector, commandName, callback)
return disposable
unless @listenersByCommandName[commandName]?
@rootNode?.addEventListener(commandName, @dispatchCommand, true)
@listenersByCommandName[commandName] = []
listener = new CommandListener(selector, callback)
listenersForCommand = @listenersByCommandName[commandName]
listenersForCommand.push(listener)
new Disposable =>
listenersForCommand.splice(listenersForCommand.indexOf(listener), 1)
if listenersForCommand.length is 0
delete @listenersByCommandName[commandName]
@rootNode.removeEventListener(commandName, @dispatchCommand, true)
dispatchCommand: (event) =>
propagationStopped = false
immediatePropagationStopped = false
currentTarget = event.target
syntheticEvent = Object.create event,
eventPhase: value: Event.BUBBLING_PHASE
currentTarget: get: -> currentTarget
stopPropagation: value: ->
propagationStopped = true
stopImmediatePropagation: value: ->
propagationStopped = true
immediatePropagationStopped = true
loop
matchingListeners =
@listenersByCommandName[event.type]
.filter (listener) -> currentTarget.webkitMatchesSelector(listener.selector)
.sort (a, b) -> a.compare(b)
for listener in matchingListeners
break if immediatePropagationStopped
listener.callback.call(currentTarget, syntheticEvent)
break if propagationStopped
break if currentTarget is @rootNode
currentTarget = currentTarget.parentNode
# Public: Find all registered commands matching a query.
#
# * `params` An {Object} containing one or more of the following keys:
# * `target` A DOM node that is the hypothetical target of a given command.
#
# Returns an {Array} of {Object}s containing the following keys:
# * `name` The name of the command. For example, `user:insert-date`.
# * `displayName` The display name of the command. For example,
# `User: Insert Date`.
# * `jQuery` Present if the command was registered with the legacy
# `$::command` method.
findCommands: ({target}) ->
commands = []
target = @rootNode unless @rootNode.contains(target)
currentTarget = target
loop
for commandName, listeners of @listenersByCommandName
for listener in listeners
if currentTarget.webkitMatchesSelector(listener.selector)
commands.push
name: commandName
displayName: _.humanizeEventName(commandName)
break if currentTarget is @rootNode
currentTarget = currentTarget.parentNode
for name, displayName of $(target).events() when displayName
commands.push({name, displayName, jQuery: true})
for name, displayName of $(window).events() when displayName
commands.push({name, displayName, jQuery: true})
commands
clear: ->
@listenersByCommandName = {}
class CommandListener
constructor: (@selector, @callback) ->
@specificity = (SpecificityCache[@selector] ?= specificity(@selector))
@sequenceNumber = SequenceCount++
compare: (other) ->
other.specificity - @specificity or
other.sequenceNumber - @sequenceNumber
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@ path = require 'path'
async = require 'async'
pathWatcher = require 'pathwatcher'
# Public: Used to access all of Atom's configuration details.
# Essential: Used to access all of Atom's configuration details.
#
# An instance of this class is always available as the `atom.config` global.
#
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ path = require 'path'
CSON = require 'season'
fs = require 'fs-plus'
# Public: Provides a registry for commands that you'd like to appear in the
# Extended: Provides a registry for commands that you'd like to appear in the
# context menu.
#
# An instance of this class is always available as the `atom.contextMenu`
+173 -143
Ver Arquivo
@@ -42,10 +42,11 @@ class Cursor extends Model
newBufferPosition: newHeadBufferPosition
newScreenPosition: newHeadScreenPosition
textChanged: textChanged
cursor: this
@emit 'moved', movedEvent
@emitter.emit 'did-change-position'
@editor.cursorMoved(this, movedEvent)
@editor.cursorMoved(movedEvent)
@marker.onDidDestroy =>
@destroyed = true
@editor.removeCursor(this)
@@ -54,11 +55,14 @@ class Cursor extends Model
@emitter.dispose()
@needsAutoscroll = true
destroy: ->
@marker.destroy()
###
Section: Event Subscription
###
# Essential: Calls your `callback` when the cursor has been moved.
# Public: Calls your `callback` when the cursor has been moved.
#
# * `callback` {Function}
# * `event` {Object}
@@ -67,12 +71,13 @@ class Cursor extends Model
# * `newBufferPosition` {Point}
# * `newScreenPosition` {Point}
# * `textChanged` {Boolean}
# * `Cursor` {Cursor} that triggered the event
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangePosition: (callback) ->
@emitter.on 'did-change-position', callback
# Extended: Calls your `callback` when the cursor is destroyed
# Public: Calls your `callback` when the cursor is destroyed
#
# * `callback` {Function}
#
@@ -80,7 +85,7 @@ class Cursor extends Model
onDidDestroy: (callback) ->
@emitter.on 'did-destroy', callback
# Extended: Calls your `callback` when the cursor's visibility has changed
# Public: Calls your `callback` when the cursor's visibility has changed
#
# * `callback` {Function}
# * `visibility` {Boolean}
@@ -102,23 +107,9 @@ class Cursor extends Model
super
###
Section: Methods
Section: Managing Cursor Position
###
destroy: ->
@marker.destroy()
changePosition: (options, fn) ->
@clearSelection()
@needsAutoscroll = options.autoscroll ? @isLastCursor()
fn()
if @needsAutoscroll
@emit 'autoscrolled' # Support legacy editor
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition # Support react editor view
getPixelRect: ->
@editor.pixelRectForScreenRange(@getScreenRange())
# Public: Moves a cursor to a given screen position.
#
# * `screenPosition` {Array} of two numbers: the screen row, and the screen column.
@@ -133,10 +124,6 @@ class Cursor extends Model
getScreenPosition: ->
@marker.getHeadScreenPosition()
getScreenRange: ->
{row, column} = @getScreenPosition()
new Range(new Point(row, column), new Point(row, column + 1))
# Public: Moves a cursor to a given buffer position.
#
# * `bufferPosition` {Array} of two numbers: the buffer row, and the buffer column.
@@ -151,47 +138,38 @@ class Cursor extends Model
getBufferPosition: ->
@marker.getHeadBufferPosition()
autoscroll: (options) ->
@editor.scrollToScreenRange(@getScreenRange(), options)
# Public: Returns the cursor's current screen row.
getScreenRow: ->
@getScreenPosition().row
# Public: If the marker range is empty, the cursor is marked as being visible.
updateVisibility: ->
@setVisible(@marker.getBufferRange().isEmpty())
# Public: Returns the cursor's current screen column.
getScreenColumn: ->
@getScreenPosition().column
# Public: Sets whether the cursor is visible.
setVisible: (visible) ->
if @visible != visible
@visible = visible
@needsAutoscroll ?= true if @visible and @isLastCursor()
@emit 'visibility-changed', @visible
@emitter.emit 'did-change-visibility', @visible
# Public: Retrieves the cursor's current buffer row.
getBufferRow: ->
@getBufferPosition().row
# Public: Returns the visibility of the cursor.
isVisible: -> @visible
# Public: Returns the cursor's current buffer column.
getBufferColumn: ->
@getBufferPosition().column
# Public: Get the RegExp used by the cursor to determine what a "word" is.
#
# * `options` (optional) {Object} with the following keys:
# * `includeNonWordCharacters` A {Boolean} indicating whether to include
# non-word characters in the regex. (default: true)
#
# Returns a {RegExp}.
wordRegExp: ({includeNonWordCharacters}={}) ->
includeNonWordCharacters ?= true
nonWordCharacters = atom.config.get('editor.nonWordCharacters')
segments = ["^[\t ]*$"]
segments.push("[^\\s#{_.escapeRegExp(nonWordCharacters)}]+")
if includeNonWordCharacters
segments.push("[#{_.escapeRegExp(nonWordCharacters)}]+")
new RegExp(segments.join("|"), "g")
# Public: Returns the cursor's current buffer row of text excluding its line
# ending.
getCurrentBufferLine: ->
@editor.lineTextForBufferRow(@getBufferRow())
# Public: Identifies if this cursor is the last in the {Editor}.
#
# "Last" is defined as the most recently added cursor.
#
# Returns a {Boolean}.
isLastCursor: ->
this == @editor.getLastCursor()
# Public: Returns whether the cursor is at the start of a line.
isAtBeginningOfLine: ->
@getBufferPosition().column == 0
# Public: Returns whether the cursor is on the line return character.
isAtEndOfLine: ->
@getBufferPosition().isEqual(@getCurrentLineBufferRange().end)
###
Section: Cursor Position Details
###
# Public: Identifies if the cursor is surrounded by whitespace.
#
@@ -229,34 +207,42 @@ class Cursor extends Model
range = [[row, column], [row, Infinity]]
@editor.getTextInBufferRange(range).search(@wordRegExp()) == 0
# Public: Prevents this cursor from causing scrolling.
clearAutoscroll: ->
@needsAutoscroll = null
# Public: Returns the indentation level of the current line.
getIndentLevel: ->
if @editor.getSoftTabs()
@getBufferColumn() / @editor.getTabLength()
else
@getBufferColumn()
# Public: Deselects the current selection.
clearSelection: ->
@selection?.clear()
# Public: Retrieves the grammar's token scopes for the line.
#
# Returns an {Array} of {String}s.
getScopes: ->
@editor.scopesForBufferPosition(@getBufferPosition())
# Public: Returns the cursor's current screen row.
getScreenRow: ->
@getScreenPosition().row
# Public: Returns true if this cursor has no non-whitespace characters before
# its current position.
hasPrecedingCharactersOnLine: ->
bufferPosition = @getBufferPosition()
line = @editor.lineTextForBufferRow(bufferPosition.row)
firstCharacterColumn = line.search(/\S/)
# Public: Returns the cursor's current screen column.
getScreenColumn: ->
@getScreenPosition().column
if firstCharacterColumn is -1
false
else
bufferPosition.column > firstCharacterColumn
# Public: Retrieves the cursor's current buffer row.
getBufferRow: ->
@getBufferPosition().row
# Public: Identifies if this cursor is the last in the {Editor}.
#
# "Last" is defined as the most recently added cursor.
#
# Returns a {Boolean}.
isLastCursor: ->
this == @editor.getLastCursor()
# Public: Returns the cursor's current buffer column.
getBufferColumn: ->
@getBufferPosition().column
# Public: Returns the cursor's current buffer row of text excluding its line
# ending.
getCurrentBufferLine: ->
@editor.lineTextForBufferRow(@getBufferRow())
###
Section: Moving the Cursor
###
# Public: Moves the cursor up one screen row.
#
@@ -417,6 +403,20 @@ class Cursor extends Model
@setBufferPosition(endOfLeadingWhitespace) if endOfLeadingWhitespace.isGreaterThan(position)
# Public: Moves the cursor to the beginning of the next paragraph
moveToBeginningOfNextParagraph: ->
if position = @getBeginningOfNextParagraphBufferPosition()
@setBufferPosition(position)
# Public: Moves the cursor to the beginning of the previous paragraph
moveToBeginningOfPreviousParagraph: ->
if position = @getBeginningOfPreviousParagraphBufferPosition()
@setBufferPosition(position)
###
Section: Local Positions and Ranges
###
# Public: Retrieves the buffer position of where the current word starts.
#
# * `options` (optional) An {Object} with the following keys:
@@ -553,15 +553,98 @@ class Cursor extends Model
getCurrentLineBufferRange: (options) ->
@editor.bufferRangeForBufferRow(@getBufferRow(), options)
# Public: Moves the cursor to the beginning of the next paragraph
moveToBeginningOfNextParagraph: ->
if position = @getBeginningOfNextParagraphBufferPosition()
@setBufferPosition(position)
# Public: Retrieves the range for the current paragraph.
#
# A paragraph is defined as a block of text surrounded by empty lines.
#
# Returns a {Range}.
getCurrentParagraphBufferRange: ->
@editor.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow())
# Public: Moves the cursor to the beginning of the previous paragraph
moveToBeginningOfPreviousParagraph: ->
if position = @getBeginningOfPreviousParagraphBufferPosition()
@setBufferPosition(position)
# Public: Returns the characters preceding the cursor in the current word.
getCurrentWordPrefix: ->
@editor.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()])
###
Section: Visibility
###
# Public: If the marker range is empty, the cursor is marked as being visible.
updateVisibility: ->
@setVisible(@marker.getBufferRange().isEmpty())
# Public: Sets whether the cursor is visible.
setVisible: (visible) ->
if @visible != visible
@visible = visible
@needsAutoscroll ?= true if @visible and @isLastCursor()
@emit 'visibility-changed', @visible
@emitter.emit 'did-change-visibility', @visible
# Public: Returns the visibility of the cursor.
isVisible: -> @visible
###
Section: Comparing to another cursor
###
# Public: Compare this cursor's buffer position to another cursor's buffer position.
#
# See {Point::compare} for more details.
#
# * `otherCursor`{Cursor} to compare against
compare: (otherCursor) ->
@getBufferPosition().compare(otherCursor.getBufferPosition())
###
Section: Utilities
###
# Public: Prevents this cursor from causing scrolling.
clearAutoscroll: ->
@needsAutoscroll = null
# Public: Deselects the current selection.
clearSelection: ->
@selection?.clear()
# Public: Get the RegExp used by the cursor to determine what a "word" is.
#
# * `options` (optional) {Object} with the following keys:
# * `includeNonWordCharacters` A {Boolean} indicating whether to include
# non-word characters in the regex. (default: true)
#
# Returns a {RegExp}.
wordRegExp: ({includeNonWordCharacters}={}) ->
includeNonWordCharacters ?= true
nonWordCharacters = atom.config.get('editor.nonWordCharacters')
segments = ["^[\t ]*$"]
segments.push("[^\\s#{_.escapeRegExp(nonWordCharacters)}]+")
if includeNonWordCharacters
segments.push("[#{_.escapeRegExp(nonWordCharacters)}]+")
new RegExp(segments.join("|"), "g")
###
Section: Private
###
changePosition: (options, fn) ->
@clearSelection()
@needsAutoscroll = options.autoscroll ? @isLastCursor()
fn()
if @needsAutoscroll
@emit 'autoscrolled' # Support legacy editor
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition # Support react editor view
getPixelRect: ->
@editor.pixelRectForScreenRange(@getScreenRange())
getScreenRange: ->
{row, column} = @getScreenPosition()
new Range(new Point(row, column), new Point(row, column + 1))
autoscroll: (options) ->
@editor.scrollToScreenRange(@getScreenRange(), options)
getBeginningOfNextParagraphBufferPosition: (editor) ->
start = @getBufferPosition()
@@ -589,56 +672,3 @@ class Cursor extends Model
position = range.start
stop()
@editor.screenPositionForBufferPosition(position)
# Public: Retrieves the range for the current paragraph.
#
# A paragraph is defined as a block of text surrounded by empty lines.
#
# Returns a {Range}.
getCurrentParagraphBufferRange: ->
@editor.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow())
# Public: Returns the characters preceding the cursor in the current word.
getCurrentWordPrefix: ->
@editor.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()])
# Public: Returns whether the cursor is at the start of a line.
isAtBeginningOfLine: ->
@getBufferPosition().column == 0
# Public: Returns the indentation level of the current line.
getIndentLevel: ->
if @editor.getSoftTabs()
@getBufferColumn() / @editor.getTabLength()
else
@getBufferColumn()
# Public: Returns whether the cursor is on the line return character.
isAtEndOfLine: ->
@getBufferPosition().isEqual(@getCurrentLineBufferRange().end)
# Public: Retrieves the grammar's token scopes for the line.
#
# Returns an {Array} of {String}s.
getScopes: ->
@editor.scopesForBufferPosition(@getBufferPosition())
# Public: Returns true if this cursor has no non-whitespace characters before
# its current position.
hasPrecedingCharactersOnLine: ->
bufferPosition = @getBufferPosition()
line = @editor.lineTextForBufferRow(bufferPosition.row)
firstCharacterColumn = line.search(/\S/)
if firstCharacterColumn is -1
false
else
bufferPosition.column > firstCharacterColumn
# Public: Compare this cursor's buffer position to another cursor's buffer position.
#
# See {Point::compare} for more details.
#
# * `otherCursor`{Cursor} to compare against
compare: (otherCursor) ->
@getBufferPosition().compare(otherCursor.getBufferPosition())
+26 -14
Ver Arquivo
@@ -32,7 +32,7 @@ module.exports =
class Decoration
EmitterMixin.includeInto(this)
# Extended: Check if the `decorationProperties.type` matches `type`
# Private: Check if the `decorationProperties.type` matches `type`
#
# * `decorationProperties` {Object} eg. `{type: 'gutter', class: 'my-new-class'}`
# * `type` {String} type like `'gutter'`, `'line'`, etc. `type` can also
@@ -46,6 +46,10 @@ class Decoration
else
type is decorationProperties.type
###
Section: Construction and Destruction
###
constructor: (@marker, @displayBuffer, @properties) ->
@emitter = new Emitter
@id = nextId()
@@ -55,6 +59,19 @@ class Decoration
@markerDestroyDisposable = @marker.onDidDestroy => @destroy()
# Essential: Destroy this marker.
#
# If you own the marker, you should use {Marker::destroy} which will destroy
# this decoration.
destroy: ->
return if @destroyed
@markerDestroyDisposable.dispose()
@markerDestroyDisposable = null
@destroyed = true
@emit 'destroyed'
@emitter.emit 'did-destroy'
@emitter.dispose()
###
Section: Event Subscription
###
@@ -79,7 +96,7 @@ class Decoration
@emitter.on 'did-destroy', callback
###
Section: Methods
Section: Decoration Details
###
# Essential: An id unique across all {Decoration} objects
@@ -98,6 +115,10 @@ class Decoration
isType: (type) ->
Decoration.isType(@properties, type)
###
Section: Properties
###
# Essential: Returns the {Decoration}'s properties.
getProperties: ->
@properties
@@ -125,18 +146,9 @@ class Decoration
Grim.deprecate 'Use Decoration::setProperties instead'
@setProperties(newProperties)
# Essential: Destroy this marker.
#
# If you own the marker, you should use {Marker::destroy} which will destroy
# this decoration.
destroy: ->
return if @destroyed
@markerDestroyDisposable.dispose()
@markerDestroyDisposable = null
@destroyed = true
@emit 'destroyed'
@emitter.emit 'did-destroy'
@emitter.dispose()
###
Section: Private methods
###
matchesPattern: (decorationPattern) ->
return false unless decorationPattern?
+1 -1
Ver Arquivo
@@ -1,4 +1,4 @@
# Public: Manages the deserializers used for serialized state
# Extended: Manages the deserializers used for serialized state
#
# An instance of this class is always available as the `atom.deserializers`
# global.
-270
Ver Arquivo
@@ -1,270 +0,0 @@
{Range} = require 'text-buffer'
_ = require 'underscore-plus'
{Subscriber} = require 'emissary'
EmitterMixin = require('emissary').Emitter
{Emitter} = require 'event-kit'
Grim = require 'grim'
module.exports =
class DisplayBufferMarker
EmitterMixin.includeInto(this)
Subscriber.includeInto(this)
bufferMarkerSubscription: null
oldHeadBufferPosition: null
oldHeadScreenPosition: null
oldTailBufferPosition: null
oldTailScreenPosition: null
wasValid: true
deferredChangeEvents: null
constructor: ({@bufferMarker, @displayBuffer}) ->
@emitter = new Emitter
@id = @bufferMarker.id
@oldHeadBufferPosition = @getHeadBufferPosition()
@oldHeadScreenPosition = @getHeadScreenPosition()
@oldTailBufferPosition = @getTailBufferPosition()
@oldTailScreenPosition = @getTailScreenPosition()
@wasValid = @isValid()
@subscribe @bufferMarker.onDidDestroy => @destroyed()
@subscribe @bufferMarker.onDidChange (event) => @notifyObservers(event)
onDidChange: (callback) ->
@emitter.on 'did-change', callback
onDidDestroy: (callback) ->
@emitter.on 'did-destroy', callback
on: (eventName) ->
switch eventName
when 'changed'
Grim.deprecate("Use DisplayBufferMarker::onDidChange instead")
when 'destroyed'
Grim.deprecate("Use DisplayBufferMarker::onDidDestroy instead")
EmitterMixin::on.apply(this, arguments)
copy: (attributes) ->
@displayBuffer.getMarker(@bufferMarker.copy(attributes).id)
# Gets the screen range of the display marker.
#
# Returns a {Range}.
getScreenRange: ->
@displayBuffer.screenRangeForBufferRange(@getBufferRange(), wrapAtSoftNewlines: true)
# Modifies the screen range of the display marker.
#
# screenRange - The new {Range} to use
# options - A hash of options matching those found in {Marker::setRange}
setScreenRange: (screenRange, options) ->
@setBufferRange(@displayBuffer.bufferRangeForScreenRange(screenRange), options)
# Gets the buffer range of the display marker.
#
# Returns a {Range}.
getBufferRange: ->
@bufferMarker.getRange()
# Modifies the buffer range of the display marker.
#
# screenRange - The new {Range} to use
# options - A hash of options matching those found in {Marker::setRange}
setBufferRange: (bufferRange, options) ->
@bufferMarker.setRange(bufferRange, options)
getPixelRange: ->
@displayBuffer.pixelRangeForScreenRange(@getScreenRange(), false)
# Retrieves the screen position of the marker's head.
#
# Returns a {Point}.
getHeadScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getHeadBufferPosition(), wrapAtSoftNewlines: true)
# Sets the screen position of the marker's head.
#
# screenRange - The new {Point} to use
# options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition}
setHeadScreenPosition: (screenPosition, options) ->
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
@setHeadBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options))
# Retrieves the buffer position of the marker's head.
#
# Returns a {Point}.
getHeadBufferPosition: ->
@bufferMarker.getHeadPosition()
# Sets the buffer position of the marker's head.
#
# screenRange - The new {Point} to use
# options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition}
setHeadBufferPosition: (bufferPosition) ->
@bufferMarker.setHeadPosition(bufferPosition)
# Retrieves the screen position of the marker's tail.
#
# Returns a {Point}.
getTailScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getTailBufferPosition(), wrapAtSoftNewlines: true)
# Sets the screen position of the marker's tail.
#
# screenRange - The new {Point} to use
# options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition}
setTailScreenPosition: (screenPosition, options) ->
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
@setTailBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options))
# Retrieves the buffer position of the marker's tail.
#
# Returns a {Point}.
getTailBufferPosition: ->
@bufferMarker.getTailPosition()
# Sets the buffer position of the marker's tail.
#
# screenRange - The new {Point} to use
# options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition}
setTailBufferPosition: (bufferPosition) ->
@bufferMarker.setTailPosition(bufferPosition)
# Retrieves the screen position of the marker's start. This will always be
# less than or equal to the result of {DisplayBufferMarker::getEndScreenPosition}.
#
# Returns a {Point}.
getStartScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getStartBufferPosition(), wrapAtSoftNewlines: true)
# Retrieves the buffer position of the marker's start. This will always be
# less than or equal to the result of {DisplayBufferMarker::getEndBufferPosition}.
#
# Returns a {Point}.
getStartBufferPosition: ->
@bufferMarker.getStartPosition()
# Retrieves the screen position of the marker's end. This will always be
# greater than or equal to the result of {DisplayBufferMarker::getStartScreenPosition}.
#
# Returns a {Point}.
getEndScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getEndBufferPosition(), wrapAtSoftNewlines: true)
# Retrieves the buffer position of the marker's end. This will always be
# greater than or equal to the result of {DisplayBufferMarker::getStartBufferPosition}.
#
# Returns a {Point}.
getEndBufferPosition: ->
@bufferMarker.getEndPosition()
# Sets the marker's tail to the same position as the marker's head.
#
# This only works if there isn't already a tail position.
#
# Returns a {Point} representing the new tail position.
plantTail: ->
@bufferMarker.plantTail()
# Removes the tail from the marker.
clearTail: ->
@bufferMarker.clearTail()
hasTail: ->
@bufferMarker.hasTail()
# Returns whether the head precedes the tail in the buffer
isReversed: ->
@bufferMarker.isReversed()
# Returns a {Boolean} indicating whether the marker is valid. Markers can be
# invalidated when a region surrounding them in the buffer is changed.
isValid: ->
@bufferMarker.isValid()
# Returns a {Boolean} indicating whether the marker has been destroyed. A marker
# can be invalid without being destroyed, in which case undoing the invalidating
# operation would restore the marker. Once a marker is destroyed by calling
# {Marker::destroy}, no undo/redo operation can ever bring it back.
isDestroyed: ->
@bufferMarker.isDestroyed()
getAttributes: ->
@bufferMarker.getProperties()
setAttributes: (attributes) ->
@bufferMarker.setProperties(attributes)
matchesAttributes: (attributes) ->
attributes = @displayBuffer.translateToBufferMarkerParams(attributes)
@bufferMarker.matchesAttributes(attributes)
# Destroys the marker
destroy: ->
@bufferMarker.destroy()
@unsubscribe()
isEqual: (other) ->
return false unless other instanceof @constructor
@bufferMarker.isEqual(other.bufferMarker)
compare: (other) ->
@bufferMarker.compare(other.bufferMarker)
# Returns a {String} representation of the marker
inspect: ->
"DisplayBufferMarker(id: #{@id}, bufferRange: #{@getBufferRange()})"
destroyed: ->
delete @displayBuffer.markers[@id]
@emit 'destroyed'
@emitter.emit 'did-destroy'
@emitter.dispose()
notifyObservers: ({textChanged}) ->
textChanged ?= false
newHeadBufferPosition = @getHeadBufferPosition()
newHeadScreenPosition = @getHeadScreenPosition()
newTailBufferPosition = @getTailBufferPosition()
newTailScreenPosition = @getTailScreenPosition()
isValid = @isValid()
return if _.isEqual(isValid, @wasValid) and
_.isEqual(newHeadBufferPosition, @oldHeadBufferPosition) and
_.isEqual(newHeadScreenPosition, @oldHeadScreenPosition) and
_.isEqual(newTailBufferPosition, @oldTailBufferPosition) and
_.isEqual(newTailScreenPosition, @oldTailScreenPosition)
changeEvent = {
@oldHeadScreenPosition, newHeadScreenPosition,
@oldTailScreenPosition, newTailScreenPosition,
@oldHeadBufferPosition, newHeadBufferPosition,
@oldTailBufferPosition, newTailBufferPosition,
textChanged,
isValid
}
if @deferredChangeEvents?
@deferredChangeEvents.push(changeEvent)
else
@emit 'changed', changeEvent
@emitter.emit 'did-change', changeEvent
@oldHeadBufferPosition = newHeadBufferPosition
@oldHeadScreenPosition = newHeadScreenPosition
@oldTailBufferPosition = newTailBufferPosition
@oldTailScreenPosition = newTailScreenPosition
@wasValid = isValid
pauseChangeEvents: ->
@deferredChangeEvents = []
resumeChangeEvents: ->
if deferredChangeEvents = @deferredChangeEvents
@deferredChangeEvents = null
for event in deferredChangeEvents
@emit 'changed', event
@emitter.emit 'did-change', event
+13 -13
Ver Arquivo
@@ -10,7 +10,7 @@ RowMap = require './row-map'
Fold = require './fold'
Token = require './token'
Decoration = require './decoration'
DisplayBufferMarker = require './display-buffer-marker'
Marker = require './marker'
Grim = require 'grim'
class BufferToScreenConversionError extends Error
@@ -45,7 +45,7 @@ class DisplayBuffer extends Model
@emitter = new Emitter
@softWrapped ?= atom.config.get('editor.softWrapped') ? false
@softWrapped ?= atom.config.get('editor.softWrap') ? false
@tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, @invisibles})
@buffer = @tokenizedBuffer.buffer
@charWidthsByScope = {}
@@ -865,21 +865,21 @@ class DisplayBuffer extends Model
@emitter.emit 'did-remove-decoration', decoration
delete @decorationsByMarkerId[marker.id] if decorations.length is 0
# Retrieves a {DisplayBufferMarker} based on its id.
# Retrieves a {Marker} based on its id.
#
# id - A {Number} representing a marker id
#
# Returns the {DisplayBufferMarker} (if it exists).
# Returns the {Marker} (if it exists).
getMarker: (id) ->
unless marker = @markers[id]
if bufferMarker = @buffer.getMarker(id)
marker = new DisplayBufferMarker({bufferMarker, displayBuffer: this})
marker = new Marker({bufferMarker, displayBuffer: this})
@markers[id] = marker
marker
# Retrieves the active markers in the buffer.
#
# Returns an {Array} of existing {DisplayBufferMarker}s.
# Returns an {Array} of existing {Marker}s.
getMarkers: ->
@buffer.getMarkers().map ({id}) => @getMarker(id)
@@ -934,7 +934,7 @@ class DisplayBuffer extends Model
#
# Refer to {DisplayBuffer::findMarkers} for details.
#
# Returns a {DisplayBufferMarker} or null
# Returns a {Marker} or null
findMarker: (params) ->
@findMarkers(params)[0]
@@ -955,7 +955,7 @@ class DisplayBuffer extends Model
# :containedInBufferRange - A {Range} or range-compatible {Array}. Only
# returns markers contained within this range.
#
# Returns an {Array} of {DisplayBufferMarker}s
# Returns an {Array} of {Marker}s
findMarkers: (params) ->
params = @translateToBufferMarkerParams(params)
@buffer.findMarkers(params).map (stringMarker) => @getMarker(stringMarker.id)
@@ -1138,13 +1138,13 @@ class DisplayBuffer extends Model
@pendingChangeEvent = null
@emitDidChange(event, false)
handleBufferMarkerCreated: (marker) =>
@createFoldForMarker(marker) if marker.matchesAttributes(@getFoldMarkerAttributes())
if displayBufferMarker = @getMarker(marker.id)
handleBufferMarkerCreated: (textBufferMarker) =>
@createFoldForMarker(textBufferMarker) if textBufferMarker.matchesParams(@getFoldMarkerAttributes())
if marker = @getMarker(textBufferMarker.id)
# The marker might have been removed in some other handler called before
# this one. Only emit when the marker still exists.
@emit 'marker-created', displayBufferMarker
@emitter.emit 'did-create-marker', displayBufferMarker
@emit 'marker-created', marker
@emitter.emit 'did-create-marker', marker
createFoldForMarker: (marker) ->
@decorateMarker(marker, type: 'gutter', class: 'folded')
+16 -5
Ver Arquivo
@@ -64,7 +64,7 @@ EditorComponent = React.createClass
decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
highlightDecorations = @getHighlightDecorations(decorations)
lineDecorations = @getLineDecorations(decorations)
placeholderText = @props.placeholderText if @props.placeholderText? and editor.isEmpty()
placeholderText = editor.getPlaceholderText() if editor.isEmpty()
visible = @isVisible()
scrollHeight = editor.getScrollHeight()
@@ -128,6 +128,7 @@ EditorComponent = React.createClass
scrollableInOppositeDirection: verticallyScrollable
verticalScrollbarWidth: verticalScrollbarWidth
horizontalScrollbarHeight: horizontalScrollbarHeight
useHardwareAcceleration: @useHardwareAcceleration
ScrollbarComponent
ref: 'verticalScrollbar'
@@ -140,6 +141,7 @@ EditorComponent = React.createClass
scrollableInOppositeDirection: horizontallyScrollable
verticalScrollbarWidth: verticalScrollbarWidth
horizontalScrollbarHeight: horizontalScrollbarHeight
useHardwareAcceleration: @useHardwareAcceleration
# Also used to measure the height/width of scrollbars after the initial render
ScrollbarCornerComponent
@@ -179,9 +181,13 @@ EditorComponent = React.createClass
@subscribe atom.themes.onDidAddStylesheet @onStylesheetsChanged
@subscribe atom.themes.onDidUpdateStylesheet @onStylesheetsChanged
@subscribe atom.themes.onDidRemoveStylesheet @onStylesheetsChanged
unless atom.themes.isInitialLoadComplete()
@subscribe atom.themes.onDidReloadAll @onStylesheetsChanged
@subscribe scrollbarStyle.changes, @refreshScrollbars
@domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval)
@updateParentViewFocusedClassIfNeeded({})
@updateParentViewMiniClassIfNeeded({})
@checkForVisibilityChange()
componentWillUnmount: ->
@@ -346,12 +352,13 @@ EditorComponent = React.createClass
observeEditor: ->
{editor} = @props
@subscribe editor.onDidChangeScreenLines(@onScreenLinesChanged)
@subscribe editor.onDidChange(@onScreenLinesChanged)
@subscribe editor.observeCursors(@onCursorAdded)
@subscribe editor.observeSelections(@onSelectionAdded)
@subscribe editor.observeDecorations(@onDecorationAdded)
@subscribe editor.onDidRemoveDecoration(@onDecorationRemoved)
@subscribe editor.onDidChangeCharacterWidths(@onCharacterWidthsChanged)
@subscribe editor.onDidChangePlaceholderText(@onPlaceholderTextChanged)
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
@subscribe editor.$scrollLeft.changes, @requestUpdate
@subscribe editor.$verticalScrollbarWidth.changes, @requestUpdate
@@ -476,7 +483,7 @@ EditorComponent = React.createClass
'editor:add-selection-above': -> editor.addSelectionAbove()
'editor:split-selections-into-lines': -> editor.splitSelectionsIntoLines()
'editor:toggle-soft-tabs': -> editor.toggleSoftTabs()
'editor:toggle-soft-wrapped': -> editor.toggleSoftWrapped()
'editor:toggle-soft-wrap': -> editor.toggleSoftWrapped()
'editor:fold-all': -> editor.foldAll()
'editor:unfold-all': -> editor.unfoldAll()
'editor:fold-current-row': -> editor.foldCurrentRow()
@@ -708,8 +715,9 @@ EditorComponent = React.createClass
onStylesheetsChanged: (stylesheet) ->
return unless @performedInitialMeasurement
return unless atom.themes.isInitialLoadComplete()
@refreshScrollbars() if @containsScrollbarSelector(stylesheet)
@refreshScrollbars() if not stylesheet? or @containsScrollbarSelector(stylesheet)
@sampleFontStyling()
@sampleBackgroundColors()
@remeasureCharacterWidths()
@@ -773,6 +781,9 @@ EditorComponent = React.createClass
onCharacterWidthsChanged: (@scopedCharacterWidthsChangeCount) ->
@requestUpdate()
onPlaceholderTextChanged: ->
@requestUpdate()
handleDragUntilMouseUp: (event, dragHandler) ->
{editor} = @props
dragging = false
@@ -949,7 +960,7 @@ EditorComponent = React.createClass
{verticalScrollbar, horizontalScrollbar, scrollbarCorner} = @refs
verticalNode = verticalScrollbar.getDOMNode()
horizontalNode = verticalScrollbar.getDOMNode()
horizontalNode = horizontalScrollbar.getDOMNode()
cornerNode = scrollbarCorner.getDOMNode()
originalVerticalDisplayValue = verticalNode.style.display
+16 -38
Ver Arquivo
@@ -9,6 +9,8 @@ EditorComponent = require './editor-component'
# Public: Represents the entire visual pane in Atom.
#
# The EditorView manages the {Editor}, which manages the file buffers.
# `EditorView` is intentionally sparse. Most of the things you'll want
# to do are on {Editor}.
#
# ## Examples
#
@@ -47,7 +49,7 @@ class EditorView extends View
nonWordCharacters: "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
preferredLineLength: 80
tabLength: 2
softWrapped: false
softWrap: false
softTabs: true
softWrapAtPreferredLineLength: false
scrollSensitivity: 40
@@ -83,13 +85,13 @@ class EditorView extends View
{@editor, mini, placeholderText} = editorOrParams
props ?= {}
props.mini = mini
props.placeholderText = placeholderText
@editor ?= new Editor
buffer: new TextBuffer
softWrapped: false
tabLength: 2
softTabs: true
mini: mini
placeholderText: placeholderText
props = defaults({@editor, parentView: this}, props)
@component = React.renderComponent(EditorComponent(props), @element)
@@ -282,56 +284,39 @@ class EditorView extends View
deprecate 'Use Editor::getLastVisibleScreenRow instead. You can get the editor via editorView.getModel()'
@editor.getLastVisibleScreenRow()
# Public: Gets the font family for the editor.
#
# Returns a {String} identifying the CSS `font-family`.
getFontFamily: ->
deprecate 'This is going away. Use atom.config.get("editor.fontFamily") instead'
@component?.getFontFamily()
# Public: Sets the font family for the editor.
#
# * `fontFamily` A {String} identifying the CSS `font-family`.
setFontFamily: (fontFamily) ->
deprecate 'This is going away. Use atom.config.set("editor.fontFamily", "my-font") instead'
@component?.setFontFamily(fontFamily)
# Public: Retrieves the font size for the editor.
#
# Returns a {Number} indicating the font size in pixels.
getFontSize: ->
deprecate 'This is going away. Use atom.config.get("editor.fontSize") instead'
@component?.getFontSize()
# Public: Sets the font size for the editor.
#
# * `fontSize` A {Number} indicating the font size in pixels.
setFontSize: (fontSize) ->
deprecate 'This is going away. Use atom.config.set("editor.fontSize", 12) instead'
@component?.setFontSize(fontSize)
setLineHeight: (lineHeight) ->
deprecate 'This is going away. Use atom.config.set("editor.lineHeight", 1.5) instead'
@component.setLineHeight(lineHeight)
setWidthInChars: (widthInChars) ->
@component.getDOMNode().style.width = (@editor.getDefaultCharWidth() * widthInChars) + 'px'
# Public: Sets the line height of the editor.
#
# Calling this method has no effect when called on a mini editor.
#
# * `lineHeight` A {Number} without a unit suffix identifying the CSS `line-height`.
setLineHeight: (lineHeight) ->
@component.setLineHeight(lineHeight)
# Public: Sets whether you want to show the indentation guides.
#
# * `showIndentGuide` A {Boolean} you can set to `true` if you want to see the
# indentation guides.
setShowIndentGuide: (showIndentGuide) ->
deprecate 'This is going away. Use atom.config.set("editor.showIndentGuide", true|false) instead'
@component.setShowIndentGuide(showIndentGuide)
setSoftWrap: (softWrapped) ->
deprecate 'Use Editor::setSoftWrapped instead. You can get the editor via editorView.getModel()'
@editor.setSoftWrapped(softWrapped)
# Public: Set whether invisible characters are shown.
#
# * `showInvisibles` A {Boolean} which, if `true`, show invisible characters.
setShowInvisibles: (showInvisibles) ->
deprecate 'This is going away. Use atom.config.set("editor.showInvisibles", true|false) instead'
@component.setShowInvisibles(showInvisibles)
getText: ->
@@ -361,16 +346,9 @@ class EditorView extends View
redraw: ->
deprecate('Please remove from your code. ::redraw no longer does anything')
# Public: Set the text to appear in the editor when it is empty.
#
# This only affects mini editors.
#
# * `placeholderText` A {String} of text to display when empty.
setPlaceholderText: (placeholderText) ->
if @component?
@component.setProps({placeholderText})
else
@props.placeholderText = placeholderText
deprecate('Use TextEditor::setPlaceholderText instead. eg. editorView.getModel().setPlaceholderText(text)')
@getModel().setPlaceholderText(placeholderText)
lineElementForScreenRow: (screenRow) ->
$(@component.lineNodeForScreenRow(screenRow))
+804 -676
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+283 -271
Ver Arquivo
@@ -10,7 +10,7 @@ GitUtils = require 'git-utils'
Task = require './task'
# Public: Represents the underlying git operations performed by Atom.
# Extended: Represents the underlying git operations performed by Atom.
#
# This class shouldn't be instantiated directly but instead by accessing the
# `atom.project` global and calling `getRepo()`. Note that this will only be
@@ -40,32 +40,13 @@ Task = require './task'
# ### Requiring in packages
#
# ```coffee
# {Git} = require 'atom'
# {GitRepository} = require 'atom'
# ```
module.exports =
class Git
class GitRepository
EmitterMixin.includeInto(this)
Subscriber.includeInto(this)
###
Section: Class Methods
###
# Public: Creates a new Git instance.
#
# * `path` The {String} path to the Git repository to open.
# * `options` An optinal {Object} with the following keys:
# * `refreshOnWindowFocus` A {Boolean}, `true` to refresh the index and
# statuses when the window is focused.
#
# Returns a {Git} instance or `null` if the repository could not be opened.
@open: (path, options) ->
return null unless path
try
new Git(path, options)
catch
null
@exists: (path) ->
if git = @open(path)
git.destroy()
@@ -74,9 +55,24 @@ class Git
false
###
Section: Construction
Section: Construction and Destruction
###
# Public: Creates a new GitRepository instance.
#
# * `path` The {String} path to the Git repository to open.
# * `options` An optinal {Object} with the following keys:
# * `refreshOnWindowFocus` A {Boolean}, `true` to refresh the index and
# statuses when the window is focused.
#
# Returns a {GitRepository} instance or `null` if the repository could not be opened.
@open: (path, options) ->
return null unless path
try
new GitRepository(path, options)
catch
null
constructor: (path, options={}) ->
@emitter = new Emitter
@repo = GitUtils.open(path)
@@ -100,11 +96,26 @@ class Git
if @project?
@subscribe @project.eachBuffer (buffer) => @subscribeToBuffer(buffer)
# Public: Destroy this {GitRepository} object.
#
# This destroys any tasks and subscriptions and releases the underlying
# libgit2 repository handle.
destroy: ->
if @statusTask?
@statusTask.terminate()
@statusTask = null
if @repo?
@repo.release()
@repo = null
@unsubscribe()
###
Section: Event Subscription
###
# Essential: Invoke the given callback when a specific file's status has
# Public: Invoke the given callback when a specific file's status has
# changed. When a file is updated, reloaded, etc, and the status changes, this
# will be fired.
#
@@ -118,7 +129,7 @@ class Git
onDidChangeStatus: (callback) ->
@emitter.on 'did-change-status', callback
# Essential: Invoke the given callback when a multiple files' statuses have
# Public: Invoke the given callback when a multiple files' statuses have
# changed. For example, on window focus, the status of all the paths in the
# repo is checked. If any of them have changed, this will be fired. Call
# {::getPathStatus(path)} to get the status for your path of choice.
@@ -132,15 +143,258 @@ class Git
on: (eventName) ->
switch eventName
when 'status-changed'
deprecate 'Use Git::onDidChangeStatus instead'
deprecate 'Use GitRepository::onDidChangeStatus instead'
when 'statuses-changed'
deprecate 'Use Git::onDidChangeStatuses instead'
deprecate 'Use GitRepository::onDidChangeStatuses instead'
else
deprecate 'Git::on is deprecated. Use event subscription methods instead.'
deprecate 'GitRepository::on is deprecated. Use event subscription methods instead.'
EmitterMixin::on.apply(this, arguments)
###
Section: Instance Methods
Section: Repository Details
###
# Public: Returns the {String} path of the repository.
getPath: ->
@path ?= fs.absolute(@getRepo().getPath())
# Public: Returns the {String} working directory path of the repository.
getWorkingDirectory: -> @getRepo().getWorkingDirectory()
# Public: Returns true if at the root, false if in a subfolder of the
# repository.
isProjectAtRoot: ->
@projectAtRoot ?= @project?.relativize(@getWorkingDirectory()) is ''
# Public: Makes a path relative to the repository's working directory.
relativize: (path) -> @getRepo().relativize(path)
# Public: Returns true if the given branch exists.
hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")?
# Public: Retrieves a shortened version of the HEAD reference value.
#
# This removes the leading segments of `refs/heads`, `refs/tags`, or
# `refs/remotes`. It also shortens the SHA-1 of a detached `HEAD` to 7
# characters.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository contains submodules.
#
# Returns a {String}.
getShortHead: (path) -> @getRepo(path).getShortHead()
# Public: Is the given path a submodule in the repository?
#
# * `path` The {String} path to check.
#
# Returns a {Boolean}.
isSubmodule: (path) ->
return false unless path
repo = @getRepo(path)
if repo.isSubmodule(repo.relativize(path))
true
else
# Check if the path is a working directory in a repo that isn't the root.
repo isnt @getRepo() and repo.relativize(join(path, 'dir')) is 'dir'
# Public: Returns the number of commits behind the current branch is from the
# its upstream remote branch.
#
# * `reference` The {String} branch reference name.
# * `path` The {String} path in the repository to get this information for,
# only needed if the repository contains submodules.
getAheadBehindCount: (reference, path) ->
@getRepo(path).getAheadBehindCount(reference)
# Public: Get the cached ahead/behind commit counts for the current branch's
# upstream branch.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
#
# Returns an {Object} with the following keys:
# * `ahead` The {Number} of commits ahead.
# * `behind` The {Number} of commits behind.
getCachedUpstreamAheadBehindCount: (path) ->
@getRepo(path).upstream ? @upstream
# Public: Returns the git configuration value specified by the key.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
getConfigValue: (key, path) -> @getRepo(path).getConfigValue(key)
# Public: Returns the origin url of the repository.
#
# * `path` (optional) {String} path in the repository to get this information
# for, only needed if the repository has submodules.
getOriginUrl: (path) -> @getConfigValue('remote.origin.url', path)
# Public: Returns the upstream branch for the current HEAD, or null if there
# is no upstream branch for the current HEAD.
#
# * `path` An optional {String} path in the repo to get this information for,
# only needed if the repository contains submodules.
#
# Returns a {String} branch name such as `refs/remotes/origin/master`.
getUpstreamBranch: (path) -> @getRepo(path).getUpstreamBranch()
# Public: Gets all the local and remote references.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
#
# Returns an {Object} with the following keys:
# * `heads` An {Array} of head reference names.
# * `remotes` An {Array} of remote reference names.
# * `tags` An {Array} of tag reference names.
getReferences: (path) -> @getRepo(path).getReferences()
# Public: Returns the current {String} SHA for the given reference.
#
# * `reference` The {String} reference to get the target of.
# * `path` An optional {String} path in the repo to get the reference target
# for. Only needed if the repository contains submodules.
getReferenceTarget: (reference, path) ->
@getRepo(path).getReferenceTarget(reference)
###
Section: Reading Status
###
# Public: Returns true if the given path is modified.
isPathModified: (path) -> @isStatusModified(@getPathStatus(path))
# Public: Returns true if the given path is new.
isPathNew: (path) -> @isStatusNew(@getPathStatus(path))
# Public: Is the given path ignored?
#
# Returns a {Boolean}.
isPathIgnored: (path) -> @getRepo().isIgnored(@relativize(path))
# Public: Get the status of a directory in the repository's working directory.
#
# * `path` The {String} path to check.
#
# Returns a {Number} representing the status. This value can be passed to
# {::isStatusModified} or {::isStatusNew} to get more information.
getDirectoryStatus: (directoryPath) ->
directoryPath = "#{@relativize(directoryPath)}/"
directoryStatus = 0
for path, status of @statuses
directoryStatus |= status if path.indexOf(directoryPath) is 0
directoryStatus
# Public: Get the status of a single path in the repository.
#
# `path` A {String} repository-relative path.
#
# Returns a {Number} representing the status. This value can be passed to
# {::isStatusModified} or {::isStatusNew} to get more information.
getPathStatus: (path) ->
repo = @getRepo(path)
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
delete @statuses[relativePath]
if currentPathStatus isnt pathStatus
@emit 'status-changed', path, pathStatus
@emitter.emit 'did-change-status', {path, pathStatus}
pathStatus
# Public: Get the cached status for the given path.
#
# * `path` A {String} path in the repository, relative or absolute.
#
# Returns a status {Number} or null if the path is not in the cache.
getCachedPathStatus: (path) ->
@statuses[@relativize(path)]
# Public: Returns true if the given status indicates modification.
isStatusModified: (status) -> @getRepo().isStatusModified(status)
# Public: Returns true if the given status indicates a new path.
isStatusNew: (status) -> @getRepo().isStatusNew(status)
###
Section: Retrieving Diffs
###
# Public: Retrieves the number of lines added and removed to a path.
#
# This compares the working directory contents of the path to the `HEAD`
# version.
#
# * `path` The {String} path to check.
#
# Returns an {Object} with the following keys:
# * `added` The {Number} of added lines.
# * `deleted` The {Number} of deleted lines.
getDiffStats: (path) ->
repo = @getRepo(path)
repo.getDiffStats(repo.relativize(path))
# Public: Retrieves the line diffs comparing the `HEAD` version of the given
# path and the given text.
#
# * `path` The {String} path relative to the repository.
# * `text` The {String} to compare against the `HEAD` contents
#
# Returns an {Array} of hunk {Object}s with the following keys:
# * `oldStart` The line {Number} of the old hunk.
# * `newStart` The line {Number} of the new hunk.
# * `oldLines` The {Number} of lines in the old hunk.
# * `newLines` The {Number} of lines in the new hunk
getLineDiffs: (path, text) ->
# Ignore eol of line differences on windows so that files checked in as
# LF don't report every line modified when the text contains CRLF endings.
options = ignoreEolWhitespace: process.platform is 'win32'
repo = @getRepo(path)
repo.getLineDiffs(repo.relativize(path), text, options)
###
Section: Checking Out
###
# Public: Restore the contents of a path in the working directory and index
# to the version at `HEAD`.
#
# This is essentially the same as running:
#
# ```sh
# git reset HEAD -- <path>
# git checkout HEAD -- <path>
# ```
#
# * `path` The {String} path to checkout.
#
# Returns a {Boolean} that's true if the method was successful.
checkoutHead: (path) ->
repo = @getRepo(path)
headCheckedOut = repo.checkoutHead(repo.relativize(path))
@getPathStatus(path) if headCheckedOut
headCheckedOut
# Public: Checks out a branch in your repository.
#
# * `reference` The {String} reference to checkout.
# * `create` A {Boolean} value which, if true creates the new reference if
# it doesn't exist.
#
# Returns a Boolean that's true if the method was successful.
checkoutReference: (reference, create) ->
@getRepo().checkoutReference(reference, create)
###
Section: Private
###
# Subscribes to buffer events.
@@ -175,21 +429,6 @@ class Git
else
checkoutHead()
# Public: Destroy this {Git} object.
#
# This destroys any tasks and subscriptions and releases the underlying
# libgit2 repository handle.
destroy: ->
if @statusTask?
@statusTask.terminate()
@statusTask = null
if @repo?
@repo.release()
@repo = null
@unsubscribe()
# Returns the corresponding {Repository}
getRepo: (path) ->
if @repo?
@@ -201,233 +440,6 @@ class Git
# last time the index was read.
refreshIndex: -> @getRepo().refreshIndex()
# Public: Returns the {String} path of the repository.
getPath: ->
@path ?= fs.absolute(@getRepo().getPath())
# Public: Returns the {String} working directory path of the repository.
getWorkingDirectory: -> @getRepo().getWorkingDirectory()
# Public: Get the status of a single path in the repository.
#
# `path` A {String} repository-relative path.
#
# Returns a {Number} representing the status. This value can be passed to
# {::isStatusModified} or {::isStatusNew} to get more information.
getPathStatus: (path) ->
repo = @getRepo(path)
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
delete @statuses[relativePath]
if currentPathStatus isnt pathStatus
@emit 'status-changed', path, pathStatus
@emitter.emit 'did-change-status', {path, pathStatus}
pathStatus
# Public: Is the given path ignored?
#
# Returns a {Boolean}.
isPathIgnored: (path) -> @getRepo().isIgnored(@relativize(path))
# Public: Returns true if the given status indicates modification.
isStatusModified: (status) -> @getRepo().isStatusModified(status)
# Public: Returns true if the given path is modified.
isPathModified: (path) -> @isStatusModified(@getPathStatus(path))
# Public: Returns true if the given status indicates a new path.
isStatusNew: (status) -> @getRepo().isStatusNew(status)
# Public: Returns true if the given path is new.
isPathNew: (path) -> @isStatusNew(@getPathStatus(path))
# Public: Returns true if at the root, false if in a subfolder of the
# repository.
isProjectAtRoot: ->
@projectAtRoot ?= @project?.relativize(@getWorkingDirectory()) is ''
# Public: Makes a path relative to the repository's working directory.
relativize: (path) -> @getRepo().relativize(path)
# Public: Retrieves a shortened version of the HEAD reference value.
#
# This removes the leading segments of `refs/heads`, `refs/tags`, or
# `refs/remotes`. It also shortens the SHA-1 of a detached `HEAD` to 7
# characters.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository contains submodules.
#
# Returns a {String}.
getShortHead: (path) -> @getRepo(path).getShortHead()
# Public: Restore the contents of a path in the working directory and index
# to the version at `HEAD`.
#
# This is essentially the same as running:
#
# ```sh
# git reset HEAD -- <path>
# git checkout HEAD -- <path>
# ```
#
# * `path` The {String} path to checkout.
#
# Returns a {Boolean} that's true if the method was successful.
checkoutHead: (path) ->
repo = @getRepo(path)
headCheckedOut = repo.checkoutHead(repo.relativize(path))
@getPathStatus(path) if headCheckedOut
headCheckedOut
# Public: Checks out a branch in your repository.
#
# * `reference` The {String} reference to checkout.
# * `create` A {Boolean} value which, if true creates the new reference if
# it doesn't exist.
#
# Returns a Boolean that's true if the method was successful.
checkoutReference: (reference, create) ->
@getRepo().checkoutReference(reference, create)
# Public: Retrieves the number of lines added and removed to a path.
#
# This compares the working directory contents of the path to the `HEAD`
# version.
#
# * `path` The {String} path to check.
#
# Returns an {Object} with the following keys:
# * `added` The {Number} of added lines.
# * `deleted` The {Number} of deleted lines.
getDiffStats: (path) ->
repo = @getRepo(path)
repo.getDiffStats(repo.relativize(path))
# Public: Is the given path a submodule in the repository?
#
# * `path` The {String} path to check.
#
# Returns a {Boolean}.
isSubmodule: (path) ->
return false unless path
repo = @getRepo(path)
if repo.isSubmodule(repo.relativize(path))
true
else
# Check if the path is a working directory in a repo that isn't the root.
repo isnt @getRepo() and repo.relativize(join(path, 'dir')) is 'dir'
# Public: Get the status of a directory in the repository's working directory.
#
# * `path` The {String} path to check.
#
# Returns a {Number} representing the status. This value can be passed to
# {::isStatusModified} or {::isStatusNew} to get more information.
getDirectoryStatus: (directoryPath) ->
directoryPath = "#{@relativize(directoryPath)}/"
directoryStatus = 0
for path, status of @statuses
directoryStatus |= status if path.indexOf(directoryPath) is 0
directoryStatus
# Public: Retrieves the line diffs comparing the `HEAD` version of the given
# path and the given text.
#
# * `path` The {String} path relative to the repository.
# * `text` The {String} to compare against the `HEAD` contents
#
# Returns an {Array} of hunk {Object}s with the following keys:
# * `oldStart` The line {Number} of the old hunk.
# * `newStart` The line {Number} of the new hunk.
# * `oldLines` The {Number} of lines in the old hunk.
# * `newLines` The {Number} of lines in the new hunk
getLineDiffs: (path, text) ->
# Ignore eol of line differences on windows so that files checked in as
# LF don't report every line modified when the text contains CRLF endings.
options = ignoreEolWhitespace: process.platform is 'win32'
repo = @getRepo(path)
repo.getLineDiffs(repo.relativize(path), text, options)
# Public: Returns the git configuration value specified by the key.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
getConfigValue: (key, path) -> @getRepo(path).getConfigValue(key)
# Public: Returns the origin url of the repository.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
getOriginUrl: (path) -> @getConfigValue('remote.origin.url', path)
# Public: Returns the upstream branch for the current HEAD, or null if there
# is no upstream branch for the current HEAD.
#
# * `path` An optional {String} path in the repo to get this information for,
# only needed if the repository contains submodules.
#
# Returns a {String} branch name such as `refs/remotes/origin/master`.
getUpstreamBranch: (path) -> @getRepo(path).getUpstreamBranch()
# Public: Returns the current {String} SHA for the given reference.
#
# * `reference` The {String} reference to get the target of.
# * `path` An optional {String} path in the repo to get the reference target
# for. Only needed if the repository contains submodules.
getReferenceTarget: (reference, path) ->
@getRepo(path).getReferenceTarget(reference)
# Public: Gets all the local and remote references.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
#
# Returns an {Object} with the following keys:
# * `heads` An {Array} of head reference names.
# * `remotes` An {Array} of remote reference names.
# * `tags` An {Array} of tag reference names.
getReferences: (path) -> @getRepo(path).getReferences()
# Public: Returns the number of commits behind the current branch is from the
# its upstream remote branch.
#
# * `reference` The {String} branch reference name.
# * `path` The {String} path in the repository to get this information for,
# only needed if the repository contains submodules.
getAheadBehindCount: (reference, path) ->
@getRepo(path).getAheadBehindCount(reference)
# Public: Get the cached ahead/behind commit counts for the current branch's
# upstream branch.
#
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
#
# Returns an {Object} with the following keys:
# * `ahead` The {Number} of commits ahead.
# * `behind` The {Number} of commits behind.
getCachedUpstreamAheadBehindCount: (path) ->
@getRepo(path).upstream ? @upstream
# Public: Get the cached status for the given path.
#
# * `path` A {String} path in the repository, relative or absolute.
#
# Returns a status {Number} or null if the path is not in the cache.
getCachedPathStatus: (path) ->
@statuses[@relativize(path)]
# Public: Returns true if the given branch exists.
hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")?
# Refreshes the current git status in an outside process and asynchronously
# updates the relevant properties.
refreshStatus: ->
+15
Ver Arquivo
@@ -0,0 +1,15 @@
module.exports =
class ItemRegistry
constructor: ->
@items = new WeakSet
addItem: (item) ->
if @hasItem(item)
throw new Error("The workspace can only contain one instance of item #{item}")
@items.add(item)
removeItem: (item) ->
@items.delete(item)
hasItem: (item) ->
@items.has(item)
+13 -8
Ver Arquivo
@@ -148,15 +148,20 @@ class LanguageMode
return unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(bufferRow).isComment()
startRow = bufferRow
for currentRow in [bufferRow-1..0]
break if @buffer.isRowBlank(currentRow)
break unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(currentRow).isComment()
startRow = currentRow
endRow = bufferRow
for currentRow in [bufferRow+1..@buffer.getLastRow()]
break if @buffer.isRowBlank(currentRow)
break unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(currentRow).isComment()
endRow = currentRow
if bufferRow > 0
for currentRow in [bufferRow-1..0]
break if @buffer.isRowBlank(currentRow)
break unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(currentRow).isComment()
startRow = currentRow
if bufferRow < @buffer.getLastRow()
for currentRow in [bufferRow+1..@buffer.getLastRow()]
break if @buffer.isRowBlank(currentRow)
break unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(currentRow).isComment()
endRow = currentRow
return [startRow, endRow] if startRow isnt endRow
rowRangeForCodeFoldAtBufferRow: (bufferRow) ->
+399
Ver Arquivo
@@ -0,0 +1,399 @@
{Range} = require 'text-buffer'
_ = require 'underscore-plus'
{Subscriber} = require 'emissary'
EmitterMixin = require('emissary').Emitter
{Emitter} = require 'event-kit'
Grim = require 'grim'
# Essential: Represents a buffer annotation that remains logically stationary
# even as the buffer changes. This is used to represent cursors, folds, snippet
# targets, misspelled words, and anything else that needs to track a logical
# location in the buffer over time.
#
# ### Marker Creation
#
# Use {Editor::markBufferRange} rather than creating Markers directly.
#
# ### Head and Tail
#
# Markers always have a *head* and sometimes have a *tail*. If you think of a
# marker as an editor selection, the tail is the part that's stationary and the
# head is the part that moves when the mouse is moved. A marker without a tail
# always reports an empty range at the head position. A marker with a head position
# greater than the tail is in a "normal" orientation. If the head precedes the
# tail the marker is in a "reversed" orientation.
#
# ### Validity
#
# Markers are considered *valid* when they are first created. Depending on the
# invalidation strategy you choose, certain changes to the buffer can cause a
# marker to become invalid, for example if the text surrounding the marker is
# deleted. The strategies, in order of descending fragility:
#
# * __never__: The marker is never marked as invalid. This is a good choice for
# markers representing selections in an editor.
# * __surround__: The marker is invalidated by changes that completely surround it.
# * __overlap__: The marker is invalidated by changes that surround the
# start or end of the marker. This is the default.
# * __inside__: The marker is invalidated by changes that extend into the
# inside of the marker. Changes that end at the marker's start or
# start at the marker's end do not invalidate the marker.
# * __touch__: The marker is invalidated by a change that touches the marked
# region in any way, including changes that end at the marker's
# start or start at the marker's end. This is the most fragile strategy.
#
# See {Editor::markBufferRange} for usage.
module.exports =
class Marker
EmitterMixin.includeInto(this)
Subscriber.includeInto(this)
bufferMarkerSubscription: null
oldHeadBufferPosition: null
oldHeadScreenPosition: null
oldTailBufferPosition: null
oldTailScreenPosition: null
wasValid: true
deferredChangeEvents: null
###
Section: Construction and Destruction
###
constructor: ({@bufferMarker, @displayBuffer}) ->
@emitter = new Emitter
@id = @bufferMarker.id
@oldHeadBufferPosition = @getHeadBufferPosition()
@oldHeadScreenPosition = @getHeadScreenPosition()
@oldTailBufferPosition = @getTailBufferPosition()
@oldTailScreenPosition = @getTailScreenPosition()
@wasValid = @isValid()
@subscribe @bufferMarker.onDidDestroy => @destroyed()
@subscribe @bufferMarker.onDidChange (event) => @notifyObservers(event)
# Essential: Destroys the marker, causing it to emit the 'destroyed' event. Once
# destroyed, a marker cannot be restored by undo/redo operations.
destroy: ->
@bufferMarker.destroy()
@unsubscribe()
# Essential: Creates and returns a new {Marker} with the same properties as this
# marker.
#
# * `properties` {Object}
copy: (properties) ->
@displayBuffer.getMarker(@bufferMarker.copy(properties).id)
###
Section: Event Subscription
###
# Essential: Invoke the given callback when the state of the marker changes.
#
# * `callback` {Function} to be called when the marker changes.
# * `event` {Object} with the following keys:
# * `oldHeadPosition` {Point} representing the former head position
# * `newHeadPosition` {Point} representing the new head position
# * `oldTailPosition` {Point} representing the former tail position
# * `newTailPosition` {Point} representing the new tail position
# * `wasValid` {Boolean} indicating whether the marker was valid before the change
# * `isValid` {Boolean} indicating whether the marker is now valid
# * `hadTail` {Boolean} indicating whether the marker had a tail before the change
# * `hasTail` {Boolean} indicating whether the marker now has a tail
# * `oldProperties` {Object} containing the marker's custom properties before the change.
# * `newProperties` {Object} containing the marker's custom properties after the change.
# * `textChanged` {Boolean} indicating whether this change was caused by a textual change
# to the buffer or whether the marker was manipulated directly via its public API.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChange: (callback) ->
@emitter.on 'did-change', callback
# Essential: Invoke the given callback when the marker is destroyed.
#
# * `callback` {Function} to be called when the marker is destroyed.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidDestroy: (callback) ->
@emitter.on 'did-destroy', callback
on: (eventName) ->
switch eventName
when 'changed'
Grim.deprecate("Use Marker::onDidChange instead")
when 'destroyed'
Grim.deprecate("Use Marker::onDidDestroy instead")
EmitterMixin::on.apply(this, arguments)
###
Section: Marker Details
###
# Essential: Returns a {Boolean} indicating whether the marker is valid. Markers can be
# invalidated when a region surrounding them in the buffer is changed.
isValid: ->
@bufferMarker.isValid()
# Essential: Returns a {Boolean} indicating whether the marker has been destroyed. A marker
# can be invalid without being destroyed, in which case undoing the invalidating
# operation would restore the marker. Once a marker is destroyed by calling
# {Marker::destroy}, no undo/redo operation can ever bring it back.
isDestroyed: ->
@bufferMarker.isDestroyed()
# Essential: Returns a {Boolean} indicating whether the head precedes the tail.
isReversed: ->
@bufferMarker.isReversed()
# Essential: Get the invalidation strategy for this marker.
#
# Valid values include: `never`, `surround`, `overlap`, `inside`, and `touch`.
#
# Returns a {String}.
getInvalidationStrategy: ->
@bufferMarker.getInvalidationStrategy()
# Essential: Returns an {Object} containing any custom properties associated with
# the marker.
getProperties: ->
@bufferMarker.getProperties()
getAttributes: ->
deprecate 'Use Marker::getProperties instead'
@getProperties()
# Essential: Merges an {Object} containing new properties into the marker's
# existing properties.
#
# * `properties` {Object}
setProperties: (properties) ->
@bufferMarker.setProperties(properties)
setAttributes: (properties) ->
deprecate 'Use Marker::getProperties instead'
@setProperties(properties)
matchesProperties: (attributes) ->
attributes = @displayBuffer.translateToBufferMarkerParams(attributes)
@bufferMarker.matchesParams(attributes)
matchesAttributes: (attributes) ->
deprecate 'Use Marker::matchesProperties instead'
@matchesProperties(attributes)
###
Section: Comparing to other markers
###
# Essential: Returns a {Boolean} indicating whether this marker is equivalent to
# another marker, meaning they have the same range and options.
#
# * `other` {Marker} other marker
isEqual: (other) ->
return false unless other instanceof @constructor
@bufferMarker.isEqual(other.bufferMarker)
# Essential: Compares this marker to another based on their ranges.
#
# * `other` {Marker}
#
# Returns a {Number}
compare: (other) ->
@bufferMarker.compare(other.bufferMarker)
###
Section: Managing the marker's range
###
# Essential: Gets the buffer range of the display marker.
#
# Returns a {Range}.
getBufferRange: ->
@bufferMarker.getRange()
# Essential: Modifies the buffer range of the display marker.
#
# * `bufferRange` The new {Range} to use
# * `properties` (optional) {Object} properties to associate with the marker.
# * `reversed` {Boolean} If true, the marker will to be in a reversed orientation.
setBufferRange: (bufferRange, properties) ->
@bufferMarker.setRange(bufferRange, properties)
# Essential: Gets the screen range of the display marker.
#
# Returns a {Range}.
getScreenRange: ->
@displayBuffer.screenRangeForBufferRange(@getBufferRange(), wrapAtSoftNewlines: true)
# Essential: Modifies the screen range of the display marker.
#
# * `screenRange` The new {Range} to use
# * `properties` (optional) {Object} properties to associate with the marker.
# * `reversed` {Boolean} If true, the marker will to be in a reversed orientation.
setScreenRange: (screenRange, options) ->
@setBufferRange(@displayBuffer.bufferRangeForScreenRange(screenRange), options)
# Essential: Retrieves the buffer position of the marker's start. This will always be
# less than or equal to the result of {Marker::getEndBufferPosition}.
#
# Returns a {Point}.
getStartBufferPosition: ->
@bufferMarker.getStartPosition()
# Essential: Retrieves the screen position of the marker's start. This will always be
# less than or equal to the result of {Marker::getEndScreenPosition}.
#
# Returns a {Point}.
getStartScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getStartBufferPosition(), wrapAtSoftNewlines: true)
# Essential: Retrieves the buffer position of the marker's end. This will always be
# greater than or equal to the result of {Marker::getStartBufferPosition}.
#
# Returns a {Point}.
getEndBufferPosition: ->
@bufferMarker.getEndPosition()
# Essential: Retrieves the screen position of the marker's end. This will always be
# greater than or equal to the result of {Marker::getStartScreenPosition}.
#
# Returns a {Point}.
getEndScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getEndBufferPosition(), wrapAtSoftNewlines: true)
# Extended: Retrieves the buffer position of the marker's head.
#
# Returns a {Point}.
getHeadBufferPosition: ->
@bufferMarker.getHeadPosition()
# Extended: Sets the buffer position of the marker's head.
#
# * `screenRange` The new {Point} to use
# * `properties` (optional) {Object} properties to associate with the marker.
setHeadBufferPosition: (bufferPosition, properties) ->
@bufferMarker.setHeadPosition(bufferPosition, properties)
# Extended: Retrieves the screen position of the marker's head.
#
# Returns a {Point}.
getHeadScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getHeadBufferPosition(), wrapAtSoftNewlines: true)
# Extended: Sets the screen position of the marker's head.
#
# * `screenRange` The new {Point} to use
# * `properties` (optional) {Object} properties to associate with the marker.
setHeadScreenPosition: (screenPosition, properties) ->
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, properties)
@setHeadBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, properties))
# Extended: Retrieves the buffer position of the marker's tail.
#
# Returns a {Point}.
getTailBufferPosition: ->
@bufferMarker.getTailPosition()
# Extended: Sets the buffer position of the marker's tail.
#
# * `screenRange` The new {Point} to use
# * `properties` (optional) {Object} properties to associate with the marker.
setTailBufferPosition: (bufferPosition) ->
@bufferMarker.setTailPosition(bufferPosition)
# Extended: Retrieves the screen position of the marker's tail.
#
# Returns a {Point}.
getTailScreenPosition: ->
@displayBuffer.screenPositionForBufferPosition(@getTailBufferPosition(), wrapAtSoftNewlines: true)
# Extended: Sets the screen position of the marker's tail.
#
# * `screenRange` The new {Point} to use
# * `properties` (optional) {Object} properties to associate with the marker.
setTailScreenPosition: (screenPosition, options) ->
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
@setTailBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options))
# Extended: Returns a {Boolean} indicating whether the marker has a tail.
hasTail: ->
@bufferMarker.hasTail()
# Extended: Plants the marker's tail at the current head position. After calling
# the marker's tail position will be its head position at the time of the
# call, regardless of where the marker's head is moved.
#
# * `properties` (optional) {Object} properties to associate with the marker.
plantTail: ->
@bufferMarker.plantTail()
# Extended: Removes the marker's tail. After calling the marker's head position
# will be reported as its current tail position until the tail is planted
# again.
#
# * `properties` (optional) {Object} properties to associate with the marker.
clearTail: (properties) ->
@bufferMarker.clearTail(properties)
###
Section: Private utility methods
###
# Returns a {String} representation of the marker
inspect: ->
"Marker(id: #{@id}, bufferRange: #{@getBufferRange()})"
destroyed: ->
delete @displayBuffer.markers[@id]
@emit 'destroyed'
@emitter.emit 'did-destroy'
@emitter.dispose()
notifyObservers: ({textChanged}) ->
textChanged ?= false
newHeadBufferPosition = @getHeadBufferPosition()
newHeadScreenPosition = @getHeadScreenPosition()
newTailBufferPosition = @getTailBufferPosition()
newTailScreenPosition = @getTailScreenPosition()
isValid = @isValid()
return if _.isEqual(isValid, @wasValid) and
_.isEqual(newHeadBufferPosition, @oldHeadBufferPosition) and
_.isEqual(newHeadScreenPosition, @oldHeadScreenPosition) and
_.isEqual(newTailBufferPosition, @oldTailBufferPosition) and
_.isEqual(newTailScreenPosition, @oldTailScreenPosition)
changeEvent = {
@oldHeadScreenPosition, newHeadScreenPosition,
@oldTailScreenPosition, newTailScreenPosition,
@oldHeadBufferPosition, newHeadBufferPosition,
@oldTailBufferPosition, newTailBufferPosition,
textChanged,
isValid
}
if @deferredChangeEvents?
@deferredChangeEvents.push(changeEvent)
else
@emit 'changed', changeEvent
@emitter.emit 'did-change', changeEvent
@oldHeadBufferPosition = newHeadBufferPosition
@oldHeadScreenPosition = newHeadScreenPosition
@oldTailBufferPosition = newTailBufferPosition
@oldTailScreenPosition = newTailScreenPosition
@wasValid = isValid
pauseChangeEvents: ->
@deferredChangeEvents = []
resumeChangeEvents: ->
if deferredChangeEvents = @deferredChangeEvents
@deferredChangeEvents = null
for event in deferredChangeEvents
@emit 'changed', event
@emitter.emit 'did-change', event
getPixelRange: ->
@displayBuffer.pixelRangeForScreenRange(@getScreenRange(), false)
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ ipc = require 'ipc'
CSON = require 'season'
fs = require 'fs-plus'
# Public: Provides a registry for menu items that you'd like to appear in the
# Extended: Provides a registry for menu items that you'd like to appear in the
# application menu.
#
# An instance of this class is always available as the `atom.menu` global.
+166 -142
Ver Arquivo
@@ -48,7 +48,7 @@ class PackageManager
Section: Event Subscription
###
# Essential: Invoke the given callback when all packages have been activated.
# Public: Invoke the given callback when all packages have been activated.
#
# * `callback` {Function}
#
@@ -56,7 +56,7 @@ class PackageManager
onDidLoadAll: (callback) ->
@emitter.on 'did-load-all', callback
# Essential: Invoke the given callback when all packages have been activated.
# Public: Invoke the given callback when all packages have been activated.
#
# * `callback` {Function}
#
@@ -75,10 +75,10 @@ class PackageManager
EmitterMixin::on.apply(this, arguments)
###
Section: Instance Methods
Section: Package system data
###
# Extended: Get the path to the apm command.
# Public: Get the path to the apm command.
#
# Return a {String} file path to apm.
getApmPath: ->
@@ -86,19 +86,43 @@ class PackageManager
commandName += '.cmd' if process.platform is 'win32'
@apmPath ?= path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', commandName)
# Extended: Get the paths being used to look for packages.
# Public: Get the paths being used to look for packages.
#
# Returns an {Array} of {String} directory paths.
getPackageDirPaths: ->
_.clone(@packageDirPaths)
getPackageState: (name) ->
@packageStates[name]
###
Section: General package data
###
setPackageState: (name, state) ->
@packageStates[name] = state
# Public: Resolve the given package name to a path on disk.
#
# * `name` - The {String} package name.
#
# Return a {String} folder path or undefined if it could not be resolved.
resolvePackagePath: (name) ->
return name if fs.isDirectorySync(name)
# Extended: Enable the package with the given name.
packagePath = fs.resolve(@packageDirPaths..., name)
return packagePath if fs.isDirectorySync(packagePath)
packagePath = path.join(@resourcePath, 'node_modules', name)
return packagePath if @hasAtomEngine(packagePath)
# Public: Is the package with the given name bundled with Atom?
#
# * `name` - The {String} package name.
#
# Returns a {Boolean}.
isBundledPackage: (name) ->
@getPackageDependencies().hasOwnProperty(name)
###
Section: Enabling and disabling packages
###
# Public: Enable the package with the given name.
#
# Returns the {Package} that was enabled or null if it isn't loaded.
enablePackage: (name) ->
@@ -106,7 +130,7 @@ class PackageManager
pack?.enable()
pack
# Extended: Disable the package with the given name.
# Public: Disable the package with the given name.
#
# Returns the {Package} that was disabled or null if it isn't loaded.
disablePackage: (name) ->
@@ -114,51 +138,23 @@ class PackageManager
pack?.disable()
pack
# Activate all the packages that should be activated.
activate: ->
for [activator, types] in @packageActivators
packages = @getLoadedPackagesForTypes(types)
activator.activatePackages(packages)
@emit 'activated'
@emitter.emit 'did-activate-all'
# Public: Is the package with the given name disabled?
#
# * `name` - The {String} package name.
#
# Returns a {Boolean}.
isPackageDisabled: (name) ->
_.include(atom.config.get('core.disabledPackages') ? [], name)
# another type of package manager can handle other package types.
# See ThemeManager
registerPackageActivator: (activator, types) ->
@packageActivators.push([activator, types])
###
Section: Accessing active packages
###
activatePackages: (packages) ->
@activatePackage(pack.name) for pack in packages
@observeDisabledPackages()
# Activate a single package by name
activatePackage: (name) ->
if pack = @getActivePackage(name)
Q(pack)
else
pack = @loadPackage(name)
pack.activate().then =>
@activePackages[pack.name] = pack
pack
# Deactivate all packages
deactivatePackages: ->
@deactivatePackage(pack.name) for pack in @getLoadedPackages()
@unobserveDisabledPackages()
# Deactivate the package with the given name
deactivatePackage: (name) ->
pack = @getLoadedPackage(name)
if @isPackageActive(name)
@setPackageState(pack.name, state) if state = pack.serialize?()
pack.deactivate()
delete @activePackages[pack.name]
# Essential: Get an {Array} of all the active {Package}s.
# Public: Get an {Array} of all the active {Package}s.
getActivePackages: ->
_.values(@activePackages)
# Essential: Get the active {Package} with the given name.
# Public: Get the active {Package} with the given name.
#
# * `name` - The {String} package name.
#
@@ -174,6 +170,91 @@ class PackageManager
isPackageActive: (name) ->
@getActivePackage(name)?
###
Section: Accessing loaded packages
###
# Public: Get an {Array} of all the loaded {Package}s
getLoadedPackages: ->
_.values(@loadedPackages)
# Get packages for a certain package type
#
# * `types` an {Array} of {String}s like ['atom', 'textmate'].
getLoadedPackagesForTypes: (types) ->
pack for pack in @getLoadedPackages() when pack.getType() in types
# Public: Get the loaded {Package} with the given name.
#
# * `name` - The {String} package name.
#
# Returns a {Package} or undefined.
getLoadedPackage: (name) ->
@loadedPackages[name]
# Public: Is the package with the given name loaded?
#
# * `name` - The {String} package name.
#
# Returns a {Boolean}.
isPackageLoaded: (name) ->
@getLoadedPackage(name)?
###
Section: Accessing available packages
###
# Public: Get an {Array} of {String}s of all the available package paths.
getAvailablePackagePaths: ->
packagePaths = []
for packageDirPath in @packageDirPaths
for packagePath in fs.listSync(packageDirPath)
packagePaths.push(packagePath) if fs.isDirectorySync(packagePath)
packagesPath = path.join(@resourcePath, 'node_modules')
for packageName, packageVersion of @getPackageDependencies()
packagePath = path.join(packagesPath, packageName)
packagePaths.push(packagePath) if fs.isDirectorySync(packagePath)
_.uniq(packagePaths)
# Public: Get an {Array} of {String}s of all the available package names.
getAvailablePackageNames: ->
_.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
# Public: Get an {Array} of {String}s of all the available package metadata.
getAvailablePackageMetadata: ->
packages = []
for packagePath in @getAvailablePackagePaths()
name = path.basename(packagePath)
metadata = @getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true)
packages.push(metadata)
packages
###
Section: Private
###
getPackageState: (name) ->
@packageStates[name]
setPackageState: (name, state) ->
@packageStates[name] = state
getPackageDependencies: ->
unless @packageDependencies?
try
metadataPath = path.join(@resourcePath, 'package.json')
{@packageDependencies} = JSON.parse(fs.readFileSync(metadataPath)) ? {}
@packageDependencies ?= {}
@packageDependencies
hasAtomEngine: (packagePath) ->
metadata = Package.loadMetadata(packagePath, true)
metadata?.engines?.atom?
unobserveDisabledPackages: ->
@disabledPackagesSubscription?.off()
@disabledPackagesSubscription = null
@@ -234,99 +315,42 @@ class PackageManager
else
throw new Error("No loaded package for name '#{name}'")
# Essential: Get the loaded {Package} with the given name.
#
# * `name` - The {String} package name.
#
# Returns a {Package} or undefined.
getLoadedPackage: (name) ->
@loadedPackages[name]
# Activate all the packages that should be activated.
activate: ->
for [activator, types] in @packageActivators
packages = @getLoadedPackagesForTypes(types)
activator.activatePackages(packages)
@emit 'activated'
@emitter.emit 'did-activate-all'
# Essential: Is the package with the given name loaded?
#
# * `name` - The {String} package name.
#
# Returns a {Boolean}.
isPackageLoaded: (name) ->
@getLoadedPackage(name)?
# another type of package manager can handle other package types.
# See ThemeManager
registerPackageActivator: (activator, types) ->
@packageActivators.push([activator, types])
# Essential: Get an {Array} of all the loaded {Package}s
getLoadedPackages: ->
_.values(@loadedPackages)
activatePackages: (packages) ->
@activatePackage(pack.name) for pack in packages
@observeDisabledPackages()
# Get packages for a certain package type
#
# * `types` an {Array} of {String}s like ['atom', 'textmate'].
getLoadedPackagesForTypes: (types) ->
pack for pack in @getLoadedPackages() when pack.getType() in types
# Activate a single package by name
activatePackage: (name) ->
if pack = @getActivePackage(name)
Q(pack)
else
pack = @loadPackage(name)
pack.activate().then =>
@activePackages[pack.name] = pack
pack
# Extended: Resolve the given package name to a path on disk.
#
# * `name` - The {String} package name.
#
# Return a {String} folder path or undefined if it could not be resolved.
resolvePackagePath: (name) ->
return name if fs.isDirectorySync(name)
# Deactivate all packages
deactivatePackages: ->
@deactivatePackage(pack.name) for pack in @getLoadedPackages()
@unobserveDisabledPackages()
packagePath = fs.resolve(@packageDirPaths..., name)
return packagePath if fs.isDirectorySync(packagePath)
packagePath = path.join(@resourcePath, 'node_modules', name)
return packagePath if @hasAtomEngine(packagePath)
# Essential: Is the package with the given name disabled?
#
# * `name` - The {String} package name.
#
# Returns a {Boolean}.
isPackageDisabled: (name) ->
_.include(atom.config.get('core.disabledPackages') ? [], name)
hasAtomEngine: (packagePath) ->
metadata = Package.loadMetadata(packagePath, true)
metadata?.engines?.atom?
# Extended: Is the package with the given name bundled with Atom?
#
# * `name` - The {String} package name.
#
# Returns a {Boolean}.
isBundledPackage: (name) ->
@getPackageDependencies().hasOwnProperty(name)
getPackageDependencies: ->
unless @packageDependencies?
try
metadataPath = path.join(@resourcePath, 'package.json')
{@packageDependencies} = JSON.parse(fs.readFileSync(metadataPath)) ? {}
@packageDependencies ?= {}
@packageDependencies
# Extended: Get an {Array} of {String}s of all the available package paths.
getAvailablePackagePaths: ->
packagePaths = []
for packageDirPath in @packageDirPaths
for packagePath in fs.listSync(packageDirPath)
packagePaths.push(packagePath) if fs.isDirectorySync(packagePath)
packagesPath = path.join(@resourcePath, 'node_modules')
for packageName, packageVersion of @getPackageDependencies()
packagePath = path.join(packagesPath, packageName)
packagePaths.push(packagePath) if fs.isDirectorySync(packagePath)
_.uniq(packagePaths)
# Extended: Get an {Array} of {String}s of all the available package names.
getAvailablePackageNames: ->
_.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
# Extended: Get an {Array} of {String}s of all the available package metadata.
getAvailablePackageMetadata: ->
packages = []
for packagePath in @getAvailablePackagePaths()
name = path.basename(packagePath)
metadata = @getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true)
packages.push(metadata)
packages
# Deactivate the package with the given name
deactivatePackage: (name) ->
pack = @getLoadedPackage(name)
if @isPackageActive(name)
@setPackageState(pack.name, state) if state = pack.serialize?()
pack.deactivate()
delete @activePackages[pack.name]
+5 -1
Ver Arquivo
@@ -273,7 +273,11 @@ class Package
@unsubscribeFromActivationEvents()
@deactivateResources()
@deactivateConfig()
@mainModule?.deactivate?() if @mainActivated
if @mainActivated
try
@mainModule?.deactivate?()
catch e
console.error "Error deactivating package '#{@name}'", e.stack
@emit 'deactivated'
@emitter.emit 'did-deactivate'
+2 -6
Ver Arquivo
@@ -16,10 +16,6 @@ class PaneAxisView extends View
afterAttach: ->
@container = @closest('.panes').view()
viewForModel: (model) ->
viewClass = model.getViewClass()
model._view ?= new viewClass(model)
onChildReplaced: ({index, oldChild, newChild}) =>
focusedElement = document.activeElement if @hasFocus()
@onChildRemoved({child: oldChild, index})
@@ -27,11 +23,11 @@ class PaneAxisView extends View
focusedElement?.focus() if document.activeElement is document.body
onChildAdded: ({child, index}) =>
view = @viewForModel(child)
view = @model.getView(child).__spacePenView
@insertAt(index, view)
onChildRemoved: ({child}) =>
view = @viewForModel(child)
view = @model.getView(child).__spacePenView
view.detach()
PaneView ?= require './pane-view'
if view instanceof PaneView and view.model.isDestroyed()
+3
Ver Arquivo
@@ -46,6 +46,9 @@ class PaneAxis extends Model
else
PaneRowView ?= require './pane-row-view'
getView: (object) ->
@container.getView(object)
getChildren: -> @children.slice()
getPanes: ->
+3 -8
Ver Arquivo
@@ -26,11 +26,6 @@ class PaneContainerView extends View
@subscriptions.add @model.observeRoot(@onRootChanged)
@subscriptions.add @model.onDidChangeActivePaneItem(@onActivePaneItemChanged)
viewForModel: (model) ->
if model?
viewClass = model.getViewClass()
model._view ?= new viewClass(model)
getRoot: ->
@children().first().view()
@@ -42,7 +37,7 @@ class PaneContainerView extends View
@trigger 'pane:removed', [oldRoot]
oldRoot?.detach()
if root?
view = @viewForModel(root)
view = @model.getView(root).__spacePenView
@append(view)
focusedElement?.focus()
else
@@ -88,7 +83,7 @@ class PaneContainerView extends View
@getActivePaneView()
getActivePaneView: ->
@viewForModel(@model.activePane)
@model.getView(@model.getActivePane()).__spacePenView
getActivePaneItem: ->
@model.getActivePaneItem()
@@ -97,7 +92,7 @@ class PaneContainerView extends View
@getActivePaneView()?.activeView
paneForUri: (uri) ->
@viewForModel(@model.paneForUri(uri))
@model.getView(@model.paneForUri(uri)).__spacePenView
focusNextPaneView: ->
@model.activateNextPane()
+23 -2
Ver Arquivo
@@ -3,6 +3,9 @@
{Emitter, CompositeDisposable} = require 'event-kit'
Serializable = require 'serializable'
Pane = require './pane'
ViewRegistry = require './view-registry'
ItemRegistry = require './item-registry'
PaneContainerView = null
module.exports =
class PaneContainer extends Model
@@ -27,6 +30,8 @@ class PaneContainer extends Model
@emitter = new Emitter
@subscriptions = new CompositeDisposable
@viewRegistry = params?.viewRegistry ? new ViewRegistry
@itemRegistry = new ItemRegistry
@setRoot(params?.root ? new Pane)
@destroyEmptyPanes() if params?.destroyEmptyPanes
@@ -43,6 +48,12 @@ class PaneContainer extends Model
root: @root?.serialize()
activePaneId: @activePane.id
getViewClass: ->
PaneContainerView ?= require './pane-container-view'
getView: (object) ->
@viewRegistry.getView(object)
onDidChangeRoot: (fn) ->
@emitter.on 'did-change-root', fn
@@ -169,7 +180,17 @@ class PaneContainer extends Model
monitorPaneItems: ->
@subscriptions.add @observePanes (pane) =>
for item, index in pane.getItems()
@emitter.emit 'did-add-pane-item', {item, pane, index}
@addedPaneItem(item, pane, index)
pane.onDidAddItem ({item, index}) =>
@emitter.emit 'did-add-pane-item', {item, pane, index}
@addedPaneItem(item, pane, index)
pane.onDidRemoveItem ({item}) =>
@removedPaneItem(item)
addedPaneItem: (item, pane, index) ->
@itemRegistry.addItem(item)
@emitter.emit 'did-add-pane-item', {item, pane, index}
removedPaneItem: (item) ->
@itemRegistry.removeItem(item)
+11 -31
Ver Arquivo
@@ -6,7 +6,7 @@ PropertyAccessors = require 'property-accessors'
Pane = require './pane'
# Extended: A container which can contains multiple items to be switched between.
# A container which can contains multiple items to be switched between.
#
# Items can be almost anything however most commonly they're {EditorView}s.
#
@@ -33,17 +33,9 @@ class PaneView extends View
previousActiveItem: null
initialize: (args...) ->
initialize: (@model) ->
@subscriptions = new CompositeDisposable
if args[0] instanceof Pane
@model = args[0]
else
@model = new Pane(items: args)
@model._view = this
@onItemAdded(item) for item in @items
@viewsByItem = new WeakMap()
@handleEvents()
handleEvents: ->
@@ -162,7 +154,7 @@ class PaneView extends View
deprecate 'Please return a Disposable object from your ::onDidChangeTitle method!' unless disposable?.dispose?
@activeItemDisposables.add(disposable) if disposable?.dispose?
else if item.on?
deprecate '::on methods for items are no longer supported. If you would like your item to title change behavior, please implement a ::onDidChangeTitle() method.'
deprecate '::on methods for items are no longer supported. If you would like your item to support title change behavior, please implement a ::onDidChangeTitle() method.'
disposable = item.on('title-changed', @activeItemTitleChanged)
@activeItemDisposables.add(disposable) if disposable?.dispose?
@@ -175,7 +167,7 @@ class PaneView extends View
item.on('modified-status-changed', @activeItemModifiedChanged)
@activeItemDisposables.add(disposable) if disposable?.dispose?
view = @viewForItem(item)
view = @model.getView(item).__spacePenView
otherView.hide() for otherView in @itemViews.children().not(view).views()
@itemViews.append(view) unless view.parent().is(@itemViews)
view.show() if @attached
@@ -189,8 +181,8 @@ class PaneView extends View
onItemRemoved: ({item, index, destroyed}) =>
if item instanceof $
viewToRemove = item
else if viewToRemove = @viewsByItem.get(item)
@viewsByItem.delete(item)
else
viewToRemove = @model.getView(item).__spacePenView
if viewToRemove?
if destroyed
@@ -213,27 +205,15 @@ class PaneView extends View
activeItemModifiedChanged: =>
@trigger 'pane:active-item-modified-status-changed'
viewForItem: (item) ->
return unless item?
if item instanceof $
item
else if view = @viewsByItem.get(item)
view
else
viewClass = item.getViewClass()
view = new viewClass(item)
@viewsByItem.set(item, view)
view
@::accessor 'activeView', -> @model.getView(@activeItem)?.__spacePenView
@::accessor 'activeView', -> @viewForItem(@activeItem)
splitLeft: (items...) -> @model.getView(@model.splitLeft({items})).__spacePenView
splitLeft: (items...) -> @model.splitLeft({items})._view
splitRight: (items...) -> @model.getView(@model.splitRight({items})).__spacePenView
splitRight: (items...) -> @model.splitRight({items})._view
splitUp: (items...) -> @model.getView(@model.splitUp({items})).__spacePenView
splitUp: (items...) -> @model.splitUp({items})._view
splitDown: (items...) -> @model.splitDown({items})._view
splitDown: (items...) -> @model.getView(@model.splitDown({items})).__spacePenView
# Public: Get the container view housing this pane.
#
+5 -1
Ver Arquivo
@@ -56,6 +56,9 @@ class Pane extends Model
# Called by the view layer to construct a view for this model.
getViewClass: -> PaneView ?= require './pane-view'
getView: (object) ->
@container.getView(object)
getParent: -> @parent
setParent: (@parent) -> @parent
@@ -377,8 +380,8 @@ class Pane extends Model
# * `index` {Number} indicating the index to which to move the item in the
# given pane.
moveItemToPane: (item, pane, index) ->
pane.addItem(item, index)
@removeItem(item)
pane.addItem(item, index)
# Public: Destroy the active item and activate the next item.
destroyActiveItem: ->
@@ -518,6 +521,7 @@ class Pane extends Model
destroyed: ->
@container.activateNextPane() if @isActive()
@emitter.emit 'did-destroy'
@emitter.dispose()
item.destroy?() for item in @items.slice()
###
+121 -99
Ver Arquivo
@@ -13,7 +13,7 @@ TextBuffer = require 'text-buffer'
Editor = require './editor'
Task = require './task'
Git = require './git'
GitRepository = require './git-repository'
# Extended: Represents a project that's opened in Atom.
#
@@ -23,14 +23,16 @@ class Project extends Model
atom.deserializers.add(this)
Serializable.includeInto(this)
# Public: Find the local path for the given repository URL.
#
# * `repoUrl` {String} url to a git repository
@pathForRepositoryUrl: (repoUrl) ->
deprecate '::pathForRepositoryUrl will be removed. Please remove from your code.'
[repoName] = url.parse(repoUrl).path.split('/')[-1..]
repoName = repoName.replace(/\.git$/, '')
path.join(atom.config.get('core.projectHome'), repoName)
###
Section: Construction and Destruction
###
constructor: ({path, @buffers}={}) ->
@buffers ?= []
@@ -40,14 +42,6 @@ class Project extends Model
@setPath(path)
serializeParams: ->
path: @path
buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained())
deserializeParams: (params) ->
params.buffers = params.buffers.map (bufferState) -> atom.deserializers.deserialize(bufferState)
params
destroyed: ->
buffer.destroy() for buffer in @getBuffers()
@destroyRepo()
@@ -60,9 +54,29 @@ class Project extends Model
destroyUnretainedBuffers: ->
buffer.destroy() for buffer in @getBuffers() when not buffer.isRetained()
# Public: Returns the {Git} repository if available.
###
Section: Serialization
###
serializeParams: ->
path: @path
buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained())
deserializeParams: (params) ->
params.buffers = params.buffers.map (bufferState) -> atom.deserializers.deserialize(bufferState)
params
###
Section: Accessing the git repository
###
# Public: Returns the {GitRepository} if available.
getRepo: -> @repo
###
Section: Managing Paths
###
# Public: Returns the project's {String} fullpath.
getPath: ->
@rootDirectory?.path
@@ -79,7 +93,7 @@ class Project extends Model
if projectPath?
directory = if fs.isDirectorySync(projectPath) then projectPath else path.dirname(projectPath)
@rootDirectory = new Directory(directory)
if @repo = Git.open(directory, project: this)
if @repo = GitRepository.open(directory, project: this)
@repo.refreshIndex()
@repo.refreshStatus()
else
@@ -124,6 +138,99 @@ class Project extends Model
contains: (pathToCheck) ->
@rootDirectory?.contains(pathToCheck) ? false
###
Section: Searching and Replacing
###
# Public: Performs a search across all the files in the project.
#
# * `regex` {RegExp} to search with.
# * `options` (optional) {Object} (default: {})
# * `paths` An {Array} of glob patterns to search within
# * `iterator` {Function} callback on each file found
scan: (regex, options={}, iterator) ->
if _.isFunction(options)
iterator = options
options = {}
deferred = Q.defer()
searchOptions =
ignoreCase: regex.ignoreCase
inclusions: options.paths
includeHidden: true
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
exclusions: atom.config.get('core.ignoredNames')
task = Task.once require.resolve('./scan-handler'), @getPath(), regex.source, searchOptions, ->
deferred.resolve()
task.on 'scan:result-found', (result) =>
iterator(result) unless @isPathModified(result.filePath)
task.on 'scan:file-error', (error) ->
iterator(null, error)
if _.isFunction(options.onPathsSearched)
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
options.onPathsSearched(numberOfPathsSearched)
for buffer in @getBuffers() when buffer.isModified()
filePath = buffer.getPath()
continue unless @contains(filePath)
matches = []
buffer.scan regex, (match) -> matches.push match
iterator {filePath, matches} if matches.length > 0
promise = deferred.promise
promise.cancel = ->
task.terminate()
deferred.resolve('cancelled')
promise
# Public: Performs a replace across all the specified files in the project.
#
# * `regex` A {RegExp} to search with.
# * `replacementText` Text to replace all matches of regex with
# * `filePaths` List of file path strings to run the replace on.
# * `iterator` A {Function} callback on each file with replacements:
# * `options` {Object} with keys `filePath` and `replacements`
replace: (regex, replacementText, filePaths, iterator) ->
deferred = Q.defer()
openPaths = (buffer.getPath() for buffer in @getBuffers())
outOfProcessPaths = _.difference(filePaths, openPaths)
inProcessFinished = !openPaths.length
outOfProcessFinished = !outOfProcessPaths.length
checkFinished = ->
deferred.resolve() if outOfProcessFinished and inProcessFinished
unless outOfProcessFinished.length
flags = 'g'
flags += 'i' if regex.ignoreCase
task = Task.once require.resolve('./replace-handler'), outOfProcessPaths, regex.source, flags, replacementText, ->
outOfProcessFinished = true
checkFinished()
task.on 'replace:path-replaced', iterator
task.on 'replace:file-error', (error) -> iterator(null, error)
for buffer in @getBuffers()
continue unless buffer.getPath() in filePaths
replacements = buffer.replace(regex, replacementText, iterator)
iterator({filePath: buffer.getPath(), replacements}) if replacements
inProcessFinished = true
checkFinished()
deferred.promise
###
Section: Private
###
# Given a path to a file, this constructs and associates a new
# {Editor}, showing the file.
#
@@ -222,91 +329,6 @@ class Project extends Model
[buffer] = @buffers.splice(index, 1)
buffer?.destroy()
# Public: Performs a search across all the files in the project.
#
# * `regex` {RegExp} to search with.
# * `options` (optional) {Object} (default: {})
# * `paths` An {Array} of glob patterns to search within
# * `iterator` {Function} callback on each file found
scan: (regex, options={}, iterator) ->
if _.isFunction(options)
iterator = options
options = {}
deferred = Q.defer()
searchOptions =
ignoreCase: regex.ignoreCase
inclusions: options.paths
includeHidden: true
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
exclusions: atom.config.get('core.ignoredNames')
task = Task.once require.resolve('./scan-handler'), @getPath(), regex.source, searchOptions, ->
deferred.resolve()
task.on 'scan:result-found', (result) =>
iterator(result) unless @isPathModified(result.filePath)
task.on 'scan:file-error', (error) ->
iterator(null, error)
if _.isFunction(options.onPathsSearched)
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
options.onPathsSearched(numberOfPathsSearched)
for buffer in @getBuffers() when buffer.isModified()
filePath = buffer.getPath()
continue unless @contains(filePath)
matches = []
buffer.scan regex, (match) -> matches.push match
iterator {filePath, matches} if matches.length > 0
promise = deferred.promise
promise.cancel = ->
task.terminate()
deferred.resolve('cancelled')
promise
# Public: Performs a replace across all the specified files in the project.
#
# * `regex` A {RegExp} to search with.
# * `replacementText` Text to replace all matches of regex with
# * `filePaths` List of file path strings to run the replace on.
# * `iterator` A {Function} callback on each file with replacements:
# * `options` {Object} with keys `filePath` and `replacements`
replace: (regex, replacementText, filePaths, iterator) ->
deferred = Q.defer()
openPaths = (buffer.getPath() for buffer in @getBuffers())
outOfProcessPaths = _.difference(filePaths, openPaths)
inProcessFinished = !openPaths.length
outOfProcessFinished = !outOfProcessPaths.length
checkFinished = ->
deferred.resolve() if outOfProcessFinished and inProcessFinished
unless outOfProcessFinished.length
flags = 'g'
flags += 'i' if regex.ignoreCase
task = Task.once require.resolve('./replace-handler'), outOfProcessPaths, regex.source, flags, replacementText, ->
outOfProcessFinished = true
checkFinished()
task.on 'replace:path-replaced', iterator
task.on 'replace:file-error', (error) -> iterator(null, error)
for buffer in @getBuffers()
continue unless buffer.getPath() in filePaths
replacements = buffer.replace(regex, replacementText, iterator)
iterator({filePath: buffer.getPath(), replacements}) if replacements
inProcessFinished = true
checkFinished()
deferred.promise
buildEditorForBuffer: (buffer, editorOptions) ->
editor = new Editor(_.extend({buffer, registerEditor: true}, editorOptions))
editor
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
{View} = require './space-pen-extensions'
# Public: Represents a view that scrolls.
# Extended: Represents a view that scrolls.
#
# Handles several core events to update scroll position:
#
+2
Ver Arquivo
@@ -9,9 +9,11 @@ ScrollbarComponent = React.createClass
render: ->
{orientation, className, scrollHeight, scrollWidth, visible} = @props
{scrollableInOppositeDirection, horizontalScrollbarHeight, verticalScrollbarWidth} = @props
{useHardwareAcceleration} = @props
style = {}
style.display = 'none' unless visible
style.transform = 'translateZ(0)' if useHardwareAcceleration # See atom/atom#3559
switch orientation
when 'vertical'
style.width = verticalScrollbarWidth
+130 -106
Ver Arquivo
@@ -46,7 +46,11 @@ class SelectListView extends View
inputThrottle: 50
cancelling: false
# Public: Initialize the select list view.
###
Section: Construction
###
# Essential: Initialize the select list view.
#
# This method can be overridden by subclasses but `super` should always
# be called.
@@ -85,13 +89,39 @@ class SelectListView extends View
@confirmSelection() if $(e.target).closest('li').hasClass('selected')
e.preventDefault()
schedulePopulateList: ->
clearTimeout(@scheduleTimeout)
populateCallback = =>
@populateList() if @isOnDom()
@scheduleTimeout = setTimeout(populateCallback, @inputThrottle)
###
Section: Methods that must be overridden
###
# Public: Set the array of items to display in the list.
# Essential: Create a view for the given model item.
#
# This method must be overridden by subclasses.
#
# This is called when the item is about to appended to the list view.
#
# * `item` The model item being rendered. This will always be one of the items
# previously passed to {::setItems}.
#
# Returns a String of HTML, DOM element, jQuery object, or View.
viewForItem: (item) ->
throw new Error("Subclass must implement a viewForItem(item) method")
# Essential: Callback function for when an item is selected.
#
# This method must be overridden by subclasses.
#
# * `item` The selected model item. This will always be one of the items
# previously passed to {::setItems}.
#
# Returns a DOM element, jQuery object, or {View}.
confirmed: (item) ->
throw new Error("Subclass must implement a confirmed(item) method")
###
Section: Managing the list of items
###
# Essential: Set the array of items to display in the list.
#
# This should be model items not actual views. {::viewForItem} will be
# called to render the item when it is being appended to the list view.
@@ -101,30 +131,26 @@ class SelectListView extends View
@populateList()
@setLoading()
# Public: Set the error message to display.
# Essential: Get the model item that is currently selected in the list view.
#
# * `message` The {String} error message (default: '').
setError: (message='') ->
if message.length is 0
@error.text('').hide()
else
@setLoading()
@error.text(message).show()
# Returns a model item.
getSelectedItem: ->
@getSelectedItemView().data('select-list-item')
# Public: Set the loading message to display.
# Extended: Get the property name to use when filtering items.
#
# * `message` The {String} loading message (default: '').
setLoading: (message='') ->
if message.length is 0
@loading.text("")
@loadingBadge.text("")
@loadingArea.hide()
else
@setError()
@loading.text(message)
@loadingArea.show()
# This method may be overridden by classes to allow fuzzy filtering based
# on a specific property of the item objects.
#
# For example if the objects you pass to {::setItems} are of the type
# `{"id": 3, "name": "Atom"}` then you would return `"name"` from this method
# to fuzzy filter by that property when text is entered into this view's
# editor.
#
# Returns the property name to fuzzy filter by.
getFilterKey: ->
# Public: Get the filter query to use when fuzzy filtering the visible
# Extended: Get the filter query to use when fuzzy filtering the visible
# elements.
#
# By default this method returns the text in the mini editor but it can be
@@ -134,7 +160,12 @@ class SelectListView extends View
getFilterQuery: ->
@filterEditorView.getEditor().getText()
# Public: Populate the list view with the model items previously set by
# Extended: Set the maximum numbers of items to display in the list.
#
# * `maxItems` The maximum {Number} of items to display.
setMaxItems: (@maxItems) ->
# Extended: Populate the list view with the model items previously set by
# calling {::setItems}.
#
# Subclasses may override this method but should always call `super`.
@@ -161,7 +192,34 @@ class SelectListView extends View
else
@setError(@getEmptyMessage(@items.length, filteredItems.length))
# Public: Get the message to display when there are no items.
###
Section: Messages to the user
###
# Essential: Set the error message to display.
#
# * `message` The {String} error message (default: '').
setError: (message='') ->
if message.length is 0
@error.text('').hide()
else
@setLoading()
@error.text(message).show()
# Essential: Set the loading message to display.
#
# * `message` The {String} loading message (default: '').
setLoading: (message='') ->
if message.length is 0
@loading.text("")
@loadingBadge.text("")
@loadingArea.hide()
else
@setError()
@loading.text(message)
@loadingArea.show()
# Extended: Get the message to display when there are no items.
#
# Subclasses may override this method to customize the message.
#
@@ -171,10 +229,36 @@ class SelectListView extends View
# Returns a {String} message (default: 'No matches found').
getEmptyMessage: (itemCount, filteredItemCount) -> 'No matches found'
# Public: Set the maximum numbers of items to display in the list.
###
Section: View Actions
###
# Essential: Cancel and close this select list view.
#
# * `maxItems` The maximum {Number} of items to display.
setMaxItems: (@maxItems) ->
# This restores focus to the previously focused element if
# {::storeFocusedElement} was called prior to this view being attached.
cancel: ->
@list.empty()
@cancelling = true
filterEditorViewFocused = @filterEditorView.isFocused
@cancelled()
@detach()
@restoreFocus() if filterEditorViewFocused
@cancelling = false
clearTimeout(@scheduleTimeout)
# Extended: Focus the fuzzy filter editor view.
focusFilterEditor: ->
@filterEditorView.focus()
# Extended: Store the currently focused element. This element will be given
# back focus when {::cancel} is called.
storeFocusedElement: ->
@previouslyFocusedElement = $(':focus')
###
Section: Private
###
selectPreviousItemView: ->
view = @getSelectedItemView().prev()
@@ -202,68 +286,6 @@ class SelectListView extends View
else if desiredBottom > @list.scrollBottom()
@list.scrollBottom(desiredBottom)
getSelectedItemView: ->
@list.find('li.selected')
# Public: Get the model item that is currently selected in the list view.
#
# Returns a model item.
getSelectedItem: ->
@getSelectedItemView().data('select-list-item')
confirmSelection: ->
item = @getSelectedItem()
if item?
@confirmed(item)
else
@cancel()
# Public: Create a view for the given model item.
#
# This method must be overridden by subclasses.
#
# This is called when the item is about to appended to the list view.
#
# * `item` The model item being rendered. This will always be one of the items
# previously passed to {::setItems}.
#
# Returns a String of HTML, DOM element, jQuery object, or View.
viewForItem: (item) ->
throw new Error("Subclass must implement a viewForItem(item) method")
# Public: Callback function for when an item is selected.
#
# This method must be overridden by subclasses.
#
# * `item` The selected model item. This will always be one of the items
# previously passed to {::setItems}.
#
# Returns a DOM element, jQuery object, or {View}.
confirmed: (item) ->
throw new Error("Subclass must implement a confirmed(item) method")
# Public: Get the property name to use when filtering items.
#
# This method may be overridden by classes to allow fuzzy filtering based
# on a specific property of the item objects.
#
# For example if the objects you pass to {::setItems} are of the type
# `{"id": 3, "name": "Atom"}` then you would return `"name"` from this method
# to fuzzy filter by that property when text is entered into this view's
# editor.
#
# Returns the property name to fuzzy filter by.
getFilterKey: ->
# Public: Focus the fuzzy filter editor view.
focusFilterEditor: ->
@filterEditorView.focus()
# Public: Store the currently focused element. This element will be given
# back focus when {::cancel} is called.
storeFocusedElement: ->
@previouslyFocusedElement = $(':focus')
restoreFocus: ->
if @previouslyFocusedElement?.isOnDom()
@previouslyFocusedElement.focus()
@@ -273,16 +295,18 @@ class SelectListView extends View
cancelled: ->
@filterEditorView.getEditor().setText('')
# Public: Cancel and close this select list view.
#
# This restores focus to the previously focused element if
# {::storeFocusedElement} was called prior to this view being attached.
cancel: ->
@list.empty()
@cancelling = true
filterEditorViewFocused = @filterEditorView.isFocused
@cancelled()
@detach()
@restoreFocus() if filterEditorViewFocused
@cancelling = false
getSelectedItemView: ->
@list.find('li.selected')
confirmSelection: ->
item = @getSelectedItem()
if item?
@confirmed(item)
else
@cancel()
schedulePopulateList: ->
clearTimeout(@scheduleTimeout)
populateCallback = =>
@populateList() if @isOnDom()
@scheduleTimeout = setTimeout(populateCallback, @inputThrottle)
+239 -200
Ver Arquivo
@@ -21,7 +21,7 @@ class Selection extends Model
@cursor.selection = this
@decoration = @editor.decorateMarker(@marker, type: 'highlight', class: 'selection')
@marker.onDidChange => @screenRangeChanged()
@marker.onDidChange (e) => @screenRangeChanged(e)
@marker.onDidDestroy =>
unless @editor.isDestroyed()
@destroyed = true
@@ -30,6 +30,9 @@ class Selection extends Model
@emitter.emit 'did-destroy'
@emitter.dispose()
destroy: ->
@marker.destroy()
###
Section: Event Subscription
###
@@ -37,7 +40,12 @@ class Selection extends Model
# Extended: Calls your `callback` when the selection was moved.
#
# * `callback` {Function}
# * `screenRange` {Range} indicating the new screenrange
# * `event` {Object}
# * `oldBufferRange` {Range}
# * `oldScreenRange` {Range}
# * `newBufferRange` {Range}
# * `newScreenRange` {Range}
# * `selection` {Selection} that triggered the event
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangeRange: (callback) ->
@@ -60,37 +68,11 @@ class Selection extends Model
super
###
Section: Methods
Section: Managing the selection range
###
destroy: ->
@marker.destroy()
finalize: ->
@initialScreenRange = null unless @initialScreenRange?.isEqual(@getScreenRange())
if @isEmpty()
@wordwise = false
@linewise = false
clearAutoscroll: ->
@needsAutoscroll = null
# Public: Determines if the selection contains anything.
isEmpty: ->
@getBufferRange().isEmpty()
# Public: Determines if the ending position of a marker is greater than the
# starting position.
#
# This can happen when, for example, you highlight text "up" in a {TextBuffer}.
isReversed: ->
@marker.isReversed()
# Public: Returns whether the selection is a single line or not.
isSingleScreenLine: ->
@getScreenRange().isSingleLine()
# Public: Returns the screen {Range} for the selection.
getScreenRange: ->
@marker.getScreenRange()
@@ -148,55 +130,61 @@ class Selection extends Model
getHeadBufferPosition: ->
@marker.getHeadBufferPosition()
autoscroll: ->
@editor.scrollToScreenRange(@getScreenRange())
###
Section: Info about the selection
###
# Public: Determines if the selection contains anything.
isEmpty: ->
@getBufferRange().isEmpty()
# Public: Determines if the ending position of a marker is greater than the
# starting position.
#
# This can happen when, for example, you highlight text "up" in a {TextBuffer}.
isReversed: ->
@marker.isReversed()
# Public: Returns whether the selection is a single line or not.
isSingleScreenLine: ->
@getScreenRange().isSingleLine()
# Public: Returns the text in the selection.
getText: ->
@editor.buffer.getTextInRange(@getBufferRange())
# Public: Identifies if a selection intersects with a given buffer range.
#
# * `bufferRange` A {Range} to check against.
#
# Returns a {Boolean}
intersectsBufferRange: (bufferRange) ->
@getBufferRange().intersectsWith(bufferRange)
intersectsScreenRowRange: (startRow, endRow) ->
@getScreenRange().intersectsRowRange(startRow, endRow)
intersectsScreenRow: (screenRow) ->
@getScreenRange().intersectsRow(screenRow)
# Public: Identifies if a selection intersects with another selection.
#
# * `otherSelection` A {Selection} to check against.
#
# Returns a {Boolean}
intersectsWith: (otherSelection, exclusive) ->
@getBufferRange().intersectsWith(otherSelection.getBufferRange(), exclusive)
###
Section: Modifying the selected range
###
# Public: Clears the selection, moving the marker to the head.
clear: ->
@marker.setAttributes(goalBufferRange: null)
@marker.setProperties(goalBufferRange: null)
@marker.clearTail() unless @retainSelection
@finalize()
# Public: Modifies the selection to encompass the current word.
#
# Returns a {Range}.
selectWord: ->
options = {}
options.wordRegex = /[\t ]*/ if @cursor.isSurroundedByWhitespace()
if @cursor.isBetweenWordAndNonWord()
options.includeNonWordCharacters = false
@setBufferRange(@cursor.getCurrentWordBufferRange(options))
@wordwise = true
@initialScreenRange = @getScreenRange()
# Public: Expands the newest selection to include the entire word on which
# the cursors rests.
expandOverWord: ->
@setBufferRange(@getBufferRange().union(@cursor.getCurrentWordBufferRange()))
# Public: Selects an entire line in the buffer.
#
# * `row` The line {Number} to select (default: the row of the cursor).
selectLine: (row=@cursor.getBufferPosition().row) ->
range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
@setBufferRange(@getBufferRange().union(range))
@linewise = true
@wordwise = false
@initialScreenRange = @getScreenRange()
# Public: Expands the newest selection to include the entire line on which
# the cursor currently rests.
#
# It also includes the newline character.
expandOverLine: ->
range = @getBufferRange().union(@cursor.getCurrentLineBufferRange(includeNewline: true))
@setBufferRange(range)
# Public: Selects the text from the current cursor position to a given screen
# position.
#
@@ -311,46 +299,45 @@ class Selection extends Model
selectToBeginningOfPreviousParagraph: ->
@modifySelection => @cursor.moveToBeginningOfPreviousParagraph()
# Public: Moves the selection down one row.
addSelectionBelow: ->
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
nextRow = range.end.row + 1
# Public: Modifies the selection to encompass the current word.
#
# Returns a {Range}.
selectWord: ->
options = {}
options.wordRegex = /[\t ]*/ if @cursor.isSurroundedByWhitespace()
if @cursor.isBetweenWordAndNonWord()
options.includeNonWordCharacters = false
for row in [nextRow..@editor.getLastBufferRow()]
range.start.row = row
range.end.row = row
clippedRange = @editor.clipBufferRange(range)
@setBufferRange(@cursor.getCurrentWordBufferRange(options))
@wordwise = true
@initialScreenRange = @getScreenRange()
if range.isEmpty()
continue if range.end.column > 0 and clippedRange.end.column is 0
else
continue if clippedRange.isEmpty()
# Public: Expands the newest selection to include the entire word on which
# the cursors rests.
expandOverWord: ->
@setBufferRange(@getBufferRange().union(@cursor.getCurrentWordBufferRange()))
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
# Public: Selects an entire line in the buffer.
#
# * `row` The line {Number} to select (default: the row of the cursor).
selectLine: (row=@cursor.getBufferPosition().row) ->
range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
@setBufferRange(@getBufferRange().union(range))
@linewise = true
@wordwise = false
@initialScreenRange = @getScreenRange()
# FIXME: I have no idea what this does.
getGoalBufferRange: ->
if goalBufferRange = @marker.getAttributes().goalBufferRange
Range.fromObject(goalBufferRange)
# Public: Expands the newest selection to include the entire line on which
# the cursor currently rests.
#
# It also includes the newline character.
expandOverLine: ->
range = @getBufferRange().union(@cursor.getCurrentLineBufferRange(includeNewline: true))
@setBufferRange(range)
# Public: Moves the selection up one row.
addSelectionAbove: ->
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
previousRow = range.end.row - 1
for row in [previousRow..0]
range.start.row = row
range.end.row = row
clippedRange = @editor.clipBufferRange(range)
if range.isEmpty()
continue if range.end.column > 0 and clippedRange.end.column is 0
else
continue if clippedRange.isEmpty()
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
###
Section: Modifying the selected text
###
# Public: Replaces text at the current selection.
#
@@ -391,71 +378,6 @@ class Selection extends Model
newBufferRange
# Public: Indents the given text to the suggested level based on the grammar.
#
# * `text` The {String} to indent within the selection.
# * `indentBasis` The beginning indent level.
normalizeIndents: (text, indentBasis) ->
textPrecedingCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferColumn()]
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
lines = text.split('\n')
firstLineIndentLevel = @editor.indentLevelForLine(lines[0])
if isCursorInsideExistingLine
minimumIndentLevel = @editor.indentationForBufferRow(@cursor.getBufferRow())
else
minimumIndentLevel = @cursor.getIndentLevel()
normalizedLines = []
for line, i in lines
if i == 0
indentLevel = 0
else if line == '' # remove all indentation from empty lines
indentLevel = 0
else
lineIndentLevel = @editor.indentLevelForLine(lines[i])
indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis)
normalizedLines.push(@setIndentationForLine(line, indentLevel))
normalizedLines.join('\n')
# Indent the current line(s).
#
# If the selection is empty, indents the current line if the cursor precedes
# non-whitespace characters, and otherwise inserts a tab. If the selection is
# non empty, calls {::indentSelectedRows}.
#
# * `options` (optional) {Object} with the keys:
# * `autoIndent` If `true`, the line is indented to an automatically-inferred
# level. Otherwise, {Editor::getTabText} is inserted.
indent: ({ autoIndent }={}) ->
{ row, column } = @cursor.getBufferPosition()
if @isEmpty()
@cursor.skipLeadingWhitespace()
desiredIndent = @editor.suggestedIndentForBufferRow(row)
delta = desiredIndent - @cursor.getIndentLevel()
if autoIndent and delta > 0
@insertText(@editor.buildIndentString(delta))
else
@insertText(@editor.buildIndentString(1, @cursor.getBufferColumn()))
else
@indentSelectedRows()
# Public: If the selection spans multiple rows, indent all of them.
indentSelectedRows: ->
[start, end] = @getBufferRowRange()
for row in [start..end]
@editor.buffer.insert([row, 0], @editor.getTabText()) unless @editor.buffer.lineLengthForRow(row) == 0
# Public: ?
setIndentationForLine: (line, indentLevel) ->
desiredIndentLevel = Math.max(0, indentLevel)
desiredIndentString = @editor.buildIndentString(desiredIndentLevel)
line.replace(/^[\t ]*/, desiredIndentString)
# Public: Removes the first character before the selection if the selection
# is empty otherwise it deletes the selection.
backspace: ->
@@ -632,41 +554,110 @@ class Selection extends Model
@editor.createFold(range.start.row, range.end.row)
@cursor.setBufferPosition([range.end.row + 1, 0])
modifySelection: (fn) ->
@retainSelection = true
@plantTail()
fn()
@retainSelection = false
# Public: Indents the given text to the suggested level based on the grammar.
#
# * `text` The {String} to indent within the selection.
# * `indentBasis` The beginning indent level.
normalizeIndents: (text, indentBasis) ->
textPrecedingCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferColumn()]
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
# Sets the marker's tail to the same position as the marker's head.
#
# This only works if there isn't already a tail position.
#
# Returns a {Point} representing the new tail position.
plantTail: ->
@marker.plantTail()
lines = text.split('\n')
firstLineIndentLevel = @editor.indentLevelForLine(lines[0])
if isCursorInsideExistingLine
minimumIndentLevel = @editor.indentationForBufferRow(@cursor.getBufferRow())
else
minimumIndentLevel = @cursor.getIndentLevel()
# Public: Identifies if a selection intersects with a given buffer range.
#
# * `bufferRange` A {Range} to check against.
#
# Returns a {Boolean}
intersectsBufferRange: (bufferRange) ->
@getBufferRange().intersectsWith(bufferRange)
normalizedLines = []
for line, i in lines
if i == 0
indentLevel = 0
else if line == '' # remove all indentation from empty lines
indentLevel = 0
else
lineIndentLevel = @editor.indentLevelForLine(lines[i])
indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis)
intersectsScreenRowRange: (startRow, endRow) ->
@getScreenRange().intersectsRowRange(startRow, endRow)
normalizedLines.push(@setIndentationForLine(line, indentLevel))
intersectsScreenRow: (screenRow) ->
@getScreenRange().intersectsRow(screenRow)
normalizedLines.join('\n')
# Public: Identifies if a selection intersects with another selection.
# Indent the current line(s).
#
# * `otherSelection` A {Selection} to check against.
# If the selection is empty, indents the current line if the cursor precedes
# non-whitespace characters, and otherwise inserts a tab. If the selection is
# non empty, calls {::indentSelectedRows}.
#
# Returns a {Boolean}
intersectsWith: (otherSelection, exclusive) ->
@getBufferRange().intersectsWith(otherSelection.getBufferRange(), exclusive)
# * `options` (optional) {Object} with the keys:
# * `autoIndent` If `true`, the line is indented to an automatically-inferred
# level. Otherwise, {Editor::getTabText} is inserted.
indent: ({ autoIndent }={}) ->
{ row, column } = @cursor.getBufferPosition()
if @isEmpty()
@cursor.skipLeadingWhitespace()
desiredIndent = @editor.suggestedIndentForBufferRow(row)
delta = desiredIndent - @cursor.getIndentLevel()
if autoIndent and delta > 0
delta = Math.max(delta, 1) unless @editor.getSoftTabs()
@insertText(@editor.buildIndentString(delta))
else
@insertText(@editor.buildIndentString(1, @cursor.getBufferColumn()))
else
@indentSelectedRows()
# Public: If the selection spans multiple rows, indent all of them.
indentSelectedRows: ->
[start, end] = @getBufferRowRange()
for row in [start..end]
@editor.buffer.insert([row, 0], @editor.getTabText()) unless @editor.buffer.lineLengthForRow(row) == 0
setIndentationForLine: (line, indentLevel) ->
desiredIndentLevel = Math.max(0, indentLevel)
desiredIndentString = @editor.buildIndentString(desiredIndentLevel)
line.replace(/^[\t ]*/, desiredIndentString)
###
Section: Managing multiple selections
###
# Public: Moves the selection down one row.
addSelectionBelow: ->
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
nextRow = range.end.row + 1
for row in [nextRow..@editor.getLastBufferRow()]
range.start.row = row
range.end.row = row
clippedRange = @editor.clipBufferRange(range)
if range.isEmpty()
continue if range.end.column > 0 and clippedRange.end.column is 0
else
continue if clippedRange.isEmpty()
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
# Public: Moves the selection up one row.
addSelectionAbove: ->
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
previousRow = range.end.row - 1
for row in [previousRow..0]
range.start.row = row
range.end.row = row
clippedRange = @editor.clipBufferRange(range)
if range.isEmpty()
continue if range.end.column > 0 and clippedRange.end.column is 0
else
continue if clippedRange.isEmpty()
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
# Public: Combines the given selection into this selection and then destroys
# the given selection.
@@ -683,6 +674,10 @@ class Selection extends Model
@setBufferRange(@getBufferRange().union(otherSelection.getBufferRange()), options)
otherSelection.destroy()
###
Section: Comparing to other selections
###
# Public: Compare this selection's buffer range to another selection's buffer
# range.
#
@@ -692,7 +687,51 @@ class Selection extends Model
compare: (otherSelection) ->
@getBufferRange().compare(otherSelection.getBufferRange())
screenRangeChanged: ->
@emit 'screen-range-changed', @getScreenRange()
###
Section: Private Utilities
###
screenRangeChanged: (e) ->
{oldHeadBufferPosition, oldTailBufferPosition} = e
{oldHeadScreenPosition, oldTailScreenPosition} = e
eventObject =
oldBufferRange: new Range(oldHeadBufferPosition, oldTailBufferPosition)
oldScreenRange: new Range(oldHeadScreenPosition, oldTailScreenPosition)
newBufferRange: @getBufferRange()
newScreenRange: @getScreenRange()
selection: this
@emit 'screen-range-changed', @getScreenRange() # old event
@emitter.emit 'did-change-range'
@editor.selectionRangeChanged(this)
@editor.selectionRangeChanged(eventObject)
finalize: ->
@initialScreenRange = null unless @initialScreenRange?.isEqual(@getScreenRange())
if @isEmpty()
@wordwise = false
@linewise = false
autoscroll: ->
@editor.scrollToScreenRange(@getScreenRange())
clearAutoscroll: ->
@needsAutoscroll = null
modifySelection: (fn) ->
@retainSelection = true
@plantTail()
fn()
@retainSelection = false
# Sets the marker's tail to the same position as the marker's head.
#
# This only works if there isn't already a tail position.
#
# Returns a {Point} representing the new tail position.
plantTail: ->
@marker.plantTail()
getGoalBufferRange: ->
if goalBufferRange = @marker.getProperties().goalBufferRange
Range.fromObject(goalBufferRange)
+1 -1
Ver Arquivo
@@ -9,7 +9,7 @@ PropertyAccessors = require 'property-accessors'
{$, $$} = require './space-pen-extensions'
Token = require './token'
# Public: Syntax class holding the grammars used for tokenizing.
# Extended: Syntax class holding the grammars used for tokenizing.
#
# An instance of this class is always available as the `atom.syntax` global.
#
+27 -3
Ver Arquivo
@@ -2,14 +2,38 @@ _ = require 'underscore-plus'
child_process = require 'child_process'
{Emitter} = require 'emissary'
# Public: Run a node script in a separate process.
# Extended: Run a node script in a separate process.
#
# Used by the fuzzy-finder.
# Used by the fuzzy-finder and [find in project](https://github.com/atom/atom/blob/master/src/scan-handler.coffee).
#
# For a real-world example, see the [scan-handler](https://github.com/atom/atom/blob/master/src/scan-handler.coffee)
# and the [instantiation of the task](https://github.com/atom/atom/blob/4a20f13162f65afc816b512ad7201e528c3443d7/src/project.coffee#L245).
#
# ## Examples
#
# In your package code:
#
# ```coffee
# {Task} = require 'atom'
#
# task = Task.once '/path/to/task-file.coffee', parameter1, parameter2, ->
# console.log 'task has finished'
#
# task.on 'some-event-from-the-task', (data) =>
# console.log data.someString # prints 'yep this is it'
# ```
#
# In `'/path/to/task-file.coffee'`:
#
# ```coffee
# module.exports = (parameter1, parameter2) ->
# # Indicates that this task will be async.
# # Call the `callback` to finish the task
# callback = @async()
#
# emit('some-event-from-the-task', {someString: 'yep this is it'})
#
# callback()
# ```
#
# ## Events
@@ -55,7 +79,7 @@ class Task
# receives a completion callback, this is overridden.
callback: null
# Public: Creates a task.
# Public: Creates a task. You should probably use {.once}
#
# * `taskPath` The {String} path to the CoffeeScript/JavaScript file that
# exports a single {Function} to execute.
+30 -17
Ver Arquivo
@@ -4,34 +4,47 @@ isHighSurrogate = (string, index) ->
isLowSurrogate = (string, index) ->
0xDC00 <= string.charCodeAt(index) <= 0xDFFF
isVariationSelector = (string, index) ->
0xFE00 <= string.charCodeAt(index) <= 0xFE0F
# Is the character at the given index the start of a high/low surrogate pair?
#
# string - The {String} to check for a surrogate pair.
# index - The {Number} index to look for a surrogate pair at.
# * `string` The {String} to check for a surrogate pair.
# * `index` The {Number} index to look for a surrogate pair at.
#
# Return a {Boolean}.
isSurrogatePair = (string, index=0) ->
isHighSurrogate(string, index) and isLowSurrogate(string, index + 1)
# Get the number of characters in the string accounting for surrogate pairs.
# Is the character at the given index the start of a variation sequence?
#
# This method counts high/low surrogate pairs as a single character and will
# always returns a value less than or equal to `string.length`.
# * `string` The {String} to check for a variation sequence.
# * `index` The {Number} index to look for a variation sequence at.
#
# string - The {String} to count the number of full characters in.
#
# Returns a {Number}.
getCharacterCount = (string) ->
count = string.length
count-- for index in [0...string.length] when isSurrogatePair(string, index)
count
# Return a {Boolean}.
isVariationSequence = (string, index=0) ->
not isVariationSelector(string, index) and isVariationSelector(string, index + 1)
# Does the given string contain at least one surrogate pair?
# Is the character at the given index the start of high/low surrogate pair
# or a variation sequence?
#
# string - The {String} to check for the presence of surrogate pairs.
# * `string` The {String} to check for a surrogate pair or variation sequence.
# * `index` The {Number} index to look for a surrogate pair at.
#
# Return a {Boolean}.
isPairedCharacter = (string, index=0) ->
isSurrogatePair(string, index) or isVariationSequence(string, index)
# Does the given string contain at least surrogate pair or variation sequence?
#
# * `string` The {String} to check for the presence of paired characters.
#
# Returns a {Boolean}.
hasSurrogatePair = (string) ->
string.length isnt getCharacterCount(string)
hasPairedCharacter = (string) ->
index = 0
while index < string.length
return true if isPairedCharacter(string, index)
index++
false
module.exports = {getCharacterCount, isSurrogatePair, hasSurrogatePair}
module.exports = {isPairedCharacter, hasPairedCharacter}
+107 -83
Ver Arquivo
@@ -20,6 +20,7 @@ class ThemeManager
constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode}) ->
@emitter = new Emitter
@lessCache = null
@initialLoadComplete = false
@packageManager.registerPackageActivator(this, ['theme'])
###
@@ -84,17 +85,29 @@ class ThemeManager
EmitterMixin::on.apply(this, arguments)
###
Section: Instance Methods
Section: Accessing Available Themes
###
getAvailableNames: ->
# TODO: Maybe should change to list all the available themes out there?
@getLoadedNames()
###
Section: Accessing Loaded Themes
###
# Public: Get an array of all the loaded theme names.
getLoadedNames: ->
theme.name for theme in @getLoadedThemes()
# Public: Get an array of all the loaded themes.
getLoadedThemes: ->
pack for pack in @packageManager.getLoadedPackages() when pack.isTheme()
###
Section: Accessing Active Themes
###
# Public: Get an array of all the active theme names.
getActiveNames: ->
theme.name for theme in @getActiveThemes()
@@ -103,13 +116,13 @@ class ThemeManager
getActiveThemes: ->
pack for pack in @packageManager.getActivePackages() when pack.isTheme()
# Public: Get an array of all the loaded themes.
getLoadedThemes: ->
pack for pack in @packageManager.getLoadedPackages() when pack.isTheme()
activatePackages: -> @activateThemes()
activatePackages: (themePackages) -> @activateThemes()
###
Section: Managing Enabled Themes
###
# Get the enabled theme names from the config.
# Public: Get the enabled theme names from the config.
#
# Returns an array of theme names in the order that they should be activated.
getEnabledThemeNames: ->
@@ -144,69 +157,15 @@ class ThemeManager
# the first/top theme to override later themes in the stack.
themeNames.reverse()
activateThemes: ->
deferred = Q.defer()
# atom.config.observe runs the callback once, then on subsequent changes.
atom.config.observe 'core.themes', =>
@deactivateThemes()
@refreshLessCache() # Update cache for packages in core.themes config
promises = []
for themeName in @getEnabledThemeNames()
if @packageManager.resolvePackagePath(themeName)
promises.push(@packageManager.activatePackage(themeName))
else
console.warn("Failed to activate theme '#{themeName}' because it isn't installed.")
Q.all(promises).then =>
@addActiveThemeClasses()
@refreshLessCache() # Update cache again now that @getActiveThemes() is populated
@loadUserStylesheet()
@reloadBaseStylesheets()
@emit 'reloaded'
@emitter.emit 'did-reload-all'
deferred.resolve()
deferred.promise
deactivateThemes: ->
@removeActiveThemeClasses()
@unwatchUserStylesheet()
@packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes()
null
addActiveThemeClasses: ->
for pack in @getActiveThemes()
atom.workspaceView?[0]?.classList.add("theme-#{pack.name}")
return
removeActiveThemeClasses: ->
for pack in @getActiveThemes()
atom.workspaceView?[0]?.classList.remove("theme-#{pack.name}")
return
refreshLessCache: ->
@lessCache?.setImportPaths(@getImportPaths())
# Public: Set the list of enabled themes.
#
# * `enabledThemeNames` An {Array} of {String} theme names.
setEnabledThemes: (enabledThemeNames) ->
atom.config.set('core.themes', enabledThemeNames)
getImportPaths: ->
activeThemes = @getActiveThemes()
if activeThemes.length > 0
themePaths = (theme.getStylesheetsPath() for theme in activeThemes when theme)
else
themePaths = []
for themeName in @getEnabledThemeNames()
if themePath = @packageManager.resolvePackagePath(themeName)
themePaths.push(path.join(themePath, Package.stylesheetsDir))
themePaths.filter (themePath) -> fs.isDirectorySync(themePath)
###
Section: Managing Stylesheets
###
# Public: Returns the {String} path to the user's stylesheet under ~/.atom
getUserStylesheetPath: ->
@@ -216,6 +175,23 @@ class ThemeManager
else
path.join(@configDirPath, 'styles.less')
# Public: Resolve and apply the stylesheet specified by the path.
#
# This supports both CSS and Less stylsheets.
#
# * `stylesheetPath` A {String} path to the stylesheet that can be an absolute
# path or a relative path that will be resolved against the load path.
#
# Returns the absolute path to the required stylesheet.
requireStylesheet: (stylesheetPath, type='bundled') ->
if fullPath = @resolveStylesheet(stylesheetPath)
content = @loadStylesheet(fullPath)
@applyStylesheet(fullPath, content, type)
else
throw new Error("Could not find a file at path '#{stylesheetPath}'")
fullPath
unwatchUserStylesheet: ->
@userStylesheetFile?.off()
@userStylesheetFile = null
@@ -251,23 +227,6 @@ class ThemeManager
else
fs.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
# Public: Resolve and apply the stylesheet specified by the path.
#
# This supports both CSS and Less stylsheets.
#
# * `stylesheetPath` A {String} path to the stylesheet that can be an absolute
# path or a relative path that will be resolved against the load path.
#
# Returns the absolute path to the required stylesheet.
requireStylesheet: (stylesheetPath, type='bundled') ->
if fullPath = @resolveStylesheet(stylesheetPath)
content = @loadStylesheet(fullPath)
@applyStylesheet(fullPath, content, type)
else
throw new Error("Could not find a file at path '#{stylesheetPath}'")
fullPath
loadStylesheet: (stylesheetPath, importFallbackVariables) ->
if path.extname(stylesheetPath) is '.less'
@loadLessStylesheet(stylesheetPath, importFallbackVariables)
@@ -296,9 +255,6 @@ class ThemeManager
#{error.message}
"""
stringToId: (string) ->
string.replace(/\\/g, '/')
removeStylesheet: (stylesheetPath) ->
fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath
element = @stylesheetElementForId(@stringToId(fullPath))
@@ -335,6 +291,74 @@ class ThemeManager
@emit 'stylesheets-changed'
@emitter.emit 'did-change-stylesheets'
###
Section: Private
###
stringToId: (string) ->
string.replace(/\\/g, '/')
activateThemes: ->
deferred = Q.defer()
# atom.config.observe runs the callback once, then on subsequent changes.
atom.config.observe 'core.themes', =>
@deactivateThemes()
@refreshLessCache() # Update cache for packages in core.themes config
promises = []
for themeName in @getEnabledThemeNames()
if @packageManager.resolvePackagePath(themeName)
promises.push(@packageManager.activatePackage(themeName))
else
console.warn("Failed to activate theme '#{themeName}' because it isn't installed.")
Q.all(promises).then =>
@addActiveThemeClasses()
@refreshLessCache() # Update cache again now that @getActiveThemes() is populated
@loadUserStylesheet()
@reloadBaseStylesheets()
@initialLoadComplete = true
@emit 'reloaded'
@emitter.emit 'did-reload-all'
deferred.resolve()
deferred.promise
deactivateThemes: ->
@removeActiveThemeClasses()
@unwatchUserStylesheet()
@packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes()
null
isInitialLoadComplete: -> @initialLoadComplete
addActiveThemeClasses: ->
for pack in @getActiveThemes()
atom.workspaceView?[0]?.classList.add("theme-#{pack.name}")
return
removeActiveThemeClasses: ->
for pack in @getActiveThemes()
atom.workspaceView?[0]?.classList.remove("theme-#{pack.name}")
return
refreshLessCache: ->
@lessCache?.setImportPaths(@getImportPaths())
getImportPaths: ->
activeThemes = @getActiveThemes()
if activeThemes.length > 0
themePaths = (theme.getStylesheetsPath() for theme in activeThemes when theme)
else
themePaths = []
for themeName in @getEnabledThemeNames()
if themePath = @packageManager.resolvePackagePath(themeName)
themePaths.push(path.join(themePath, Package.stylesheetsDir))
themePaths.filter (themePath) -> fs.isDirectorySync(themePath)
updateGlobalEditorStyle: (property, value) ->
unless styleNode = @stylesheetElementForId('global-editor-styles')
@applyStylesheet('global-editor-styles', '.editor {}')
+16 -14
Ver Arquivo
@@ -12,7 +12,7 @@ MaxTokenLength = 20000
module.exports =
class Token
value: null
hasSurrogatePair: false
hasPairedCharacter: false
scopes: null
isAtomic: null
isHardTab: null
@@ -23,7 +23,7 @@ class Token
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab}) ->
@screenDelta = @value.length
@bufferDelta ?= @screenDelta
@hasSurrogatePair = textUtils.hasSurrogatePair(@value)
@hasPairedCharacter = textUtils.hasPairedCharacter(@value)
isEqual: (other) ->
@value == other.value and _.isEqual(@scopes, other.scopes) and !!@isAtomic == !!other.isAtomic
@@ -57,11 +57,11 @@ class Token
WhitespaceRegexesByTabLength[tabLength] ?= new RegExp("([ ]{#{tabLength}})|(\t)|([^\t]+)", "g")
breakOutAtomicTokens: (tabLength, breakOutLeadingSoftTabs, startColumn) ->
if @hasSurrogatePair
if @hasPairedCharacter
outputTokens = []
column = startColumn
for token in @breakOutSurrogatePairs()
for token in @breakOutPairedCharacters()
if token.isAtomic
outputTokens.push(token)
else
@@ -98,27 +98,27 @@ class Token
outputTokens
breakOutSurrogatePairs: ->
breakOutPairedCharacters: ->
outputTokens = []
index = 0
nonSurrogatePairStart = 0
nonPairStart = 0
while index < @value.length
if textUtils.isSurrogatePair(@value, index)
if nonSurrogatePairStart isnt index
outputTokens.push(new Token({value: @value[nonSurrogatePairStart...index], @scopes}))
outputTokens.push(@buildSurrogatePairToken(@value, index))
if textUtils.isPairedCharacter(@value, index)
if nonPairStart isnt index
outputTokens.push(new Token({value: @value[nonPairStart...index], @scopes}))
outputTokens.push(@buildPairedCharacterToken(@value, index))
index += 2
nonSurrogatePairStart = index
nonPairStart = index
else
index++
if nonSurrogatePairStart isnt index
outputTokens.push(new Token({value: @value[nonSurrogatePairStart...index], @scopes}))
if nonPairStart isnt index
outputTokens.push(new Token({value: @value[nonPairStart...index], @scopes}))
outputTokens
buildSurrogatePairToken: (value, index) ->
buildPairedCharacterToken: (value, index) ->
new Token(
value: value[index..index + 1]
scopes: @scopes
@@ -153,6 +153,8 @@ class Token
getValueAsHtml: ({hasIndentGuide}) ->
if @isHardTab
classes = 'hard-tab'
classes += ' leading-whitespace' if @hasLeadingWhitespace()
classes += ' trailing-whitespace' if @hasTrailingWhitespace()
classes += ' indent-guide' if hasIndentGuide
classes += ' invisible-character' if @hasInvisibleCharacters
html = "<span class='#{classes}'>#{@escapeString(@value)}</span>"
+45
Ver Arquivo
@@ -0,0 +1,45 @@
{Disposable} = require 'event-kit'
{jQuery} = require './space-pen-extensions'
module.exports =
class ViewRegistry
constructor: ->
@views = new WeakMap
@providers = []
addViewProvider: (providerSpec) ->
@providers.push(providerSpec)
new Disposable =>
@providers = @providers.filter (provider) -> provider isnt providerSpec
getView: (object) ->
return unless object?
if view = @views.get(object)
view
else
view = @createView(object)
@views.set(object, view)
view
createView: (object) ->
if object instanceof HTMLElement
object
else if object instanceof jQuery
object[0].__spacePenView ?= object
object[0]
else if provider = @findProvider(object)
element = provider.createView?(object)
unless element?
element = new provider.viewConstructor
element.setModel(object)
element
else if viewConstructor = object?.getViewClass?()
view = new viewConstructor(object)
view[0].__spacePenView ?= view
view[0]
else
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
findProvider: (object) ->
@providers.find ({modelConstructor}) -> object instanceof modelConstructor
+271 -145
Ver Arquivo
@@ -15,7 +15,12 @@ PaneRowView = require './pane-row-view'
PaneContainerView = require './pane-container-view'
Editor = require './editor'
# Essential: The top-level view for the entire window. An instance of this class is
atom.commands.add '.workspace',
'window:increase-font-size': -> @getModel().increaseFontSize()
'window:decrease-font-size': -> @getModel().decreaseFontSize()
'window:reset-font-size': -> @getModel().resetFontSize()
# Extended: The top-level view for the entire window. An instance of this class is
# available via the `atom.workspaceView` global.
#
# It is backed by a model object, an instance of {Workspace}, which is available
@@ -77,10 +82,12 @@ class WorkspaceView extends View
@div class: 'vertical', outlet: 'vertical', =>
@div class: 'panes', outlet: 'panes'
initialize: (@model) ->
@model = atom.workspace ? new Workspace unless @model?
initialize: (model) ->
@model = model ? atom.workspace ? new Workspace unless @model?
@element.getModel = -> model
atom.commands.setRootNode(@[0])
panes = new PaneContainerView(@model.paneContainer)
panes = @model.getView(@model.paneContainer).__spacePenView
@panes.replaceWith(panes)
@panes = panes
@@ -136,12 +143,10 @@ class WorkspaceView extends View
@command 'application:open-your-stylesheet', -> ipc.send('command', 'application:open-your-stylesheet')
@command 'application:open-license', => @model.openLicense()
@command 'window:install-shell-commands', => @installShellCommands()
if process.platform is 'darwin'
@command 'window:install-shell-commands', => @installShellCommands()
@command 'window:run-package-specs', -> ipc.send('run-package-specs', path.join(atom.project.getPath(), 'spec'))
@command 'window:increase-font-size', => @increaseFontSize()
@command 'window:decrease-font-size', => @decreaseFontSize()
@command 'window:reset-font-size', => @model.resetFontSize()
@command 'window:focus-next-pane', => @focusNextPaneView()
@command 'window:focus-previous-pane', => @focusPreviousPaneView()
@@ -162,12 +167,175 @@ class WorkspaceView extends View
@command 'core:save', => @saveActivePaneItem()
@command 'core:save-as', => @saveActivePaneItemAs()
# Public: Get the underlying model object.
@deprecatedViewEvents()
###
Section: Accessing the Workspace Model
###
# Essential: Get the underlying model object.
#
# Returns a {Workspace}.
getModel: -> @model
# Public: Install the Atom shell commands on the user's system.
###
Section: Accessing Views
###
# Essential: Register a function to be called for every current and future
# editor view in the workspace (only includes {EditorView}s that are pane
# items).
#
# * `callback` A {Function} with an {EditorView} as its only argument.
# * `editorView` {EditorView}
#
# Returns a subscription object with an `.off` method that you can call to
# unregister the callback.
eachEditorView: (callback) ->
callback(editorView) for editorView in @getEditorViews()
attachedCallback = (e, editorView) ->
callback(editorView) unless editorView.mini
@on('editor:attached', attachedCallback)
off: => @off('editor:attached', attachedCallback)
# Essential: Register a function to be called for every current and future
# pane view in the workspace.
#
# * `callback` A {Function} with a {PaneView} as its only argument.
# * `paneView` {PaneView}
#
# Returns a subscription object with an `.off` method that you can call to
# unregister the callback.
eachPaneView: (callback) ->
@panes.eachPaneView(callback)
# Essential: Get all existing pane views.
#
# Prefer {Workspace::getPanes} if you don't need access to the view objects.
# Also consider using {::eachPaneView} if you want to register a callback for
# all current and *future* pane views.
#
# Returns an Array of all open {PaneView}s.
getPaneViews: ->
@panes.getPaneViews()
# Essential: Get the active pane view.
#
# Prefer {Workspace::getActivePane} if you don't actually need access to the
# view.
#
# Returns a {PaneView}.
getActivePaneView: ->
@panes.getActivePaneView()
# Essential: Get the view associated with the active pane item.
#
# Returns a view.
getActiveView: ->
@panes.getActiveView()
###
Section: Adding elements to the workspace
###
# Essential: Prepend an element or view to the panels at the top of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToTop: (element) ->
@vertical.prepend(element)
# Essential: Append an element or view to the panels at the top of the workspace.
#
# * `element` jQuery object or DOM element
appendToTop: (element) ->
@panes.before(element)
# Essential: Prepend an element or view to the panels at the bottom of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToBottom: (element) ->
@panes.after(element)
# Essential: Append an element or view to the panels at the bottom of the
# workspace.
#
# * `element` jQuery object or DOM element
appendToBottom: (element) ->
@vertical.append(element)
# Essential: Prepend an element or view to the panels at the left of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToLeft: (element) ->
@horizontal.prepend(element)
# Essential: Append an element or view to the panels at the left of the
# workspace.
#
# * `element` jQuery object or DOM element
appendToLeft: (element) ->
@vertical.before(element)
# Essential: Prepend an element or view to the panels at the right of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToRight: (element) ->
@vertical.after(element)
# Essential: Append an element or view to the panels at the right of the
# workspace.
#
# * `element` jQuery object or DOM element
appendToRight: (element) ->
@horizontal.append(element)
###
Section: Focusing pane views
###
# Focus the previous pane by id.
focusPreviousPaneView: -> @model.activatePreviousPane()
# Focus the next pane by id.
focusNextPaneView: -> @model.activateNextPane()
# Focus the pane directly above the active pane.
focusPaneViewAbove: -> @panes.focusPaneViewAbove()
# Focus the pane directly below the active pane.
focusPaneViewBelow: -> @panes.focusPaneViewBelow()
# Focus the pane directly to the left of the active pane.
focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft()
# Focus the pane directly to the right of the active pane.
focusPaneViewOnRight: -> @panes.focusPaneViewOnRight()
###
Section: Private
###
afterAttach: (onDom) ->
@focus() if onDom
# Called by SpacePen
beforeRemove: ->
@model.destroy()
setEditorFontSize: (fontSize) ->
atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
setEditorFontFamily: (fontFamily) ->
atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
setEditorLineHeight: (lineHeight) ->
atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
# Install the Atom shell commands on the user's system.
installShellCommands: ->
showErrorDialog = (error) ->
installDirectory = CommandInstaller.getInstallDirectory()
@@ -202,9 +370,6 @@ class WorkspaceView extends View
$(document.body).focus()
true
afterAttach: (onDom) ->
@focus() if onDom
# Prompts to save all unsaved items
confirmClose: ->
@panes.confirmClose()
@@ -243,143 +408,104 @@ class WorkspaceView extends View
for editorElement in @panes.element.querySelectorAll('.pane > .item-views > .editor')
$(editorElement).view()
# Public: Prepend an element or view to the panels at the top of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToTop: (element) ->
@vertical.prepend(element)
# Public: Append an element or view to the panels at the top of the workspace.
#
# * `element` jQuery object or DOM element
appendToTop: (element) ->
@panes.before(element)
###
Section: Deprecated
###
# Public: Prepend an element or view to the panels at the bottom of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToBottom: (element) ->
@panes.after(element)
deprecatedViewEvents: ->
originalWorkspaceViewOn = @on
# Public: Append an element or view to the panels at the bottom of the
# workspace.
#
# * `element` jQuery object or DOM element
appendToBottom: (element) ->
@vertical.append(element)
@on = (eventName) =>
switch eventName
when 'beep'
deprecate('Use Atom::onDidBeep instead')
when 'cursor:moved'
deprecate('Use Editor::onDidChangeCursorPosition instead')
when 'editor:attached'
deprecate('Use Editor::onDidAddTextEditor instead')
when 'editor:detached'
deprecate('Use Editor::onDidDestroy instead')
when 'editor:will-be-removed'
deprecate('Use Editor::onDidDestroy instead')
when 'pane:active-item-changed'
deprecate('Use Pane::onDidChangeActiveItem instead')
when 'pane:active-item-modified-status-changed'
deprecate('Use Pane::onDidChangeActiveItem and call onDidChangeModified on the active item instead')
when 'pane:active-item-title-changed'
deprecate('Use Pane::onDidChangeActiveItem and call onDidChangeTitle on the active item instead')
when 'pane:attached'
deprecate('Use Workspace::onDidAddPane instead')
when 'pane:became-active'
deprecate('Use Pane::onDidActivate instead')
when 'pane:became-inactive'
deprecate('Use Pane::onDidChangeActive instead')
when 'pane:item-added'
deprecate('Use Pane::onDidAddItem instead')
when 'pane:item-moved'
deprecate('Use Pane::onDidMoveItem instead')
when 'pane:item-removed'
deprecate('Use Pane::onDidRemoveItem instead')
when 'pane:removed'
deprecate('Use Pane::onDidDestroy instead')
when 'pane-container:active-pane-item-changed'
deprecate('Use Workspace::onDidChangeActivePaneItem instead')
when 'selection:changed'
deprecate('Use Editor::onDidChangeSelectionRange instead')
when 'uri-opened'
deprecate('Use Workspace::onDidOpen instead')
originalWorkspaceViewOn.apply(this, arguments)
# Public: Prepend an element or view to the panels at the left of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToLeft: (element) ->
@horizontal.prepend(element)
EditorView = require './editor-view'
originalEditorViewOn = EditorView::on
EditorView::on = (eventName) ->
switch eventName
when 'cursor:moved'
deprecate('Use Editor::onDidChangeCursorPosition instead')
when 'editor:attached'
deprecate('Use Editor::onDidAddTextEditor instead')
when 'editor:detached'
deprecate('Use Editor::onDidDestroy instead')
when 'editor:will-be-removed'
deprecate('Use Editor::onDidDestroy instead')
when 'selection:changed'
deprecate('Use Editor::onDidChangeSelectionRange instead')
originalEditorViewOn.apply(this, arguments)
# Public: Append an element or view to the panels at the left of the
# workspace.
#
# * `element` jQuery object or DOM element
appendToLeft: (element) ->
@vertical.before(element)
# Public: Prepend an element or view to the panels at the right of the
# workspace.
#
# * `element` jQuery object or DOM element
prependToRight: (element) ->
@vertical.after(element)
# Public: Append an element or view to the panels at the right of the
# workspace.
#
# * `element` jQuery object or DOM element
appendToRight: (element) ->
@horizontal.append(element)
# Public: Get the active pane view.
#
# Prefer {Workspace::getActivePane} if you don't actually need access to the
# view.
#
# Returns a {PaneView}.
getActivePaneView: ->
@panes.getActivePaneView()
# Public: Get the view associated with the active pane item.
#
# Returns a view.
getActiveView: ->
@panes.getActiveView()
# Focus the previous pane by id.
focusPreviousPaneView: -> @model.activatePreviousPane()
# Focus the next pane by id.
focusNextPaneView: -> @model.activateNextPane()
# Public: Focus the pane directly above the active pane.
focusPaneViewAbove: -> @panes.focusPaneViewAbove()
# Public: Focus the pane directly below the active pane.
focusPaneViewBelow: -> @panes.focusPaneViewBelow()
# Public: Focus the pane directly to the left of the active pane.
focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft()
# Public: Focus the pane directly to the right of the active pane.
focusPaneViewOnRight: -> @panes.focusPaneViewOnRight()
# Public: Register a function to be called for every current and future
# pane view in the workspace.
#
# * `callback` A {Function} with a {PaneView} as its only argument.
# * `paneView` {PaneView}
#
# Returns a subscription object with an `.off` method that you can call to
# unregister the callback.
eachPaneView: (callback) ->
@panes.eachPaneView(callback)
# Public: Get all existing pane views.
#
# Prefer {Workspace::getPanes} if you don't need access to the view objects.
# Also consider using {::eachPaneView} if you want to register a callback for
# all current and *future* pane views.
#
# Returns an Array of all open {PaneView}s.
getPaneViews: ->
@panes.getPaneViews()
# Public: Register a function to be called for every current and future
# editor view in the workspace (only includes {EditorView}s that are pane
# items).
#
# * `callback` A {Function} with an {EditorView} as its only argument.
# * `editorView` {EditorView}
#
# Returns a subscription object with an `.off` method that you can call to
# unregister the callback.
eachEditorView: (callback) ->
callback(editorView) for editorView in @getEditorViews()
attachedCallback = (e, editorView) ->
callback(editorView) unless editorView.mini
@on('editor:attached', attachedCallback)
off: => @off('editor:attached', attachedCallback)
# Called by SpacePen
beforeRemove: ->
@model.destroy()
setEditorFontSize: (fontSize) =>
atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
setEditorFontFamily: (fontFamily) =>
atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
setEditorLineHeight: (lineHeight) =>
atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
originalPaneViewOn = PaneView::on
PaneView::on = (eventName) ->
switch eventName
when 'cursor:moved'
deprecate('Use Editor::onDidChangeCursorPosition instead')
when 'editor:attached'
deprecate('Use Editor::onDidAddTextEditor instead')
when 'editor:detached'
deprecate('Use Editor::onDidDestroy instead')
when 'editor:will-be-removed'
deprecate('Use Editor::onDidDestroy instead')
when 'pane:active-item-changed'
deprecate('Use Pane::onDidChangeActiveItem instead')
when 'pane:active-item-modified-status-changed'
deprecate('Use Pane::onDidChangeActiveItem and call onDidChangeModified on the active item instead')
when 'pane:active-item-title-changed'
deprecate('Use Pane::onDidChangeActiveItem and call onDidChangeTitle on the active item instead')
when 'pane:attached'
deprecate('Use Workspace::onDidAddPane instead')
when 'pane:became-active'
deprecate('Use Pane::onDidActivate instead')
when 'pane:became-inactive'
deprecate('Use Pane::onDidChangeActive instead')
when 'pane:item-added'
deprecate('Use Pane::onDidAddItem instead')
when 'pane:item-moved'
deprecate('Use Pane::onDidMoveItem instead')
when 'pane:item-removed'
deprecate('Use Pane::onDidRemoveItem instead')
when 'pane:removed'
deprecate('Use Pane::onDidDestroy instead')
when 'selection:changed'
deprecate('Use Editor::onDidChangeSelectionRange instead')
originalPaneViewOn.apply(this, arguments)
# Deprecated
eachPane: (callback) ->
+165 -45
Ver Arquivo
@@ -9,8 +9,10 @@ Delegator = require 'delegato'
Editor = require './editor'
PaneContainer = require './pane-container'
Pane = require './pane'
ViewRegistry = require './view-registry'
WorkspaceView = null
# Public: Represents the state of the user interface for the entire window.
# Essential: Represents the state of the user interface for the entire window.
# An instance of this class is available via the `atom.workspace` global.
#
# Interact with this object to open files, be notified of current and future
@@ -27,7 +29,7 @@ class Workspace extends Model
@delegatesProperty 'activePane', 'activePaneItem', toProperty: 'paneContainer'
@properties
paneContainer: -> new PaneContainer
paneContainer: null
fullScreen: false
destroyedItemUris: -> []
@@ -37,6 +39,8 @@ class Workspace extends Model
@emitter = new Emitter
@openers = []
@viewRegistry ?= new ViewRegistry
@paneContainer ?= new PaneContainer({@viewRegistry})
@paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed)
@registerOpener (filePath) =>
@@ -55,6 +59,8 @@ class Workspace extends Model
for packageName in params.packagesWithActiveGrammars ? []
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
params.viewRegistry = new ViewRegistry
params.paneContainer.viewRegistry = params.viewRegistry
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
params
@@ -64,6 +70,9 @@ class Workspace extends Model
fullScreen: atom.isFullScreen()
packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars()
getViewClass: ->
WorkspaceView ?= require './workspace-view'
getPackageNamesWithActiveGrammars: ->
packageNames = []
addGrammar = ({includedGrammarScopes, packageName}={}) ->
@@ -91,6 +100,52 @@ class Workspace extends Model
Section: Event Subscription
###
# Essential: Invoke the given callback with all current and future text
# editors in the workspace.
#
# * `callback` {Function} to be called with current and future text editors.
# * `editor` An {Editor} that is present in {::getTextEditors} at the time
# of subscription or that is added at some later time.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observeTextEditors: (callback) ->
callback(textEditor) for textEditor in @getTextEditors()
@onDidAddTextEditor ({textEditor}) -> callback(textEditor)
# Essential: Invoke the given callback with all current and future panes items in
# the workspace.
#
# * `callback` {Function} to be called with current and future pane items.
# * `item` An item that is present in {::getPaneItems} at the time of
# subscription or that is added at some later time.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observePaneItems: (callback) -> @paneContainer.observePaneItems(callback)
# Essential: Invoke the given callback when the active pane item changes.
#
# * `callback` {Function} to be called when the active pane item changes.
# * `event` {Object} with the following keys:
# * `activeItem` The active pane item.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangeActivePaneItem: (callback) -> @paneContainer.onDidChangeActivePaneItem(callback)
# Essential: Invoke the given callback whenever an item is opened. Unlike
# {::onDidAddPaneItem}, observers will be notified for items that are already
# present in the workspace when they are reopened.
#
# * `callback` {Function} to be called whenever an item is opened.
# * `event` {Object} with the following keys:
# * `uri` {String} representing the opened URI. Could be `undefined`.
# * `item` The opened item.
# * `pane` The pane in which the item was opened.
# * `index` The index of the opened item on its pane.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidOpen: (callback) ->
@emitter.on 'did-open', callback
# Extended: Invoke the given callback when a pane is added to the workspace.
#
# * `callback` {Function} to be called panes are added.
@@ -110,10 +165,28 @@ class Workspace extends Model
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observePanes: (callback) -> @paneContainer.observePanes(callback)
# Extended: Invoke the given callback when the active pane changes.
#
# * `callback` {Function} to be called when the active pane changes.
# * `pane` A {Pane} that is the current return value of {::getActivePane}.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangeActivePane: (callback) -> @paneContainer.onDidChangeActivePane(callback)
# Extended: Invoke the given callback with the current active pane and when
# the active pane changes.
#
# * `callback` {Function} to be called with the current and future active#
# panes.
# * `pane` A {Pane} that is the current return value of {::getActivePane}.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observeActivePane: (callback) -> @paneContainer.observeActivePane(callback)
# Extended: Invoke the given callback when a pane item is added to the
# workspace.
#
# * `callback` {Function} to be called panes are added.
# * `callback` {Function} to be called when panes are added.
# * `event` {Object} with the following keys:
# * `item` The added pane item.
# * `pane` {Pane} containing the added item.
@@ -122,16 +195,6 @@ class Workspace extends Model
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidAddPaneItem: (callback) -> @paneContainer.onDidAddPaneItem(callback)
# Extended: Invoke the given callback with all current and future panes items in
# the workspace.
#
# * `callback` {Function} to be called with current and future pane items.
# * `item` An item that is present in {::getPaneItems} at the time of
# subscription or that is added at some later time.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observePaneItems: (callback) -> @paneContainer.observePaneItems(callback)
# Extended: Invoke the given callback when a text editor is added to the
# workspace.
#
@@ -147,33 +210,6 @@ class Workspace extends Model
@onDidAddPaneItem ({item, pane, index}) ->
callback({textEditor: item, pane, index}) if item instanceof Editor
# Essential: Invoke the given callback with all current and future text
# editors in the workspace.
#
# * `callback` {Function} to be called with current and future text editors.
# * `editor` An {Editor} that is present in {::getTextEditors} at the time
# of subscription or that is added at some later time.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observeTextEditors: (callback) ->
callback(textEditor) for textEditor in @getTextEditors()
@onDidAddTextEditor ({textEditor}) -> callback(textEditor)
# Essential: Invoke the given callback whenever an item is opened. Unlike
# ::onDidAddPaneItem, observers will be notified for items that are already
# present in the workspace when they are reopened.
#
# * `callback` {Function} to be called whenever an item is opened.
# * `event` {Object} with the following keys:
# * `uri` {String} representing the opened URI. Could be `undefined`.
# * `item` The opened item.
# * `pane` The pane in which the item was opened.
# * `index` The index of the opened item on its pane.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidOpen: (callback) ->
@emitter.on 'did-open', callback
eachEditor: (callback) ->
deprecate("Use Workspace::observeTextEditors instead")
@@ -296,7 +332,7 @@ class Workspace extends Model
.catch (error) ->
console.error(error.stack ? error)
# Extended: Asynchronously reopens the last-closed item's URI if it hasn't already been
# Public: Asynchronously reopens the last-closed item's URI if it hasn't already been
# reopened.
#
# Returns a promise that is resolved when the item is opened
@@ -312,7 +348,9 @@ class Workspace extends Model
if uri = @destroyedItemUris.pop()
@openSync(uri)
# Extended: Register an opener for a uri.
# TODO: make ::registerOpener() return a disposable
# Public: Register an opener for a uri.
#
# An {Editor} will be used if no openers return a value.
#
@@ -328,7 +366,7 @@ class Workspace extends Model
registerOpener: (opener) ->
@openers.push(opener)
# Extended: Unregister an opener registered with {::registerOpener}.
# Unregister an opener registered with {::registerOpener}.
unregisterOpener: (opener) ->
_.remove(@openers, opener)
@@ -362,14 +400,14 @@ class Workspace extends Model
# Returns an {Editor} or `undefined` if the current active item is not an
# {Editor}.
getActiveTextEditor: ->
activeItem = @getActiveItem()
activeItem = @getActivePaneItem()
activeItem if activeItem instanceof Editor
# Deprecated:
getActiveEditor: ->
@activePane?.getActiveEditor()
# Extended: Save all pane items.
# Save all pane items.
saveAll: ->
@paneContainer.saveAll()
@@ -459,3 +497,85 @@ class Workspace extends Model
# Called by Model superclass when destroyed
destroyed: ->
@paneContainer.destroy()
###
Section: View Management
###
# Essential: Get the view associated with an object in the workspace.
#
# If you're just *using* the workspace, you shouldn't need to access the view
# layer, but view layer access may be necessary if you want to perform DOM
# manipulation that isn't supported via the model API.
#
# ## Examples
#
# ### Getting An Editor View
# ```coffee
# textEditor = atom.workspace.getActiveTextEditor()
# textEditorView = atom.workspace.getView(textEditor)
# ```
#
# ### Getting A Pane View
# ```coffee
# pane = atom.workspace.getActivePane()
# paneView = atom.workspace.getView(pane)
# ```
#
# ### Getting The Workspace View
#
# ```coffee
# workspaceView = atom.workspace.getView(atom.workspace)
# ```
#
# * `object` The object for which you want to retrieve a view. This can be a
# pane item, a pane, or the workspace itself.
#
# Returns a DOM element.
getView: (object) ->
@viewRegistry.getView(object)
# Essential: Add a provider that will be used to construct views in the
# workspace's view layer based on model objects in its model layer.
#
# If you're adding your own kind of pane item, a good strategy for all but the
# simplest items is to separate the model and the view. The model handles
# application logic and is the primary point of API interaction. The view
# just handles presentation.
#
# Use view providers to inform the workspace how your model objects should be
# presented in the DOM. A view provider must always return a DOM node, which
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
# an ideal tool for implementing views in Atom.
#
# ## Example
#
# Text editors are divided into a model and a view layer, so when you interact
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
# to get the model object. We display text editors on screen by teaching the
# workspace what view constructor it should use to represent them:
#
# ```coffee
# atom.workspace.addViewProvider
# modelConstructor: TextEditor
# viewConstructor: TextEditorElement
# ```
#
# * `providerSpec` {Object} containing the following keys:
# * `modelConstructor` Constructor {Function} for your model.
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
# should be a subclass of `HTMLElement` (that is, your view should be a
# DOM node) and have a `::setModel()` method which will be called
# immediately after construction. If you don't supply this property, you
# must supply the `createView` property with a function that never returns
# `undefined`.
# * `createView` (Optional) Factory {Function} that must return a subclass
# of `HTMLElement` or `undefined`. If this property is not present or the
# function returns `undefined`, the view provider will fall back to the
# `viewConstructor` property. If you don't provide this property, you must
# provider a `viewConstructor` property.
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added provider.
addViewProvider: (providerSpec) ->
@viewRegistry.addViewProvider(providerSpec)
-1
Ver Arquivo
@@ -20,7 +20,6 @@
@import "overlay";
@import "lists";
@import "popover-list";
@import "notification";
@import "messages";
@import "markdown";
@import "editor";
-6
Ver Arquivo
@@ -1,7 +1,5 @@
.source {
.gfm {
-webkit-font-smoothing: antialiased;
.markup.heading {
font-weight: bold;
}
@@ -17,9 +15,5 @@
.comment.quote {
font-style: italic;
}
.raw {
-webkit-font-smoothing: subpixel-antialiased;
}
}
}
-56
Ver Arquivo
@@ -1,56 +0,0 @@
.notification {
position: absolute;
top: 40px;
left: 50%;
margin-left: -5%;
z-index: 9999;
border: 2px solid rgba(0, 0, 0, 0.2);
border-radius: 5px;
box-shadow:
inset 1px 1px 0 rgba(255, 255, 255, 0.05),
0 0 5px rgba(0, 0, 0, 0.5);
background: -webkit-linear-gradient(
rgba(20, 20, 20, 0.5),
rgba(0, 0, 0, 0.5));
color: #eee;
width: 300px;
}
.notification .content {
padding: 10px;
margin-left: 42px;
box-sizing: border-box;
}
.notification .content:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
}
.notification .title {
font-size: 12px;
font-weight: bold;
margin-bottom: 3px;
}
.notification .message {
font-size: 12px;
color: #777;
}
.notification .icon {
display: inline-block;
font-family: 'Octicons Regular';
font-size: 32px;
width: 32px;
height: 32px;
margin-right: 5px;
-webkit-font-smoothing: antialiased;
}
/* TODO: Full Octicon Support */
.icon-gist {
content: "\f20e";
}