diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2afb8ac19..f2379dbaa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,8 +66,9 @@ in the proper package's repository. * Use [TomDoc](http://tomdoc.org). * Use [Markdown](https://daringfireball.net/projects/markdown). -* Reference classes with `{ClassName}` style notation. -* Reference methods with `{ClassName.methodName}` style notation. +* Reference classes with `{ClassName}`. +* Reference instance methods with `{ClassName::methodName}`. +* Reference class methods with `{ClassName.methodName}`. * Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}` style notation. diff --git a/build/package.json b/build/package.json index 7c0e92194..ff112b90d 100644 --- a/build/package.json +++ b/build/package.json @@ -7,7 +7,7 @@ }, "dependencies": { "async": "~0.2.9", - "biscotto": "0.6.0", + "biscotto": "1.x", "formidable": "~1.0.14", "fs-plus": "2.x", "github-releases": "~0.2.0", diff --git a/docs/contributing.md b/docs/contributing.md index b042275c5..257dd4d3a 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -116,8 +116,10 @@ dependencies up to date by running `apm update` after pulling upstream changes. * Use [TomDoc](http://tomdoc.org). * Use [Markdown](https://daringfireball.net/projects/markdown). -* Reference classes with the custom `{ClassName}` notation. -* Reference methods with the custom `{ClassName.methodName}` notation. +* Reference methods and classes in markdown with the custom `{}` notation: + * Reference classes with `{ClassName}` + * Reference instance methods with `{ClassName::methodName}` + * Reference class methods with `{ClassName.methodName}` ### Example diff --git a/docs/index.md b/docs/index.md index 001836228..96aeebf3a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,6 +4,7 @@ * [Customizing Atom](customizing-atom.md) * [Creating a Package](creating-a-package.md) * [Creating a Theme](creating-a-theme.md) +* [Publishing a Package](publishing-a-package.md) ### Advanced Topics diff --git a/package.json b/package.json index 4b262d776..f259313b6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.51.0", + "version": "0.52.0", "main": "./src/browser/main.js", "repository": { "type": "git", @@ -74,7 +74,7 @@ "command-palette": "0.17.0", "dev-live-reload": "0.26.0", "exception-reporting": "0.13.0", - "feedback": "0.23.0", + "feedback": "0.24.0", "find-and-replace": "0.83.0", "fuzzy-finder": "0.35.0", "gists": "0.17.0", @@ -85,12 +85,12 @@ "image-view": "0.24.0", "keybinding-resolver": "0.10.0", "link": "0.17.0", - "markdown-preview": "0.32.0", + "markdown-preview": "0.33.0", "metrics": "0.26.0", "open-on-github": "0.20.0", "package-generator": "0.26.0", "release-notes": "0.21.0", - "settings-view": "0.76.0", + "settings-view": "0.77.0", "snippets": "0.30.0", "spell-check": "0.25.0", "status-bar": "0.32.0", @@ -105,7 +105,7 @@ "wrap-guide": "0.14.0", "language-c": "0.10.0", "language-clojure": "0.2.0", - "language-coffee-script": "0.9.0", + "language-coffee-script": "0.10.0", "language-css": "0.8.0", "language-gfm": "0.17.0", "language-git": "0.8.0", diff --git a/spec/keymap-spec.coffee b/spec/keymap-spec.coffee index 064c5b1c7..b79783322 100644 --- a/spec/keymap-spec.coffee +++ b/spec/keymap-spec.coffee @@ -399,3 +399,32 @@ describe "Keymap", -> runs -> keyBinding = keymap.keyBindingsForKeystroke('ctrl-l')[0] expect(keyBinding).toBeUndefined() + + it "logs a warning when it can't be parsed", -> + keymapFilePath = path.join(configDirPath, "keymap.json") + fs.writeFileSync(keymapFilePath, '') + keymap.loadUserKeymap() + + spyOn(keymap, 'loadUserKeymap').andCallThrough() + fs.writeFileSync(keymapFilePath, '}{') + spyOn(console, 'warn') + + waitsFor -> + keymap.loadUserKeymap.callCount > 0 + + runs -> + expect(console.warn.callCount).toBe 1 + expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0 + + describe "when adding a binding with an invalid selector", -> + it "logs a warning and does not add it", -> + spyOn(console, 'warn') + keybinding = + '##selector': + 'cmd-a': 'invalid-command' + keymap.add('test', keybinding) + + expect(console.warn.callCount).toBe 1 + expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0 + expect(-> keymap.keyBindingsMatchingElement(document.body)).not.toThrow() + expect(keymap.keyBindingsForCommand('invalid:command')).toEqual [] diff --git a/spec/pane-container-view-spec.coffee b/spec/pane-container-view-spec.coffee index 28fbd56a6..149658b0e 100644 --- a/spec/pane-container-view-spec.coffee +++ b/spec/pane-container-view-spec.coffee @@ -45,10 +45,10 @@ describe "PaneContainerView", -> expect(container.getFocusedPane()).toBe pane3 expect(container.getActivePane()).toBe pane3 - describe ".eachPane(callback)", -> + describe ".eachPaneView(callback)", -> it "runs the callback with all current and future panes until the subscription is cancelled", -> panes = [] - subscription = container.eachPane (pane) -> panes.push(pane) + subscription = container.eachPaneView (pane) -> panes.push(pane) expect(panes).toEqual [pane1, pane2, pane3] panes = [] @@ -66,7 +66,7 @@ describe "PaneContainerView", -> container.saveAll() - for pane in container.getPanes() + for pane in container.getPaneViews() for item in pane.getItems() expect(item.saved).toBeTruthy() @@ -240,30 +240,30 @@ describe "PaneContainerView", -> pane2.remove() expect(activeItemChangedHandler).not.toHaveBeenCalled() - describe ".focusNextPane()", -> + describe ".focusNextPaneView()", -> it "focuses the pane following the focused pane or the first pane if no pane has focus", -> container.attachToDom() - container.focusNextPane() + container.focusNextPaneView() expect(pane1.activeItem).toMatchSelector ':focus' - container.focusNextPane() + container.focusNextPaneView() expect(pane2.activeItem).toMatchSelector ':focus' - container.focusNextPane() + container.focusNextPaneView() expect(pane3.activeItem).toMatchSelector ':focus' - container.focusNextPane() + container.focusNextPaneView() expect(pane1.activeItem).toMatchSelector ':focus' - describe ".focusPreviousPane()", -> + describe ".focusPreviousPaneView()", -> it "focuses the pane preceding the focused pane or the last pane if no pane has focus", -> container.attachToDom() - container.getPanes()[0].focus() # activate first pane + container.getPaneViews()[0].focus() # activate first pane - container.focusPreviousPane() + container.focusPreviousPaneView() expect(pane3.activeItem).toMatchSelector ':focus' - container.focusPreviousPane() + container.focusPreviousPaneView() expect(pane2.activeItem).toMatchSelector ':focus' - container.focusPreviousPane() + container.focusPreviousPaneView() expect(pane1.activeItem).toMatchSelector ':focus' - container.focusPreviousPane() + container.focusPreviousPaneView() expect(pane3.activeItem).toMatchSelector ':focus' describe "changing focus directionally between panes", -> @@ -300,54 +300,54 @@ describe "PaneContainerView", -> container.width(400) container.attachToDom() - describe ".focusPaneAbove()", -> + describe ".focusPaneViewAbove()", -> describe "when there are multiple rows above the focused pane", -> it "focuses up to the adjacent row", -> pane8.focus() - container.focusPaneAbove() + container.focusPaneViewAbove() expect(pane5.activeItem).toMatchSelector ':focus' describe "when there are no rows above the focused pane", -> it "keeps the current pane focused", -> pane2.focus() - container.focusPaneAbove() + container.focusPaneViewAbove() expect(pane2.activeItem).toMatchSelector ':focus' - describe ".focusPaneBelow()", -> + describe ".focusPaneViewBelow()", -> describe "when there are multiple rows below the focused pane", -> it "focuses down to the adjacent row", -> pane2.focus() - container.focusPaneBelow() + container.focusPaneViewBelow() expect(pane5.activeItem).toMatchSelector ':focus' describe "when there are no rows below the focused pane", -> it "keeps the current pane focused", -> pane8.focus() - container.focusPaneBelow() + container.focusPaneViewBelow() expect(pane8.activeItem).toMatchSelector ':focus' - describe ".focusPaneOnLeft()", -> + describe ".focusPaneViewOnLeft()", -> describe "when there are multiple columns to the left of the focused pane", -> it "focuses left to the adjacent column", -> pane6.focus() - container.focusPaneOnLeft() + container.focusPaneViewOnLeft() expect(pane5.activeItem).toMatchSelector ':focus' describe "when there are no columns to the left of the focused pane", -> it "keeps the current pane focused", -> pane4.focus() - container.focusPaneOnLeft() + container.focusPaneViewOnLeft() expect(pane4.activeItem).toMatchSelector ':focus' - describe ".focusPaneOnRight()", -> + describe ".focusPaneViewOnRight()", -> describe "when there are multiple columns to the right of the focused pane", -> it "focuses right to the adjacent column", -> pane4.focus() - container.focusPaneOnRight() + container.focusPaneViewOnRight() expect(pane5.activeItem).toMatchSelector ':focus' describe "when there are no columns to the right of the focused pane", -> it "keeps the current pane focused", -> pane6.focus() - container.focusPaneOnRight() + container.focusPaneViewOnRight() expect(pane6.activeItem).toMatchSelector ':focus' diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index 8bd6f1f89..490f1137c 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -224,3 +224,14 @@ describe "ThemeManager", -> runs -> expect($(document.body).css('border-style')).toBe 'none' + + describe "when a non-existent theme is present in the config", -> + it "logs a warning but does not throw an exception (regression)", -> + waitsForPromise -> + themeManager.activateThemes() + + runs -> + spyOn(console, 'warn') + expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow() + expect(console.warn.callCount).toBe 1 + expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0 diff --git a/spec/workspace-view-spec.coffee b/spec/workspace-view-spec.coffee index d13ca3323..245666c23 100644 --- a/spec/workspace-view-spec.coffee +++ b/spec/workspace-view-spec.coffee @@ -36,12 +36,12 @@ describe "WorkspaceView", -> editorView1 = atom.workspaceView.getActiveView() buffer = editorView1.getEditor().getBuffer() editorView1.splitRight() - expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPanes()[1] + expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPaneViews()[1] simulateReload() expect(atom.workspaceView.getEditorViews().length).toBe 2 - expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPanes()[1] + expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPaneViews()[1] expect(atom.workspaceView.title).toBe "untitled - #{atom.project.getPath()}" describe "when there are open editors", -> diff --git a/src/clipboard.coffee b/src/clipboard.coffee index 82d75d2d4..c717350ae 100644 --- a/src/clipboard.coffee +++ b/src/clipboard.coffee @@ -20,7 +20,7 @@ class Clipboard # Public: Write the given text to the clipboard. # # The metadata associated with the text is available by calling - # {.readWithMetadata}. + # {::readWithMetadata}. # # text - The {String} to store. # metadata - The additional info to associate with the text. @@ -40,7 +40,7 @@ class Clipboard # # Returns an {Object} with the following keys: # :text - The {String} clipboard text. - # :metadata - The metadata stored by an earlier call to {.write}. + # :metadata - The metadata stored by an earlier call to {::write}. readWithMetadata: -> text = @read() if @signatureForMetadata is @md5(text) diff --git a/src/cursor.coffee b/src/cursor.coffee index 6b3747479..e946a3523 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -311,7 +311,7 @@ class Cursor # # options - An {Object} with the following keys: # :wordRegex - A {RegExp} indicating what constitutes a "word" - # (default: {.wordRegExp}). + # (default: {::wordRegExp}). # :includeNonWordCharacters - A {Boolean} indicating whether to include # non-word characters in the default word regex. # Has no effect if wordRegex is set. @@ -379,7 +379,7 @@ class Cursor # # options - An {Object} with the following keys: # :wordRegex - A {RegExp} indicating what constitutes a "word" - # (default: {.wordRegExp}) + # (default: {::wordRegExp}) # :includeNonWordCharacters - A Boolean indicating whether to include # non-word characters in the default word regex. # Has no effect if wordRegex is set. @@ -403,7 +403,7 @@ class Cursor # # options - # :wordRegex - A {RegExp} indicating what constitutes a "word" - # (default: {.wordRegExp}). + # (default: {::wordRegExp}). # # Returns a {Range}. getBeginningOfNextWordBufferPosition: (options = {}) -> @@ -422,7 +422,7 @@ class Cursor # # options - # :wordRegex - A {RegExp} indicating what constitutes a "word" - # (default: {.wordRegExp}). + # (default: {::wordRegExp}). getCurrentWordBufferRange: (options={}) -> startOptions = _.extend(_.clone(options), allowPrevious: false) endOptions = _.extend(_.clone(options), allowNext: false) diff --git a/src/display-buffer-marker.coffee b/src/display-buffer-marker.coffee index 184162622..6369d8cb5 100644 --- a/src/display-buffer-marker.coffee +++ b/src/display-buffer-marker.coffee @@ -37,7 +37,7 @@ class DisplayBufferMarker # Modifies the screen range of the display marker. # # screenRange - The new {Range} to use - # options - A hash of options matching those found in {Marker.setRange} + # options - A hash of options matching those found in {Marker::setRange} setScreenRange: (screenRange, options) -> @setBufferRange(@displayBuffer.bufferRangeForScreenRange(screenRange), options) @@ -50,7 +50,7 @@ class DisplayBufferMarker # Modifies the buffer range of the display marker. # # screenRange - The new {Range} to use - # options - A hash of options matching those found in {Marker.setRange} + # options - A hash of options matching those found in {Marker::setRange} setBufferRange: (bufferRange, options) -> @bufferMarker.setRange(bufferRange, options) @@ -63,7 +63,7 @@ class DisplayBufferMarker # Sets the screen position of the marker's head. # # screenRange - The new {Point} to use - # options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition} + # options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition} setHeadScreenPosition: (screenPosition, options) -> screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options) @setHeadBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options)) @@ -77,7 +77,7 @@ class DisplayBufferMarker # Sets the buffer position of the marker's head. # # screenRange - The new {Point} to use - # options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition} + # options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition} setHeadBufferPosition: (bufferPosition) -> @bufferMarker.setHeadPosition(bufferPosition) @@ -90,7 +90,7 @@ class DisplayBufferMarker # Sets the screen position of the marker's tail. # # screenRange - The new {Point} to use - # options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition} + # options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition} setTailScreenPosition: (screenPosition, options) -> screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options) @setTailBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options)) @@ -104,7 +104,7 @@ class DisplayBufferMarker # Sets the buffer position of the marker's tail. # # screenRange - The new {Point} to use - # options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition} + # options - A hash of options matching those found in {DisplayBuffer::bufferPositionForScreenPosition} setTailBufferPosition: (bufferPosition) -> @bufferMarker.setTailPosition(bufferPosition) @@ -135,7 +135,7 @@ class DisplayBufferMarker # Returns a {Boolean} indicating whether the marker has been destroyed. A marker # can be invalid without being destroyed, in which case undoing the invalidating # operation would restore the marker. Once a marker is destroyed by calling - # {Marker.destroy}, no undo/redo operation can ever bring it back. + # {Marker::destroy}, no undo/redo operation can ever bring it back. isDestroyed: -> @bufferMarker.isDestroyed() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index b5063a280..a5e9d881e 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -308,7 +308,6 @@ class DisplayBuffer extends Model screenColumn = Infinity break - new Point(screenRow, screenColumn) @clipScreenPosition([screenRow, screenColumn], options) # Given a buffer position, this converts it into a screen position. @@ -509,7 +508,7 @@ class DisplayBuffer extends Model # Finds the first marker satisfying the given attributes # - # Refer to {DisplayBuffer.findMarkers} for details. + # Refer to {DisplayBuffer::findMarkers} for details. # # Returns a {DisplayBufferMarker} or null findMarker: (attributes) -> diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 4aa277192..27e190070 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -609,7 +609,7 @@ class EditorView extends View # # bufferPosition - An object that represents a buffer position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # options - A hash matching the options available to {.scrollToPixelPosition} + # options - A hash matching the options available to {::scrollToPixelPosition} scrollToBufferPosition: (bufferPosition, options) -> @scrollToPixelPosition(@pixelPositionForBufferPosition(bufferPosition), options) @@ -617,7 +617,7 @@ class EditorView extends View # # screenPosition - An object that represents a buffer position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # options - A hash matching the options available to {.scrollToPixelPosition} + # options - A hash matching the options available to {::scrollToPixelPosition} scrollToScreenPosition: (screenPosition, options) -> @scrollToPixelPosition(@pixelPositionForScreenPosition(screenPosition), options) diff --git a/src/editor.coffee b/src/editor.coffee index 633604e54..a8fe6e646 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -222,7 +222,7 @@ class Editor extends Model # Public: Returns that String used to indicate a tab. # - # If soft tabs are enabled, this is a space (`" "`) times the {.getTabLength} value. + # If soft tabs are enabled, this is a space (`" "`) times the {::getTabLength} value. # Otherwise, it's a tab (`\t`). getTabText: -> @buildIndentString(1) @@ -427,7 +427,7 @@ class Editor extends Model # Public: Inserts text at the current cursor positions # # text - A {String} representing the text to insert. - # options - A set of options equivalent to {Selection.insertText}. + # options - A set of options equivalent to {Selection::insertText}. insertText: (text, options={}) -> options.autoIndentNewline ?= @shouldAutoIndent() options.autoDecreaseIndent ?= @shouldAutoIndent() @@ -454,7 +454,7 @@ class Editor extends Model # Public: Indents the current line. # - # options - A set of options equivalent to {Selection.indent}. + # options - A set of options equivalent to {Selection::indent}. indent: (options={})-> options.autoIndent ?= @shouldAutoIndent() @mutateSelectedText (selection) -> selection.indent(options) @@ -513,7 +513,7 @@ class Editor extends Model autoIndentSelectedRows: -> @mutateSelectedText (selection) -> selection.autoIndentSelectedRows() - # Public: Converts all indents to the current {.getTabText} given a {Range}. + # Public: Converts all indents to the current {::getTabText} given a {Range}. normalizeTabsInBufferRange: (bufferRange) -> return unless @getSoftTabs() @scanInBufferRange /\t/, bufferRange, ({replace}) => replace(@getTabText()) @@ -542,7 +542,7 @@ class Editor extends Model # Public: Pastes the text in the clipboard. # - # options - A set of options equivalent to {Selection.insertText}. + # options - A set of options equivalent to {Selection::insertText}. pasteText: (options={}) -> {text, metadata} = atom.clipboard.readWithMetadata() @@ -867,7 +867,7 @@ class Editor extends Model # Public: Given a buffer range, this adds a new selection for it. # # bufferRange - A {Range} in the buffer. - # options - An options {Object} for {.markBufferRange}. + # options - An options {Object} for {::markBufferRange}. # # Returns the new {Selection}. addSelectionForBufferRange: (bufferRange, options={}) -> @@ -878,7 +878,7 @@ class Editor extends Model # creates a new selection for it. # # bufferRange - A {Range} in the buffer. - # options - An options {Object} for {.setSelectedBufferRanges}. + # options - An options {Object} for {::setSelectedBufferRanges}. setSelectedBufferRange: (bufferRange, options) -> @setSelectedBufferRanges([bufferRange], options) @@ -886,7 +886,7 @@ class Editor extends Model # selections and creates new selections for them. # # bufferRange - A {Range} in the buffer. - # options - An options {Object} for {.setSelectedBufferRanges}. + # options - An options {Object} for {::setSelectedBufferRanges}. setSelectedBufferRanges: (bufferRanges, options={}) -> throw new Error("Passed an empty array to setSelectedBufferRanges") unless bufferRanges.length @@ -961,7 +961,7 @@ class Editor extends Model # Public: Moves every local cursor to a given screen position. # # position - An {Array} of two numbers: the screen row, and the screen column. - # options - An {Object} with properties based on {Cursor.setScreenPosition}. + # options - An {Object} with properties based on {Cursor::setScreenPosition}. setCursorScreenPosition: (position, options) -> @moveCursors (cursor) -> cursor.setScreenPosition(position, options) @@ -981,7 +981,7 @@ class Editor extends Model # Public: Moves every cursor to a given buffer position. # # position - An {Array} of two numbers: the buffer row, and the buffer column. - # options - An object with properties based on {Cursor.setBufferPosition}. + # options - An object with properties based on {Cursor::setBufferPosition}. setCursorBufferPosition: (position, options) -> @moveCursors (cursor) -> cursor.setBufferPosition(position, options) @@ -1025,7 +1025,7 @@ class Editor extends Model # Public: Returns the word under the most recently added local {Cursor}. # # options - An object with properties based on - # {Cursor.getBeginningOfCurrentWordBufferPosition}. + # {Cursor::getBeginningOfCurrentWordBufferPosition}. getWordUnderCursor: (options) -> @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) diff --git a/src/git.coffee b/src/git.coffee index 7143b4e69..1e5c9fb5b 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -110,7 +110,7 @@ class Git # path - A {String} repository-relative path. # # Returns a {Number} representing the status. This value can be passed to - # {.isStatusModified} or {.isStatusNew} to get more information. + # {::isStatusModified} or {::isStatusNew} to get more information. getPathStatus: (path) -> currentPathStatus = @statuses[path] ? 0 pathStatus = @getRepo().getStatus(@relativize(path)) ? 0 @@ -208,7 +208,7 @@ class Git # path - The {String} path to check. # # Returns a {Number} representing the status. This value can be passed to - # {.isStatusModified} or {.isStatusNew} to get more information. + # {::isStatusModified} or {::isStatusNew} to get more information. getDirectoryStatus: (directoryPath) -> {sep} = require 'path' directoryPath = "#{directoryPath}#{sep}" diff --git a/src/keymap.coffee b/src/keymap.coffee index 98b4a89ad..2b47b3053 100644 --- a/src/keymap.coffee +++ b/src/keymap.coffee @@ -135,9 +135,16 @@ class Keymap userKeymapPath = @getUserKeymapPath() if fs.isFileSync(userKeymapPath) @userKeymapPath = userKeymapPath - @load(userKeymapPath) @userKeymapFile = new File(userKeymapPath) @userKeymapFile.on 'contents-changed moved removed', => @loadUserKeymap() + @add(@userKeymapPath, @readUserKeymap()) + + readUserKeymap: -> + try + CSON.readFileSync(@userKeymapPath) ? {} + catch error + console.warn("Failed to load your keymap file: #{@userKeymapPath}", error.stack ? error) + {} loadDirectory: (directoryPath) -> platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32'] @@ -159,7 +166,12 @@ class Keymap bindKeys: (source, selector, keyMappings) -> for keystroke, command of keyMappings - @keyBindings.push new KeyBinding(source, command, keystroke, selector) + keyBinding = new KeyBinding(source, command, keystroke, selector) + try + $(keyBinding.selector) # Verify selector is valid before registering + @keyBindings.push(keyBinding) + catch + console.warn("Keybinding '#{keystroke}': '#{command}' in #{source} has an invalid selector: '#{selector}'") handleKeyEvent: (event) -> element = event.target diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 82e8512a7..b726c555f 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -46,7 +46,11 @@ class MenuManager # # Returns true to include the selector, false otherwise. includeSelector: (selector) -> - return true if document.body.webkitMatchesSelector(selector) + try + return true if document.body.webkitMatchesSelector(selector) + catch error + # Selector isn't valid + return false # Simulate an .editor element attached to a .workspace element attached to # a body element that has the same classes as the current body element. diff --git a/src/pane-container-view.coffee b/src/pane-container-view.coffee index 093c3e29d..2ed53b19b 100644 --- a/src/pane-container-view.coffee +++ b/src/pane-container-view.coffee @@ -54,24 +54,24 @@ class PaneContainerView extends View confirmClose: -> saved = true - for pane in @getPanes() + for pane in @getPaneViews() for item in pane.getItems() if not pane.promptToSaveItem(item) saved = false break saved - getPanes: -> + getPaneViews: -> @find('.pane').views() indexOfPane: (pane) -> - @getPanes().indexOf(pane.view()) + @getPaneViews().indexOf(pane.view()) paneAtIndex: (index) -> - @getPanes()[index] + @getPaneViews()[index] - eachPane: (callback) -> - callback(pane) for pane in @getPanes() + eachPaneView: (callback) -> + callback(pane) for pane in @getPaneViews() paneAttached = (e) -> callback($(e.target).view()) @on 'pane:attached', paneAttached off: => @off 'pane:attached', paneAttached @@ -91,22 +91,22 @@ class PaneContainerView extends View paneForUri: (uri) -> @viewForModel(@model.paneForUri(uri)) - focusNextPane: -> + focusNextPaneView: -> @model.activateNextPane() - focusPreviousPane: -> + focusPreviousPaneView: -> @model.activatePreviousPane() - focusPaneAbove: -> + focusPaneViewAbove: -> @nearestPaneInDirection('above')?.focus() - focusPaneBelow: -> + focusPaneViewBelow: -> @nearestPaneInDirection('below')?.focus() - focusPaneOnLeft: -> + focusPaneViewOnLeft: -> @nearestPaneInDirection('left')?.focus() - focusPaneOnRight: -> + focusPaneViewOnRight: -> @nearestPaneInDirection('right')?.focus() nearestPaneInDirection: (direction) -> @@ -117,7 +117,7 @@ class PaneContainerView extends View pane = @getActivePane() box = @boundingBoxForPane(pane) - panes = @getPanes() + panes = @getPaneViews() .filter (otherPane) => otherBox = @boundingBoxForPane(otherPane) switch direction @@ -143,3 +143,7 @@ class PaneContainerView extends View right: {x: boundingBox.right, y: boundingBox.top} top: {x: boundingBox.left, y: boundingBox.top} bottom: {x: boundingBox.left, y: boundingBox.bottom} + + # Deprecated + getPanes: -> + @getPaneViews() diff --git a/src/pane-view.coffee b/src/pane-view.coffee index 09cc2a62b..59fb98074 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -117,7 +117,7 @@ class PaneView extends View # Public: Returns the next pane, ordered by creation. getNextPane: -> - panes = @container?.getPanes() + panes = @container?.getPaneViews() return unless panes.length > 1 nextIndex = (panes.indexOf(this) + 1) % panes.length panes[nextIndex] diff --git a/src/select-list-view.coffee b/src/select-list-view.coffee index 0536bff57..c97daa52e 100644 --- a/src/select-list-view.coffee +++ b/src/select-list-view.coffee @@ -8,8 +8,8 @@ fuzzyFilter = require('fuzzaldrin').filter # # Subclasses must implement the following methods: # -# * {.viewForItem} -# * {.confirmed} +# * {::viewForItem} +# * {::confirmed} # # ## Requiring in packages # @@ -88,7 +88,7 @@ class SelectListView extends View # Public: Set the array of items to display in the list. # - # This should be model items not actual views. {.viewForItem} will be + # This should be model items not actual views. {::viewForItem} will be # called to render the item when it is being appended to the list view. # # items - The {Array} of model items to display in the list (default: []). @@ -130,7 +130,7 @@ class SelectListView extends View @filterEditorView.getEditor().getText() # Public: Populate the list view with the model items previously set by - # calling {.setItems}. + # calling {::setItems}. # # Subclasses may override this method but should always call `super`. populateList: -> @@ -160,7 +160,7 @@ class SelectListView extends View # # Subclasses may override this method to customize the message. # - # itemCount - The {Number} of items in the array specified to {.setItems} + # itemCount - The {Number} of items in the array specified to {::setItems} # filteredItemCount - The {Number} of items that pass the fuzzy filter test. # # Returns a {String} message (default: 'No matches found'). @@ -220,7 +220,7 @@ class SelectListView extends View # This is called when the item is about to appended to the list view. # # item - The model item being rendered. This will always be one of the items - # previously passed to {.setItems}. + # previously passed to {::setItems}. # # Returns a String of HTML, DOM element, jQuery object, or View. viewForItem: (item) -> @@ -231,7 +231,7 @@ class SelectListView extends View # This method must be overridden by subclasses. # # item - The selected model item. This will always be one of the items - # previously passed to {.setItems}. + # previously passed to {::setItems}. # # Returns a DOM element, jQuery object, or {View}. confirmed: (item) -> @@ -242,7 +242,7 @@ class SelectListView extends View # This method may be overridden by classes to allow fuzzy filtering based # on a specific property of the item objects. # - # For example if the objects you pass to {.setItems} are of the type + # For example if the objects you pass to {::setItems} are of the type # `{"id": 3, "name": "Atom"}` then you would return `"name"` from this method # to fuzzy filter by that property when text is entered into this view's # editor. @@ -255,7 +255,7 @@ class SelectListView extends View @filterEditorView.focus() # Public: Store the currently focused element. This element will be given - # back focus when {.cancel} is called. + # back focus when {::cancel} is called. storeFocusedElement: -> @previouslyFocusedElement = $(':focus') @@ -272,7 +272,7 @@ class SelectListView extends View # Public: Cancel and close this select list view. # # This restores focus to the previously focused element if - # {.storeFocusedElement} was called prior to this view being attached. + # {::storeFocusedElement} was called prior to this view being attached. cancel: -> @list.empty() @cancelling = true diff --git a/src/selection.coffee b/src/selection.coffee index 6f5e50788..a1e11990a 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -56,7 +56,7 @@ class Selection # Public: Modifies the screen range for the selection. # # screenRange - The new {Range} to use. - # options - A hash of options matching those found in {.setBufferRange}. + # options - A hash of options matching those found in {::setBufferRange}. setScreenRange: (screenRange, options) -> @setBufferRange(@editor.bufferRangeForScreenRange(screenRange), options) @@ -338,7 +338,7 @@ class Selection # # options - A {Object} with the keys: # :autoIndent - If `true`, the indentation is performed appropriately. - # Otherwise, {Editor.getTabText} is used. + # Otherwise, {Editor::getTabText} is used. indent: ({ autoIndent }={})-> { row, column } = @cursor.getBufferPosition() @@ -543,7 +543,7 @@ class Selection # the given selection. # # otherSelection - A {Selection} to merge with. - # options - A hash of options matching those found in {.setBufferRange}. + # options - A hash of options matching those found in {::setBufferRange}. merge: (otherSelection, options) -> myGoalBufferRange = @getGoalBufferRange() otherGoalBufferRange = otherSelection.getGoalBufferRange() @@ -557,7 +557,7 @@ class Selection # Public: Compare this selection's buffer range to another selection's buffer # range. # - # See {Range.compare} for more details. + # See {Range::compare} for more details. # # otherSelection - A {Selection} to compare against. compare: (otherSelection) -> diff --git a/src/task.coffee b/src/task.coffee index 8e2b57277..b0c8b3623 100644 --- a/src/task.coffee +++ b/src/task.coffee @@ -37,7 +37,7 @@ class Task # # It receives the same arguments that were passed to the task. # - # If subclassed, this is intended to be overridden. However if {.start} + # If subclassed, this is intended to be overridden. However if {::start} # receives a completion callback, this is overridden. callback: null diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 80204905a..6b4e1ccaf 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -61,7 +61,14 @@ class ThemeManager @deactivateThemes() @refreshLessCache() # Update cache for packages in core.themes config - promises = @getEnabledThemeNames().map (themeName) => @packageManager.activatePackage(themeName) + + promises = [] + for themeName in @getEnabledThemeNames() + if @packageManager.resolvePackagePath(themeName) + promises.push(@packageManager.activatePackage(themeName)) + else + console.warn("Failed to activate theme '#{themeName}' because it isn't installed.") + Q.all(promises).then => @refreshLessCache() # Update cache again now that @getActiveThemes() is populated @loadUserStylesheet() diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 2128e04c2..bb7779b3e 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -119,12 +119,12 @@ class WorkspaceView extends View @command 'window:decrease-font-size', => @decreaseFontSize() @command 'window:reset-font-size', => @model.resetFontSize() - @command 'window:focus-next-pane', => @focusNextPane() - @command 'window:focus-previous-pane', => @focusPreviousPane() - @command 'window:focus-pane-above', => @focusPaneAbove() - @command 'window:focus-pane-below', => @focusPaneBelow() - @command 'window:focus-pane-on-left', => @focusPaneOnLeft() - @command 'window:focus-pane-on-right', => @focusPaneOnRight() + @command 'window:focus-next-pane', => @focusNextPaneView() + @command 'window:focus-previous-pane', => @focusPreviousPaneView() + @command 'window:focus-pane-above', => @focusPaneViewAbove() + @command 'window:focus-pane-below', => @focusPaneViewBelow() + @command 'window:focus-pane-on-left', => @focusPaneViewOnLeft() + @command 'window:focus-pane-on-right', => @focusPaneViewOnRight() @command 'window:save-all', => @saveAll() @command 'window:toggle-invisibles', => atom.config.toggle("editor.showInvisibles") @@ -233,10 +233,6 @@ class WorkspaceView extends View getActivePaneView: -> @panes.getActivePane() - # Deprecated: Returns the currently focused {PaneView}. - getActivePane: -> - @getActivePaneView() - # Public: Returns the currently focused item from within the focused {PaneView} getActivePaneItem: -> @model.activePaneItem @@ -246,40 +242,31 @@ class WorkspaceView extends View @panes.getActiveView() # Public: Focuses the previous pane by id. - focusPreviousPane: -> @model.activatePreviousPane() + focusPreviousPaneView: -> @model.activatePreviousPane() # Public: Focuses the next pane by id. - focusNextPane: -> @model.activateNextPane() + focusNextPaneView: -> @model.activateNextPane() # Public: Focuses the pane directly above the active pane. - focusPaneAbove: -> @panes.focusPaneAbove() + focusPaneViewAbove: -> @panes.focusPaneViewAbove() # Public: Focuses the pane directly below the active pane. - focusPaneBelow: -> @panes.focusPaneBelow() + focusPaneViewBelow: -> @panes.focusPaneViewBelow() # Public: Focuses the pane directly to the left of the active pane. - focusPaneOnLeft: -> @panes.focusPaneOnLeft() + focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft() # Public: Focuses the pane directly to the right of the active pane. - focusPaneOnRight: -> @panes.focusPaneOnRight() - - # Public: - # - # FIXME: Difference between active and focused pane? - getFocusedPane: -> @panes.getFocusedPane() + focusPaneViewOnRight: -> @panes.focusPaneViewOnRight() # Public: Fires a callback on each open {PaneView}. - eachPane: (callback) -> - @panes.eachPane(callback) + eachPaneView: (callback) -> + @panes.eachPaneView(callback) - # Public: Returns an Array of all open {PaneView}s. - getPanes: -> + # Returns an Array of all open {PaneView}s. + getPaneViews: -> @panes.getPanes() - # Public: Return the id of the given a {PaneView} - indexOfPane: (pane) -> - @panes.indexOfPane(pane) - # Public: Fires a callback on each open {EditorView}. eachEditorView: (callback) -> callback(editor) for editor in @getEditorViews() @@ -290,3 +277,15 @@ class WorkspaceView extends View # Called by SpacePen beforeRemove: -> @model.destroy() + + # Deprecated + eachPane: (callback) -> + @eachPaneView(callback) + + # Deprecated + getPanes: -> + @getPaneViews() + + # Deprecated + getActivePane: -> + @getActivePaneView() diff --git a/src/workspace.coffee b/src/workspace.coffee index b94fcde33..1a9b1d0ee 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -77,16 +77,14 @@ class Workspace extends Model split = options.split uri = atom.project.resolve(uri) - pane = switch split + pane = @paneContainer.paneForUri(uri) if searchAllPanes + pane ?= switch split when 'left' @activePane.findLeftmostSibling() when 'right' @activePane.findOrCreateRightmostSibling() else - if searchAllPanes - @paneContainer.paneForUri(uri) ? @activePane - else - @activePane + @activePane @openUriInPane(uri, pane, options) @@ -155,6 +153,15 @@ class Workspace extends Model getOpeners: -> atom.project.openers + # Public: Returns the active {Pane}. + getActivePane: -> + @paneContainer.activePane + + # Public: Returns the first pane {Pane} with an item for the given uri or + # undefined if none exists. + paneForUri: (uri) -> + @paneContainer.paneForUri(uri) + # Public: save the active item. saveActivePaneItem: -> @activePane?.saveActiveItem() diff --git a/vendor/apm b/vendor/apm index 97d281afe..5e1cfe1c1 160000 --- a/vendor/apm +++ b/vendor/apm @@ -1 +1 @@ -Subproject commit 97d281afec51c1e1be216e5d82f9e974d30fb63b +Subproject commit 5e1cfe1c1cd80035c182646a1c3e564385a0d999