Comparar commits

..

229 Commits

Autor SHA1 Mensagem Data
Kevin Sawicki 8f8c0cbf45 Mention theme not found fix 2013-08-09 11:26:37 -07:00
Kevin Sawicki 7e04d85e1e Log a warning when a theme fails to load
Previously Atom would fail to launch if a theme referenced in
the config was not found.
2013-08-09 11:25:07 -07:00
Kevin Sawicki 136836e615 Allow non-existent files to be opened from fuzzy finder
The previous isFileSync check prevented unsaved buffers with a path to a
non-existent file from being opened from the fuzzy finder.

Now an error is only displayed if the selected path is a directory.

Closes #686
2013-08-09 10:31:40 -07:00
Matt Colyer 82882624ce Handle atom standard output from atom.sh 2013-08-09 10:23:05 -07:00
Kevin Sawicki c03e849089 Add missing dot in usage ellipsis 2013-08-09 10:10:39 -07:00
Kevin Sawicki 25f98e223f Use subscribe for syntax event callback 2013-08-09 09:37:21 -07:00
Kevin Sawicki c2290ab8b4 Show symlink directory icon in tree view 2013-08-08 21:35:43 -07:00
Kevin Sawicki 9c39587d6e Debounce grammar-added/updated render callback
This prevents rendering from occurring once per grammar loaded
when Atom is started with a markdown preview already opened.
2013-08-08 20:37:54 -07:00
Kevin Sawicki 972aa75f3e Add mixin for adding octicon font-face 2013-08-08 18:54:13 -07:00
Kevin Sawicki 1d1e4b33d4 💄 2013-08-08 18:44:08 -07:00
Kevin Sawicki 79a61d47b2 Remove unused parameter 2013-08-08 18:41:00 -07:00
Kevin Sawicki 26c9e7cfa9 Re-render markdown when a grammar is added
Previously if the markdown preview launched before grammars finished
loading the fenced code blocks would not be colorized correctly.
2013-08-08 18:28:26 -07:00
Kevin Sawicki 28f9f22614 Map coffee-script fence to coffee extension 2013-08-08 18:20:51 -07:00
Kevin Sawicki 69caf6c98f Upgrade to roaster 0.0.7 2013-08-08 18:18:16 -07:00
Kevin Sawicki 51f1bb896c Update config.cson example with accurate keys 2013-08-08 18:07:40 -07:00
Kevin Sawicki 0fd834004e Support optional dash in CoffeeScript fence name 2013-08-08 18:03:47 -07:00
Kevin Sawicki d2654cb70c 💄 2013-08-08 17:56:01 -07:00
Kevin Sawicki 268553cda9 Use css extension for css fenced blocks 2013-08-08 17:50:40 -07:00
Kevin Sawicki 64a61d86d4 Update docs for new window keybinding change 2013-08-08 17:48:28 -07:00
Kevin Sawicki 216a9e11c0 Run set-development-version task during ci task 2013-08-08 17:25:35 -07:00
probablycorey 04373d2d9d Score files with a low nesting depth higher.
Fixes #692
2013-08-08 17:06:58 -07:00
probablycorey 9a2e768882 Group mini-editor css styles 2013-08-08 17:06:58 -07:00
Kevin Sawicki d13d0543b9 Ignore display-property-grouping lint errors
These aren't always accurate since the computed value for floats
can override the specified value.
2013-08-08 16:47:00 -07:00
Kevin Sawicki 6178294537 Use octicon mixin for gutter and line fold icons
This corrects a line height mismatch issue between the editor
and the gutter for certain fonts and font sizes.

Close #689
2013-08-08 16:12:26 -07:00
Kevin Sawicki & Nathan Sobo 4871a7a06d Floor subpixel aware values when calculating position left
getClientRects() does not return subpixels so subpixels values
should be ignored if returned either from scrollView.offset() or
scrollLeft().
2013-08-08 16:11:23 -07:00
Kevin Sawicki fe23d82e23 Use octicon mixins in fuzzy finder and status bar 2013-08-08 14:17:58 -07:00
Kevin Sawicki d6e94b1105 Try chevrons instead of triangles in command panel 2013-08-08 14:12:19 -07:00
Kevin Sawicki f0a2b17914 Use octicon mixins in command-panel.less 2013-08-08 14:10:28 -07:00
Kevin Sawicki ab2252f80f Try chevrons in tree view instead of triangles 2013-08-08 14:00:18 -07:00
Matt Colyer f1cf8711a8 Explictly stop updates if the version is a SHA 2013-08-08 10:41:44 -07:00
Kevin Sawicki & Nathan Sobo d7cfb757d6 Downgrade to atom-shell@v0.2.1
atom-shell@v0.3.0 removed the node binary which was needed for
scripts spawned by BufferedProcess such as nak. We can explore
other approaches to spawning node-based  subprocesses if it's
a deal-breaker to ship with a node binary.
2013-08-08 09:45:17 -07:00
Kevin Sawicki ea2113e753 Omit 'core.themes' from general-panel
This setting is handled in the theme-panel
2013-08-08 08:45:09 -07:00
Kevin Sawicki 05f4604005 Spy on shell.beep() to prevent an audible beep when specs run 2013-08-08 08:37:09 -07:00
Kevin Sawicki 71b2400dbc Upgrade to space-pen 1.2.0
This should speed up CI times that were originally slowed
down by the upgrade from 1.0.0 to 1.1.0
2013-08-07 21:28:11 -07:00
Kevin Sawicki 1de46330d7 Upgrade to coffee-script-tmbundle 4.0.0
Previous spec failures caused by earlier upgrade were fixed in prior commit.
2013-08-07 18:20:54 -07:00
Kevin Sawicki de4e24582d Comma separate left and right matcher in or matcher 2013-08-07 18:20:41 -07:00
Kevin Sawicki dffb0b35e7 Revert to coffee-script-tmbundle 2.0.0
4.0.0 caused some specs to fails regarding commenting lines
2013-08-07 18:07:06 -07:00
Kevin Sawicki d8ec4573ec Remove all references to vendor/packages
3rd party packages are stored in node_modules
2013-08-07 17:40:15 -07:00
Kevin Sawicki 09a6e9a42e Remove vendored TextMate themes 2013-08-07 17:39:18 -07:00
probablycorey 57fe9c6903 Remove left padding to gutter fold octicon (it causes spec failures) 2013-08-07 16:46:32 -07:00
probablycorey cf3e1a9b6d Remove superfluous logging 2013-08-07 15:52:49 -07:00
probablycorey 4629905b65 Remove all references to TextMate themes.
Let's not ship with TextMate theme support. Our .less theme files are
easier to read and write than TextMate themes. If we want to use
TextMate themes we should write a script that converts them to the 
Atom .less version.

Closes #629
2013-08-07 15:21:47 -07:00
Kevin Sawicki d4e8de60ce Upgrade coffee-script-tmbundle 2013-08-07 14:37:55 -07:00
Kevin Sawicki 3237636206 Use octicon variables in bookmarks.less 2013-08-07 14:06:30 -07:00
Kevin Sawicki 934fe1c6d0 Add left padding to gutter fold octicon 2013-08-07 14:01:23 -07:00
Kevin Sawicki 9aff1476d4 Use octicon variables in command-panel.less and editor.less 2013-08-07 13:57:41 -07:00
Kevin Sawicki 084d310366 Use octicon variables in fuzzy-finder.less 2013-08-07 13:50:38 -07:00
Kevin Sawicki d122d18a34 Update New Window menu keybinding to cmd-shift-n 2013-08-07 13:39:45 -07:00
Kevin Sawicki 6fb3dea9cd Use octicon variables in status-bar.less 2013-08-07 13:36:06 -07:00
Nathan Sobo ceb2a3857d Merge pull request #681 from github/scope-ranges
Add ability to query for a range covering a given scope/position
2013-08-07 12:14:00 -07:00
Nathan Sobo ab80da4363 Add EditSession.bufferRangeForScopeAtCursor 2013-08-07 12:53:09 -06:00
Nathan Sobo 19545e1113 Add setTextInBufferRange to EditSession
We should probably rename TextBuffer.change to .setTextInRange as well
2013-08-07 12:53:09 -06:00
Nathan Sobo 88603e2771 Use normalized variables instead of original parameters 2013-08-07 12:53:09 -06:00
Nathan Sobo 5f323cc67c Add TokenizedBuffer.bufferRangeForScopeAtPosition(selector, position)
You can call this method with a selector and a position and get the range
of any matching scope containing the given position, or a falsy value
if the scope does not match at that position.
2013-08-07 12:53:03 -06:00
Jason Rudolph & Nathan Sobo 39d15d6087 Add _.isSubset 2013-08-07 12:37:03 -06:00
Jason Rudolph & Nathan Sobo eaba8ef016 Add Jason Rudolph to .pairs file 2013-08-07 12:36:05 -06:00
Jason Rudolph & Nathan Sobo 6cc4cf87b9 💄 Add intention-revealing helper method 2013-08-07 12:36:05 -06:00
Kevin Sawicki c6a914a6e1 Default looking for octicons in ~/github/octicons 2013-08-07 10:59:45 -07:00
Kevin Sawicki 32af574206 Add trailing newline to octicon-utf-codes.less 2013-08-07 10:56:08 -07:00
Kevin Sawicki 552ab150cb Mention no more reload for theme changes 2013-08-07 10:52:36 -07:00
Kevin Sawicki 2698925d10 Reload stylesheets when core.themes config changes
Extracted a new ThemeManager class to encapsulate all the theme
work previously done directly in atom global.

Closes #642
2013-08-07 10:51:25 -07:00
probablycorey 13b1632dfc Update octicons 2013-08-07 10:37:12 -07:00
probablycorey de204b0321 Add script to automate octicon updates 2013-08-07 10:37:12 -07:00
Kevin Sawicki def07344e9 Visually separate core and package specs in reporter 2013-08-07 09:32:29 -07:00
Kevin Sawicki 4ef3f39a7b Rename settings.cson to settings-view.cson 2013-08-07 08:53:20 -07:00
Kevin Sawicki 2bf26e8db5 Rename theme-config-panel-spec to theme-panel-spec 2013-08-07 08:52:02 -07:00
Kevin Sawicki 24b3b664dc Rename config-view-spec.less to settings-view-spec.less 2013-08-07 08:51:23 -07:00
Kevin Sawicki 2352829b28 Rename config-view.less to settings-view.less 2013-08-07 08:50:45 -07:00
Kevin Sawicki 3ca34dad40 Tweak settings view button text 2013-08-07 08:50:31 -07:00
Kevin Sawicki 15dc6442d0 Upgrade to less 1.4.2
Prevents issues with version incompatibilities between our less fork,
grunt-contrib-less, and grunt-lesslint.

Closes #647
2013-08-06 19:40:53 -07:00
Kevin Sawicki d775038f8d Don't expand snippets when text is selected
Closes #675
2013-08-06 19:31:49 -07:00
Kevin Sawicki 3829970a09 Register edit session with project at end of ctor
Previously edit-session-created could be fired before certain properties
were set which could cause listeners to raise exceptions.
2013-08-06 19:09:14 -07:00
Kevin Sawicki 633306e6bf Fire edit-session-created event when deserializing
This event was previously not being fired when splitting panes
since the constructor pushing the edit session directly to the
project's array.

Closes #684
2013-08-06 19:07:24 -07:00
Kevin Sawicki 7d58008ed3 Show completions for current scope in autocomplete
Add the TextMate "completions" preferences available as "editor.completions"
and add all completions matching the current scope of the cursor position
when building the autocomplete word list.

Closes #676
2013-08-06 18:18:22 -07:00
Kevin Sawicki bc9e32a3cf 💄 2013-08-06 17:11:32 -07:00
Kevin Sawicki a98791ebd0 Add filter support to selector grammar
Currently these are unimplemented but they can now be parsed
successfully since they are used by certain snippets.
2013-08-06 17:06:22 -07:00
Kevin Sawicki a72e1813e9 Support stand-alone negation in selector grammar
Previously negation was only supported as the right hand side
of an composite.
2013-08-06 16:54:32 -07:00
Kevin Sawicki fe9ffbeb12 Support selectors with a trailing comma 2013-08-06 15:55:50 -07:00
Kevin Sawicki e61992c1f6 Allow _ characters in selector segments 2013-08-06 15:21:31 -07:00
Kevin Sawicki 612332cd9f Allow + characters in selector segments 2013-08-06 15:12:24 -07:00
Kevin Sawicki 40d81ca22c Upgrade to space-pen 1.1.1
Fixes regression when removing multiple views
2013-08-06 15:09:11 -07:00
Kevin Sawicki faf02460f5 Add TextMateScopeSelector.toCssSelector() 2013-08-06 15:09:10 -07:00
Kevin Sawicki f010e8a888 Add Editor.scopesForBufferPosition()
Passes through to EditSession.scopesForBufferPosition()
2013-08-06 15:09:10 -07:00
probablycorey 712e9c7203 Add spec to test cutToEndOfLine when soft wrap is enabled 2013-08-06 14:02:30 -07:00
probablycorey 128a030880 Moving to the start or end of a line treats screen lines as real lines 2013-08-06 14:02:30 -07:00
Kevin Sawicki 907c3245a9 Upgrade to space-pen 1.1.0
Uses WeakMap cache for faster element to View lookup.
2013-08-06 13:49:20 -07:00
Kevin Sawicki da7cbeddc7 Support scope selectors with dashes in segments
Previously dashes were only interpreted as negation which
wasn't correct.

Segments should be able to contain a dash as long as it isn't at
the very beginning of the segment.
2013-08-06 12:18:36 -07:00
Kevin Sawicki 8b55c4981d Add assert for multi-segment prefix 2013-08-06 11:35:37 -07:00
Kevin Sawicki b7a59748c4 Adding missing parens 2013-08-06 10:47:56 -07:00
probablycorey b49de61402 Rename getMovePreviousWordBoundaryBufferPosition
New name is getPreviousWordBoundaryBufferPosition
2013-08-06 08:53:27 -07:00
probablycorey c38edbfe0b Cursor.moveCursorToBeginningOfNextWord() behaves correctly on whitespace
Closes #669
2013-08-05 16:47:29 -07:00
Kevin Sawicki 557ada7c81 Read metadata when TextMate packages are loaded
The bundled TextMate packages contain valid package metadata
which should be available when displaying in the packages settings
view.
2013-08-05 16:09:10 -07:00
Kevin Sawicki 236ec6fc3b Ignore children with no names
This will be elements that aren't package views
2013-08-05 15:54:03 -07:00
Kevin Sawicki 35890588ca Remove separation for release that didn't happen 2013-08-05 14:10:52 -07:00
probablycorey c6c0ecbb37 Make changelog entries more readable 2013-08-05 14:09:08 -07:00
probablycorey 1fdbf4612c Update changelog 2013-08-05 13:56:22 -07:00
probablycorey 948fa3a91c Fix naming errors 2013-08-05 13:54:39 -07:00
probablycorey a624d52f42 💄 2013-08-05 13:54:39 -07:00
probablycorey 2b50f2409e Add settings view package description 2013-08-05 13:54:39 -07:00
probablycorey 0b11ce64a2 Rename config view to settings view 2013-08-05 13:54:39 -07:00
probablycorey f70c6928cd Use rootView.open to display config panel 2013-08-05 13:54:39 -07:00
probablycorey cbb6d58d1b Rename ThemeConfigPanel to ThemePanel 2013-08-05 13:54:39 -07:00
probablycorey 4dc2e48e8c Activate all packages before loading the settings config panel 2013-08-05 13:54:39 -07:00
probablycorey 7385bd97c6 💄 2013-08-05 13:54:39 -07:00
probablycorey 063078cd34 Remove Config panel class and update Settings Panel spec 2013-08-05 13:54:39 -07:00
probablycorey 789b8a2987 Rename GeneralConfigPanel to SettingsPanel 2013-08-05 13:54:38 -07:00
probablycorey 53ea135799 Add defaults for autodave and excludeVcsIgnoredPaths 2013-08-05 13:54:38 -07:00
probablycorey 32242687bd Rename @pack to @metadata 2013-08-05 13:54:38 -07:00
probablycorey 3aca556827 Simplify tab clicking 2013-08-05 13:54:38 -07:00
probablycorey 372a64bd5d Typo 2013-08-05 13:54:38 -07:00
probablycorey 3f83d42afc Fix broken specs 2013-08-05 13:54:38 -07:00
probablycorey 8bf877e400 Inline available packages 2013-08-05 13:54:38 -07:00
probablycorey 29f45b787b Add set loading text 2013-08-05 13:54:38 -07:00
probablycorey 68491a512d Fix broken specs 2013-08-05 13:54:38 -07:00
probablycorey bd72f245b1 Inline installed packages panel 2013-08-05 13:54:38 -07:00
probablycorey 4ef5082887 Add filter to packages config panel 2013-08-05 13:54:38 -07:00
probablycorey 27822fb37c Remove editor config panel 2013-08-05 13:54:38 -07:00
probablycorey be803bf122 Remove comments 2013-08-05 13:54:38 -07:00
probablycorey db29a1b6a2 Auto populate config settings 2013-08-05 13:54:38 -07:00
probablycorey 25d4bb8d6c Add _.uncamelcase 2013-08-05 13:54:37 -07:00
probablycorey 8cc47a2069 Add _.deepExtend 2013-08-05 13:54:37 -07:00
probablycorey c825e20f62 Make config view focusable 2013-08-05 13:54:37 -07:00
probablycorey 69eace6292 Remove references to windowed config panel 2013-08-05 13:54:37 -07:00
probablycorey 2284435551 Move config view to a package 2013-08-05 13:54:37 -07:00
probablycorey 1252b94fcb Warn if no deserilizer can be found for some state 2013-08-05 13:54:37 -07:00
probablycorey 8d0afc087f Don't set uri when pane item doesn't serialize itself 2013-08-05 13:54:37 -07:00
probablycorey f789c7e2df 💄 2013-08-05 12:43:56 -07:00
probablycorey 80bbd035db Do not download update if Atom is running in dev mode 2013-08-05 12:40:47 -07:00
Kevin Sawicki 0397df2f4d Rename package main to just Bookmarks
This allows the view that displays the bookmarks for browsing
to be called just BookmarksView.
2013-08-05 11:32:50 -07:00
Kevin Sawicki cd8796b561 Add select list to browse and open bookmarks from 2013-08-05 11:28:10 -07:00
Kevin Sawicki 68103601e6 Move folding changes to next release section 2013-08-01 09:13:12 -07:00
Kevin Sawicki c278ead451 Mention bookmarks view 2013-08-01 09:12:18 -07:00
Kevin Sawicki c44e9b6308 💄 2013-08-01 08:48:15 -07:00
Kevin Sawicki 1c37537d19 Show octicon in gutter for bookmarked line 2013-08-01 08:47:41 -07:00
Kevin Sawicki 684dec4b24 Always suggest non-negative indent levels
Close #668
2013-07-31 18:01:38 -07:00
Kevin Sawicki 30f72c1519 Update bootstrap URL in .gitmodules 2013-07-30 16:39:23 -07:00
Kevin Sawicki 69733a8f7a Put file name at beginning of markdown preview title
Previously the 'Markdown Preview - ' prefix dominated the tab text
making it hard to disambiguate which preview was for which editor.

Now the title leads with the file name and follows with a "Preview" suffix.
2013-07-29 14:41:23 -07:00
Cheng Zhao b9261a33be Update apm: update node to v0.10.15. 2013-07-26 20:16:56 +08:00
Ben Ogle e1a78d1f0f newlines follow last line's indent 2013-07-24 15:28:12 -07:00
Ben Ogle c7de0ba3bc fix #634 jump to the beginning of the fold when clicking on folded block. 2013-07-24 15:12:19 -07:00
Ben Ogle & Corey Johnson 16cce1efb1 nof 2013-07-24 14:55:43 -07:00
Ben Ogle b3025a4dfc rename rowRangeForCommentFoldAtBufferRow -> rowRangeForCommentAtBufferRow 2013-07-24 13:09:00 -07:00
Ben Ogle 11a1a27dbd Handle * prefixes properly 2013-07-24 12:18:27 -07:00
Ben Ogle e76fe439ba Fix tests. Indent oops. 2013-07-24 12:18:27 -07:00
Ben Ogle cc8513afdf remove !! hack on isComment 2013-07-24 12:18:27 -07:00
Ben Ogle c17f5bd41e Return false from isComment() for consistency 2013-07-24 12:18:27 -07:00
Ben Ogle 2d9ef9aad6 Add note for ScreenRow in tokenizedBuffers 2013-07-24 12:18:27 -07:00
Ben Ogle f7bb8aab9e Move rowRangeForParagraphAtBufferRow into LanguageMode 2013-07-24 12:18:27 -07:00
Ben Ogle c5c1980c9a remove fdescribe 2013-07-24 12:11:33 -07:00
Ben Ogle f234b8fa27 respects comment chars 2013-07-24 12:11:33 -07:00
Ben Ogle 778e3bbd67 respects indentation 2013-07-24 12:11:33 -07:00
Ben Ogle 5d8d5da602 autoflow respects current paragraphs 2013-07-24 12:11:33 -07:00
Ben Ogle fe449e31e3 Move config stuff out of the autoflow 2013-07-24 12:11:33 -07:00
Ben Ogle 617f0ae79a tests work again 2013-07-24 12:11:33 -07:00
Ben Ogle cf3de0e8dc move autoflow into lib dir 2013-07-24 12:11:32 -07:00
Ben Ogle 173c47f780 Fix issue in jumping to next bookmark 2013-07-24 12:07:56 -07:00
Ben Ogle 77e12e3658 add comment about using better invalidation strategy 2013-07-24 12:07:56 -07:00
Ben Ogle 8db9551700 Handle one bookmark 2013-07-24 12:07:56 -07:00
Ben Ogle ece0c76158 Use @editor.command to bind to commands 2013-07-24 12:07:56 -07:00
Ben Ogle 8881847c61 Handle jumping case when no bookmarks 2013-07-24 12:07:55 -07:00
Ben Ogle 4254efd49e remove fdescribe 2013-07-24 12:07:55 -07:00
Ben Ogle 6968075d38 Jumping to bookmarks works 2013-07-24 12:07:55 -07:00
Ben Ogle 3cb29e1d5c visually marks bookmarked lines 2013-07-24 12:07:55 -07:00
Ben Ogle e632b091f9 add initial bookmark plugin 2013-07-24 12:07:55 -07:00
Ben Ogle afa92e51f6 update changelog for the folding changes 2013-07-24 12:05:16 -07:00
Ben Ogle d746c7566c Fix CommandPanel spec
I added a new sample-with-comments.js file which 
has more matches for 'sort', so the test needed 
to be updated.
2013-07-24 12:05:16 -07:00
Ben Ogle 0a075c6934 remove fdescribe 2013-07-24 12:05:16 -07:00
Ben Ogle cef3b7d634 move folding tests from EditSession -> LanguageMode 2013-07-24 12:05:16 -07:00
Ben Ogle c31ba651cf Add shortcuts for folding at an indent level. 2013-07-24 12:05:16 -07:00
Ben Ogle d4d3426b4e Add foldAllAtIndentLevel() 2013-07-24 12:05:16 -07:00
Ben Ogle 89e3d2efec Rearrange folding functions
I think it is more clear to have small constituent 
functions below functions that compose them. IMO, 
this reads better.
2013-07-24 12:05:15 -07:00
Ben Ogle c2326d096b Fold comments in foldAll() 2013-07-24 12:05:15 -07:00
Ben Ogle 18146346f6 add failing comment fold tests 2013-07-24 12:05:15 -07:00
Ben Ogle 519c514092 add a new sample with some comments 2013-07-24 12:05:15 -07:00
Ben Ogle 4187615fa7 Fix test 2013-07-24 11:53:33 -07:00
Ben Ogle d98ea0180c Proper handling of cursor up and down behavior when selection range 2013-07-24 11:53:33 -07:00
Ben Ogle 226a4bf391 Add tests for moving to end of selection 2013-07-24 11:53:33 -07:00
Ben Ogle a689a5906e add moveToEndOfSelection option to moveLEft and moveRight 2013-07-24 11:53:33 -07:00
Ben Ogle 18370bb663 Merge pull request #645 from github/bo-move-word-behavior
Add new commands for moving between words
2013-07-23 15:38:37 -07:00
Ben Ogle 1465736974 Merge branch 'master' into bo-move-word-behavior
Conflicts:
	src/app/editor.coffee
2013-07-23 15:34:20 -07:00
Ben Ogle 3907344fef Merge pull request #646 from github/bo-small-dark-theme-change
Small dark theme change
2013-07-23 15:32:51 -07:00
Ben Ogle 7c414d47cb Merge pull request #644 from github/bo-fix-scrollbar-issues
Fix scrollbar css issues
2013-07-23 15:31:38 -07:00
Kevin Sawicki bc74be531d Mention keymap changes and inspect element menu 2013-07-23 08:13:32 -07:00
Ben Ogle 592b0886b2 new editor is now cmd+n, cmd+shift+n is new window fixes #652 2013-07-22 13:45:04 -07:00
Kevin Sawicki & Nathan Sobo 1685d62cae Don't allow caching of coffee requires to be overridden in tasks
This is a follow-on to the previous commit which handled the index.html
case.
2013-07-22 11:50:14 -07:00
Kevin Sawicki & Nathan Sobo e705e3e045 Don't allow caching of coffee requires to be overridden
Previously coffeestack was requiring a different version of coffeescript
than atom was, which had a side effect of re-registering the extension
handler for .coffee requires. This disabled coffee-cache, which made
require really slow again.
2013-07-22 11:44:39 -07:00
Kevin Sawicki 0bb7d3ba09 Default save as dialog to directory of active item 2013-07-22 09:11:57 -07:00
Ben Ogle 8e92499ebb Fix comments so they match up with actual behavior 2013-07-22 09:02:05 -07:00
Ben Ogle 62e0274ff6 hook selectToFirstCharacterOfLine up to a command in editor. 2013-07-22 09:02:05 -07:00
Ben Ogle fe4c4e9751 Add selectToFirstCharacterOfLine to editSession 2013-07-22 09:02:05 -07:00
Kevin Sawicki baa03f5587 Upgrade apm
Closes #638
2013-07-22 08:35:10 -07:00
Ben Ogle 214d73d812 Remove line highlight in dark syntax
When moving around and selecting things, the entire line looks selected
and is super confusing. This leaves the line number highlighted, but 
not the line itself.
2013-07-19 13:57:08 -07:00
Ben Ogle 8c6fe7a540 lighten selection color so it's more clear. 2013-07-19 13:55:29 -07:00
Ben Ogle 164d5591a0 remove comment 2013-07-19 13:25:05 -07:00
Ben Ogle 85cb7c88fa plumb up the select to boundary to editor commands 2013-07-19 12:21:36 -07:00
Ben Ogle 4ccbd03daf I can't spell. Boundary. 2013-07-19 12:17:17 -07:00
Ben Ogle 3df33a7367 Add selection counterparts to move next/prev word boundary 2013-07-19 12:07:30 -07:00
Ben Ogle 13b592d1f3 Add Cursor::moveToNextWordBoundry()
Plumb up to editor as well.
2013-07-19 11:37:47 -07:00
Ben Ogle ab8df8dcde Add moveToPreviousWordBoundry to cursor.
Plumb it up to a command in the editor.
2013-07-19 11:16:14 -07:00
Ben Ogle 2b25d433c7 move editor scrollbar above the edit pane
So you can grab it with your mouse!
2013-07-18 17:45:38 -07:00
Ben Ogle 1ba8218743 Move the resize handle over between the treeview and the editor
Otherwise it covers up the scrollbar in the treeview. No bueno.
2013-07-18 17:42:36 -07:00
Ben Ogle 17cf2bd1c8 Merge pull request #635 from github/bo-fix-comment-indent
Add proper indents to comments on toggle-line-comments Closes #615
2013-07-18 10:13:28 -07:00
Cheng Zhao 1746bc8797 Add 'Inspect Element' context menu. Fixes #632. 2013-07-18 20:10:33 +08:00
Cheng Zhao 635f09b741 Destroy window immediately when user choose to close window.
There is no need to delay destroy now.
2013-07-18 18:57:34 +08:00
Cheng Zhao ee0443e40c Revert "Use atom-shell 23dd5b4da8"
Since the async function issue is fixed in atom-shell, we can go back to
use the latest release.
2013-07-18 18:57:13 +08:00
Ben Ogle d02e9172da 💄 2013-07-17 21:04:50 -07:00
Ben Ogle bc55ee6bd2 Add change string to changelog.md
Added a newline; assumed I am the first on this deploy
2013-07-17 18:30:43 -07:00
Ben Ogle 76be95bd6c update comment 2013-07-17 18:25:41 -07:00
Ben Ogle e43e8d156e Combat against empty range; fixes tests 2013-07-17 18:22:41 -07:00
Ben Ogle 2aca31988f Fix tests in EditSession 2013-07-17 17:56:52 -07:00
Ben Ogle c937827582 Use editSession.lineForBufferRow()
Rather than the buffer directly.
2013-07-17 17:51:40 -07:00
Ben Ogle c52cf836cd remove the f on the describe 2013-07-17 17:42:33 -07:00
Ben Ogle 0924ad586f spaces around the + 2013-07-17 17:39:39 -07:00
Ben Ogle abdce2df04 replace new Range(...) with [[..], [..]] syntax 2013-07-17 17:38:51 -07:00
Ben Ogle 3f8c120ad0 update tests to be more clear 2013-07-17 17:37:45 -07:00
Ben Ogle 365e5e8413 calcMinIndent -> minIndentLevelForRowRange 2013-07-17 17:35:05 -07:00
Ben Ogle 90e53ad3e2 Add proper indents on auto comments 2013-07-17 16:04:53 -07:00
Corey Johnson & Matt Colyer 4a67bfcf15 Remove editor.autoIndentOnPaste config option
Normalize paste on indent covers most use cases of autoindent when pasting.

