From b5c9a90ae00ec44e91782b0d6e30be7ca2fea11c Mon Sep 17 00:00:00 2001 From: Einar Boson Date: Sun, 5 Jul 2015 01:04:15 +0200 Subject: [PATCH 01/18] :bug: Ask user to 'save as' if save fails when closing tab, fixes #7708 --- spec/pane-spec.coffee | 98 +++++++++++++++++++++++++++++++++++++++++++ src/pane.coffee | 58 +++++++++++++++++-------- 2 files changed, 139 insertions(+), 17 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 3453ac44d..bdeb9615a 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -671,6 +671,104 @@ describe "Pane", -> expect(item1.save).not.toHaveBeenCalled() expect(pane.isDestroyed()).toBe false + it "does not destroy the pane if save fails and user clicks cancel", -> + pane = new Pane(items: [new Item("A"), new Item("B")]) + [item1, item2] = pane.getItems() + + item1.shouldPromptToSave = -> true + item1.getURI = -> "/test/path" + + item1.save = jasmine.createSpy("save").andCallFake -> + error = new Error("EACCES, permission denied '/test/path'") + error.path = '/test/path' + error.code = 'EACCES' + throw error + + confirmations = 0 + spyOn(atom, 'confirm').andCallFake -> + confirmations++ + if confirmations is 1 + return 0 + else + return 1 + + pane.close() + + expect(atom.confirm).toHaveBeenCalled() + expect(confirmations).toBe(2) + expect(item1.save).toHaveBeenCalled() + expect(pane.isDestroyed()).toBe false + + it "does destroy the pane if the user saves the file under a new name", -> + pane = new Pane(items: [new Item("A"), new Item("B")]) + [item1, item2] = pane.getItems() + + item1.shouldPromptToSave = -> true + item1.getURI = -> "/test/path" + + item1.save = jasmine.createSpy("save").andCallFake -> + error = new Error("EACCES, permission denied '/test/path'") + error.path = '/test/path' + error.code = 'EACCES' + throw error + + item1.saveAs = jasmine.createSpy("saveAs").andReturn(true) + + confirmations = 0 + spyOn(atom, 'confirm').andCallFake -> + confirmations++ + return 0 + + spyOn(atom, 'showSaveDialogSync').andReturn("new/path") + + pane.close() + + expect(atom.confirm).toHaveBeenCalled() + expect(confirmations).toBe(2) + expect(atom.showSaveDialogSync).toHaveBeenCalled() + expect(item1.save).toHaveBeenCalled() + expect(item1.saveAs).toHaveBeenCalled() + expect(pane.isDestroyed()).toBe true + + it "asks again if the saveAs also fails", -> + pane = new Pane(items: [new Item("A"), new Item("B")]) + [item1, item2] = pane.getItems() + + item1.shouldPromptToSave = -> true + item1.getURI = -> "/test/path" + + item1.save = jasmine.createSpy("save").andCallFake -> + error = new Error("EACCES, permission denied '/test/path'") + error.path = '/test/path' + error.code = 'EACCES' + throw error + + item1.saveAs = jasmine.createSpy("saveAs").andCallFake -> + error = new Error("EACCES, permission denied '/test/path'") + error.path = '/test/path' + error.code = 'EACCES' + throw error + + + confirmations = 0 + spyOn(atom, 'confirm').andCallFake -> + confirmations++ + if confirmations < 3 + return 0 + return 2 + + spyOn(atom, 'showSaveDialogSync').andReturn("new/path") + + pane.close() + + expect(atom.confirm).toHaveBeenCalled() + expect(confirmations).toBe(3) + expect(atom.showSaveDialogSync).toHaveBeenCalled() + expect(item1.save).toHaveBeenCalled() + expect(item1.saveAs).toHaveBeenCalled() + expect(pane.isDestroyed()).toBe true + + describe "::destroy()", -> [container, pane1, pane2] = [] diff --git a/src/pane.coffee b/src/pane.coffee index f77da9d58..759146564 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -454,13 +454,26 @@ class Pane extends Model else return true + saveError = (error) => + if error + chosen = atom.confirm + message: @getSaveErrorMessage(error) + detailedMessage: "Your changes will be lost if you close this item without saving." + buttons: ["Save as", "Cancel", "Don't save"] + switch chosen + when 0 then @saveItemAs item, saveError + when 1 then false + when 2 then true + else + true + chosen = atom.confirm message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?" detailedMessage: "Your changes will be lost if you close this item without saving." buttons: ["Save", "Cancel", "Don't Save"] switch chosen - when 0 then @saveItem(item, -> true) + when 0 then @saveItem(item, saveError) when 1 then false when 2 then true @@ -479,8 +492,10 @@ class Pane extends Model # Public: Save the given item. # # * `item` The item to save. - # * `nextAction` (optional) {Function} which will be called after the item is - # successfully saved. + # * `nextAction` (optional) {Function} which will be called with no argument + # after the item is successfully saved, or with the error if it failed. + # The return value will be that of `nextAction` or `undefined` if it was not + # provided saveItem: (item, nextAction) -> if typeof item?.getURI is 'function' itemURI = item.getURI() @@ -490,9 +505,9 @@ class Pane extends Model if itemURI? try item.save?() + nextAction?() catch error - @handleSaveError(error) - nextAction?() + (nextAction ? @handleSaveError)(error) else @saveItemAs(item, nextAction) @@ -500,8 +515,10 @@ class Pane extends Model # path they select. # # * `item` The item to save. - # * `nextAction` (optional) {Function} which will be called after the item is - # successfully saved. + # * `nextAction` (optional) {Function} which will be called with no argument + # after the item is successfully saved, or with the error if it failed. + # The return value will be that of `nextAction` or `undefined` if it was not + # provided saveItemAs: (item, nextAction) -> return unless item?.saveAs? @@ -511,9 +528,9 @@ class Pane extends Model if newItemPath try item.saveAs(newItemPath) + nextAction?() catch error - @handleSaveError(error) - nextAction?() + (nextAction ? @handleSaveError)(error) # Public: Save all items. saveItems: -> @@ -676,22 +693,29 @@ class Pane extends Model return false unless @promptToSaveItem(item) true - handleSaveError: (error) -> + # Translate an error object to a human readable string + getSaveErrorMessage: (error) -> if error.code is 'EISDIR' or error.message.endsWith('is a directory') - atom.notifications.addWarning("Unable to save file: #{error.message}") + "Unable to save file: #{error.message}." else if error.code is 'EACCES' and error.path? - atom.notifications.addWarning("Unable to save file: Permission denied '#{error.path}'") + "Unable to save file: Permission denied '#{error.path}'." else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST'] and error.path? - atom.notifications.addWarning("Unable to save file '#{error.path}'", detail: error.message) + "Unable to save file '#{error.path}': #{error.message}." else if error.code is 'EROFS' and error.path? - atom.notifications.addWarning("Unable to save file: Read-only file system '#{error.path}'") + "Unable to save file: Read-only file system '#{error.path}'." else if error.code is 'ENOSPC' and error.path? - atom.notifications.addWarning("Unable to save file: No space left on device '#{error.path}'") + "Unable to save file: No space left on device '#{error.path}'." else if error.code is 'ENXIO' and error.path? - atom.notifications.addWarning("Unable to save file: No such device or address '#{error.path}'") + "Unable to save file: No such device or address '#{error.path}'." else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message) fileName = errorMatch[1] - atom.notifications.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to") + "Unable to save file: A directory in the path '#{fileName}' could not be written to." + + # Display a popup warning to the user + handleSaveError: (error) -> + errorMessage = Pane::getSaveErrorMessage(error) + if errorMessage? + atom.notifications.addWarning(errorMessage) else throw error From 698854679072603f7d564fbab36ad6df8c7653be Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Thu, 14 Apr 2016 22:02:35 -0700 Subject: [PATCH 02/18] Update to use current APIs --- spec/pane-spec.coffee | 140 ++++++++++++++++++------------------------ src/pane.coffee | 32 +--------- 2 files changed, 62 insertions(+), 110 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 5b4830dd6..8abbb0ece 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -917,103 +917,81 @@ describe "Pane", -> expect(item1.save).not.toHaveBeenCalled() expect(pane.isDestroyed()).toBe false - it "does not destroy the pane if save fails and user clicks cancel", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) - [item1, item2] = pane.getItems() + describe "when item fails to save", -> + [pane, item1, item2] = [] - item1.shouldPromptToSave = -> true - item1.getURI = -> "/test/path" + beforeEach -> + pane = new Pane({items: [new Item("A"), new Item("B")], applicationDelegate: atom.applicationDelegate, config: atom.config}) + [item1, item2] = pane.getItems() - item1.save = jasmine.createSpy("save").andCallFake -> - error = new Error("EACCES, permission denied '/test/path'") - error.path = '/test/path' - error.code = 'EACCES' - throw error + item1.shouldPromptToSave = -> true + item1.getURI = -> "/test/path" - confirmations = 0 - spyOn(atom, 'confirm').andCallFake -> - confirmations++ - if confirmations is 1 - return 0 - else - return 1 + item1.save = jasmine.createSpy("save").andCallFake -> + error = new Error("EACCES, permission denied '/test/path'") + error.path = '/test/path' + error.code = 'EACCES' + throw error - pane.close() + it "does not destroy the pane if save fails and user clicks cancel", -> + confirmations = 0 + confirm.andCallFake -> + confirmations++ + if confirmations is 1 + return 0 # click save + else + return 1 # click cancel - expect(atom.confirm).toHaveBeenCalled() - expect(confirmations).toBe(2) - expect(item1.save).toHaveBeenCalled() - expect(pane.isDestroyed()).toBe false + pane.close() - it "does destroy the pane if the user saves the file under a new name", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) - [item1, item2] = pane.getItems() + expect(atom.applicationDelegate.confirm).toHaveBeenCalled() + expect(confirmations).toBe(2) + expect(item1.save).toHaveBeenCalled() + expect(pane.isDestroyed()).toBe false - item1.shouldPromptToSave = -> true - item1.getURI = -> "/test/path" + it "does destroy the pane if the user saves the file under a new name", -> + item1.saveAs = jasmine.createSpy("saveAs").andReturn(true) - item1.save = jasmine.createSpy("save").andCallFake -> - error = new Error("EACCES, permission denied '/test/path'") - error.path = '/test/path' - error.code = 'EACCES' - throw error + confirmations = 0 + confirm.andCallFake -> + confirmations++ + return 0 # save and then save as - item1.saveAs = jasmine.createSpy("saveAs").andReturn(true) + showSaveDialog.andReturn("new/path") - confirmations = 0 - spyOn(atom, 'confirm').andCallFake -> - confirmations++ - return 0 + pane.close() - spyOn(atom, 'showSaveDialogSync').andReturn("new/path") + expect(atom.applicationDelegate.confirm).toHaveBeenCalled() + expect(confirmations).toBe(2) + expect(atom.applicationDelegate.showSaveDialog).toHaveBeenCalled() + expect(item1.save).toHaveBeenCalled() + expect(item1.saveAs).toHaveBeenCalled() + expect(pane.isDestroyed()).toBe true - pane.close() + it "asks again if the saveAs also fails", -> + item1.saveAs = jasmine.createSpy("saveAs").andCallFake -> + error = new Error("EACCES, permission denied '/test/path'") + error.path = '/test/path' + error.code = 'EACCES' + throw error - expect(atom.confirm).toHaveBeenCalled() - expect(confirmations).toBe(2) - expect(atom.showSaveDialogSync).toHaveBeenCalled() - expect(item1.save).toHaveBeenCalled() - expect(item1.saveAs).toHaveBeenCalled() - expect(pane.isDestroyed()).toBe true + confirmations = 0 + confirm.andCallFake -> + confirmations++ + if confirmations < 3 + return 0 # save, save as, save as + return 2 # don't save - it "asks again if the saveAs also fails", -> - pane = new Pane(items: [new Item("A"), new Item("B")]) - [item1, item2] = pane.getItems() + showSaveDialog.andReturn("new/path") - item1.shouldPromptToSave = -> true - item1.getURI = -> "/test/path" - - item1.save = jasmine.createSpy("save").andCallFake -> - error = new Error("EACCES, permission denied '/test/path'") - error.path = '/test/path' - error.code = 'EACCES' - throw error - - item1.saveAs = jasmine.createSpy("saveAs").andCallFake -> - error = new Error("EACCES, permission denied '/test/path'") - error.path = '/test/path' - error.code = 'EACCES' - throw error - - - confirmations = 0 - spyOn(atom, 'confirm').andCallFake -> - confirmations++ - if confirmations < 3 - return 0 - return 2 - - spyOn(atom, 'showSaveDialogSync').andReturn("new/path") - - pane.close() - - expect(atom.confirm).toHaveBeenCalled() - expect(confirmations).toBe(3) - expect(atom.showSaveDialogSync).toHaveBeenCalled() - expect(item1.save).toHaveBeenCalled() - expect(item1.saveAs).toHaveBeenCalled() - expect(pane.isDestroyed()).toBe true + pane.close() + expect(atom.applicationDelegate.confirm).toHaveBeenCalled() + expect(confirmations).toBe(3) + expect(atom.applicationDelegate.showSaveDialog).toHaveBeenCalled() + expect(item1.save).toHaveBeenCalled() + expect(item1.saveAs).toHaveBeenCalled() + expect(pane.isDestroyed()).toBe true describe "::destroy()", -> [container, pane1, pane2] = [] diff --git a/src/pane.coffee b/src/pane.coffee index 0f33ef218..e1dbc8596 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -579,8 +579,8 @@ class Pane extends Model saveError = (error) => if error - chosen = atom.confirm - message: @getSaveErrorMessage(error) + chosen = @applicationDelegate.confirm + message: @getMessageForErrorCode(error) detailedMessage: "Your changes will be lost if you close this item without saving." buttons: ["Save as", "Cancel", "Don't save"] switch chosen @@ -657,7 +657,7 @@ class Pane extends Model nextAction?() catch error if nextAction - nextAction() + nextAction(error) else @handleSaveError(error, item) @@ -851,7 +851,6 @@ class Pane extends Model return false unless @promptToSaveItem(item) true -# <<<<<<< HEAD handleSaveError: (error, item) -> itemPath = error.path ? item?.getPath?() addWarningWithPath = (message, options) => @@ -868,31 +867,6 @@ class Pane extends Model else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message) fileName = errorMatch[1] @notificationManager.addWarning("Unable to save file: A directory in the path '#{fileName}' could not be written to") -# ======= -# # Translate an error object to a human readable string -# getSaveErrorMessage: (error) -> -# if error.code is 'EISDIR' or error.message.endsWith('is a directory') -# "Unable to save file: #{error.message}." -# else if error.code is 'EACCES' and error.path? -# "Unable to save file: Permission denied '#{error.path}'." -# else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST'] and error.path? -# "Unable to save file '#{error.path}': #{error.message}." -# else if error.code is 'EROFS' and error.path? -# "Unable to save file: Read-only file system '#{error.path}'." -# else if error.code is 'ENOSPC' and error.path? -# "Unable to save file: No space left on device '#{error.path}'." -# else if error.code is 'ENXIO' and error.path? -# "Unable to save file: No such device or address '#{error.path}'." -# else if errorMatch = /ENOTDIR, not a directory '([^']+)'/.exec(error.message) -# fileName = errorMatch[1] -# "Unable to save file: A directory in the path '#{fileName}' could not be written to." -# -# # Display a popup warning to the user -# handleSaveError: (error) -> -# errorMessage = Pane::getSaveErrorMessage(error) -# if errorMessage? -# atom.notifications.addWarning(errorMessage) -# >>>>>>> b5c9a90ae00ec44e91782b0d6e30be7ca2fea11c else throw error From 4e9048d22de5fce1fb4bce20515fcee96aae786d Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Thu, 14 Apr 2016 23:25:27 -0700 Subject: [PATCH 03/18] Create saveDialog helper function and name file in message --- spec/fixtures/sample.txt | 2 +- src/pane.coffee | 33 ++++++++++++++------------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/spec/fixtures/sample.txt b/spec/fixtures/sample.txt index 9701a96c5..34dad6adf 100644 --- a/spec/fixtures/sample.txt +++ b/spec/fixtures/sample.txt @@ -1 +1 @@ -Some textSome textSome text. +Some textSome textSome textSome textSome textSome textSome textSome textSome textSome textSome text. diff --git a/src/pane.coffee b/src/pane.coffee index e1dbc8596..add6a365b 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -577,28 +577,23 @@ class Pane extends Model else return true + saveDialog = (saveButtonText, saveFn, message) => + chosen = @applicationDelegate.confirm + message: message + detailedMessage: "Your changes will be lost if you close this item without saving." + buttons: [saveButtonText, "Cancel", "Don't save"] + switch chosen + when 0 then saveFn(item, saveError) + when 1 then false + when 2 then true + saveError = (error) => if error - chosen = @applicationDelegate.confirm - message: @getMessageForErrorCode(error) - detailedMessage: "Your changes will be lost if you close this item without saving." - buttons: ["Save as", "Cancel", "Don't save"] - switch chosen - when 0 then @saveItemAs item, saveError - when 1 then false - when 2 then true + saveDialog("Save as", @saveItemAs, "'#{item.getTitle?() ? uri}' could not be saved.\nError: #{@getMessageForErrorCode(error.code)}") else true - chosen = @applicationDelegate.confirm - message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?" - detailedMessage: "Your changes will be lost if you close this item without saving." - buttons: ["Save", "Cancel", "Don't Save"] - - switch chosen - when 0 then @saveItem(item, saveError) - when 1 then false - when 2 then true + saveDialog("Save", @saveItem, "'#{item.getTitle?() ? uri}' has changes, do you want to save them?") # Public: Save the active item. saveActiveItem: (nextAction) -> @@ -619,7 +614,7 @@ class Pane extends Model # after the item is successfully saved, or with the error if it failed. # The return value will be that of `nextAction` or `undefined` if it was not # provided - saveItem: (item, nextAction) -> + saveItem: (item, nextAction) => if typeof item?.getURI is 'function' itemURI = item.getURI() else if typeof item?.getUri is 'function' @@ -645,7 +640,7 @@ class Pane extends Model # after the item is successfully saved, or with the error if it failed. # The return value will be that of `nextAction` or `undefined` if it was not # provided - saveItemAs: (item, nextAction) -> + saveItemAs: (item, nextAction) => return unless item?.saveAs? saveOptions = item.getSaveDialogOptions?() ? {} From b790716caae25587dc8f5bdc811c90c8304c0f40 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Thu, 14 Apr 2016 23:28:13 -0700 Subject: [PATCH 04/18] Revert sample.txt file --- spec/fixtures/sample.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/fixtures/sample.txt b/spec/fixtures/sample.txt index 34dad6adf..9701a96c5 100644 --- a/spec/fixtures/sample.txt +++ b/spec/fixtures/sample.txt @@ -1 +1 @@ -Some textSome textSome textSome textSome textSome textSome textSome textSome textSome textSome text. +Some textSome textSome text. From 57bf8f797bf15cf25189acb709c4a78d9b2597fc Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Sun, 1 May 2016 10:32:21 -0700 Subject: [PATCH 05/18] :arrow_up: encoding-selector@0.22.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 535294933..af906359f 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "command-palette": "0.38.0", "deprecation-cop": "0.54.1", "dev-live-reload": "0.47.0", - "encoding-selector": "0.21.0", + "encoding-selector": "0.22.0", "exception-reporting": "0.38.1", "fuzzy-finder": "1.0.5", "git-diff": "1.0.1", From 73748ef768f8691c0f22a9d7a846370de4ec4dfb Mon Sep 17 00:00:00 2001 From: Willem Van Lint Date: Sun, 17 Apr 2016 17:06:22 -0700 Subject: [PATCH 06/18] Order listeners by reverse registration order --- spec/command-registry-spec.coffee | 7 +++++++ src/command-registry.coffee | 11 +++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/spec/command-registry-spec.coffee b/spec/command-registry-spec.coffee index ecdd42fd6..aaf044b1d 100644 --- a/spec/command-registry-spec.coffee +++ b/spec/command-registry-spec.coffee @@ -74,6 +74,13 @@ describe "CommandRegistry", -> grandchild.dispatchEvent(new CustomEvent('command', bubbles: true)) expect(calls).toEqual ['.foo.bar', '.bar', '.foo'] + it "orders inline listeners by reverse registration order", -> + calls = [] + registry.add child, 'command', -> calls.push('child1') + registry.add child, 'command', -> calls.push('child2') + child.dispatchEvent(new CustomEvent('command', bubbles: true)) + expect(calls).toEqual ['child2', 'child1'] + it "stops bubbling through ancestors when .stopPropagation() is called on the event", -> calls = [] diff --git a/src/command-registry.coffee b/src/command-registry.coffee index db2cf498d..955a1b540 100644 --- a/src/command-registry.coffee +++ b/src/command-registry.coffee @@ -244,11 +244,14 @@ class CommandRegistry (@selectorBasedListenersByCommandName[event.type] ? []) .filter (listener) -> currentTarget.webkitMatchesSelector(listener.selector) .sort (a, b) -> a.compare(b) - listeners = listeners.concat(selectorBasedListeners) + listeners = selectorBasedListeners.concat(listeners) matched = true if listeners.length > 0 - for listener in listeners + # Call inline listeners first in reverse registration order, + # and selector-based listeners by specificity and reverse + # registration order. + for listener in listeners by -1 break if immediatePropagationStopped listener.callback.call(currentTarget, dispatchedEvent) @@ -271,8 +274,8 @@ class SelectorBasedListener @sequenceNumber = SequenceCount++ compare: (other) -> - other.specificity - @specificity or - other.sequenceNumber - @sequenceNumber + @specificity - other.specificity or + @sequenceNumber - other.sequenceNumber class InlineListener constructor: (@callback) -> From 671334993f5984646f47755e783272440c6bb6ab Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sun, 1 May 2016 22:16:36 -0700 Subject: [PATCH 07/18] :arrow_up: apm@1.10.0 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 4ddb4dabe..d4fcc851a 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.9.3" + "atom-package-manager": "1.10.0" } } From 874be7d242ce6e88d32f63d5e7455ac9c20c9331 Mon Sep 17 00:00:00 2001 From: Timothy Cyrus Date: Mon, 2 May 2016 10:47:49 -0400 Subject: [PATCH 08/18] Update package.json Update `marked` to fix sanitization issue on david-dm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af906359f..04ee2034c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "key-path-helpers": "^0.4.0", "less-cache": "0.23", "line-top-index": "0.2.0", - "marked": "^0.3.4", + "marked": "^0.3.5", "normalize-package-data": "^2.0.0", "nslog": "^3", "ohnogit": "0.0.11", From 9adc822822d42877151bda2fe1f3051205d76b98 Mon Sep 17 00:00:00 2001 From: joshaber Date: Mon, 2 May 2016 11:32:29 -0400 Subject: [PATCH 09/18] Mark text editors as being registered. --- src/text-editor-registry.coffee | 14 +++++++++++++- src/text-editor.coffee | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/text-editor-registry.coffee b/src/text-editor-registry.coffee index 8a17335d4..e31630fee 100644 --- a/src/text-editor-registry.coffee +++ b/src/text-editor-registry.coffee @@ -26,8 +26,20 @@ class TextEditorRegistry # editor is destroyed. add: (editor) -> @editors.add(editor) + editor.registered = true + @emitter.emit 'did-add-editor', editor - new Disposable => @editors.delete(editor) + new Disposable => @remove(editor) + + # Remove a `TextEditor`. + # + # * `editor` The editor to remove. + # + # Returns a {Boolean} indicating whether the editor was successfully removed. + remove: (editor) -> + removed = @editors.delete(editor) + editor.registered = false + removed # Invoke the given callback with all the current and future registered # `TextEditors`. diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 9976e5906..bdc283d8f 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -62,6 +62,7 @@ class TextEditor extends Model selectionFlashDuration: 500 gutterContainer: null editorElement: null + registered: false Object.defineProperty @prototype, "element", get: -> @getElement() @@ -157,7 +158,7 @@ class TextEditor extends Model firstVisibleScreenColumn: @getFirstVisibleScreenColumn() displayBuffer: @displayBuffer.serialize() selectionsMarkerLayerId: @selectionsMarkerLayer.id - registered: atom.textEditors.editors.has this + registered: @registered subscribeToBuffer: -> @buffer.retain() From d325e02def5e7819030e09eab09fcb62e5d701b9 Mon Sep 17 00:00:00 2001 From: joshaber Date: Mon, 2 May 2016 11:32:38 -0400 Subject: [PATCH 10/18] Test it. --- spec/text-editor-registry-spec.coffee | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/text-editor-registry-spec.coffee b/spec/text-editor-registry-spec.coffee index 04665bef2..80f29f897 100644 --- a/spec/text-editor-registry-spec.coffee +++ b/spec/text-editor-registry-spec.coffee @@ -10,6 +10,7 @@ describe "TextEditorRegistry", -> it "gets added to the list of registered editors", -> editor = {} registry.add(editor) + expect(editor.registered).toBe true expect(registry.editors.size).toBe 1 expect(registry.editors.has(editor)).toBe(true) @@ -19,6 +20,16 @@ describe "TextEditorRegistry", -> expect(registry.editors.size).toBe 1 disposable.dispose() expect(registry.editors.size).toBe 0 + expect(editor.registered).toBe false + + it "can be removed", -> + editor = {} + registry.add(editor) + expect(registry.editors.size).toBe 1 + success = registry.remove(editor) + expect(success).toBe true + expect(registry.editors.size).toBe 0 + expect(editor.registered).toBe false describe "when the registry is observed", -> it "calls the callback for current and future editors until unsubscribed", -> From dd24e3b22304b495625140f74be9d221238074ab Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Mon, 2 May 2016 13:19:19 -0700 Subject: [PATCH 11/18] :arrow_up: tabs@0.93.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af906359f..8b4d137ff 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "status-bar": "1.2.6", "styleguide": "0.45.2", "symbols-view": "0.112.0", - "tabs": "0.93.1", + "tabs": "0.93.2", "timecop": "0.33.1", "tree-view": "0.206.2", "update-package-dependencies": "0.10.0", From d6d47c422c07b71421471720f7d96b52890feeb0 Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Tue, 3 May 2016 09:20:47 -0700 Subject: [PATCH 12/18] :arrow_up: settings-view@0.236.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d007eefa8..5a752cd6d 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "notifications": "0.63.2", "open-on-github": "1.1.0", "package-generator": "1.0.0", - "settings-view": "0.235.1", + "settings-view": "0.236.0", "snippets": "1.0.2", "spell-check": "0.67.1", "status-bar": "1.2.6", From 0e194f1021935deb7acc7237bda43a63382ae5a1 Mon Sep 17 00:00:00 2001 From: Lee Dohm Date: Tue, 3 May 2016 16:04:04 -0700 Subject: [PATCH 13/18] :arrow_up: line-ending-selector@0.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a752cd6d..e76dce85e 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "image-view": "0.57.0", "incompatible-packages": "0.26.1", "keybinding-resolver": "0.35.0", - "line-ending-selector": "0.4.1", + "line-ending-selector": "0.5.0", "link": "0.31.1", "markdown-preview": "0.158.0", "metrics": "0.53.1", From c56cbe3ce364ac0e2d6ad4c4818bdbca935889db Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Tue, 3 May 2016 16:50:06 -0700 Subject: [PATCH 14/18] :shirt: Change fat arrow to thin arrow for linter warning --- src/workspace.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index f75f00bc6..5e9de93dd 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -1092,7 +1092,7 @@ class Workspace extends Model if editor.getPath() checkoutHead = => @project.repositoryForDirectory(new Directory(editor.getDirectoryPath())) - .then (repository) => + .then (repository) -> repository?.async.checkoutHeadForEditor(editor) if @config.get('editor.confirmCheckoutHeadRevision') From d29e96e358970ccea1aa0bd5305ba61b04559afb Mon Sep 17 00:00:00 2001 From: Wliu Date: Tue, 3 May 2016 20:47:02 -0400 Subject: [PATCH 15/18] :arrow_up: language-sass@0.50.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e76dce85e..29d08589b 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ "language-python": "0.43.1", "language-ruby": "0.68.5", "language-ruby-on-rails": "0.25.0", - "language-sass": "0.49.0", + "language-sass": "0.50.0", "language-shellscript": "0.22.0", "language-source": "0.9.0", "language-sql": "0.21.0", From b9dbb81bd5404294bb33b2b30ffe1b464a2d2eac Mon Sep 17 00:00:00 2001 From: simurai Date: Wed, 4 May 2016 12:05:04 +0900 Subject: [PATCH 16/18] Revert ":arrow_up: language-sass@0.50.0" This reverts commit d29e96e358970ccea1aa0bd5305ba61b04559afb. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29d08589b..e76dce85e 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ "language-python": "0.43.1", "language-ruby": "0.68.5", "language-ruby-on-rails": "0.25.0", - "language-sass": "0.50.0", + "language-sass": "0.49.0", "language-shellscript": "0.22.0", "language-source": "0.9.0", "language-sql": "0.21.0", From 6c6f8fc34154f2900e003c5956465119c66618c8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 4 May 2016 10:15:02 +0200 Subject: [PATCH 17/18] :arrow_up: autocomplete-plus --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e76dce85e..7f7a5dfe8 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "autocomplete-atom-api": "0.10.0", "autocomplete-css": "0.11.1", "autocomplete-html": "0.7.2", - "autocomplete-plus": "2.30.0", + "autocomplete-plus": "2.31.0", "autocomplete-snippets": "1.10.0", "autoflow": "0.27.0", "autosave": "0.23.1", From 512f1fb540700ed455e4aca3821bf6e0ee6ed6f9 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Wed, 4 May 2016 11:56:17 +0200 Subject: [PATCH 18/18] :arrow_up: symbols-view@0.113.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f7a5dfe8..f5a432a2d 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "spell-check": "0.67.1", "status-bar": "1.2.6", "styleguide": "0.45.2", - "symbols-view": "0.112.0", + "symbols-view": "0.113.0", "tabs": "0.93.2", "timecop": "0.33.1", "tree-view": "0.206.2",