Closes #584
2013-07-16 17:08:12 -07:00
Corey Johnson & Matt Colyer 2410ea0d5b Add Matt to pairs file 2013-07-16 17:07:59 -07:00
Kevin Sawicki 17cecda23e Use atom-shell 23dd5b4da8
The release past this build is causing issues with async callbacks
not firing.
2013-07-16 09:48:15 -07:00
Kevin Sawicki 9d733a2da9 Don't grab native window focus
Call $(window) instead of atom.focus() so the native window
doesn't regain focus on each spec run preventing it from running
in the background.
2013-07-15 13:56:21 -07:00
Kevin Sawicki 6bbcc58542 Call atom.focus() in the root beforeEach
Async events are not currently firing in specs and this
appears to cause them fire.
2013-07-15 13:40:53 -07:00
Kevin Sawicki 1a76e3dc9d Add missing '..' to node directory path
The path has changed and one more parent directory needs to be
traversed to find the bundled path to node for spawning child
processes.
2013-07-15 12:20:09 -07:00
Kevin Sawicki ff70ae633d Correct broken link to npm 2013-07-12 17:30:05 -07:00
Kevin Sawicki d1f372e439 Rebuild native modules when atom-shell is upgraded
Spawn an apm rebuild when the atom shell version changes
after running the update-atom-shell script.

Closes #618
2013-07-12 14:48:10 -07:00
Kevin Sawicki 041f52aaaa Upgrade apm 2013-07-12 14:07:03 -07:00
Kevin Sawicki 270d17814e Move right border to tree view resizer
This allows the border to still show when the tree view
scrolls horizontally.

Closes #622
2013-07-12 13:59:52 -07:00
Kevin Sawicki 16095c8086 Add New Window to File menu
Closes #626
2013-07-11 20:22:43 -07:00
Coby Chapple 94e2dbbc2c extraneous paren in package docs 2013-07-11 10:20:29 +01:00
154 arquivos alterados com 2942 adições e 16919 exclusões
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
[submodule "vendor/bootstrap"]
path = vendor/bootstrap
url = https://github.com/twitter/bootstrap
url = https://github.com/twbs/bootstrap
[submodule "vendor/apm"]
path = vendor/apm
url = https://github.com/github/apm.git
+2
Ver Arquivo
@@ -7,6 +7,8 @@ pairs:
bl: Brian Lopez; brian
jp: Justin Palmer; justin
gt: Garen Torikian; garen
mc: Matt Colyer; mcolyer
jr: Jason Rudolph; jasonrudolph
email:
domain: github.com
#global: true
+22
Ver Arquivo
@@ -1,3 +1,25 @@
* Fixed: Atom failing to launch if the theme being used was not found
* Improved: Theme changes now immediately take effect
* Fixed: Wrap in quotes/parens now works in split panes
* Improved: Autocomplete now includes CSS property names and values
* Improved: Settings GUI is now a pane item
* Added: Support package filtering in Settings GUI
* Added: Dynamically load all config options in the Settings GUI
* Added: Ability to bookmark lines and navigate bookmarks
* Fixed: Error when inserting newlines in CSS
* Fixed: Folding all will fold comments as well
* Added: Ability to fold all code at a given indentation level
* Improved: cmd-n now opens a new tab and cmd-shift-n now opens a new window.
* Added: Inspect Element context menu
* Fixed: Save As dialog now defaults to directory path of current editor
* Fixed: Using toggle comment shortcut respects indentation level
* Fixed: Search never completing in the command panel
* Fixed: cmd-n now works when no windows are open
* Fixed: Error selecting a grammar for an untitled editor
* Added: j/k now can be used to navigate the tree view and archive editor
+2 -1
Ver Arquivo
@@ -77,6 +77,7 @@ module.exports = (grunt) ->
'box-sizing': false
'bulletproof-font-face': false
'compatible-vendor-prefixes': false
'display-property-grouping': false
'fallback-colors': false
'font-sizes': false
'gradients': false
@@ -112,6 +113,6 @@ module.exports = (grunt) ->
grunt.registerTask('compile', ['coffee', 'less', 'cson'])
grunt.registerTask('lint', ['coffeelint', 'csslint', 'lesslint'])
grunt.registerTask('ci', ['lint', 'partial-clean', 'update-atom-shell', 'build', 'test'])
grunt.registerTask('ci', ['lint', 'partial-clean', 'update-atom-shell', 'build', 'set-development-version', 'test'])
grunt.registerTask('deploy', ['partial-clean', 'update-atom-shell', 'build', 'codesign'])
grunt.registerTask('default', ['update-atom-shell', 'build', 'set-development-version', 'install'])
+27 -11
Ver Arquivo
@@ -1,5 +1,6 @@
#!/bin/sh
ATOM_PATH=/Applications/Atom.app
ATOM_BINARY=$ATOM_PATH/Contents/MacOS/Atom
if [ ! -d $ATOM_PATH ]; then sleep 5; fi # Wait for Atom to reappear, Sparkle may be replacing it.
@@ -8,7 +9,32 @@ if [ ! -d $ATOM_PATH ]; then
exit 1
fi
open -a $ATOM_PATH -n --args --executed-from="$(pwd)" --pid=$$ $@
while getopts ":whv-:" opt; do
case "$opt" in
-)
case "${OPTARG}" in
wait)
WAIT=1
;;
help|version)
EXPECT_OUTPUT=1
;;
esac
;;
w)
WAIT=1
;;
h|v)
EXPECT_OUTPUT=1
;;
esac
done
if [ $EXPECT_OUTPUT ]; then
$ATOM_BINARY --executed-from="$(pwd)" --pid=$$ $@
else
open -a $ATOM_PATH -n --args --executed-from="$(pwd)" --pid=$$ $@
fi
# Used to exit process when atom is used as $EDITOR
on_die() {
@@ -16,16 +42,6 @@ on_die() {
}
trap 'on_die' SIGQUIT SIGTERM
# Don't exit process if we were told to wait.
while [ "$#" -gt "0" ]; do
case $1 in
-W|--wait)
WAIT=1
;;
esac
shift
done
if [ $WAIT ]; then
while true; do
sleep 1
+12 -9
Ver Arquivo
@@ -22,7 +22,7 @@ You can always use `meta-p` to explore available commands and their
bindings, but here's a list of a few useful commands.
- `meta-o` : open a file or directory
- `meta-n` : open new window
- `meta-shift-n` : open new window
- `meta-r` : reload the current window
- `meta-alt-ctrl-s` : run test specs
- `meta-t` : open file finder to navigate files in your project
@@ -146,10 +146,13 @@ Atom loads configuration settings from the `config.cson` file in your `~/.atom`
directory, which contains CoffeeScript-style JSON:
```coffeescript
core:
hideGitIgnoredFiles: true
editor:
fontSize: 18
'editor':
'fontSize': 16
'core':
'themes': [
'atom-dark-ui'
'atom-dark-syntax'
]
```
Configuration is broken into namespaces, which are defined by the config hash's
@@ -192,12 +195,12 @@ to apply styles to elements, Atom keymaps use selectors to associate keystrokes
with events in specific contexts. Here's a small example, excerpted from Atom's
built-in keymaps:
```coffee-script
```coffeescript
'.editor':
'enter': 'editor:newline'
".select-list .editor.mini":
'enter': 'core:confirm',
'.select-list .editor.mini':
'enter': 'core:confirm'
```
This keymap defines the meaning of `enter` in two different contexts. In a
@@ -220,7 +223,7 @@ active at the same time. For example, you'll usually select a theme for the UI
and another theme for syntax highlighting. You can select themes by specifying
them in the `core.themes` array in your `config.cson`:
```coffee-script
```coffeescript
core:
themes: ["atom-light-ui", "atom-light-syntax"]
# or, if the sun is going down:
+1 -1
Ver Arquivo
@@ -29,7 +29,7 @@ on creating your first package.
## package.json
Similar to [npm packages](http://en.wikipedia.org/wiki/Npm_(software)), Atom packages
Similar to [npm packages](http://en.wikipedia.org/wiki/Npm_(software\)), Atom packages
can contain a _package.json_ file in their top-level directory. This file contains metadata
about the package, such as the path to its "main" module, library dependencies,
and manifests specifying the order in which its resources should be loaded.
+6 -5
Ver Arquivo
@@ -25,9 +25,9 @@
"temp": "0.5.0",
"rimraf": "2.1.4",
"plist": "git://github.com/nathansobo/node-plist.git",
"space-pen": "1.0.0",
"space-pen": "1.2.0",
"less": "git://github.com/nathansobo/less.js.git",
"roaster": "0.0.5",
"roaster": "0.0.7",
"jqueryui-browser": "1.10.2-1",
"optimist": "0.4.0",
"season": "0.10.0",
@@ -37,7 +37,7 @@
"tantamount": "0.3.0",
"coffeestack": "0.4.0",
"c-tmbundle": "1.0.0",
"coffee-script-tmbundle": "2.0.0",
"coffee-script-tmbundle": "4.0.0",
"css-tmbundle": "1.0.0",
"git-tmbundle": "1.0.0",
"go-tmbundle": "1.0.0",
@@ -78,9 +78,10 @@
"grunt-cson": "0.5.0",
"grunt-contrib-csslint": "~0.1.2",
"grunt-contrib-coffee": "~0.7.0",
"grunt-contrib-less": "~0.5.2",
"grunt-contrib-less": "~0.6.4",
"jasmine-focused": "~0.7.0",
"walkdir": "0.0.7"
"walkdir": "0.0.7",
"js-yaml": "~2.1.0"
},
"private": true,
"scripts": {
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ cd "$(dirname "${BASH_SOURCE[0]}" )/.."
TARGET=${1:-atom-shell}
DISTURL="https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell"
CURRENT_VERSION=$(cat "${TARGET}/version" 2>&1)
LATEST_VERSION=$(curl -fsSkL $DISTURL/version)
LATEST_VERSION=ea1f81aa5260fe2d4a844f18e0251278fbadc093 # v0.2.1
if [ -z "${LATEST_VERSION}" ] ; then
echo "Could determine lastest version of atom-shell" >&2
Arquivo executável
+32
Ver Arquivo
@@ -0,0 +1,32 @@
#!/usr/bin/env coffee
usage = """
Usage:
update-octicons PATH-TO-OCTICONS
"""
path = require 'path'
fs = require 'fs'
YAML = require 'js-yaml'
scriptPath = process.argv[1]
pathToOcticons = process.argv[2] ? path.join(process.env.HOME, 'github', 'octicons')
atomDir = path.resolve(scriptPath, "../../..")
unless fs.existsSync(pathToOcticons)
console.error(usage)
process.exit(1)
# Copy font-file
fontSrc = path.join(pathToOcticons, 'octicons', 'octicons.woff')
fontDest = path.join(atomDir, 'static', 'octicons.woff')
fs.createReadStream(fontSrc).pipe(fs.createWriteStream(fontDest))
# Update Octicon UTF codes
glyphsSrc = path.join(pathToOcticons, 'data', 'glyphs.yml')
octiconUtfDest = path.join atomDir, 'static', 'octicon-utf-codes.less'
output = []
for {css, code} in YAML.load(fs.readFileSync(glyphsSrc).toString())
output.push "@#{css}: \"\\#{code}\";"
fs.writeFileSync octiconUtfDest, "#{output.join('\n')}\n"
-12
Ver Arquivo
@@ -217,18 +217,6 @@ describe "the `atom` global", ->
runs ->
expect(syntax.getProperty(['.source.pref'], 'editor.increaseIndentPattern')).toBe '^abc$'
describe ".activatePackageConfig(id)", ->
it "calls the optional .activateConfigMenu method on the package's main module", ->
pack = atom.activatePackageConfig('package-with-activate-config')
expect(pack.mainModule.activateCalled).toBeFalsy()
expect(pack.mainModule.activateConfigCalled).toBeTruthy()
it "loads the package's config defaults", ->
expect(config.get('package-with-config-defaults.numbers.one')).toBeUndefined()
atom.activatePackageConfig('package-with-config-defaults')
expect(config.get('package-with-config-defaults.numbers.one')).toBe 1
expect(config.get('package-with-config-defaults.numbers.two')).toBe 2
describe ".deactivatePackage(id)", ->
describe "atom packages", ->
it "calls `deactivate` on the package's main module", ->
-138
Ver Arquivo
@@ -1,138 +0,0 @@
ConfigPanel = require 'config-panel'
Editor = require 'editor'
describe "ConfigPanel", ->
it "automatically binds named input fields to their corresponding config keys", ->
class TestPanel extends ConfigPanel
@content: ->
@div =>
@input outlet: 'intInput', id: 'foo.int', type: 'int'
@input outlet: 'floatInput', id: 'foo.float', type: 'float'
@input outlet: 'stringInput', id: 'foo.string', type: 'string'
@input outlet: 'booleanInput', id: 'foo.boolean', type: 'checkbox'
config.set('foo.int', 22)
config.set('foo.boolean', true)
panel = new TestPanel
expect(panel.intInput.val()).toBe '22'
expect(panel.floatInput.val()).toBe ''
expect(panel.stringInput.val()).toBe ''
expect(panel.booleanInput.attr('checked')).toBeTruthy()
config.set('foo.int', 10)
expect(panel.intInput.val()).toBe '10'
expect(panel.floatInput.val()).toBe ''
expect(panel.stringInput.val()).toBe ''
config.set('foo.string', 'hey')
expect(panel.intInput.val()).toBe '10'
expect(panel.floatInput.val()).toBe ''
expect(panel.stringInput.val()).toBe 'hey'
config.set('foo.boolean', false)
expect(panel.booleanInput.attr('checked')).toBeFalsy()
panel.intInput.val('90.2').change()
expect(config.get('foo.int')).toBe 90
panel.floatInput.val('90.2').change()
expect(config.get('foo.float')).toBe 90.2
panel.intInput.val('0').change()
expect(config.get('foo.int')).toBe 0
panel.floatInput.val('0').change()
expect(config.get('foo.float')).toBe 0
panel.stringInput.val('moo').change()
expect(config.get('foo.string')).toBe 'moo'
panel.intInput.val('abcd').change()
expect(config.get('foo.int')).toBe 'abcd'
panel.floatInput.val('defg').change()
expect(config.get('foo.float')).toBe 'defg'
panel.intInput.val('').change()
expect(config.get('foo.int')).toBe undefined
panel.floatInput.val('').change()
expect(config.get('foo.float')).toBe undefined
panel.stringInput.val('').change()
expect(config.get('foo.string')).toBe undefined
it "automatically binds named editors to their corresponding config keys", ->
class TestPanel extends ConfigPanel
@content: ->
@div =>
@subview 'intEditor', new Editor(mini: true, attributes: { id: 'foo.int', type: 'int' })
@subview 'floatEditor', new Editor(mini: true, attributes: { id: 'foo.float', type: 'float' })
@subview 'stringEditor', new Editor(mini: true, attributes: { id: 'foo.string', type: 'string' })
config.set('foo.int', 1)
config.set('foo.float', 1.1)
config.set('foo.string', 'I think therefore I am.')
panel = new TestPanel
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(panel.intEditor.getText()).toBe '1'
expect(panel.floatEditor.getText()).toBe '1.1'
expect(panel.stringEditor.getText()).toBe 'I think therefore I am.'
config.set('foo.int', 2)
config.set('foo.float', 2.2)
config.set('foo.string', 'We are what we think.')
expect(panel.intEditor.getText()).toBe '2'
expect(panel.floatEditor.getText()).toBe '2.2'
expect(panel.stringEditor.getText()).toBe 'We are what we think.'
panel.intEditor.setText('3')
panel.floatEditor.setText('3.3')
panel.stringEditor.setText('All limitations are self imposed.')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe 3
expect(config.get('foo.float')).toBe 3.3
expect(config.get('foo.string')).toBe 'All limitations are self imposed.'
panel.intEditor.setText('not an int')
panel.floatEditor.setText('not a float')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe 'not an int'
expect(config.get('foo.float')).toBe 'not a float'
panel.intEditor.setText('')
panel.floatEditor.setText('')
panel.stringEditor.setText('')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe undefined
expect(config.get('foo.float')).toBe undefined
expect(config.get('foo.string')).toBe undefined
panel.intEditor.setText('0')
panel.floatEditor.setText('0')
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(config.get('foo.int')).toBe 0
expect(config.get('foo.float')).toBe 0
it "does not save the config value until it has been changed to a new value", ->
class TestPanel extends ConfigPanel
@content: ->
@div =>
@subview "fooInt", new Editor(mini: true, attributes: {id: 'foo.int', type: 'int'})
config.set('foo.int', 1)
observeHandler = jasmine.createSpy("observeHandler")
config.observe "foo.int", observeHandler
observeHandler.reset()
testPanel = new TestPanel
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).not.toHaveBeenCalled()
testPanel.fooInt.setText("1")
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).not.toHaveBeenCalled()
testPanel.fooInt.setText("2")
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).toHaveBeenCalled()
-46
Ver Arquivo
@@ -1,46 +0,0 @@
ConfigView = require 'config-view'
{$$} = require 'space-pen'
describe "ConfigView", ->
configView = null
beforeEach ->
configView = new ConfigView
describe "serialization", ->
it "remembers which panel was visible", ->
configView.showPanel('Editor')
newConfigView = deserialize(configView.serialize())
configView.remove()
newConfigView.attachToDom()
expect(newConfigView.activePanelName).toBe 'Editor'
it "shows the previously active panel if it is added after deserialization", ->
configView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
configView.showPanel('Panel 1')
newConfigView = deserialize(configView.serialize())
configView.remove()
newConfigView.attachToDom()
newConfigView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
expect(newConfigView.activePanelName).toBe 'Panel 1'
describe ".addPanel(name, view)", ->
it "adds a menu entry to the left and a panel that can be activated by clicking it", ->
configView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
configView.addPanel('Panel 2', $$ -> @div id: 'panel-2')
expect(configView.panelMenu.find('li a:contains(Panel 1)')).toExist()
expect(configView.panelMenu.find('li a:contains(Panel 2)')).toExist()
expect(configView.panelMenu.children(':first')).toHaveClass 'active'
configView.attachToDom()
configView.panelMenu.find('li a:contains(Panel 1)').click()
expect(configView.panelMenu.children('.active').length).toBe 1
expect(configView.panelMenu.find('li:contains(Panel 1)')).toHaveClass('active')
expect(configView.panels.find('#panel-1')).toBeVisible()
expect(configView.panels.find('#panel-2')).toBeHidden()
configView.panelMenu.find('li a:contains(Panel 2)').click()
expect(configView.panelMenu.children('.active').length).toBe 1
expect(configView.panelMenu.find('li:contains(Panel 2)')).toHaveClass('active')
expect(configView.panels.find('#panel-1')).toBeHidden()
expect(configView.panels.find('#panel-2')).toBeVisible()
+233 -182
Ver Arquivo
@@ -103,6 +103,15 @@ describe "EditSession", ->
editSession.moveCursorDown()
expect(editSession.getCursorScreenPosition()).toEqual([1, 4])
describe "when there is a selection", ->
beforeEach ->
editSession.setSelectedBufferRange([[4, 9],[5, 10]])
it "moves above the selection", ->
cursor = editSession.getCursor()
editSession.moveCursorUp()
expect(cursor.getBufferPosition()).toEqual [3, 9]
it "merges cursors when they overlap", ->
editSession.addCursorAtScreenPosition([1, 0])
[cursor1, cursor2] = editSession.getCursors()
@@ -152,6 +161,15 @@ describe "EditSession", ->
editSession.moveCursorUp()
expect(editSession.getCursorScreenPosition().column).toBe 0
describe "when there is a selection", ->
beforeEach ->
editSession.setSelectedBufferRange([[4, 9],[5, 10]])
it "moves below the selection", ->
cursor = editSession.getCursor()
editSession.moveCursorDown()
expect(cursor.getBufferPosition()).toEqual [6, 10]
it "merges cursors when they overlap", ->
editSession.setCursorScreenPosition([12, 2])
editSession.addCursorAtScreenPosition([11, 2])
@@ -187,6 +205,18 @@ describe "EditSession", ->
editSession.moveCursorLeft()
expect(editSession.getCursorBufferPosition()).toEqual [5, 4]
describe "when there is a selection", ->
beforeEach ->
editSession.setSelectedBufferRange([[5, 22],[5, 27]])
it "moves to the left of the selection", ->
cursor = editSession.getCursor()
editSession.moveCursorLeft()
expect(cursor.getBufferPosition()).toEqual [5, 22]
editSession.moveCursorLeft()
expect(cursor.getBufferPosition()).toEqual [5, 21]
it "merges cursors when they overlap", ->
editSession.setCursorScreenPosition([0, 0])
editSession.addCursorAtScreenPosition([0, 1])
@@ -221,6 +251,18 @@ describe "EditSession", ->
expect(editSession.getCursorScreenPosition()).toEqual(lastPosition)
describe "when there is a selection", ->
beforeEach ->
editSession.setSelectedBufferRange([[5, 22],[5, 27]])
it "moves to the left of the selection", ->
cursor = editSession.getCursor()
editSession.moveCursorRight()
expect(cursor.getBufferPosition()).toEqual [5, 27]
editSession.moveCursorRight()
expect(cursor.getBufferPosition()).toEqual [5, 28]
it "merges cursors when they overlap", ->
editSession.setCursorScreenPosition([12, 2])
editSession.addCursorAtScreenPosition([12, 1])
@@ -247,44 +289,72 @@ describe "EditSession", ->
expect(editSession.getCursorBufferPosition()).toEqual [12,2]
describe ".moveCursorToBeginningOfLine()", ->
it "moves cursor to the beginning of line", ->
editSession.setCursorScreenPosition [0,5]
editSession.addCursorAtScreenPosition [1,7]
editSession.moveCursorToBeginningOfLine()
expect(editSession.getCursors().length).toBe 2
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,0]
describe "when soft wrap is on", ->
it "moves cursor to the beginning of the screen line", ->
editSession.setSoftWrapColumn(10)
editSession.setCursorScreenPosition([1, 2])
editSession.moveCursorToBeginningOfLine()
cursor = editSession.getCursor()
expect(cursor.getScreenPosition()).toEqual [1, 0]
describe "when soft wrap is off", ->
it "moves cursor to the beginning of then line", ->
editSession.setCursorScreenPosition [0,5]
editSession.addCursorAtScreenPosition [1,7]
editSession.moveCursorToBeginningOfLine()
expect(editSession.getCursors().length).toBe 2
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,0]
describe ".moveCursorToEndOfLine()", ->
it "moves cursor to the end of line", ->
editSession.setCursorScreenPosition [0,0]
editSession.addCursorAtScreenPosition [1,0]
editSession.moveCursorToEndOfLine()
expect(editSession.getCursors().length).toBe 2
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,29]
expect(cursor2.getBufferPosition()).toEqual [1,30]
describe "when soft wrap is on", ->
it "moves cursor to the beginning of the screen line", ->
editSession.setSoftWrapColumn(10)
editSession.setCursorScreenPosition([1, 2])
editSession.moveCursorToEndOfLine()
cursor = editSession.getCursor()
expect(cursor.getScreenPosition()).toEqual [1, 9]
describe "when soft wrap is off", ->
it "moves cursor to the end of line", ->
editSession.setCursorScreenPosition [0,0]
editSession.addCursorAtScreenPosition [1,0]
editSession.moveCursorToEndOfLine()
expect(editSession.getCursors().length).toBe 2
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,29]
expect(cursor2.getBufferPosition()).toEqual [1,30]
describe ".moveCursorToFirstCharacterOfLine()", ->
it "moves to the first character of the current line or the beginning of the line if it's already on the first character", ->
editSession.setCursorScreenPosition [0,5]
editSession.addCursorAtScreenPosition [1,7]
describe "when soft wrap is on", ->
it "moves to the first character of the current screen line or the beginning of the screen line if it's already on the first character", ->
editSession.setSoftWrapColumn(10)
editSession.setCursorScreenPosition [2,5]
editSession.addCursorAtScreenPosition [8,7]
editSession.moveCursorToFirstCharacterOfLine()
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,2]
editSession.moveCursorToFirstCharacterOfLine()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,0]
describe "when triggered ", ->
it "does not move the cursor", ->
editSession.setCursorBufferPosition([10, 0])
editSession.moveCursorToFirstCharacterOfLine()
expect(editSession.getCursorBufferPosition()).toEqual [10, 0]
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getScreenPosition()).toEqual [2,0]
expect(cursor2.getScreenPosition()).toEqual [8,4]
editSession.moveCursorToFirstCharacterOfLine()
expect(cursor1.getScreenPosition()).toEqual [2,0]
expect(cursor2.getScreenPosition()).toEqual [8,0]
describe "when soft wrap is of", ->
it "moves to the first character of the current line or the beginning of the line if it's already on the first character", ->
editSession.setCursorScreenPosition [0,5]
editSession.addCursorAtScreenPosition [1,7]
editSession.moveCursorToFirstCharacterOfLine()
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,2]
editSession.moveCursorToFirstCharacterOfLine()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,0]
describe ".moveCursorToBeginningOfWord()", ->
it "moves the cursor to the beginning of the word", ->
@@ -313,6 +383,36 @@ describe "EditSession", ->
editSession.moveCursorToBeginningOfWord()
expect(editSession.getCursorBufferPosition()).toEqual [9, 2]
describe ".moveCursorToPreviousWordBoundary()", ->
it "moves the cursor to the previous word boundary", ->
editSession.setCursorBufferPosition [0, 8]
editSession.addCursorAtBufferPosition [2, 0]
editSession.addCursorAtBufferPosition [2, 4]
editSession.addCursorAtBufferPosition [3, 14]
[cursor1, cursor2, cursor3, cursor4] = editSession.getCursors()
editSession.moveCursorToPreviousWordBoundary()
expect(cursor1.getBufferPosition()).toEqual [0, 4]
expect(cursor2.getBufferPosition()).toEqual [1, 30]
expect(cursor3.getBufferPosition()).toEqual [2, 0]
expect(cursor4.getBufferPosition()).toEqual [3, 13]
describe ".moveCursorToNextWordBoundary()", ->
it "moves the cursor to the previous word boundary", ->
editSession.setCursorBufferPosition [0, 8]
editSession.addCursorAtBufferPosition [2, 40]
editSession.addCursorAtBufferPosition [3, 0]
editSession.addCursorAtBufferPosition [3, 30]
[cursor1, cursor2, cursor3, cursor4] = editSession.getCursors()
editSession.moveCursorToNextWordBoundary()
expect(cursor1.getBufferPosition()).toEqual [0, 13]
expect(cursor2.getBufferPosition()).toEqual [3, 0]
expect(cursor3.getBufferPosition()).toEqual [3, 4]
expect(cursor4.getBufferPosition()).toEqual [3, 31]
describe ".moveCursorToEndOfWord()", ->
it "moves the cursor to the end of the word", ->
editSession.setCursorBufferPosition [0, 6]
@@ -355,6 +455,14 @@ describe "EditSession", ->
expect(cursor2.getBufferPosition()).toEqual [1, 13]
expect(cursor3.getBufferPosition()).toEqual [2, 4]
# When the cursor is on whitespace
editSession.setText("ab cde- ")
editSession.setCursorBufferPosition [0,2]
cursor = editSession.getCursor()
editSession.moveCursorToBeginningOfNextWord()
expect(cursor.getBufferPosition()).toEqual [0, 3]
it "does not blow up when there is no next word", ->
editSession.setCursorBufferPosition [Infinity, Infinity]
endPosition = editSession.getCursorBufferPosition()
@@ -668,6 +776,46 @@ describe "EditSession", ->
expect(selection2.getBufferRange()).toEqual [[3,48], [3,51]]
expect(selection2.isReversed()).toBeFalsy()
describe ".selectToPreviousWordBoundary()", ->
it "select to the previous word boundary", ->
editSession.setCursorBufferPosition [0, 8]
editSession.addCursorAtBufferPosition [2, 0]
editSession.addCursorAtBufferPosition [3, 4]
editSession.addCursorAtBufferPosition [3, 14]
editSession.selectToPreviousWordBoundary()
expect(editSession.getSelections().length).toBe 4
[selection1, selection2, selection3, selection4] = editSession.getSelections()
expect(selection1.getBufferRange()).toEqual [[0,8], [0,4]]
expect(selection1.isReversed()).toBeTruthy()
expect(selection2.getBufferRange()).toEqual [[2,0], [1,30]]
expect(selection2.isReversed()).toBeTruthy()
expect(selection3.getBufferRange()).toEqual [[3,4], [3,0]]
expect(selection3.isReversed()).toBeTruthy()
expect(selection4.getBufferRange()).toEqual [[3,14], [3,13]]
expect(selection4.isReversed()).toBeTruthy()
describe ".selectToNextWordBoundary()", ->
it "select to the next word boundary", ->
editSession.setCursorBufferPosition [0, 8]
editSession.addCursorAtBufferPosition [2, 40]
editSession.addCursorAtBufferPosition [4, 0]
editSession.addCursorAtBufferPosition [3, 30]
editSession.selectToNextWordBoundary()
expect(editSession.getSelections().length).toBe 4
[selection1, selection2, selection3, selection4] = editSession.getSelections()
expect(selection1.getBufferRange()).toEqual [[0,8], [0,13]]
expect(selection1.isReversed()).toBeFalsy()
expect(selection2.getBufferRange()).toEqual [[2,40], [3,0]]
expect(selection2.isReversed()).toBeFalsy()
expect(selection3.getBufferRange()).toEqual [[4,0], [4,4]]
expect(selection3.isReversed()).toBeFalsy()
expect(selection4.getBufferRange()).toEqual [[3,30], [3,31]]
expect(selection4.isReversed()).toBeFalsy()
describe ".selectWord()", ->
describe "when the cursor is inside a word", ->
it "selects the entire word", ->
@@ -703,6 +851,31 @@ describe "EditSession", ->
editSession.selectWord()
expect(editSession.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]]
describe ".selectToFirstCharacterOfLine()", ->
it "moves to the first character of the current line or the beginning of the line if it's already on the first character", ->
editSession.setCursorScreenPosition [0,5]
editSession.addCursorAtScreenPosition [1,7]
editSession.selectToFirstCharacterOfLine()
[cursor1, cursor2] = editSession.getCursors()
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor2.getBufferPosition()).toEqual [1,2]
expect(editSession.getSelections().length).toBe 2
[selection1, selection2] = editSession.getSelections()
expect(selection1.getBufferRange()).toEqual [[0,0], [0,5]]
expect(selection1.isReversed()).toBeTruthy()
expect(selection2.getBufferRange()).toEqual [[1,2], [1,7]]
expect(selection2.isReversed()).toBeTruthy()
editSession.selectToFirstCharacterOfLine()
[selection1, selection2] = editSession.getSelections()
expect(selection1.getBufferRange()).toEqual [[0,0], [0,5]]
expect(selection1.isReversed()).toBeTruthy()
expect(selection2.getBufferRange()).toEqual [[1,0], [1,7]]
expect(selection2.isReversed()).toBeTruthy()
describe ".setSelectedBufferRanges(ranges)", ->
it "clears existing selections and creates selections for each of the given ranges", ->
editSession.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]])
@@ -1559,24 +1732,32 @@ describe "EditSession", ->
expect(clipboard.readText()).toBe 'quicksort\nsort'
describe ".cutToEndOfLine()", ->
describe "when nothing is selected", ->
describe "when soft wrap is on", ->
it "cuts up to the end of the line", ->
editSession.setCursorBufferPosition([2, 20])
editSession.addCursorAtBufferPosition([3, 20])
editSession.setSoftWrapColumn(10)
editSession.setCursorScreenPosition([2, 2])
editSession.cutToEndOfLine()
expect(buffer.lineForRow(2)).toBe ' if (items.length'
expect(buffer.lineForRow(3)).toBe ' var pivot = item'
expect(pasteboard.read()[0]).toBe ' <= 1) return items;\ns.shift(), current, left = [], right = [];'
expect(editSession.lineForScreenRow(2).text).toBe '= () {'
describe "when text is selected", ->
it "only cuts the selected text, not to the end of the line", ->
editSession.setSelectedBufferRanges([[[2,20], [2, 30]], [[3, 20], [3, 20]]])
describe "when soft wrap is off", ->
describe "when nothing is selected", ->
it "cuts up to the end of the line", ->
editSession.setCursorBufferPosition([2, 20])
editSession.addCursorAtBufferPosition([3, 20])
editSession.cutToEndOfLine()
expect(buffer.lineForRow(2)).toBe ' if (items.length'
expect(buffer.lineForRow(3)).toBe ' var pivot = item'
expect(pasteboard.read()[0]).toBe ' <= 1) return items;\ns.shift(), current, left = [], right = [];'
editSession.cutToEndOfLine()
describe "when text is selected", ->
it "only cuts the selected text, not to the end of the line", ->
editSession.setSelectedBufferRanges([[[2,20], [2, 30]], [[3, 20], [3, 20]]])
expect(buffer.lineForRow(2)).toBe ' if (items.lengthurn items;'
expect(buffer.lineForRow(3)).toBe ' var pivot = item'
expect(pasteboard.read()[0]).toBe ' <= 1) ret\ns.shift(), current, left = [], right = [];'
editSession.cutToEndOfLine()
expect(buffer.lineForRow(2)).toBe ' if (items.lengthurn items;'
expect(buffer.lineForRow(3)).toBe ' var pivot = item'
expect(pasteboard.read()[0]).toBe ' <= 1) ret\ns.shift(), current, left = [], right = [];'
describe ".copySelectedText()", ->
it "copies selected text onto the clipboard", ->
@@ -1717,10 +1898,10 @@ describe "EditSession", ->
editSession.setSelectedBufferRange([[4, 5], [7, 5]])
editSession.toggleLineCommentsInSelection()
expect(buffer.lineForRow(4)).toBe "// while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe "// current = items.shift();"
expect(buffer.lineForRow(6)).toBe "// current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe "// }"
expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe " // current = items.shift();"
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe " // }"
expect(editSession.getSelectedBufferRange()).toEqual [[4, 8], [7, 8]]
editSession.toggleLineCommentsInSelection()
@@ -1732,9 +1913,9 @@ describe "EditSession", ->
it "does not comment the last line of a non-empty selection if it ends at column 0", ->
editSession.setSelectedBufferRange([[4, 5], [7, 0]])
editSession.toggleLineCommentsInSelection()
expect(buffer.lineForRow(4)).toBe "// while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe "// current = items.shift();"
expect(buffer.lineForRow(6)).toBe "// current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe " // current = items.shift();"
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe " }"
it "uncomments lines if all lines match the comment regex", ->
@@ -1942,91 +2123,6 @@ describe "EditSession", ->
expect(cursor1.getBufferPosition()).toEqual [0,0]
expect(cursor3.getBufferPosition()).toEqual [1,2]
describe "folding", ->
describe ".unfoldAll()", ->
it "unfolds every folded line", ->
initialScreenLineCount = editSession.getScreenLineCount()
editSession.foldBufferRow(0)
editSession.foldBufferRow(1)
expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount
editSession.unfoldAll()
expect(editSession.getScreenLineCount()).toBe initialScreenLineCount
describe ".foldAll()", ->
it "folds every foldable line", ->
editSession.foldAll()
fold1 = editSession.lineForScreenRow(0).fold
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 12]
fold1.destroy()
fold2 = editSession.lineForScreenRow(1).fold
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 9]
fold2.destroy()
fold3 = editSession.lineForScreenRow(4).fold
expect([fold3.getStartRow(), fold3.getEndRow()]).toEqual [4, 7]
describe ".foldBufferRow(bufferRow)", ->
describe "when bufferRow can be folded", ->
it "creates a fold based on the syntactic region starting at the given row", ->
editSession.foldBufferRow(1)
fold = editSession.lineForScreenRow(1).fold
expect(fold.getStartRow()).toBe 1
expect(fold.getEndRow()).toBe 9
describe "when bufferRow can't be folded", ->
it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", ->
editSession.foldBufferRow(8)
fold = editSession.lineForScreenRow(1).fold
expect(fold.getStartRow()).toBe 1
expect(fold.getEndRow()).toBe 9
describe "when the bufferRow is already folded", ->
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
editSession.foldBufferRow(2)
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
expect(editSession.lineForScreenRow(0).fold).not.toBeDefined()
editSession.foldBufferRow(1)
expect(editSession.lineForScreenRow(0).fold).toBeDefined()
describe "when the bufferRow is in a multi-line comment", ->
it "searches upward and downward for surrounding comment lines and folds them as a single fold", ->
buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment")
editSession.foldBufferRow(1)
fold = editSession.lineForScreenRow(1).fold
expect(fold.getStartRow()).toBe 1
expect(fold.getEndRow()).toBe 3
describe "when the bufferRow is a single-line comment", ->
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
buffer.insert([1,0], " //this is a single line comment\n")
editSession.foldBufferRow(1)
fold = editSession.lineForScreenRow(0).fold
expect(fold.getStartRow()).toBe 0
expect(fold.getEndRow()).toBe 13
describe ".unfoldBufferRow(bufferRow)", ->
describe "when bufferRow can be unfolded", ->
it "destroys a fold based on the syntactic region starting at the given row", ->
editSession.foldBufferRow(1)
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
editSession.unfoldBufferRow(1)
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
describe "when bufferRow can't be unfolded", ->
it "does not throw an error", ->
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
editSession.unfoldBufferRow(1)
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
it "maintains cursor buffer position when a folding/unfolding", ->
editSession.setCursorBufferPosition([5,5])
editSession.foldAll()
expect(editSession.getCursorBufferPosition()).toEqual([5,5])
describe ".deleteLine()", ->
it "deletes the first line when the cursor is there", ->
editSession.getCursor().moveToTop()
@@ -2334,55 +2430,10 @@ describe "EditSession", ->
editSession.insertText('foo')
expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1
describe "editor.autoIndentOnPaste", ->
describe "when the text contains multiple lines", ->
beforeEach ->
copyText("function() {\ninside=true\n}\n i=1\n")
editSession.setCursorBufferPosition([2, 0])
it "does not auto-indent pasted text by default", ->
editSession.pasteText()
expect(editSession.lineForBufferRow(2)).toBe "function() {"
expect(editSession.lineForBufferRow(3)).toBe "inside=true"
expect(editSession.lineForBufferRow(4)).toBe "}"
expect(editSession.lineForBufferRow(5)).toBe " i=1"
it "auto-indents pasted text when editor.autoIndentOnPaste is true", ->
config.set("editor.autoIndentOnPaste", true)
editSession.pasteText()
expect(editSession.lineForBufferRow(2)).toBe " function() {"
expect(editSession.lineForBufferRow(3)).toBe " inside=true"
expect(editSession.lineForBufferRow(4)).toBe " }"
expect(editSession.lineForBufferRow(5)).toBe " i=1"
describe "when the text contains no newlines", ->
it "increaseses indent of pasted text when editor.autoIndentOnPaste is true", ->
copyText("var number")
editSession.setCursorBufferPosition([10, 0])
config.set("editor.autoIndentOnPaste", true)
editSession.pasteText()
expect(editSession.lineForBufferRow(10)).toBe " var number"
it "decreaseses indent of pasted text when editor.autoIndentOnPaste is true", ->
copyText(" var number")
editSession.setCursorBufferPosition([10, 0])
config.set("editor.autoIndentOnPaste", true)
editSession.pasteText()
expect(editSession.lineForBufferRow(10)).toBe " var number"
describe "editor.normalizeIndentOnPaste", ->
beforeEach ->
config.set('editor.normalizeIndentOnPaste', true)
it "does not normalize the indentation level of the text when editor.autoIndentOnPaste is true", ->
copyText(" function() {\nvar cool = 1;\n }\n")
config.set('editor.autoIndentOnPaste', true)
editSession.setCursorBufferPosition([5, ])
editSession.pasteText()
expect(editSession.lineForBufferRow(5)).toBe " function() {"
expect(editSession.lineForBufferRow(6)).toBe " var cool = 1;"
expect(editSession.lineForBufferRow(7)).toBe " }"
it "does not normalize the indentation level of the text when editor.normalizeIndentOnPaste is false", ->
copyText(" function() {\nvar cool = 1;\n }\n")
config.set('editor.normalizeIndentOnPaste', false)
+236 -23
Ver Arquivo
@@ -14,19 +14,27 @@ describe "LanguageMode", ->
editSession = project.open('sample.js', autoIndent: false)
{buffer, languageMode} = editSession
describe ".minIndentLevelForRowRange(startRow, endRow)", ->
it "returns the minimum indent level for the given row range", ->
expect(languageMode.minIndentLevelForRowRange(4, 7)).toBe 2
expect(languageMode.minIndentLevelForRowRange(5, 7)).toBe 2
expect(languageMode.minIndentLevelForRowRange(5, 6)).toBe 3
expect(languageMode.minIndentLevelForRowRange(9, 11)).toBe 1
expect(languageMode.minIndentLevelForRowRange(10, 10)).toBe 0
describe ".toggleLineCommentsForBufferRows(start, end)", ->
it "comments/uncomments lines in the given range", ->
languageMode.toggleLineCommentsForBufferRows(4, 7)
expect(buffer.lineForRow(4)).toBe "// while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe "// current = items.shift();"
expect(buffer.lineForRow(6)).toBe "// current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe "// }"
expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe " // current = items.shift();"
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe " // }"
languageMode.toggleLineCommentsForBufferRows(4, 5)
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
expect(buffer.lineForRow(5)).toBe " current = items.shift();"
expect(buffer.lineForRow(6)).toBe "// current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe "// }"
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
expect(buffer.lineForRow(7)).toBe " // }"
describe "fold suggestion", ->
describe ".doesBufferRowStartFold(bufferRow)", ->
@@ -36,12 +44,12 @@ describe "LanguageMode", ->
expect(languageMode.doesBufferRowStartFold(2)).toBeFalsy()
expect(languageMode.doesBufferRowStartFold(3)).toBeFalsy()
describe ".rowRangeForFoldAtBufferRow(bufferRow)", ->
describe ".rowRangeForCodeFoldAtBufferRow(bufferRow)", ->
it "returns the start/end rows of the foldable region starting at the given row", ->
expect(languageMode.rowRangeForFoldAtBufferRow(0)).toEqual [0, 12]
expect(languageMode.rowRangeForFoldAtBufferRow(1)).toEqual [1, 9]
expect(languageMode.rowRangeForFoldAtBufferRow(2)).toBeNull()
expect(languageMode.rowRangeForFoldAtBufferRow(4)).toEqual [4, 7]
expect(languageMode.rowRangeForCodeFoldAtBufferRow(0)).toEqual [0, 12]
expect(languageMode.rowRangeForCodeFoldAtBufferRow(1)).toEqual [1, 9]
expect(languageMode.rowRangeForCodeFoldAtBufferRow(2)).toBeNull()
expect(languageMode.rowRangeForCodeFoldAtBufferRow(4)).toEqual [4, 7]
describe "suggestedIndentForBufferRow", ->
it "returns the suggested indentation based on auto-indent/outdent rules", ->
@@ -50,6 +58,47 @@ describe "LanguageMode", ->
expect(languageMode.suggestedIndentForBufferRow(2)).toBe 2
expect(languageMode.suggestedIndentForBufferRow(9)).toBe 1
describe "rowRangeForParagraphAtBufferRow", ->
describe "with code and comments", ->
beforeEach ->
buffer.setText '''
var quicksort = function () {
/* Single line comment block */
var sort = function(items) {};
/*
A multiline
comment is here
*/
var sort = function(items) {};
// A comment
//
// Multiple comment
// lines
var sort = function(items) {};
// comment line after fn
};
'''
it "will limit paragraph range to comments", ->
range = languageMode.rowRangeForParagraphAtBufferRow(0)
expect(range).toEqual [[0,0], [0,29]]
range = languageMode.rowRangeForParagraphAtBufferRow(10)
expect(range).toEqual [[10,0], [10,14]]
range = languageMode.rowRangeForParagraphAtBufferRow(11)
expect(range).toBeFalsy()
range = languageMode.rowRangeForParagraphAtBufferRow(12)
expect(range).toEqual [[12,0], [13,10]]
range = languageMode.rowRangeForParagraphAtBufferRow(14)
expect(range).toEqual [[14,0], [14,32]]
range = languageMode.rowRangeForParagraphAtBufferRow(15)
expect(range).toEqual [[15,0], [15,26]]
describe "coffeescript", ->
beforeEach ->
atom.activatePackage('coffee-script-tmbundle', sync: true)
@@ -58,17 +107,28 @@ describe "LanguageMode", ->
describe ".toggleLineCommentsForBufferRows(start, end)", ->
it "comments/uncomments lines in the given range", ->
languageMode.toggleLineCommentsForBufferRows(4, 7)
expect(buffer.lineForRow(4)).toBe "# pivot = items.shift()"
expect(buffer.lineForRow(5)).toBe "# left = []"
expect(buffer.lineForRow(6)).toBe "# right = []"
expect(buffer.lineForRow(7)).toBe "# "
languageMode.toggleLineCommentsForBufferRows(4, 6)
expect(buffer.lineForRow(4)).toBe " # pivot = items.shift()"
expect(buffer.lineForRow(5)).toBe " # left = []"
expect(buffer.lineForRow(6)).toBe " # right = []"
languageMode.toggleLineCommentsForBufferRows(4, 5)
expect(buffer.lineForRow(4)).toBe " pivot = items.shift()"
expect(buffer.lineForRow(5)).toBe " left = []"
expect(buffer.lineForRow(6)).toBe "# right = []"
expect(buffer.lineForRow(7)).toBe "# "
expect(buffer.lineForRow(6)).toBe " # right = []"
it "comments/uncomments lines when empty line", ->
languageMode.toggleLineCommentsForBufferRows(4, 7)
expect(buffer.lineForRow(4)).toBe " # pivot = items.shift()"
expect(buffer.lineForRow(5)).toBe " # left = []"
expect(buffer.lineForRow(6)).toBe " # right = []"
expect(buffer.lineForRow(7)).toBe " # "
languageMode.toggleLineCommentsForBufferRows(4, 5)
expect(buffer.lineForRow(4)).toBe " pivot = items.shift()"
expect(buffer.lineForRow(5)).toBe " left = []"
expect(buffer.lineForRow(6)).toBe " # right = []"
expect(buffer.lineForRow(7)).toBe " # "
describe "fold suggestion", ->
describe ".doesBufferRowStartFold(bufferRow)", ->
@@ -79,12 +139,12 @@ describe "LanguageMode", ->
expect(languageMode.doesBufferRowStartFold(3)).toBeFalsy()
expect(languageMode.doesBufferRowStartFold(19)).toBeTruthy()
describe ".rowRangeForFoldAtBufferRow(bufferRow)", ->
describe ".rowRangeForCodeFoldAtBufferRow(bufferRow)", ->
it "returns the start/end rows of the foldable region starting at the given row", ->
expect(languageMode.rowRangeForFoldAtBufferRow(0)).toEqual [0, 20]
expect(languageMode.rowRangeForFoldAtBufferRow(1)).toEqual [1, 17]
expect(languageMode.rowRangeForFoldAtBufferRow(2)).toBeNull()
expect(languageMode.rowRangeForFoldAtBufferRow(19)).toEqual [19, 20]
expect(languageMode.rowRangeForCodeFoldAtBufferRow(0)).toEqual [0, 20]
expect(languageMode.rowRangeForCodeFoldAtBufferRow(1)).toEqual [1, 17]
expect(languageMode.rowRangeForCodeFoldAtBufferRow(2)).toBeNull()
expect(languageMode.rowRangeForCodeFoldAtBufferRow(19)).toEqual [19, 20]
describe "css", ->
beforeEach ->
@@ -139,3 +199,156 @@ describe "LanguageMode", ->
languageMode.toggleLineCommentsForBufferRows(0, 0)
expect(buffer.lineForRow(0)).toBe "// @color: #4D926F;"
describe "folding", ->
beforeEach ->
atom.activatePackage('javascript-tmbundle', sync: true)
editSession = project.open('sample.js', autoIndent: false)
{buffer, languageMode} = editSession
it "maintains cursor buffer position when a folding/unfolding", ->
editSession.setCursorBufferPosition([5,5])
languageMode.foldAll()
expect(editSession.getCursorBufferPosition()).toEqual([5,5])
describe ".unfoldAll()", ->
it "unfolds every folded line", ->
initialScreenLineCount = editSession.getScreenLineCount()
languageMode.foldBufferRow(0)
languageMode.foldBufferRow(1)
expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount
languageMode.unfoldAll()
expect(editSession.getScreenLineCount()).toBe initialScreenLineCount
describe ".foldAll()", ->
it "folds every foldable line", ->
languageMode.foldAll()
fold1 = editSession.lineForScreenRow(0).fold
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 12]
fold1.destroy()
fold2 = editSession.lineForScreenRow(1).fold
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 9]
fold2.destroy()
fold3 = editSession.lineForScreenRow(4).fold
expect([fold3.getStartRow(), fold3.getEndRow()]).toEqual [4, 7]
describe ".foldBufferRow(bufferRow)", ->
describe "when bufferRow can be folded", ->
it "creates a fold based on the syntactic region starting at the given row", ->
languageMode.foldBufferRow(1)
fold = editSession.lineForScreenRow(1).fold
expect(fold.getStartRow()).toBe 1
expect(fold.getEndRow()).toBe 9
describe "when bufferRow can't be folded", ->
it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", ->
languageMode.foldBufferRow(8)
fold = editSession.lineForScreenRow(1).fold
expect(fold.getStartRow()).toBe 1
expect(fold.getEndRow()).toBe 9
describe "when the bufferRow is already folded", ->
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
languageMode.foldBufferRow(2)
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
expect(editSession.lineForScreenRow(0).fold).not.toBeDefined()
languageMode.foldBufferRow(1)
expect(editSession.lineForScreenRow(0).fold).toBeDefined()
describe "when the bufferRow is in a multi-line comment", ->
it "searches upward and downward for surrounding comment lines and folds them as a single fold", ->
buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment")
languageMode.foldBufferRow(1)
fold = editSession.lineForScreenRow(1).fold
expect(fold.getStartRow()).toBe 1
expect(fold.getEndRow()).toBe 3
describe "when the bufferRow is a single-line comment", ->
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
buffer.insert([1,0], " //this is a single line comment\n")
languageMode.foldBufferRow(1)
fold = editSession.lineForScreenRow(0).fold
expect(fold.getStartRow()).toBe 0
expect(fold.getEndRow()).toBe 13
describe ".unfoldBufferRow(bufferRow)", ->
describe "when bufferRow can be unfolded", ->
it "destroys a fold based on the syntactic region starting at the given row", ->
languageMode.foldBufferRow(1)
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
languageMode.unfoldBufferRow(1)
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
describe "when bufferRow can't be unfolded", ->
it "does not throw an error", ->
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
languageMode.unfoldBufferRow(1)
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
describe "folding with comments", ->
beforeEach ->
atom.activatePackage('javascript-tmbundle', sync: true)
editSession = project.open('sample-with-comments.js', autoIndent: false)
{buffer, languageMode} = editSession
describe ".unfoldAll()", ->
it "unfolds every folded line", ->
initialScreenLineCount = editSession.getScreenLineCount()
languageMode.foldBufferRow(0)
languageMode.foldBufferRow(5)
expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount
languageMode.unfoldAll()
expect(editSession.getScreenLineCount()).toBe initialScreenLineCount
describe ".foldAll()", ->
it "folds every foldable line", ->
languageMode.foldAll()
fold1 = editSession.lineForScreenRow(0).fold
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19]
fold1.destroy()
fold2 = editSession.lineForScreenRow(1).fold
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 4]
fold3 = editSession.lineForScreenRow(2).fold.destroy()
fold4 = editSession.lineForScreenRow(3).fold
expect([fold4.getStartRow(), fold4.getEndRow()]).toEqual [6, 8]
describe ".foldAllAtIndentLevel()", ->
it "folds every foldable range at a given indentLevel", ->
languageMode.foldAllAtIndentLevel(2)
fold1 = editSession.lineForScreenRow(6).fold
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [6, 8]
fold1.destroy()
fold2 = editSession.lineForScreenRow(11).fold
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [11, 14]
fold2.destroy()
it "does not fold anything but the indentLevel", ->
languageMode.foldAllAtIndentLevel(0)
fold1 = editSession.lineForScreenRow(0).fold
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19]
fold1.destroy()
fold2 = editSession.lineForScreenRow(5).fold
expect(fold2).toBeFalsy()
describe "css", ->
beforeEach ->
atom.activatePackage('source-tmbundle', sync: true)
atom.activatePackage('css-tmbundle', sync: true)
editSession = project.open('css.css', autoIndent: true)
describe "suggestedIndentForBufferRow", ->
it "does not return negative values (regression)", ->
editSession.setText('.test {\npadding: 0;\n}')
expect(editSession.suggestedIndentForBufferRow(2)).toBe 0
+2 -1
Ver Arquivo
@@ -2,6 +2,7 @@ PaneContainer = require 'pane-container'
Pane = require 'pane'
{View} = require 'space-pen'
$ = require 'jquery'
{dirname} = require 'path'
describe "Pane", ->
[container, view1, view2, editSession1, editSession2, pane] = []
@@ -373,7 +374,7 @@ describe "Pane", ->
pane.trigger 'core:save-as'
expect(atom.showSaveDialogSync).toHaveBeenCalled()
expect(atom.showSaveDialogSync).toHaveBeenCalledWith(dirname(editSession2.getPath()))
expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path')
describe "when the current item does not have a saveAs method", ->
+16
Ver Arquivo
@@ -31,6 +31,22 @@ describe "Project", ->
expect(project.getPath()).toBe '/tmp'
fsUtils.remove('/tmp/atom-test-save-sets-project-path')
describe "when an edit session is deserialized", ->
it "emits an 'edit-session-created' event and stores the edit session", ->
handler = jasmine.createSpy('editSessionCreatedHandler')
project.on 'edit-session-created', handler
editSession1 = project.open("a")
expect(handler.callCount).toBe 1
expect(project.getEditSessions().length).toBe 1
expect(project.getEditSessions()[0]).toBe editSession1
editSession2 = deserialize(editSession1.serialize())
expect(handler.callCount).toBe 2
expect(project.getEditSessions().length).toBe 2
expect(project.getEditSessions()[0]).toBe editSession1
expect(project.getEditSessions()[1]).toBe editSession2
describe ".open(path)", ->
[fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = []
beforeEach ->
+69 -36
Ver Arquivo
@@ -1,46 +1,79 @@
TextMateScopeSelector = require 'text-mate-scope-selector'
describe "TextMateScopeSelector", ->
it "matches the asterix", ->
expect(new TextMateScopeSelector('*').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('*').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.d.c'])).toBeFalsy()
describe ".matches(scopes)", ->
it "matches the asterix", ->
expect(new TextMateScopeSelector('*').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('*').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.*.c').matches(['a.b.d.c'])).toBeFalsy()
it "matches prefixes", ->
expect(new TextMateScopeSelector('a').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['a.b'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['abc'])).toBeFalsy()
it "matches prefixes", ->
expect(new TextMateScopeSelector('a').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['a.b'])).toBeTruthy()
expect(new TextMateScopeSelector('a.b').matches(['a.b.c'])).toBeTruthy()
expect(new TextMateScopeSelector('a').matches(['abc'])).toBeFalsy()
expect(new TextMateScopeSelector('a.b-c').matches(['a.b-c.d'])).toBeTruthy()
expect(new TextMateScopeSelector('a.b').matches(['a.b-d'])).toBeFalsy()
expect(new TextMateScopeSelector('c++').matches(['c++'])).toBeTruthy()
expect(new TextMateScopeSelector('c++').matches(['c'])).toBeFalsy()
expect(new TextMateScopeSelector('a_b_c').matches(['a_b_c'])).toBeTruthy()
expect(new TextMateScopeSelector('a_b_c').matches(['a_b'])).toBeFalsy()
it "matches disjunction", ->
expect(new TextMateScopeSelector('a | b').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['d'])).toBeFalsy()
it "matches filters", ->
expect(new TextMateScopeSelector('R:g').matches(['g'])).toBeTruthy()
it "matches negation", ->
expect(new TextMateScopeSelector('a - c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a-b').matches(['a', 'b'])).toBeFalsy()
it "matches disjunction", ->
expect(new TextMateScopeSelector('a | b').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('a|b|c').matches(['d'])).toBeFalsy()
it "matches conjunction", ->
expect(new TextMateScopeSelector('a & b').matches(['b', 'a'])).toBeTruthy()
expect(new TextMateScopeSelector('a&b&c').matches(['c'])).toBeFalsy()
expect(new TextMateScopeSelector('a&b&c').matches(['a', 'b', 'd'])).toBeFalsy()
it "matches negation", ->
expect(new TextMateScopeSelector('a - c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a - c').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('-c').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('-c').matches(['c', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a-b').matches(['a', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a -b').matches(['a', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a -c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a-c').matches(['a', 'b'])).toBeFalsy()
it "matches composites", ->
expect(new TextMateScopeSelector('a,b,c').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'e'])).toBeFalsy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'c.e'])).toBeTruthy()
it "matches conjunction", ->
expect(new TextMateScopeSelector('a & b').matches(['b', 'a'])).toBeTruthy()
expect(new TextMateScopeSelector('a&b&c').matches(['c'])).toBeFalsy()
expect(new TextMateScopeSelector('a&b&c').matches(['a', 'b', 'd'])).toBeFalsy()
expect(new TextMateScopeSelector('a & -b').matches(['a', 'b', 'd'])).toBeFalsy()
expect(new TextMateScopeSelector('a & -b').matches(['a', 'd'])).toBeTruthy()
it "matches groups", ->
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['d'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['e'])).toBeFalsy()
it "matches composites", ->
expect(new TextMateScopeSelector('a,b,c').matches(['b', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'e'])).toBeFalsy()
expect(new TextMateScopeSelector('a, b, c').matches(['d', 'c.e'])).toBeTruthy()
expect(new TextMateScopeSelector('a,').matches(['a', 'c'])).toBeTruthy()
expect(new TextMateScopeSelector('a,').matches(['b', 'c'])).toBeFalsy()
it "matches paths", ->
expect(new TextMateScopeSelector('a b').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a b').matches(['b', 'a'])).toBeFalsy()
expect(new TextMateScopeSelector('a c').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
expect(new TextMateScopeSelector('a b e').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
it "matches groups", ->
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['c'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['d'])).toBeTruthy()
expect(new TextMateScopeSelector('(a,b) | (c, d)').matches(['e'])).toBeFalsy()
it "matches paths", ->
expect(new TextMateScopeSelector('a b').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a b').matches(['b', 'a'])).toBeFalsy()
expect(new TextMateScopeSelector('a c').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
expect(new TextMateScopeSelector('a b e').matches(['a', 'b', 'c', 'd', 'e'])).toBeTruthy()
describe ".toCssSelector()", ->
it "converts the TextMate scope selector to a CSS selector", ->
expect(new TextMateScopeSelector('a b c').toCssSelector()).toBe '.a .b .c'
expect(new TextMateScopeSelector('a.b.c').toCssSelector()).toBe '.a.b.c'
expect(new TextMateScopeSelector('*').toCssSelector()).toBe '*'
expect(new TextMateScopeSelector('a - b').toCssSelector()).toBe '.a:not(.b)'
expect(new TextMateScopeSelector('a & b').toCssSelector()).toBe '.a .b'
expect(new TextMateScopeSelector('a & -b').toCssSelector()).toBe '.a:not(.b)'
expect(new TextMateScopeSelector('a | b').toCssSelector()).toBe '.a, .b'
expect(new TextMateScopeSelector('a - (b.c d)').toCssSelector()).toBe '.a:not(.b.c .d)'
expect(new TextMateScopeSelector('a, b').toCssSelector()).toBe '.a, .b'
-54
Ver Arquivo
@@ -1,54 +0,0 @@
fsUtils = require 'fs-utils'
path = require 'path'
plist = require 'plist'
TextMateTheme = require 'text-mate-theme'
Theme = require 'theme'
describe "TextMateTheme", ->
[theme, themePath] = []
beforeEach ->
themePath = fsUtils.resolveOnLoadPath(path.join('fixtures', 'test.tmTheme'))
theme = Theme.load(themePath)
afterEach ->
theme.deactivate()
describe ".getRulesets()", ->
rulesets = null
beforeEach ->
rulesets = theme.getRulesets()
it "returns rulesets representing the theme's global style settings", ->
expect(rulesets[0]).toEqual
selector: '.editor, .editor .gutter'
properties:
'background-color': '#141414'
'color': '#F8F8F8'
expect(rulesets[1]).toEqual
selector: '.editor.is-focused .cursor'
properties:
'border-color': '#A7A7A7'
expect(rulesets[2]).toEqual
selector: '.editor.is-focused .selection .region'
properties:
'background-color': "rgba(221, 240, 255, 0.2)"
it "returns an array of objects representing the theme's scope selectors", ->
expect(rulesets[12]).toEqual
comment: "Invalid – Deprecated"
selector: ".invalid.deprecated"
properties:
'color': "#D2A8A1"
'font-style': 'italic'
'text-decoration': 'underline'
expect(rulesets[13]).toEqual
comment: "Invalid – Illegal"
selector: ".invalid.illegal"
properties:
'color': "#F8F8F8"
'background-color': 'rgba(86, 45, 86, 0.75)'
+32
Ver Arquivo
@@ -0,0 +1,32 @@
$ = require 'jquery'
Theme = require 'theme'
ThemeManager = require 'theme-manager'
describe "ThemeManager", ->
describe "when the core.themes config value changes", ->
it "add/removes stylesheets to reflect the new config value", ->
themeManager = new ThemeManager()
spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null
themeManager.load()
config.set('core.themes', [])
expect($('style.userTheme').length).toBe 0
config.set('core.themes', ['atom-dark-syntax'])
expect($('style.userTheme').length).toBe 1
expect($('style.userTheme:eq(0)').attr('id')).toMatch /atom-dark-syntax.less$/
config.set('core.themes', ['atom-light-syntax', 'atom-dark-syntax'])
expect($('style.userTheme').length).toBe 2
expect($('style.userTheme:eq(0)').attr('id')).toMatch /atom-light-syntax.less$/
expect($('style.userTheme:eq(1)').attr('id')).toMatch /atom-dark-syntax.less$/
config.set('core.themes', [])
expect($('style.userTheme').length).toBe 0
describe "when a theme fails to load", ->
it "logs a warning", ->
themeManager = new ThemeManager()
spyOn(console, 'warn')
themeManager.loadTheme('a-theme-that-will-not-be-found')
expect(console.warn).toHaveBeenCalled()
+32 -41
Ver Arquivo
@@ -3,7 +3,7 @@ fsUtils = require 'fs-utils'
path = require 'path'
Theme = require 'theme'
describe "@load(name)", ->
describe "Theme", ->
theme = null
beforeEach ->
@@ -12,48 +12,39 @@ describe "@load(name)", ->
afterEach ->
theme.deactivate()
describe "TextMateTheme", ->
it "applies the theme's stylesheet to the current window", ->
expect($(".editor").css("background-color")).not.toBe("rgb(20, 20, 20)")
describe "when the theme is a file", ->
it "loads and applies css", ->
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
themePath = project.resolve('themes/theme-stylesheet.css')
theme = new Theme(themePath)
expect($(".editor").css("padding-top")).toBe "1234px"
themePath = fsUtils.resolveOnLoadPath(path.join('fixtures', 'test.tmTheme'))
theme = Theme.load(themePath)
expect($(".editor").css("background-color")).toBe("rgb(20, 20, 20)")
it "parses, loads and applies less", ->
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
themePath = project.resolve('themes/theme-stylesheet.less')
theme = new Theme(themePath)
expect($(".editor").css("padding-top")).toBe "4321px"
describe "AtomTheme", ->
describe "when the theme is a file", ->
it "loads and applies css", ->
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
themePath = project.resolve('themes/theme-stylesheet.css')
theme = Theme.load(themePath)
expect($(".editor").css("padding-top")).toBe "1234px"
describe "when the theme contains a package.json file", ->
it "loads and applies stylesheets from package.json in the correct order", ->
expect($(".editor").css("padding-top")).not.toBe("101px")
expect($(".editor").css("padding-right")).not.toBe("102px")
expect($(".editor").css("padding-bottom")).not.toBe("103px")
it "parses, loads and applies less", ->
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
themePath = project.resolve('themes/theme-stylesheet.less')
theme = Theme.load(themePath)
expect($(".editor").css("padding-top")).toBe "4321px"
themePath = project.resolve('themes/theme-with-package-file')
theme = new Theme(themePath)
expect($(".editor").css("padding-top")).toBe("101px")
expect($(".editor").css("padding-right")).toBe("102px")
expect($(".editor").css("padding-bottom")).toBe("103px")
describe "when the theme contains a package.json file", ->
it "loads and applies stylesheets from package.json in the correct order", ->
expect($(".editor").css("padding-top")).not.toBe("101px")
expect($(".editor").css("padding-right")).not.toBe("102px")
expect($(".editor").css("padding-bottom")).not.toBe("103px")
describe "when the theme does not contain a package.json file and is a directory", ->
it "loads all stylesheet files in the directory", ->
expect($(".editor").css("padding-top")).not.toBe "10px"
expect($(".editor").css("padding-right")).not.toBe "20px"
expect($(".editor").css("padding-bottom")).not.toBe "30px"
themePath = project.resolve('themes/theme-with-package-file')
theme = Theme.load(themePath)
expect($(".editor").css("padding-top")).toBe("101px")
expect($(".editor").css("padding-right")).toBe("102px")
expect($(".editor").css("padding-bottom")).toBe("103px")
describe "when the theme does not contain a package.json file and is a directory", ->
it "loads all stylesheet files in the directory", ->
expect($(".editor").css("padding-top")).not.toBe "10px"
expect($(".editor").css("padding-right")).not.toBe "20px"
expect($(".editor").css("padding-bottom")).not.toBe "30px"
themePath = project.resolve('themes/theme-without-package-file')
theme = Theme.load(themePath)
expect($(".editor").css("padding-top")).toBe "10px"
expect($(".editor").css("padding-right")).toBe "20px"
expect($(".editor").css("padding-bottom")).toBe "30px"
themePath = project.resolve('themes/theme-without-package-file')
theme = new Theme(themePath)
expect($(".editor").css("padding-top")).toBe "10px"
expect($(".editor").css("padding-right")).toBe "20px"
expect($(".editor").css("padding-bottom")).toBe "30px"
+24 -5
Ver Arquivo
@@ -12,7 +12,11 @@ describe "TokenizedBuffer", ->
TokenizedBuffer.prototype.chunkSize = 5
jasmine.unspy(TokenizedBuffer.prototype, 'tokenizeInBackground')
startTokenizing = (tokenizedBuffer) ->
tokenizedBuffer.setVisible(true)
fullyTokenize = (tokenizedBuffer) ->
tokenizedBuffer.setVisible(true)
advanceClock() while tokenizedBuffer.firstInvalidRow()?
changeHandler?.reset()
@@ -20,7 +24,7 @@ describe "TokenizedBuffer", ->
beforeEach ->
buffer = project.bufferForPath('sample.js')
tokenizedBuffer = new TokenizedBuffer(buffer)
tokenizedBuffer.setVisible(true)
startTokenizing(tokenizedBuffer)
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
afterEach ->
@@ -300,7 +304,7 @@ describe "TokenizedBuffer", ->
atom.activatePackage('coffee-script-tmbundle', sync: true)
buffer = project.bufferForPath('sample-with-tabs.coffee')
tokenizedBuffer = new TokenizedBuffer(buffer)
tokenizedBuffer.setVisible(true)
startTokenizing(tokenizedBuffer)
afterEach ->
tokenizedBuffer.destroy()
@@ -333,7 +337,6 @@ describe "TokenizedBuffer", ->
//\uD835\uDF97xyz
"""
tokenizedBuffer = new TokenizedBuffer(buffer)
tokenizedBuffer.setVisible(true)
fullyTokenize(tokenizedBuffer)
afterEach ->
@@ -371,7 +374,6 @@ describe "TokenizedBuffer", ->
buffer = project.bufferForPath(null, "<div class='name'><%= User.find(2).full_name %></div>")
tokenizedBuffer = new TokenizedBuffer(buffer)
tokenizedBuffer.setGrammar(syntax.selectGrammar('test.erb'))
tokenizedBuffer.setVisible(true)
fullyTokenize(tokenizedBuffer)
{tokens} = tokenizedBuffer.lineForScreenRow(0)
@@ -390,8 +392,25 @@ describe "TokenizedBuffer", ->
it "returns the correct token (regression)", ->
buffer = project.bufferForPath('sample.js')
tokenizedBuffer = new TokenizedBuffer(buffer)
tokenizedBuffer.setVisible(true)
fullyTokenize(tokenizedBuffer)
expect(tokenizedBuffer.tokenForPosition([1,0]).scopes).toEqual ["source.js"]
expect(tokenizedBuffer.tokenForPosition([1,1]).scopes).toEqual ["source.js"]
expect(tokenizedBuffer.tokenForPosition([1,2]).scopes).toEqual ["source.js", "storage.modifier.js"]
describe ".bufferRangeForScopeAtPosition(selector, position)", ->
beforeEach ->
buffer = project.bufferForPath('sample.js')
tokenizedBuffer = new TokenizedBuffer(buffer)
fullyTokenize(tokenizedBuffer)
describe "when the selector does not match the token at the position", ->
it "returns a falsy value", ->
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.bogus', [0, 1])).toBeFalsy()
describe "when the selector matches a single token at the position", ->
it "returns the range covered by the token", ->
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.storage.modifier.js', [0, 1])).toEqual [[0, 0], [0, 3]]
describe "when the selector matches a run of multiple tokens at the position", ->
it "returns the range covered by all contigous tokens (within a single line)", ->
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.function', [1, 18])).toEqual [[1, 6], [1, 28]]
+15 -2
Ver Arquivo
@@ -21,7 +21,10 @@ class AtomReporter extends View
@div id: 'HTMLReporter', class: 'jasmine_reporter', =>
@div outlet: 'specPopup', class: "spec-popup"
@div outlet: "suites"
@ul outlet: "symbolSummary", class: 'symbolSummary list-unstyled'
@div outlet: 'coreHeader', class: 'symbolHeader'
@ul outlet: 'coreSummary', class: 'symbolSummary list-unstyled'
@div outlet: 'packagesHeader', class: 'symbolHeader'
@ul outlet: 'packagesSummary', class: 'symbolSummary list-unstyled'
@div outlet: "status", class: 'status', =>
@div outlet: "time", class: 'time'
@div outlet: "specCount", class: 'spec-count'
@@ -118,9 +121,19 @@ class AtomReporter extends View
@time.text "#{time[0...-2]}.#{time[-2..]}s"
addSpecs: (specs) ->
coreSpecs = 0
packageSpecs = 0
for spec in specs
symbol = $$ -> @li class: "spec-summary pending spec-summary-#{spec.id}"
@symbolSummary.append symbol
if spec.coreSpec
coreSpecs++
@coreSummary.append symbol
else
packageSpecs++
@packagesSummary.append symbol
@coreHeader.text("Core Specs (#{coreSpecs}):")
@packagesHeader.text("Package Specs (#{packageSpecs}):")
specStarted: (spec) ->
@runningSpecCount++
@@ -1,3 +0,0 @@
module.exports =
activate: -> @activateCalled = true
activateConfig: -> @activateConfigCalled = true
+20
Ver Arquivo
@@ -0,0 +1,20 @@
var quicksort = function () {
/*
this is a multiline comment
it is, I promise
*/
var sort = function(items) {
// This is a collection of
// single line comments.
// Wowza
if (items.length <= 1) return items;
var pivot = items.shift(), current, left = [], right = [];
while(items.length > 0) {
current = items.shift();
current < pivot ? left.push(current) : right.push(current);
}
return sort(left).concat(pivot).concat(sort(right));
};
return sort(Array.apply(this, arguments));
};
-1
Ver Arquivo
@@ -42,7 +42,6 @@ beforeEach ->
window.git = Git.open(window.project.getPath())
window.resetTimeouts()
atom.windowMode = 'editor'
atom.packageStates = {}
spyOn(atom, 'saveWindowState')
syntax.clearGrammarOverrides()
+2
Ver Arquivo
@@ -9,6 +9,8 @@ measure 'spec suite require time', ->
for specPath in fsUtils.listTreeSync(fsUtils.resolveOnLoadPath("spec")) when /-spec\.coffee$/.test specPath
require specPath
spec.coreSpec = true for spec in jasmine.getEnv().currentRunner().specs()
# Run extension specs
for packageDirPath in config.packageDirPaths
for packagePath in fsUtils.listSync(packageDirPath)
@@ -76,3 +76,42 @@ describe "underscore extensions", ->
it "space separates the undasherized/capitalized versions of the namespace and event name", ->
expect(_.humanizeEventName('space:final-frontier')).toBe 'Space: Final Frontier'
expect(_.humanizeEventName('star-trek:the-next-generation')).toBe 'Star Trek: The Next Generation'
describe "_.deepExtend(objects...)", ->
it "copies all key/values from each object into a new object", ->
first =
things:
string: "oh"
boolean: false
anotherArray: ['a', 'b', 'c']
object:
first: 1
second: 2
second =
things:
string: "cool"
array: [1,2,3]
anotherArray: ['aa', 'bb', 'cc']
object:
first: 1
result = _.deepExtend(first, second)
expect(result).toEqual
things:
string: "oh"
boolean: false
array: [1,2,3]
anotherArray: ['a', 'b', 'c']
object:
first: 1
second: 2
describe "_.isSubset(potentialSubset, potentialSuperset)", ->
it "returns whether the first argument is a subset of the second", ->
expect(_.isSubset([1, 2], [1, 2])).toBeTruthy()
expect(_.isSubset([1, 2], [1, 2, 3])).toBeTruthy()
expect(_.isSubset([], [1])).toBeTruthy()
expect(_.isSubset([], [])).toBeTruthy()
expect(_.isSubset([1, 2], [2, 3])).toBeFalsy()
-30
Ver Arquivo
@@ -1,30 +0,0 @@
fsUtils = require 'fs-utils'
path = require 'path'
Theme = require 'theme'
# Internal: Represents a theme that Atom can use.
module.exports =
class AtomTheme extends Theme
# Given a path, this loads it as a stylesheet.
#
# stylesheetPath - A {String} to a stylesheet
loadStylesheet: (stylesheetPath)->
@stylesheets[stylesheetPath] = window.loadStylesheet(stylesheetPath)
# Loads the stylesheets found in a `package.cson` file.
load: ->
if path.extname(@path) in ['.css', '.less']
@loadStylesheet(@path)
else
metadataPath = fsUtils.resolveExtension(path.join(@path, 'package'), ['cson', 'json'])
if fsUtils.isFileSync(metadataPath)
stylesheetNames = fsUtils.readObjectSync(metadataPath)?.stylesheets
if stylesheetNames
for name in stylesheetNames
filename = fsUtils.resolveExtension(path.join(@path, name), ['.css', '.less', ''])
@loadStylesheet(filename)
else
@loadStylesheet(stylesheetPath) for stylesheetPath in fsUtils.listSync(@path, ['.css', '.less'])
super
+6 -45
Ver Arquivo
@@ -2,19 +2,19 @@ fsUtils = require 'fs-utils'
$ = require 'jquery'
_ = require 'underscore'
Package = require 'package'
Theme = require 'theme'
ipc = require 'ipc'
remote = require 'remote'
crypto = require 'crypto'
path = require 'path'
dialog = remote.require 'dialog'
telepath = require 'telepath'
ThemeManager = require 'theme-manager'
window.atom =
loadedThemes: []
loadedPackages: {}
activePackages: {}
packageStates: {}
themes: new ThemeManager()
getLoadSettings: ->
remote.getCurrentWindow().loadSettings
@@ -54,15 +54,6 @@ window.atom =
getActivePackages: ->
_.values(@activePackages)
activatePackageConfigs: ->
@activatePackageConfig(pack.name) for pack in @getLoadedPackages()
activatePackageConfig: (name, options) ->
if pack = @loadPackage(name, options)
@activePackages[pack.name] = pack
pack.activateConfig()
pack
loadPackages: ->
@loadPackage(name) for name in @getAvailablePackageNames() when not @isPackageDisabled(name)
@@ -135,34 +126,6 @@ window.atom =
packages.push(metadata)
packages
loadThemes: ->
themeNames = config.get("core.themes")
themeNames = [themeNames] unless _.isArray(themeNames)
@loadTheme(themeName) for themeName in themeNames
@loadUserStylesheet()
getAvailableThemePaths: ->
themePaths = []
for themeDirPath in config.themeDirPaths
themePaths.push(fsUtils.listSync(themeDirPath, ['', '.tmTheme', '.css', 'less'])...)
_.uniq(themePaths)
getAvailableThemeNames: ->
path.basename(themePath).split('.')[0] for themePath in @getAvailableThemePaths()
loadTheme: (name) ->
@loadedThemes.push Theme.load(name)
loadUserStylesheet: ->
userStylesheetPath = fsUtils.resolve(path.join(config.configDirPath, 'user'), ['css', 'less'])
if fsUtils.isFileSync(userStylesheetPath)
userStyleesheetContents = loadStylesheet(userStylesheetPath)
applyStylesheet(userStylesheetPath, userStyleesheetContents, 'userTheme')
getAtomThemeStylesheets: ->
themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
themeNames = [themeNames] unless _.isArray(themeNames)
open: (url...) ->
ipc.sendChannel('open', [url...])
@@ -172,9 +135,6 @@ window.atom =
newWindow: ->
ipc.sendChannel('new-window')
openConfig: ->
ipc.sendChannel('open-config')
openWindow: (windowSettings) ->
ipc.sendChannel('open-window', windowSettings)
@@ -199,9 +159,10 @@ window.atom =
showSaveDialog: (callback) ->
callback(showSaveDialogSync())
showSaveDialogSync: ->
showSaveDialogSync: (defaultPath) ->
defaultPath ?= project?.getPath()
currentWindow = remote.getCurrentWindow()
dialog.showSaveDialog currentWindow, title: 'Save File'
dialog.showSaveDialog currentWindow, {title: 'Save File', defaultPath}
openDevTools: ->
remote.getCurrentWindow().openDevTools()
@@ -236,7 +197,7 @@ window.atom =
getWindowStatePath: ->
switch @windowMode
when 'config', 'spec'
when 'spec'
filename = @windowMode
when 'editor'
{initialPath} = @getLoadSettings()
@@ -1,36 +0,0 @@
PackageConfigView = require 'package-config-view'
ConfigPanel = require 'config-panel'
packageManager = require 'package-manager'
### Internal ###
module.exports =
class AvailablePackagesConfigPanel extends ConfigPanel
@content: ->
@div class: 'available-packages', =>
@div outlet: 'loadingArea', class: 'alert alert-info loading-area', =>
@span 'Loading available packages\u2026'
@div outlet: 'errorArea', class: 'alert alert-error', =>
@span 'Error fetching available packages.'
@button outlet: 'retry', class: 'btn btn-mini btn-retry', 'Retry'
@div outlet: 'packagesArea'
initialize: (@packageEventEmitter) ->
@retry.on 'click', => @refresh()
@refresh()
refresh: ->
@loadingArea.show()
@errorArea.hide()
packageManager.getAvailable (error, @packages=[]) =>
@loadingArea.hide()
if error?
@errorArea.show()
console.error(error.stack ? error)
else
@packagesArea.empty()
for pack in @packages
@packagesArea.append(new PackageConfigView(pack, @packageEventEmitter))
@packageEventEmitter.trigger('available-packages-loaded', @packages)
getPackageCount: -> @packages.length
-58
Ver Arquivo
@@ -1,58 +0,0 @@
$ = require 'jquery'
{View} = require 'space-pen'
###
# Internal #
###
module.exports =
class ConfigPanel extends View
initialize: ->
@bindFormFields()
@bindEditors()
bindFormFields: ->
for input in @find('input[id]').toArray()
do (input) =>
input = $(input)
name = input.attr('id')
type = input.attr('type')
@observeConfig name, (value) ->
if type is 'checkbox'
input.attr('checked', value)
else
input.val(value) if value
input.on 'change', =>
value = input.val()
if type == 'checkbox'
value = !!input.attr('checked')
else
value = @parseValue(type, value)
config.set(name, value)
bindEditors: ->
for editor in @find('.editor[id]').views()
do (editor) =>
name = editor.attr('id')
type = editor.attr('type')
@observeConfig name, (value) ->
return if value?.toString() == editor.getText()
value ?= ""
editor.setText(value.toString())
editor.getBuffer().on 'contents-modified', =>
config.set(name, @parseValue(type, editor.getText()))
parseValue: (type, value) ->
switch type
when 'int'
intValue = parseInt(value)
value = intValue unless isNaN(intValue)
when 'float'
floatValue = parseFloat(value)
value = floatValue unless isNaN(floatValue)
value = undefined if value == ''
value
+7 -6
Ver Arquivo
@@ -11,8 +11,6 @@ configDirPath = fsUtils.absolute("~/.atom")
bundledPackagesDirPath = path.join(resourcePath, "src/packages")
nodeModulesDirPath = path.join(resourcePath, "node_modules")
bundledThemesDirPath = path.join(resourcePath, "themes")
vendoredPackagesDirPath = path.join(resourcePath, "vendor/packages")
vendoredThemesDirPath = path.join(resourcePath, "vendor/themes")
userThemesDirPath = path.join(configDirPath, "themes")
userPackagesDirPath = path.join(configDirPath, "packages")
userStoragePath = path.join(configDirPath, ".storage")
@@ -24,9 +22,9 @@ userStoragePath = path.join(configDirPath, ".storage")
module.exports =
class Config
configDirPath: configDirPath
themeDirPaths: [userThemesDirPath, bundledThemesDirPath, vendoredThemesDirPath]
bundledPackageDirPaths: [vendoredPackagesDirPath, bundledPackagesDirPath, nodeModulesDirPath]
packageDirPaths: [userPackagesDirPath, vendoredPackagesDirPath, bundledPackagesDirPath]
themeDirPaths: [userThemesDirPath, bundledThemesDirPath]
bundledPackageDirPaths: [bundledPackagesDirPath, nodeModulesDirPath]
packageDirPaths: [userPackagesDirPath, bundledPackagesDirPath]
userPackagesDirPath: userPackagesDirPath
userStoragePath: userStoragePath
lessSearchPaths: [path.join(resourcePath, 'static'), path.join(resourcePath, 'vendor')]
@@ -100,6 +98,9 @@ class Config
### Public ###
getSettings: ->
_.deepExtend(@settings, @defaultSettings)
# Retrieves the setting for the given key.
#
# keyPath - The {String} name of the key to retrieve
@@ -116,7 +117,7 @@ class Config
#
# Returns the value from Atom's default settings, the user's configuration file,
# or `NaN` if the key doesn't exist in either.
getInt: (keyPath, defaultValueWhenFalsy) ->
getInt: (keyPath) ->
parseInt(@get(keyPath))
# Retrieves the setting for the given key as a positive integer.
+106 -38
Ver Arquivo
@@ -128,6 +128,11 @@ class Cursor
range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]]
/^\s+$/.test @editSession.getTextInBufferRange(range)
isInsideWord: ->
{row, column} = @getBufferPosition()
range = [[row, column], [row, Infinity]]
@editSession.getTextInBufferRange(range).search(@wordRegExp()) == 0
# Removes the setting for auto-scroll.
clearAutoscroll: ->
@needsAutoscroll = null
@@ -169,29 +174,53 @@ class Cursor
@editSession.lineForBufferRow(@getBufferRow())
# Moves the cursor up one screen row.
moveUp: (rowCount = 1) ->
{ row, column } = @getScreenPosition()
moveUp: (rowCount = 1, {moveToEndOfSelection}={}) ->
range = @marker.getScreenRange()
if moveToEndOfSelection and not range.isEmpty()
{ row, column } = range.start
else
{ row, column } = @getScreenPosition()
column = @goalColumn if @goalColumn?
@setScreenPosition({row: row - rowCount, column: column})
@goalColumn = column
# Moves the cursor down one screen row.
moveDown: (rowCount = 1) ->
{ row, column } = @getScreenPosition()
moveDown: (rowCount = 1, {moveToEndOfSelection}={}) ->
range = @marker.getScreenRange()
if moveToEndOfSelection and not range.isEmpty()
{ row, column } = range.end
else
{ row, column } = @getScreenPosition()
column = @goalColumn if @goalColumn?
@setScreenPosition({row: row + rowCount, column: column})
@goalColumn = column
# Moves the cursor left one screen column.
moveLeft: ->
{ row, column } = @getScreenPosition()
[row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity]
@setScreenPosition({row, column})
#
# options -
# moveToEndOfSelection: true will move to the left of the selection if a selection
moveLeft: ({moveToEndOfSelection}={}) ->
range = @marker.getScreenRange()
if moveToEndOfSelection and not range.isEmpty()
@setScreenPosition(range.start)
else
{row, column} = @getScreenPosition()
[row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity]
@setScreenPosition({row, column})
# Moves the cursor right one screen column.
moveRight: ->
{ row, column } = @getScreenPosition()
@setScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true)
#
# options -
# moveToEndOfSelection: true will move to the right of the selection if a selection
moveRight: ({moveToEndOfSelection}={}) ->
range = @marker.getScreenRange()
if moveToEndOfSelection and not range.isEmpty()
@setScreenPosition(range.end)
else
{ row, column } = @getScreenPosition()
@setScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true)
# Moves the cursor to the top of the buffer.
moveToTop: ->
@@ -201,20 +230,20 @@ class Cursor
moveToBottom: ->
@setBufferPosition(@editSession.getEofBufferPosition())
# Moves the cursor to the beginning of the buffer line.
# Moves the cursor to the beginning of the screen line.
moveToBeginningOfLine: ->
@setBufferPosition([@getBufferRow(), 0])
@setScreenPosition([@getScreenRow(), 0])
# Moves the cursor to the beginning of the first character in the line.
moveToFirstCharacterOfLine: ->
position = @getBufferPosition()
scanRange = @getCurrentLineBufferRange()
newPosition = null
@editSession.scanInBufferRange /^\s*/, scanRange, ({range}) =>
newPosition = range.end
return unless newPosition
newPosition = [position.row, 0] if newPosition.isEqual(position)
@setBufferPosition(newPosition)
{row, column} = @getScreenPosition()
screenline = @editSession.lineForScreenRow(row)
goalColumn = screenline.text.search(/\S/)
return if goalColumn == -1
goalColumn = 0 if goalColumn == column
@setScreenPosition([row, goalColumn])
# Moves the cursor to the beginning of the buffer line, skipping all whitespace.
skipLeadingWhitespace: ->
@@ -228,7 +257,7 @@ class Cursor
# Moves the cursor to the end of the buffer line.
moveToEndOfLine: ->
@setBufferPosition([@getBufferRow(), Infinity])
@setScreenPosition([@getScreenRow(), Infinity])
# Moves the cursor to the beginning of the word.
moveToBeginningOfWord: ->
@@ -244,6 +273,16 @@ class Cursor
if position = @getBeginningOfNextWordBufferPosition()
@setBufferPosition(position)
# Moves the cursor to the previous word boundary.
moveToPreviousWordBoundary: ->
if position = @getPreviousWordBoundaryBufferPosition()
@setBufferPosition(position)
# Moves the cursor to the next word boundary.
moveToNextWordBoundary: ->
if position = @getMoveNextWordBoundaryBufferPosition()
@setBufferPosition(position)
# Retrieves the buffer position of where the current word starts.
#
# options - A hash with one option:
@@ -265,6 +304,49 @@ class Cursor
beginningOfWordPosition or currentBufferPosition
# Retrieves buffer position of previous word boiundry. It might be on the
# current word, or the previous word.
getPreviousWordBoundaryBufferPosition: (options = {}) ->
currentBufferPosition = @getBufferPosition()
previousNonBlankRow = @editSession.buffer.previousNonBlankRow(currentBufferPosition.row)
scanRange = [[previousNonBlankRow, 0], currentBufferPosition]
beginningOfWordPosition = null
@editSession.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
if range.start.row < currentBufferPosition.row and currentBufferPosition.column > 0
# force it to stop at the beginning of each line
beginningOfWordPosition = new Point(currentBufferPosition.row, 0)
else if range.end.isLessThan(currentBufferPosition)
beginningOfWordPosition = range.end
else
beginningOfWordPosition = range.start
if not beginningOfWordPosition?.isEqual(currentBufferPosition)
stop()
beginningOfWordPosition or currentBufferPosition
# Retrieves buffer position of previous word boiundry. It might be on the
# current word, or the previous word.
getMoveNextWordBoundaryBufferPosition: (options = {}) ->
currentBufferPosition = @getBufferPosition()
scanRange = [currentBufferPosition, @editSession.getEofBufferPosition()]
endOfWordPosition = null
@editSession.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
if range.start.row > currentBufferPosition.row
# force it to stop at the beginning of each line
endOfWordPosition = new Point(range.start.row, 0)
else if range.start.isGreaterThan(currentBufferPosition)
endOfWordPosition = range.start
else
endOfWordPosition = range.end
if not endOfWordPosition?.isEqual(currentBufferPosition)
stop()
endOfWordPosition or currentBufferPosition
# Retrieves the buffer position of where the current word ends.
#
# options - A hash with one option:
@@ -293,7 +375,7 @@ class Cursor
# Returns a {Range}.
getBeginningOfNextWordBufferPosition: (options = {}) ->
currentBufferPosition = @getBufferPosition()
start = if @isSurroundedByWhitespace() then currentBufferPosition else @getEndOfCurrentWordBufferPosition()
start = if @isInsideWord() then @getEndOfCurrentWordBufferPosition() else currentBufferPosition
scanRange = [start, @editSession.getEofBufferPosition()]
beginningOfNextWordPosition = null
@@ -327,21 +409,7 @@ class Cursor
#
# Returns a {Range}.
getCurrentParagraphBufferRange: ->
row = @getBufferRow()
return unless /\w/.test(@editSession.lineForBufferRow(row))
startRow = row
while startRow > 0
break unless /\w/.test(@editSession.lineForBufferRow(startRow - 1))
startRow--
endRow = row
lastRow = @editSession.getLastBufferRow()
while endRow < lastRow
break unless /\w/.test(@editSession.lineForBufferRow(endRow + 1))
endRow++
new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)])
@editSession.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow())
# Retrieves the characters that constitute a word preceeding the current cursor position.
#
+3
Ver Arquivo
@@ -282,6 +282,9 @@ class DisplayBuffer
scopesForBufferPosition: (bufferPosition) ->
@tokenizedBuffer.scopesForPosition(bufferPosition)
bufferRangeForScopeAtPosition: (selector, position) ->
@tokenizedBuffer.bufferRangeForScopeAtPosition(selector, position)
# Retrieves the grammar's token for a buffer position.
#
# bufferPosition - A {Point} in the {Buffer}.
+32 -10
Ver Arquivo
@@ -36,13 +36,13 @@ class EditSession
constructor: (optionsOrState) ->
if optionsOrState instanceof telepath.Document
project.editSessions.push(this)
@state = optionsOrState
{tabLength, softTabs, @softWrap} = @state.toObject()
@buffer = deserialize(@state.get('buffer'))
@setScrollTop(@state.get('scrollTop'))
@setScrollLeft(@state.get('scrollLeft'))
cursorScreenPosition = @state.getObject('cursorScreenPosition')
registerEditSession = true
else
{@buffer, tabLength, softTabs, @softWrap} = optionsOrState
@state = telepath.Document.create
@@ -82,6 +82,8 @@ class EditSession
when 'scrollLeft'
@trigger 'scroll-left-changed', newValue
project.addEditSession(this) if registerEditSession
getViewClass: ->
require 'editor'
@@ -383,9 +385,12 @@ class EditSession
# {Delegates to: DisplayBuffer.bufferRowsForScreenRows}
bufferRowsForScreenRows: (startRow, endRow) -> @displayBuffer.bufferRowsForScreenRows(startRow, endRow)
# {Delegates to: DisplayBuffer.bufferRowsForScreenRows}
# {Delegates to: DisplayBuffer.scopesForBufferPosition}
scopesForBufferPosition: (bufferPosition) -> @displayBuffer.scopesForBufferPosition(bufferPosition)
bufferRangeForScopeAtCursor: (selector) ->
@displayBuffer.bufferRangeForScopeAtPosition(selector, @getCursorBufferPosition())
# {Delegates to: DisplayBuffer.tokenForBufferPosition}
tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition)
@@ -510,7 +515,6 @@ class EditSession
pasteText: (options={}) ->
[text, metadata] = pasteboard.read()
options.autoIndent ?= @shouldAutoIndentPastedText()
if config.get('editor.normalizeIndentOnPaste') and metadata
options.indentBasis ?= metadata.indentBasis
@@ -532,6 +536,9 @@ class EditSession
unfoldAll: ->
@languageMode.unfoldAll()
foldAllAtIndentLevel: (indentLevel) ->
@languageMode.foldAllAtIndentLevel(indentLevel)
# Folds the current row.
foldCurrentRow: ->
bufferRow = @bufferPositionForScreenPosition(@getCursorScreenPosition()).row
@@ -1038,6 +1045,8 @@ class EditSession
getTextInBufferRange: (range) ->
@buffer.getTextInRange(range)
setTextInBufferRange: (range, text) -> @getBuffer().change(range, text)
# Retrieves the range for the current paragraph.
#
# A paragraph is defined as a block of text surrounded by empty lines.
@@ -1056,19 +1065,19 @@ class EditSession
# Moves every cursor up one row.
moveCursorUp: (lineCount) ->
@moveCursors (cursor) -> cursor.moveUp(lineCount)
@moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true)
# Moves every cursor down one row.
moveCursorDown: (lineCount) ->
@moveCursors (cursor) -> cursor.moveDown(lineCount)
@moveCursors (cursor) -> cursor.moveDown(lineCount, moveToEndOfSelection: true)
# Moves every cursor left one column.
moveCursorLeft: ->
@moveCursors (cursor) -> cursor.moveLeft()
@moveCursors (cursor) -> cursor.moveLeft(moveToEndOfSelection: true)
# Moves every cursor right one column.
moveCursorRight: ->
@moveCursors (cursor) -> cursor.moveRight()
@moveCursors (cursor) -> cursor.moveRight(moveToEndOfSelection: true)
# Moves every cursor to the top of the buffer.
moveCursorToTop: ->
@@ -1102,6 +1111,12 @@ class EditSession
moveCursorToBeginningOfNextWord: ->
@moveCursors (cursor) -> cursor.moveToBeginningOfNextWord()
moveCursorToPreviousWordBoundary: ->
@moveCursors (cursor) -> cursor.moveToPreviousWordBoundary()
moveCursorToNextWordBoundary: ->
@moveCursors (cursor) -> cursor.moveToNextWordBoundary()
# Internal:
moveCursors: (fn) ->
fn(cursor) for cursor in @getCursors()
@@ -1147,10 +1162,20 @@ class EditSession
selectToBeginningOfLine: ->
@expandSelectionsBackward (selection) => selection.selectToBeginningOfLine()
# Selects to the first non-whitespace character of the line.
selectToFirstCharacterOfLine: ->
@expandSelectionsBackward (selection) => selection.selectToFirstCharacterOfLine()
# Selects all the text from the current cursor position to the end of the line.
selectToEndOfLine: ->
@expandSelectionsForward (selection) => selection.selectToEndOfLine()
selectToPreviousWordBoundary: ->
@expandSelectionsBackward (selection) => selection.selectToPreviousWordBoundary()
selectToNextWordBoundary: ->
@expandSelectionsForward (selection) => selection.selectToNextWordBoundary()
# Selects the current line.
selectLine: ->
@expandSelectionsForward (selection) => selection.selectLine()
@@ -1288,9 +1313,6 @@ class EditSession
shouldAutoIndent: ->
config.get("editor.autoIndent")
shouldAutoIndentPastedText: ->
config.get("editor.autoIndentOnPaste")
transact: (fn) -> @buffer.transact(fn)
commit: -> @buffer.commit()
-70
Ver Arquivo
@@ -1,70 +0,0 @@
ConfigPanel = require 'config-panel'
Editor = require 'editor'
###
# Internal #
###
module.exports =
class EditorConfigPanel extends ConfigPanel
@content: ->
@form class: 'form-horizontal', =>
@fieldset =>
@legend "Editor Settings"
@div class: 'control-group', =>
@label class: 'control-label', "Font Size:"
@div class: 'controls', =>
@subview "fontSizeEditor", new Editor(mini: true, attributes: {id: 'editor.fontSize', type: 'int', style: 'width: 4em'})
@div class: 'control-group', =>
@label class: 'control-label', "Font Family:"
@div class: 'controls', =>
@subview "fontFamilyEditor", new Editor(mini: true, attributes: {id: 'editor.fontFamily', type: 'string'})
@div class: 'control-group', =>
@div class: 'controls', =>
@div class: 'checkbox', =>
@label for: 'editor.autoIndent', =>
@input id: 'editor.autoIndent', type: 'checkbox'
@text 'Auto-Indent'
@div class: 'controls', =>
@div class: 'checkbox', =>
@label for: 'editor.autoIndentOnPaste', =>
@input id: 'editor.autoIndentOnPaste', type: 'checkbox'
@text 'Auto-Indent on Paste'
@div class: 'controls', =>
@div class: 'checkbox', =>
@label for: 'editor.normalizeIndentOnPaste', =>
@input id: 'editor.normalizeIndentOnPaste', type: 'checkbox'
@text 'Normalize Indent on Paste'
@div class: 'controls', =>
@div class: 'checkbox', =>
@label for: 'editor.showLineNumbers', =>
@input id: 'editor.showLineNumbers', type: 'checkbox'
@text 'Show Line Numbers'
@div class: 'controls', =>
@div class: 'checkbox', =>
@label for: 'editor.showInvisibles', =>
@input id: 'editor.showInvisibles', type: 'checkbox'
@text 'Show Invisible Characters'
@div class: 'controls', =>
@div class: 'checkbox', =>
@label for: 'editor.showIndentGuide', =>
@input id: 'editor.showIndentGuide', type: 'checkbox'
@text 'Show Indent Guide'
@div class: 'control-group', =>
@label class: 'control-label', for: 'editor.preferredLineLength', "Preferred Line Length:"
@div class: 'controls', =>
@subview "preferredLineLengthEditor", new Editor(mini: true, attributes: {id: 'editor.preferredLineLength', type: 'int', style: 'width: 4em'})
@div class: 'control-group', =>
@label class: 'control-label', for: 'editor.nonWordCharacters', "Non-Word Characters:"
@div class: 'controls', =>
@subview "nonWordCharactersEditor", new Editor(mini: true, attributes: {id: 'editor.nonWordCharacters', type: 'string'})
+40 -3
Ver Arquivo
@@ -21,7 +21,6 @@ class Editor extends View
showIndentGuide: false
showLineNumbers: true
autoIndent: true
autoIndentOnPaste: false
normalizeIndentOnPaste: true
nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?-"
preferredLineLength: 80
@@ -142,11 +141,16 @@ class Editor extends View
'editor:move-to-beginning-of-word': @moveCursorToBeginningOfWord
'editor:move-to-end-of-word': @moveCursorToEndOfWord
'editor:move-to-beginning-of-next-word': @moveCursorToBeginningOfNextWord
'editor:move-to-previous-word-boundary': @moveCursorToPreviousWordBoundary
'editor:move-to-next-word-boundary': @moveCursorToNextWordBoundary
'editor:select-to-end-of-line': @selectToEndOfLine
'editor:select-to-beginning-of-line': @selectToBeginningOfLine
'editor:select-to-end-of-word': @selectToEndOfWord
'editor:select-to-beginning-of-word': @selectToBeginningOfWord
'editor:select-to-beginning-of-next-word': @selectToBeginningOfNextWord
'editor:select-to-next-word-boundary': @selectToNextWordBoundary
'editor:select-to-previous-word-boundary': @selectToPreviousWordBoundary
'editor:select-to-first-character-of-line': @selectToFirstCharacterOfLine
'editor:add-selection-below': @addSelectionBelow
'editor:add-selection-above': @addSelectionAbove
'editor:select-line': @selectLine
@@ -175,6 +179,15 @@ class Editor extends View
'editor:fold-current-row': @foldCurrentRow
'editor:unfold-current-row': @unfoldCurrentRow
'editor:fold-selection': @foldSelection
'editor:fold-at-indent-level-1': => @foldAllAtIndentLevel(0)
'editor:fold-at-indent-level-2': => @foldAllAtIndentLevel(1)
'editor:fold-at-indent-level-3': => @foldAllAtIndentLevel(2)
'editor:fold-at-indent-level-4': => @foldAllAtIndentLevel(3)
'editor:fold-at-indent-level-5': => @foldAllAtIndentLevel(4)
'editor:fold-at-indent-level-6': => @foldAllAtIndentLevel(5)
'editor:fold-at-indent-level-7': => @foldAllAtIndentLevel(6)
'editor:fold-at-indent-level-8': => @foldAllAtIndentLevel(7)
'editor:fold-at-indent-level-9': => @foldAllAtIndentLevel(8)
'editor:toggle-line-comments': @toggleLineCommentsInSelection
'editor:log-cursor-scope': @logCursorScope
'editor:checkout-head-revision': @checkoutHead
@@ -238,6 +251,12 @@ class Editor extends View
# {Delegates to: EditSession.moveCursorToFirstCharacterOfLine}
moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine()
# {Delegates to: EditSession.moveCursorToPreviousWordBoundary}
moveCursorToPreviousWordBoundary: -> @activeEditSession.moveCursorToPreviousWordBoundary()
# {Delegates to: EditSession.moveCursorToNextWordBoundary}
moveCursorToNextWordBoundary: -> @activeEditSession.moveCursorToNextWordBoundary()
# {Delegates to: EditSession.moveCursorToEndOfLine}
moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine()
@@ -328,9 +347,18 @@ class Editor extends View
# {Delegates to: EditSession.selectToBeginningOfLine}
selectToBeginningOfLine: -> @activeEditSession.selectToBeginningOfLine()
# {Delegates to: EditSession.selectToFirstCharacterOfLine}
selectToFirstCharacterOfLine: -> @activeEditSession.selectToFirstCharacterOfLine()
# {Delegates to: EditSession.selectToEndOfLine}
selectToEndOfLine: -> @activeEditSession.selectToEndOfLine()
# {Delegates to: EditSession.selectToPreviousWordBoundary}
selectToPreviousWordBoundary: -> @activeEditSession.selectToPreviousWordBoundary()
# {Delegates to: EditSession.selectToNextWordBoundary}
selectToNextWordBoundary: -> @activeEditSession.selectToNextWordBoundary()
# {Delegates to: EditSession.addSelectionBelow}
addSelectionBelow: -> @activeEditSession.addSelectionBelow()
@@ -457,6 +485,8 @@ class Editor extends View
# {Delegates to: EditSession.isFoldedAtCursorRow}
isFoldedAtCursorRow: -> @activeEditSession.isFoldedAtCursorRow()
foldAllAtIndentLevel: (indentLevel) -> @activeEditSession.foldAllAtIndentLevel(indentLevel)
# {Delegates to: EditSession.lineForScreenRow}
lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow)
@@ -619,7 +649,10 @@ class Editor extends View
false if @isFocused
@renderedLines.on 'mousedown', '.fold.line', (e) =>
@activeEditSession.destroyFoldWithId($(e.currentTarget).attr('fold-id'))
id = $(e.currentTarget).attr('fold-id')
marker = @activeEditSession.displayBuffer.getMarker(id)
@activeEditSession.setCursorBufferPosition(marker.getBufferRange().start)
@activeEditSession.destroyFoldWithId(id)
false
@renderedLines.on 'mousedown', (e) =>
@@ -1466,7 +1499,7 @@ class Editor extends View
range = document.createRange()
range.setEnd(textNode, offset)
range.collapse()
leftPixels = range.getClientRects()[0].left - @scrollView.offset().left + @scrollLeft()
leftPixels = range.getClientRects()[0].left - Math.floor(@scrollView.offset().left) + Math.floor(@scrollLeft())
range.detach()
leftPixels
@@ -1527,6 +1560,10 @@ class Editor extends View
reloadGrammar: ->
@activeEditSession.reloadGrammar()
# {Delegates to: EditSession.scopesForBufferPosition}
scopesForBufferPosition: (bufferPosition) ->
@activeEditSession.scopesForBufferPosition(bufferPosition)
# Copies the current file path to the native clipboard.
copyPathToPasteboard: ->
path = @getPath()
-26
Ver Arquivo
@@ -1,26 +0,0 @@
ConfigPanel = require 'config-panel'
{$$} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
###
# Internal #
###
module.exports =
class GeneralConfigPanel extends ConfigPanel
@content: ->
@form id: 'general-config-panel', class: 'form-horizontal', =>
@fieldset =>
@legend "General Settings"
@div class: 'control-group', =>
@div class: 'checkbox', =>
@label for: 'core.hideGitIgnoredFiles', =>
@input id: 'core.hideGitIgnoredFiles', type: 'checkbox'
@text 'Hide Git-Ignored Files'
@div class: 'checkbox', =>
@label for: 'core.autosave', =>
@input id: 'core.autosave', type: 'checkbox'
@text 'Auto-Save on Focus Change'
@@ -1,44 +0,0 @@
_ = require 'underscore'
ConfigPanel = require 'config-panel'
PackageConfigView = require 'package-config-view'
packageManager = require 'package-manager'
### Internal ###
module.exports =
class InstalledPackagesConfigPanel extends ConfigPanel
@content: ->
@div class: 'installed-packages', =>
@div outlet: 'loadingArea', class: 'alert alert-info loading-area', =>
@span 'Loading installed packages\u2026'
@div outlet: 'packagesArea'
initialize: (@packageEventEmitter) ->
@packages = _.sortBy(atom.getAvailablePackageMetadata(), 'name')
packageManager.renderMarkdownInMetadata @packages, =>
@loadingArea.hide()
for pack in @packages
@packagesArea.append(new PackageConfigView(pack, @packageEventEmitter))
@packageEventEmitter.trigger 'installed-packages-loaded', [@packages]
@packageEventEmitter.on 'package-installed', (error, pack) =>
@addPackage(pack) unless error?
@packageEventEmitter.on 'package-uninstalled', (error, pack) =>
@removePackage(pack) unless error?
removePackage: ({name}) ->
@packages = _.reject @packages, (pack) -> pack.name is name
@packagesArea.children("[name=#{name}]").remove()
addPackage: (pack) ->
@packages.push(pack)
@packages = _.sortBy(@packages, 'name')
index = @packages.indexOf(pack)
view = new PackageConfigView(pack, @packageEventEmitter)
if index is 0
@packagesArea.prepend(view)
else if index is @packages.length - 1
@packagesArea.append(view)
else
@packagesArea.children(":eq(#{index})").before(view)
getPackageCount: -> @packages.length
-1
Ver Arquivo
@@ -31,7 +31,6 @@ class Keymap
bindDefaultKeys: ->
$(document).command 'new-window', => atom.newWindow()
$(document).command 'open-user-configuration', => atom.openConfig()
$(document).command 'open', => atom.open()
$(document).command 'open-dev', => atom.openDev()
$(document).command 'toggle-dev-tools', => atom.toggleDevTools()
+2 -2
Ver Arquivo
@@ -55,8 +55,8 @@
'alt-meta-w': 'pane:close-other-items'
'meta-P': 'pane:close'
'meta-n': 'new-window'
'meta-N': 'new-editor'
'meta-n': 'new-editor'
'meta-N': 'new-window'
'meta-,': 'open-user-configuration'
'meta-o': 'open'
'meta-O': 'open-dev'
+11
Ver Arquivo
@@ -5,10 +5,21 @@
'tab': 'editor:indent'
'meta-=': 'editor:auto-indent'
'meta-d': 'editor:delete-line'
'ctrl-[': 'editor:fold-current-row'
'ctrl-]': 'editor:unfold-current-row'
'ctrl-{': 'editor:fold-all'
'ctrl-}': 'editor:unfold-all'
'ctrl-meta-1': 'editor:fold-at-indent-level-1'
'ctrl-meta-2': 'editor:fold-at-indent-level-2'
'ctrl-meta-3': 'editor:fold-at-indent-level-3'
'ctrl-meta-4': 'editor:fold-at-indent-level-4'
'ctrl-meta-5': 'editor:fold-at-indent-level-5'
'ctrl-meta-6': 'editor:fold-at-indent-level-6'
'ctrl-meta-7': 'editor:fold-at-indent-level-7'
'ctrl-meta-8': 'editor:fold-at-indent-level-8'
'ctrl-meta-9': 'editor:fold-at-indent-level-9'
'alt-shift-down': 'editor:add-selection-below'
'alt-shift-up': 'editor:add-selection-above'
'alt-meta-ctrl-f': 'editor:fold-selection'
+91 -26
Ver Arquivo
@@ -81,15 +81,16 @@ class LanguageMode
columnEnd = columnStart + match[2].length
buffer.change([[row, columnStart], [row, columnEnd]], "")
else
indent = @minIndentLevelForRowRange(start, end)
indentString = @editSession.buildIndentString(indent)
for row in [start..end]
buffer.insert([row, 0], commentStartString)
buffer.change([[row, 0], [row, indentString.length]], indentString + commentStartString)
# Folds all the foldable lines in the buffer.
foldAll: ->
for currentRow in [0..@buffer.getLastRow()]
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
continue unless startRow?
@editSession.createFold(startRow, endRow)
# Unfolds all the foldable lines in the buffer.
@@ -97,6 +98,18 @@ class LanguageMode
for row in [@buffer.getLastRow()..0]
fold.destroy() for fold in @editSession.displayBuffer.foldsStartingAtBufferRow(row)
# Fold all comment and code blocks at a given indentLevel
#
# indentLevel - A {Number} indicating indentLevel; 0 based.
foldAllAtIndentLevel: (indentLevel) ->
for currentRow in [0..@buffer.getLastRow()]
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
continue unless startRow?
# assumption: startRow will always be the min indent level for the entire range
if @editSession.indentationForBufferRow(startRow) == indentLevel
@editSession.createFold(startRow, endRow)
# Given a buffer row, creates a fold at it.
#
# bufferRow - A {Number} indicating the buffer row
@@ -104,9 +117,7 @@ class LanguageMode
# Returns the new {Fold}.
foldBufferRow: (bufferRow) ->
for currentRow in [bufferRow..0]
rowRange = @rowRangeForCommentAtBufferRow(currentRow)
rowRange ?= @rowRangeForFoldAtBufferRow(currentRow)
[startRow, endRow] = rowRange ? []
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
continue unless startRow? and startRow <= bufferRow <= endRow
fold = @editSession.displayBuffer.largestFoldStartingAtBufferRow(startRow)
return @editSession.createFold(startRow, endRow) unless fold
@@ -117,13 +128,33 @@ class LanguageMode
unfoldBufferRow: (bufferRow) ->
@editSession.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy()
doesBufferRowStartFold: (bufferRow) ->
return false if @editSession.isBufferRowBlank(bufferRow)
nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow)
return false unless nextNonEmptyRow?
@editSession.indentationForBufferRow(nextNonEmptyRow) > @editSession.indentationForBufferRow(bufferRow)
# Find the row range for a fold at a given bufferRow. Will handle comments
# and code.
#
# bufferRow - A {Number} indicating the buffer row
#
# Returns an {Array} of the [startRow, endRow]. Returns null if no range.
rowRangeForFoldAtBufferRow: (bufferRow) ->
rowRange = @rowRangeForCommentAtBufferRow(bufferRow)
rowRange ?= @rowRangeForCodeFoldAtBufferRow(bufferRow)
rowRange
rowRangeForCommentAtBufferRow: (bufferRow) ->
return unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment()
startRow = bufferRow
for currentRow in [bufferRow-1..0]
break if @buffer.isRowBlank(currentRow)
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
startRow = currentRow
endRow = bufferRow
for currentRow in [bufferRow+1..@buffer.getLastRow()]
break if @buffer.isRowBlank(currentRow)
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
endRow = currentRow
return [startRow, endRow] if startRow isnt endRow
rowRangeForCodeFoldAtBufferRow: (bufferRow) ->
return null unless @doesBufferRowStartFold(bufferRow)
startIndentLevel = @editSession.indentationForBufferRow(bufferRow)
@@ -140,20 +171,43 @@ class LanguageMode
[bufferRow, foldEndRow]
rowRangeForCommentAtBufferRow: (row) ->
return unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
doesBufferRowStartFold: (bufferRow) ->
return false if @editSession.isBufferRowBlank(bufferRow)
nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow)
return false unless nextNonEmptyRow?
@editSession.indentationForBufferRow(nextNonEmptyRow) > @editSession.indentationForBufferRow(bufferRow)
startRow = row
for currentRow in [row-1..0]
break if @buffer.isRowBlank(currentRow)
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
startRow = currentRow
endRow = row
for currentRow in [row+1..@buffer.getLastRow()]
break if @buffer.isRowBlank(currentRow)
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
endRow = currentRow
return [startRow, endRow] if startRow isnt endRow
# Find a row range for a 'paragraph' around specified bufferRow.
# Right now, a paragraph is a block of text bounded by and empty line or a
# block of text that is not the same type (comments next to source code).
rowRangeForParagraphAtBufferRow: (bufferRow) ->
return unless /\w/.test(@editSession.lineForBufferRow(bufferRow))
isRowComment = (row) =>
@editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
if isRowComment(bufferRow)
isOriginalRowComment = true
range = @rowRangeForCommentAtBufferRow(bufferRow)
[firstRow, lastRow] = range or [bufferRow, bufferRow]
else
isOriginalRowComment = false
[firstRow, lastRow] = [0, @editSession.getLastBufferRow()-1]
startRow = bufferRow
while startRow > firstRow
break if isRowComment(startRow - 1) != isOriginalRowComment
break unless /\w/.test(@editSession.lineForBufferRow(startRow - 1))
startRow--
endRow = bufferRow
lastRow = @editSession.getLastBufferRow()
while endRow < lastRow
break if isRowComment(endRow + 1) != isOriginalRowComment
break unless /\w/.test(@editSession.lineForBufferRow(endRow + 1))
endRow++
new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)])
# Given a buffer row, this returns a suggested indentation level.
#
@@ -168,7 +222,7 @@ class LanguageMode
return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
currentLine = @buffer.lineForRow(bufferRow)
precedingRow = @buffer.previousNonBlankRow(bufferRow)
precedingRow = if bufferRow > 0 then bufferRow - 1 else null
return currentIndentLevel unless precedingRow?
precedingLine = @buffer.lineForRow(precedingRow)
@@ -178,7 +232,18 @@ class LanguageMode
return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine)
desiredIndentLevel
Math.max(desiredIndentLevel, 0)
# Calculate a minimum indent level for a range of lines excluding empty lines.
#
# startRow - The row {Number} to start at
# endRow - The row {Number} to end at
#
# Returns a {Number} of the indent level of the block of lines.
minIndentLevelForRowRange: (startRow, endRow) ->
indents = (@editSession.indentationForBufferRow(row) for row in [startRow..endRow] when not @editSession.isBufferRowBlank(row))
indents = [0] unless indents.length
Math.min(indents...)
# Indents all the rows between two buffer row numbers.
#
-48
Ver Arquivo
@@ -1,48 +0,0 @@
ConfigPanel = require 'config-panel'
InstalledPackagesConfigPanel = require 'installed-packages-config-panel'
AvailablePackagesConfigPanel = require 'available-packages-config-panel'
_ = require 'underscore'
EventEmitter = require 'event-emitter'
### Internal ###
class PackageEventEmitter
_.extend PackageEventEmitter.prototype, EventEmitter
module.exports =
class PackageConfigPanel extends ConfigPanel
@content: ->
@div class: 'package-panel', =>
@legend 'Packages'
@ul class: 'nav nav-tabs', =>
@li class: 'active', outlet: 'installedLink', =>
@a 'Installed', =>
@span class: 'badge pull-right', outlet: 'installedCount'
@li outlet: 'availableLink', =>
@a 'Available', =>
@span class: 'badge pull-right', outlet: 'availableCount'
initialize: ->
@packageEventEmitter = new PackageEventEmitter()
@installed = new InstalledPackagesConfigPanel(@packageEventEmitter)
@available = new AvailablePackagesConfigPanel(@packageEventEmitter)
@append(@installed, @available)
@available.hide()
@installedLink.on 'click', =>
@availableLink.removeClass('active')
@available.hide()
@installedLink.addClass('active')
@installed.show()
@availableLink.on 'click', =>
@installedLink.removeClass('active')
@installed.hide()
@availableLink.addClass('active')
@available.show()
@packageEventEmitter.on 'installed-packages-loaded package-installed package-uninstalled', =>
@installedCount.text(@installed.getPackageCount())
@packageEventEmitter.on 'available-packages-loaded', =>
@availableCount.text(@available.getPackageCount())
+3 -3
Ver Arquivo
@@ -77,9 +77,9 @@ class PaneContainer extends View
newPane.focus()
itemDestroyed: (item) ->
state = item.serialize?()
state.uri ?= item.getUri?()
@destroyedItemStates.push(state) if state?
if state = item.serialize?()
state.uri ?= item.getUri?()
@destroyedItemStates.push(state)
itemAdded: (item) ->
itemUri = item.getUri?()
+5 -1
Ver Arquivo
@@ -1,3 +1,4 @@
{dirname} = require 'path'
{View} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
@@ -222,7 +223,10 @@ class Pane extends View
saveItemAs: (item, nextAction) ->
return unless item.saveAs?
path = atom.showSaveDialogSync()
itemPath = item.getUri?()
itemPath = dirname(itemPath) if itemPath
path = atom.showSaveDialogSync(itemPath)
if path
item.saveAs(path)
nextAction?()
+5 -2
Ver Arquivo
@@ -179,6 +179,10 @@ class Project
getEditSessions: ->
new Array(@editSessions...)
addEditSession: (editSession) ->
@editSessions.push editSession
@trigger 'edit-session-created', editSession
### Public ###
# Removes an {EditSession} association from the project.
@@ -297,8 +301,7 @@ class Project
options = _.extend(@defaultEditSessionOptions(), editSessionOptions)
options.buffer = buffer
editSession = new EditSession(options)
@editSessions.push editSession
@trigger 'edit-session-created', editSession
@addEditSession(editSession)
editSession
defaultEditSessionOptions: ->
+3 -3
Ver Arquivo
@@ -31,9 +31,9 @@ class Range
# columnDelta - A {Number} indicating how far from the starting {Point} the range's column should be
#
# Returns the new {Range}.
@fromPointWithDelta: (point, rowDelta, columnDelta) ->
pointA = Point.fromObject(point)
pointB = new Point(point.row + rowDelta, point.column + columnDelta)
@fromPointWithDelta: (pointA, rowDelta, columnDelta) ->
pointA = Point.fromObject(pointA)
pointB = new Point(pointA.row + rowDelta, pointA.column + columnDelta)
new Range(pointA, pointB)
# Creates a new `Range` object based on two {Point}s.
+2 -3
Ver Arquivo
@@ -21,7 +21,9 @@ class RootView extends View
@version: 1
@configDefaults:
autosave: false
ignoredNames: [".git", ".svn", ".DS_Store"]
excludeVcsIgnoredPaths: false
disabledPackages: []
themes: ['atom-dark-ui', 'atom-dark-syntax']
@@ -71,9 +73,6 @@ class RootView extends View
@command 'window:toggle-auto-indent', =>
config.set("editor.autoIndent", !config.get("editor.autoIndent"))
@command 'window:toggle-auto-indent-on-paste', =>
config.set("editor.autoIndentOnPaste", !config.get("editor.autoIndentOnPaste"))
@command 'pane:reopen-closed-item', =>
@panes.reopenItem()
+12
Ver Arquivo
@@ -198,6 +198,10 @@ class Selection
selectToBeginningOfLine: ->
@modifySelection => @cursor.moveToBeginningOfLine()
# Selects all the text from the current cursor position to the first character of the line.
selectToFirstCharacterOfLine: ->
@modifySelection => @cursor.moveToFirstCharacterOfLine()
# Selects all the text from the current cursor position to the end of the line.
selectToEndOfLine: ->
@modifySelection => @cursor.moveToEndOfLine()
@@ -214,6 +218,14 @@ class Selection
selectToBeginningOfNextWord: ->
@modifySelection => @cursor.moveToBeginningOfNextWord()
# Selects text to the previous word boundary.
selectToPreviousWordBoundary: ->
@modifySelection => @cursor.moveToPreviousWordBoundary()
# Selects text to the next word boundary.
selectToNextWordBoundary: ->
@modifySelection => @cursor.moveToNextWordBoundary()
# Moves the selection down one row.
addSelectionBelow: ->
range = (@goalBufferRange ? @getBufferRange()).copy()
+2 -7
Ver Arquivo
@@ -5,6 +5,7 @@ Specificity = require 'specificity'
fsUtils = require 'fs-utils'
EventEmitter = require 'event-emitter'
NullGrammar = require 'null-grammar'
TextMateScopeSelector = require 'text-mate-scope-selector'
### Internal ###
@@ -131,12 +132,6 @@ class Syntax
element[0]
cssSelectorFromScopeSelector: (scopeSelector) ->
scopeSelector.split(', ').map((commaFragment) ->
commaFragment.split(' ').map((spaceFragment) ->
spaceFragment.split('.').map((dotFragment) ->
'.' + dotFragment.replace(/\+/g, '\\+')
).join('')
).join(' ')
).join(', ')
new TextMateScopeSelector(scopeSelector).toCssSelector()
_.extend(Syntax.prototype, EventEmitter)
+6 -2
Ver Arquivo
@@ -27,6 +27,8 @@ class TextMatePackage extends Package
@metadata = {@name}
load: ({sync}={}) ->
@metadata = Package.loadMetadata(@path, true)
if sync
@loadGrammarsSync()
@loadScopedPropertiesSync()
@@ -100,8 +102,9 @@ class TextMatePackage extends Package
selector = syntax.cssSelectorFromScopeSelector(scope) if scope?
@scopedProperties.push({selector, properties})
for {selector, properties} in @scopedProperties
syntax.addProperties(@path, selector, properties)
if @isActive()
for {selector, properties} in @scopedProperties
syntax.addProperties(@path, selector, properties)
loadScopedProperties: (callback) ->
scopedProperties = []
@@ -157,5 +160,6 @@ class TextMatePackage extends Package
increaseIndentPattern: textMateSettings.increaseIndentPattern
decreaseIndentPattern: textMateSettings.decreaseIndentPattern
foldEndPattern: textMateSettings.foldingStopMarker
completions: textMateSettings.completions
)
{ editor: editorProperties } if _.size(editorProperties) > 0
+36 -15
Ver Arquivo
@@ -1,17 +1,24 @@
_ = require 'underscore'
### Internal ###
class SegmentMatcher
constructor: (segment) ->
@segment = segment.join('')
@segment = _.flatten(segment).join('')
matches: (scope) ->
scope is @segment
matches: (scope) -> scope is @segment
toCssSelector: ->
@segment.split('.').map((dotFragment) ->
'.' + dotFragment.replace(/\+/g, '\\+')
).join('')
class TrueMatcher
constructor: ->
matches: ->
true
matches: -> true
toCssSelector: -> '*'
class ScopeMatcher
constructor: (first, others) ->
@@ -27,6 +34,9 @@ class ScopeMatcher
true
toCssSelector: ->
@segments.map((matcher) -> matcher.toCssSelector()).join('')
class PathMatcher
constructor: (first, others) ->
@matchers = [first]
@@ -40,33 +50,44 @@ class PathMatcher
return true unless matcher?
false
toCssSelector: ->
@matchers.map((matcher) -> matcher.toCssSelector()).join(' ')
class OrMatcher
constructor: (@left, @right) ->
matches: (scopes) ->
@left.matches(scopes) or @right.matches(scopes)
matches: (scopes) -> @left.matches(scopes) or @right.matches(scopes)
toCssSelector: -> "#{@left.toCssSelector()}, #{@right.toCssSelector()}"
class AndMatcher
constructor: (@left, @right) ->
matches: (scopes) ->
@left.matches(scopes) and @right.matches(scopes)
matches: (scopes) -> @left.matches(scopes) and @right.matches(scopes)
toCssSelector: ->
if @right instanceof NegateMatcher
"#{@left.toCssSelector()}#{@right.toCssSelector()}"
else
"#{@left.toCssSelector()} #{@right.toCssSelector()}"
class NegateMatcher
constructor: (@left, @right) ->
constructor: (@matcher) ->
matches: (scopes) ->
@left.matches(scopes) and not @right.matches(scopes)
matches: (scopes) -> not @matcher.matches(scopes)
toCssSelector: -> ":not(#{@matcher.toCssSelector()})"
class CompositeMatcher
constructor: (left, operator, right) ->
switch operator
when '|' then @matcher = new OrMatcher(left, right)
when '&' then @matcher = new AndMatcher(left, right)
when '-' then @matcher = new NegateMatcher(left, right)
when '-' then @matcher = new AndMatcher(left, new NegateMatcher(right))
matches: (scopes) ->
@matcher.matches(scopes)
matches: (scopes) -> @matcher.matches(scopes)
toCssSelector: -> @matcher.toCssSelector()
module.exports = {
AndMatcher
+37 -8
Ver Arquivo
@@ -7,7 +7,7 @@ start = _ selector:(selector) _ {
}
segment
= _ segment:[a-zA-Z0-9]+ _ {
= _ segment:([a-zA-Z0-9+_]+[a-zA-Z0-9-+_]*) _ {
return new matchers.SegmentMatcher(segment);
}
@@ -25,23 +25,52 @@ path
return new matchers.PathMatcher(first, others);
}
expression
= path
/ "(" _ selector:selector _ ")" {
group
= "(" _ selector:selector _ ")" {
return selector;
}
filter
= prefix:([LRB]":") _ group:group {
return group;
}
/ prefix:([LRB]":") _ path:path {
return path;
}
expression
= "-" _ filter:filter _ {
return new matchers.NegateMatcher(filter);
}
/ "-" _ group:group _ {
return new matchers.NegateMatcher(group);
}
/ "-" _ path:path _ {
return new matchers.NegateMatcher(path);
}
/ filter
/ group
/ path
composite
= left:expression _ operator:[|&-] _ right:composite {
= left:expression _ operator:[|&-] _ right:composite {
return new matchers.CompositeMatcher(left, operator, right);
}
/ expression
selector
= left:composite _ "," _ right:selector {
return new matchers.OrMatcher(left, right);
= left:composite _ "," _ right:selector? {
if (right)
return new matchers.OrMatcher(left, right);
else
return left;
}
/ composite
+2
Ver Arquivo
@@ -28,3 +28,5 @@ class TextMateScopeSelector
# Return a {Boolean}.
matches: (scopes) ->
@matcher.matches(scopes)
toCssSelector: -> @matcher.toCssSelector()
-97
Ver Arquivo
@@ -1,97 +0,0 @@
_ = require 'underscore'
fsUtils = require 'fs-utils'
plist = require 'plist'
Theme = require 'theme'
### Internal ###
module.exports =
class TextMateTheme extends Theme
@testPath: (path) ->
/\.(tmTheme|plist)$/.test(path)
constructor: (@path) ->
super
@rulesets = []
load: ->
@buildRulesets()
@stylesheets[@path] = @getStylesheet()
super
buildRulesets: ->
{settings} = plist.parseFileSync(@path)
@buildGlobalSettingsRulesets(settings[0])
@buildScopeSelectorRulesets(settings[1..])
getStylesheet: ->
lines = []
for {selector, properties} in @getRulesets()
lines.push("#{selector} {")
for name, value of properties
lines.push " #{name}: #{value};"
lines.push("}\n")
lines.join("\n")
getRulesets: -> @rulesets
buildGlobalSettingsRulesets: ({settings}) ->
{ background, foreground, caret, selection, lineHighlight } = settings
@rulesets.push
selector: '.editor, .editor .gutter'
properties:
'background-color': @translateColor(background)
'color': @translateColor(foreground)
@rulesets.push
selector: '.editor.is-focused .cursor'
properties:
'border-color': @translateColor(caret)
@rulesets.push
selector: '.editor.is-focused .selection .region'
properties:
'background-color': @translateColor(selection)
@rulesets.push
selector: '.editor.is-focused .line-number.cursor-line-no-selection, .editor.is-focused .line.cursor-line'
properties:
'background-color': @translateColor(lineHighlight)
buildScopeSelectorRulesets: (scopeSelectorSettings) ->
for { name, scope, settings } in scopeSelectorSettings
continue unless scope
@rulesets.push
comment: name
selector: @translateScopeSelector(scope)
properties: @translateScopeSelectorSettings(settings)
translateScopeSelector: (textmateScopeSelector) ->
scopes = textmateScopeSelector.split(/\s+/).map (scope) -> '.' + scope
scopes.join(' ')
translateScopeSelectorSettings: ({ foreground, background, fontStyle }) ->
properties = {}
if fontStyle
fontStyles = fontStyle.split(/\s+/)
properties['font-weight'] = 'bold' if _.contains(fontStyles, 'bold')
properties['font-style'] = 'italic' if _.contains(fontStyles, 'italic')
properties['text-decoration'] = 'underline' if _.contains(fontStyles, 'underline')
properties['color'] = @translateColor(foreground) if foreground
properties['background-color'] = @translateColor(background) if background
properties
translateColor: (textmateColor) ->
if textmateColor.length <= 7
textmateColor
else
r = parseInt(textmateColor[1..2], 16)
g = parseInt(textmateColor[3..4], 16)
b = parseInt(textmateColor[5..6], 16)
a = parseInt(textmateColor[7..8], 16)
a = Math.round((a / 255.0) * 100) / 100
"rgba(#{r}, #{g}, #{b}, #{a})"
+47
Ver Arquivo
@@ -0,0 +1,47 @@
path = require 'path'
_ = require 'underscore'
fsUtils = require 'fs-utils'
Theme = require 'theme'
module.exports =
class ThemeManager
constructor: ->
@loadedThemes = []
getAvailablePaths: ->
themePaths = []
for themeDirPath in config.themeDirPaths
themePaths.push(fsUtils.listSync(themeDirPath, ['', '.css', 'less'])...)
_.uniq(themePaths)
getAvailableNames: ->
path.basename(themePath).split('.')[0] for themePath in @getAvailablePaths()
load: ->
config.observe 'core.themes', (themeNames) =>
removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
theme.deactivate() while theme = @loadedThemes.pop()
themeNames = [themeNames] unless _.isArray(themeNames)
@loadTheme(themeName) for themeName in themeNames
@loadUserStylesheet()
loadTheme: (name) ->
try
@loadedThemes.push(new Theme(name))
catch error
console.warn("Failed to load theme #{name}", error.stack ? error)
getUserStylesheetPath: ->
stylesheetPath = fsUtils.resolve(path.join(config.configDirPath, 'user'), ['css', 'less'])
if fsUtils.isFileSync(stylesheetPath)
stylesheetPath
else
null
loadUserStylesheet: ->
if userStylesheetPath = @getUserStylesheetPath()
@userStylesheetPath = userStylesheetPath
userStylesheetContents = loadStylesheet(userStylesheetPath)
applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
+31 -23
Ver Arquivo
@@ -1,38 +1,46 @@
fsUtils = require 'fs-utils'
path = require 'path'
### Internal ###
module.exports =
class Theme
@stylesheets: null
@load: (name) ->
TextMateTheme = require 'text-mate-theme'
AtomTheme = require 'atom-theme'
stylesheetPath: null
stylesheets: null
constructor: (name) ->
@stylesheets = []
if fsUtils.exists(name)
path = name
@stylesheetPath = name
else
path = fsUtils.resolve(config.themeDirPaths..., name, ['', '.tmTheme', '.css', 'less'])
@stylesheetPath = fsUtils.resolve(config.themeDirPaths..., name, ['', '.css', 'less'])
throw new Error("No theme exists named '#{name}'") unless path
throw new Error("No theme exists named '#{name}'") unless @stylesheetPath
theme =
if TextMateTheme.testPath(path)
new TextMateTheme(path)
else
new AtomTheme(path)
theme.load()
theme
constructor: (@path) ->
@stylesheets = {}
@load()
# Loads the stylesheets found in a `package.cson` file.
load: ->
for stylesheetPath, stylesheetContent of @stylesheets
applyStylesheet(stylesheetPath, stylesheetContent, 'userTheme')
if path.extname(@stylesheetPath) in ['.css', '.less']
@loadStylesheet(@stylesheetPath)
else
metadataPath = fsUtils.resolveExtension(path.join(@stylesheetPath, 'package'), ['cson', 'json'])
if fsUtils.isFileSync(metadataPath)
stylesheetNames = fsUtils.readObjectSync(metadataPath)?.stylesheets
if stylesheetNames
for name in stylesheetNames
filename = fsUtils.resolveExtension(path.join(@stylesheetPath, name), ['.css', '.less', ''])
@loadStylesheet(filename)
else
@loadStylesheet(stylesheetPath) for stylesheetPath in fsUtils.listSync(@stylesheetPath, ['.css', '.less'])
# Given a path, this loads it as a stylesheet.
#
# stylesheetPath - A {String} to a stylesheet
loadStylesheet: (stylesheetPath) ->
@stylesheets.push stylesheetPath
content = window.loadStylesheet(stylesheetPath)
window.applyStylesheet(stylesheetPath, content, 'userTheme')
deactivate: ->
for stylesheetPath, stylesheetContent of @stylesheets
removeStylesheet(stylesheetPath)
window.removeStylesheet(stylesheetPath) for stylesheetPath in @stylesheets
+6
Ver Arquivo
@@ -109,6 +109,12 @@ class Token
isOnlyWhitespace: ->
not /\S/.test(@value)
matchesScopeSelector: (selector) ->
targetClasses = selector.replace(/^\.?/, '').split('.')
_.any @scopes, (scope) ->
scopeClasses = scope.split('.')
_.isSubset(targetClasses, scopeClasses)
getValueAsHtml: ({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})->
invisibles ?= {}
html = @value
+31 -1
Ver Arquivo
@@ -183,9 +183,13 @@ class TokenizedBuffer
{ tokens, ruleStack } = @grammar.tokenizeLine(line, ruleStack, row is 0)
new TokenizedLine({tokens, ruleStack, @tabLength, lineEnding})
# FIXME: benogle says: These are actually buffer rows as all buffer rows are
# accounted for in @tokenizedLines
lineForScreenRow: (row) ->
@linesForScreenRows(row, row)[0]
# FIXME: benogle says: These are actually buffer rows as all buffer rows are
# accounted for in @tokenizedLines
linesForScreenRows: (startRow, endRow) ->
@tokenizedLines[startRow..endRow]
@@ -196,8 +200,34 @@ class TokenizedBuffer
@tokenForPosition(position).scopes
tokenForPosition: (position) ->
{row, column} = Point.fromObject(position)
@tokenizedLines[row].tokenAtBufferColumn(column)
tokenStartPositionForPosition: (position) ->
{row, column} = Point.fromObject(position)
column = @tokenizedLines[row].tokenStartColumnForBufferColumn(column)
new Point(row, column)
bufferRangeForScopeAtPosition: (selector, position) ->
position = Point.fromObject(position)
@tokenizedLines[position.row].tokenAtBufferColumn(position.column)
tokenizedLine = @tokenizedLines[position.row]
startIndex = tokenizedLine.tokenIndexAtBufferColumn(position.column)
for index in [startIndex..0]
token = tokenizedLine.tokenAtIndex(index)
break unless token.matchesScopeSelector(selector)
firstToken = token
for index in [startIndex...tokenizedLine.getTokenCount()]
token = tokenizedLine.tokenAtIndex(index)
break unless token.matchesScopeSelector(selector)
lastToken = token
return unless firstToken? and lastToken?
startColumn = tokenizedLine.bufferColumnForToken(firstToken)
endColumn = tokenizedLine.bufferColumnForToken(lastToken) + lastToken.bufferDelta
new Range([position.row, startColumn], [position.row, endColumn])
destroy: ->
@unsubscribe()
+27 -3
Ver Arquivo
@@ -90,11 +90,22 @@ class TokenizedLine
@lineEnding is null
tokenAtBufferColumn: (bufferColumn) ->
@tokens[@tokenIndexAtBufferColumn(bufferColumn)]
tokenIndexAtBufferColumn: (bufferColumn) ->
delta = 0
for token, index in @tokens
delta += token.bufferDelta
return index if delta > bufferColumn
index - 1
tokenStartColumnForBufferColumn: (bufferColumn) ->
delta = 0
for token in @tokens
delta += token.bufferDelta
return token if delta > bufferColumn
token
nextDelta = delta + token.bufferDelta
break if nextDelta > bufferColumn
delta = nextDelta
delta
breakOutAtomicTokens: (inputTokens, tabLength) ->
outputTokens = []
@@ -111,3 +122,16 @@ class TokenizedLine
for scope in token.scopes
return true if _.contains(scope.split('.'), 'comment')
break
false
tokenAtIndex: (index) ->
@tokens[index]
getTokenCount: ->
@tokens.length
bufferColumnForToken: (targetToken) ->
column = 0
for token in @tokens
return column if token is targetToken
column += token.bufferDelta
+5
Ver Arquivo
@@ -1,6 +1,7 @@
$ = require 'jquery'
_ = require 'underscore'
ipc = require 'ipc'
remote = require 'remote'
Subscriber = require 'subscriber'
fsUtils = require 'fs-utils'
@@ -32,6 +33,10 @@ class WindowEventHandler
@subscribe $(document), 'click', 'a', @openLink
@subscribe $(document), 'contextmenu', (e) ->
e.preventDefault()
remote.getCurrentWindow().emit('context-menu', e.pageX, e.pageY)
openLink: (event) =>
location = $(event.target).attr('href')
if location and location[0] isnt '#' and /^https?:\/\//.test(location)
+5 -27
Ver Arquivo
@@ -50,7 +50,7 @@ window.startEditorWindow = ->
restoreDimensions()
config.load()
keymap.loadBundledKeymaps()
atom.loadThemes()
atom.themes.load()
atom.loadPackages()
deserializeEditorWindow()
atom.activatePackages()
@@ -60,20 +60,6 @@ window.startEditorWindow = ->
atom.show()
atom.focus()
window.startConfigWindow = ->
restoreDimensions()
windowEventHandler = new WindowEventHandler
config.load()
keymap.loadBundledKeymaps()
atom.loadThemes()
atom.loadPackages()
deserializeConfigWindow()
atom.activatePackageConfigs()
keymap.loadUserKeymaps()
$(window).on 'unload', -> unloadConfigWindow(); false
atom.show()
atom.focus()
window.unloadEditorWindow = ->
return if not project and not rootView
windowState = atom.getWindowState()
@@ -98,13 +84,6 @@ window.installApmCommand = (callback) ->
commandPath = path.join(window.resourcePath, 'node_modules', '.bin', 'apm')
require('command-installer').install(commandPath, callback)
window.unloadConfigWindow = ->
return if not configView
atom.getWindowState().set('configView', configView.serialize())
configView.remove()
windowEventHandler?.unsubscribe()
window.configView = null
window.onDrop = (e) ->
e.preventDefault()
e.stopPropagation()
@@ -140,11 +119,6 @@ window.deserializeEditorWindow = ->
window.git?.destroy()
window.git = Git.open(projectPath)
window.deserializeConfigWindow = ->
ConfigView = require 'config-view'
window.configView = deserialize(atom.getWindowState('configView')) ? new ConfigView()
$(rootViewParentSelector).append(configView)
window.stylesheetElementForId = (id) ->
$("""head style[id="#{id}"]""")
@@ -233,12 +207,15 @@ window.unregisterDeserializer = (klass) ->
delete deserializers[klass.name]
window.deserialize = (state) ->
return unless state?
if deserializer = getDeserializer(state)
stateVersion = state.get?('version') ? state.version
return if deserializer.version? and deserializer.version isnt stateVersion
if (state instanceof telepath.Document) and not deserializer.acceptsDocuments
state = state.toObject()
deserializer.deserialize(state)
else
console.warn "No deserializer found for", state
window.getDeserializer = (state) ->
return unless state?
@@ -247,6 +224,7 @@ window.getDeserializer = (state) ->
if deferredDeserializers[name]
deferredDeserializers[name]()
delete deferredDeserializers[name]
deserializers[name]
window.requireWithGlobals = (id, globals={}) ->
+14 -18
Ver Arquivo
@@ -32,7 +32,6 @@ class AtomApplication
client.on 'error', createAtomApplication
windows: null
configWindow: null
menu: null
resourcePath: null
installUpdate: null
@@ -80,10 +79,15 @@ class AtomApplication
app.commandLine.appendSwitch 'js-flags', '--harmony_collections'
checkForUpdates: ->
return if /\w{7}/.test @version # Don't check for updates if version is a short sha
versionIsSha = /\w{7}/.test @version
autoUpdater.setAutomaticallyChecksForUpdates true
autoUpdater.checkForUpdatesInBackground()
if versionIsSha
autoUpdater.setAutomaticallyDownloadsUpdates false
autoUpdater.setAutomaticallyChecksForUpdates false
else
autoUpdater.setAutomaticallyDownloadsUpdates true
autoUpdater.setAutomaticallyChecksForUpdates true
autoUpdater.checkForUpdatesInBackground()
buildApplicationMenu: (version, continueUpdate) ->
menus = []
@@ -92,7 +96,7 @@ class AtomApplication
submenu: [
{ label: 'About Atom', selector: 'orderFrontStandardAboutPanel:' }
{ type: 'separator' }
{ label: 'Preferences...', accelerator: 'Command+,', click: => @openConfig() }
{ label: 'Preferences...', accelerator: 'Command+,', click: => console.error("preferences not setup yet") }
{ type: 'separator' }
{ label: 'Hide Atom', accelerator: 'Command+H', selector: 'hide:' }
{ label: 'Hide Others', accelerator: 'Command+Shift+H', selector: 'hideOtherApplications:' }
@@ -124,6 +128,7 @@ class AtomApplication
menus.push
label: 'File'
submenu: [
{ label: 'New Window', accelerator: 'Command+Shift+N', click: => @openPath() }
{ label: 'Open...', accelerator: 'Command+O', click: => @promptForPath() }
{ label: 'Open In Dev Mode...', accelerator: 'Command+Shift+O', click: => @promptForPath(devMode: true) }
]
@@ -175,8 +180,10 @@ class AtomApplication
@installUpdate = quitAndUpdate
@buildApplicationMenu version, quitAndUpdate
ipc.on 'open-config', =>
@openConfig()
ipc.on 'close-without-confirm', (processId, routingId) ->
window = BrowserWindow.fromProcessIdAndRoutingId processId, routingId
window.removeAllListeners 'close'
window.close()
ipc.on 'open', (processId, routingId, pathsToOpen) =>
if pathsToOpen?.length > 0
@@ -239,17 +246,6 @@ class AtomApplication
console.log("Killing process #{pid} failed: #{error.code}")
delete @pidsToOpenWindows[pid]
openConfig: ->
if @configWindow
@configWindow.focus()
return
@configWindow = new AtomWindow
bootstrapScript: 'config-bootstrap'
resourcePath: @resourcePath
@configWindow.browserWindow.on 'destroyed', =>
@configWindow = null
runSpecs: ({exitWhenDone, resourcePath}) ->
if resourcePath isnt @resourcePath and not fs.existsSync(resourcePath)
resourcePath = @resourcePath
+16 -3
Ver Arquivo
@@ -1,4 +1,6 @@
BrowserWindow = require 'browser-window'
Menu = require 'menu'
MenuItem = require 'menu-item'
app = require 'app'
dialog = require 'dialog'
ipc = require 'ipc'
@@ -9,12 +11,15 @@ _ = require 'underscore'
module.exports =
class AtomWindow
browserWindow: null
contextMenu: null
inspectElementMenuItem: null
constructor: (settings={}) ->
{resourcePath, pathToOpen, isSpec} = settings
global.atomApplication.addWindow(this)
@setupNodePath(resourcePath)
@createContextMenu()
@browserWindow = new BrowserWindow show: false, title: 'Atom'
@handleEvents(isSpec)
@@ -77,8 +82,7 @@ class AtomWindow
buttons: ['Close', 'Keep Waiting']
message: 'Editor is not responsing'
detail: 'The editor is not responding. Would you like to force close it or just keep waiting?'
if chosen is 0
setImmediate => @browserWindow.destroy()
@browserWindow.destroy() if chosen is 0
@browserWindow.on 'crashed', =>
chosen = dialog.showMessageBox @browserWindow,
@@ -87,9 +91,13 @@ class AtomWindow
message: 'The editor has crashed'
detail: 'Please report this issue to https://github.com/github/atom/issues'
switch chosen
when 0 then setImmediate => @browserWindow.destroy()
when 0 then @browserWindow.destroy()
when 1 then @browserWindow.restart()
@browserWindow.on 'context-menu', (x, y) =>
@inspectElementMenuItem.click = => @browserWindow.inspectElement(x, y)
@contextMenu.popup(@browserWindow)
if isSpec
# Spec window's web view should always have focus
@browserWindow.on 'blur', =>
@@ -102,6 +110,11 @@ class AtomWindow
else
@browserWindow.once 'window:loaded', => @openPath(pathToOpen)
createContextMenu: ->
@contextMenu = new Menu
@inspectElementMenuItem = new MenuItem(label: 'Inspect Element')
@contextMenu.append(@inspectElementMenuItem)
sendCommand: (command, args...) ->
ipc.sendChannel @browserWindow.getProcessId(), @browserWindow.getRoutingId(), 'command', command, args...
-7
Ver Arquivo
@@ -1,7 +0,0 @@
date = new Date().getTime()
require 'atom'
require 'window'
window.setUpEnvironment('config')
window.startConfigWindow()
console.log "Load time: #{new Date().getTime() - date}"
+1 -2
Ver Arquivo
@@ -52,7 +52,6 @@ setupCrashReporter = ->
setupAutoUpdater = ->
autoUpdater.setFeedUrl 'https://speakeasy.githubapp.com/apps/27/appcast.xml'
autoUpdater.setAutomaticallyDownloadsUpdates true
parseCommandLine = ->
version = app.getVersion()
@@ -60,7 +59,7 @@ parseCommandLine = ->
options.usage """
Atom #{version}
Usage: atom [options] [file ..]
Usage: atom [options] [file ...]
"""
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
@@ -16,7 +16,7 @@
.loading-message {
margin: 5px;
.mini-icon(hourglass);
.octicon(hourglass);
&:before {
font-size: 16px;
@@ -45,10 +45,10 @@
padding-right: @icon-margin;
}
.mini-icon(text-file);
.octicon(file-text);
&.symlink {
.mini-icon(symlink);
.octicon(file-symlink-file);
}
}
@@ -60,7 +60,7 @@
margin-right: @icon-margin;
}
.mini-icon(directory);
.octicon(file-directory);
}
}
}
@@ -1,5 +1,6 @@
$ = require 'jquery'
{$$} = require 'space-pen'
_ = require 'underscore'
Range = require 'range'
SelectList = require 'select-list'
@@ -59,10 +60,17 @@ class AutocompleteView extends SelectList
false
getCompletionsForCursorScope: ->
cursorScope = @editor.scopesForBufferPosition(@editor.getCursorBufferPosition())
completions = syntax.propertiesForScope(cursorScope, 'editor.completions')
completions = completions.map (properties) -> _.valueForKeyPath(properties, 'editor.completions')
_.uniq(_.flatten(completions))
buildWordList: ->
wordHash = {}
matches = @currentBuffer.getText().match(@wordRegex)
wordHash[word] ?= true for word in (matches or [])
wordHash[word] ?= true for word in matches ? []
wordHash[word] ?= true for word in @getCompletionsForCursorScope()
@wordList = Object.keys(wordHash).sort (word1, word2) ->
word1 = word1.toLowerCase()
@@ -433,7 +433,24 @@ describe "AutocompleteView", ->
editor.attachToDom()
editor.insertText('thisIsAReallyReallyReallyLongCompletion ')
editor.moveCursorToBottom()
editor.insertNewline
editor.insertNewline()
editor.insertText('t')
autocomplete.attach()
expect(autocomplete.list.prop('scrollWidth')).toBe autocomplete.list.width()
it "includes completions for the scope's completion preferences", ->
atom.activatePackage('css-tmbundle', sync: true)
cssEditor = new Editor(editSession: project.open('css.css'))
autocomplete = new AutocompleteView(cssEditor)
cssEditor.attachToDom()
cssEditor.moveCursorToEndOfLine()
cssEditor.insertText(' out')
cssEditor.moveCursorToEndOfLine()
autocomplete.attach()
expect(autocomplete.list.find('li').length).toBe 4
expect(autocomplete.list.find('li:eq(0)')).toHaveText 'outline'
expect(autocomplete.list.find('li:eq(1)')).toHaveText 'outline-color'
expect(autocomplete.list.find('li:eq(2)')).toHaveText 'outline-style'
expect(autocomplete.list.find('li:eq(3)')).toHaveText 'outline-width'
-36
Ver Arquivo
@@ -1,36 +0,0 @@
module.exports =
activate: ->
rootView.command 'autoflow:reflow-paragraph', '.editor', (e) =>
@reflowParagraph(e.currentTargetView())
reflowParagraph: (editor) ->
if range = editor.getCurrentParagraphBufferRange()
editor.getBuffer().change(range, @reflow(editor.getTextInRange(range)))
reflow: (text) ->
wrapColumn = config.getPositiveInt('editor.preferredLineLength', 80)
lines = []
currentLine = []
currentLineLength = 0
for segment in @segmentText(text.replace(/\n/g, ' '))
if @wrapSegment(segment, currentLineLength, wrapColumn)
lines.push(currentLine.join(''))
currentLine = []
currentLineLength = 0
currentLine.push(segment)
currentLineLength += segment.length
lines.push(currentLine.join(''))
lines.join('\n').replace(/\s+\n/g, '\n')
wrapSegment: (segment, currentLineLength, wrapColumn) ->
/\w/.test(segment) and
(currentLineLength + segment.length > wrapColumn) and
(currentLineLength > 0 or segment.length < wrapColumn)
segmentText: (text) ->
segments = []
re = /[\s]+|[^\s]+/g
segments.push(match[0]) while match = re.exec(text)
segments
@@ -0,0 +1,2 @@
'.editor':
'alt-meta-q': 'autoflow:reflow-paragraph'
+50
Ver Arquivo
@@ -0,0 +1,50 @@
module.exports =
activate: ->
rootView.eachEditor (editor) =>
return unless editor.attached and editor.getPane()?
editor.command 'autoflow:reflow-paragraph', (e) =>
@reflowParagraph(e.currentTargetView())
reflowParagraph: (editor) ->
if range = editor.getCurrentParagraphBufferRange()
wrapColumn = config.getPositiveInt('editor.preferredLineLength', 80)
editor.getBuffer().change(range, @reflow(editor.getTextInRange(range), {wrapColumn}))
reflow: (text, {wrapColumn}) ->
paragraphs = []
paragraphBlocks = text.split(/\n\s*\n/g)
for block in paragraphBlocks
# TODO: this could be more language specific. Use the actual comment char.
linePrefix = block.match(/^\s*[\/#*-]*\s*/g)[0]
blockLines = block.split('\n')
blockLines = (blockLine.replace(new RegExp('^' + linePrefix.replace('*', '\\*')), '') for blockLine in blockLines) if linePrefix
lines = []
currentLine = []
currentLineLength = linePrefix.length
for segment in @segmentText(blockLines.join(' '))
if @wrapSegment(segment, currentLineLength, wrapColumn)
lines.push(linePrefix + currentLine.join(''))
currentLine = []
currentLineLength = linePrefix.length
currentLine.push(segment)
currentLineLength += segment.length
lines.push(linePrefix + currentLine.join(''))
paragraphs.push(lines.join('\n').replace(/\s+\n/g, '\n'))
paragraphs.join('\n\n')
wrapSegment: (segment, currentLineLength, wrapColumn) ->
/\w/.test(segment) and
(currentLineLength + segment.length > wrapColumn) and
(currentLineLength > 0 or segment.length < wrapColumn)
segmentText: (text) ->
segments = []
re = /[\s]+|[^\s]+/g
segments.push(match[0]) while match = re.exec(text)
segments
+3 -1
Ver Arquivo
@@ -1,2 +1,4 @@
'main': 'autoflow'
'main': './lib/autoflow'
'description': 'Format the current paragraph to have lines no longer than 80 characters.\n\nThis packages uses the config value of `editor.preferredLineLength` when set.'
'activationEvents':
'autoflow:reflow-paragraph': '.editor'
+119 -7
Ver Arquivo
@@ -2,15 +2,18 @@ RootView = require 'root-view'
describe "Autoflow package", ->
editor = null
beforeEach ->
window.rootView = new RootView
rootView.open()
atom.activatePackage('autoflow')
editor = rootView.getActiveView()
config.set('editor.preferredLineLength', 30)
autoflow = null
describe "autoflow:reflow-paragraph", ->
beforeEach ->
window.rootView = new RootView
rootView.open()
atom.activatePackage('autoflow')
rootView.attachToDom()
editor = rootView.getActiveView()
config.set('editor.preferredLineLength', 30)
it "rearranges line breaks in the current paragraph to ensure lines are shorter than config.editor.preferredLineLength", ->
editor.setText """
This is a preceding paragraph, which shouldn't be modified by a reflow of the following paragraph.
@@ -52,3 +55,112 @@ describe "Autoflow package", ->
and these are some smaller
words
"""
describe "reflowing text", ->
beforeEach ->
window.rootView = new RootView
autoflow = atom.activatePackage('autoflow', immediate: true).mainModule
it 'respects current paragraphs', ->
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh id magna ullamcorper sagittis. Maecenas
et enim eu orci tincidunt adipiscing
aliquam ligula.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus gravida
nibh id magna ullamcorper
tincidunt adipiscing lacinia a dui. Etiam quis erat dolor.
rutrum nisl fermentum rhoncus. Duis blandit ligula facilisis fermentum.
'''
res = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh
id magna ullamcorper sagittis. Maecenas et enim eu orci tincidunt adipiscing
aliquam ligula.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh
id magna ullamcorper tincidunt adipiscing lacinia a dui. Etiam quis erat dolor.
rutrum nisl fermentum rhoncus. Duis blandit ligula facilisis fermentum.
'''
expect(autoflow.reflow(text, wrapColumn: 80)).toEqual res
it 'respects indentation', ->
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh id magna ullamcorper sagittis. Maecenas
et enim eu orci tincidunt adipiscing
aliquam ligula.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus gravida
nibh id magna ullamcorper
tincidunt adipiscing lacinia a dui. Etiam quis erat dolor.
rutrum nisl fermentum rhoncus. Duis blandit ligula facilisis fermentum
'''
res = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh
id magna ullamcorper sagittis. Maecenas et enim eu orci tincidunt adipiscing
aliquam ligula.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida
nibh id magna ullamcorper tincidunt adipiscing lacinia a dui. Etiam quis
erat dolor. rutrum nisl fermentum rhoncus. Duis blandit ligula facilisis
fermentum
'''
expect(autoflow.reflow(text, wrapColumn: 80)).toEqual res
it 'respects prefixed text (comments!)', ->
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh id magna ullamcorper sagittis. Maecenas
et enim eu orci tincidunt adipiscing
aliquam ligula.
# Lorem ipsum dolor sit amet, consectetur adipiscing elit.
# Phasellus gravida
# nibh id magna ullamcorper
# tincidunt adipiscing lacinia a dui. Etiam quis erat dolor.
# rutrum nisl fermentum rhoncus. Duis blandit ligula facilisis fermentum
'''
res = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida nibh
id magna ullamcorper sagittis. Maecenas et enim eu orci tincidunt adipiscing
aliquam ligula.
# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida
# nibh id magna ullamcorper tincidunt adipiscing lacinia a dui. Etiam quis
# erat dolor. rutrum nisl fermentum rhoncus. Duis blandit ligula facilisis
# fermentum
'''
expect(autoflow.reflow(text, wrapColumn: 80)).toEqual res
it 'respects multiple prefixes (js/c comments)', ->
text = '''
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida
et enim eu orci tincidunt adipiscing
aliquam ligula.
'''
res = '''
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida et
// enim eu orci tincidunt adipiscing aliquam ligula.
'''
expect(autoflow.reflow(text, wrapColumn: 80)).toEqual res
it 'properly handles * prefix', ->
text = '''
* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida
et enim eu orci tincidunt adipiscing
aliquam ligula.
* soidjfiojsoidj foi
'''
res = '''
* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus gravida et
* enim eu orci tincidunt adipiscing aliquam ligula.
* soidjfiojsoidj foi
'''
expect(autoflow.reflow(text, wrapColumn: 80)).toEqual res
@@ -0,0 +1,5 @@
'.editor':
'meta-shift-f2': 'bookmarks:view-all'
'meta-f2': 'bookmarks:toggle-bookmark'
'f2': 'bookmarks:jump-to-next-bookmark'
'shift-f2': 'bookmarks:jump-to-previous-bookmark'
@@ -0,0 +1,77 @@
path = require 'path'
{$$} = require 'space-pen'
SelectList = require 'select-list'
module.exports =
class BookmarksView extends SelectList
@viewClass: -> "#{super} bookmarks-view overlay from-top"
filterKey: 'bookmarkFilterText'
initialize: ->
super
toggle: ->
if @hasParent()
@cancel()
else
@populateBookmarks()
@attach()
getFilterText: (bookmark) ->
segments = []
bookmarkRow = bookmark.getStartPosition().row
segments.push(bookmarkRow)
if bufferPath = bookmark.buffer.getPath()
segments.push(bufferPath)
if lineText = @getLineText(bookmark)
segments.push(lineText)
segments.join(' ')
getLineText: (bookmark) ->
bookmark.buffer.lineForRow(bookmark.getStartPosition().row)?.trim()
populateBookmarks: ->
markers = []
attributes = class: 'bookmark'
for buffer in project.getBuffers()
for marker in buffer.findMarkers(attributes)
marker.bookmarkFilterText = @getFilterText(marker)
markers.push(marker)
@setArray(markers)
itemForElement: (bookmark) ->
bookmarkRow = bookmark.getStartPosition().row
if filePath = bookmark.buffer.getPath()
bookmarkLocation = "#{path.basename(filePath)}:#{bookmarkRow + 1}"
else
bookmarkLocation = "untitled:#{bookmarkRow + 1}"
lineText = @getLineText(bookmark)
$$ ->
if lineText
@li class: 'bookmark two-lines', =>
@div bookmarkLocation, class: 'primary-line'
@div lineText, class: 'secondary-line line-text'
else
@li class: 'bookmark', =>
@div bookmarkLocation, class: 'primary-line'
getEmptyMessage: (itemCount) ->
if itemCount is 0
'No bookmarks found'
else
super
confirmed : (bookmark) ->
for editor in rootView.getEditors()
if editor.getBuffer() is bookmark.buffer
editor.activeEditSession.setSelectedBufferRange(bookmark.getRange(), autoscroll: true)
attach: ->
super
rootView.append(this)
@miniEditor.focus()
+108
Ver Arquivo
@@ -0,0 +1,108 @@
_ = require 'underscore'
shell = require 'shell'
module.exports =
class Bookmarks
@activate: ->
bookmarksList = null
rootView.command 'bookmarks:view-all', ->
unless bookmarksList?
BookmarksListView = require './bookmarks-view'
bookmarksList = new BookmarksListView()
bookmarksList.toggle()
rootView.eachEditor (editor) ->
new Bookmarks(editor) if editor.attached and editor.getPane()?
editor: null
constructor: (@editor) ->
@gutter = @editor.gutter
@editor.on 'editor:display-updated', @renderBookmarkMarkers
@editor.command 'bookmarks:toggle-bookmark', @toggleBookmark
@editor.command 'bookmarks:jump-to-next-bookmark', @jumpToNextBookmark
@editor.command 'bookmarks:jump-to-previous-bookmark', @jumpToPreviousBookmark
toggleBookmark: =>
cursors = @editor.getCursors()
for cursor in cursors
position = cursor.getBufferPosition()
bookmarks = @findBookmarkMarkers(startBufferRow: position.row)
if bookmarks and bookmarks.length
bookmark.destroy() for bookmark in bookmarks
else
newmark = @createBookmarkMarker(position.row)
@renderBookmarkMarkers()
jumpToNextBookmark: =>
@jumpToBookmark('getNextBookmark')
jumpToPreviousBookmark: =>
@jumpToBookmark('getPreviousBookmark')
renderBookmarkMarkers: =>
return unless @gutter.isVisible()
@gutter.find(".line-number.bookmarked").removeClass('bookmarked')
markers = @findBookmarkMarkers()
for marker in markers
row = marker.getBufferRange().start.row
@gutter.find(".line-number[lineNumber=#{row}]").addClass('bookmarked')
### Internal ###
jumpToBookmark: (getBookmarkFunction) =>
cursor = @editor.getCursor()
position = cursor.getBufferPosition()
bookmarkMarker = @[getBookmarkFunction](position.row)
if bookmarkMarker
@editor.activeEditSession.setSelectedBufferRange(bookmarkMarker.getBufferRange(), autoscroll: true)
else
shell.beep()
getPreviousBookmark: (bufferRow) ->
markers = @findBookmarkMarkers()
return null unless markers.length
return markers[0] if markers.length == 1
bookmarkIndex = _.sortedIndex markers, bufferRow, (marker) ->
if marker.getBufferRange then marker.getBufferRange().start.row else marker
bookmarkIndex--
bookmarkIndex = markers.length - 1 if bookmarkIndex < 0
markers[bookmarkIndex]
getNextBookmark: (bufferRow) ->
markers = @findBookmarkMarkers()
return null unless markers.length
return markers[0] if markers.length == 1
bookmarkIndex = _.sortedIndex markers, bufferRow, (marker) ->
if marker.getBufferRange then marker.getBufferRange().start.row else marker
bookmarkIndex++ if markers[bookmarkIndex] and markers[bookmarkIndex].getBufferRange().start.row == bufferRow
bookmarkIndex = 0 if bookmarkIndex >= markers.length
markers[bookmarkIndex]
createBookmarkMarker: (bufferRow) ->
range = [[bufferRow, 0], [bufferRow, 0]]
# TODO: use the 'surround' strategy when collaboration is merged in
@displayBuffer().markBufferRange(range, @bookmarkMarkerAttributes(invalidationStrategy: 'never'))
findBookmarkMarkers: (attributes={}) ->
@displayBuffer().findMarkers(@bookmarkMarkerAttributes(attributes))
bookmarkMarkerAttributes: (attributes={}) ->
_.extend(attributes, class: 'bookmark', displayBufferId: @displayBuffer().id)
displayBuffer: ->
@editor.activeEditSession.displayBuffer
+2
Ver Arquivo
@@ -0,0 +1,2 @@
'main': './lib/bookmarks'
'description': 'Can mark lines, then jump back to them'
@@ -0,0 +1,173 @@
RootView = require 'root-view'
_ = require 'underscore'
shell = require 'shell'
describe "Bookmarks package", ->
[editor, editSession, displayBuffer] = []
beforeEach ->
window.rootView = new RootView
rootView.open('sample.js')
rootView.enableKeymap()
atom.activatePackage('bookmarks', immediate: true)
rootView.attachToDom()
editor = rootView.getActiveView()
editSession = editor.activeEditSession
displayBuffer = editSession.displayBuffer
spyOn(shell, 'beep')
describe "toggling bookmarks", ->
it "creates a marker when toggled", ->
editSession.setCursorBufferPosition([3, 10])
expect(displayBuffer.findMarkers(class: 'bookmark').length).toEqual 0
editor.trigger 'bookmarks:toggle-bookmark'
markers = displayBuffer.findMarkers(class: 'bookmark')
expect(markers.length).toEqual 1
expect(markers[0].getBufferRange()).toEqual [[3, 0], [3, 0]]
it "removes marker when toggled", ->
editSession.setCursorBufferPosition([3, 10])
expect(displayBuffer.findMarkers(class: 'bookmark').length).toEqual 0
editor.trigger 'bookmarks:toggle-bookmark'
expect(displayBuffer.findMarkers(class: 'bookmark').length).toEqual 1
editor.trigger 'bookmarks:toggle-bookmark'
expect(displayBuffer.findMarkers(class: 'bookmark').length).toEqual 0
it "toggles proper classes on proper gutter row", ->
editSession.setCursorBufferPosition([3, 10])
expect(editor.find('.bookmarked').length).toEqual 0
editor.trigger 'bookmarks:toggle-bookmark'
lines = editor.find('.bookmarked')
expect(lines.length).toEqual 1
expect(lines.attr('linenumber')).toEqual '3'
editor.trigger 'bookmarks:toggle-bookmark'
expect(editor.find('.bookmarked').length).toEqual 0
describe "jumping between bookmarks", ->
it "doesnt die when no bookmarks", ->
editSession.setCursorBufferPosition([5, 10])
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [5, 10]
expect(shell.beep.callCount).toBe 1
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [5, 10]
expect(shell.beep.callCount).toBe 2
describe "with one bookmark", ->
beforeEach ->
editSession.setCursorBufferPosition([2, 0])
editor.trigger 'bookmarks:toggle-bookmark'
it "jump-to-next-bookmark jumps to the right place", ->
editSession.setCursorBufferPosition([0, 0])
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editSession.setCursorBufferPosition([5, 0])
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
it "jump-to-previous-bookmark jumps to the right place", ->
editSession.setCursorBufferPosition([0, 0])
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editSession.setCursorBufferPosition([5, 0])
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
describe "with bookmarks", ->
beforeEach ->
editSession.setCursorBufferPosition([2, 0])
editor.trigger 'bookmarks:toggle-bookmark'
editSession.setCursorBufferPosition([10, 0])
editor.trigger 'bookmarks:toggle-bookmark'
it "jump-to-next-bookmark finds next bookmark", ->
editSession.setCursorBufferPosition([0, 0])
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [10, 0]
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editSession.setCursorBufferPosition([11, 0])
editor.trigger 'bookmarks:jump-to-next-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
it "jump-to-previous-bookmark finds previous bookmark", ->
editSession.setCursorBufferPosition([0, 0])
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [10, 0]
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [2, 0]
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [10, 0]
editSession.setCursorBufferPosition([11, 0])
editor.trigger 'bookmarks:jump-to-previous-bookmark'
expect(editSession.getCursor().getBufferPosition()).toEqual [10, 0]
describe "browsing bookmarks", ->
it "displays a select list of all bookmarks", ->
editSession.setCursorBufferPosition([0])
editor.trigger 'bookmarks:toggle-bookmark'
editSession.setCursorBufferPosition([2])
editor.trigger 'bookmarks:toggle-bookmark'
editSession.setCursorBufferPosition([4])
editor.trigger 'bookmarks:toggle-bookmark'
rootView.trigger 'bookmarks:view-all'
bookmarks = rootView.find('.bookmarks-view')
expect(bookmarks).toExist()
expect(bookmarks.find('.bookmark').length).toBe 3
expect(bookmarks.find('.bookmark:eq(0)').find('.primary-line').text()).toBe 'sample.js:1'
expect(bookmarks.find('.bookmark:eq(0)').find('.secondary-line').text()).toBe 'var quicksort = function () {'
expect(bookmarks.find('.bookmark:eq(1)').find('.primary-line').text()).toBe 'sample.js:3'
expect(bookmarks.find('.bookmark:eq(1)').find('.secondary-line').text()).toBe 'if (items.length <= 1) return items;'
expect(bookmarks.find('.bookmark:eq(2)').find('.primary-line').text()).toBe 'sample.js:5'
expect(bookmarks.find('.bookmark:eq(2)').find('.secondary-line').text()).toBe 'while(items.length > 0) {'
describe "when a bookmark is selected", ->
it "sets the cursor to the location the bookmark", ->
editSession.setCursorBufferPosition([8])
editor.trigger 'bookmarks:toggle-bookmark'
editSession.setCursorBufferPosition([0])
rootView.trigger 'bookmarks:view-all'
bookmarks = rootView.find('.bookmarks-view')
expect(bookmarks).toExist()
bookmarks.find('.bookmark').mousedown().mouseup()
expect(editSession.getCursorBufferPosition()).toEqual [8, 0]
@@ -0,0 +1,15 @@
@import "octicon-utf-codes.less";
.editor .gutter .line-number.bookmarked:after {
color: #09C;
content: @bookmark;
visibility: visible;
}
.bookmarks-view {
.bookmark {
.line-text {
font-family: monospace;
}
}
}
@@ -453,7 +453,7 @@ describe "CommandPanel", ->
it "displays the number of files and operations", ->
rootView.attachToDom()
expect(commandPanel.previewCount.text()).toBe '17 matches in 4 files'
expect(commandPanel.previewCount.text()).toBe '22 matches in 5 files'
describe "when move-down and move-up are triggered on the preview list", ->
it "selects the next/previous operation (if there is one), and scrolls the list if needed", ->
@@ -1,3 +1,6 @@
@import "octicon-utf-codes.less";
@import "octicon-mixins.less";
.command-panel {
position: relative;
padding: 0;
@@ -15,14 +18,10 @@
border-top: 1px solid rgba(0,0,0,1);
border-left: 1px solid rgba(0,0,0,1);
.octicon(hourglass, 1.1em);
&:before {
font-family: 'Octicons Regular';
font-size: 1.1em;
width: 1.1em;
height: 1.1em;
margin-right: 5px;
-webkit-font-smoothing: antialiased;
content: '\f09e';
}
}
}
@@ -46,37 +45,33 @@
-webkit-user-select: none;
}
.path-details:before {
font-family: 'Octicons Regular';
font-size: 12px;
width: 12px;
height: 12px;
margin-right: 5px;
margin-left: 5px;
-webkit-font-smoothing: antialiased;
content: "\f05b";
position: relative;
top: 0;
.path-details {
.octicon(chevron-down, 12px);
&:before {
margin-right: 5px;
margin-left: 5px;
position: relative;
top: 0;
}
}
.is-collapsed .path-details:before {
content: "\f05a";
content: @chevron-right;
}
.path-name:before {
font-family: 'Octicons Regular';
font-size: 16px;
width: 16px;
height: 16px;
margin-right: 5px;
-webkit-font-smoothing: antialiased;
content: "\f011";
position: relative;
top: 1px;
.path-name {
.octicon(file-text);
&:before {
margin-right: 5px;
position: relative;
top: 1px;
}
}
.path.readme .path-name:before {
content: "\f007";
content: @book;
}
.operation {
@@ -98,13 +98,13 @@ class FuzzyFinderView extends SelectList
confirmed : ({filePath}) ->
return unless filePath
if fsUtils.isFileSync(filePath)
if fsUtils.isDirectorySync(filePath)
@setError('Selected path is a directory')
setTimeout((=> @setError()), 2000)
else
lineNumber = @getLineNumber()
@cancel()
@openPath(filePath, lineNumber)
else
@setError('Selected path does not exist')
setTimeout((=> @setError()), 2000)
toggleFileFinder: ->
@finderMode = 'file'
@@ -109,12 +109,12 @@ describe 'FuzzyFinder', ->
expect(editor2.getPath()).toBe expectedPath
expect(editor2.isFocused).toBeTruthy()
describe "when the selected path isn't a file that exists", ->
describe "when the selected path is a directory", ->
it "leaves the the tree view open, doesn't open the path in the editor, and displays an error", ->
rootView.attachToDom()
editorPath = rootView.getActiveView().getPath()
rootView.trigger 'fuzzy-finder:toggle-file-finder'
finderView.confirmed({filePath: 'dir/this/is/not/a/file.txt'})
finderView.confirmed({filePath: project.resolve('dir')})
expect(finderView.hasParent()).toBeTruthy()
expect(rootView.getActiveView().getPath()).toBe editorPath
expect(finderView.error.text().length).toBeGreaterThan 0
@@ -1,3 +1,6 @@
@import "octicon-utf-codes.less";
@import "octicon-mixins.less";
.fuzzy-finder {
&.select-list li {
@@ -11,62 +14,54 @@
}
.status {
font-family: 'Octicons Regular';
font-size: 16px;
width: 16px;
height: 16px;
.icon(16px);
margin-left: 5px;
-webkit-font-smoothing: antialiased;
color: #9d9d9d;
float: right;
&new:before {
&.new:before {
position: relative;
top: 3px;
content: "\f06b";
content: @diff-added;
}
&:before {
&.modified:before {
position: relative;
top: 3px;
content: "\f06d";
content: @diff-modified;
}
}
.file {
&:before {
font-family: 'Octicons Regular';
font-size: 16px;
width: 16px;
height: 16px;
.icon(16px);
margin-right: 5px;
margin-left: 5px;
-webkit-font-smoothing: antialiased;
color: #9d9d9d;
}
&.text-name:before {
content: "\f011";
content: @file-text;
}
&.image-name:before {
content: "\f012";
content: @file-media;
}
&.compressed-name:before {
content: "\f013";
content: @file-zip;
}
&.pdf-name:before {
content: "\f014";
content: @file-pdf;
}
&.readme-name:before {
content: "\f007";
content: @book;
}
&.binary-name:before {
content: "\f094";
content: @file-binary;
}
}
}
+1 -1
Ver Arquivo
@@ -55,7 +55,7 @@
'name': 'comment.hr.gfm'
}
{
'begin': '^`{3,}\\s*coffee(script)?$'
'begin': '^`{3,}\\s*coffee-?(script)?$'
'beginCaptures':
'0': 'name': 'support.gfm'
'end': '^`{3,}$'
+1 -1
Ver Arquivo
@@ -28,7 +28,7 @@ class Gists
pasteboard.write(response.html_url)
notification = $$ ->
@div class: 'notification', =>
@span class: 'icon icon-gist mega-icon'
@span class: 'icon icon-gist mega-octicon'
@div class: 'content', =>
@h3 "Gist #{response.id} created", class: 'title'
@p "The url is on your clipboard", class: 'message'
@@ -9,6 +9,8 @@ fenceNameToExtension =
'bash': 'sh'
'coffee': 'coffee'
'coffeescript': 'coffee'
'coffee-script': 'coffee'
'css': 'css'
'go': 'go'
'java': 'java'
'javascript': 'js'
@@ -35,6 +37,7 @@ class MarkdownPreviewView extends ScrollView
super
@renderMarkdown()
@subscribe syntax, 'grammar-added grammar-updated', _.debounce((=> @renderMarkdown()), 250)
@on 'core:move-up', => @scrollUp()
@on 'core:move-down', => @scrollDown()
@@ -52,7 +55,7 @@ class MarkdownPreviewView extends ScrollView
path: @buffer.getPath()
getTitle: ->
"Markdown Preview – #{@buffer.getBaseName()}"
"#{@buffer.getBaseName()} Preview"
getUri: ->
"markdown-preview:#{@buffer.getPath()}"
@@ -70,7 +73,6 @@ class MarkdownPreviewView extends ScrollView
setLoading: ->
@html($$$ -> @div class: 'markdown-spinner', 'Loading Markdown...')
tokenizeCodeBlocks: (html) =>
html = $(html)
preList = $(html.filter("pre"))
@@ -2,7 +2,7 @@ RootView = require 'root-view'
MarkdownPreviewView = require 'markdown-preview/lib/markdown-preview-view'
{$$} = require 'space-pen'
describe "MarkdownPreview package", ->
describe "Markdown preview package", ->
beforeEach ->
atom.activatePackage('gfm')
project.setPath(project.resolve('markdown'))
@@ -122,3 +122,14 @@ describe "MarkdownPreview package", ->
pane1.activeItem.buffer.trigger 'saved'
expect(preview.renderMarkdown).toHaveBeenCalled()
expect(pane2.activeItem).toBe preview
describe "when a new grammar is loaded", ->
it "reloads the view to colorize any fenced code blocks matching the newly loaded grammar", ->
rootView.getActiveView().trigger 'markdown-preview:show'
[pane1, pane2] = rootView.getPanes()
preview = pane2.activeItem
preview.renderMarkdown.reset()
jasmine.unspy(window, 'setTimeout')
atom.activatePackage('javascript-tmbundle', sync: true)
waitsFor -> preview.renderMarkdown.callCount > 0
@@ -79,7 +79,7 @@
cursor: text;
position: relative;
.mini-icon-link {
.octicon-link {
display: none;
color: #000;
}
@@ -91,7 +91,7 @@
margin-left: -22px;
top: 15%;
.mini-icon-link {
.octicon-link {
display: inline-block;
}
}
@@ -0,0 +1,2 @@
'body':
'meta-,': 'settings-view:toggle'
@@ -0,0 +1,134 @@
{$$, View} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
async = require 'async'
AtomPackage = require 'atom-package'
Editor = require 'editor'
###
# Internal #
###
module.exports =
class GeneralPanel extends View
@content: ->
@form id: 'general-panel', class: 'form-horizontal', =>
@div outlet: "loadingElement", class: 'alert alert-info loading-area', "Loading settings"
initialize: ->
window.setTimeout (=> @activatePackages => @showSettings()), 1
showSettings: ->
@loadingElement.hide()
@appendSettings(name, settings) for name, settings of config.getSettings()
@bindFormFields()
@bindEditors()
activatePackages: (finishedCallback) ->
iterator = (pack, callback) ->
try
if pack instanceof AtomPackage and not pack.isActive()
pack.activate({immediate: true})
catch e
console.error e
finally
callback()
async.each atom.getLoadedPackages(), iterator, finishedCallback
appendSettings: (namespace, settings) ->
return if _.isEmpty(settings)
@append $$ ->
@fieldset =>
@legend "#{_.uncamelcase(namespace)} settings"
appendSetting.call(this, namespace, name, value) for name, value of settings
bindFormFields: ->
for input in @find('input[id]').toArray()
do (input) =>
input = $(input)
name = input.attr('id')
type = input.attr('type')
@observeConfig name, (value) ->
if type is 'checkbox'
input.attr('checked', value)
else
input.val(value) if value
input.on 'change', =>
value = input.val()
if type == 'checkbox'
value = !!input.attr('checked')
else
value = @parseValue(type, value)
config.set(name, value)
bindEditors: ->
for editor in @find('.editor[id]').views()
do (editor) =>
name = editor.attr('id')
type = editor.attr('type')
@observeConfig name, (value) ->
return if value?.toString() == editor.getText()
value ?= ""
editor.setText(value.toString())
editor.getBuffer().on 'contents-modified', =>
config.set(name, @parseValue(type, editor.getText()))
parseValue: (type, value) ->
if value == ''
value = undefined
else if type == 'int'
intValue = parseInt(value)
value = intValue unless isNaN(intValue)
else if type == 'float'
floatValue = parseFloat(value)
value = floatValue unless isNaN(floatValue)
value
###
# Space Pen Helpers
###
appendSetting = (namespace, name, value) ->
return if namespace is 'core' and name is 'themes' # Handled in the Themes panel
@div class: 'control-group', =>
@div class: 'controls', =>
if _.isBoolean(value)
appendCheckbox.call(this, namespace, name, value)
else if _.isArray(value)
appendArray.call(this, namespace, name, value)
else
appendEditor.call(this, namespace, name, value)
appendCheckbox = (namespace, name, value) ->
englishName = _.uncamelcase(name)
keyPath = "#{namespace}.#{name}"
@div class: 'checkbox', =>
@label for: keyPath, =>
@input id: keyPath, type: 'checkbox'
@text englishName
appendEditor = (namespace, name, value) ->
englishName = _.uncamelcase(name)
keyPath = "#{namespace}.#{name}"
if _.isNumber(value)
type = if value % 1 == 0 then 'int' else 'float'
else
type = 'string'
@label class: 'control-label', englishName
@div class: 'controls', =>
@subview keyPath.replace('.', ''), new Editor(mini: true, attributes: {id: keyPath, type: type})
appendArray = (namespace, name, value) ->
englishName = _.uncamelcase(name)
@label class: 'control-label', englishName
@div class: 'controls', =>
@text "readOnly: " + value.join(", ")
@@ -0,0 +1,127 @@
$ = require 'jquery'
_ = require 'underscore'
{View, $$} = require 'space-pen'
EventEmitter = require 'event-emitter'
Editor = require 'editor'
PackageView = require './package-view'
packageManager = require './package-manager'
stringScore = require 'stringscore'
### Internal ###
class PackageEventEmitter
_.extend PackageEventEmitter.prototype, EventEmitter
module.exports =
class PackagePanel extends View
@content: ->
@div class: 'package-panel', =>
@legend 'Packages'
@ul class: 'nav nav-tabs', =>
@li class: 'active', =>
@a 'Installed', =>
@span class: 'badge pull-right', outlet: 'installedCount'
@li =>
@a 'Available', =>
@span class: 'badge pull-right', outlet: 'availableCount'
@subview 'packageFilter', new Editor(mini: true, attributes: {id: 'package-filter'})
@div outlet: 'installedPackages'
@div outlet: 'availablePackages'
initialize: ->
@packageEventEmitter = new PackageEventEmitter()
@availablePackages.hide()
@loadInstalledViews()
@loadAvailableViews()
@find('.nav-tabs li').on 'click', (event) =>
return if $(event.currentTarget).hasClass('active')
@find('.nav-tabs li').toggleClass('active')
@availablePackages.toggle()
@installedPackages.toggle()
@packageEventEmitter.on 'package-installed', (error, pack) =>
@addInstalledPackage(pack) unless error?
@packageEventEmitter.on 'package-uninstalled', (error, pack) =>
@removeInstalledPackage(pack) unless error?
@packageFilter.getBuffer().on 'contents-modified', =>
@filterPackages(@packageFilter.getText())
loadInstalledViews: ->
@installedPackages.empty()
@installedPackages.append @createLoadingView('Loading installed packages\u2026')
packages = _.sortBy(atom.getAvailablePackageMetadata(), 'name')
packageManager.renderMarkdownInMetadata packages, =>
@installedPackages.empty()
for pack in packages
view = new PackageView(pack, @packageEventEmitter)
@installedPackages.append(view)
@updateInstalledCount()
loadAvailableViews: ->
@availablePackages.empty()
@availablePackages.append @createLoadingView('Loading available packages\u2026')
packageManager.getAvailable (error, @packages=[]) =>
@availablePackages.empty()
if error?
errorView = @createErrorView('Error fetching available packages.')
errorView.on 'click', => @loadAvailableViews()
@availablePackages.append errorView
console.error(error.stack ? error)
else
for pack in @packages
view = new PackageView(pack, @packageEventEmitter)
@availablePackages.append(view)
@updateAvailableCount()
createLoadingView: (text) ->
$$ ->
@div class: 'alert alert-info loading-area', text
createErrorView: (text) ->
$$ ->
@div class: 'alert alert-error', =>
@span text
@button class: 'btn btn-mini btn-retry', 'Retry'
updateInstalledCount: ->
@installedCount.text(@installedPackages.children().length)
updateAvailableCount: ->
@availableCount.text(@availablePackages.children().length)
removeInstalledPackage: ({name}) ->
@installedPackages.children("[name=#{name}]").remove()
@updateInstalledCount()
addInstalledPackage: (pack) ->
packageNames = [pack.name]
@installedPackages.children().each (index, el) -> packageNames.push(el.getAttribute('name'))
packageNames.sort()
insertAfterIndex = packageNames.indexOf(pack.name) - 1
view = new PackageView(pack, @packageEventEmitter)
if insertAfterIndex < 0
@installedPackages.prepend(view)
else
@installedPackages.children(":eq(#{insertAfterIndex})").after(view)
@updateInstalledCount()
filterPackages: (filterString) ->
for children in [@installedPackages.children(), @availablePackages.children()]
for packageView in children
name = packageView.getAttribute('name')
continue unless name
if /^\s*$/.test(filterString) or stringScore(name, filterString)
$(packageView).show()
else
$(packageView).hide()
@@ -1,13 +1,13 @@
Package = require 'package'
semver = require 'semver'
packageManager = require 'package-manager'
packageManager = require './package-manager'
_ = require 'underscore'
{$$, View} = require 'space-pen'
requireWithGlobals 'bootstrap/js/bootstrap-dropdown', jQuery: require 'jquery'
### Internal ###
module.exports =
class PackageConfigView extends View
class PackageView extends View
@content: ->
@div class: 'panel', =>
@div outlet: 'heading', class: 'panel-heading', =>
@@ -29,33 +29,41 @@ class PackageConfigView extends View
@a 'Show README', outlet: 'readmeLink'
@div class: 'readme', outlet: 'readme'
pack: null
metadata: null
installed: false
disabled: false
bundled: false
updateAvailable: false
initialize: (@pack, @packageEventEmitter) ->
initialize: (pack, @packageEventEmitter) ->
if pack instanceof Package
@pack = pack
@metadata = @pack.metadata
else
@metadata = pack
@updatePackageState()
@attr('name', @pack.name)
@name.text(@pack.name)
if version = semver.valid(@pack.version)
@attr('name', @metadata.name)
@name.text(@metadata.name)
if version = semver.valid(@metadata.version)
@version.text(version)
else
@version.hide()
if @pack.descriptionHtml
@description.html(@pack.descriptionHtml)
else if @pack.description
@description.text(@pack.description)
if @metadata.descriptionHtml
@description.html(@metadata.descriptionHtml)
else if @metadata.description
@description.text(@metadata.description)
else
@description.text('No further description available.')
@readme.hide()
if @pack.readmeHtml
@readme.html(pack.readmeHtml)
else if @pack.readme
@readme.text(@pack.readme)
if @metadata.readmeHtml
@readme.html(@metadata.readmeHtml)
else if @metadata.readme
@readme.text(@metadata.readme)
else
@readmeArea.hide()
@@ -67,12 +75,12 @@ class PackageConfigView extends View
@readme.show()
@readmeLink.text('Hide README')
homepage = @pack.homepage
homepage = @metadata.homepage
unless homepage
if _.isString(@pack.repository)
repoUrl = @pack.repository
if _.isString(@metadata.repository)
repoUrl = @metadata.repository
else
repoUrl = @pack.repository?.url
repoUrl = @metadata.repository?.url
if repoUrl
repoUrl = repoUrl.replace(/.git$/, '')
homepage = repoUrl if require('url').parse(repoUrl).host is 'github.com'
@@ -81,7 +89,7 @@ class PackageConfigView extends View
else
@homepage.hide()
if issues = @pack.bugs?.url
if issues = @metadata.bugs?.url
@issues.find('a').attr('href', issues)
else
@issues.hide()
@@ -96,16 +104,16 @@ class PackageConfigView extends View
if @installed
if @updateAvailable
@defaultAction.text('Upgrading\u2026')
packageManager.install @pack, (error) =>
@packageEventEmitter.trigger('package-upgraded', error, @pack)
packageManager.install @metadata, (error) =>
@packageEventEmitter.trigger('package-upgraded', error, @metadata)
else
@defaultAction.text('Uninstalling\u2026')
packageManager.uninstall @pack, (error) =>
@packageEventEmitter.trigger('package-uninstalled', error, @pack)
packageManager.uninstall @metadata, (error) =>
@packageEventEmitter.trigger('package-uninstalled', error, @metadata)
else
@defaultAction.text('Installing\u2026')
packageManager.install @pack, (error) =>
@packageEventEmitter.trigger('package-installed', error, @pack)
packageManager.install @metadata, (error) =>
@packageEventEmitter.trigger('package-installed', error, @metadata)
@updateDefaultAction()
@@ -116,24 +124,24 @@ class PackageConfigView extends View
@updateDefaultAction()
@updateEnabledState()
@packageEventEmitter.on 'package-installed package-uninstalled package-upgraded', (error, pack) =>
if pack?.name is @pack.name
@packageEventEmitter.on 'package-installed package-uninstalled package-upgraded', (error, metadata) =>
if metadata?.name is @metadata.name
@defaultAction.enable()
@updatePackageState()
@updateDefaultAction()
togglePackageEnablement: ->
if @disabled
config.removeAtKeyPath('core.disabledPackages', @pack.name)
config.removeAtKeyPath('core.disabledPackages', @metadata.name)
else
config.pushAtKeyPath('core.disabledPackages', @pack.name)
config.pushAtKeyPath('core.disabledPackages', @metadata.name)
updatePackageState: ->
@disabled = atom.isPackageDisabled(@pack.name)
@disabled = atom.isPackageDisabled(@metadata.name)
@updateAvailable = false
@bundled = false
loadedPackage = atom.getLoadedPackage(@pack.name)
packagePath = loadedPackage?.path ? atom.resolvePackagePath(@pack.name)
loadedPackage = atom.getLoadedPackage(@metadata.name)
packagePath = loadedPackage?.path ? atom.resolvePackagePath(@metadata.name)
@installed = packagePath?
if @installed
for packageDirPath in config.bundledPackageDirPaths
@@ -144,8 +152,8 @@ class PackageConfigView extends View
version = loadedPackage?.metadata.version
unless version
try
version = Package.loadMetadata(@pack.name).version
@updateAvailable = semver.gt(@pack.version, version)
version = Package.loadMetadata(@metadata.name).version
@updateAvailable = semver.gt(@metadata.version, version)
if @updateAvailable
@update.show()
@@ -1,44 +1,59 @@
{View, $$} = require 'space-pen'
{$$} = require 'space-pen'
ScrollView = require 'scroll-view'
$ = require 'jquery'
_ = require 'underscore'
GeneralConfigPanel = require 'general-config-panel'
EditorConfigPanel = require 'editor-config-panel'
ThemeConfigPanel = require 'theme-config-panel'
PackageConfigPanel = require 'package-config-panel'
Pane = require 'pane'
GeneralPanel = require './general-panel'
ThemePanel = require './theme-panel'
PackagePanel = require './package-panel'
Project = require 'project'
configUri = "atom://config"
###
# Internal #
###
module.exports =
class ConfigView extends View
class SettingsView extends ScrollView
registerDeserializer(this)
@deserialize: ({activePanelName}) ->
view = new ConfigView()
view.showPanel(activePanelName)
view
@activate: (state) ->
Project.registerOpener (filePath) ->
new SettingsView() if filePath is configUri
rootView.command 'settings-view:toggle', ->
rootView.open(configUri)
@deserialize: ({activePanelName}={}) ->
new SettingsView(activePanelName)
@content: ->
@div id: 'config-view', =>
@div id: 'settings-view', tabindex: -1, =>
@div id: 'config-menu', =>
@ul id: 'panels-menu', class: 'nav nav-pills nav-stacked', outlet: 'panelMenu'
@button "open .atom", id: 'open-dot-atom', class: 'btn btn-default btn-small'
@button "Open ~/.atom", id: 'open-dot-atom', class: 'btn btn-default btn-small'
@div id: 'panels', outlet: 'panels'
initialize: ->
activePanelName: null
initialize: (activePanelName) ->
super
@panelsByName = {}
document.title = "Atom Configuration"
@on 'click', '#panels-menu li a', (e) =>
@showPanel($(e.target).closest('li').attr('name'))
@on 'click', '#open-dot-atom', ->
atom.open(config.configDirPath)
@addPanel('General', new GeneralConfigPanel)
@addPanel('Editor', new EditorConfigPanel)
@addPanel('Themes', new ThemeConfigPanel)
@addPanel('Packages', new PackageConfigPanel)
@addPanel('General', new GeneralPanel)
@addPanel('Themes', new ThemePanel)
@addPanel('Packages', new PackagePanel)
@showPanel(activePanelName) if activePanelName
serialize: ->
deserializer: 'SettingsView'
activePanelName: @activePanelName
addPanel: (name, panel) ->
panelItem = $$ -> @li name: name, => @a name
@@ -64,6 +79,11 @@ class ConfigView extends View
else
@panelToShow = name
serialize: ->
deserializer: @constructor.name
activePanelName: @activePanelName
getTitle: ->
"Settings"
getUri: ->
configUri
isEqual: (other) ->
other instanceof SettingsView
@@ -1,5 +1,4 @@
ConfigPanel = require 'config-panel'
{$$} = require 'space-pen'
{View, $$} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
@@ -16,7 +15,7 @@ require 'jqueryui-browser/ui/jquery.ui.draggable'
delete window.jQuery
module.exports =
class ThemeConfigPanel extends ConfigPanel
class ThemeConfigPanel extends View
@content: ->
@div id: 'themes-config', =>
@legend "Themes"
@@ -30,7 +29,7 @@ class ThemeConfigPanel extends ConfigPanel
constructor: ->
super
for name in atom.getAvailableThemeNames()
for name in atom.themes.getAvailableNames()
@availableThemes.append(@buildThemeLi(name, draggable: true))
@observeConfig "core.themes", (enabledThemes) =>
+3
Ver Arquivo
@@ -0,0 +1,3 @@
'main': './lib/settings-view'
'deferredDeserializers': ['SettingsView']
'description': 'GUI pane for Atom settings'

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