From 7a0a808af17fc83488cf2705e0bca5cd8477aba5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 19 Aug 2014 12:14:16 -0600 Subject: [PATCH 001/355] Change ctrl-a binding to editor:move-to-first-character-of-line Considering that the entire Atom core team has ctrl-a bound to move to the first character and it's also the the default behavior of Sublime, this seems like a more sensible and useful default option even though it deviates from text editing norms on OS X. --- keymaps/darwin.cson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymaps/darwin.cson b/keymaps/darwin.cson index 9c164c9c0..34f977209 100644 --- a/keymaps/darwin.cson +++ b/keymaps/darwin.cson @@ -119,7 +119,7 @@ 'cmd-shift-right': 'editor:select-to-end-of-line' 'alt-backspace': 'editor:delete-to-beginning-of-word' 'alt-delete': 'editor:delete-to-end-of-word' - 'ctrl-a': 'editor:move-to-beginning-of-line' + 'ctrl-a': 'editor:move-to-first-character-of-line' 'ctrl-e': 'editor:move-to-end-of-line' 'ctrl-k': 'editor:cut-to-end-of-line' From ebb02bcd37b297180a6ed5cf65461f94329c33c3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Aug 2014 20:21:20 -0600 Subject: [PATCH 002/355] Use public getters instead of properties in pane-spec --- spec/pane-spec.coffee | 140 +++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 04b1c2474..d6eeb57e0 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -21,28 +21,28 @@ describe "Pane", -> describe "construction", -> it "sets the active item to the first item", -> pane = new Pane(items: [new Item("A"), new Item("B")]) - expect(pane.activeItem).toBe pane.items[0] + expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) it "compacts the items array", -> pane = new Pane(items: [undefined, new Item("A"), null, new Item("B")]) - expect(pane.items.length).toBe 2 - expect(pane.activeItem).toBe pane.items[0] + expect(pane.getItems().length).toBe 2 + expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) describe "::addItem(item, index)", -> it "adds the item at the given index", -> pane = new Pane(items: [new Item("A"), new Item("B")]) - [item1, item2] = pane.items + [item1, item2] = pane.getItems() item3 = new Item("C") pane.addItem(item3, 1) - expect(pane.items).toEqual [item1, item3, item2] + expect(pane.getItems()).toEqual [item1, item3, item2] it "adds the item after the active item ", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() pane.activateItem(item2) item4 = new Item("D") pane.addItem(item4) - expect(pane.items).toEqual [item1, item2, item4, item3] + expect(pane.getItems()).toEqual [item1, item2, item4, item3] it "sets the active item after adding the first item", -> pane = new Pane @@ -52,7 +52,7 @@ describe "Pane", -> pane.$activeItem.changes.onValue -> events.push('active-item-changed') pane.addItem(item) - expect(pane.activeItem).toBe item + expect(pane.getActiveItem()).toBe item expect(events).toEqual ['item-added', 'active-item-changed'] describe "::activateItem(item)", -> @@ -62,78 +62,78 @@ describe "Pane", -> pane = new Pane(items: [new Item("A"), new Item("B")]) it "changes the active item to the current item", -> - expect(pane.activeItem).toBe pane.items[0] - pane.activateItem(pane.items[1]) - expect(pane.activeItem).toBe pane.items[1] + expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) + pane.activateItem(pane.itemAtIndex(1)) + expect(pane.getActiveItem()).toBe pane.itemAtIndex(1) it "adds the given item if it isn't present in ::items", -> item = new Item("C") pane.activateItem(item) - expect(item in pane.items).toBe true - expect(pane.activeItem).toBe item + expect(item in pane.getItems()).toBe true + expect(pane.getActiveItem()).toBe item describe "::activateNextItem() and ::activatePreviousItem()", -> it "sets the active item to the next/previous item, looping around at either end", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 pane.activatePreviousItem() - expect(pane.activeItem).toBe item3 + expect(pane.getActiveItem()).toBe item3 pane.activatePreviousItem() - expect(pane.activeItem).toBe item2 + expect(pane.getActiveItem()).toBe item2 pane.activateNextItem() - expect(pane.activeItem).toBe item3 + expect(pane.getActiveItem()).toBe item3 pane.activateNextItem() - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 describe "::activateItemAtIndex(index)", -> it "activates the item at the given index", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() pane.activateItemAtIndex(2) - expect(pane.activeItem).toBe item3 + expect(pane.getActiveItem()).toBe item3 pane.activateItemAtIndex(1) - expect(pane.activeItem).toBe item2 + expect(pane.getActiveItem()).toBe item2 pane.activateItemAtIndex(0) - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 # Doesn't fail with out-of-bounds indices pane.activateItemAtIndex(100) - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 pane.activateItemAtIndex(-1) - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 describe "::destroyItem(item)", -> [pane, item1, item2, item3] = [] beforeEach -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() it "removes the item from the items list", -> - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 pane.destroyItem(item2) - expect(item2 in pane.items).toBe false - expect(pane.activeItem).toBe item1 + expect(item2 in pane.getItems()).toBe false + expect(pane.getActiveItem()).toBe item1 pane.destroyItem(item1) - expect(item1 in pane.items).toBe false + expect(item1 in pane.getItems()).toBe false describe "when the destroyed item is the active item and is the first item", -> it "activates the next item", -> - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 pane.destroyItem(item1) - expect(pane.activeItem).toBe item2 + expect(pane.getActiveItem()).toBe item2 describe "when the destroyed item is the active item and is not the first item", -> beforeEach -> pane.activateItem(item2) it "activates the previous item", -> - expect(pane.activeItem).toBe item2 + expect(pane.getActiveItem()).toBe item2 pane.destroyItem(item2) - expect(pane.activeItem).toBe item1 + expect(pane.getActiveItem()).toBe item1 it "emits 'item-removed' with the item, its index, and true indicating the item is being destroyed", -> pane.on 'item-removed', itemRemovedHandler = jasmine.createSpy("itemRemovedHandler") @@ -157,7 +157,7 @@ describe "Pane", -> pane.destroyItem(item1) expect(item1.save).toHaveBeenCalled() - expect(item1 in pane.items).toBe false + expect(item1 in pane.getItems()).toBe false expect(item1.isDestroyed()).toBe true describe "when the item has no uri", -> @@ -170,7 +170,7 @@ describe "Pane", -> expect(atom.showSaveDialogSync).toHaveBeenCalled() expect(item1.saveAs).toHaveBeenCalledWith("/selected/path") - expect(item1 in pane.items).toBe false + expect(item1 in pane.getItems()).toBe false expect(item1.isDestroyed()).toBe true describe "if the [Don't Save] option is selected", -> @@ -179,7 +179,7 @@ describe "Pane", -> pane.destroyItem(item1) expect(item1.save).not.toHaveBeenCalled() - expect(item1 in pane.items).toBe false + expect(item1 in pane.getItems()).toBe false expect(item1.isDestroyed()).toBe true describe "if the [Cancel] option is selected", -> @@ -188,7 +188,7 @@ describe "Pane", -> pane.destroyItem(item1) expect(item1.save).not.toHaveBeenCalled() - expect(item1 in pane.items).toBe true + expect(item1 in pane.getItems()).toBe true expect(item1.isDestroyed()).toBe false describe "when the last item is destroyed", -> @@ -197,7 +197,7 @@ describe "Pane", -> expect(atom.config.get('core.destroyEmptyPanes')).toBe false pane.destroyItem(item) for item in pane.getItems() expect(pane.isDestroyed()).toBe false - expect(pane.activeItem).toBeUndefined() + expect(pane.getActiveItem()).toBeUndefined() expect(-> pane.saveActiveItem()).not.toThrow() expect(-> pane.saveActiveItemAs()).not.toThrow() @@ -210,10 +210,10 @@ describe "Pane", -> describe "::destroyActiveItem()", -> it "destroys the active item", -> pane = new Pane(items: [new Item("A"), new Item("B")]) - activeItem = pane.activeItem + activeItem = pane.getActiveItem() pane.destroyActiveItem() expect(activeItem.isDestroyed()).toBe true - expect(activeItem in pane.items).toBe false + expect(activeItem in pane.getItems()).toBe false it "does not throw an exception if there are no more items", -> pane = new Pane @@ -222,27 +222,27 @@ describe "Pane", -> describe "::destroyItems()", -> it "destroys all items", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() pane.destroyItems() expect(item1.isDestroyed()).toBe true expect(item2.isDestroyed()).toBe true expect(item3.isDestroyed()).toBe true - expect(pane.items).toEqual [] + expect(pane.getItems()).toEqual [] describe "when an item emits a destroyed event", -> it "removes it from the list of items", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items - pane.items[1].destroy() - expect(pane.items).toEqual [item1, item3] + [item1, item2, item3] = pane.getItems() + pane.itemAtIndex(1).destroy() + expect(pane.getItems()).toEqual [item1, item3] describe "::destroyInactiveItems()", -> it "destroys all items but the active item", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() pane.activateItem(item2) pane.destroyInactiveItems() - expect(pane.items).toEqual [item2] + expect(pane.getItems()).toEqual [item2] describe "::saveActiveItem()", -> pane = null @@ -253,30 +253,30 @@ describe "Pane", -> describe "when the active item has a uri", -> beforeEach -> - pane.activeItem.uri = "test" + pane.getActiveItem().uri = "test" describe "when the active item has a save method", -> it "saves the current item", -> - pane.activeItem.save = jasmine.createSpy("save") + pane.getActiveItem().save = jasmine.createSpy("save") pane.saveActiveItem() - expect(pane.activeItem.save).toHaveBeenCalled() + expect(pane.getActiveItem().save).toHaveBeenCalled() describe "when the current item has no save method", -> it "does nothing", -> - expect(pane.activeItem.save).toBeUndefined() + expect(pane.getActiveItem().save).toBeUndefined() pane.saveActiveItem() describe "when the current item has no uri", -> describe "when the current item has a saveAs method", -> it "opens a save dialog and saves the current item as the selected path", -> - pane.activeItem.saveAs = jasmine.createSpy("saveAs") + pane.getActiveItem().saveAs = jasmine.createSpy("saveAs") pane.saveActiveItem() expect(atom.showSaveDialogSync).toHaveBeenCalled() - expect(pane.activeItem.saveAs).toHaveBeenCalledWith('/selected/path') + expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path') describe "when the current item has no saveAs method", -> it "does nothing", -> - expect(pane.activeItem.saveAs).toBeUndefined() + expect(pane.getActiveItem().saveAs).toBeUndefined() pane.saveActiveItem() expect(atom.showSaveDialogSync).not.toHaveBeenCalled() @@ -289,22 +289,22 @@ describe "Pane", -> describe "when the current item has a saveAs method", -> it "opens the save dialog and calls saveAs on the item with the selected path", -> - pane.activeItem.path = __filename - pane.activeItem.saveAs = jasmine.createSpy("saveAs") + pane.getActiveItem().path = __filename + pane.getActiveItem().saveAs = jasmine.createSpy("saveAs") pane.saveActiveItemAs() expect(atom.showSaveDialogSync).toHaveBeenCalledWith(__filename) - expect(pane.activeItem.saveAs).toHaveBeenCalledWith('/selected/path') + expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path') describe "when the current item does not have a saveAs method", -> it "does nothing", -> - expect(pane.activeItem.saveAs).toBeUndefined() + expect(pane.getActiveItem().saveAs).toBeUndefined() pane.saveActiveItemAs() expect(atom.showSaveDialogSync).not.toHaveBeenCalled() describe "::itemForUri(uri)", -> it "returns the item for which a call to .getUri() returns the given uri", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) - [item1, item2, item3] = pane.items + [item1, item2, item3] = pane.getItems() item1.uri = "a" item2.uri = "b" expect(pane.itemForUri("a")).toBe item1 @@ -314,7 +314,7 @@ describe "Pane", -> describe "::moveItem(item, index)", -> it "moves the item to the given index and emits an 'item-moved' event with the item and its new index", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) - [item1, item2, item3, item4] = pane.items + [item1, item2, item3, item4] = pane.getItems() pane.on 'item-moved', itemMovedHandler = jasmine.createSpy("itemMovedHandler") pane.moveItem(item1, 2) @@ -339,13 +339,13 @@ describe "Pane", -> pane1 = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) container = new PaneContainer(root: pane1) pane2 = pane1.splitRight(items: [new Item("D"), new Item("E")]) - [item1, item2, item3] = pane1.items - [item4, item5] = pane2.items + [item1, item2, item3] = pane1.getItems() + [item4, item5] = pane2.getItems() it "moves the item to the given pane at the given index", -> pane1.moveItemToPane(item2, pane2, 1) - expect(pane1.items).toEqual [item1, item3] - expect(pane2.items).toEqual [item4, item2, item5] + expect(pane1.getItems()).toEqual [item1, item3] + expect(pane2.getItems()).toEqual [item4, item2, item5] describe "when the moved item the last item in the source pane", -> beforeEach -> @@ -455,7 +455,7 @@ describe "Pane", -> pane2 = pane1.splitRight() it "destroys the pane's destroyable items", -> - [item1, item2] = pane1.items + [item1, item2] = pane1.getItems() pane1.destroy() expect(item1.isDestroyed()).toBe true expect(item2.isDestroyed()).toBe true @@ -493,12 +493,12 @@ describe "Pane", -> it "can serialize and deserialize the pane and all its items", -> newPane = pane.testSerialization() - expect(newPane.items).toEqual pane.items + expect(newPane.getItems()).toEqual pane.getItems() it "restores the active item on deserialization", -> pane.activateItemAtIndex(1) newPane = pane.testSerialization() - expect(newPane.activeItem).toEqual newPane.items[1] + expect(newPane.getActiveItem()).toEqual newPane.itemAtIndex(1) it "does not include items that cannot be deserialized", -> spyOn(console, 'warn') @@ -506,8 +506,8 @@ describe "Pane", -> pane.activateItem(unserializable) newPane = pane.testSerialization() - expect(newPane.activeItem).toEqual pane.items[0] - expect(newPane.items.length).toBe pane.items.length - 1 + expect(newPane.getActiveItem()).toEqual pane.itemAtIndex(0) + expect(newPane.getItems().length).toBe pane.getItems().length - 1 it "includes the pane's focus state in the serialized state", -> pane.focus() From b8fcbe9451690a64ae1e1e54cc9a7b40ef0e5f17 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Aug 2014 20:54:19 -0600 Subject: [PATCH 003/355] Start adding event subscription methods to pane This branch uses EventKit, an ultra-simple library for implementing events. The object implementing the methods maintains its own emitter object rather than doing a mixin like Emissary encourages. This will make it easier for us to deprecate ::on on the object itself. Unlike emissary, the EventKit Emitter implements a super minimalistic API that only allows one value to be emitted and always returns a Disposable from subscriptions. --- package.json | 2 +- spec/pane-spec.coffee | 29 ++++++++++++++++++++--------- src/pane.coffee | 26 ++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 28bbf5e6c..53078da1a 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.2.2", + "event-kit": "0.0.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", @@ -109,7 +110,6 @@ "welcome": "0.18.0", "whitespace": "0.25.0", "wrap-guide": "0.21.0", - "language-c": "0.28.0", "language-coffee-script": "0.30.0", "language-css": "0.17.0", diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index d6eeb57e0..b525c1c69 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -36,7 +36,7 @@ describe "Pane", -> pane.addItem(item3, 1) expect(pane.getItems()).toEqual [item1, item3, item2] - it "adds the item after the active item ", -> + it "adds the item after the active item if no index is provided", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) [item1, item2, item3] = pane.getItems() pane.activateItem(item2) @@ -47,13 +47,17 @@ describe "Pane", -> it "sets the active item after adding the first item", -> pane = new Pane item = new Item("A") - events = [] - pane.on 'item-added', -> events.push('item-added') - pane.$activeItem.changes.onValue -> events.push('active-item-changed') - pane.addItem(item) expect(pane.getActiveItem()).toBe item - expect(events).toEqual ['item-added', 'active-item-changed'] + + it "invokes ::onDidAddItem() observers", -> + pane = new Pane(items: [new Item("A"), new Item("B")]) + events = [] + pane.onDidAddItem (event) -> events.push(event) + + item = new Item("C") + pane.addItem(item, 1) + expect(events).toEqual [{item, index: 1}] describe "::activateItem(item)", -> pane = null @@ -72,6 +76,12 @@ describe "Pane", -> expect(item in pane.getItems()).toBe true expect(pane.getActiveItem()).toBe item + it "invokes ::onDidChangeActiveItem() observers", -> + observed = [] + pane.onDidChangeActiveItem (item) -> observed.push(item) + pane.activateItem(pane.itemAtIndex(1)) + expect(observed).toEqual [pane.itemAtIndex(1)] + describe "::activateNextItem() and ::activatePreviousItem()", -> it "sets the active item to the next/previous item, looping around at either end", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) @@ -135,10 +145,11 @@ describe "Pane", -> pane.destroyItem(item2) expect(pane.getActiveItem()).toBe item1 - it "emits 'item-removed' with the item, its index, and true indicating the item is being destroyed", -> - pane.on 'item-removed', itemRemovedHandler = jasmine.createSpy("itemRemovedHandler") + it "invokes ::onDidRemoveItem() observers", -> + events = [] + pane.onDidRemoveItem (event) -> events.push(event) pane.destroyItem(item2) - expect(itemRemovedHandler).toHaveBeenCalledWith(item2, 1, true) + expect(events).toEqual [{item: item2, index: 1, destroyed: true}] describe "if the item is modified", -> itemUri = null diff --git a/src/pane.coffee b/src/pane.coffee index 678e2156e..61ad60cc1 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -1,5 +1,6 @@ {find, compact, extend, last} = require 'underscore-plus' {Model, Sequence} = require 'theorist' +{Emitter} = require 'event-kit' Serializable = require 'serializable' PaneAxis = require './pane-axis' Editor = require './editor' @@ -64,6 +65,8 @@ class Pane extends Model constructor: (params) -> super + @emitter = new Emitter + @items = Sequence.fromArray(compact(params?.items ? [])) @activeItem ?= @items[0] @@ -91,6 +94,15 @@ class Pane extends Model # Called by the view layer to construct a view for this model. getViewClass: -> PaneView ?= require './pane-view' + onDidAddItem: (fn) -> + @emitter.on 'did-add-item', fn + + onDidRemoveItem: (fn) -> + @emitter.on 'did-remove-item', fn + + onDidChangeActiveItem: (fn) -> + @emitter.on 'did-change-active-item', fn + isActive: -> @active # Called by the view layer to indicate that the pane has gained focus. @@ -123,6 +135,10 @@ class Pane extends Model getActiveItem: -> @activeItem + setActiveItem: (@activeItem) -> + @emitter.emit 'did-change-active-item', @activeItem + @activeItem + # Public: Returns an {Editor} if the pane item is an {Editor}, or null # otherwise. getActiveEditor: -> @@ -160,7 +176,7 @@ class Pane extends Model activateItem: (item) -> if item? @addItem(item) - @activeItem = item + @setActiveItem(item) # Public: Adds the item to the pane. # @@ -174,6 +190,7 @@ class Pane extends Model @items.splice(index, 0, item) @emit 'item-added', item, index + @emitter.emit 'did-add-item', {item, index} @activeItem ?= item item @@ -191,7 +208,7 @@ class Pane extends Model @addItem(item, index + i) for item, i in items items - removeItem: (item, destroying) -> + removeItem: (item, destroyed) -> index = @items.indexOf(item) return if index is -1 if item is @activeItem @@ -202,8 +219,9 @@ class Pane extends Model else @activatePreviousItem() @items.splice(index, 1) - @emit 'item-removed', item, index, destroying - @container?.itemDestroyed(item) if destroying + @emit 'item-removed', item, index, destroyed + @emitter.emit 'did-remove-item', {item, index, destroyed} + @container?.itemDestroyed(item) if destroyed @destroy() if @items.length is 0 and atom.config.get('core.destroyEmptyPanes') # Public: Moves the given item to the specified index. From 9bd2eec4bc5dddd0a3a24a0ccd45907df2e71536 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 10:08:58 -0600 Subject: [PATCH 004/355] Add Pane::onDidMoveItem() --- spec/pane-spec.coffee | 22 +++++++++++++++------- src/pane.coffee | 4 ++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index b525c1c69..71c9fcc03 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -323,24 +323,32 @@ describe "Pane", -> expect(pane.itemForUri("bogus")).toBeUndefined() describe "::moveItem(item, index)", -> - it "moves the item to the given index and emits an 'item-moved' event with the item and its new index", -> + [pane, item1, item2, item3, item4] = [] + + beforeEach -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")]) [item1, item2, item3, item4] = pane.getItems() - pane.on 'item-moved', itemMovedHandler = jasmine.createSpy("itemMovedHandler") + it "moves the item to the given index and invokes ::onDidMoveItem observers", -> pane.moveItem(item1, 2) expect(pane.getItems()).toEqual [item2, item3, item1, item4] - expect(itemMovedHandler).toHaveBeenCalledWith(item1, 2) - itemMovedHandler.reset() pane.moveItem(item2, 3) expect(pane.getItems()).toEqual [item3, item1, item4, item2] - expect(itemMovedHandler).toHaveBeenCalledWith(item2, 3) - itemMovedHandler.reset() pane.moveItem(item2, 1) expect(pane.getItems()).toEqual [item3, item2, item1, item4] - expect(itemMovedHandler).toHaveBeenCalledWith(item2, 1) + + it "invokes ::onDidMoveItem() observers", -> + events = [] + pane.onDidMoveItem (event) -> events.push(event) + + pane.moveItem(item1, 2) + pane.moveItem(item2, 3) + expect(events).toEqual [ + {item: item1, oldIndex: 0, newIndex: 2} + {item: item2, oldIndex: 0, newIndex: 3} + ] describe "::moveItemToPane(item, pane, index)", -> [container, pane1, pane2] = [] diff --git a/src/pane.coffee b/src/pane.coffee index 61ad60cc1..23f188d25 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -100,6 +100,9 @@ class Pane extends Model onDidRemoveItem: (fn) -> @emitter.on 'did-remove-item', fn + onDidMoveItem: (fn) -> + @emitter.on 'did-move-item', fn + onDidChangeActiveItem: (fn) -> @emitter.on 'did-change-active-item', fn @@ -230,6 +233,7 @@ class Pane extends Model @items.splice(oldIndex, 1) @items.splice(newIndex, 0, item) @emit 'item-moved', item, newIndex + @emitter.emit 'did-move-item', {item, oldIndex, newIndex} # Public: Moves the given item to the given index at another pane. moveItemToPane: (item, pane, index) -> From 548018e9b29ea7fb93ae68efb340cf66b35c5bb0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 10:12:34 -0600 Subject: [PATCH 005/355] Add spec for onDidRemoveItem observers when moving items to other panes --- spec/pane-spec.coffee | 7 +++++++ src/pane.coffee | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 71c9fcc03..ab9ba7661 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -366,6 +366,13 @@ describe "Pane", -> expect(pane1.getItems()).toEqual [item1, item3] expect(pane2.getItems()).toEqual [item4, item2, item5] + it "invokes ::onDidRemoveItem() observers", -> + events = [] + pane1.onDidRemoveItem (event) -> events.push(event) + pane1.moveItemToPane(item2, pane2, 1) + + expect(events).toEqual [{item: item2, index: 1, destroyed: false}] + describe "when the moved item the last item in the source pane", -> beforeEach -> item5.destroy() diff --git a/src/pane.coffee b/src/pane.coffee index 23f188d25..fc8fee05e 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -211,7 +211,7 @@ class Pane extends Model @addItem(item, index + i) for item, i in items items - removeItem: (item, destroyed) -> + removeItem: (item, destroyed=false) -> index = @items.indexOf(item) return if index is -1 if item is @activeItem From 2d58d9c8b5d5fa0bb565bf949a9cdbcbb080224b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 10:22:14 -0600 Subject: [PATCH 006/355] Add Pane::onDidActivate --- spec/pane-spec.coffee | 23 +++++++++++++++++++++++ src/pane-container.coffee | 2 ++ src/pane.coffee | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index ab9ba7661..2fb011124 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -28,6 +28,29 @@ describe "Pane", -> expect(pane.getItems().length).toBe 2 expect(pane.getActiveItem()).toBe pane.itemAtIndex(0) + describe "::activate()", -> + [container, pane1, pane2] = [] + + beforeEach -> + container = new PaneContainer(root: new Pane) + container.getRoot().splitRight() + [pane1, pane2] = container.getPanes() + + it "changes the active pane on the container", -> + expect(container.getActivePane()).toBe pane2 + pane1.activate() + expect(container.getActivePane()).toBe pane1 + pane2.activate() + expect(container.getActivePane()).toBe pane2 + + it "invokes ::onDidActivate() observers", -> + eventCount = 0 + pane1.onDidActivate -> eventCount++ + pane1.activate() + pane1.activate() + pane2.activate() + expect(eventCount).toBe 2 + describe "::addItem(item, index)", -> it "adds the item at the given index", -> pane = new Pane(items: [new Item("A"), new Item("B")]) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 07083263a..2a3271eb5 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -36,6 +36,8 @@ class PaneContainer extends Model root: @root?.serialize() activePaneId: @activePane.id + getRoot: -> @root + replaceChild: (oldChild, newChild) -> throw new Error("Replacing non-existent child") if oldChild isnt @root @root = newChild diff --git a/src/pane.coffee b/src/pane.coffee index fc8fee05e..e81d2f7d1 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -94,6 +94,9 @@ class Pane extends Model # Called by the view layer to construct a view for this model. getViewClass: -> PaneView ?= require './pane-view' + onDidActivate: (fn) -> + @emitter.on 'did-activate', fn + onDidAddItem: (fn) -> @emitter.on 'did-add-item', fn @@ -123,6 +126,7 @@ class Pane extends Model activate: -> @container?.activePane = this @emit 'activated' + @emitter.emit 'did-activate' getPanes: -> [this] From 8225f759bf4fb21b81a9a68ca66fe902e38fa07f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 10:34:57 -0600 Subject: [PATCH 007/355] Add Pane::onWillDestroyItem() --- spec/pane-spec.coffee | 26 +++++++++++++++++++------- src/pane.coffee | 7 ++++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 2fb011124..dcd5eb7d8 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -144,14 +144,32 @@ describe "Pane", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) [item1, item2, item3] = pane.getItems() - it "removes the item from the items list", -> + it "removes the item from the items list and destroyes it", -> expect(pane.getActiveItem()).toBe item1 pane.destroyItem(item2) expect(item2 in pane.getItems()).toBe false + expect(item2.isDestroyed()).toBe true expect(pane.getActiveItem()).toBe item1 pane.destroyItem(item1) expect(item1 in pane.getItems()).toBe false + expect(item1.isDestroyed()).toBe true + + it "invokes ::onWillDestroyItem() observers before destroying the item", -> + events = [] + pane.onWillDestroyItem (event) -> + expect(item2.isDestroyed()).toBe false + events.push(event) + + pane.destroyItem(item2) + expect(item2.isDestroyed()).toBe true + expect(events).toEqual [{item: item2, index: 1}] + + it "invokes ::onDidRemoveItem() observers", -> + events = [] + pane.onDidRemoveItem (event) -> events.push(event) + pane.destroyItem(item2) + expect(events).toEqual [{item: item2, index: 1, destroyed: true}] describe "when the destroyed item is the active item and is the first item", -> it "activates the next item", -> @@ -168,12 +186,6 @@ describe "Pane", -> pane.destroyItem(item2) expect(pane.getActiveItem()).toBe item1 - it "invokes ::onDidRemoveItem() observers", -> - events = [] - pane.onDidRemoveItem (event) -> events.push(event) - pane.destroyItem(item2) - expect(events).toEqual [{item: item2, index: 1, destroyed: true}] - describe "if the item is modified", -> itemUri = null diff --git a/src/pane.coffee b/src/pane.coffee index e81d2f7d1..45d49575e 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -109,6 +109,9 @@ class Pane extends Model onDidChangeActiveItem: (fn) -> @emitter.on 'did-change-active-item', fn + onWillDestroyItem: (fn) -> + @emitter.on 'will-destroy-item', fn + isActive: -> @active # Called by the view layer to indicate that the pane has gained focus. @@ -252,8 +255,10 @@ class Pane extends Model # Public: Destroys the given item. If it is the active item, activate the next # one. If this is the last item, also destroys the pane. destroyItem: (item) -> - if item? + index = @items.indexOf(item) + if index isnt -1 @emit 'before-item-destroyed', item + @emitter.emit 'will-destroy-item', {item, index} if @promptToSaveItem(item) @removeItem(item, true) item.destroy?() From 2b63f8a4eea93206d2dc247b659e55472cce6465 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 10:56:56 -0600 Subject: [PATCH 008/355] Add PaneContainer::onDidChangeActivePane --- spec/pane-spec.coffee | 10 ++++++++++ src/pane-container.coffee | 15 ++++++++++++++- src/pane.coffee | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index dcd5eb7d8..b61b0a76f 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -43,6 +43,16 @@ describe "Pane", -> pane2.activate() expect(container.getActivePane()).toBe pane2 + it "invokes ::onDidChangeActivePane observers on the container", -> + observed = [] + container.onDidChangeActivePane (activePane) -> observed.push(activePane) + + pane1.activate() + pane1.activate() + pane2.activate() + pane1.activate() + expect(observed).toEqual [pane1, pane2, pane1] + it "invokes ::onDidActivate() observers", -> eventCount = 0 pane1.onDidActivate -> eventCount++ diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 2a3271eb5..7161d172f 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -1,5 +1,6 @@ {find} = require 'underscore-plus' {Model} = require 'theorist' +{Emitter} = require 'event-kit' Serializable = require 'serializable' Pane = require './pane' @@ -23,6 +24,9 @@ class PaneContainer extends Model constructor: (params) -> super + + @emitter = new Emitter + @subscribe @$root, @onRootChanged @destroyEmptyPanes() if params?.destroyEmptyPanes @@ -36,6 +40,9 @@ class PaneContainer extends Model root: @root?.serialize() activePaneId: @activePane.id + onDidChangeActivePane: (fn) -> + @emitter.on 'did-change-active-pane', fn + getRoot: -> @root replaceChild: (oldChild, newChild) -> @@ -48,6 +55,12 @@ class PaneContainer extends Model getActivePane: -> @activePane + setActivePane: (pane) -> + if pane isnt @activePane + @activePane = pane + @emitter.emit 'did-change-active-pane', @activePane + @activePane + paneForUri: (uri) -> find @getPanes(), (pane) -> pane.itemForUri(uri)? @@ -80,7 +93,7 @@ class PaneContainer extends Model @previousRoot = root unless root? - @activePane = null + @setActivePane(null) return root.parent = this diff --git a/src/pane.coffee b/src/pane.coffee index 45d49575e..4e681cbe1 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -127,7 +127,7 @@ class Pane extends Model # Public: Makes this pane the *active* pane, causing it to gain focus # immediately. activate: -> - @container?.activePane = this + @container?.setActivePane(this) @emit 'activated' @emitter.emit 'did-activate' From 44d70aaa5b6ae929248e404c787d3627682e8448 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 10:57:09 -0600 Subject: [PATCH 009/355] Add Pane::onDidChangeActive() --- spec/pane-spec.coffee | 7 +++++++ src/pane.coffee | 3 +++ 2 files changed, 10 insertions(+) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index b61b0a76f..980490d81 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -53,6 +53,13 @@ describe "Pane", -> pane1.activate() expect(observed).toEqual [pane1, pane2, pane1] + it "invokes ::onDidChangeActive observers on the relevant panes", -> + observed = [] + pane1.onDidChangeActive (active) -> observed.push(active) + pane1.activate() + pane2.activate() + expect(observed).toEqual [true, false] + it "invokes ::onDidActivate() observers", -> eventCount = 0 pane1.onDidActivate -> eventCount++ diff --git a/src/pane.coffee b/src/pane.coffee index 4e681cbe1..ccc114407 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -97,6 +97,9 @@ class Pane extends Model onDidActivate: (fn) -> @emitter.on 'did-activate', fn + onDidChangeActive: (fn) -> + @container.onDidChangeActivePane (activePane) => fn(this is activePane) + onDidAddItem: (fn) -> @emitter.on 'did-add-item', fn From b6c669a292791180127a65af4811e3b147b6dc92 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:06:53 -0600 Subject: [PATCH 010/355] Subscribe with new event methods in PaneView --- src/pane-view.coffee | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index 0d641582e..8ecaa4ffe 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -1,6 +1,7 @@ {$, View} = require './space-pen-extensions' Delegator = require 'delegato' {deprecate} = require 'grim' +{CompositeDisposable} = require 'event-kit' PropertyAccessors = require 'property-accessors' Pane = require './pane' @@ -33,6 +34,8 @@ class PaneView extends View previousActiveItem: null initialize: (args...) -> + @disposables = new CompositeDisposable + if args[0] instanceof Pane @model = args[0] else @@ -44,13 +47,13 @@ class PaneView extends View @handleEvents() handleEvents: -> - @subscribe @model.$activeItem, @onActiveItemChanged - @subscribe @model, 'item-added', @onItemAdded - @subscribe @model, 'item-removed', @onItemRemoved - @subscribe @model, 'item-moved', @onItemMoved - @subscribe @model, 'before-item-destroyed', @onBeforeItemDestroyed - @subscribe @model, 'activated', @onActivated - @subscribe @model.$active, @onActiveStatusChanged + @disposables.add @model.onDidChangeActiveItem(@onActiveItemChanged) + @disposables.add @model.onDidAddItem(@onItemAdded) + @disposables.add @model.onDidRemoveItem(@onItemRemoved) + @disposables.add @model.onDidMoveItem(@onItemMoved) + @disposables.add @model.onWillDestroyItem(@onBeforeItemDestroyed) + @disposables.add @model.onDidActivate(@onActivated) + @disposables.add @model.onDidChangeActive(@onActiveStatusChanged) @subscribe this, 'focusin', => @model.focus() @subscribe this, 'focusout', => @model.blur() @@ -219,6 +222,7 @@ class PaneView extends View @closest('.panes').view() beforeRemove: -> + @disposables.dispose() @model.destroy() unless @model.isDestroyed() remove: (selector, keepData) -> From e7a7e86deaad5b8e6333305460115479e6d496e6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:44:55 -0600 Subject: [PATCH 011/355] Add Pane::observeActive and ::observeActiveItem These have behavior semantics, invoking the observer immediately with the current value of the observed property. --- src/pane-view.coffee | 4 ++-- src/pane.coffee | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index 8ecaa4ffe..f235ba13c 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -47,13 +47,13 @@ class PaneView extends View @handleEvents() handleEvents: -> - @disposables.add @model.onDidChangeActiveItem(@onActiveItemChanged) + @disposables.add @model.observeActiveItem(@onActiveItemChanged) @disposables.add @model.onDidAddItem(@onItemAdded) @disposables.add @model.onDidRemoveItem(@onItemRemoved) @disposables.add @model.onDidMoveItem(@onItemMoved) @disposables.add @model.onWillDestroyItem(@onBeforeItemDestroyed) @disposables.add @model.onDidActivate(@onActivated) - @disposables.add @model.onDidChangeActive(@onActiveStatusChanged) + @disposables.add @model.observeActive(@onActiveStatusChanged) @subscribe this, 'focusin', => @model.focus() @subscribe this, 'focusout', => @model.blur() diff --git a/src/pane.coffee b/src/pane.coffee index ccc114407..33846fd8c 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -100,6 +100,10 @@ class Pane extends Model onDidChangeActive: (fn) -> @container.onDidChangeActivePane (activePane) => fn(this is activePane) + observeActive: (fn) -> + fn(@isActive()) + @onDidChangeActive(fn) + onDidAddItem: (fn) -> @emitter.on 'did-add-item', fn @@ -112,6 +116,10 @@ class Pane extends Model onDidChangeActiveItem: (fn) -> @emitter.on 'did-change-active-item', fn + observeActiveItem: (fn) -> + fn(@getActiveItem()) + @onDidChangeActiveItem(fn) + onWillDestroyItem: (fn) -> @emitter.on 'will-destroy-item', fn From 87cdc1a45d1bc0ac000fb36d004d1b137bbc0b40 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:56:32 -0600 Subject: [PATCH 012/355] =?UTF-8?q?Don=E2=80=99t=20invoke=20::onDidChangeA?= =?UTF-8?q?ctivePane=20events=20unless=20it=20really=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pane-container.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 7161d172f..63e6a5a9a 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -55,9 +55,9 @@ class PaneContainer extends Model getActivePane: -> @activePane - setActivePane: (pane) -> - if pane isnt @activePane - @activePane = pane + setActivePane: (activePane) -> + if activePane isnt @activePane + @activePane = activePane @emitter.emit 'did-change-active-pane', @activePane @activePane From 99d70b4a4e5343a1ca08f35cd5a56482c8183618 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:56:58 -0600 Subject: [PATCH 013/355] =?UTF-8?q?Don=E2=80=99t=20emit=20::onDidChangeAct?= =?UTF-8?q?iveItem=20events=20unless=20it=20really=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pane.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 33846fd8c..0202f3249 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -156,8 +156,10 @@ class Pane extends Model getActiveItem: -> @activeItem - setActiveItem: (@activeItem) -> - @emitter.emit 'did-change-active-item', @activeItem + setActiveItem: (activeItem) -> + unless activeItem is @activeItem + @activeItem = activeItem + @emitter.emit 'did-change-active-item', @activeItem @activeItem # Public: Returns an {Editor} if the pane item is an {Editor}, or null From 40d93cd0cf0e61f77b9b408f3a0358125e57905a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:57:25 -0600 Subject: [PATCH 014/355] Use Pane::setActiveItem internally so observers are invoked --- src/pane.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 0202f3249..612a83e78 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -68,7 +68,7 @@ class Pane extends Model @emitter = new Emitter @items = Sequence.fromArray(compact(params?.items ? [])) - @activeItem ?= @items[0] + @setActiveItem(@items[0]) unless @getActiveItem()? @subscribe @items.onEach (item) => if typeof item.on is 'function' @@ -214,7 +214,7 @@ class Pane extends Model @items.splice(index, 0, item) @emit 'item-added', item, index @emitter.emit 'did-add-item', {item, index} - @activeItem ?= item + @setActiveItem(item) unless @getActiveItem()? item # Public: Adds the given items to the pane. @@ -236,7 +236,7 @@ class Pane extends Model return if index is -1 if item is @activeItem if @items.length is 1 - @activeItem = undefined + @setActiveItem(undefined) else if index is 0 @activateNextItem() else From 475dc6074ce24bfa6784b1f7681d75075b5f52b5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:57:29 -0600 Subject: [PATCH 015/355] :lipstick: --- src/pane.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 612a83e78..43b703582 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -153,8 +153,7 @@ class Pane extends Model # Public: Get the active pane item in this pane. # # Returns a pane item. - getActiveItem: -> - @activeItem + getActiveItem: -> @activeItem setActiveItem: (activeItem) -> unless activeItem is @activeItem From b9feed8eb47cc46a6043d7e366821ea674b03729 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:57:48 -0600 Subject: [PATCH 016/355] Handle objects in subscriptions instead of multiple args --- src/pane-view.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index f235ba13c..bb5b11554 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -166,7 +166,7 @@ class PaneView extends View onItemAdded: (item, index) => @trigger 'pane:item-added', [item, index] - onItemRemoved: (item, index, destroyed) => + onItemRemoved: ({item, index, destroyed}) => if item instanceof $ viewToRemove = item else if viewToRemove = @viewsByItem.get(item) @@ -180,7 +180,7 @@ class PaneView extends View @trigger 'pane:item-removed', [item, index] - onItemMoved: (item, newIndex) => + onItemMoved: ({item, newIndex}) => @trigger 'pane:item-moved', [item, newIndex] onBeforeItemDestroyed: (item) => From 1d365db9df98b13241188626a68f732074a46d1b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 11:59:53 -0600 Subject: [PATCH 017/355] Use getActiveItem getter in pane-view-spec --- spec/pane-view-spec.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee index 9f73884b5..4862e639b 100644 --- a/spec/pane-view-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -37,7 +37,7 @@ describe "PaneView", -> describe "when the active pane item changes", -> it "hides all item views except the active one", -> - expect(pane.activeItem).toBe view1 + expect(pane.getActiveItem()).toBe view1 expect(view1.css('display')).not.toBe 'none' pane.activateItem(view2) @@ -48,7 +48,7 @@ describe "PaneView", -> itemChangedHandler = jasmine.createSpy("itemChangedHandler") container.on 'pane:active-item-changed', itemChangedHandler - expect(pane.activeItem).toBe view1 + expect(pane.getActiveItem()).toBe view1 paneModel.activateItem(view2) paneModel.activateItem(view2) @@ -149,7 +149,7 @@ describe "PaneView", -> activeItemTitleChangedHandler = jasmine.createSpy("activeItemTitleChangedHandler") pane.on 'pane:active-item-title-changed', activeItemTitleChangedHandler - expect(pane.activeItem).toBe view1 + expect(pane.getActiveItem()).toBe view1 view2.trigger 'title-changed' expect(activeItemTitleChangedHandler).not.toHaveBeenCalled() @@ -246,7 +246,7 @@ describe "PaneView", -> it "transfers focus to the active view", -> focusHandler = jasmine.createSpy("focusHandler") - pane.activeItem.on 'focus', focusHandler + pane.getActiveItem().on 'focus', focusHandler pane.focus() expect(focusHandler).toHaveBeenCalled() From 4f826a70f831bd80e1de978e5d52c1c9733d9871 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 12:07:16 -0600 Subject: [PATCH 018/355] Use Array instead of Sequence for Pane::items --- src/pane.coffee | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 43b703582..8d3226b41 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -1,5 +1,5 @@ {find, compact, extend, last} = require 'underscore-plus' -{Model, Sequence} = require 'theorist' +{Model} = require 'theorist' {Emitter} = require 'event-kit' Serializable = require 'serializable' PaneAxis = require './pane-axis' @@ -66,17 +66,11 @@ class Pane extends Model super @emitter = new Emitter + @items = [] - @items = Sequence.fromArray(compact(params?.items ? [])) + @addItems(compact(params?.items ? [])) @setActiveItem(@items[0]) unless @getActiveItem()? - @subscribe @items.onEach (item) => - if typeof item.on is 'function' - @subscribe item, 'destroyed', => @removeItem(item, true) - - @subscribe @items.onRemoval (item, index) => - @unsubscribe item if typeof item.on is 'function' - # Called by the Serializable mixin during serialization. serializeParams: -> id: @id @@ -210,6 +204,9 @@ class Pane extends Model addItem: (item, index=@getActiveItemIndex() + 1) -> return if item in @items + if typeof item.on is 'function' + @subscribe item, 'destroyed', => @removeItem(item, true) + @items.splice(index, 0, item) @emit 'item-added', item, index @emitter.emit 'did-add-item', {item, index} @@ -233,6 +230,10 @@ class Pane extends Model removeItem: (item, destroyed=false) -> index = @items.indexOf(item) return if index is -1 + + if typeof item.on is 'function' + @unsubscribe item + if item is @activeItem if @items.length is 1 @setActiveItem(undefined) From f161f5352ef4e0636f9dd1e6d148ab2702e2aa32 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 15:16:39 -0600 Subject: [PATCH 019/355] =?UTF-8?q?Don=E2=80=99t=20rely=20on=20Sequences?= =?UTF-8?q?=20to=20reparent=20the=20last=20child?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pane-axis.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 39657fcf7..f974c970e 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -20,9 +20,6 @@ class PaneAxis extends Model @subscribe @children.onRemoval (child) => @unsubscribe(child) - @when @children.$length.becomesLessThan(2), 'reparentLastChild' - @when @children.$length.becomesLessThan(1), 'destroy' - deserializeParams: (params) -> {container} = params params.children = params.children.map (childState) -> atom.deserializers.deserialize(childState, {container}) @@ -48,6 +45,8 @@ class PaneAxis extends Model index = @children.indexOf(child) throw new Error("Removing non-existent child") if index is -1 @children.splice(index, 1) + @reparentLastChild() if @children.length < 2 + replaceChild: (oldChild, newChild) -> index = @children.indexOf(oldChild) @@ -64,3 +63,4 @@ class PaneAxis extends Model reparentLastChild: -> @parent.replaceChild(this, @children[0]) + @destroy() From a9294aebc3b1ceec2be05b030f8768503c520654 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 15:25:52 -0600 Subject: [PATCH 020/355] =?UTF-8?q?Don=E2=80=99t=20use=20Sequence=20in=20P?= =?UTF-8?q?aneAxis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pane-axis.coffee | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index f974c970e..12b335519 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -1,4 +1,4 @@ -{Model, Sequence} = require 'theorist' +{Model} = require 'theorist' {flatten} = require 'underscore-plus' Serializable = require 'serializable' @@ -11,14 +11,9 @@ class PaneAxis extends Model Serializable.includeInto(this) constructor: ({@container, @orientation, children}) -> - @children = Sequence.fromArray(children ? []) - - @subscribe @children.onEach (child) => - child.parent = this - child.container = @container - @subscribe child, 'destroyed', => @removeChild(child) - - @subscribe @children.onRemoval (child) => @unsubscribe(child) + @children = [] + if children? + @addChild(child) for child in children deserializeParams: (params) -> {container} = params @@ -40,27 +35,40 @@ class PaneAxis extends Model addChild: (child, index=@children.length) -> @children.splice(index, 0, child) + @childAdded(child) removeChild: (child) -> index = @children.indexOf(child) throw new Error("Removing non-existent child") if index is -1 @children.splice(index, 1) + @childRemoved(child) @reparentLastChild() if @children.length < 2 - replaceChild: (oldChild, newChild) -> index = @children.indexOf(oldChild) throw new Error("Replacing non-existent child") if index is -1 @children.splice(index, 1, newChild) + @childRemoved(oldChild) + @childAdded(newChild) insertChildBefore: (currentChild, newChild) -> index = @children.indexOf(currentChild) @children.splice(index, 0, newChild) + @childAdded(newChild) insertChildAfter: (currentChild, newChild) -> index = @children.indexOf(currentChild) @children.splice(index + 1, 0, newChild) + @childAdded(newChild) reparentLastChild: -> @parent.replaceChild(this, @children[0]) @destroy() + + childAdded: (child) -> + child.parent = this + child.container = @container + @subscribe child, 'destroyed', => @removeChild(child) + + childRemoved: (child) -> + @unsubscribe child From 9979ae4b09cc1a10dcdd7fc0d879d0e9e01e9a05 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 16:17:53 -0600 Subject: [PATCH 021/355] Add child event methods to PaneAxis This eliminates our reliance on the Sequence object for informing us of changes --- package.json | 2 +- src/pane-axis-view.coffee | 23 +++++++++++------ src/pane-axis.coffee | 52 +++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 53078da1a..d6118f789 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "coffee-script": "1.7.0", "coffeestack": "0.7.0", "delegato": "^1", - "emissary": "^1.2.2", + "emissary": "^1.3.0", "event-kit": "0.0.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", diff --git a/src/pane-axis-view.coffee b/src/pane-axis-view.coffee index 3039600c0..0018ee6b1 100644 --- a/src/pane-axis-view.coffee +++ b/src/pane-axis-view.coffee @@ -1,11 +1,17 @@ +{CompositeDisposable} = require 'event-kit' {View} = require './space-pen-extensions' PaneView = null module.exports = class PaneAxisView extends View initialize: (@model) -> - @onChildAdded(child) for child in @model.children - @subscribe @model.children, 'changed', @onChildrenChanged + @subscriptions = new CompositeDisposable + + @onChildAdded({child, index}) for child, index in @model.getChildren() + + @subscriptions.add @model.onDidAddChild(@onChildAdded) + @subscriptions.add @model.onDidRemoveChild(@onChildRemoved) + @subscriptions.add @model.onDidReplaceChild(@onChildReplaced) afterAttach: -> @container = @closest('.panes').view() @@ -14,19 +20,22 @@ class PaneAxisView extends View viewClass = model.getViewClass() model._view ?= new viewClass(model) - onChildrenChanged: ({index, removedValues, insertedValues}) => + onChildReplaced: ({index, oldChild, newChild}) => focusedElement = document.activeElement if @hasFocus() - @onChildRemoved(child, index) for child in removedValues - @onChildAdded(child, index + i) for child, i in insertedValues + @onChildRemoved({child: oldChild, index}) + @onChildAdded({child: newChild, index}) focusedElement?.focus() if document.activeElement is document.body - onChildAdded: (child, index) => + onChildAdded: ({child, index}) => view = @viewForModel(child) @insertAt(index, view) - onChildRemoved: (child) => + onChildRemoved: ({child}) => view = @viewForModel(child) view.detach() PaneView ?= require './pane-view' if view instanceof PaneView and view.model.isDestroyed() @container?.trigger 'pane:removed', [view] + + beforeRemove: -> + @subscriptions.dispose() diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 12b335519..ffef40275 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -1,4 +1,5 @@ {Model} = require 'theorist' +{Emitter} = require 'event-kit' {flatten} = require 'underscore-plus' Serializable = require 'serializable' @@ -11,6 +12,7 @@ class PaneAxis extends Model Serializable.includeInto(this) constructor: ({@container, @orientation, children}) -> + @emitter = new Emitter @children = [] if children? @addChild(child) for child in children @@ -30,45 +32,53 @@ class PaneAxis extends Model else PaneRowView ?= require './pane-row-view' + getChildren: -> @children.slice() + getPanes: -> flatten(@children.map (child) -> child.getPanes()) - addChild: (child, index=@children.length) -> - @children.splice(index, 0, child) - @childAdded(child) + onDidAddChild: (fn) -> + @emitter.on 'did-add-child', fn - removeChild: (child) -> + onDidRemoveChild: (fn) -> + @emitter.on 'did-remove-child', fn + + onDidReplaceChild: (fn) -> + @emitter.on 'did-replace-child', fn + + addChild: (child, index=@children.length) -> + child.parent = this + child.container = @container + @subscribe child, 'destroyed', => @removeChild(child) + @children.splice(index, 0, child) + @emitter.emit 'did-add-child', {child, index} + + removeChild: (child, replacing=false) -> index = @children.indexOf(child) throw new Error("Removing non-existent child") if index is -1 + @unsubscribe child @children.splice(index, 1) - @childRemoved(child) - @reparentLastChild() if @children.length < 2 + @emitter.emit 'did-remove-child', {child, index} + @reparentLastChild() if not replacing and @children.length < 2 replaceChild: (oldChild, newChild) -> + @unsubscribe oldChild + newChild.parent = this + newChild.container = @container + @subscribe newChild, 'destroyed', => @removeChild(newChild) + index = @children.indexOf(oldChild) - throw new Error("Replacing non-existent child") if index is -1 @children.splice(index, 1, newChild) - @childRemoved(oldChild) - @childAdded(newChild) + @emitter.emit 'did-replace-child', {oldChild, newChild, index} insertChildBefore: (currentChild, newChild) -> index = @children.indexOf(currentChild) - @children.splice(index, 0, newChild) - @childAdded(newChild) + @addChild(newChild, index) insertChildAfter: (currentChild, newChild) -> index = @children.indexOf(currentChild) - @children.splice(index + 1, 0, newChild) - @childAdded(newChild) + @addChild(newChild, index + 1) reparentLastChild: -> @parent.replaceChild(this, @children[0]) @destroy() - - childAdded: (child) -> - child.parent = this - child.container = @container - @subscribe child, 'destroyed', => @removeChild(child) - - childRemoved: (child) -> - @unsubscribe child From c25ab0db43e7118eaf8b6c34f5222690c9cd75e2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 16:18:26 -0600 Subject: [PATCH 022/355] Rename ::disposables to ::subscriptions in PaneView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that emissary’s Subscriber no longer conflicts with the name --- src/pane-view.coffee | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index bb5b11554..317fca95b 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -34,7 +34,7 @@ class PaneView extends View previousActiveItem: null initialize: (args...) -> - @disposables = new CompositeDisposable + @subscriptions = new CompositeDisposable if args[0] instanceof Pane @model = args[0] @@ -47,13 +47,13 @@ class PaneView extends View @handleEvents() handleEvents: -> - @disposables.add @model.observeActiveItem(@onActiveItemChanged) - @disposables.add @model.onDidAddItem(@onItemAdded) - @disposables.add @model.onDidRemoveItem(@onItemRemoved) - @disposables.add @model.onDidMoveItem(@onItemMoved) - @disposables.add @model.onWillDestroyItem(@onBeforeItemDestroyed) - @disposables.add @model.onDidActivate(@onActivated) - @disposables.add @model.observeActive(@onActiveStatusChanged) + @subscriptions.add @model.observeActiveItem(@onActiveItemChanged) + @subscriptions.add @model.onDidAddItem(@onItemAdded) + @subscriptions.add @model.onDidRemoveItem(@onItemRemoved) + @subscriptions.add @model.onDidMoveItem(@onItemMoved) + @subscriptions.add @model.onWillDestroyItem(@onBeforeItemDestroyed) + @subscriptions.add @model.onDidActivate(@onActivated) + @subscriptions.add @model.observeActive(@onActiveStatusChanged) @subscribe this, 'focusin', => @model.focus() @subscribe this, 'focusout', => @model.blur() @@ -222,7 +222,7 @@ class PaneView extends View @closest('.panes').view() beforeRemove: -> - @disposables.dispose() + @subscriptions.dispose() @model.destroy() unless @model.isDestroyed() remove: (selector, keepData) -> From 67c3a41a60aebe44d8dbc0ef6deaa0657de3c2e9 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 16:30:57 -0600 Subject: [PATCH 023/355] Upgrade event-kit to fix bug and get CompositeDisposable::remove --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6118f789..b26a7900d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.0", - "event-kit": "0.0.0", + "event-kit": "0.1.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", From da63c6bab2e653451c0f9119c1a3bcf7a84ad416 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 17:10:50 -0600 Subject: [PATCH 024/355] Add ::onDidDestroy to Pane and PaneAxis --- package.json | 2 +- src/pane-axis.coffee | 34 +++++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b26a7900d..7e5767ef2 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.0", - "event-kit": "0.1.0", + "event-kit": "0.2.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index ffef40275..0aa8c743a 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -1,5 +1,5 @@ {Model} = require 'theorist' -{Emitter} = require 'event-kit' +{Emitter, CompositeDisposable} = require 'event-kit' {flatten} = require 'underscore-plus' Serializable = require 'serializable' @@ -13,6 +13,8 @@ class PaneAxis extends Model constructor: ({@container, @orientation, children}) -> @emitter = new Emitter + @subscriptionsByChild = new WeakMap + @subscriptions = new CompositeDisposable @children = [] if children? @addChild(child) for child in children @@ -46,26 +48,34 @@ class PaneAxis extends Model onDidReplaceChild: (fn) -> @emitter.on 'did-replace-child', fn + onDidDestroy: (fn) -> + @emitter.on 'did-destroy' + addChild: (child, index=@children.length) -> child.parent = this child.container = @container - @subscribe child, 'destroyed', => @removeChild(child) + + @subscribeToChild(child) + @children.splice(index, 0, child) @emitter.emit 'did-add-child', {child, index} removeChild: (child, replacing=false) -> index = @children.indexOf(child) throw new Error("Removing non-existent child") if index is -1 - @unsubscribe child + + @unsubscribeFromChild(child) + @children.splice(index, 1) @emitter.emit 'did-remove-child', {child, index} @reparentLastChild() if not replacing and @children.length < 2 replaceChild: (oldChild, newChild) -> - @unsubscribe oldChild + @unsubscribeFromChild(oldChild) + @subscribeToChild(newChild) + newChild.parent = this newChild.container = @container - @subscribe newChild, 'destroyed', => @removeChild(newChild) index = @children.indexOf(oldChild) @children.splice(index, 1, newChild) @@ -82,3 +92,17 @@ class PaneAxis extends Model reparentLastChild: -> @parent.replaceChild(this, @children[0]) @destroy() + + subscribeToChild: (child) -> + subscription = child.onDidDestroy => @removeChild(child) + @subscriptionsByChild.set(child, subscription) + @subscriptions.add(child) + + unsubscribeFromChild: (child) -> + subscription = @subscriptionsByChild.get(child) + @subscriptions.remove(child) + subscription.dispose() + + destroyed: -> + @emitter.emit 'did-destroy' + @emitter.dispose() From 9487609f0cc95b523403cc9374e42eb3a2e79c63 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 17:26:20 -0600 Subject: [PATCH 025/355] :lipstick: pane-container-spec --- spec/pane-container-spec.coffee | 44 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index df9921e69..ad7f80b6a 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -27,42 +27,42 @@ describe "PaneContainer", -> it "preserves the active pane across serialization, independent of focus", -> pane3A.activate() - expect(containerA.activePane).toBe pane3A + expect(containerA.getActivePane()).toBe pane3A containerB = containerA.testSerialization() [pane1B, pane2B, pane3B] = containerB.getPanes() - expect(containerB.activePane).toBe pane3B + expect(containerB.getActivePane()).toBe pane3B - describe "::activePane", -> + it "does not allow the root pane to be destroyed", -> + pane1.destroy() + expect(container.getRoot()).toBe pane1 + expect(pane1.isDestroyed()).toBe false + + describe "::getActivePane()", -> [container, pane1, pane2] = [] beforeEach -> container = new PaneContainer - pane1 = container.root + pane1 = container.getRoot() - it "references the first pane if no pane has been made active", -> - expect(container.activePane).toBe pane1 - expect(pane1.active).toBe true + it "returns the first pane if no pane has been made active", -> + expect(container.getActivePane()).toBe pane1 + expect(pane1.isActive()).toBe true - it "references the most pane on which ::activate was most recently called", -> + it "returns the most pane on which ::activate() was most recently called", -> pane2 = pane1.splitRight() pane2.activate() - expect(container.activePane).toBe pane2 - expect(pane1.active).toBe false - expect(pane2.active).toBe true + expect(container.getActivePane()).toBe pane2 + expect(pane1.isActive()).toBe false + expect(pane2.isActive()).toBe true pane1.activate() - expect(container.activePane).toBe pane1 - expect(pane1.active).toBe true - expect(pane2.active).toBe false + expect(container.getActivePane()).toBe pane1 + expect(pane1.isActive()).toBe true + expect(pane2.isActive()).toBe false - it "is reassigned to the next pane if the current active pane is destroyed", -> + it "returns the next pane if the current active pane is destroyed", -> pane2 = pane1.splitRight() pane2.activate() pane2.destroy() - expect(container.activePane).toBe pane1 - expect(pane1.active).toBe true - - it "does not allow the root pane to be destroyed", -> - pane1.destroy() - expect(container.root).toBe pane1 - expect(pane1.isDestroyed()).toBe false + expect(container.getActivePane()).toBe pane1 + expect(pane1.isActive()).toBe true From b89202f82c220ce9ee5042b19de36f546bf18e3c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 17:51:36 -0600 Subject: [PATCH 026/355] Dispose of PaneAxis subscriptions when destroyed --- src/pane-axis.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 0aa8c743a..1cc1dea51 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -104,5 +104,6 @@ class PaneAxis extends Model subscription.dispose() destroyed: -> + @subscriptions.dispose() @emitter.emit 'did-destroy' @emitter.dispose() From 74b2f265406d3d6222c902800e6dbe08b0e8d6fe Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Aug 2014 17:52:04 -0600 Subject: [PATCH 027/355] Add PaneContainer::onDidChangeActivePaneItem --- spec/pane-container-spec.coffee | 21 ++++++++++++++++++++ src/pane-container.coffee | 34 +++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index ad7f80b6a..c87a2fe3c 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -66,3 +66,24 @@ describe "PaneContainer", -> pane2.destroy() expect(container.getActivePane()).toBe pane1 expect(pane1.isActive()).toBe true + + describe "::onDidChangeActivePaneItem()", -> + [container, pane1, pane2, observed] = [] + + beforeEach -> + container = new PaneContainer(root: new Pane(items: [new Object, new Object])) + container.getRoot().splitRight(items: [new Object, new Object]) + [pane1, pane2] = container.getPanes() + + observed = [] + container.onDidChangeActivePaneItem (item) -> observed.push(item) + + it "invokes observers when the active item of the active pane changes", -> + pane2.activateNextItem() + pane2.activateNextItem() + expect(observed).toEqual [pane2.itemAtIndex(1), pane2.itemAtIndex(0)] + + it "invokes observers when the active pane changes", -> + pane1.activate() + pane2.activate() + expect(observed).toEqual [pane1.itemAtIndex(0), pane2.itemAtIndex(0)] diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 63e6a5a9a..a3a1f3ba7 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -1,6 +1,6 @@ {find} = require 'underscore-plus' {Model} = require 'theorist' -{Emitter} = require 'event-kit' +{Emitter, CompositeDisposable} = require 'event-kit' Serializable = require 'serializable' Pane = require './pane' @@ -26,10 +26,13 @@ class PaneContainer extends Model super @emitter = new Emitter + @subscriptions = new CompositeDisposable @subscribe @$root, @onRootChanged @destroyEmptyPanes() if params?.destroyEmptyPanes + @monitorActivePaneItem() + deserializeParams: (params) -> params.root = atom.deserializers.deserialize(params.root, container: this) params.destroyEmptyPanes = atom.config.get('core.destroyEmptyPanes') @@ -43,6 +46,17 @@ class PaneContainer extends Model onDidChangeActivePane: (fn) -> @emitter.on 'did-change-active-pane', fn + observeActivePane: (fn) -> + fn(@getActivePane()) + @onDidChangeActivePane(fn) + + onDidChangeActivePaneItem: (fn) -> + @emitter.on 'did-change-active-pane-item', fn + + observeActivePaneItem: (fn) -> + fn(@getActivePaneItem()) + @onDidChangeActivePaneItem(fn) + getRoot: -> @root replaceChild: (oldChild, newChild) -> @@ -61,6 +75,9 @@ class PaneContainer extends Model @emitter.emit 'did-change-active-pane', @activePane @activePane + getActivePaneItem: -> + @getActivePane().getActiveItem() + paneForUri: (uri) -> find @getPanes(), (pane) -> pane.itemForUri(uri)? @@ -99,7 +116,6 @@ class PaneContainer extends Model root.parent = this root.container = this - @activePane ?= root if root instanceof Pane destroyEmptyPanes: -> @@ -111,3 +127,17 @@ class PaneContainer extends Model # Called by Model superclass when destroyed destroyed: -> pane.destroy() for pane in @getPanes() + @subscriptions.dispose() + @emitter.dispose() + + monitorActivePaneItem: -> + childSubscription = null + @subscriptions.add @observeActivePane (activePane) => + if childSubscription? + @subscriptions.remove(childSubscription) + childSubscription.dispose() + + childSubscription = activePane.observeActiveItem (activeItem) => + @emitter.emit 'did-change-active-pane-item', activeItem + + @subscriptions.add(childSubscription) From cf3e1177ab705ec2f756bb9d78b8a9df0e40e893 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 10:51:17 -0600 Subject: [PATCH 028/355] Upgrade event-kit to fix stupid bug --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7e5767ef2..971f7e9f3 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.0", - "event-kit": "0.2.0", + "event-kit": "0.3.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", From b34367ad44da49e5258856b0c653875eb8d36d83 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 10:51:39 -0600 Subject: [PATCH 029/355] :lipstick: pane-container-spec --- spec/pane-container-spec.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index c87a2fe3c..2b5f24c36 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -34,9 +34,10 @@ describe "PaneContainer", -> expect(containerB.getActivePane()).toBe pane3B it "does not allow the root pane to be destroyed", -> - pane1.destroy() - expect(container.getRoot()).toBe pane1 - expect(pane1.isDestroyed()).toBe false + container = new PaneContainer + container.getRoot().destroy() + expect(container.getRoot()).toBeDefined() + expect(container.getRoot().isDestroyed()).toBe false describe "::getActivePane()", -> [container, pane1, pane2] = [] From b74554ad4c1f55d6c2562c0929998838ccb9e48f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 10:53:54 -0600 Subject: [PATCH 030/355] Actually subscribe --- src/pane-axis.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 1cc1dea51..8e384ca87 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -49,7 +49,7 @@ class PaneAxis extends Model @emitter.on 'did-replace-child', fn onDidDestroy: (fn) -> - @emitter.on 'did-destroy' + @emitter.on 'did-destroy', fn addChild: (child, index=@children.length) -> child.parent = this From 7556b8580657d898412ea1f55cae3f5441cc0308 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 10:54:06 -0600 Subject: [PATCH 031/355] Remove/add the *subscription*, not the child --- src/pane-axis.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 8e384ca87..95039e737 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -96,11 +96,11 @@ class PaneAxis extends Model subscribeToChild: (child) -> subscription = child.onDidDestroy => @removeChild(child) @subscriptionsByChild.set(child, subscription) - @subscriptions.add(child) + @subscriptions.add(subscription) unsubscribeFromChild: (child) -> subscription = @subscriptionsByChild.get(child) - @subscriptions.remove(child) + @subscriptions.remove(subscription) subscription.dispose() destroyed: -> From 9223361c228de524017a2ff8c683831a25649aa7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 11:00:35 -0600 Subject: [PATCH 032/355] Add PaneContainer::onDidChange/observeRoot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, don’t use a behavior to monitor root changes --- src/pane-container-view.coffee | 10 ++++++++-- src/pane-container.coffee | 36 +++++++++++++++++----------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/pane-container-view.coffee b/src/pane-container-view.coffee index 77be49420..2b3f45cca 100644 --- a/src/pane-container-view.coffee +++ b/src/pane-container-view.coffee @@ -1,5 +1,6 @@ {deprecate} = require 'grim' Delegator = require 'delegato' +{CompositeDisposable} = require 'event-kit' {$, View} = require './space-pen-extensions' PaneView = require './pane-view' PaneContainer = require './pane-container' @@ -15,13 +16,15 @@ class PaneContainerView extends View @div class: 'panes' initialize: (params) -> + @subscriptions = new CompositeDisposable + if params instanceof PaneContainer @model = params else @model = new PaneContainer({root: params?.root?.model}) - @subscribe @model.$root, @onRootChanged - @subscribe @model.$activePaneItem.changes, @onActivePaneItemChanged + @subscriptions.add @model.observeRoot(@onRootChanged) + @subscriptions.add @model.onDidChangeActivePaneItem(@onActivePaneItemChanged) viewForModel: (model) -> if model? @@ -153,3 +156,6 @@ class PaneContainerView extends View getPanes: -> deprecate("Use PaneContainerView::getPaneViews() instead") @getPaneViews() + + beforeRemove: -> + @subscriptions.dispose() diff --git a/src/pane-container.coffee b/src/pane-container.coffee index a3a1f3ba7..7b0ce7a61 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -12,10 +12,9 @@ class PaneContainer extends Model @version: 1 @properties - root: -> new Pane activePane: null - previousRoot: null + root: null @behavior 'activePaneItem', -> @$activePane @@ -28,7 +27,7 @@ class PaneContainer extends Model @emitter = new Emitter @subscriptions = new CompositeDisposable - @subscribe @$root, @onRootChanged + @setRoot(params?.root ? new Pane) @destroyEmptyPanes() if params?.destroyEmptyPanes @monitorActivePaneItem() @@ -43,6 +42,13 @@ class PaneContainer extends Model root: @root?.serialize() activePaneId: @activePane.id + onDidChangeRoot: (fn) -> + @emitter.on 'did-change-root', fn + + observeRoot: (fn) -> + fn(@getRoot()) + @onDidChangeRoot(fn) + onDidChangeActivePane: (fn) -> @emitter.on 'did-change-active-pane', fn @@ -59,12 +65,19 @@ class PaneContainer extends Model getRoot: -> @root + setRoot: (@root) -> + @root.parent = this + @root.container = this + @emitter.emit 'did-change-root', @root + if not @getActivePane()? and @root instanceof Pane + @setActivePane(@root) + replaceChild: (oldChild, newChild) -> throw new Error("Replacing non-existent child") if oldChild isnt @root - @root = newChild + @setRoot(newChild) getPanes: -> - @root?.getPanes() ? [] + @getRoot().getPanes() getActivePane: -> @activePane @@ -105,19 +118,6 @@ class PaneContainer extends Model else false - onRootChanged: (root) => - @unsubscribe(@previousRoot) if @previousRoot? - @previousRoot = root - - unless root? - @setActivePane(null) - return - - root.parent = this - root.container = this - - @activePane ?= root if root instanceof Pane - destroyEmptyPanes: -> pane.destroy() for pane in @getPanes() when pane.items.length is 0 From b1916069deed75e6dadc5f6f38817897b1f76ce4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 11:11:05 -0600 Subject: [PATCH 033/355] Delegate ::getActivePane[Item] directly to PaneContainer --- src/workspace.coffee | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 85870ef1b..bf35c9a82 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -243,7 +243,13 @@ class Workspace extends Model # # Returns a {Pane}. getActivePane: -> - @paneContainer.activePane + @paneContainer.getActivePane() + + # Public: Get the active {Pane}'s active item. + # + # Returns an pane item {Object}. + getActivePaneItem: -> + @paneContainer.getActivePaneItem() # Public: Get all {Pane}s. # @@ -271,12 +277,6 @@ class Workspace extends Model paneForUri: (uri) -> @paneContainer.paneForUri(uri) - # Public: Get the active {Pane}'s active item. - # - # Returns an pane item {Object}. - getActivePaneItem: -> - @paneContainer.getActivePane().getActiveItem() - # Public: Save the active pane item. # # If the active pane item currently has a URI according to the item's From 95e9686b37303080098ae51010756d32dab5b621 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 11:17:06 -0600 Subject: [PATCH 034/355] Emit legacy item-added DOM event correctly --- src/pane-view.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index 317fca95b..ac79faaba 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -163,7 +163,7 @@ class PaneView extends View @trigger 'pane:active-item-changed', [item] - onItemAdded: (item, index) => + onItemAdded: ({item, index}) => @trigger 'pane:item-added', [item, index] onItemRemoved: ({item, index, destroyed}) => From 34cb5d60124b5fa73597f7231d94e50e2764d025 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 15:21:10 -0600 Subject: [PATCH 035/355] =?UTF-8?q?Don=E2=80=99t=20implement=20::isActive?= =?UTF-8?q?=20in=20terms=20of=20the=20theorist=20model=20behavior?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pane.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pane.coffee b/src/pane.coffee index 8d3226b41..f8e0fa391 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -117,7 +117,8 @@ class Pane extends Model onWillDestroyItem: (fn) -> @emitter.on 'will-destroy-item', fn - isActive: -> @active + isActive: -> + @container?.getActivePane() is this # Called by the view layer to indicate that the pane has gained focus. focus: -> From d7063c0932732ad4930b4d927b7df53ab5300add Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 15:21:35 -0600 Subject: [PATCH 036/355] Add Pane::onDidDestroy --- src/pane.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pane.coffee b/src/pane.coffee index f8e0fa391..72f104866 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -93,6 +93,8 @@ class Pane extends Model onDidChangeActive: (fn) -> @container.onDidChangeActivePane (activePane) => fn(this is activePane) + onDidDestroy: (callback) -> + @emitter.on 'did-destroy', callback observeActive: (fn) -> fn(@isActive()) @@ -296,6 +298,7 @@ class Pane extends Model # Called by model superclass. destroyed: -> + @emitter.emit 'did-destroy' @container.activateNextPane() if @isActive() item.destroy?() for item in @items.slice() From e88eb3012e552b34810c8cf35f70a22324534bf1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 15:21:48 -0600 Subject: [PATCH 037/355] Document Pane event subscription methods --- src/pane.coffee | 119 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 20 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 72f104866..039f42aef 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -88,36 +88,115 @@ class Pane extends Model # Called by the view layer to construct a view for this model. getViewClass: -> PaneView ?= require './pane-view' - onDidActivate: (fn) -> - @emitter.on 'did-activate', fn + # Public: Invoke the given callback when the pane is activated. + # + # The given callback will be invoked whenever {::activate} is called on the + # pane, even if it is already active at the time. + # + # * `callback` {Function} to be called when the pane is activated. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidActivate: (callback) -> + @emitter.on 'did-activate', callback - onDidChangeActive: (fn) -> - @container.onDidChangeActivePane (activePane) => fn(this is activePane) + # Public: Invoke the given callback when the pane is destroyed. + # + # * `callback` {Function} to be called when the pane is destroyed. onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback - observeActive: (fn) -> - fn(@isActive()) - @onDidChangeActive(fn) + # Public: Invoke the given callback when the value of the {::isActive} + # property changes. + # + # * `callback` {Function} to be called when the value of the {::isActive} + # property changes. + # * `active` {Boolean} indicating whether the pane is active. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidChangeActive: (callback) -> + @container.onDidChangeActivePane (activePane) => + callback(this is activePane) - onDidAddItem: (fn) -> - @emitter.on 'did-add-item', fn + # Public: Invoke the given callback with the current and future values of the + # {::isActive} property. + # + # * `callback` {Function} to be called with the current and future values of + # the {::isActive} property. + # * `active` {Boolean} indicating whether the pane is active. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observeActive: (callback) -> + callback(@isActive()) + @onDidChangeActive(callback) - onDidRemoveItem: (fn) -> - @emitter.on 'did-remove-item', fn + # Public: Invoke the given callback when an item is added to the pane. + # + # * `callback` {Function} to be called with when items are added. + # * `event` {Object} with the following keys: + # * `item` The added pane item. + # * `index` {Number} indicating where the item is located. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidAddItem: (callback) -> + @emitter.on 'did-add-item', callback - onDidMoveItem: (fn) -> - @emitter.on 'did-move-item', fn + # Public: Invoke the given callback when an item is removed from the pane. + # + # * `callback` {Function} to be called with when items are removed. + # * `event` {Object} with the following keys: + # * `item` The removed pane item. + # * `index` {Number} indicating where the item was located. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidRemoveItem: (callback) -> + @emitter.on 'did-remove-item', callback - onDidChangeActiveItem: (fn) -> - @emitter.on 'did-change-active-item', fn + # Public: Invoke the given callback when an item is moved within the pane. + # + # * `callback` {Function} to be called with when items are moved. + # * `event` {Object} with the following keys: + # * `item` The removed pane item. + # * `oldIndex` {Number} indicating where the item was located. + # * `newIndex` {Number} indicating where the item is now located. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidMoveItem: (callback) -> + @emitter.on 'did-move-item', callback - observeActiveItem: (fn) -> - fn(@getActiveItem()) - @onDidChangeActiveItem(fn) + # Public: Invoke the given callback when the value of {::getActiveItem} + # changes. + # + # * `callback` {Function} to be called with when the active item + # changes. + # * `activeItem` The current active item. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidChangeActiveItem: (callback) -> + @emitter.on 'did-change-active-item', callback - onWillDestroyItem: (fn) -> - @emitter.on 'will-destroy-item', fn + # Public: Invoke the given callback with the current and future values of + # {::getActiveItem}. + # + # * `callback` {Function} to be called with the current and future active + # items. + # * `activeItem` The current active item. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observeActiveItem: (callback) -> + callback(@getActiveItem()) + @onDidChangeActiveItem(callback) + + # Public: Invoke the given callback before items are destroyed. + # + # * `callback` {Function} to be called before items are destroyed. + # * `event` {Object} with the following keys: + # * `item` The item that will be destroyed. + # * `index` The location of the item. + # + # Returns a {Disposable} on which `.dispose()` can be called to + # unsubscribe. + onWillDestroyItem: (callback) -> + @emitter.on 'will-destroy-item', callback isActive: -> @container?.getActivePane() is this From 78c24fb737371047546e5ebd084fbf56ac76a4d1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 15:54:16 -0600 Subject: [PATCH 038/355] Remove legacy event documentation --- src/pane.coffee | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 039f42aef..5afd35b3d 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -9,40 +9,6 @@ PaneView = null # Extended: A container for multiple items, one of which is *active* at a given # time. With the default packages, a tab is displayed for each item and the # active item's view is displayed. -# -# ## Events -# ### activated -# -# Extended: Emit when this pane as been activated -# -# ### item-added -# -# Extended: Emit when an item was added to the pane -# -# * `item` The pane item that has been added -# * `index` {Number} Index in the pane -# -# ### before-item-destroyed -# -# Extended: Emit before the item is destroyed -# -# * `item` The pane item that will be destoryed -# -# ### item-removed -# -# Extended: Emit when the item was removed from the pane -# -# * `item` The pane item that was removed -# * `index` {Number} Index in the pane -# * `destroying` {Boolean} `true` when the item is being removed because of destruction -# -# ### item-moved -# -# Extended: Emit when an item was moved within the pane -# -# * `item` The pane item that was moved -# * `newIndex` {Number} Index that the item was moved to -# module.exports = class Pane extends Model atom.deserializers.add(this) From 345617e0f34b41e485f47012e458c044659a4f46 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 15:54:39 -0600 Subject: [PATCH 039/355] Clean up existing pane API docs --- src/pane.coffee | 147 ++++++++++++++++++++++++++++++------------------ 1 file changed, 91 insertions(+), 56 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index 5afd35b3d..b97c8ad53 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -6,9 +6,10 @@ PaneAxis = require './pane-axis' Editor = require './editor' PaneView = null -# Extended: A container for multiple items, one of which is *active* at a given -# time. With the default packages, a tab is displayed for each item and the -# active item's view is displayed. +# Extended: A container for presenting content in the center of the workspace. +# Panes can contain multiple items, one of which is *active* at a given time. +# The view corresponding to the active item is displayed in the interface. In +# the default configuration, tabs are also displayed for each item. module.exports = class Pane extends Model atom.deserializers.add(this) @@ -164,6 +165,9 @@ class Pane extends Model onWillDestroyItem: (callback) -> @emitter.on 'will-destroy-item', callback + # Public: Determine whether the pane is active. + # + # Returns a {Boolean}. isActive: -> @container?.getActivePane() is this @@ -177,8 +181,7 @@ class Pane extends Model @focused = false true # if this is called from an event handler, don't cancel it - # Public: Makes this pane the *active* pane, causing it to gain focus - # immediately. + # Public: Makes this pane the *active* pane, causing it to gain focus. activate: -> @container?.setActivePane(this) @emit 'activated' @@ -203,12 +206,15 @@ class Pane extends Model @emitter.emit 'did-change-active-item', @activeItem @activeItem - # Public: Returns an {Editor} if the pane item is an {Editor}, or null - # otherwise. + # Return an {Editor} if the pane item is an {Editor}, or null otherwise. getActiveEditor: -> @activeItem if @activeItem instanceof Editor - # Public: Returns the item at the specified index. + # Public: Return the item at the given index. + # + # * `index` {Number} + # + # Returns an item or `null` if no item exists at the given index. itemAtIndex: (index) -> @items[index] @@ -228,27 +234,33 @@ class Pane extends Model else @activateItemAtIndex(@items.length - 1) - # Returns the index of the current active item. + # Public: Get the index of the active item. + # + # Returns a {Number}. getActiveItemIndex: -> @items.indexOf(@activeItem) - # Makes the item at the given index active. + # Public: Activate the item at the given index. + # + # * `index` {Number} activateItemAtIndex: (index) -> @activateItem(@itemAtIndex(index)) - # Makes the given item active, adding the item if necessary. + # Public: Make the given item *active*, causing it to be displayed by + # the pane's view. activateItem: (item) -> if item? @addItem(item) @setActiveItem(item) - # Public: Adds the item to the pane. + # Public: Add the given item to the pane. # - # * `item` The item to add. It can be a model with an associated view or a view. - # * `index` (optional) {Number} at which to add the item. If omitted, the item is - # added after the current active item. + # * `item` The item to add. It can be a model with an associated view or a + # view. + # * `index` (optional) {Number} at which to add the item. If omitted, the item + # is added after the current active item. # - # Returns the added item + # Returns the added item. addItem: (item, index=@getActiveItemIndex() + 1) -> return if item in @items @@ -261,15 +273,15 @@ class Pane extends Model @setActiveItem(item) unless @getActiveItem()? item - # Public: Adds the given items to the pane. + # Public: Add the given items to the pane. # - # * `items` An {Array} of items to add. Items can be models with associated - # views or views. Any items that are already present in items will - # not be added. - # * `index` (optional) {Number} index at which to add the item. If omitted, the item is - # added after the current active item. + # * `items` An {Array} of items to add. Items can be views or models with + # associated views. Any objects that are already present in the pane's + # current items will not be added again. + # * `index` (optional) {Number} index at which to add the items. If omitted, + # the item is # added after the current active item. # - # Returns an {Array} of the added items + # Returns an {Array} of added items. addItems: (items, index=@getActiveItemIndex() + 1) -> items = items.filter (item) => not (item in @items) @addItem(item, index + i) for item, i in items @@ -295,7 +307,10 @@ class Pane extends Model @container?.itemDestroyed(item) if destroyed @destroy() if @items.length is 0 and atom.config.get('core.destroyEmptyPanes') - # Public: Moves the given item to the specified index. + # Public: Move the given item to the given index. + # + # * `item` The item to move. + # * `index` {Number} indicating the index to which to move the item. moveItem: (item, newIndex) -> oldIndex = @items.indexOf(item) @items.splice(oldIndex, 1) @@ -303,18 +318,26 @@ class Pane extends Model @emit 'item-moved', item, newIndex @emitter.emit 'did-move-item', {item, oldIndex, newIndex} - # Public: Moves the given item to the given index at another pane. + # Public: Move the given item to the given index on another pane. + # + # * `item` The item to move. + # * `pane` {Pane} to which to move the item. + # * `index` {Number} indicating the index to which to move the item in the + # given pane. moveItemToPane: (item, pane, index) -> pane.addItem(item, index) @removeItem(item) - # Public: Destroys the currently active item and make the next item active. + # Public: Destroy the active item and activate the next item. destroyActiveItem: -> @destroyItem(@activeItem) false - # Public: Destroys the given item. If it is the active item, activate the next - # one. If this is the last item, also destroys the pane. + # Public: Destroy the given item. + # + # If the item is active, the next item will be activated. If the item is the + # last item, the pane will be destroyed if the `core.destroyEmptyPanes` config + # setting is `true`. destroyItem: (item) -> index = @items.indexOf(item) if index isnt -1 @@ -327,14 +350,18 @@ class Pane extends Model else false - # Public: Destroys all items and destroys the pane. + # Public: Destroy all items. destroyItems: -> @destroyItem(item) for item in @getItems() - # Public: Destroys all items but the active one. + # Public: Destroy all items except for the active item. destroyInactiveItems: -> @destroyItem(item) for item in @getItems() when item isnt @activeItem + # Public: Destroy the pane and all its items. + # + # If this is the last pane, all the items will be destroyed but the pane + # itself will not be destroyed. destroy: -> if @container?.isAlive() and @container.getPanes().length is 1 @destroyItems() @@ -347,8 +374,6 @@ class Pane extends Model @container.activateNextPane() if @isActive() item.destroy?() for item in @items.slice() - # Public: Prompts the user to save the given item if it can be saved and is - # currently unsaved. promptToSaveItem: (item) -> return true unless item.shouldPromptToSave?() @@ -363,18 +388,23 @@ class Pane extends Model when 1 then false when 2 then true - # Public: Saves the active item. - saveActiveItem: -> - @saveItem(@activeItem) + # Public: Save the active item. + saveActiveItem: (nextAction) -> + @saveItem(@getActiveItem(), nextAction) - # Public: Saves the active item at a prompted-for location. - saveActiveItemAs: -> - @saveItemAs(@activeItem) + # Public: Prompt the user for a location and save the active item with the + # path they select. + # + # * `nextAction` (optional) {Function} which will be called after the item is + # successfully saved. + saveActiveItemAs: (nextAction) -> + @saveItemAs(@getActiveItem(), nextAction) - # Public: Saves the specified item. + # Public: Save the given item. # # * `item` The item to save. - # * `nextAction` (optional) {Function} which will be called after the item is saved. + # * `nextAction` (optional) {Function} which will be called after the item is + # successfully saved. saveItem: (item, nextAction) -> if item?.getUri?() item.save?() @@ -382,10 +412,12 @@ class Pane extends Model else @saveItemAs(item, nextAction) - # Public: Saves the given item at a prompted-for location. + # Public: Prompt the user for a location and save the active item with the + # path they select. # # * `item` The item to save. - # * `nextAction` (optional) {Function} which will be called after the item is saved. + # * `nextAction` (optional) {Function} which will be called after the item is + # successfully saved. saveItemAs: (item, nextAction) -> return unless item?.saveAs? @@ -395,17 +427,20 @@ class Pane extends Model item.saveAs(newItemPath) nextAction?() - # Public: Saves all items. + # Public: Save all items. saveItems: -> @saveItem(item) for item in @getItems() - # Public: Returns the first item that matches the given URI or undefined if + # Public: Return the first item that matches the given URI or undefined if # none exists. + # + # * `uri` {String} containing a URI. itemForUri: (uri) -> find @items, (item) -> item.getUri?() is uri - # Public: Activates the first item that matches the given URI. Returns a - # boolean indicating whether a matching item was found. + # Public: Activate the first item that matches the given URI. + # + # Returns a {Boolean} indicating whether an item matching the URI was found. activateItemForUri: (uri) -> if item = @itemForUri(uri) @activateItem(item) @@ -417,19 +452,19 @@ class Pane extends Model if @activeItem? @activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize()) - # Public: Creates a new pane to the left of the receiver. + # Public: Create a new pane to the left of this pane. # - # * `params` {Object} with keys - # * `items` (optional) {Array} of items with which to construct the new pane. + # * `params` (optional) {Object} with the following keys: + # * `items` (optional) {Array} of items to add to the new pane. # # Returns the new {Pane}. splitLeft: (params) -> @split('horizontal', 'before', params) - # Public: Creates a new pane to the right of the receiver. + # Public: Create a new pane to the right of this pane. # - # * `params` {Object} with keys: - # * `items` (optional) {Array} of items with which to construct the new pane. + # * `params` (optional) {Object} with the following keys: + # * `items` (optional) {Array} of items to add to the new pane. # # Returns the new {Pane}. splitRight: (params) -> @@ -437,8 +472,8 @@ class Pane extends Model # Public: Creates a new pane above the receiver. # - # * `params` {Object} with keys: - # * `items` (optional) {Array} of items with which to construct the new pane. + # * `params` (optional) {Object} with the following keys: + # * `items` (optional) {Array} of items to add to the new pane. # # Returns the new {Pane}. splitUp: (params) -> @@ -446,8 +481,8 @@ class Pane extends Model # Public: Creates a new pane below the receiver. # - # * `params` {Object} with keys: - # * `items` (optional) {Array} of items with which to construct the new pane. + # * `params` (optional) {Object} with the following keys: + # * `items` (optional) {Array} of items to add to the new pane. # # Returns the new {Pane}. splitDown: (params) -> From cea4db538108c83b159f612f66878e636fae8f3f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 16:19:29 -0600 Subject: [PATCH 040/355] Break pane API into sections --- src/pane.coffee | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index b97c8ad53..d3022ad35 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -55,6 +55,10 @@ class Pane extends Model # Called by the view layer to construct a view for this model. getViewClass: -> PaneView ?= require './pane-view' + ### + Section: Event Subscription + ### + # Public: Invoke the given callback when the pane is activated. # # The given callback will be invoked whenever {::activate} is called on the @@ -165,12 +169,6 @@ class Pane extends Model onWillDestroyItem: (callback) -> @emitter.on 'will-destroy-item', callback - # Public: Determine whether the pane is active. - # - # Returns a {Boolean}. - isActive: -> - @container?.getActivePane() is this - # Called by the view layer to indicate that the pane has gained focus. focus: -> @focused = true @@ -181,14 +179,12 @@ class Pane extends Model @focused = false true # if this is called from an event handler, don't cancel it - # Public: Makes this pane the *active* pane, causing it to gain focus. - activate: -> - @container?.setActivePane(this) - @emit 'activated' - @emitter.emit 'did-activate' - getPanes: -> [this] + ### + Section: Items + ### + # Public: Get the items in this pane. # # Returns an {Array} of items. @@ -358,22 +354,6 @@ class Pane extends Model destroyInactiveItems: -> @destroyItem(item) for item in @getItems() when item isnt @activeItem - # Public: Destroy the pane and all its items. - # - # If this is the last pane, all the items will be destroyed but the pane - # itself will not be destroyed. - destroy: -> - if @container?.isAlive() and @container.getPanes().length is 1 - @destroyItems() - else - super - - # Called by model superclass. - destroyed: -> - @emitter.emit 'did-destroy' - @container.activateNextPane() if @isActive() - item.destroy?() for item in @items.slice() - promptToSaveItem: (item) -> return true unless item.shouldPromptToSave?() @@ -452,6 +432,42 @@ class Pane extends Model if @activeItem? @activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize()) + ### + Section: Lifecycle + ### + + # Public: Determine whether the pane is active. + # + # Returns a {Boolean}. + isActive: -> + @container?.getActivePane() is this + + # Public: Makes this pane the *active* pane, causing it to gain focus. + activate: -> + @container?.setActivePane(this) + @emit 'activated' + @emitter.emit 'did-activate' + + # Public: Close the pane and destroy all its items. + # + # If this is the last pane, all the items will be destroyed but the pane + # itself will not be destroyed. + destroy: -> + if @container?.isAlive() and @container.getPanes().length is 1 + @destroyItems() + else + super + + # Called by model superclass. + destroyed: -> + @emitter.emit 'did-destroy' + @container.activateNextPane() if @isActive() + item.destroy?() for item in @items.slice() + + ### + Section: Splitting + ### + # Public: Create a new pane to the left of this pane. # # * `params` (optional) {Object} with the following keys: From 12f78dd95782a8b928eb6f49dbe1fae9a6c703ef Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 16:27:20 -0600 Subject: [PATCH 041/355] :lipstick: --- src/pane.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index d3022ad35..7e28bd9e4 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -253,8 +253,8 @@ class Pane extends Model # # * `item` The item to add. It can be a model with an associated view or a # view. - # * `index` (optional) {Number} at which to add the item. If omitted, the item - # is added after the current active item. + # * `index` (optional) {Number} indicating the index at which to add the item. + # If omitted, the item is added after the current active item. # # Returns the added item. addItem: (item, index=@getActiveItemIndex() + 1) -> From b60b9f3e3a7caea442b1b2938d8900c0f481fa55 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 16:40:54 -0600 Subject: [PATCH 042/355] Add Pane::observeItems --- spec/pane-spec.coffee | 13 +++++++++++++ src/pane.coffee | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 980490d81..c66b88850 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -292,6 +292,19 @@ describe "Pane", -> expect(item3.isDestroyed()).toBe true expect(pane.getItems()).toEqual [] + describe "::observeItems()", -> + it "invokes the observer with all current and future items", -> + pane = new Pane(items: [new Item, new Item]) + [item1, item2] = pane.getItems() + + observed = [] + pane.observeItems (item) -> observed.push(item) + + item3 = new Item + pane.addItem(item3) + + expect(observed).toEqual [item1, item2, item3] + describe "when an item emits a destroyed event", -> it "removes it from the list of items", -> pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")]) diff --git a/src/pane.coffee b/src/pane.coffee index 7e28bd9e4..b95c72067 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -134,6 +134,15 @@ class Pane extends Model onDidMoveItem: (callback) -> @emitter.on 'did-move-item', callback + # Public: Invoke the given callback with all current and future items. + # + # * `callback` {Function} to be called with current and future items. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observeItems: (callback) -> + callback(item) for item in @getItems() + @onDidAddItem ({item}) -> callback(item) + # Public: Invoke the given callback when the value of {::getActiveItem} # changes. # From 5471e9bcccf959c03b9c3943c6fe794547fca69d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 16:58:38 -0600 Subject: [PATCH 043/355] Add PaneContainer::onDidDestroyPaneItem --- src/pane-container.coffee | 7 +++++-- src/pane.coffee | 2 +- src/workspace.coffee | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 7b0ce7a61..37210cb7a 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -63,6 +63,9 @@ class PaneContainer extends Model fn(@getActivePaneItem()) @onDidChangeActivePaneItem(fn) + onDidDestroyPaneItem: (fn) -> + @emitter.on 'did-destroy-pane-item', fn + getRoot: -> @root setRoot: (@root) -> @@ -121,8 +124,8 @@ class PaneContainer extends Model destroyEmptyPanes: -> pane.destroy() for pane in @getPanes() when pane.items.length is 0 - itemDestroyed: (item) -> - @emit 'item-destroyed', item + paneItemDestroyed: (item) -> + @emitter.emit 'did-destroy-pane-item', item # Called by Model superclass when destroyed destroyed: -> diff --git a/src/pane.coffee b/src/pane.coffee index b95c72067..bbd1bc729 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -309,7 +309,7 @@ class Pane extends Model @items.splice(index, 1) @emit 'item-removed', item, index, destroyed @emitter.emit 'did-remove-item', {item, index, destroyed} - @container?.itemDestroyed(item) if destroyed + @container?.paneItemDestroyed(item) if destroyed @destroy() if @items.length is 0 and atom.config.get('core.destroyEmptyPanes') # Public: Move the given item to the given index. diff --git a/src/workspace.coffee b/src/workspace.coffee index bf35c9a82..198b74a19 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -46,7 +46,8 @@ class Workspace extends Model @openers = [] - @subscribe @paneContainer, 'item-destroyed', @onPaneItemDestroyed + @paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed) + @registerOpener (filePath) => switch filePath when 'atom://.atom/stylesheet' From cee7539e35a7e030756dbdf84b09ba3fd3f25a3f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:14:15 -0600 Subject: [PATCH 044/355] Add PaneContainer::observePanes and ::onDidAddPane --- spec/pane-container-spec.coffee | 14 ++++++++++++++ src/pane-axis.coffee | 20 ++++++++++++++++---- src/pane-container.coffee | 14 ++++++++++++-- src/pane.coffee | 10 ++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 2b5f24c36..279b543ce 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -88,3 +88,17 @@ describe "PaneContainer", -> pane1.activate() pane2.activate() expect(observed).toEqual [pane1.itemAtIndex(0), pane2.itemAtIndex(0)] + + describe "::observePanes()", -> + it "invokes with subscribers with all current and future panes", -> + container = new PaneContainer + container.getRoot().splitRight() + [pane1, pane2] = container.getPanes() + + observed = [] + container.observePanes (pane) -> observed.push(pane) + + pane3 = pane2.splitDown() + pane4 = pane2.splitRight() + + expect(observed).toEqual [pane1, pane2, pane3, pane4] diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 95039e737..e9bc4993b 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -11,6 +11,10 @@ class PaneAxis extends Model atom.deserializers.add(this) Serializable.includeInto(this) + parent: null + container: null + orientation: null + constructor: ({@container, @orientation, children}) -> @emitter = new Emitter @subscriptionsByChild = new WeakMap @@ -28,6 +32,14 @@ class PaneAxis extends Model children: @children.map (child) -> child.serialize() orientation: @orientation + getParent: -> @parent + + setParent: (@parent) -> @parent + + getContainer: -> @container + + setContainer: (@container) -> @container + getViewClass: -> if @orientation is 'vertical' PaneColumnView ?= require './pane-column-view' @@ -52,8 +64,8 @@ class PaneAxis extends Model @emitter.on 'did-destroy', fn addChild: (child, index=@children.length) -> - child.parent = this - child.container = @container + child.setParent(this) + child.setContainer(@container) @subscribeToChild(child) @@ -74,8 +86,8 @@ class PaneAxis extends Model @unsubscribeFromChild(oldChild) @subscribeToChild(newChild) - newChild.parent = this - newChild.container = @container + newChild.setParent(this) + newChild.setContainer(@container) index = @children.indexOf(oldChild) @children.splice(index, 1, newChild) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 37210cb7a..73bcabc6a 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -49,6 +49,13 @@ class PaneContainer extends Model fn(@getRoot()) @onDidChangeRoot(fn) + onDidAddPane: (fn) -> + @emitter.on 'did-add-pane', fn + + observePanes: (fn) -> + fn(pane) for pane in @getPanes() + @onDidAddPane ({pane}) -> fn(pane) + onDidChangeActivePane: (fn) -> @emitter.on 'did-change-active-pane', fn @@ -69,8 +76,8 @@ class PaneContainer extends Model getRoot: -> @root setRoot: (@root) -> - @root.parent = this - @root.container = this + @root.setParent(this) + @root.setContainer(this) @emitter.emit 'did-change-root', @root if not @getActivePane()? and @root instanceof Pane @setActivePane(@root) @@ -127,6 +134,9 @@ class PaneContainer extends Model paneItemDestroyed: (item) -> @emitter.emit 'did-destroy-pane-item', item + didAddPane: (pane) -> + @emitter.emit 'did-add-pane', pane + # Called by Model superclass when destroyed destroyed: -> pane.destroy() for pane in @getPanes() diff --git a/src/pane.coffee b/src/pane.coffee index bbd1bc729..4e4bb7350 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -55,6 +55,16 @@ class Pane extends Model # Called by the view layer to construct a view for this model. getViewClass: -> PaneView ?= require './pane-view' + getParent: -> @parent + + setParent: (@parent) -> @parent + + getContainer: -> @container + + setContainer: (container) -> + container.didAddPane({pane: this}) unless container is @container + @container = container + ### Section: Event Subscription ### From 877fa40a496030505f5190f91b28efa5c7ad8e12 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:22:51 -0600 Subject: [PATCH 045/355] Activate next pane on before invoking onDidDestroy observers --- spec/pane-container-spec.coffee | 2 +- src/pane.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 279b543ce..e9f220e0e 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -90,7 +90,7 @@ describe "PaneContainer", -> expect(observed).toEqual [pane1.itemAtIndex(0), pane2.itemAtIndex(0)] describe "::observePanes()", -> - it "invokes with subscribers with all current and future panes", -> + it "invokes observers with all current and future panes", -> container = new PaneContainer container.getRoot().splitRight() [pane1, pane2] = container.getPanes() diff --git a/src/pane.coffee b/src/pane.coffee index 4e4bb7350..55c1c182a 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -479,8 +479,8 @@ class Pane extends Model # Called by model superclass. destroyed: -> - @emitter.emit 'did-destroy' @container.activateNextPane() if @isActive() + @emitter.emit 'did-destroy' item.destroy?() for item in @items.slice() ### From a33706ddbcffa7ad53137973fbabcf8419625af0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:42:12 -0600 Subject: [PATCH 046/355] Add PaneContainer::onDidAddPaneItem and ::observePaneItems --- spec/pane-container-spec.coffee | 13 +++++++++++++ src/pane-axis.coffee | 3 +++ src/pane-container.coffee | 21 ++++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index e9f220e0e..1701e3f03 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -102,3 +102,16 @@ describe "PaneContainer", -> pane4 = pane2.splitRight() expect(observed).toEqual [pane1, pane2, pane3, pane4] + + describe "::observePaneItems()", -> + it "invokes observers with all current and future pane items", -> + container = new PaneContainer(root: new Pane(items: [new Object, new Object])) + container.getRoot().splitRight(items: [new Object]) + [pane1, pane2] = container.getPanes() + observed = [] + container.observePaneItems (pane) -> observed.push(pane) + + pane3 = pane2.splitDown(items: [new Object]) + pane3.addItems([new Object, new Object]) + + expect(observed).toEqual container.getPaneItems() diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index e9bc4993b..9ef95bc8c 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -51,6 +51,9 @@ class PaneAxis extends Model getPanes: -> flatten(@children.map (child) -> child.getPanes()) + getItems: -> + flatten(@children.map (child) -> child.getItems()) + onDidAddChild: (fn) -> @emitter.on 'did-add-child', fn diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 73bcabc6a..14eeae077 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -1,4 +1,4 @@ -{find} = require 'underscore-plus' +{find, flatten} = require 'underscore-plus' {Model} = require 'theorist' {Emitter, CompositeDisposable} = require 'event-kit' Serializable = require 'serializable' @@ -31,6 +31,7 @@ class PaneContainer extends Model @destroyEmptyPanes() if params?.destroyEmptyPanes @monitorActivePaneItem() + @monitorPaneItems() deserializeParams: (params) -> params.root = atom.deserializers.deserialize(params.root, container: this) @@ -63,6 +64,13 @@ class PaneContainer extends Model fn(@getActivePane()) @onDidChangeActivePane(fn) + onDidAddPaneItem: (fn) -> + @emitter.on 'did-add-pane-item', fn + + observePaneItems: (fn) -> + fn(item) for item in @getPaneItems() + @onDidAddPaneItem ({item}) -> fn(item) + onDidChangeActivePaneItem: (fn) -> @emitter.on 'did-change-active-pane-item', fn @@ -89,6 +97,9 @@ class PaneContainer extends Model getPanes: -> @getRoot().getPanes() + getPaneItems: -> + @getRoot().getItems() + getActivePane: -> @activePane @@ -154,3 +165,11 @@ class PaneContainer extends Model @emitter.emit 'did-change-active-pane-item', activeItem @subscriptions.add(childSubscription) + + monitorPaneItems: -> + @subscriptions.add @observePanes (pane) => + for item, index in pane.getItems() + @emitter.emit 'did-add-pane-item', {item, pane, index} + + pane.onDidAddItem ({item, index}) => + @emitter.emit 'did-add-pane-item', {item, pane, index} From acb9bdaf330fbec27d2fec2a109898d4f140233f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:52:30 -0600 Subject: [PATCH 047/355] Add pane and pane item observer methods to workspace. Also document. --- src/workspace.coffee | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/workspace.coffee b/src/workspace.coffee index 198b74a19..7dee0b7cc 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -90,6 +90,43 @@ class Workspace extends Model editorAdded: (editor) -> @emit 'editor-created', editor + # Public: Invoke the given callback when a pane is added to the workspace. + # + # * `callback` {Function} to be called panes are added. + # * `event` {Object} with the following keys: + # * `pane` The added pane. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidAddPane: (callback) -> @paneContainer.onDidAddPane(callback) + + # Public: Invoke the given callback with all current and future panes in the + # workspace. + # + # * `callback` {Function} to be called with current and future panes. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observePanes: (callback) -> @paneContainer.observePanes(callback) + + # Public: Invoke the given callback when a pane item is added to the + # workspace. + # + # * `callback` {Function} to be called panes are added. + # * `event` {Object} with the following keys: + # * `item` The added pane item. + # * `pane` {Pane} containing the added item. + # * `index` {Number} indicating the index of the added item in its pane. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidAddPaneItem: (callback) -> @paneContainer.onDidAddPaneItem(callback) + + # Public: Invoke the given callback with all current and future panes items in + # the workspace. + # + # * `callback` {Function} to be called with current and future pane items. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observePaneItems: (callback) -> @paneContainer.observePaneItems(callback) + # Public: Register a function to be called for every current and future # {Editor} in the workspace. # From 70a23b010762c68e0f6611e6d60671a08ea1a862 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 18:27:13 -0600 Subject: [PATCH 048/355] Add Workspace::getPanes and ::getPaneItems --- src/workspace.coffee | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/workspace.coffee b/src/workspace.coffee index 7dee0b7cc..4581d0099 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -277,12 +277,24 @@ class Workspace extends Model getOpeners: -> @openers + # Public: Get all panes in the workspace. + # + # Returns an {Array} of {Pane}s. + getPanes: -> + @paneContainer.getPanes() + # Public: Get the active {Pane}. # # Returns a {Pane}. getActivePane: -> @paneContainer.getActivePane() + # Public: Get all pane items in the workspace. + # + # Returns an {Array} of items. + getPaneItems: -> + @paneContainer.getPaneItems() + # Public: Get the active {Pane}'s active item. # # Returns an pane item {Object}. From 6c2bb26e77054fe43041effd2fbe2633097b6c7e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 18:28:10 -0600 Subject: [PATCH 049/355] Add Workspace::observeTextEditors and ::onDidAddTextEditor --- spec/workspace-spec.coffee | 15 +++++++++++++++ src/workspace.coffee | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index a75896582..64ba379b2 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -284,6 +284,21 @@ describe "Workspace", -> waitsForPromise -> workspace.openLicense() runs -> expect(workspace.activePaneItem.getText()).toMatch /Copyright/ + describe "::observeTextEditors()", -> + it "invokes the observer with current and future text editors", -> + observed = [] + + waitsForPromise -> workspace.open() + waitsForPromise -> workspace.open() + waitsForPromise -> workspace.openLicense() + + runs -> + workspace.observeTextEditors (editor) -> observed.push(editor) + + waitsForPromise -> workspace.open() + + expect(observed).toEqual workspace.getTextEditors() + describe "when an editor is destroyed", -> it "removes the editor", -> editor = null diff --git a/src/workspace.coffee b/src/workspace.coffee index 4581d0099..84e3ff4a8 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -127,7 +127,32 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observePaneItems: (callback) -> @paneContainer.observePaneItems(callback) - # Public: Register a function to be called for every current and future + # Public: Invoke the given callback when a text editor is added to the + # workspace. + # + # * `callback` {Function} to be called panes are added. + # * `event` {Object} with the following keys: + # * `textEditor` {Editor} that was added. + # * `pane` {Pane} containing the added text editor. + # * `index` {Number} indicating the index of the added text editor in its + # pane. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidAddTextEditor: (callback) -> + @onDidAddPaneItem ({item, pane, index}) -> + callback({textEditor: item, pane, index}) if item instanceof Editor + + # Public: Invoke the given callback with all current and future text editors + # in the workspace. + # + # * `callback` {Function} to be called with current and future text editors. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observeTextEditors: (callback) -> + callback(textEditor) for textEditor in @getTextEditors() + @onDidAddTextEditor ({textEditor}) -> callback(textEditor) + + # Deprecated: Register a function to be called for every current and future # {Editor} in the workspace. # # * `callback` A {Function} with an {Editor} as its only argument. @@ -138,7 +163,7 @@ class Workspace extends Model callback(editor) for editor in @getEditors() @subscribe this, 'editor-created', (editor) -> callback(editor) - # Public: Get all current editors in the workspace. + # Deprecated: Get all current editors in the workspace. # # Returns an {Array} of {Editor}s. getEditors: -> @@ -148,6 +173,12 @@ class Workspace extends Model editors + # Public: Get all text editors in the workspace. + # + # Returns an {Array} of {Editor}s. + getTextEditors: -> + @getPaneItems().filter (item) -> item instanceof Editor + # Public: Open a given a URI in Atom asynchronously. # # * `uri` A {String} containing a URI. From c9e5ff66061788135bcb9ee49640863d1964fa0a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 19:06:57 -0600 Subject: [PATCH 050/355] Organize workspace API into sections. Add ::getActiveTextEditor --- src/workspace.coffee | 154 ++++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 84e3ff4a8..65f1b1ddc 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -16,17 +16,6 @@ Pane = require './pane' # editors, and manipulate panes. To add panels, you'll need to use the # {WorkspaceView} class for now until we establish APIs at the model layer. # -# ## Events -# -# ### uri-opened -# -# Extended: Emit when something has been opened. This can be anything, from an -# editor to the settings view. You can get the new item via {::getActivePaneItem} -# -# ### editor-created -# -# Extended: Emit when an editor is created (a file opened). -# # * `editor` {Editor} the new editor # module.exports = @@ -90,7 +79,11 @@ class Workspace extends Model editorAdded: (editor) -> @emit 'editor-created', editor - # Public: Invoke the given callback when a pane is added to the workspace. + ### + Section: Event Subscription + ### + + # Extended: Invoke the given callback when a pane is added to the workspace. # # * `callback` {Function} to be called panes are added. # * `event` {Object} with the following keys: @@ -99,7 +92,7 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddPane: (callback) -> @paneContainer.onDidAddPane(callback) - # Public: Invoke the given callback with all current and future panes in the + # Extended: Invoke the given callback with all current and future panes in the # workspace. # # * `callback` {Function} to be called with current and future panes. @@ -107,7 +100,7 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observePanes: (callback) -> @paneContainer.observePanes(callback) - # Public: Invoke the given callback when a pane item is added to the + # Extended: Invoke the given callback when a pane item is added to the # workspace. # # * `callback` {Function} to be called panes are added. @@ -119,7 +112,7 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddPaneItem: (callback) -> @paneContainer.onDidAddPaneItem(callback) - # Public: Invoke the given callback with all current and future panes items in + # Extended: Invoke the given callback with all current and future panes items in # the workspace. # # * `callback` {Function} to be called with current and future pane items. @@ -127,7 +120,7 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observePaneItems: (callback) -> @paneContainer.observePaneItems(callback) - # Public: Invoke the given callback when a text editor is added to the + # Extended: Invoke the given callback when a text editor is added to the # workspace. # # * `callback` {Function} to be called panes are added. @@ -142,8 +135,8 @@ class Workspace extends Model @onDidAddPaneItem ({item, pane, index}) -> callback({textEditor: item, pane, index}) if item instanceof Editor - # Public: Invoke the given callback with all current and future text editors - # in the workspace. + # Essential: Invoke the given callback with all current and future text + # editors in the workspace. # # * `callback` {Function} to be called with current and future text editors. # @@ -173,13 +166,11 @@ class Workspace extends Model editors - # Public: Get all text editors in the workspace. - # - # Returns an {Array} of {Editor}s. - getTextEditors: -> - @getPaneItems().filter (item) -> item instanceof Editor + ### + Section: Opening + ### - # Public: Open a given a URI in Atom asynchronously. + # Essential: Open a given a URI in Atom asynchronously. # # * `uri` A {String} containing a URI. # * `options` (optional) {Object} @@ -269,7 +260,7 @@ class Workspace extends Model .catch (error) -> console.error(error.stack ? error) - # Public: Asynchronously reopens the last-closed item's URI if it hasn't already been + # Extended: Asynchronously reopens the last-closed item's URI if it hasn't already been # reopened. # # Returns a promise that is resolved when the item is opened @@ -285,7 +276,7 @@ class Workspace extends Model if uri = @destroyedItemUris.pop() @openSync(uri) - # Public: Register an opener for a uri. + # Extended: Register an opener for a uri. # # An {Editor} will be used if no openers return a value. # @@ -301,64 +292,52 @@ class Workspace extends Model registerOpener: (opener) -> @openers.push(opener) - # Public: Unregister an opener registered with {::registerOpener}. + # Extended: Unregister an opener registered with {::registerOpener}. unregisterOpener: (opener) -> _.remove(@openers, opener) getOpeners: -> @openers - # Public: Get all panes in the workspace. - # - # Returns an {Array} of {Pane}s. - getPanes: -> - @paneContainer.getPanes() + ### + Section: Pane Items + ### - # Public: Get the active {Pane}. - # - # Returns a {Pane}. - getActivePane: -> - @paneContainer.getActivePane() - - # Public: Get all pane items in the workspace. + # Essential: Get all pane items in the workspace. # # Returns an {Array} of items. getPaneItems: -> @paneContainer.getPaneItems() - # Public: Get the active {Pane}'s active item. + # Essential: Get the active {Pane}'s active item. # # Returns an pane item {Object}. getActivePaneItem: -> @paneContainer.getActivePaneItem() - # Public: Get all {Pane}s. + # Essential: Get all text editors in the workspace. # - # Returns an {Array} of {Pane}s. - getPanes: -> - @paneContainer.getPanes() + # Returns an {Array} of {Editor}s. + getTextEditors: -> + @getPaneItems().filter (item) -> item instanceof Editor - # Public: Save all pane items. + # Essential: Get the active item if it is an {Editor}. + # + # Returns an {Editor} or `undefined` if the current active item is not an + # {Editor}. + getActiveTextEditor: -> + activeItem = @getActiveItem() + activeItem if activeItem instanceof Editor + + # Deprecated: + getActiveEditor: -> + @activePane?.getActiveEditor() + + # Extended: Save all pane items. saveAll: -> @paneContainer.saveAll() - # Public: Make the next pane active. - activateNextPane: -> - @paneContainer.activateNextPane() - - # Public: Make the previous pane active. - activatePreviousPane: -> - @paneContainer.activatePreviousPane() - - # Public: Get the first pane {Pane} with an item for the given URI. - # - # * `uri` {String} uri - # - # Returns a {Pane} or `undefined` if no pane exists for the given URI. - paneForUri: (uri) -> - @paneContainer.paneForUri(uri) - - # Public: Save the active pane item. + # Save the active pane item. # # If the active pane item currently has a URI according to the item's # `.getUri` method, calls `.save` on the item. Otherwise @@ -367,7 +346,7 @@ class Workspace extends Model saveActivePaneItem: -> @activePane?.saveActiveItem() - # Public: Prompt the user for a path and save the active pane item to it. + # Prompt the user for a path and save the active pane item to it. # # Opens a native dialog where the user selects a path on disk, then calls # `.saveAs` on the item with the selected path. This method does nothing if @@ -375,34 +354,59 @@ class Workspace extends Model saveActivePaneItemAs: -> @activePane?.saveActiveItemAs() - # Public: Destroy (close) the active pane item. + # Destroy (close) the active pane item. # # Removes the active pane item and calls the `.destroy` method on it if one is # defined. destroyActivePaneItem: -> @activePane?.destroyActiveItem() - # Public: Destroy (close) the active pane. + ### + Section: Panes + ### + + # Extended: Get all panes in the workspace. + # + # Returns an {Array} of {Pane}s. + getPanes: -> + @paneContainer.getPanes() + + # Extended: Get the active {Pane}. + # + # Returns a {Pane}. + getActivePane: -> + @paneContainer.getActivePane() + + # Extended: Make the next pane active. + activateNextPane: -> + @paneContainer.activateNextPane() + + # Extended: Make the previous pane active. + activatePreviousPane: -> + @paneContainer.activatePreviousPane() + + # Extended: Get the first pane {Pane} with an item for the given URI. + # + # * `uri` {String} uri + # + # Returns a {Pane} or `undefined` if no pane exists for the given URI. + paneForUri: (uri) -> + @paneContainer.paneForUri(uri) + + # Destroy (close) the active pane. destroyActivePane: -> @activePane?.destroy() - # Public: Get the active item if it is an {Editor}. - # - # Returns an {Editor} or `undefined` if the current active item is not an - # {Editor}. - getActiveEditor: -> - @activePane?.getActiveEditor() - - # Public: Increase the editor font size by 1px. + # Increase the editor font size by 1px. increaseFontSize: -> atom.config.set("editor.fontSize", atom.config.get("editor.fontSize") + 1) - # Public: Decrease the editor font size by 1px. + # Decrease the editor font size by 1px. decreaseFontSize: -> fontSize = atom.config.get("editor.fontSize") atom.config.set("editor.fontSize", fontSize - 1) if fontSize > 1 - # Public: Restore to a default editor font size. + # Restore to a default editor font size. resetFontSize: -> atom.config.restoreDefault("editor.fontSize") From 8c36d2673b1e80d84ecf5884f0a6c07723ff6511 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Sat, 30 Aug 2014 20:20:09 +0200 Subject: [PATCH 051/355] Select row when clicking the gutter --- spec/editor-component-spec.coffee | 4 ++-- src/editor-component.coffee | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index d80396d23..5b30bdbdf 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -1331,9 +1331,9 @@ describe "EditorComponent", -> gutterNode = componentNode.querySelector('.gutter') describe "when the gutter is clicked", -> - it "moves the cursor to the beginning of the clicked row", -> + it "selects the clicked row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(4))) - expect(editor.getCursorScreenPosition()).toEqual [4, 0] + expect(editor.getSelectedScreenRange()).toEqual [[4, 0], [5, 0]] describe "when the gutter is shift-clicked", -> beforeEach -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index b14a169b8..17c0f831c 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -649,7 +649,7 @@ EditorComponent = React.createClass {editor} = @props clickedRow = @screenPositionForMouseEvent(event).row - editor.setCursorScreenPosition([clickedRow, 0]) + editor.setSelectedScreenRange([[clickedRow, 0], [clickedRow + 1, 0]]) @handleDragUntilMouseUp event, (screenPosition) -> dragRow = screenPosition.row From 7f14965ca829323c8bdd9a3d31b0ecd4b0199497 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Sun, 31 Aug 2014 21:39:16 +0200 Subject: [PATCH 052/355] Support selecting multiple rows with meta-click --- spec/editor-component-spec.coffee | 44 +++++++++++++++++++++++++++++++ src/editor-component.coffee | 31 +++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 5b30bdbdf..411b39241 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -1335,6 +1335,16 @@ describe "EditorComponent", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(4))) expect(editor.getSelectedScreenRange()).toEqual [[4, 0], [5, 0]] + describe "when the gutter is meta-clicked", -> + it "creates a new selection for the clicked row", -> + editor.setSelectedScreenRange([[3, 0], [3, 2]]) + + gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(4), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[3, 0], [3, 2]], [[4, 0], [5, 0]]] + + gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[3, 0], [3, 2]], [[4, 0], [5, 0]], [[6, 0], [7, 0]]] + describe "when the gutter is shift-clicked", -> beforeEach -> editor.setSelectedScreenRange([[3, 4], [4, 5]]) @@ -1366,6 +1376,40 @@ describe "EditorComponent", -> gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(2))) expect(editor.getSelectedScreenRange()).toEqual [[2, 0], [7, 0]] + describe "when the gutter is meta-clicked and dragged", -> + beforeEach -> + editor.setSelectedScreenRange([[3, 0], [3, 2]]) + + describe "when dragging downward", -> + it "selects the rows between the start and end of the drag", -> + gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(4), metaKey: true)) + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + nextAnimationFrame() + gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[3, 0], [3, 2]], [[4, 0], [7, 0]]] + + it "merges overlapping selections", -> + gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(2), metaKey: true)) + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + nextAnimationFrame() + gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[2, 0], [7, 0]]] + + describe "when dragging upward", -> + it "selects the rows between the start and end of the drag", -> + gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(4), metaKey: true)) + nextAnimationFrame() + gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(4), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[3, 0], [3, 2]], [[4, 0], [7, 0]]] + + it "merges overlapping selections", -> + gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(6), metaKey: true)) + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(2), metaKey: true)) + nextAnimationFrame() + gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(2), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[2, 0], [7, 0]]] + describe "when the gutter is shift-clicked and dragged", -> describe "when the shift-click is below the existing selection's tail", -> describe "when dragging downward", -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 17c0f831c..003e9b703 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -1,3 +1,4 @@ +_ = require 'underscore-plus' React = require 'react-atom-fork' {div, span} = require 'reactionary-atom-fork' {debounce, defaults, isEqualForProperties} = require 'underscore-plus' @@ -640,8 +641,12 @@ EditorComponent = React.createClass onGutterMouseDown: (event) -> return unless event.button is 0 # only handle the left mouse button - if event.shiftKey + {shiftKey, metaKey, ctrlKey} = event + + if shiftKey @onGutterShiftClick(event) + else if metaKey or (ctrlKey and process.platform isnt 'darwin') + @onGutterMetaClick(event) else @onGutterClick(event) @@ -658,6 +663,30 @@ EditorComponent = React.createClass else editor.setSelectedScreenRange([[clickedRow, 0], [dragRow + 1, 0]]) + onGutterMetaClick: (event) -> + {editor} = @props + clickedRow = @screenPositionForMouseEvent(event).row + + bufferRange = editor.bufferRangeForScreenRange([[clickedRow, 0], [clickedRow + 1, 0]]) + rowSelection = editor.addSelectionForBufferRange(bufferRange) + + @handleDragUntilMouseUp event, (screenPosition) -> + dragRow = screenPosition.row + + if dragRow < clickedRow # dragging up + rowSelection.setScreenRange([[dragRow, 0], [clickedRow + 1, 0]]) + else + rowSelection.setScreenRange([[clickedRow, 0], [dragRow + 1, 0]]) + + # After updating the selected screen range, merge overlapping selections + editor.mergeIntersectingSelections() + + # The merge process will possibly destroy the current selection because + # it will be merged into another one. Therefore, we need to obtain a + # reference to the new selection that contains the originally selected row + rowSelection = _.find editor.getSelections(), (selection) -> + selection.intersectsBufferRange(bufferRange) + onGutterShiftClick: (event) -> {editor} = @props clickedRow = @screenPositionForMouseEvent(event).row From 65cae0f68d4e6c5c69c28b71eed6647c27f75722 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Mon, 1 Sep 2014 18:24:04 +0200 Subject: [PATCH 053/355] Fix indentation to make coffeelint happy --- src/editor-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 003e9b703..52ca61bc6 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -685,7 +685,7 @@ EditorComponent = React.createClass # it will be merged into another one. Therefore, we need to obtain a # reference to the new selection that contains the originally selected row rowSelection = _.find editor.getSelections(), (selection) -> - selection.intersectsBufferRange(bufferRange) + selection.intersectsBufferRange(bufferRange) onGutterShiftClick: (event) -> {editor} = @props From 29ad748aa4fbd9365050a16b2998c5140f19f3cd Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Wed, 3 Sep 2014 18:52:50 +0200 Subject: [PATCH 054/355] Dont propagate fold icon clicks to editor component --- src/gutter-component.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/gutter-component.coffee b/src/gutter-component.coffee index e9eeddaf9..c6cf62490 100644 --- a/src/gutter-component.coffee +++ b/src/gutter-component.coffee @@ -21,7 +21,7 @@ GutterComponent = React.createClass if gutterBackgroundColor isnt 'rbga(0, 0, 0, 0)' backgroundColor = gutterBackgroundColor - div className: 'gutter', onClick: @onClick, onMouseDown: onMouseDown, + div className: 'gutter', onClick: @onClick, onMouseDown: @onMouseDown, div className: 'line-numbers', ref: 'lineNumbers', style: height: Math.max(scrollHeight, scrollViewHeight) WebkitTransform: @getTransform() @@ -215,6 +215,14 @@ GutterComponent = React.createClass lineNumberNodeForScreenRow: (screenRow) -> @lineNumberNodesById[@lineNumberIdsByScreenRow[screenRow]] + onMouseDown: (event) -> + {editor} = @props + {target} = event + lineNumber = target.parentNode + + unless target.classList.contains('icon-right') and lineNumber.classList.contains('foldable') + @props.onMouseDown(event) + onClick: (event) -> {editor} = @props {target} = event From ebbfaa23ce9267528f6bed802920517ee2c9b42d Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Wed, 3 Sep 2014 18:54:46 +0200 Subject: [PATCH 055/355] Preserve folds when selecting rows by clicking the gutter --- src/editor-component.coffee | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 52ca61bc6..cc248c69a 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -654,32 +654,32 @@ EditorComponent = React.createClass {editor} = @props clickedRow = @screenPositionForMouseEvent(event).row - editor.setSelectedScreenRange([[clickedRow, 0], [clickedRow + 1, 0]]) + editor.setSelectedScreenRange([[clickedRow, 0], [clickedRow + 1, 0]], preserveFolds: true) @handleDragUntilMouseUp event, (screenPosition) -> dragRow = screenPosition.row if dragRow < clickedRow # dragging up - editor.setSelectedScreenRange([[dragRow, 0], [clickedRow + 1, 0]]) + editor.setSelectedScreenRange([[dragRow, 0], [clickedRow + 1, 0]], preserveFolds: true) else - editor.setSelectedScreenRange([[clickedRow, 0], [dragRow + 1, 0]]) + editor.setSelectedScreenRange([[clickedRow, 0], [dragRow + 1, 0]], preserveFolds: true) onGutterMetaClick: (event) -> {editor} = @props clickedRow = @screenPositionForMouseEvent(event).row bufferRange = editor.bufferRangeForScreenRange([[clickedRow, 0], [clickedRow + 1, 0]]) - rowSelection = editor.addSelectionForBufferRange(bufferRange) + rowSelection = editor.addSelectionForBufferRange(bufferRange, preserveFolds: true) @handleDragUntilMouseUp event, (screenPosition) -> dragRow = screenPosition.row if dragRow < clickedRow # dragging up - rowSelection.setScreenRange([[dragRow, 0], [clickedRow + 1, 0]]) + rowSelection.setScreenRange([[dragRow, 0], [clickedRow + 1, 0]], preserveFolds: true) else - rowSelection.setScreenRange([[clickedRow, 0], [dragRow + 1, 0]]) + rowSelection.setScreenRange([[clickedRow, 0], [dragRow + 1, 0]], preserveFolds: true) # After updating the selected screen range, merge overlapping selections - editor.mergeIntersectingSelections() + editor.mergeIntersectingSelections(preserveFolds: true) # The merge process will possibly destroy the current selection because # it will be merged into another one. Therefore, we need to obtain a @@ -700,9 +700,9 @@ EditorComponent = React.createClass @handleDragUntilMouseUp event, (screenPosition) -> dragRow = screenPosition.row if dragRow < tailPosition.row # dragging up - editor.setSelectedScreenRange([[dragRow, 0], tailPosition]) + editor.setSelectedScreenRange([[dragRow, 0], tailPosition], preserveFolds: true) else - editor.setSelectedScreenRange([tailPosition, [dragRow + 1, 0]]) + editor.setSelectedScreenRange([tailPosition, [dragRow + 1, 0]], preserveFolds: true) onStylesheetsChanged: (stylesheet) -> return unless @performedInitialMeasurement From 873818ee52c0be8f898e1b62970e4499c7fe102d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:19:21 -0600 Subject: [PATCH 056/355] Deprecate string-based event subscriptions --- src/pane.coffee | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/pane.coffee b/src/pane.coffee index 55c1c182a..34ef6f5f4 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -2,6 +2,7 @@ {Model} = require 'theorist' {Emitter} = require 'event-kit' Serializable = require 'serializable' +Grim = require 'grim' PaneAxis = require './pane-axis' Editor = require './editor' PaneView = null @@ -188,6 +189,24 @@ class Pane extends Model onWillDestroyItem: (callback) -> @emitter.on 'will-destroy-item', callback + on: (eventName) -> + switch eventName + when 'activated' + Grim.deprecate("Use Pane::onDidActivate instead") + when 'destroyed' + Grim.deprecate("Use Pane::onDidDestroy instead") + when 'item-added' + Grim.deprecate("Use Pane::onDidAddItem instead") + when 'item-removed' + Grim.deprecate("Use Pane::onDidRemoveItem instead") + when 'item-moved' + Grim.deprecate("Use Pane::onDidMoveItem instead") + when 'before-item-destroyed' + Grim.deprecate("Use Pane::onWillDestroyItem instead") + else + Grim.deprecate("Subscribing via ::on is deprecated. Use event subscription methods instead.") + super + # Called by the view layer to indicate that the pane has gained focus. focus: -> @focused = true From 87fb0b46f75920469aa11f7cbda0a56b66017c8b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:31:14 -0600 Subject: [PATCH 057/355] Deprecate theorist-provided behaviors in Pane --- src/pane.coffee | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/pane.coffee b/src/pane.coffee index 34ef6f5f4..62efffaee 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -207,6 +207,21 @@ class Pane extends Model Grim.deprecate("Subscribing via ::on is deprecated. Use event subscription methods instead.") super + behavior: (behaviorName) -> + switch behaviorName + when 'active' + Grim.deprecate("The $active behavior property is deprecated. Use ::observeActive or ::onDidChangeActive instead.") + when 'container' + Grim.deprecate("The $container behavior property is deprecated.") + when 'activeItem' + Grim.deprecate("The $activeItem behavior property is deprecated. Use ::observeActiveItem or ::onDidChangeActiveItem instead.") + when 'focused' + Grim.deprecate("The $focused behavior property is deprecated.") + else + Grim.deprecate("Pane::behavior is deprecated. Use event subscription methods instead.") + + super + # Called by the view layer to indicate that the pane has gained focus. focus: -> @focused = true From 7ad992e52f70bd38ef51fdac8526f4afbb69c8a3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:35:46 -0600 Subject: [PATCH 058/355] :lipstick: --- src/pane.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pane.coffee b/src/pane.coffee index 62efffaee..ebc91caa0 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -204,7 +204,7 @@ class Pane extends Model when 'before-item-destroyed' Grim.deprecate("Use Pane::onWillDestroyItem instead") else - Grim.deprecate("Subscribing via ::on is deprecated. Use event subscription methods instead.") + Grim.deprecate("Subscribing via ::on is deprecated. Use documented event subscription methods instead.") super behavior: (behaviorName) -> From a8c1f2d0a5e072774bbdc09365e7214013a29e88 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:35:54 -0600 Subject: [PATCH 059/355] Deprecate Workspace methods --- src/workspace.coffee | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/workspace.coffee b/src/workspace.coffee index 65f1b1ddc..664dbb28b 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -153,6 +153,8 @@ class Workspace extends Model # Returns a subscription object with an `.off` method that you can call to # unregister the callback. eachEditor: (callback) -> + deprecate("Use Workspace::observeTextEditors instead") + callback(editor) for editor in @getEditors() @subscribe this, 'editor-created', (editor) -> callback(editor) @@ -160,12 +162,25 @@ class Workspace extends Model # # Returns an {Array} of {Editor}s. getEditors: -> + deprecate("Use Workspace::getTextEditors instead") + editors = [] for pane in @paneContainer.getPanes() editors.push(item) for item in pane.getItems() when item instanceof Editor editors + on: (eventName) -> + switch eventName + when 'editor-created' + deprecate("Use Workspace::onDidAddTextEditor or Workspace::observeTextEditors instead.") + when 'uri-opened' + deprecate("Use Workspace::onDidAddPaneItem instead.") + else + deprecate("Subscribing via ::on is deprecated. Use documented event subscription methods instead.") + + super + ### Section: Opening ### From c508f76af05896d37dc24ca52cf012707dc2970a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:40:18 -0600 Subject: [PATCH 060/355] Upgrade event-kit for deprecated .off on subscriptions --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 971f7e9f3..a5ca6245b 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.0", - "event-kit": "0.3.0", + "event-kit": "0.4.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", From 67dc703c185b3ea7edf93dedba5d496604bc834c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:46:53 -0600 Subject: [PATCH 061/355] :lipstick: docs --- src/pane.coffee | 7 +++++-- src/workspace.coffee | 16 ++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/pane.coffee b/src/pane.coffee index ebc91caa0..d56ae007b 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -84,6 +84,8 @@ class Pane extends Model # Public: Invoke the given callback when the pane is destroyed. # # * `callback` {Function} to be called when the pane is destroyed. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback @@ -148,6 +150,8 @@ class Pane extends Model # Public: Invoke the given callback with all current and future items. # # * `callback` {Function} to be called with current and future items. + # * `item` An item that is present in {::getItems} at the time of + # subscription or that is added at some later time. # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observeItems: (callback) -> @@ -157,8 +161,7 @@ class Pane extends Model # Public: Invoke the given callback when the value of {::getActiveItem} # changes. # - # * `callback` {Function} to be called with when the active item - # changes. + # * `callback` {Function} to be called with when the active item changes. # * `activeItem` The current active item. # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. diff --git a/src/workspace.coffee b/src/workspace.coffee index 664dbb28b..6f2003e8e 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -96,6 +96,8 @@ class Workspace extends Model # workspace. # # * `callback` {Function} to be called with current and future panes. + # * `pane` A {Pane} that is present in {::getPanes} at the time of + # subscription or that is added at some later time. # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observePanes: (callback) -> @paneContainer.observePanes(callback) @@ -116,6 +118,8 @@ class Workspace extends Model # the workspace. # # * `callback` {Function} to be called with current and future pane items. + # * `item` An item that is present in {::getPaneItems} at the time of + # subscription or that is added at some later time. # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observePaneItems: (callback) -> @paneContainer.observePaneItems(callback) @@ -139,28 +143,20 @@ class Workspace extends Model # editors in the workspace. # # * `callback` {Function} to be called with current and future text editors. + # * `editor` An {Editor} that is present in {::getTextEditors} at the time + # of subscription or that is added at some later time. # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observeTextEditors: (callback) -> callback(textEditor) for textEditor in @getTextEditors() @onDidAddTextEditor ({textEditor}) -> callback(textEditor) - # Deprecated: Register a function to be called for every current and future - # {Editor} in the workspace. - # - # * `callback` A {Function} with an {Editor} as its only argument. - # - # Returns a subscription object with an `.off` method that you can call to - # unregister the callback. eachEditor: (callback) -> deprecate("Use Workspace::observeTextEditors instead") callback(editor) for editor in @getEditors() @subscribe this, 'editor-created', (editor) -> callback(editor) - # Deprecated: Get all current editors in the workspace. - # - # Returns an {Array} of {Editor}s. getEditors: -> deprecate("Use Workspace::getTextEditors instead") From f87f7c358a54f65e8479013062a4405679f50d34 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 17:08:13 -0600 Subject: [PATCH 062/355] Kill a couple deprecation errors --- src/workspace-view.coffee | 2 +- src/workspace.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 9da0d7b90..74b05def1 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -84,7 +84,7 @@ class WorkspaceView extends View @panes.replaceWith(panes) @panes = panes - @subscribe @model, 'uri-opened', => @trigger 'uri-opened' + @subscribe @model.onDidAddPaneItem => @trigger 'uri-opened' @subscribe scrollbarStyle, (style) => @removeClass('scrollbars-visible-always scrollbars-visible-when-scrolling') diff --git a/src/workspace.coffee b/src/workspace.coffee index 6f2003e8e..e8de5eeb0 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -73,7 +73,7 @@ class Workspace extends Model for scopeName in includedGrammarScopes ? [] addGrammar(atom.syntax.grammarForScopeName(scopeName)) - addGrammar(editor.getGrammar()) for editor in @getEditors() + addGrammar(editor.getGrammar()) for editor in @getTextEditors() _.uniq(packageNames) editorAdded: (editor) -> From 3a85148f690be9a0217ac0954496b2952e29897e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:28:32 -0700 Subject: [PATCH 063/355] Fix doc strings --- src/cursor.coffee | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index f86721d6d..0b449eaa1 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -225,6 +225,11 @@ class Cursor extends Model @editor.lineTextForBufferRow(@getBufferRow()) # Public: Moves the cursor up one screen row. + # + # * `rowCount` (optional) {Number} number of rows to move (default: 1) + # * `options` (optional) {Object} with the following keys: + # * `moveToEndOfSelection` if true, move to the left of the selection if a + # selection exists. moveUp: (rowCount=1, {moveToEndOfSelection}={}) -> range = @marker.getScreenRange() if moveToEndOfSelection and not range.isEmpty() @@ -237,7 +242,12 @@ class Cursor extends Model @goalColumn = column # Public: Moves the cursor down one screen row. - moveDown: (rowCount = 1, {moveToEndOfSelection}={}) -> + # + # * `rowCount` (optional) {Number} number of rows to move (default: 1) + # * `options` (optional) {Object} with the following keys: + # * `moveToEndOfSelection` if true, move to the left of the selection if a + # selection exists. + moveDown: (rowCount=1, {moveToEndOfSelection}={}) -> range = @marker.getScreenRange() if moveToEndOfSelection and not range.isEmpty() { row, column } = range.end From 851034c8d3b1d831606efa4d1206faa51f7c4f6c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:29:05 -0700 Subject: [PATCH 064/355] Failing test --- spec/editor-spec.coffee | 5 +++++ src/cursor.coffee | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 36eb57bee..a97a5d2dd 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -321,6 +321,11 @@ describe "Editor", -> editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual [1, 7] + it "moves the cursor by n columns to the left", -> + editor.setCursorScreenPosition([1, 8]) + editor.moveLeft(4) + expect(editor.getCursorScreenPosition()).toEqual [1, 4] + describe "when the cursor is in the first column", -> describe "when there is a previous line", -> it "wraps to the end of the previous line", -> diff --git a/src/cursor.coffee b/src/cursor.coffee index 0b449eaa1..23343fc3d 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -260,10 +260,11 @@ class Cursor extends Model # Public: Moves the cursor left one screen column. # + # * `columnCount` (optional) {Number} number of rows to move (default: 1) # * `options` (optional) {Object} with the following keys: # * `moveToEndOfSelection` if true, move to the left of the selection if a # selection exists. - moveLeft: ({moveToEndOfSelection}={}) -> + moveLeft: (columnCount=1, {moveToEndOfSelection}={}) -> range = @marker.getScreenRange() if moveToEndOfSelection and not range.isEmpty() @setScreenPosition(range.start) From 99c07decf2d9444df659cc2f2f5dc7289ed3257c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:29:30 -0700 Subject: [PATCH 065/355] Add `columnCount` var to Editor::moveLeft and Cursor::moveLeft --- spec/editor-spec.coffee | 10 ++++++++++ src/cursor.coffee | 9 ++++++++- src/editor.coffee | 4 ++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index a97a5d2dd..053a81573 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -333,12 +333,22 @@ describe "Editor", -> editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: buffer.lineForRow(0).length) + it "moves the cursor by n columns to the left", -> + editor.setCursorScreenPosition([1, 0]) + editor.moveLeft(4) + expect(editor.getCursorScreenPosition()).toEqual [0, 26] + describe "when the cursor is on the first line", -> it "remains in the same position (0,0)", -> editor.setCursorScreenPosition(row: 0, column: 0) editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) + it "moves the cursor by n columns to the left", -> + editor.setCursorScreenPosition([0, 0]) + editor.moveLeft(4) + expect(editor.getCursorScreenPosition()).toEqual [0, 0] + describe "when softTabs is enabled and the cursor is preceded by leading whitespace", -> it "skips tabLength worth of whitespace at a time", -> editor.setCursorBufferPosition([5, 6]) diff --git a/src/cursor.coffee b/src/cursor.coffee index 23343fc3d..b2c00ce71 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -270,7 +270,14 @@ class Cursor extends Model @setScreenPosition(range.start) else {row, column} = @getScreenPosition() - [row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity] + newColumn = column - columnCount + + if newColumn >= 0 + column = newColumn + else if row > 0 + row-- + column = @editor.lineTextForScreenRow(row).length + newColumn + 1 + @setScreenPosition({row, column}) # Public: Moves the cursor right one screen column. diff --git a/src/editor.coffee b/src/editor.coffee index 337b5da9d..0b3227507 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1636,8 +1636,8 @@ class Editor extends Model @moveDown(lineCount) # Essential: Move every cursor left one column. - moveLeft: -> - @moveCursors (cursor) -> cursor.moveLeft(moveToEndOfSelection: true) + moveLeft: (columnCount) -> + @moveCursors (cursor) -> cursor.moveLeft(columnCount, moveToEndOfSelection: true) moveCursorLeft: -> deprecate("Use Editor::moveLeft() instead") @moveLeft() From 29f15d0f2079d624445a92d8a0dc83d03d60c8bd Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 15:27:42 -0700 Subject: [PATCH 066/355] Make moveLeft() with huge values span multiple rows --- spec/editor-spec.coffee | 14 ++++++++++++-- src/cursor.coffee | 11 ++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 053a81573..f243b67c7 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -326,6 +326,16 @@ describe "Editor", -> editor.moveLeft(4) expect(editor.getCursorScreenPosition()).toEqual [1, 4] + it "moves the cursor by two rows up when the columnCount is longer than an entire line", -> + editor.setCursorScreenPosition([2, 2]) + editor.moveLeft(34) + expect(editor.getCursorScreenPosition()).toEqual [0, 28] + + it "moves the cursor to the beginning columnCount is longer than the position in the buffer", -> + editor.setCursorScreenPosition([1, 0]) + editor.moveLeft(100) + expect(editor.getCursorScreenPosition()).toEqual [0, 0] + describe "when the cursor is in the first column", -> describe "when there is a previous line", -> it "wraps to the end of the previous line", -> @@ -333,7 +343,7 @@ describe "Editor", -> editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: buffer.lineForRow(0).length) - it "moves the cursor by n columns to the left", -> + it "moves the cursor by one row up columns to the left", -> editor.setCursorScreenPosition([1, 0]) editor.moveLeft(4) expect(editor.getCursorScreenPosition()).toEqual [0, 26] @@ -344,7 +354,7 @@ describe "Editor", -> editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - it "moves the cursor by n columns to the left", -> + it "remains in the same position (0,0) when columnCount is specified", -> editor.setCursorScreenPosition([0, 0]) editor.moveLeft(4) expect(editor.getCursorScreenPosition()).toEqual [0, 0] diff --git a/src/cursor.coffee b/src/cursor.coffee index b2c00ce71..70f0938d8 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -274,9 +274,14 @@ class Cursor extends Model if newColumn >= 0 column = newColumn - else if row > 0 - row-- - column = @editor.lineTextForScreenRow(row).length + newColumn + 1 + else + columnDelta = -(newColumn + 1) + while columnDelta >= 0 and row > 0 + row-- + rowLength = @editor.lineTextForScreenRow(row).length + column = rowLength - columnDelta + columnDelta -= rowLength + column = Math.max(column, 0) @setScreenPosition({row, column}) From f82c59d865ac0412f814ba6c1c58057f59a3bfb8 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 15:54:46 -0700 Subject: [PATCH 067/355] Add columnCount to moveRight --- spec/editor-spec.coffee | 22 +++++++++++++++++++++- src/cursor.coffee | 18 ++++++++++++++++-- src/editor.coffee | 4 ++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index f243b67c7..c2ca4c01a 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -343,7 +343,7 @@ describe "Editor", -> editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: buffer.lineForRow(0).length) - it "moves the cursor by one row up columns to the left", -> + it "moves the cursor by one row up and n columns to the left", -> editor.setCursorScreenPosition([1, 0]) editor.moveLeft(4) expect(editor.getCursorScreenPosition()).toEqual [0, 26] @@ -393,6 +393,21 @@ describe "Editor", -> editor.moveRight() expect(editor.getCursorScreenPosition()).toEqual [3, 4] + it "moves the cursor by n columns to the right", -> + editor.setCursorScreenPosition([3, 7]) + editor.moveRight(4) + expect(editor.getCursorScreenPosition()).toEqual [3, 11] + + it "moves the cursor by two rows down when the columnCount is longer than an entire line", -> + editor.setCursorScreenPosition([0, 28]) + editor.moveRight(32) + expect(editor.getCursorScreenPosition()).toEqual [2, 0] + + it "moves the cursor to the end of the buffer when columnCount is longer than the number of characters following the cursor position", -> + editor.setCursorScreenPosition([11, 5]) + editor.moveRight(100) + expect(editor.getCursorScreenPosition()).toEqual [12, 2] + describe "when the cursor is on the last column of a line", -> describe "when there is a subsequent line", -> it "wraps to the beginning of the next line", -> @@ -400,6 +415,11 @@ describe "Editor", -> editor.moveRight() expect(editor.getCursorScreenPosition()).toEqual [1, 0] + it "moves the cursor by one row down and n columns to the right", -> + editor.setCursorScreenPosition([0, buffer.lineForRow(0).length]) + editor.moveRight(4) + expect(editor.getCursorScreenPosition()).toEqual [1, 3] + describe "when the cursor is on the last line", -> it "remains in the same position", -> lastLineIndex = buffer.getLines().length - 1 diff --git a/src/cursor.coffee b/src/cursor.coffee index 70f0938d8..4a7c37692 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -290,13 +290,27 @@ class Cursor extends Model # * `options` (optional) {Object} with the following keys: # * `moveToEndOfSelection` if true, move to the right of the selection if a # selection exists. - moveRight: ({moveToEndOfSelection}={}) -> + moveRight: (columnCount=1, {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) + newColumn = column + columnCount + rowLength = @editor.lineTextForScreenRow(row).length + + if newColumn <= rowLength + column = newColumn + else + columnDelta = newColumn - rowLength - 1 + maxLines = @editor.getScreenLineCount() + while columnDelta >= 0 and row < maxLines - 1 + row++ + rowLength = @editor.lineTextForScreenRow(row).length + column = columnDelta + columnDelta -= rowLength + + @setScreenPosition({row, column}, skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true) # Public: Moves the cursor to the top of the buffer. moveToTop: -> diff --git a/src/editor.coffee b/src/editor.coffee index 0b3227507..7e4184466 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1643,8 +1643,8 @@ class Editor extends Model @moveLeft() # Essential: Move every cursor right one column. - moveRight: -> - @moveCursors (cursor) -> cursor.moveRight(moveToEndOfSelection: true) + moveRight: (columnCount) -> + @moveCursors (cursor) -> cursor.moveRight(columnCount, moveToEndOfSelection: true) moveCursorRight: -> deprecate("Use Editor::moveRight() instead") @moveRight() From 06165b2167fb85ce392f5a9a8aaa12c7d0608b52 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 15:55:50 -0700 Subject: [PATCH 068/355] Remove the max call --- src/cursor.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 4a7c37692..e91b8cbf1 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -281,7 +281,6 @@ class Cursor extends Model rowLength = @editor.lineTextForScreenRow(row).length column = rowLength - columnDelta columnDelta -= rowLength - column = Math.max(column, 0) @setScreenPosition({row, column}) From 7a3893c7bbbd6307ced4ffd88e9d164317fcb06f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 15:57:53 -0700 Subject: [PATCH 069/355] Update doc strings --- src/cursor.coffee | 3 ++- src/editor.coffee | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index e91b8cbf1..ed34a1336 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -260,7 +260,7 @@ class Cursor extends Model # Public: Moves the cursor left one screen column. # - # * `columnCount` (optional) {Number} number of rows to move (default: 1) + # * `columnCount` (optional) {Number} number of columns to move (default: 1) # * `options` (optional) {Object} with the following keys: # * `moveToEndOfSelection` if true, move to the left of the selection if a # selection exists. @@ -286,6 +286,7 @@ class Cursor extends Model # Public: Moves the cursor right one screen column. # + # * `columnCount` (optional) {Number} number of columns to move (default: 1) # * `options` (optional) {Object} with the following keys: # * `moveToEndOfSelection` if true, move to the right of the selection if a # selection exists. diff --git a/src/editor.coffee b/src/editor.coffee index 7e4184466..9d88d976e 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1619,7 +1619,7 @@ class Editor extends Model # Essential: Move every cursor up one row in screen coordinates. # - # * `lineCount` {Number} number of lines to move + # * `lineCount` (optional) {Number} number of lines to move moveUp: (lineCount) -> @moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true) moveCursorUp: (lineCount) -> @@ -1628,7 +1628,7 @@ class Editor extends Model # Essential: Move every cursor down one row in screen coordinates. # - # * `lineCount` {Number} number of lines to move + # * `lineCount` (optional) {Number} number of lines to move moveDown: (lineCount) -> @moveCursors (cursor) -> cursor.moveDown(lineCount, moveToEndOfSelection: true) moveCursorDown: (lineCount) -> @@ -1636,6 +1636,8 @@ class Editor extends Model @moveDown(lineCount) # Essential: Move every cursor left one column. + # + # * `columnCount` (optional) {Number} number of columns to move (default: 1) moveLeft: (columnCount) -> @moveCursors (cursor) -> cursor.moveLeft(columnCount, moveToEndOfSelection: true) moveCursorLeft: -> @@ -1643,6 +1645,8 @@ class Editor extends Model @moveLeft() # Essential: Move every cursor right one column. + # + # * `columnCount` (optional) {Number} number of columns to move (default: 1) moveRight: (columnCount) -> @moveCursors (cursor) -> cursor.moveRight(columnCount, moveToEndOfSelection: true) moveCursorRight: -> From 48b693c1c17ad5a52b515bbf2941ea8251ef87d2 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 16:20:25 -0700 Subject: [PATCH 070/355] Add columnCounts to selection methods --- spec/editor-spec.coffee | 21 +++++++++++++++++++++ src/editor.coffee | 16 ++++++++++------ src/selection.coffee | 16 ++++++++++++---- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index c2ca4c01a..e8c092ded 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -969,6 +969,27 @@ describe "Editor", -> expect(selection1.getScreenRange()).toEqual([[0, 9], [1, 21]]) expect(selection1.isReversed()).toBeFalsy() + describe "when counts are passed into the selection functions", -> + it "expands each selection to its cursor's new location", -> + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[3,16], [3,21]]]) + [selection1, selection2] = editor.getSelections() + + editor.selectRight(2) + expect(selection1.getBufferRange()).toEqual [[0,9], [0,15]] + expect(selection2.getBufferRange()).toEqual [[3,16], [3,23]] + + editor.selectLeft(3) + expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]] + expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]] + + editor.selectDown(3) + expect(selection1.getBufferRange()).toEqual [[0,9], [3,12]] + expect(selection2.getBufferRange()).toEqual [[3,16], [6,20]] + + editor.selectUp(2) + expect(selection1.getBufferRange()).toEqual [[0,9], [1,12]] + expect(selection2.getBufferRange()).toEqual [[3,16], [4,20]] + describe ".selectToBufferPosition(bufferPosition)", -> it "expands the last selection to the given position", -> editor.setSelectedBufferRange([[3, 0], [4, 5]]) diff --git a/src/editor.coffee b/src/editor.coffee index 9d88d976e..3ade2ecb9 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1982,7 +1982,7 @@ class Editor extends Model # Essential: Move the cursor of each selection one character upward while # preserving the selection's tail position. # - # * `rowCount` {Number} of rows to select up + # * `rowCount` (optional) {Number} number of rows to select (default: 1) # # This method may merge selections that end up intesecting. selectUp: (rowCount) -> @@ -1991,7 +1991,7 @@ class Editor extends Model # Essential: Move the cursor of each selection one character downward while # preserving the selection's tail position. # - # * `rowCount` {Number} of rows to select down + # * `rowCount` (optional) {Number} number of rows to select (default: 1) # # This method may merge selections that end up intesecting. selectDown: (rowCount) -> @@ -2000,16 +2000,20 @@ class Editor extends Model # Essential: Move the cursor of each selection one character leftward while # preserving the selection's tail position. # + # * `columnCount` (optional) {Number} number of columns to select (default: 1) + # # This method may merge selections that end up intesecting. - selectLeft: -> - @expandSelectionsBackward (selection) -> selection.selectLeft() + selectLeft: (columnCount) -> + @expandSelectionsBackward (selection) -> selection.selectLeft(columnCount) # Essential: Move the cursor of each selection one character rightward while # preserving the selection's tail position. # + # * `columnCount` (optional) {Number} number of columns to select (default: 1) + # # This method may merge selections that end up intesecting. - selectRight: -> - @expandSelectionsForward (selection) -> selection.selectRight() + selectRight: (columnCount) -> + @expandSelectionsForward (selection) -> selection.selectRight(columnCount) # Essential: Select from the top of the buffer to the end of the last selection # in the buffer. diff --git a/src/selection.coffee b/src/selection.coffee index a0db277c1..38198fef4 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -198,18 +198,26 @@ class Selection extends Model @modifySelection => @cursor.setBufferPosition(position) # Public: Selects the text one position right of the cursor. - selectRight: -> - @modifySelection => @cursor.moveRight() + # + # * `columnCount` (optional) {Number} number of columns to select (default: 1) + selectRight: (columnCount) -> + @modifySelection => @cursor.moveRight(columnCount) # Public: Selects the text one position left of the cursor. - selectLeft: -> - @modifySelection => @cursor.moveLeft() + # + # * `columnCount` (optional) {Number} number of columns to select (default: 1) + selectLeft: (columnCount) -> + @modifySelection => @cursor.moveLeft(columnCount) # Public: Selects all the text one position above the cursor. + # + # * `rowCount` (optional) {Number} number of rows to select (default: 1) selectUp: (rowCount) -> @modifySelection => @cursor.moveUp(rowCount) # Public: Selects all the text one position below the cursor. + # + # * `rowCount` (optional) {Number} number of rows to select (default: 1) selectDown: (rowCount) -> @modifySelection => @cursor.moveDown(rowCount) From 691c7ee585c5ee80ad135cf26916fe5fac85a406 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 17:19:06 -0700 Subject: [PATCH 071/355] Considerably more elegant (and correct) moveLeft and moveRight --- spec/editor-spec.coffee | 20 ++++++++++++++++---- src/cursor.coffee | 36 +++++++++++++++--------------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index e8c092ded..5b0af428c 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -329,7 +329,7 @@ describe "Editor", -> it "moves the cursor by two rows up when the columnCount is longer than an entire line", -> editor.setCursorScreenPosition([2, 2]) editor.moveLeft(34) - expect(editor.getCursorScreenPosition()).toEqual [0, 28] + expect(editor.getCursorScreenPosition()).toEqual [0, 29] it "moves the cursor to the beginning columnCount is longer than the position in the buffer", -> editor.setCursorScreenPosition([1, 0]) @@ -348,6 +348,12 @@ describe "Editor", -> editor.moveLeft(4) expect(editor.getCursorScreenPosition()).toEqual [0, 26] + describe "when the next line is empty", -> + it "wraps to the beginning of the previous line", -> + editor.setCursorScreenPosition([11, 0]) + editor.moveLeft() + expect(editor.getCursorScreenPosition()).toEqual [10, 0] + describe "when the cursor is on the first line", -> it "remains in the same position (0,0)", -> editor.setCursorScreenPosition(row: 0, column: 0) @@ -399,9 +405,9 @@ describe "Editor", -> expect(editor.getCursorScreenPosition()).toEqual [3, 11] it "moves the cursor by two rows down when the columnCount is longer than an entire line", -> - editor.setCursorScreenPosition([0, 28]) - editor.moveRight(32) - expect(editor.getCursorScreenPosition()).toEqual [2, 0] + editor.setCursorScreenPosition([0, 29]) + editor.moveRight(34) + expect(editor.getCursorScreenPosition()).toEqual [2, 2] it "moves the cursor to the end of the buffer when columnCount is longer than the number of characters following the cursor position", -> editor.setCursorScreenPosition([11, 5]) @@ -420,6 +426,12 @@ describe "Editor", -> editor.moveRight(4) expect(editor.getCursorScreenPosition()).toEqual [1, 3] + describe "when the next line is empty", -> + it "wraps to the beginning of the next line", -> + editor.setCursorScreenPosition([9, 4]) + editor.moveRight() + expect(editor.getCursorScreenPosition()).toEqual [10, 0] + describe "when the cursor is on the last line", -> it "remains in the same position", -> lastLineIndex = buffer.getLines().length - 1 diff --git a/src/cursor.coffee b/src/cursor.coffee index ed34a1336..68018a72c 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -270,18 +270,13 @@ class Cursor extends Model @setScreenPosition(range.start) else {row, column} = @getScreenPosition() - newColumn = column - columnCount - if newColumn >= 0 - column = newColumn - else - columnDelta = -(newColumn + 1) - while columnDelta >= 0 and row > 0 - row-- - rowLength = @editor.lineTextForScreenRow(row).length - column = rowLength - columnDelta - columnDelta -= rowLength + while columnCount > column and row > 0 + columnCount -= column + column = @editor.lineTextForScreenRow(--row).length + columnCount-- # subtract 1 for the row move + column = column - columnCount @setScreenPosition({row, column}) # Public: Moves the cursor right one screen column. @@ -296,20 +291,19 @@ class Cursor extends Model @setScreenPosition(range.end) else { row, column } = @getScreenPosition() - newColumn = column + columnCount + maxLines = @editor.getScreenLineCount() rowLength = @editor.lineTextForScreenRow(row).length + columnsRemainingInLine = rowLength - column - if newColumn <= rowLength - column = newColumn - else - columnDelta = newColumn - rowLength - 1 - maxLines = @editor.getScreenLineCount() - while columnDelta >= 0 and row < maxLines - 1 - row++ - rowLength = @editor.lineTextForScreenRow(row).length - column = columnDelta - columnDelta -= rowLength + while columnCount > columnsRemainingInLine and row < maxLines - 1 + columnCount -= columnsRemainingInLine + columnCount-- # subtract 1 for the row move + column = 0 + rowLength = @editor.lineTextForScreenRow(++row).length + columnsRemainingInLine = rowLength + + column = column + columnCount @setScreenPosition({row, column}, skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true) # Public: Moves the cursor to the top of the buffer. From 83327eeabb9d9d3d87fbd97566d5ba18bd41a62e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 19:25:40 -0600 Subject: [PATCH 072/355] =?UTF-8?q?Don=E2=80=99t=20test=20for=20editor-cre?= =?UTF-8?q?ated=20events=20when=20editor=20is=20copied?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can handle this through ::onDidAddTextEditor when the copy is added back to the pane. --- spec/workspace-spec.coffee | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 64ba379b2..79ea6c1de 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -311,20 +311,6 @@ describe "Workspace", -> editor.destroy() expect(workspace.getEditors()).toHaveLength 0 - describe "when an editor is copied", -> - it "emits an 'editor-created' event", -> - editor = null - handler = jasmine.createSpy('editorCreatedHandler') - workspace.on 'editor-created', handler - - waitsForPromise -> - workspace.open("a").then (o) -> editor = o - - runs -> - expect(handler.callCount).toBe 1 - editorCopy = editor.copy() - expect(handler.callCount).toBe 2 - it "stores the active grammars used by all the open editors", -> waitsForPromise -> atom.packages.activatePackage('language-javascript') From 22c62b3107451066e2779d2d9e93696c0ca5ff3f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 19:26:07 -0600 Subject: [PATCH 073/355] =?UTF-8?q?Replace=20=E2=80=98editor-created?= =?UTF-8?q?=E2=80=99=20event=20with=20::onDidAddTextEditor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/workspace-spec.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 79ea6c1de..1a2525646 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -203,17 +203,17 @@ describe "Workspace", -> workspace.open("bar://baz").then (item) -> expect(item).toEqual { bar: "bar://baz" } - it "emits an 'editor-created' event", -> + it "notifies ::onDidAddTextEditor observers", -> absolutePath = require.resolve('./fixtures/dir/a') newEditorHandler = jasmine.createSpy('newEditorHandler') - workspace.on 'editor-created', newEditorHandler + workspace.onDidAddTextEditor newEditorHandler editor = null waitsForPromise -> workspace.open(absolutePath).then (e) -> editor = e runs -> - expect(newEditorHandler).toHaveBeenCalledWith editor + expect(newEditorHandler.argsForCall[0][0].textEditor).toBe editor describe "::reopenItem()", -> it "opens the uri associated with the last closed pane that isn't currently open", -> From db571a2fbf333773bf78994c1a8901e75bc5db27 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 19:26:19 -0600 Subject: [PATCH 074/355] Avoid deprecation by calling ::getActivePaneItem --- docs/your-first-package.md | 4 ++-- spec/workspace-spec.coffee | 38 +++++++++++++++++----------------- src/pane-container-view.coffee | 2 +- src/workspace-view.coffee | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/your-first-package.md b/docs/your-first-package.md index 4fc41d044..e97f4e86d 100644 --- a/docs/your-first-package.md +++ b/docs/your-first-package.md @@ -53,7 +53,7 @@ module.exports = convert: -> # This assumes the active pane item is an editor - editor = atom.workspace.activePaneItem + editor = atom.workspace.getActivePaneItem() editor.insertText('Hello, World!') ``` @@ -131,7 +131,7 @@ inserting 'Hello, World!' convert the selected text to ASCII art. ```coffeescript convert: -> # This assumes the active pane item is an editor - editor = atom.workspace.activePaneItem + editor = atom.workspace.getActivePaneItem() selection = editor.getSelection() figlet = require 'figlet' diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 1a2525646..c090d5c37 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -22,7 +22,7 @@ describe "Workspace", -> runs -> expect(editor1.getPath()).toBeUndefined() expect(workspace.activePane.items).toEqual [editor1] - expect(workspace.activePaneItem).toBe editor1 + expect(workspace.getActivePaneItem()).toBe editor1 expect(workspace.activePane.activate).toHaveBeenCalled() waitsForPromise -> @@ -31,7 +31,7 @@ describe "Workspace", -> runs -> expect(editor2.getPath()).toBeUndefined() expect(workspace.activePane.items).toEqual [editor1, editor2] - expect(workspace.activePaneItem).toBe editor2 + expect(workspace.getActivePaneItem()).toBe editor2 expect(workspace.activePane.activate).toHaveBeenCalled() describe "when called with a uri", -> @@ -51,7 +51,7 @@ describe "Workspace", -> runs -> expect(editor).toBe editor1 - expect(workspace.activePaneItem).toBe editor + expect(workspace.getActivePaneItem()).toBe editor expect(workspace.activePane.activate).toHaveBeenCalled() describe "when the active pane does not have an editor for the given uri", -> @@ -62,7 +62,7 @@ describe "Workspace", -> runs -> expect(editor.getUri()).toBe atom.project.resolve('a') - expect(workspace.activePaneItem).toBe editor + expect(workspace.getActivePaneItem()).toBe editor expect(workspace.activePane.items).toEqual [editor] expect(workspace.activePane.activate).toHaveBeenCalled() @@ -83,14 +83,14 @@ describe "Workspace", -> workspace.open('b').then (o) -> editor2 = o runs -> - expect(workspace.activePaneItem).toBe editor2 + expect(workspace.getActivePaneItem()).toBe editor2 waitsForPromise -> workspace.open('a', searchAllPanes: true) runs -> expect(workspace.activePane).toBe pane1 - expect(workspace.activePaneItem).toBe editor1 + expect(workspace.getActivePaneItem()).toBe editor1 describe "when no editor for the given uri is open in any pane", -> it "opens an editor for the given uri in the active pane", -> @@ -99,7 +99,7 @@ describe "Workspace", -> workspace.open('a', searchAllPanes: true).then (o) -> editor = o runs -> - expect(workspace.activePaneItem).toBe editor + expect(workspace.getActivePaneItem()).toBe editor describe "when the 'split' option is set", -> describe "when the 'split' option is 'left'", -> @@ -226,44 +226,44 @@ describe "Workspace", -> runs -> # does not reopen items with no uri - expect(workspace.activePaneItem.getUri()).toBeUndefined() + expect(workspace.getActivePaneItem().getUri()).toBeUndefined() pane.destroyActiveItem() waitsForPromise -> workspace.reopenItem() runs -> - expect(workspace.activePaneItem.getUri()).not.toBeUndefined() + expect(workspace.getActivePaneItem().getUri()).not.toBeUndefined() # destroy all items - expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1') + expect(workspace.getActivePaneItem().getUri()).toBe atom.project.resolve('file1') pane.destroyActiveItem() - expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b') + expect(workspace.getActivePaneItem().getUri()).toBe atom.project.resolve('b') pane.destroyActiveItem() - expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a') + expect(workspace.getActivePaneItem().getUri()).toBe atom.project.resolve('a') pane.destroyActiveItem() # reopens items with uris - expect(workspace.activePaneItem).toBeUndefined() + expect(workspace.getActivePaneItem()).toBeUndefined() waitsForPromise -> workspace.reopenItem() runs -> - expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('a') + expect(workspace.getActivePaneItem().getUri()).toBe atom.project.resolve('a') # does not reopen items that are already open waitsForPromise -> workspace.open('b') runs -> - expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('b') + expect(workspace.getActivePaneItem().getUri()).toBe atom.project.resolve('b') waitsForPromise -> workspace.reopenItem() runs -> - expect(workspace.activePaneItem.getUri()).toBe atom.project.resolve('file1') + expect(workspace.getActivePaneItem().getUri()).toBe atom.project.resolve('file1') describe "::increase/decreaseFontSize()", -> it "increases/decreases the font size without going below 1", -> @@ -282,7 +282,7 @@ describe "Workspace", -> describe "::openLicense()", -> it "opens the license as plain-text in a buffer", -> waitsForPromise -> workspace.openLicense() - runs -> expect(workspace.activePaneItem.getText()).toMatch /Copyright/ + runs -> expect(workspace.getActivePaneItem().getText()).toMatch /Copyright/ describe "::observeTextEditors()", -> it "invokes the observer with current and future text editors", -> @@ -307,9 +307,9 @@ describe "Workspace", -> workspace.open("a").then (e) -> editor = e runs -> - expect(workspace.getEditors()).toHaveLength 1 + expect(workspace.getTextEditors()).toHaveLength 1 editor.destroy() - expect(workspace.getEditors()).toHaveLength 0 + expect(workspace.getTextEditors()).toHaveLength 0 it "stores the active grammars used by all the open editors", -> waitsForPromise -> diff --git a/src/pane-container-view.coffee b/src/pane-container-view.coffee index 2b3f45cca..09a890d74 100644 --- a/src/pane-container-view.coffee +++ b/src/pane-container-view.coffee @@ -91,7 +91,7 @@ class PaneContainerView extends View @viewForModel(@model.activePane) getActivePaneItem: -> - @model.activePaneItem + @model.getActivePaneItem() getActiveView: -> @getActivePaneView()?.activeView diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 74b05def1..27062e6b5 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -409,4 +409,4 @@ class WorkspaceView extends View # Deprecated: Call {Workspace::getActivePaneItem} instead. getActivePaneItem: -> deprecate("Use Workspace::getActivePaneItem instead") - @model.activePaneItem + @model.getActivePaneItem() From 0f912c97b9ccab43bf759e19e7ded53807986c56 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 19:37:42 -0600 Subject: [PATCH 075/355] Upgrade emissary to call prefer calling ::dispose in Subscriber mixin --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 66e368ee7..5a8b5c63b 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "coffee-script": "1.7.0", "coffeestack": "0.7.0", "delegato": "^1", - "emissary": "^1.3.0", + "emissary": "^1.3.1", "event-kit": "0.4.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", From 8a6e72f21f18a85745dfbe1503e5984049216417 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Thu, 4 Sep 2014 13:57:41 +0200 Subject: [PATCH 076/355] Respect preserveFolds attribute when creating selections from markers --- src/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 9753ad409..629955d3f 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1722,7 +1722,7 @@ class Editor extends Model selection = new Selection(_.extend({editor: this, marker, cursor}, options)) @selections.push(selection) selectionBufferRange = selection.getBufferRange() - @mergeIntersectingSelections() + @mergeIntersectingSelections(preserveFolds: marker.getAttributes().preserveFolds) if selection.destroyed for selection in @getSelections() if selection.intersectsBufferRange(selectionBufferRange) From 57699e62455358fa85bd8fc58f6e9a3ecf517c87 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 06:57:46 -0600 Subject: [PATCH 077/355] Use Workspace::getActivePane instead of property in spec --- spec/workspace-spec.coffee | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index c090d5c37..92d8e66c3 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -9,7 +9,7 @@ describe "Workspace", -> describe "::open(uri, options)", -> beforeEach -> - spyOn(workspace.activePane, 'activate').andCallThrough() + spyOn(workspace.getActivePane(), 'activate').andCallThrough() describe "when the 'searchAllPanes' option is false (default)", -> describe "when called without a uri", -> @@ -21,18 +21,18 @@ describe "Workspace", -> runs -> expect(editor1.getPath()).toBeUndefined() - expect(workspace.activePane.items).toEqual [editor1] + expect(workspace.getActivePane().items).toEqual [editor1] expect(workspace.getActivePaneItem()).toBe editor1 - expect(workspace.activePane.activate).toHaveBeenCalled() + expect(workspace.getActivePane().activate).toHaveBeenCalled() waitsForPromise -> workspace.open().then (editor) -> editor2 = editor runs -> expect(editor2.getPath()).toBeUndefined() - expect(workspace.activePane.items).toEqual [editor1, editor2] + expect(workspace.getActivePane().items).toEqual [editor1, editor2] expect(workspace.getActivePaneItem()).toBe editor2 - expect(workspace.activePane.activate).toHaveBeenCalled() + expect(workspace.getActivePane().activate).toHaveBeenCalled() describe "when called with a uri", -> describe "when the active pane already has an editor for the given uri", -> @@ -52,7 +52,7 @@ describe "Workspace", -> runs -> expect(editor).toBe editor1 expect(workspace.getActivePaneItem()).toBe editor - expect(workspace.activePane.activate).toHaveBeenCalled() + expect(workspace.getActivePane().activate).toHaveBeenCalled() describe "when the active pane does not have an editor for the given uri", -> it "adds and activates a new editor for the given path on the active pane", -> @@ -63,8 +63,8 @@ describe "Workspace", -> runs -> expect(editor.getUri()).toBe atom.project.resolve('a') expect(workspace.getActivePaneItem()).toBe editor - expect(workspace.activePane.items).toEqual [editor] - expect(workspace.activePane.activate).toHaveBeenCalled() + expect(workspace.getActivePane().items).toEqual [editor] + expect(workspace.getActivePane().activate).toHaveBeenCalled() describe "when the 'searchAllPanes' option is true", -> describe "when an editor for the given uri is already open on an inactive pane", -> @@ -89,7 +89,7 @@ describe "Workspace", -> workspace.open('a', searchAllPanes: true) runs -> - expect(workspace.activePane).toBe pane1 + expect(workspace.getActivePane()).toBe pane1 expect(workspace.getActivePaneItem()).toBe editor1 describe "when no editor for the given uri is open in any pane", -> @@ -104,16 +104,16 @@ describe "Workspace", -> describe "when the 'split' option is set", -> describe "when the 'split' option is 'left'", -> it "opens the editor in the leftmost pane of the current pane axis", -> - pane1 = workspace.activePane + pane1 = workspace.getActivePane() pane2 = pane1.splitRight() - expect(workspace.activePane).toBe pane2 + expect(workspace.getActivePane()).toBe pane2 editor = null waitsForPromise -> workspace.open('a', split: 'left').then (o) -> editor = o runs -> - expect(workspace.activePane).toBe pane1 + expect(workspace.getActivePane()).toBe pane1 expect(pane1.items).toEqual [editor] expect(pane2.items).toEqual [] @@ -123,37 +123,37 @@ describe "Workspace", -> workspace.open('a', split: 'left').then (o) -> editor = o runs -> - expect(workspace.activePane).toBe pane1 + expect(workspace.getActivePane()).toBe pane1 expect(pane1.items).toEqual [editor] expect(pane2.items).toEqual [] describe "when a pane axis is the leftmost sibling of the current pane", -> it "opens the new item in the current pane", -> editor = null - pane1 = workspace.activePane + pane1 = workspace.getActivePane() pane2 = pane1.splitLeft() pane3 = pane2.splitDown() pane1.activate() - expect(workspace.activePane).toBe pane1 + expect(workspace.getActivePane()).toBe pane1 waitsForPromise -> workspace.open('a', split: 'left').then (o) -> editor = o runs -> - expect(workspace.activePane).toBe pane1 + expect(workspace.getActivePane()).toBe pane1 expect(pane1.items).toEqual [editor] describe "when the 'split' option is 'right'", -> it "opens the editor in the rightmost pane of the current pane axis", -> editor = null - pane1 = workspace.activePane + pane1 = workspace.getActivePane() pane2 = null waitsForPromise -> workspace.open('a', split: 'right').then (o) -> editor = o runs -> pane2 = workspace.getPanes().filter((p) -> p != pane1)[0] - expect(workspace.activePane).toBe pane2 + expect(workspace.getActivePane()).toBe pane2 expect(pane1.items).toEqual [] expect(pane2.items).toEqual [editor] @@ -163,18 +163,18 @@ describe "Workspace", -> workspace.open('a', split: 'right').then (o) -> editor = o runs -> - expect(workspace.activePane).toBe pane2 + expect(workspace.getActivePane()).toBe pane2 expect(pane1.items).toEqual [] expect(pane2.items).toEqual [editor] describe "when a pane axis is the rightmost sibling of the current pane", -> it "opens the new item in a new pane split to the right of the current pane", -> editor = null - pane1 = workspace.activePane + pane1 = workspace.getActivePane() pane2 = pane1.splitRight() pane3 = pane2.splitDown() pane1.activate() - expect(workspace.activePane).toBe pane1 + expect(workspace.getActivePane()).toBe pane1 pane4 = null waitsForPromise -> @@ -182,7 +182,7 @@ describe "Workspace", -> runs -> pane4 = workspace.getPanes().filter((p) -> p != pane1)[0] - expect(workspace.activePane).toBe pane4 + expect(workspace.getActivePane()).toBe pane4 expect(pane4.items).toEqual [editor] expect(workspace.paneContainer.root.children[0]).toBe pane1 expect(workspace.paneContainer.root.children[1]).toBe pane4 @@ -217,7 +217,7 @@ describe "Workspace", -> describe "::reopenItem()", -> it "opens the uri associated with the last closed pane that isn't currently open", -> - pane = workspace.activePane + pane = workspace.getActivePane() waitsForPromise -> workspace.open('a').then -> workspace.open('b').then -> From 9de0ba17b2e8cf8e31bfffc394415d778df0b80a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 06:57:59 -0600 Subject: [PATCH 078/355] Add Workspace::onDidOpen event subscription method --- spec/workspace-spec.coffee | 28 ++++++++++++++++++++++++++++ src/workspace-view.coffee | 2 +- src/workspace.coffee | 13 ++++++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 92d8e66c3..88bcdf49c 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -8,7 +8,11 @@ describe "Workspace", -> atom.workspace = workspace = new Workspace describe "::open(uri, options)", -> + openEvents = null + beforeEach -> + openEvents = [] + workspace.onDidOpen (event) -> openEvents.push(event) spyOn(workspace.getActivePane(), 'activate').andCallThrough() describe "when the 'searchAllPanes' option is false (default)", -> @@ -24,6 +28,8 @@ describe "Workspace", -> expect(workspace.getActivePane().items).toEqual [editor1] expect(workspace.getActivePaneItem()).toBe editor1 expect(workspace.getActivePane().activate).toHaveBeenCalled() + expect(openEvents).toEqual [{uri: undefined, pane: workspace.getActivePane(), item: editor1, index: 0}] + openEvents = [] waitsForPromise -> workspace.open().then (editor) -> editor2 = editor @@ -33,6 +39,7 @@ describe "Workspace", -> expect(workspace.getActivePane().items).toEqual [editor1, editor2] expect(workspace.getActivePaneItem()).toBe editor2 expect(workspace.getActivePane().activate).toHaveBeenCalled() + expect(openEvents).toEqual [{uri: undefined, pane: workspace.getActivePane(), item: editor2, index: 1}] describe "when called with a uri", -> describe "when the active pane already has an editor for the given uri", -> @@ -54,6 +61,27 @@ describe "Workspace", -> expect(workspace.getActivePaneItem()).toBe editor expect(workspace.getActivePane().activate).toHaveBeenCalled() + expect(openEvents).toEqual [ + { + uri: atom.project.resolve('a') + item: editor1 + pane: atom.workspace.getActivePane() + index: 0 + } + { + uri: atom.project.resolve('b') + item: editor2 + pane: atom.workspace.getActivePane() + index: 1 + } + { + uri: atom.project.resolve('a') + item: editor1 + pane: atom.workspace.getActivePane() + index: 0 + } + ] + describe "when the active pane does not have an editor for the given uri", -> it "adds and activates a new editor for the given path on the active pane", -> editor = null diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 27062e6b5..b4ae47318 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -84,7 +84,7 @@ class WorkspaceView extends View @panes.replaceWith(panes) @panes = panes - @subscribe @model.onDidAddPaneItem => @trigger 'uri-opened' + @subscribe @model.onDidOpen => @trigger 'uri-opened' @subscribe scrollbarStyle, (style) => @removeClass('scrollbars-visible-always scrollbars-visible-when-scrolling') diff --git a/src/workspace.coffee b/src/workspace.coffee index e8de5eeb0..59dc2c0f2 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -5,6 +5,7 @@ _ = require 'underscore-plus' Q = require 'q' Serializable = require 'serializable' Delegator = require 'delegato' +{Emitter} = require 'event-kit' Editor = require './editor' PaneContainer = require './pane-container' Pane = require './pane' @@ -33,6 +34,7 @@ class Workspace extends Model constructor: -> super + @emitter = new Emitter @openers = [] @paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed) @@ -151,6 +153,9 @@ class Workspace extends Model callback(textEditor) for textEditor in @getTextEditors() @onDidAddTextEditor ({textEditor}) -> callback(textEditor) + onDidOpen: (callback) -> + @emitter.on 'did-open', callback + eachEditor: (callback) -> deprecate("Use Workspace::observeTextEditors instead") @@ -208,11 +213,11 @@ class Workspace extends Model pane = @paneContainer.paneForUri(uri) if searchAllPanes pane ?= switch split when 'left' - @activePane.findLeftmostSibling() + @getActivePane().findLeftmostSibling() when 'right' - @activePane.findOrCreateRightmostSibling() + @getActivePane().findOrCreateRightmostSibling() else - @activePane + @getActivePane() @openUriInPane(uri, pane, options) @@ -266,7 +271,9 @@ class Workspace extends Model @itemOpened(item) pane.activateItem(item) pane.activate() if changeFocus + index = pane.getActiveItemIndex() @emit "uri-opened" + @emitter.emit 'did-open', {uri, pane, item, index} item .catch (error) -> console.error(error.stack ? error) From aac64e3a9bd551454f6848338f7c2913f2551ecd Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 07:01:32 -0600 Subject: [PATCH 079/355] Document Workspace::onDidOpen --- src/workspace.coffee | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/workspace.coffee b/src/workspace.coffee index 59dc2c0f2..97fff29e1 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -153,6 +153,18 @@ class Workspace extends Model callback(textEditor) for textEditor in @getTextEditors() @onDidAddTextEditor ({textEditor}) -> callback(textEditor) + # Essential: Invoke the given callback whenever an item is opened. Unlike + # ::onDidAddPaneItem, observers will be notified for items that are already + # present in the workspace when they are reopened. + # + # * `callback` {Function} to be called whenever an item is opened. + # * `event` {Object} with the following keys: + # * `uri` {String} representing the opened URI. Could be `undefined`. + # * `item` The opened item. + # * `pane` The pane in which the item was opened. + # * `index` The index of the opened item on its pane. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidOpen: (callback) -> @emitter.on 'did-open', callback From 2f6f374cc713c67dd03dae712fe471fe7939f4e6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 07:02:35 -0600 Subject: [PATCH 080/355] Upgrade event-kit to stop throwing when emitting on disposed emitters --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a8b5c63b..6dc56fa54 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.1", - "event-kit": "0.4.0", + "event-kit": "0.5.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", From b9e90f2fdd38948a347e39596ebc0bc8464b7626 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 08:06:19 -0600 Subject: [PATCH 081/355] Fix editor observation docs --- src/editor.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 3ade2ecb9..342d9cc0f 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -24,12 +24,12 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # ## Accessing Editor Instances # # The easiest way to get hold of `Editor` objects is by registering a callback -# with `::eachEditor` on the `atom.workspace` global. Your callback will then -# be called with all current editor instances and also when any editor is +# with `::observeTextEditors` on the `atom.workspace` global. Your callback will +# then be called with all current editor instances and also when any editor is # created in the future. # # ```coffee -# atom.workspace.eachEditor (editor) -> +# atom.workspace.observeTextEditors (editor) -> # editor.insertText('Hello World') # ``` # From 55913626ccb264b8bc9d94641061172d6dc53e32 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Sep 2014 09:45:45 -0700 Subject: [PATCH 082/355] Upgrade to fuzzaldrin 2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6dc56fa54..96851f421 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", - "fuzzaldrin": "^1.1", + "fuzzaldrin": "^2.1", "git-utils": "^2.1.4", "grim": "0.12.0", "guid": "0.0.10", From 641698330f5a142156409dd66b0b4d7247f5fd0b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Sep 2014 09:53:38 -0700 Subject: [PATCH 083/355] Upgrade to fuzzy-finder@0.58 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 96851f421..c180d81d0 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "exception-reporting": "0.20.0", "feedback": "0.33.0", "find-and-replace": "0.132.0", - "fuzzy-finder": "0.57.0", + "fuzzy-finder": "0.58.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", "grammar-selector": "0.29.0", From a947a357f4500c57cb6218d42a0737dcb8e3982e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 12:44:53 -0600 Subject: [PATCH 084/355] Upgrade text-buffer for event subscription methods --- package.json | 2 +- spec/git-spec.coffee | 4 ++-- src/display-buffer-marker.coffee | 4 ++-- src/display-buffer.coffee | 4 ++-- src/editor.coffee | 14 +++++++------- src/fold.coffee | 4 ++-- src/git.coffee | 8 ++++++-- src/project.coffee | 6 +++--- src/select-list-view.coffee | 2 +- src/tokenized-buffer.coffee | 6 ++---- 10 files changed, 28 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 6dc56fa54..bb1203df1 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "serializable": "^1", "space-pen": "3.4.6", "temp": "0.7.0", - "text-buffer": "^3.1.0", + "text-buffer": "^3.2.0", "theorist": "^1.0.2", "underscore-plus": "^1.5.1", "vm-compatibility-layer": "0.1.0" diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index b40f68182..2de1d2e16 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -253,10 +253,10 @@ describe "Git", -> statusHandler = jasmine.createSpy('statusHandler') atom.project.getRepo().on 'status-changed', statusHandler - editor.getBuffer().emit 'path-changed' + editor.getBuffer().emitter.emit 'did-change-path' expect(statusHandler.callCount).toBe 1 expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 - editor.getBuffer().emit 'path-changed' + editor.getBuffer().emitter.emit 'did-change-path' expect(statusHandler.callCount).toBe 1 describe "when a project is deserialized", -> diff --git a/src/display-buffer-marker.coffee b/src/display-buffer-marker.coffee index e2324f6b7..7f868f24e 100644 --- a/src/display-buffer-marker.coffee +++ b/src/display-buffer-marker.coffee @@ -22,8 +22,8 @@ class DisplayBufferMarker @oldTailScreenPosition = @getTailScreenPosition() @wasValid = @isValid() - @subscribe @bufferMarker, 'destroyed', => @destroyed() - @subscribe @bufferMarker, 'changed', (event) => @notifyObservers(event) + @subscribe @bufferMarker.onDidDestroy => @destroyed() + @subscribe @bufferMarker.onDidChange (event) => @notifyObservers(event) copy: (attributes) -> @displayBuffer.getMarker(@bufferMarker.copy(attributes).id) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 5146f1816..6b345ab89 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -55,8 +55,8 @@ class DisplayBuffer extends Model @subscribe @tokenizedBuffer, 'grammar-changed', (grammar) => @emit 'grammar-changed', grammar @subscribe @tokenizedBuffer, 'tokenized', => @emit 'tokenized' @subscribe @tokenizedBuffer, 'changed', @handleTokenizedBufferChange - @subscribe @buffer, 'markers-updated', @handleBufferMarkersUpdated - @subscribe @buffer, 'marker-created', @handleBufferMarkerCreated + @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated + @subscribe @buffer.onDidCreateMarker @handleBufferMarkerCreated @subscribe @$softWrap, (softWrap) => @emit 'soft-wrap-changed', softWrap diff --git a/src/editor.coffee b/src/editor.coffee index 342d9cc0f..9f9d18da7 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -253,15 +253,15 @@ class Editor extends Model subscribeToBuffer: -> @buffer.retain() - @subscribe @buffer, "path-changed", => + @subscribe @buffer.onDidChangePath => unless atom.project.getPath()? atom.project.setPath(path.dirname(@getPath())) @emit "title-changed" @emit "path-changed" - @subscribe @buffer, "contents-modified", => @emit "contents-modified" - @subscribe @buffer, "contents-conflicted", => @emit "contents-conflicted" - @subscribe @buffer, "modified-status-changed", => @emit "modified-status-changed" - @subscribe @buffer, "destroyed", => @destroy() + @subscribe @buffer.onDidStopChanging => @emit "contents-modified" + @subscribe @buffer.onDidConflict => @emit "contents-conflicted" + @subscribe @buffer.onDidChangeModified => @emit "modified-status-changed" + @subscribe @buffer.onDidDestroy => @destroy() @preserveCursorPositionOnBufferReload() subscribeToDisplayBuffer: -> @@ -1821,9 +1821,9 @@ class Editor extends Model preserveCursorPositionOnBufferReload: -> cursorPosition = null - @subscribe @buffer, "will-reload", => + @subscribe @buffer.onWillReload => cursorPosition = @getCursorBufferPosition() - @subscribe @buffer, "reloaded", => + @subscribe @buffer.onDidReload => @setCursorBufferPosition(cursorPosition) if cursorPosition cursorPosition = null diff --git a/src/fold.coffee b/src/fold.coffee index 4b61d24af..617d590ce 100644 --- a/src/fold.coffee +++ b/src/fold.coffee @@ -14,8 +14,8 @@ class Fold @id = @marker.id @displayBuffer.foldsByMarkerId[@marker.id] = this @updateDisplayBuffer() - @marker.on 'destroyed', => @destroyed() - @marker.on 'changed', ({isValid}) => @destroy() unless isValid + @marker.onDidDestroy => @destroyed() + @marker.onDidChange ({isValid}) => @destroy() unless isValid # Returns whether this fold is contained within another fold isInsideLargerFold: -> diff --git a/src/git.coffee b/src/git.coffee index 7cf4014a9..2c9cc7550 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -88,10 +88,14 @@ class Git # Subscribes to buffer events. subscribeToBuffer: (buffer) -> - @subscribe buffer, 'saved reloaded path-changed', => + getBufferPathStatus = => if path = buffer.getPath() @getPathStatus(path) - @subscribe buffer, 'destroyed', => @unsubscribe(buffer) + + @subscribe buffer.onDidSave(getBufferPathStatus) + @subscribe buffer.onDidReload(getBufferPathStatus) + @subscribe buffer.onDidChangePath(getBufferPathStatus) + @subscribe buffer.onDidDestroy => @unsubscribe(buffer) # Subscribes to editor view event. checkoutHeadForEditor: (editor) -> diff --git a/src/project.coffee b/src/project.coffee index bf2adf2c3..a34a442a5 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -49,7 +49,7 @@ class Project extends Model for buffer in @buffers do (buffer) => - buffer.once 'destroyed', => @removeBuffer(buffer) + buffer.onDidDestroy => @removeBuffer(buffer) @setPath(path) @@ -216,11 +216,11 @@ class Project extends Model addBuffer: (buffer, options={}) -> @addBufferAtIndex(buffer, @buffers.length, options) - buffer.once 'destroyed', => @removeBuffer(buffer) + buffer.onDidDestroy => @removeBuffer(buffer) addBufferAtIndex: (buffer, index, options={}) -> @buffers.splice(index, 0, buffer) - buffer.once 'destroyed', => @removeBuffer(buffer) + buffer.onDidDestroy => @removeBuffer(buffer) @emit 'buffer-created', buffer buffer diff --git a/src/select-list-view.coffee b/src/select-list-view.coffee index b9227df18..ae5ffdc93 100644 --- a/src/select-list-view.coffee +++ b/src/select-list-view.coffee @@ -51,7 +51,7 @@ class SelectListView extends View # This method can be overridden by subclasses but `super` should always # be called. initialize: -> - @filterEditorView.getEditor().getBuffer().on 'changed', => + @filterEditorView.getEditor().getBuffer().onDidChange => @schedulePopulateList() @filterEditorView.hiddenInput.on 'focusout', => @cancel() unless @cancelling diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 79dcba5f7..0ef877869 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -30,10 +30,8 @@ class TokenizedBuffer extends Model @setGrammar(grammar, newScore) if newScore > @currentGrammarScore @on 'grammar-changed grammar-updated', => @retokenizeLines() - @subscribe @buffer, "changed", (e) => @handleBufferChange(e) - @subscribe @buffer, "path-changed", => - @bufferPath = @buffer.getPath() - @reloadGrammar() + @subscribe @buffer.onDidChange (e) => @handleBufferChange(e) + @subscribe @buffer.onDidChangePath (@bufferPath) => @reloadGrammar() @subscribe @$tabLength.changes, (tabLength) => @retokenizeLines() From b5676adf8adfe8ab8b42f3e3d7b5e718e26973cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C5=BDu=C5=BEak?= Date: Thu, 4 Sep 2014 21:52:00 +0200 Subject: [PATCH 085/355] Remove check for deprecated function calls --- spec/spec-helper.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 6fdbed35b..46d43ed7d 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -138,7 +138,6 @@ afterEach -> jasmine.unspy(atom, 'saveSync') ensureNoPathSubscriptions() atom.syntax.off() - ensureNoDeprecatedFunctionsCalled() if isCoreSpec waits(0) # yield to ui thread to make screen update more frequently ensureNoPathSubscriptions = -> From effe7e8070b948f6c5406d9bcf84fc23b8d57b73 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 14:00:14 -0600 Subject: [PATCH 086/355] Upgrade find-and-replace for spec fixes --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb1203df1..978c19756 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.132.0", + "find-and-replace": "0.133.0", "fuzzy-finder": "0.57.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From 6cb085b3410ef102e94f094854ff9b708b7b83a8 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 14:15:42 -0600 Subject: [PATCH 087/355] Upgrade text-buffer again to fix specs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 978c19756..98a71f29c 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.133.0", + "find-and-replace": "0.134.0", "fuzzy-finder": "0.57.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From eb9d4ba8166c61ee8ed481dbb73f16c6685bf0ec Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 13:39:49 -0700 Subject: [PATCH 088/355] :memo: Use ### for example sections --- src/git.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/git.coffee b/src/git.coffee index 7cf4014a9..08a24d23b 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -27,12 +27,14 @@ Task = require './task' # # ## Examples # +# ### Logging the URL of the origin remote +# # ```coffee # git = atom.project.getRepo() # console.log git.getOriginUrl() # ``` # -# ## Requiring in packages +# ### Requiring in packages # # ```coffee # {Git} = require 'atom' From 326f5fc646a35d71af145ee10f7bd999d809a8dd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 14:28:49 -0700 Subject: [PATCH 089/355] Upgrade to settings-view@0.142 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dea61b73b..cfcbc762a 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "open-on-github": "0.30.0", "package-generator": "0.31.0", "release-notes": "0.36.0", - "settings-view": "0.141.0", + "settings-view": "0.142.0", "snippets": "0.51.0", "spell-check": "0.42.0", "status-bar": "0.44.0", From 2c9241506b97eebf7dce431ebfaab006996ce2c6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 14:53:33 -0700 Subject: [PATCH 090/355] Fix doc strings --- src/editor-view.coffee | 6 +++--- src/git.coffee | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 2f945f458..cefec694d 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -70,9 +70,9 @@ class EditorView extends View # The constructor for setting up an `EditorView` instance. # # * `editorOrParams` Either an {Editor}, or an object with one property, `mini`. - # If `mini` is `true`, a "miniature" `Editor` is constructed. - # Typically, this is ideal for scenarios where you need an Atom editor, - # but without all the chrome, like scrollbars, gutter, _e.t.c._. + # If `mini` is `true`, a "miniature" `Editor` is constructed. + # Typically, this is ideal for scenarios where you need an Atom editor, + # but without all the chrome, like scrollbars, gutter, _e.t.c._. # constructor: (editorOrParams, props) -> super diff --git a/src/git.coffee b/src/git.coffee index 9bbd25d61..0e5273aa9 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -20,9 +20,9 @@ Task = require './task' # For a repository with submodules this would have the following outcome: # # ```coffee -# repo = atom.project.getRepo() -# repo.getShortHead() # 'master' -# repo.getShortHead('vendor/path/to/a/submodule') # 'dead1234' +# repo = atom.project.getRepo() +# repo.getShortHead() # 'master' +# repo.getShortHead('vendor/path/to/a/submodule') # 'dead1234' # ``` # # ## Examples @@ -30,14 +30,14 @@ Task = require './task' # ### Logging the URL of the origin remote # # ```coffee -# git = atom.project.getRepo() -# console.log git.getOriginUrl() +# git = atom.project.getRepo() +# console.log git.getOriginUrl() # ``` # # ### Requiring in packages # # ```coffee -# {Git} = require 'atom' +# {Git} = require 'atom' # ``` module.exports = class Git From 04b0ed9704c89fe7a8b2607dd963d31c0aa64d75 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:14:38 -0700 Subject: [PATCH 091/355] Deprecate EditorView::scrollTo*Position() functions --- src/editor-view.coffee | 13 +++-------- src/editor.coffee | 50 +++++++++++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index cefec694d..8d9421a52 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -173,23 +173,16 @@ class EditorView extends View scrollToBottom: -> @editor.setScrollBottom(Infinity) - # Public: Scrolls the editor to the given screen position. - # - # * `screenPosition` An object that represents a buffer position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # * `options` (optional) {Object} matching the options available to {::scrollToScreenPosition} scrollToScreenPosition: (screenPosition, options) -> + deprecate 'Use Editor::scrollToScreenPosition instead. You can get the editor via editorView.getModel()' @editor.scrollToScreenPosition(screenPosition, options) - # Public: Scrolls the editor to the given buffer position. - # - # * `bufferPosition` An object that represents a buffer position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # * `options` (optional) {Object} matching the options available to {::scrollToBufferPosition} scrollToBufferPosition: (bufferPosition, options) -> + deprecate 'Use Editor::scrollToBufferPosition instead. You can get the editor via editorView.getModel()' @editor.scrollToBufferPosition(bufferPosition, options) scrollToCursorPosition: -> + deprecate 'Use Editor::scrollToCursorPosition instead. You can get the editor via editorView.getModel()' @editor.scrollToCursorPosition() # Public: Converts a buffer position to a pixel position. diff --git a/src/editor.coffee b/src/editor.coffee index 4e5be2195..7ea4f888b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2293,14 +2293,44 @@ class Editor extends Model Section: Scrolling the Editor ### - # Public: Scroll the editor to reveal the most recently added cursor if it is + # Essential: Scroll the editor to reveal the most recently added cursor if it is # off-screen. # # * `options` (optional) {Object} - # * `center` Center the editor around the cursor if possible. Defauls to true. + # * `center` Center the editor around the cursor if possible. (default: true) scrollToCursorPosition: (options) -> @getLastCursor().autoscroll(center: options?.center ? true) + # Essential: Scrolls the editor to the given buffer position. + # + # * `bufferPosition` An object that represents a buffer position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # * `options` (optional) {Object} + # * `center` Center the editor around the position if possible. (default: false) + scrollToBufferPosition: (bufferPosition, options) -> + @displayBuffer.scrollToBufferPosition(bufferPosition, options) + + # Essential: Scrolls the editor to the given screen position. + # + # * `screenPosition` An object that represents a buffer position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # * `options` (optional) {Object} + # * `center` Center the editor around the position if possible. (default: false) + scrollToScreenPosition: (screenPosition, options) -> + @displayBuffer.scrollToScreenPosition(screenPosition, options) + + scrollToScreenRange: (screenRange, options) -> @displayBuffer.scrollToScreenRange(screenRange, options) + + horizontallyScrollable: -> @displayBuffer.horizontallyScrollable() + + verticallyScrollable: -> @displayBuffer.verticallyScrollable() + + getHorizontalScrollbarHeight: -> @displayBuffer.getHorizontalScrollbarHeight() + setHorizontalScrollbarHeight: (height) -> @displayBuffer.setHorizontalScrollbarHeight(height) + + getVerticalScrollbarWidth: -> @displayBuffer.getVerticalScrollbarWidth() + setVerticalScrollbarWidth: (width) -> @displayBuffer.setVerticalScrollbarWidth(width) + pageUp: -> newScrollTop = @getScrollTop() - @getHeight() @moveUp(@getRowsPerPage()) @@ -2419,22 +2449,6 @@ class Editor extends Model pixelRectForScreenRange: (screenRange) -> @displayBuffer.pixelRectForScreenRange(screenRange) - scrollToScreenRange: (screenRange, options) -> @displayBuffer.scrollToScreenRange(screenRange, options) - - scrollToScreenPosition: (screenPosition, options) -> @displayBuffer.scrollToScreenPosition(screenPosition, options) - - scrollToBufferPosition: (bufferPosition, options) -> @displayBuffer.scrollToBufferPosition(bufferPosition, options) - - horizontallyScrollable: -> @displayBuffer.horizontallyScrollable() - - verticallyScrollable: -> @displayBuffer.verticallyScrollable() - - getHorizontalScrollbarHeight: -> @displayBuffer.getHorizontalScrollbarHeight() - setHorizontalScrollbarHeight: (height) -> @displayBuffer.setHorizontalScrollbarHeight(height) - - getVerticalScrollbarWidth: -> @displayBuffer.getVerticalScrollbarWidth() - setVerticalScrollbarWidth: (width) -> @displayBuffer.setVerticalScrollbarWidth(width) - # Deprecated: Call {::joinLines} instead. joinLine: -> deprecate("Use Editor::joinLines() instead") From c511a714886b17fb8d7dae505abe7d2eead51fc0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:17:01 -0700 Subject: [PATCH 092/355] Deprecate EditorView::scrollToBottom --- src/editor-view.coffee | 2 +- src/editor.coffee | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 8d9421a52..544f77288 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -169,8 +169,8 @@ class EditorView extends View else @editor.getScrollLeft() - # Public: Scrolls the editor to the bottom. scrollToBottom: -> + deprecate 'Use Editor::scrollToBottom instead. You can get the editor via editorView.getModel()' @editor.setScrollBottom(Infinity) scrollToScreenPosition: (screenPosition, options) -> diff --git a/src/editor.coffee b/src/editor.coffee index 7ea4f888b..f4ae24ddc 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2319,6 +2319,10 @@ class Editor extends Model scrollToScreenPosition: (screenPosition, options) -> @displayBuffer.scrollToScreenPosition(screenPosition, options) + # Essential: Scrolls the editor to the bottom + scrollToBottom: -> + @setScrollBottom(Infinity) + scrollToScreenRange: (screenRange, options) -> @displayBuffer.scrollToScreenRange(screenRange, options) horizontallyScrollable: -> @displayBuffer.horizontallyScrollable() From 5ae040f6887c2ec27156a14cf475106f4917bdb7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:17:17 -0700 Subject: [PATCH 093/355] Add Editor::scrollToTop to compliment scrollToBottom() --- src/editor.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index f4ae24ddc..d95445491 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2319,6 +2319,10 @@ class Editor extends Model scrollToScreenPosition: (screenPosition, options) -> @displayBuffer.scrollToScreenPosition(screenPosition, options) + # Essential: Scrolls the editor to the top + scrollToTop: -> + @setScrollTop(0) + # Essential: Scrolls the editor to the bottom scrollToBottom: -> @setScrollBottom(Infinity) From 52c19a5dcd419e73d550eda424a0b4633fb6e42a Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:20:20 -0700 Subject: [PATCH 094/355] Deprecate pixelPositionFor*Position --- src/editor-view.coffee | 14 ++------------ src/editor.coffee | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 544f77288..cc891ec3a 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -185,22 +185,12 @@ class EditorView extends View deprecate 'Use Editor::scrollToCursorPosition instead. You can get the editor via editorView.getModel()' @editor.scrollToCursorPosition() - # Public: Converts a buffer position to a pixel position. - # - # * `bufferPosition` An object that represents a buffer position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # - # Returns an {Object} with two values: `top` and `left`, representing the pixel positions. pixelPositionForBufferPosition: (bufferPosition) -> + deprecate 'Use Editor::pixelPositionForBufferPosition instead. You can get the editor via editorView.getModel()' @editor.pixelPositionForBufferPosition(bufferPosition) - # Public: Converts a screen position to a pixel position. - # - # * `screenPosition` An object that represents a screen position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # - # Returns an object with two values: `top` and `left`, representing the pixel positions. pixelPositionForScreenPosition: (screenPosition) -> + deprecate 'Use Editor::pixelPositionForScreenPosition instead. You can get the editor via editorView.getModel()' @editor.pixelPositionForScreenPosition(screenPosition) appendToLinesView: (view) -> diff --git a/src/editor.coffee b/src/editor.coffee index d95445491..2ca4d20d4 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2396,6 +2396,22 @@ class Editor extends Model Section: Editor Rendering ### + # Public: Converts a buffer position to a pixel position. + # + # * `bufferPosition` An object that represents a buffer position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # + # Returns an {Object} with two values: `top` and `left`, representing the pixel positions. + pixelPositionForBufferPosition: (bufferPosition) -> @displayBuffer.pixelPositionForBufferPosition(bufferPosition) + + # Extended: Converts a screen position to a pixel position. + # + # * `screenPosition` An object that represents a screen position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # + # Returns an {Object} with two values: `top` and `left`, representing the pixel positions. + pixelPositionForScreenPosition: (screenPosition) -> @displayBuffer.pixelPositionForScreenPosition(screenPosition) + getSelectionMarkerAttributes: -> type: 'selection', editorId: @id, invalidate: 'never' @@ -2449,10 +2465,6 @@ class Editor extends Model selectionIntersectsVisibleRowRange: (selection) -> @displayBuffer.selectionIntersectsVisibleRowRange(selection) - pixelPositionForScreenPosition: (screenPosition) -> @displayBuffer.pixelPositionForScreenPosition(screenPosition) - - pixelPositionForBufferPosition: (bufferPosition) -> @displayBuffer.pixelPositionForBufferPosition(bufferPosition) - screenPositionForPixelPosition: (pixelPosition) -> @displayBuffer.screenPositionForPixelPosition(pixelPosition) pixelRectForScreenRange: (screenRange) -> @displayBuffer.pixelRectForScreenRange(screenRange) From dc21e8707f54de77fb0f4459df897c5dace95247 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:25:55 -0700 Subject: [PATCH 095/355] Deprecate EditorView::getFirstVisibleScreenRow --- benchmark/benchmark-suite.coffee | 8 ++++---- src/editor-view.coffee | 14 ++++---------- src/editor.coffee | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/benchmark/benchmark-suite.coffee b/benchmark/benchmark-suite.coffee index c60811985..0a3901ec9 100644 --- a/benchmark/benchmark-suite.coffee +++ b/benchmark/benchmark-suite.coffee @@ -62,8 +62,8 @@ describe "editorView.", -> describe "empty-vs-set-innerHTML.", -> [firstRow, lastRow] = [] beforeEach -> - firstRow = editorView.getFirstVisibleScreenRow() - lastRow = editorView.getLastVisibleScreenRow() + firstRow = editorView.getModel().getFirstVisibleScreenRow() + lastRow = editorView.getModel().getLastVisibleScreenRow() benchmark "build-gutter-html.", 1000, -> editorView.gutter.renderLineNumbers(null, firstRow, lastRow) @@ -97,8 +97,8 @@ describe "editorView.", -> describe "multiple-lines.", -> [firstRow, lastRow] = [] beforeEach -> - firstRow = editorView.getFirstVisibleScreenRow() - lastRow = editorView.getLastVisibleScreenRow() + firstRow = editorView.getModel().getFirstVisibleScreenRow() + lastRow = editorView.getModel().getLastVisibleScreenRow() benchmark "cache-entire-visible-area", 100, -> for i in [firstRow..lastRow] diff --git a/src/editor-view.coffee b/src/editor-view.coffee index cc891ec3a..3eccc2340 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -256,19 +256,13 @@ class EditorView extends View deprecate('Use editorView.getModel().pageUp()') @editor.pageUp() - # Public: Retrieves the number of the row that is visible and currently at the - # top of the editor. - # - # Returns a {Number}. getFirstVisibleScreenRow: -> - @editor.getVisibleRowRange()[0] + deprecate 'Use Editor::getFirstVisibleScreenRow instead. You can get the editor via editorView.getModel()' + @editor.getFirstVisibleScreenRow() - # Public: Retrieves the number of the row that is visible and currently at the - # bottom of the editor. - # - # Returns a {Number}. getLastVisibleScreenRow: -> - @editor.getVisibleRowRange()[1] + deprecate 'Use Editor::getLastVisibleScreenRow instead. You can get the editor via editorView.getModel()' + @editor.getLastVisibleScreenRow() # Public: Gets the font family for the editor. # diff --git a/src/editor.coffee b/src/editor.coffee index 2ca4d20d4..de62f8453 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2396,7 +2396,21 @@ class Editor extends Model Section: Editor Rendering ### - # Public: Converts a buffer position to a pixel position. + # Extended: Retrieves the number of the row that is visible and currently at the + # top of the editor. + # + # Returns a {Number}. + getFirstVisibleScreenRow: -> + @getVisibleRowRange()[0] + + # Extended: Retrieves the number of the row that is visible and currently at the + # bottom of the editor. + # + # Returns a {Number}. + getLastVisibleScreenRow: -> + @getVisibleRowRange()[1] + + # Extended: Converts a buffer position to a pixel position. # # * `bufferPosition` An object that represents a buffer position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} From dba1e22dedad98cc2a28f6d8bfe3445e4c104db7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:29:54 -0700 Subject: [PATCH 096/355] Deprecate EditorView::setSoftWrap --- src/editor-view.coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 3eccc2340..41d6d4431 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -306,10 +306,8 @@ class EditorView extends View setShowIndentGuide: (showIndentGuide) -> @component.setShowIndentGuide(showIndentGuide) - # Public: Enables/disables soft wrap on the editor. - # - # * `softWrap` A {Boolean} which, if `true`, enables soft wrap setSoftWrap: (softWrap) -> + deprecate 'Use Editor::setSoftWrap instead. You can get the editor via editorView.getModel()' @editor.setSoftWrap(softWrap) # Public: Set whether invisible characters are shown. From 70df5a5c0ab594579340b154229ad2ddd16c04f3 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 15:30:06 -0700 Subject: [PATCH 097/355] Remove unnecessary fixme --- src/editor-view.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 41d6d4431..852463d8e 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -101,7 +101,6 @@ class EditorView extends View @overlayer = $(node).find('.lines').addClass('overlayer') @hiddenInput = $(node).find('.hidden-input') - # FIXME: there should be a better way to deal with the gutter element @subscribe atom.config.observe 'editor.showLineNumbers', => @gutter = $(node).find('.gutter') From 914e4e6342130c2f27c8c4de83631af296a253e9 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 16:00:34 -0700 Subject: [PATCH 098/355] Deprecate EditorView::split* methods --- src/editor-view.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 852463d8e..c4e6a6711 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -213,23 +213,23 @@ class EditorView extends View unmountComponent: -> React.unmountComponentAtNode(@element) if @component.isMounted() - # Public: Split the editor view left. splitLeft: -> + deprecate 'Use Pane::splitLeft instead. To duplicate this editor into the split use: editorView.getPane().splitLeft(editorView.getPane().copyActiveItem())' pane = @getPane() pane?.splitLeft(pane?.copyActiveItem()).activeView - # Public: Split the editor view right. splitRight: -> + deprecate 'Use Pane::splitRight instead. To duplicate this editor into the split use: editorView.getPane().splitRight(editorView.getPane().copyActiveItem())' pane = @getPane() pane?.splitRight(pane?.copyActiveItem()).activeView - # Public: Split the editor view up. splitUp: -> + deprecate 'Use Pane::splitUp instead. To duplicate this editor into the split use: editorView.getPane().splitUp(editorView.getPane().copyActiveItem())' pane = @getPane() pane?.splitUp(pane?.copyActiveItem()).activeView - # Public: Split the editor view down. splitDown: -> + deprecate 'Use Pane::splitDown instead. To duplicate this editor into the split use: editorView.getPane().splitDown(editorView.getPane().copyActiveItem())' pane = @getPane() pane?.splitDown(pane?.copyActiveItem()).activeView From 90592a70be3389a1440ce97ad8267db896043b13 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 16:04:32 -0700 Subject: [PATCH 099/355] Include injection grammars in active list Prevents an immediate flicker when restarting Atom with editors open that have injection matches. --- spec/workspace-spec.coffee | 9 +++++++-- src/workspace.coffee | 8 +++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spec/workspace-spec.coffee b/spec/workspace-spec.coffee index 88bcdf49c..f95910d01 100644 --- a/spec/workspace-spec.coffee +++ b/spec/workspace-spec.coffee @@ -346,14 +346,19 @@ describe "Workspace", -> waitsForPromise -> atom.packages.activatePackage('language-coffee-script') + waitsForPromise -> + atom.packages.activatePackage('language-todo') + waitsForPromise -> atom.workspace.open('sample.coffee') runs -> - atom.workspace.getActiveEditor().setText('i = /test/;') + atom.workspace.getActiveEditor().setText """ + i = /test/; #FIXME + """ state = atom.workspace.serialize() - expect(state.packagesWithActiveGrammars).toEqual ['language-coffee-script', 'language-javascript'] + expect(state.packagesWithActiveGrammars).toEqual ['language-coffee-script', 'language-javascript', 'language-todo'] jsPackage = atom.packages.getLoadedPackage('language-javascript') coffeePackage = atom.packages.getLoadedPackage('language-coffee-script') diff --git a/src/workspace.coffee b/src/workspace.coffee index 97fff29e1..a74cd3897 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -75,7 +75,13 @@ class Workspace extends Model for scopeName in includedGrammarScopes ? [] addGrammar(atom.syntax.grammarForScopeName(scopeName)) - addGrammar(editor.getGrammar()) for editor in @getTextEditors() + editors = @getTextEditors() + addGrammar(editor.getGrammar()) for editor in editors + + if editors.length > 0 + for grammar in atom.syntax.grammars when grammar.injectionSelector + addGrammar(grammar) + _.uniq(packageNames) editorAdded: (editor) -> From 7c8451e17870df853f5506e410960ec56584f12c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 16:09:46 -0700 Subject: [PATCH 100/355] Use getter on GrammarRegistry --- src/workspace.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index a74cd3897..47d0cbe17 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -79,7 +79,7 @@ class Workspace extends Model addGrammar(editor.getGrammar()) for editor in editors if editors.length > 0 - for grammar in atom.syntax.grammars when grammar.injectionSelector + for grammar in atom.syntax.getGrammars() when grammar.injectionSelector addGrammar(grammar) _.uniq(packageNames) From 3e407296ad4dafbcba6d44fb67a21763a5f9bf70 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 16:31:21 -0700 Subject: [PATCH 101/355] :racehorse: Upgrade to less-cache@0.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfcbc762a..9a16a6eaa 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "grim": "0.12.0", "guid": "0.0.10", "jasmine-tagged": "^1.1.2", - "less-cache": "0.13.0", + "less-cache": "0.14.0", "mixto": "^1", "mkdirp": "0.3.5", "nslog": "^1.0.1", From a81393320cc5f746e0e5b72b5aca40e014c2c931 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 16:41:20 -0700 Subject: [PATCH 102/355] Support a copyActiveItem param in Pane::split* methods --- spec/pane-spec.coffee | 54 +++++++++++++++++++++++++++++-------------- src/pane.coffee | 8 +++++++ 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index c66b88850..2f2de1910 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -459,22 +459,27 @@ describe "Pane", -> [pane1, container] = [] beforeEach -> - pane1 = new Pane(items: ["A"]) + pane1 = new Pane(items: [new Item("A")]) container = new PaneContainer(root: pane1) describe "::splitLeft(params)", -> describe "when the parent is the container root", -> it "replaces itself with a row and inserts a new pane to the left of itself", -> - pane2 = pane1.splitLeft(items: ["B"]) - pane3 = pane1.splitLeft(items: ["C"]) + pane2 = pane1.splitLeft(items: [new Item("B")]) + pane3 = pane1.splitLeft(items: [new Item("C")]) expect(container.root.orientation).toBe 'horizontal' expect(container.root.children).toEqual [pane2, pane3, pane1] + describe "when `copyActiveItem: true` is passed in the params", -> + it "duplicates the active item", -> + pane2 = pane1.splitLeft(copyActiveItem: true) + expect(pane2.getActiveItem()).toEqual pane1.getActiveItem() + describe "when the parent is a column", -> it "replaces itself with a row and inserts a new pane to the left of itself", -> pane1.splitDown() - pane2 = pane1.splitLeft(items: ["B"]) - pane3 = pane1.splitLeft(items: ["C"]) + pane2 = pane1.splitLeft(items: [new Item("B")]) + pane3 = pane1.splitLeft(items: [new Item("C")]) row = container.root.children[0] expect(row.orientation).toBe 'horizontal' expect(row.children).toEqual [pane2, pane3, pane1] @@ -482,16 +487,21 @@ describe "Pane", -> describe "::splitRight(params)", -> describe "when the parent is the container root", -> it "replaces itself with a row and inserts a new pane to the right of itself", -> - pane2 = pane1.splitRight(items: ["B"]) - pane3 = pane1.splitRight(items: ["C"]) + pane2 = pane1.splitRight(items: [new Item("B")]) + pane3 = pane1.splitRight(items: [new Item("C")]) expect(container.root.orientation).toBe 'horizontal' expect(container.root.children).toEqual [pane1, pane3, pane2] + describe "when `copyActiveItem: true` is passed in the params", -> + it "duplicates the active item", -> + pane2 = pane1.splitRight(copyActiveItem: true) + expect(pane2.getActiveItem()).toEqual pane1.getActiveItem() + describe "when the parent is a column", -> it "replaces itself with a row and inserts a new pane to the right of itself", -> pane1.splitDown() - pane2 = pane1.splitRight(items: ["B"]) - pane3 = pane1.splitRight(items: ["C"]) + pane2 = pane1.splitRight(items: [new Item("B")]) + pane3 = pane1.splitRight(items: [new Item("C")]) row = container.root.children[0] expect(row.orientation).toBe 'horizontal' expect(row.children).toEqual [pane1, pane3, pane2] @@ -499,16 +509,21 @@ describe "Pane", -> describe "::splitUp(params)", -> describe "when the parent is the container root", -> it "replaces itself with a column and inserts a new pane above itself", -> - pane2 = pane1.splitUp(items: ["B"]) - pane3 = pane1.splitUp(items: ["C"]) + pane2 = pane1.splitUp(items: [new Item("B")]) + pane3 = pane1.splitUp(items: [new Item("C")]) expect(container.root.orientation).toBe 'vertical' expect(container.root.children).toEqual [pane2, pane3, pane1] + describe "when `copyActiveItem: true` is passed in the params", -> + it "duplicates the active item", -> + pane2 = pane1.splitUp(copyActiveItem: true) + expect(pane2.getActiveItem()).toEqual pane1.getActiveItem() + describe "when the parent is a row", -> it "replaces itself with a column and inserts a new pane above itself", -> pane1.splitRight() - pane2 = pane1.splitUp(items: ["B"]) - pane3 = pane1.splitUp(items: ["C"]) + pane2 = pane1.splitUp(items: [new Item("B")]) + pane3 = pane1.splitUp(items: [new Item("C")]) column = container.root.children[0] expect(column.orientation).toBe 'vertical' expect(column.children).toEqual [pane2, pane3, pane1] @@ -516,16 +531,21 @@ describe "Pane", -> describe "::splitDown(params)", -> describe "when the parent is the container root", -> it "replaces itself with a column and inserts a new pane below itself", -> - pane2 = pane1.splitDown(items: ["B"]) - pane3 = pane1.splitDown(items: ["C"]) + pane2 = pane1.splitDown(items: [new Item("B")]) + pane3 = pane1.splitDown(items: [new Item("C")]) expect(container.root.orientation).toBe 'vertical' expect(container.root.children).toEqual [pane1, pane3, pane2] + describe "when `copyActiveItem: true` is passed in the params", -> + it "duplicates the active item", -> + pane2 = pane1.splitDown(copyActiveItem: true) + expect(pane2.getActiveItem()).toEqual pane1.getActiveItem() + describe "when the parent is a row", -> it "replaces itself with a column and inserts a new pane below itself", -> pane1.splitRight() - pane2 = pane1.splitDown(items: ["B"]) - pane3 = pane1.splitDown(items: ["C"]) + pane2 = pane1.splitDown(items: [new Item("B")]) + pane3 = pane1.splitDown(items: [new Item("C")]) column = container.root.children[0] expect(column.orientation).toBe 'vertical' expect(column.children).toEqual [pane1, pane3, pane2] diff --git a/src/pane.coffee b/src/pane.coffee index d56ae007b..c6351f656 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -528,6 +528,7 @@ class Pane extends Model # # * `params` (optional) {Object} with the following keys: # * `items` (optional) {Array} of items to add to the new pane. + # * `copyActiveItem` (optional) {Boolean} true will copy the active item into the new split pane # # Returns the new {Pane}. splitLeft: (params) -> @@ -537,6 +538,7 @@ class Pane extends Model # # * `params` (optional) {Object} with the following keys: # * `items` (optional) {Array} of items to add to the new pane. + # * `copyActiveItem` (optional) {Boolean} true will copy the active item into the new split pane # # Returns the new {Pane}. splitRight: (params) -> @@ -546,6 +548,7 @@ class Pane extends Model # # * `params` (optional) {Object} with the following keys: # * `items` (optional) {Array} of items to add to the new pane. + # * `copyActiveItem` (optional) {Boolean} true will copy the active item into the new split pane # # Returns the new {Pane}. splitUp: (params) -> @@ -555,12 +558,17 @@ class Pane extends Model # # * `params` (optional) {Object} with the following keys: # * `items` (optional) {Array} of items to add to the new pane. + # * `copyActiveItem` (optional) {Boolean} true will copy the active item into the new split pane # # Returns the new {Pane}. splitDown: (params) -> @split('vertical', 'after', params) split: (orientation, side, params) -> + if params?.copyActiveItem + params.items ?= [] + params.items.push(@copyActiveItem()) + if @parent.orientation isnt orientation @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this]})) From 336afc32c24aa645725400e1b84330bf4e8cb7ee Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 16:41:34 -0700 Subject: [PATCH 103/355] Add PaneView::getModel() --- spec/pane-view-spec.coffee | 4 ++-- src/pane-view.coffee | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee index 4862e639b..63c812621 100644 --- a/spec/pane-view-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -29,7 +29,7 @@ describe "PaneView", -> runs -> pane = container.getRoot() - paneModel = pane.model + paneModel = pane.getModel() paneModel.addItems([view1, editor1, view2, editor2]) afterEach -> @@ -259,7 +259,7 @@ describe "PaneView", -> describe "when a pane is split", -> it "builds the appropriate pane-row and pane-column views", -> pane1 = pane - pane1Model = pane.model + pane1Model = pane.getModel() pane.activateItem(editor1) pane2Model = pane1Model.splitRight(items: [pane1Model.copyActiveItem()]) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index ac79faaba..b41162389 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -84,6 +84,9 @@ class PaneView extends View @model.destroy() @command 'pane:close-other-items', => @destroyInactiveItems() + # Essential: Returns the {Pane} model underlying this pane view + getModel: -> @model + # Deprecated: Use ::destroyItem removeItem: (item) -> deprecate("Use PaneView::destroyItem instead") From 1291cf19fbd0c7ba8229172397637918222eea1f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 16:49:02 -0700 Subject: [PATCH 104/355] Rename EditorView::getPane -> ::getPaneView() --- src/editor-view.coffee | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index c4e6a6711..234da607f 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -233,11 +233,14 @@ class EditorView extends View pane = @getPane() pane?.splitDown(pane?.copyActiveItem()).activeView - # Public: Get this view's pane. + # Public: Get this {EditorView}'s {PaneView}. # - # Returns a {Pane}. - getPane: -> + # Returns a {PaneView} + getPaneView: -> @parent('.item-views').parents('.pane').view() + getPane: -> + deprecate 'Use EditorView::getPaneView() instead' + @getPaneView() show: -> super From e48748122f6b78986cdabc7490cd5150edf8c91b Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 16:49:33 -0700 Subject: [PATCH 105/355] Suggest better alternative in deprecation warnings --- src/editor-view.coffee | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 234da607f..d88a17bb3 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -214,22 +214,38 @@ class EditorView extends View React.unmountComponentAtNode(@element) if @component.isMounted() splitLeft: -> - deprecate 'Use Pane::splitLeft instead. To duplicate this editor into the split use: editorView.getPane().splitLeft(editorView.getPane().copyActiveItem())' + deprecate """ + Use Pane::splitLeft instead. + To duplicate this editor into the split use: + editorView.getPaneView().getModel().splitLeft(copyActiveItem: true) + """ pane = @getPane() pane?.splitLeft(pane?.copyActiveItem()).activeView splitRight: -> - deprecate 'Use Pane::splitRight instead. To duplicate this editor into the split use: editorView.getPane().splitRight(editorView.getPane().copyActiveItem())' + deprecate """ + Use Pane::splitRight instead. + To duplicate this editor into the split use: + editorView.getPaneView().getModel().splitRight(copyActiveItem: true) + """ pane = @getPane() pane?.splitRight(pane?.copyActiveItem()).activeView splitUp: -> - deprecate 'Use Pane::splitUp instead. To duplicate this editor into the split use: editorView.getPane().splitUp(editorView.getPane().copyActiveItem())' + deprecate """ + Use Pane::splitUp instead. + To duplicate this editor into the split use: + editorView.getPaneView().getModel().splitUp(copyActiveItem: true) + """ pane = @getPane() pane?.splitUp(pane?.copyActiveItem()).activeView splitDown: -> - deprecate 'Use Pane::splitDown instead. To duplicate this editor into the split use: editorView.getPane().splitDown(editorView.getPane().copyActiveItem())' + deprecate """ + Use Pane::splitDown instead. + To duplicate this editor into the split use: + editorView.getPaneView().getModel().splitDown(copyActiveItem: true) + """ pane = @getPane() pane?.splitDown(pane?.copyActiveItem()).activeView From 7fe567521e839bfd9fde838f2b3efd78db868307 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 4 Sep 2014 17:09:52 -0700 Subject: [PATCH 106/355] Use the model methods in the commands --- src/pane-view.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index b41162389..0de2ca7f1 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -75,10 +75,10 @@ class PaneView extends View @command 'pane:show-item-8', => @activateItemAtIndex(7) @command 'pane:show-item-9', => @activateItemAtIndex(8) - @command 'pane:split-left', => @splitLeft(@copyActiveItem()) - @command 'pane:split-right', => @splitRight(@copyActiveItem()) - @command 'pane:split-up', => @splitUp(@copyActiveItem()) - @command 'pane:split-down', => @splitDown(@copyActiveItem()) + @command 'pane:split-left', => @model.splitLeft(copyActiveItem: true) + @command 'pane:split-right', => @model.splitRight(copyActiveItem: true) + @command 'pane:split-up', => @model.splitUp(copyActiveItem: true) + @command 'pane:split-down', => @model.splitDown(copyActiveItem: true) @command 'pane:close', => @model.destroyItems() @model.destroy() From 0c749537a13a51b6d3f495ce0ab416839b3a7838 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 09:39:06 -0700 Subject: [PATCH 107/355] Prepare 0.126 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9a16a6eaa..af6d4fdec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.125.0", + "version": "0.126.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 8f6053c53f00f530aef3d0958c9b4f18483a1653 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 11:31:40 -0700 Subject: [PATCH 108/355] Upgrade bracket matcher to use new apis It was really noisy with deprecations --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af6d4fdec..ea9e5cee2 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "autosave": "0.15.0", "background-tips": "0.16.0", "bookmarks": "0.28.0", - "bracket-matcher": "0.54.0", + "bracket-matcher": "0.55.0", "command-palette": "0.24.0", "deprecation-cop": "0.10.0", "dev-live-reload": "0.34.0", From b731f7cbdce1facaa61ca1346d1587c951352a0f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 08:12:51 -0600 Subject: [PATCH 109/355] Add Editor::onDidChangeTitle --- spec/editor-spec.coffee | 9 +++++---- src/editor.coffee | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 5b0af428c..adacad7d0 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -138,13 +138,14 @@ describe "Editor", -> buffer.setPath(undefined) expect(editor.getLongTitle()).toBe 'untitled' - it "emits 'title-changed' events when the underlying buffer path", -> - titleChangedHandler = jasmine.createSpy("titleChangedHandler") - editor.on 'title-changed', titleChangedHandler + it "notifies ::onDidChangeTitle observers when the underlying buffer path changes", -> + observed = [] + editor.onDidChangeTitle (title) -> observed.push(title) buffer.setPath('/foo/bar/baz.txt') buffer.setPath(undefined) - expect(titleChangedHandler.callCount).toBe 2 + + expect(observed).toEqual ['baz.txt', 'untitled'] describe "cursor", -> describe ".getLastCursor()", -> diff --git a/src/editor.coffee b/src/editor.coffee index de62f8453..fb81af254 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -4,6 +4,7 @@ Serializable = require 'serializable' Delegator = require 'delegato' {deprecate} = require 'grim' {Model} = require 'theorist' +{Emitter} = require 'event-kit' {Point, Range} = require 'text-buffer' LanguageMode = require './language-mode' DisplayBuffer = require './display-buffer' @@ -206,6 +207,7 @@ class Editor extends Model constructor: ({@softTabs, initialLine, initialColumn, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation, @mini}) -> super + @emitter = new Emitter @cursors = [] @selections = [] @@ -257,6 +259,7 @@ class Editor extends Model unless atom.project.getPath()? atom.project.setPath(path.dirname(@getPath())) @emit "title-changed" + @emitter.emit 'did-change-title', @getTitle() @emit "path-changed" @subscribe @buffer.onDidStopChanging => @emit "contents-modified" @subscribe @buffer.onDidConflict => @emit "contents-conflicted" @@ -287,6 +290,9 @@ class Editor extends Model @displayBuffer.destroy() @languageMode.destroy() + onDidChangeTitle: (callback) -> + @emitter.on 'did-change-title', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 133f3f45abad46ca17904d6d35f6af3589361e6b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 08:15:19 -0600 Subject: [PATCH 110/355] Add Editor::onDidChangePath --- spec/editor-spec.coffee | 10 ++++++++++ src/editor.coffee | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index adacad7d0..90cc4e1e0 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -147,6 +147,16 @@ describe "Editor", -> expect(observed).toEqual ['baz.txt', 'untitled'] + describe "path", -> + it "notifies ::onDidChangePath observers when the underlying buffer path changes", -> + observed = [] + editor.onDidChangePath (filePath) -> observed.push(filePath) + + buffer.setPath('/foo/bar/baz.txt') + buffer.setPath(undefined) + + expect(observed).toEqual ['/foo/bar/baz.txt', undefined] + describe "cursor", -> describe ".getLastCursor()", -> it "returns the most recently created cursor", -> diff --git a/src/editor.coffee b/src/editor.coffee index fb81af254..8598a121a 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -261,6 +261,7 @@ class Editor extends Model @emit "title-changed" @emitter.emit 'did-change-title', @getTitle() @emit "path-changed" + @emitter.emit 'did-change-path', @getPath() @subscribe @buffer.onDidStopChanging => @emit "contents-modified" @subscribe @buffer.onDidConflict => @emit "contents-conflicted" @subscribe @buffer.onDidChangeModified => @emit "modified-status-changed" @@ -293,6 +294,9 @@ class Editor extends Model onDidChangeTitle: (callback) -> @emitter.on 'did-change-title', callback + onDidChangePath: (callback) -> + @emitter.on 'did-change-path', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From d15d1572ef5d3ff219222c9e15a535838850c88f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 08:17:15 -0600 Subject: [PATCH 111/355] Add Editor::onDidChangeModified --- src/editor.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 8598a121a..1caaebd8b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -297,6 +297,9 @@ class Editor extends Model onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback + onDidChangeModified: (callback) -> + @getBuffer().onDidChangeModified(callback) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 965afc2c3753a4da286569b3fede43fae14e204f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 08:42:32 -0600 Subject: [PATCH 112/355] Rename softWrap to softWrapped Our new pattern for booleans is to have ::set and ::is, and that means the property name needs to be in passive voice for ::is to make sense. This is in preparation for adding a new change observation method. * ::setSoftWrapped * ::isSoftWrapped * ::toggleSoftWrapped --- docs/customizing-atom.md | 2 +- dot-atom/init.coffee | 2 +- menus/darwin.cson | 2 +- menus/linux.cson | 2 +- menus/win32.cson | 2 +- spec/display-buffer-spec.coffee | 14 ++++++------ spec/editor-component-spec.coffee | 10 ++++----- spec/editor-spec.coffee | 30 ++++++++++++------------- spec/random-editor-spec.coffee | 8 +++---- src/display-buffer.coffee | 32 +++++++++++++------------- src/editor-component.coffee | 2 +- src/editor-view.coffee | 10 ++++----- src/editor.coffee | 37 +++++++++++++++++++++---------- 13 files changed, 82 insertions(+), 71 deletions(-) diff --git a/docs/customizing-atom.md b/docs/customizing-atom.md index d83e960be..0b86298d6 100644 --- a/docs/customizing-atom.md +++ b/docs/customizing-atom.md @@ -123,7 +123,7 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu. - `showInvisibles`: Whether to render placeholders for invisible characters (defaults to `false`) - `showIndentGuide`: Show/hide indent indicators within the editor - `showLineNumbers`: Show/hide line numbers within the gutter - - `softWrap`: Enable/disable soft wrapping of text within the editor + - `softWrapped`: Enable/disable soft wrapping of text within the editor - `softWrapAtPreferredLineLength`: Enable/disable soft line wrapping at `preferredLineLength` - `tabLength`: Number of spaces within a tab (defaults to `2`) - `fuzzyFinder` diff --git a/dot-atom/init.coffee b/dot-atom/init.coffee index 4d10e775b..cf8a5a249 100644 --- a/dot-atom/init.coffee +++ b/dot-atom/init.coffee @@ -11,4 +11,4 @@ # atom.workspaceView.eachEditorView (editorView) -> # editor = editorView.getEditor() # if path.extname(editor.getPath()) is '.md' -# editor.setSoftWrap(true) +# editor.setSoftWrapped(true) diff --git a/menus/darwin.cson b/menus/darwin.cson index 900e42ce7..f49d0ea22 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -164,7 +164,7 @@ ] } { type: 'separator' } - { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrap' } + { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrapped' } ] } diff --git a/menus/linux.cson b/menus/linux.cson index 2f2396b85..14269e475 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -103,7 +103,7 @@ ] } { type: 'separator' } - { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' } + { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrapped' } ] } diff --git a/menus/win32.cson b/menus/win32.cson index d002c2428..f428acf4c 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -122,7 +122,7 @@ ] } { type: 'separator' } - { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' } + { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrapped' } ] } diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 75e906376..433b2a234 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -58,7 +58,7 @@ describe "DisplayBuffer", -> describe "soft wrapping", -> beforeEach -> - displayBuffer.setSoftWrap(true) + displayBuffer.setSoftWrapped(true) displayBuffer.setEditorWidthInChars(50) changeHandler.reset() @@ -129,7 +129,7 @@ describe "DisplayBuffer", -> expect(event).toEqual(start: 7, end: 8, screenDelta: -1, bufferDelta: 0) - describe "when the update causes a line to softwrap an additional time", -> + describe "when the update causes a line to soft wrap an additional time", -> it "rewraps the line and emits a change event", -> buffer.insert([6, 28], '1234567890') expect(displayBuffer.tokenizedLineForScreenRow(7).text).toBe ' current < pivot ? ' @@ -162,7 +162,7 @@ describe "DisplayBuffer", -> describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", -> it "correctly renders the original wrapped line", -> buffer = atom.project.buildBufferSync(null, '') - displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, softWrap: true}) + displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, softWrapped: true}) buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.") buffer.insert([0, Infinity], '\n') @@ -220,10 +220,10 @@ describe "DisplayBuffer", -> displayBuffer.setWidth(50) displayBuffer.manageScrollPosition = true - displayBuffer.setSoftWrap(false) + displayBuffer.setSoftWrapped(false) displayBuffer.setScrollLeft(Infinity) expect(displayBuffer.getScrollLeft()).toBeGreaterThan 0 - displayBuffer.setSoftWrap(true) + displayBuffer.setSoftWrapped(true) expect(displayBuffer.getScrollLeft()).toBe 0 displayBuffer.setScrollLeft(10) expect(displayBuffer.getScrollLeft()).toBe 0 @@ -568,7 +568,7 @@ describe "DisplayBuffer", -> describe "::clipScreenPosition(screenPosition, wrapBeyondNewlines: false, wrapAtSoftNewlines: false, skipAtomicTokens: false)", -> beforeEach -> - displayBuffer.setSoftWrap(true) + displayBuffer.setSoftWrapped(true) displayBuffer.setEditorWidthInChars(50) it "allows valid positions", -> @@ -643,7 +643,7 @@ describe "DisplayBuffer", -> it "correctly translates positions on soft wrapped lines containing tabs", -> buffer.setText('\t\taa bb cc dd ee ff gg') - displayBuffer.setSoftWrap(true) + displayBuffer.setSoftWrapped(true) displayBuffer.setEditorWidthInChars(10) expect(displayBuffer.screenPositionForBufferPosition([0, 10], wrapAtSoftNewlines: true)).toEqual [1, 0] expect(displayBuffer.bufferPositionForScreenPosition([1, 0])).toEqual [0, 10] diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 2ea61d36c..7aa902834 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -278,7 +278,7 @@ describe "EditorComponent", -> describe "when soft wrapping is enabled", -> beforeEach -> editor.setText "a line that wraps \n" - editor.setSoftWrap(true) + editor.setSoftWrapped(true) nextAnimationFrame() componentNode.style.width = 16 * charWidth + editor.getVerticalScrollbarWidth() + 'px' component.measureHeightAndWidth() @@ -457,7 +457,7 @@ describe "EditorComponent", -> expect(component.lineNumberNodeForScreenRow(6).offsetTop).toBe 6 * lineHeightInPixels it "renders • characters for soft-wrapped lines", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px' wrapperNode.style.width = 30 * charWidth + 'px' component.measureHeightAndWidth() @@ -893,7 +893,7 @@ describe "EditorComponent", -> it "only applies decorations to screen rows that are spanned by their marker when lines are soft-wrapped", -> editor.setText("a line that wraps, ok") - editor.setSoftWrap(true) + editor.setSoftWrapped(true) componentNode.style.width = 16 * charWidth + 'px' component.measureHeightAndWidth() nextAnimationFrame() @@ -2066,7 +2066,7 @@ describe "EditorComponent", -> describe "soft wrapping", -> beforeEach -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) nextAnimationFrame() it "updates the wrap location when the editor is resized", -> @@ -2192,7 +2192,7 @@ describe "EditorComponent", -> describe "legacy editor compatibility", -> it "triggers the screen-lines-changed event before the editor:display-update event", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) callingOrder = [] editor.on 'screen-lines-changed', -> callingOrder.push 'screen-lines-changed' diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 90cc4e1e0..1cf896e46 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -98,11 +98,11 @@ describe "Editor", -> expect(editor2.isFoldedAtBufferRow(4)).not.toBe editor.isFoldedAtBufferRow(4) describe "config defaults", -> - it "uses the `editor.tabLength`, `editor.softWrap`, and `editor.softTabs` config values", -> + it "uses the `editor.tabLength`, `editor.softWrapped`, and `editor.softTabs` config values", -> editor1 = null editor2 = null atom.config.set('editor.tabLength', 4) - atom.config.set('editor.softWrap', true) + atom.config.set('editor.softWrapped', true) atom.config.set('editor.softTabs', false) waitsForPromise -> @@ -110,11 +110,11 @@ describe "Editor", -> runs -> expect(editor1.getTabLength()).toBe 4 - expect(editor1.getSoftWrap()).toBe true + expect(editor1.isSoftWrapped()).toBe true expect(editor1.getSoftTabs()).toBe false atom.config.set('editor.tabLength', 100) - atom.config.set('editor.softWrap', false) + atom.config.set('editor.softWrapped', false) atom.config.set('editor.softTabs', true) waitsForPromise -> @@ -122,7 +122,7 @@ describe "Editor", -> runs -> expect(editor2.getTabLength()).toBe 100 - expect(editor2.getSoftWrap()).toBe false + expect(editor2.isSoftWrapped()).toBe false expect(editor2.getSoftTabs()).toBe true describe "title", -> @@ -214,7 +214,7 @@ describe "Editor", -> describe "when soft-wrap is enabled and code is folded", -> beforeEach -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(50) editor.createFold(2, 3) @@ -495,7 +495,7 @@ describe "Editor", -> describe ".moveToBeginningOfScreenLine()", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToBeginningOfScreenLine() @@ -515,7 +515,7 @@ describe "Editor", -> describe ".moveToEndOfScreenLine()", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToEndOfScreenLine() @@ -534,7 +534,7 @@ describe "Editor", -> describe ".moveToBeginningOfLine()", -> it "moves cursor to the beginning of the buffer line", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToBeginningOfLine() @@ -543,7 +543,7 @@ describe "Editor", -> describe ".moveToEndOfLine()", -> it "moves cursor to the end of the buffer line", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([0, 2]) editor.moveToEndOfLine() @@ -553,7 +553,7 @@ describe "Editor", -> describe ".moveToFirstCharacterOfLine()", -> 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", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition [2,5] editor.addCursorAtScreenPosition [8,7] @@ -2433,7 +2433,7 @@ describe "Editor", -> describe ".cutToEndOfLine()", -> describe "when soft wrap is on", -> it "cuts up to the end of the line", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([2, 2]) editor.cutToEndOfLine() @@ -2935,7 +2935,7 @@ describe "Editor", -> describe "when soft wrap is enabled", -> it "deletes the entire line that the cursor is on", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setEditorWidthInChars(10) editor.setCursorBufferPosition([6]) @@ -3433,7 +3433,7 @@ describe "Editor", -> describe ".setIndentationForBufferRow", -> describe "when the editor uses soft tabs but the row has hard tabs", -> it "only replaces whitespace characters", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setText("\t1\n\t2") editor.setCursorBufferPosition([0, 0]) editor.setIndentationForBufferRow(0, 2) @@ -3441,7 +3441,7 @@ describe "Editor", -> describe "when the indentation level is a non-integer", -> it "does not throw an exception", -> - editor.setSoftWrap(true) + editor.setSoftWrapped(true) editor.setText("\t1\n\t2") editor.setCursorBufferPosition([0, 0]) editor.setIndentationForBufferRow(0, 2.1) diff --git a/spec/random-editor-spec.coffee b/spec/random-editor-spec.coffee index 33d941115..8c3a65d0b 100644 --- a/spec/random-editor-spec.coffee +++ b/spec/random-editor-spec.coffee @@ -50,9 +50,9 @@ describe "Editor", -> randomlyMutateEditor = -> if Math.random() < .2 - softWrap = not editor.getSoftWrap() - steps.push(['setSoftWrap', softWrap]) - editor.setSoftWrap(softWrap) + softWrapped = not editor.isSoftWrapped() + steps.push(['setSoftWrapped', softWrapped]) + editor.setSoftWrapped(softWrapped) else range = getRandomRange() text = getRandomText() @@ -79,7 +79,7 @@ describe "Editor", -> text getReferenceScreenLines = -> - if editor.getSoftWrap() + if editor.isSoftWrapped() screenLines = [] bufferRows = [] for bufferRow in [0..tokenizedBuffer.getLastRow()] diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 6b345ab89..a114a7256 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -22,7 +22,7 @@ class DisplayBuffer extends Model @properties manageScrollPosition: false - softWrap: null + softWrapped: null editorWidthInChars: null lineHeightInPixels: null defaultCharWidth: null @@ -40,7 +40,7 @@ class DisplayBuffer extends Model constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, @invisibles}={}) -> super - @softWrap ?= atom.config.get('editor.softWrap') ? false + @softWrapped ?= atom.config.get('editor.softWrapped') ? false @tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, @invisibles}) @buffer = @tokenizedBuffer.buffer @charWidthsByScope = {} @@ -58,19 +58,19 @@ class DisplayBuffer extends Model @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated @subscribe @buffer.onDidCreateMarker @handleBufferMarkerCreated - @subscribe @$softWrap, (softWrap) => - @emit 'soft-wrap-changed', softWrap + @subscribe @$softWrapped, (softWrapped) => + @emit 'soft-wrap-changed', softWrapped @updateWrappedScreenLines() @subscribe atom.config.observe 'editor.preferredLineLength', callNow: false, => - @updateWrappedScreenLines() if @softWrap and atom.config.get('editor.softWrapAtPreferredLineLength') + @updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get('editor.softWrapAtPreferredLineLength') @subscribe atom.config.observe 'editor.softWrapAtPreferredLineLength', callNow: false, => - @updateWrappedScreenLines() if @softWrap + @updateWrappedScreenLines() if @isSoftWrapped() serializeParams: -> id: @id - softWrap: @softWrap + softWrapped: @isSoftWrapped() editorWidthInChars: @editorWidthInChars scrollTop: @scrollTop scrollLeft: @scrollLeft @@ -153,7 +153,7 @@ class DisplayBuffer extends Model horizontallyScrollable: (reentrant) -> return false unless @width? - return false if @getSoftWrap() + return false if @isSoftWrapped() if reentrant @getScrollWidth() > @getWidth() else @@ -178,7 +178,7 @@ class DisplayBuffer extends Model setWidth: (newWidth) -> oldWidth = @width @width = newWidth - @updateWrappedScreenLines() if newWidth isnt oldWidth and @softWrap + @updateWrappedScreenLines() if newWidth isnt oldWidth and @isSoftWrapped() @setScrollTop(@getScrollTop()) # Ensure scrollTop is still valid in case horizontal scrollbar disappeared @width @@ -344,11 +344,9 @@ class DisplayBuffer extends Model setInvisibles: (@invisibles) -> @tokenizedBuffer.setInvisibles(@invisibles) - # Deprecated: Use the softWrap property directly - setSoftWrap: (@softWrap) -> @softWrap + setSoftWrapped: (@softWrapped) -> @softWrapped - # Deprecated: Use the softWrap property directly - getSoftWrap: -> @softWrap + isSoftWrapped: -> @softWrapped # Set the number of characters that fit horizontally in the editor. # @@ -357,7 +355,7 @@ class DisplayBuffer extends Model if editorWidthInChars > 0 previousWidthInChars = @editorWidthInChars @editorWidthInChars = editorWidthInChars - if editorWidthInChars isnt previousWidthInChars and @softWrap + if editorWidthInChars isnt previousWidthInChars and @isSoftWrapped() @updateWrappedScreenLines() # Returns the editor width in characters for soft wrap. @@ -627,7 +625,7 @@ class DisplayBuffer extends Model unless screenLine? throw new BufferToScreenConversionError "No screen line exists when converting buffer row to screen row", - softWrapEnabled: @getSoftWrap() + softWrapEnabled: @isSoftWrapped() foldCount: @findFoldMarkers().length lastBufferRow: @buffer.getLastRow() lastScreenRow: @getLastRow() @@ -743,7 +741,7 @@ class DisplayBuffer extends Model # Returns a {Number} representing the `line` position where the wrap would take place. # Returns `null` if a wrap wouldn't occur. findWrapColumn: (line, softWrapColumn=@getSoftWrapColumn()) -> - return unless @softWrap + return unless @isSoftWrapped() return unless line.length > softWrapColumn if /\s/.test(line[softWrapColumn]) @@ -1087,7 +1085,7 @@ class DisplayBuffer extends Model computeScrollWidth: -> @scrollWidth = @pixelPositionForScreenPosition([@longestScreenRow, @maxLineLength]).left - @scrollWidth += 1 unless @getSoftWrap() + @scrollWidth += 1 unless @isSoftWrapped() @setScrollLeft(Math.min(@getScrollLeft(), @getMaxScrollLeft())) handleBufferMarkersUpdated: => diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 056c29fe7..2d2aa7286 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -478,7 +478,7 @@ EditorComponent = React.createClass 'editor:add-selection-above': -> editor.addSelectionAbove() 'editor:split-selections-into-lines': -> editor.splitSelectionsIntoLines() 'editor:toggle-soft-tabs': -> editor.toggleSoftTabs() - 'editor:toggle-soft-wrap': -> editor.toggleSoftWrap() + 'editor:toggle-soft-wrapped': -> editor.toggleSoftWrapped() 'editor:fold-all': -> editor.foldAll() 'editor:unfold-all': -> editor.unfoldAll() 'editor:fold-current-row': -> editor.foldCurrentRow() diff --git a/src/editor-view.coffee b/src/editor-view.coffee index d88a17bb3..e7c7d97e9 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -47,7 +47,7 @@ class EditorView extends View nonWordCharacters: "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" preferredLineLength: 80 tabLength: 2 - softWrap: false + softWrapped: false softTabs: true softWrapAtPreferredLineLength: false scrollSensitivity: 40 @@ -86,7 +86,7 @@ class EditorView extends View props.placeholderText = placeholderText @editor ?= new Editor buffer: new TextBuffer - softWrap: false + softWrapped: false tabLength: 2 softTabs: true mini: mini @@ -324,9 +324,9 @@ class EditorView extends View setShowIndentGuide: (showIndentGuide) -> @component.setShowIndentGuide(showIndentGuide) - setSoftWrap: (softWrap) -> - deprecate 'Use Editor::setSoftWrap instead. You can get the editor via editorView.getModel()' - @editor.setSoftWrap(softWrap) + setSoftWrap: (softWrapped) -> + deprecate 'Use Editor::setSoftWrapped instead. You can get the editor via editorView.getModel()' + @editor.setSoftWrapped(softWrapped) # Public: Set whether invisible characters are shown. # diff --git a/src/editor.coffee b/src/editor.coffee index 1caaebd8b..f9a73e98b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -70,7 +70,7 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # # Extended: Emit when soft wrap was enabled or disabled. # -# * `softWrap` {Boolean} indicating whether soft wrap is enabled or disabled. +# * `softWrapped` {Boolean} indicating whether soft wrap is enabled or disabled. # # ### grammar-changed # @@ -204,7 +204,7 @@ class Editor extends Model '$verticalScrollbarWidth', '$horizontalScrollbarHeight', '$scrollTop', '$scrollLeft', 'manageScrollPosition', toProperty: 'displayBuffer' - constructor: ({@softTabs, initialLine, initialColumn, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation, @mini}) -> + constructor: ({@softTabs, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, registerEditor, suppressCursorCreation, @mini}) -> super @emitter = new Emitter @@ -215,7 +215,7 @@ class Editor extends Model invisibles = atom.config.get('editor.invisibles') @displayBuffer?.setInvisibles(invisibles) - @displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrap, invisibles}) + @displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped, invisibles}) @buffer = @displayBuffer.buffer @softTabs = @usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true @@ -917,18 +917,31 @@ class Editor extends Model # Public: Sets the column at which column will soft wrap getSoftWrapColumn: -> @displayBuffer.getSoftWrapColumn() - # Public: Get whether soft wrap is enabled for this editor. - getSoftWrap: -> @displayBuffer.getSoftWrap() - - # Public: Enable or disable soft wrap for this editor. + # Public: Determine whether lines in this editor are soft-wrapped. # - # * `softWrap` A {Boolean} - setSoftWrap: (softWrap) -> @displayBuffer.setSoftWrap(softWrap) - - # Public: Toggle soft wrap for this editor - toggleSoftWrap: -> @setSoftWrap(not @getSoftWrap()) + # Returns a {Boolean}. + isSoftWrapped: (softWrapped) -> @displayBuffer.isSoftWrapped() + getSoftWrapped: -> + deprecate("Use Editor::isSoftWrapped instead") + @displayBuffer.isSoftWrapped() + # Public: Enable or disable soft wrapping for this editor. + # + # * `softWrapped` A {Boolean} + # + # Returns a {Boolean}. + setSoftWrapped: (softWrapped) -> @displayBuffer.setSoftWrapped(softWrapped) + setSoftWrap: (softWrapped) -> + deprecate("Use Editor::setSoftWrapped instead") + @setSoftWrapped(softWrapped) + # Public: Toggle soft wrapping for this editor + # + # Returns a {Boolean}. + toggleSoftWrapped: -> @setSoftWrapped(not @isSoftWrapped()) + toggleSoftWrap: -> + deprecate("Use Editor::toggleSoftWrapped instead") + @toggleSoftWrapped() ### Section: Indentation From 3e260eea56b6fdd6ce276ac622e2fe719bc476c4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 08:55:24 -0600 Subject: [PATCH 113/355] Add Editor::onDidChangeSoftWrapped --- src/display-buffer.coffee | 21 ++++++++++++++++----- src/editor.coffee | 3 +++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index a114a7256..4db929bdf 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -3,6 +3,7 @@ _ = require 'underscore-plus' guid = require 'guid' Serializable = require 'serializable' {Model} = require 'theorist' +{Emitter} = require 'event-kit' {Point, Range} = require 'text-buffer' TokenizedBuffer = require './tokenized-buffer' RowMap = require './row-map' @@ -40,6 +41,9 @@ class DisplayBuffer extends Model constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, @invisibles}={}) -> super + + @emitter = new Emitter + @softWrapped ?= atom.config.get('editor.softWrapped') ? false @tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, @invisibles}) @buffer = @tokenizedBuffer.buffer @@ -58,16 +62,14 @@ class DisplayBuffer extends Model @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated @subscribe @buffer.onDidCreateMarker @handleBufferMarkerCreated - @subscribe @$softWrapped, (softWrapped) => - @emit 'soft-wrap-changed', softWrapped - @updateWrappedScreenLines() - @subscribe atom.config.observe 'editor.preferredLineLength', callNow: false, => @updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get('editor.softWrapAtPreferredLineLength') @subscribe atom.config.observe 'editor.softWrapAtPreferredLineLength', callNow: false, => @updateWrappedScreenLines() if @isSoftWrapped() + @updateAllScreenLines() + serializeParams: -> id: @id softWrapped: @isSoftWrapped() @@ -96,6 +98,9 @@ class DisplayBuffer extends Model @rowMap = new RowMap @updateScreenLines(0, @buffer.getLineCount(), null, suppressChangeEvent: true) + onDidChangeSoftWrapped: (callback) -> + @emitter.on 'did-change-soft-wrapped', callback + emitChanged: (eventProperties, refreshMarkers=true) -> if refreshMarkers @pauseMarkerObservers() @@ -344,7 +349,13 @@ class DisplayBuffer extends Model setInvisibles: (@invisibles) -> @tokenizedBuffer.setInvisibles(@invisibles) - setSoftWrapped: (@softWrapped) -> @softWrapped + setSoftWrapped: (softWrapped) -> + if softWrapped isnt @softWrapped + @softWrapped = softWrapped + @updateWrappedScreenLines() + @emit 'soft-wrap-changed', @softWrapped + @emitter.emit 'did-change-soft-wrapped', @softWrapped + @softWrapped isSoftWrapped: -> @softWrapped diff --git a/src/editor.coffee b/src/editor.coffee index f9a73e98b..b0f9e45a0 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -300,6 +300,9 @@ class Editor extends Model onDidChangeModified: (callback) -> @getBuffer().onDidChangeModified(callback) + onDidChangeSoftWrapped: (callback) -> + @displayBuffer.onDidChangeSoftWrapped(callback) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 1c95a557408c9a482abf86e69ae68edf9839697f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:07:10 -0600 Subject: [PATCH 114/355] Add ::onDidChangeGrammar to Editor, DisplayBuffer, and TokenizedBuffer --- src/display-buffer.coffee | 5 ++++- src/editor.coffee | 5 ++++- src/tokenized-buffer.coffee | 9 ++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 4db929bdf..91950c6f6 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -56,7 +56,7 @@ class DisplayBuffer extends Model @decorationMarkerDestroyedSubscriptions = {} @updateAllScreenLines() @createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes()) - @subscribe @tokenizedBuffer, 'grammar-changed', (grammar) => @emit 'grammar-changed', grammar + @subscribe @tokenizedBuffer.onDidChangeGrammar (grammar) => @emit 'grammar-changed', grammar @subscribe @tokenizedBuffer, 'tokenized', => @emit 'tokenized' @subscribe @tokenizedBuffer, 'changed', @handleTokenizedBufferChange @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated @@ -101,6 +101,9 @@ class DisplayBuffer extends Model onDidChangeSoftWrapped: (callback) -> @emitter.on 'did-change-soft-wrapped', callback + onDidChangeGrammar: (callback) -> + @tokenizedBuffer.onDidChangeGrammar(callback) + emitChanged: (eventProperties, refreshMarkers=true) -> if refreshMarkers @pauseMarkerObservers() diff --git a/src/editor.coffee b/src/editor.coffee index b0f9e45a0..6ee7fed6b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -272,7 +272,7 @@ class Editor extends Model @subscribe @displayBuffer, 'marker-created', @handleMarkerCreated @subscribe @displayBuffer, "changed", (e) => @emit 'screen-lines-changed', e @subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections() - @subscribe @displayBuffer, 'grammar-changed', => @handleGrammarChange() + @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @subscribe @displayBuffer, 'tokenized', => @handleTokenization() @subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args... @subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args... @@ -303,6 +303,9 @@ class Editor extends Model onDidChangeSoftWrapped: (callback) -> @displayBuffer.onDidChangeSoftWrapped(callback) + onDidChangeGrammar: (callback)-> + @displayBuffer.onDidChangeGrammar(callback) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 0ef877869..25ad8d90f 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -1,5 +1,6 @@ _ = require 'underscore-plus' {Model} = require 'theorist' +{Emitter} = require 'event-kit' {Point, Range} = require 'text-buffer' Serializable = require 'serializable' TokenizedLine = require './tokenized-line' @@ -20,6 +21,8 @@ class TokenizedBuffer extends Model visible: false constructor: ({@buffer, @tabLength, @invisibles}) -> + @emitter = new Emitter + @tabLength ?= atom.config.getPositiveInt('editor.tabLength', 2) @subscribe atom.syntax, 'grammar-added grammar-updated', (grammar) => @@ -29,7 +32,6 @@ class TokenizedBuffer extends Model newScore = grammar.getScore(@buffer.getPath(), @buffer.getText()) @setGrammar(grammar, newScore) if newScore > @currentGrammarScore - @on 'grammar-changed grammar-updated', => @retokenizeLines() @subscribe @buffer.onDidChange (e) => @handleBufferChange(e) @subscribe @buffer.onDidChangePath (@bufferPath) => @reloadGrammar() @@ -49,13 +51,18 @@ class TokenizedBuffer extends Model params.buffer = atom.project.bufferForPathSync(params.bufferPath) params + onDidChangeGrammar: (callback) -> + @emitter.on 'did-change-grammar', callback + setGrammar: (grammar, score) -> return if grammar is @grammar @unsubscribe(@grammar) if @grammar @grammar = grammar @currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText()) @subscribe @grammar, 'grammar-updated', => @retokenizeLines() + @retokenizeLines() @emit 'grammar-changed', grammar + @emitter.emit 'did-change-grammar', grammar reloadGrammar: -> if grammar = atom.syntax.selectGrammar(@buffer.getPath(), @buffer.getText()) From 5a02303b5832b962e4b88227bcaf5ce388645cf5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:10:10 -0600 Subject: [PATCH 115/355] Add Editor::onDidStopChanging which delegates to TextBuffer --- src/editor.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 6ee7fed6b..9ccce8149 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -306,6 +306,9 @@ class Editor extends Model onDidChangeGrammar: (callback)-> @displayBuffer.onDidChangeGrammar(callback) + onDidStopChanging: (callback) -> + @getBuffer().onDidStopChanging(callback) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 63c9da02f685e8cfdae3202000fec3fae1d90f0f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:12:31 -0600 Subject: [PATCH 116/355] Add Editor::onDidConflict --- src/editor.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 9ccce8149..ef128bfcd 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -309,6 +309,9 @@ class Editor extends Model onDidStopChanging: (callback) -> @getBuffer().onDidStopChanging(callback) + onDidConflict: (callback) -> + @getBuffer().onDidConflict(callback) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 05ea381c0a359a2a5d73876f34d9c807bd657745 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:18:29 -0600 Subject: [PATCH 117/355] Add Editor::onWill/DidInsertText --- spec/editor-spec.coffee | 16 ++++++++-------- src/editor.coffee | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 1cf896e46..7b1a94bc6 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1662,7 +1662,7 @@ describe "Editor", -> beforeEach -> editor.setSelectedBufferRange([[1, 0], [1, 2]]) - it "will-insert-text and did-insert-text events are emitted when inserting text", -> + it "replaces the selection with the given text", -> range = editor.insertText('xxx') expect(range).toEqual [ [[1, 0], [1, 3]] ] expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {' @@ -1744,19 +1744,19 @@ describe "Editor", -> editor.insertText('holy cow') expect(editor.tokenizedLineForScreenRow(2).fold).toBeUndefined() - describe "when will-insert-text and did-insert-text events are used", -> + describe "when there are ::onWillInsertText and ::onDidInsertText observers", -> beforeEach -> editor.setSelectedBufferRange([[1, 0], [1, 2]]) - it "will-insert-text and did-insert-text events are emitted when inserting text", -> + it "notifies the observers when inserting text", -> willInsertSpy = jasmine.createSpy().andCallFake -> expect(buffer.lineForRow(1)).toBe ' var sort = function(items) {' didInsertSpy = jasmine.createSpy().andCallFake -> expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {' - editor.on('will-insert-text', willInsertSpy) - editor.on('did-insert-text', didInsertSpy) + editor.onWillInsertText(willInsertSpy) + editor.onDidInsertText(didInsertSpy) expect(editor.insertText('xxx')).toBeTruthy() expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {' @@ -1771,14 +1771,14 @@ describe "Editor", -> options = didInsertSpy.mostRecentCall.args[0] expect(options.text).toBe 'xxx' - it "text insertion is prevented when cancel is called from a will-insert-text handler", -> + it "cancels text insertion when an ::onWillInsertText observer calls cancel on an event", -> willInsertSpy = jasmine.createSpy().andCallFake ({cancel}) -> cancel() didInsertSpy = jasmine.createSpy() - editor.on('will-insert-text', willInsertSpy) - editor.on('did-insert-text', didInsertSpy) + editor.onWillInsertText(willInsertSpy) + editor.onDidInsertText(didInsertSpy) expect(editor.insertText('xxx')).toBe false expect(buffer.lineForRow(1)).toBe ' var sort = function(items) {' diff --git a/src/editor.coffee b/src/editor.coffee index ef128bfcd..b83afd10b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -312,6 +312,12 @@ class Editor extends Model onDidConflict: (callback) -> @getBuffer().onDidConflict(callback) + onWillInsertText: (callback) -> + @emitter.on 'will-insert-text', callback + + onDidInsertText: (callback) -> + @emitter.on 'did-insert-text', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer @@ -760,14 +766,18 @@ class Editor extends Model insertText: (text, options={}) -> willInsert = true cancel = -> willInsert = false - @emit('will-insert-text', {cancel, text}) + willInsertEvent = {cancel, text} + @emit('will-insert-text', willInsertEvent) + @emitter.emit 'will-insert-text', willInsertEvent if willInsert options.autoIndentNewline ?= @shouldAutoIndent() options.autoDecreaseIndent ?= @shouldAutoIndent() @mutateSelectedText (selection) => range = selection.insertText(text, options) - @emit('did-insert-text', {text, range}) + didInsertEvent = {text, range} + @emit('did-insert-text', didInsertEvent) + @emitter.emit 'did-insert-text', didInsertEvent range else false From 2a81687d38359c693c916d4939d0c4cf637cbb04 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:29:11 -0600 Subject: [PATCH 118/355] Add Editor::onDidMoveCursor --- spec/editor-spec.coffee | 9 +++++---- src/cursor.coffee | 2 +- src/editor.coffee | 6 +++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 7b1a94bc6..fbc307f27 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -793,19 +793,20 @@ describe "Editor", -> editor.setCursorBufferPosition([3, 1]) expect(editor.getCurrentParagraphBufferRange()).toBeUndefined() - describe "cursor-moved events", -> + describe "::onDidMoveCursor", -> cursorMovedHandler = null beforeEach -> editor.foldBufferRow(4) editor.setSelectedBufferRange([[8, 1], [9, 0]]) cursorMovedHandler = jasmine.createSpy("cursorMovedHandler") - editor.on 'cursor-moved', cursorMovedHandler + editor.onDidMoveCursor(cursorMovedHandler) describe "when the position of the cursor changes", -> - it "emits a cursor-moved event", -> + it "notifies observers", -> buffer.insert([9, 0], '...') expect(cursorMovedHandler).toHaveBeenCalledWith( + cursor: editor.getLastCursor() oldBufferPosition: [9, 0] oldScreenPosition: [6, 0] newBufferPosition: [9, 3] @@ -814,7 +815,7 @@ describe "Editor", -> ) describe "when the position of the associated selection's tail changes, but not the cursor's position", -> - it "does not emit a cursor-moved event", -> + it "does not notify observers", -> buffer.insert([8, 0], '...') expect(cursorMovedHandler).not.toHaveBeenCalled() diff --git a/src/cursor.coffee b/src/cursor.coffee index 68018a72c..f75b8f790 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -65,7 +65,7 @@ class Cursor extends Model textChanged: textChanged @emit 'moved', movedEvent - @editor.cursorMoved(movedEvent) + @editor.cursorMoved(this, movedEvent) @marker.on 'destroyed', => @destroyed = true @editor.removeCursor(this) diff --git a/src/editor.coffee b/src/editor.coffee index b83afd10b..de4369bc9 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -318,6 +318,9 @@ class Editor extends Model onDidInsertText: (callback) -> @emitter.on 'did-insert-text', callback + onDidMoveCursor: (callback) -> + @emitter.on 'did-move-cursor', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer @@ -1853,8 +1856,9 @@ class Editor extends Model @movingCursors = false @emit 'cursors-moved' - cursorMoved: (event) -> + cursorMoved: (cursor, event) -> @emit 'cursor-moved', event + @emitter.emit 'did-move-cursor', _.extend({cursor}, event) @emit 'cursors-moved' unless @movingCursors # Merge cursors that have the same screen position From 161edfd15adeaac6431dac17bdc5af79b5a2d850 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:36:49 -0600 Subject: [PATCH 119/355] =?UTF-8?q?Remove=20=E2=80=98cursors-moved?= =?UTF-8?q?=E2=80=99=20event?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It event was not document only being used in EditorComponent. Due to our batching strategy, it’s fine to respond to individual ::onDidMoveCursor events. --- spec/editor-spec.coffee | 15 --------------- src/editor-component.coffee | 14 +++++++------- src/editor.coffee | 4 ---- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index fbc307f27..2fd1b037e 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -174,21 +174,6 @@ describe "Editor", -> editor.moveDown() expect(editor.getCursorBufferPosition()).toEqual [1, 1] - it "emits a single 'cursors-moved' event for all moved cursors", -> - editor.on 'cursors-moved', cursorsMovedHandler = jasmine.createSpy("cursorsMovedHandler") - - editor.moveDown() - expect(cursorsMovedHandler.callCount).toBe 1 - - cursorsMovedHandler.reset() - editor.addCursorAtScreenPosition([3, 0]) - editor.moveDown() - expect(cursorsMovedHandler.callCount).toBe 1 - - cursorsMovedHandler.reset() - editor.getLastCursor().moveDown() - expect(cursorsMovedHandler.callCount).toBe 1 - describe ".setCursorScreenPosition(screenPosition)", -> it "clears a goal column established by vertical movement", -> # set a goal column by moving down diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 2d2aa7286..e3ec24442 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -31,7 +31,7 @@ EditorComponent = React.createClass updateRequested: false updatesPaused: false updateRequestedWhilePaused: false - cursorsMoved: false + cursorMoved: false selectionChanged: false selectionAdded: false scrollingVertically: false @@ -196,16 +196,16 @@ EditorComponent = React.createClass @props.editor.setMini(newProps.mini) componentDidUpdate: (prevProps, prevState) -> - cursorsMoved = @cursorsMoved + cursorMoved = @cursorMoved selectionChanged = @selectionChanged @pendingChanges.length = 0 - @cursorsMoved = false + @cursorMoved = false @selectionChanged = false if @props.editor.isAlive() @updateParentViewFocusedClassIfNeeded(prevState) @updateParentViewMiniClassIfNeeded(prevState) - @props.parentView.trigger 'cursor:moved' if cursorsMoved + @props.parentView.trigger 'cursor:moved' if cursorMoved @props.parentView.trigger 'selection:changed' if selectionChanged @props.parentView.trigger 'editor:display-updated' @@ -346,7 +346,7 @@ EditorComponent = React.createClass observeEditor: -> {editor} = @props @subscribe editor, 'screen-lines-changed', @onScreenLinesChanged - @subscribe editor, 'cursors-moved', @onCursorsMoved + @subscribe editor.onDidMoveCursor(@onCursorMoved) @subscribe editor, 'selection-removed selection-screen-range-changed', @onSelectionChanged @subscribe editor, 'selection-added', @onSelectionAdded @subscribe editor, 'decoration-added', @onDecorationChanged @@ -749,8 +749,8 @@ EditorComponent = React.createClass onStoppedScrollingAfterDelay: null # created lazily - onCursorsMoved: -> - @cursorsMoved = true + onCursorMoved: -> + @cursorMoved = true @requestUpdate() onDecorationChanged: -> diff --git a/src/editor.coffee b/src/editor.coffee index de4369bc9..53c01dca0 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1850,16 +1850,12 @@ class Editor extends Model @emit 'cursor-removed', cursor moveCursors: (fn) -> - @movingCursors = true fn(cursor) for cursor in @getCursors() @mergeCursors() - @movingCursors = false - @emit 'cursors-moved' cursorMoved: (cursor, event) -> @emit 'cursor-moved', event @emitter.emit 'did-move-cursor', _.extend({cursor}, event) - @emit 'cursors-moved' unless @movingCursors # Merge cursors that have the same screen position mergeCursors: -> From 3b6e40fbd830b3b9b25628e956e0c7429b9986fe Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:39:35 -0600 Subject: [PATCH 120/355] Add Editor::onDidAddCursor --- src/editor.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 53c01dca0..76db121f7 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -321,6 +321,9 @@ class Editor extends Model onDidMoveCursor: (callback) -> @emitter.on 'did-move-cursor', callback + onDidAddCursor: (callback) -> + @emitter.on 'did-add-cursor', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer @@ -1842,6 +1845,7 @@ class Editor extends Model @decorateMarker(marker, type: 'gutter', class: 'cursor-line-no-selection', onlyHead: true, onlyEmpty: true) @decorateMarker(marker, type: 'line', class: 'cursor-line', onlyEmpty: true) @emit 'cursor-added', cursor + @emitter.emit 'did-add-cursor', cursor cursor # Remove the given cursor from this editor. From e77b4a54dda6f26d04fe3c2b5ea21588e200b462 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:41:55 -0600 Subject: [PATCH 121/355] Add Editor::onDidRemoveCursor --- src/editor.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 76db121f7..62fe65982 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -324,6 +324,9 @@ class Editor extends Model onDidAddCursor: (callback) -> @emitter.on 'did-add-cursor', callback + onDidRemoveCursor: (callback) -> + @emitter.on 'did-remove-cursor', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer @@ -1852,6 +1855,7 @@ class Editor extends Model removeCursor: (cursor) -> _.remove(@cursors, cursor) @emit 'cursor-removed', cursor + @emitter.emit 'did-remove-cursor', cursor moveCursors: (fn) -> fn(cursor) for cursor in @getCursors() From 3e77b9b7c03f8760f8af1eceea9722894912c044 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:52:14 -0600 Subject: [PATCH 122/355] Eliminate Editor::onDidMoveCursor If you want to know if a cursor moved, subscribe to the cursor. --- src/editor-component.coffee | 6 +++++- src/editor.coffee | 4 ---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index e3ec24442..847aa9d57 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -346,7 +346,7 @@ EditorComponent = React.createClass observeEditor: -> {editor} = @props @subscribe editor, 'screen-lines-changed', @onScreenLinesChanged - @subscribe editor.onDidMoveCursor(@onCursorMoved) + @subscribe editor.onDidAddCursor(@onCursorAdded) @subscribe editor, 'selection-removed selection-screen-range-changed', @onSelectionChanged @subscribe editor, 'selection-added', @onSelectionAdded @subscribe editor, 'decoration-added', @onDecorationChanged @@ -749,6 +749,10 @@ EditorComponent = React.createClass onStoppedScrollingAfterDelay: null # created lazily + onCursorAdded: (cursor) -> + @subscribe cursor, 'moved', @onCursorMoved + @subscribe cursor, 'destroyed', => @unsubscribe(cursor) + onCursorMoved: -> @cursorMoved = true @requestUpdate() diff --git a/src/editor.coffee b/src/editor.coffee index 62fe65982..dfd355679 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -318,9 +318,6 @@ class Editor extends Model onDidInsertText: (callback) -> @emitter.on 'did-insert-text', callback - onDidMoveCursor: (callback) -> - @emitter.on 'did-move-cursor', callback - onDidAddCursor: (callback) -> @emitter.on 'did-add-cursor', callback @@ -1863,7 +1860,6 @@ class Editor extends Model cursorMoved: (cursor, event) -> @emit 'cursor-moved', event - @emitter.emit 'did-move-cursor', _.extend({cursor}, event) # Merge cursors that have the same screen position mergeCursors: -> From 651eb783159c62f870140707ae2eb76442a31c3a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 09:59:08 -0600 Subject: [PATCH 123/355] Add Editor::onDidAdd/RemoveSelection Also update EditorComponent to use the new ::onDidAddSelection method. --- src/editor-component.coffee | 15 +++++++++------ src/editor.coffee | 8 ++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 847aa9d57..88bea3e83 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -33,7 +33,6 @@ EditorComponent = React.createClass updateRequestedWhilePaused: false cursorMoved: false selectionChanged: false - selectionAdded: false scrollingVertically: false mouseWheelScreenRow: null mouseWheelScreenRowClearDelay: 150 @@ -347,8 +346,7 @@ EditorComponent = React.createClass {editor} = @props @subscribe editor, 'screen-lines-changed', @onScreenLinesChanged @subscribe editor.onDidAddCursor(@onCursorAdded) - @subscribe editor, 'selection-removed selection-screen-range-changed', @onSelectionChanged - @subscribe editor, 'selection-added', @onSelectionAdded + @subscribe editor.onDidAddSelection(@onSelectionAdded) @subscribe editor, 'decoration-added', @onDecorationChanged @subscribe editor, 'decoration-removed', @onDecorationChanged @subscribe editor, 'decoration-changed', @onDecorationChanged @@ -721,17 +719,22 @@ EditorComponent = React.createClass @pendingChanges.push(change) @requestUpdate() if editor.intersectsVisibleRowRange(change.start, change.end + 1) # TODO: Use closed-open intervals for change events - onSelectionChanged: (selection) -> + onSelectionAdded: (selection) -> {editor} = @props + + @subscribe selection, 'screen-range-changed', => @onSelectionChanged(selection) + @subscribe selection, 'destroyed', => + @onSelectionChanged(selection) + @unsubscribe(selection) + if editor.selectionIntersectsVisibleRowRange(selection) @selectionChanged = true @requestUpdate() - onSelectionAdded: (selection) -> + onSelectionChanged: (selection) -> {editor} = @props if editor.selectionIntersectsVisibleRowRange(selection) @selectionChanged = true - @selectionAdded = true @requestUpdate() onScrollTopChanged: -> diff --git a/src/editor.coffee b/src/editor.coffee index dfd355679..3a548a713 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -324,6 +324,12 @@ class Editor extends Model onDidRemoveCursor: (callback) -> @emitter.on 'did-remove-cursor', callback + onDidAddSelection: (callback) -> + @emitter.on 'did-add-selection', callback + + onDidRemoveSelection: (callback) -> + @emitter.on 'did-remove-selection', callback + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer @@ -2315,12 +2321,14 @@ class Editor extends Model return selection else @emit 'selection-added', selection + @emitter.emit 'did-add-selection', selection selection # Remove the given selection. removeSelection: (selection) -> _.remove(@selections, selection) @emit 'selection-removed', selection + @emitter.emit 'did-remove-selection', selection # Reduce one or more selections to a single empty selection based on the most # recently added cursor. From 1131b33a83beee07a3a476ebebf07039b29f782d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 12:07:40 -0600 Subject: [PATCH 124/355] Add DisplayBufferMarker::onDidChange and ::onDidDestroy --- spec/display-buffer-spec.coffee | 6 +++--- src/cursor.coffee | 4 ++-- src/display-buffer-marker.coffee | 19 ++++++++++++++++--- src/selection.coffee | 4 ++-- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 433b2a234..ca5048433 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -722,7 +722,7 @@ describe "DisplayBuffer", -> beforeEach -> marker = displayBuffer.markScreenRange([[5, 4], [5, 10]]) - marker.on 'changed', markerChangedHandler = jasmine.createSpy("markerChangedHandler") + marker.onDidChange markerChangedHandler = jasmine.createSpy("markerChangedHandler") it "triggers the 'changed' event whenever the markers head's screen position changes in the buffer or on screen", -> marker.setHeadScreenPosition([8, 20]) @@ -859,7 +859,7 @@ describe "DisplayBuffer", -> it "updates markers before emitting buffer change events, but does not notify their observers until the change event", -> marker2 = displayBuffer.markBufferRange([[8, 1], [8, 1]]) - marker2.on 'changed', marker2ChangedHandler = jasmine.createSpy("marker2ChangedHandler") + marker2.onDidChange marker2ChangedHandler = jasmine.createSpy("marker2ChangedHandler") displayBuffer.on 'changed', changeHandler = jasmine.createSpy("changeHandler").andCallFake -> onDisplayBufferChange() # New change ---- @@ -886,7 +886,7 @@ describe "DisplayBuffer", -> marker2ChangedHandler.reset() marker3 = displayBuffer.markBufferRange([[8, 1], [8, 2]]) - marker3.on 'changed', marker3ChangedHandler = jasmine.createSpy("marker3ChangedHandler") + marker3.onDidChange marker3ChangedHandler = jasmine.createSpy("marker3ChangedHandler") onDisplayBufferChange = -> # calls change handler first diff --git a/src/cursor.coffee b/src/cursor.coffee index f75b8f790..95807d978 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -44,7 +44,7 @@ class Cursor extends Model constructor: ({@editor, @marker, id}) -> @assignId(id) @updateVisibility() - @marker.on 'changed', (e) => + @marker.onDidChange (e) => @updateVisibility() {oldHeadScreenPosition, newHeadScreenPosition} = e {oldHeadBufferPosition, newHeadBufferPosition} = e @@ -66,7 +66,7 @@ class Cursor extends Model @emit 'moved', movedEvent @editor.cursorMoved(this, movedEvent) - @marker.on 'destroyed', => + @marker.onDidDestroy => @destroyed = true @editor.removeCursor(this) @emit 'destroyed' diff --git a/src/display-buffer-marker.coffee b/src/display-buffer-marker.coffee index 7f868f24e..6d7b97e6f 100644 --- a/src/display-buffer-marker.coffee +++ b/src/display-buffer-marker.coffee @@ -1,10 +1,12 @@ {Range} = require 'text-buffer' _ = require 'underscore-plus' -{Emitter, Subscriber} = require 'emissary' +{Subscriber} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' module.exports = class DisplayBufferMarker - Emitter.includeInto(this) + EmitterMixin.includeInto(this) Subscriber.includeInto(this) bufferMarkerSubscription: null @@ -15,6 +17,7 @@ class DisplayBufferMarker wasValid: true constructor: ({@bufferMarker, @displayBuffer}) -> + @emitter = new Emitter @id = @bufferMarker.id @oldHeadBufferPosition = @getHeadBufferPosition() @oldHeadScreenPosition = @getHeadScreenPosition() @@ -25,6 +28,12 @@ class DisplayBufferMarker @subscribe @bufferMarker.onDidDestroy => @destroyed() @subscribe @bufferMarker.onDidChange (event) => @notifyObservers(event) + onDidChange: (callback) -> + @emitter.on 'did-change', callback + + onDidDestroy: (callback) -> + @emitter.on 'did-destroy', callback + copy: (attributes) -> @displayBuffer.getMarker(@bufferMarker.copy(attributes).id) @@ -199,6 +208,8 @@ class DisplayBufferMarker destroyed: -> delete @displayBuffer.markers[@id] @emit 'destroyed' + @emitter.emit 'did-destroy' + @emitter.dispose() notifyObservers: ({textChanged}) -> textChanged ?= false @@ -215,7 +226,7 @@ class DisplayBufferMarker _.isEqual(newTailBufferPosition, @oldTailBufferPosition) and _.isEqual(newTailScreenPosition, @oldTailScreenPosition) - @emit 'changed', { + changeEvent = { @oldHeadScreenPosition, newHeadScreenPosition, @oldTailScreenPosition, newTailScreenPosition, @oldHeadBufferPosition, newHeadBufferPosition, @@ -223,6 +234,8 @@ class DisplayBufferMarker textChanged, isValid } + @emit 'changed', changeEvent + @emitter.emit 'did-change', changeEvent @oldHeadBufferPosition = newHeadBufferPosition @oldHeadScreenPosition = newHeadScreenPosition diff --git a/src/selection.coffee b/src/selection.coffee index 38198fef4..a071f8d83 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -30,8 +30,8 @@ class Selection extends Model @cursor.selection = this @decoration = @editor.decorateMarker(@marker, type: 'highlight', class: 'selection') - @marker.on 'changed', => @screenRangeChanged() - @marker.on 'destroyed', => + @marker.onDidChange => @screenRangeChanged() + @marker.onDidDestroy => @destroyed = true @editor.removeSelection(this) @emit 'destroyed' unless @editor.isDestroyed() From c69b5fc0a0a8e7672295f94ab13342d49cecaaa7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 13:27:53 -0600 Subject: [PATCH 125/355] Remove specs for ::onDidMoveCursor, which was removed --- spec/editor-spec.coffee | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 2fd1b037e..3e5bd6460 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -778,38 +778,6 @@ describe "Editor", -> editor.setCursorBufferPosition([3, 1]) expect(editor.getCurrentParagraphBufferRange()).toBeUndefined() - describe "::onDidMoveCursor", -> - cursorMovedHandler = null - - beforeEach -> - editor.foldBufferRow(4) - editor.setSelectedBufferRange([[8, 1], [9, 0]]) - cursorMovedHandler = jasmine.createSpy("cursorMovedHandler") - editor.onDidMoveCursor(cursorMovedHandler) - - describe "when the position of the cursor changes", -> - it "notifies observers", -> - buffer.insert([9, 0], '...') - expect(cursorMovedHandler).toHaveBeenCalledWith( - cursor: editor.getLastCursor() - oldBufferPosition: [9, 0] - oldScreenPosition: [6, 0] - newBufferPosition: [9, 3] - newScreenPosition: [6, 3] - textChanged: true - ) - - describe "when the position of the associated selection's tail changes, but not the cursor's position", -> - it "does not notify observers", -> - buffer.insert([8, 0], '...') - expect(cursorMovedHandler).not.toHaveBeenCalled() - - describe "::getCursorBufferPositions()", -> - it "returns the cursor positions in the order they were added", -> - cursor1 = editor.addCursorAtBufferPosition([8, 5]) - cursor2 = editor.addCursorAtBufferPosition([4, 5]) - expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [8, 5], [4, 5]] - describe "::getCursorScreenPositions()", -> it "returns the cursor positions in the order they were added", -> editor.foldBufferRow(4) From 6bd87024213e2fb27eb769a1cb6d079bf119bc9e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 13:28:19 -0600 Subject: [PATCH 126/355] Deprecate DisplayBufferMarker::on --- spec/display-buffer-spec.coffee | 6 +++--- src/display-buffer-marker.coffee | 30 ++++++++++++++++++++++++++++-- src/display-buffer.coffee | 22 +++++++++++----------- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index ca5048433..acdaa1136 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -998,16 +998,16 @@ describe "DisplayBuffer", -> expect(marker.isValid()).toBeFalsy() expect(displayBuffer.getMarker(marker.id)).toBeUndefined() - it "emits 'destroyed' events when markers are destroyed", -> + it "notifies ::onDidDestroy observers when markers are destroyed", -> destroyedHandler = jasmine.createSpy("destroyedHandler") marker = displayBuffer.markScreenRange([[5, 4], [5, 10]]) - marker.on 'destroyed', destroyedHandler + marker.onDidDestroy destroyedHandler marker.destroy() expect(destroyedHandler).toHaveBeenCalled() destroyedHandler.reset() marker2 = displayBuffer.markScreenRange([[5, 4], [5, 10]]) - marker2.on 'destroyed', destroyedHandler + marker2.onDidDestroy destroyedHandler buffer.getMarker(marker2.id).destroy() expect(destroyedHandler).toHaveBeenCalled() diff --git a/src/display-buffer-marker.coffee b/src/display-buffer-marker.coffee index 6d7b97e6f..8300cac23 100644 --- a/src/display-buffer-marker.coffee +++ b/src/display-buffer-marker.coffee @@ -3,6 +3,7 @@ _ = require 'underscore-plus' {Subscriber} = require 'emissary' EmitterMixin = require('emissary').Emitter {Emitter} = require 'event-kit' +Grim = require 'grim' module.exports = class DisplayBufferMarker @@ -15,6 +16,7 @@ class DisplayBufferMarker oldTailBufferPosition: null oldTailScreenPosition: null wasValid: true + deferredChangeEvents: null constructor: ({@bufferMarker, @displayBuffer}) -> @emitter = new Emitter @@ -34,6 +36,15 @@ class DisplayBufferMarker onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback + on: (eventName) -> + switch eventName + when 'changed' + Grim.deprecate("Use DisplayBufferMarker::onDidChange instead") + when 'destroyed' + Grim.deprecate("Use DisplayBufferMarker::onDidDestroy instead") + + EmitterMixin::on.apply(this, arguments) + copy: (attributes) -> @displayBuffer.getMarker(@bufferMarker.copy(attributes).id) @@ -234,11 +245,26 @@ class DisplayBufferMarker textChanged, isValid } - @emit 'changed', changeEvent - @emitter.emit 'did-change', changeEvent + + if @deferredChangeEvents? + @deferredChangeEvents.push(changeEvent) + else + @emit 'changed', changeEvent + @emitter.emit 'did-change', changeEvent @oldHeadBufferPosition = newHeadBufferPosition @oldHeadScreenPosition = newHeadScreenPosition @oldTailBufferPosition = newTailBufferPosition @oldTailScreenPosition = newTailScreenPosition @wasValid = isValid + + pauseChangeEvents: -> + @deferredChangeEvents = [] + + resumeChangeEvents: -> + if deferredChangeEvents = @deferredChangeEvents + @deferredChangeEvents = null + + for event in deferredChangeEvents + @emit 'changed', event + @emitter.emit 'did-change', event diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 91950c6f6..456aea179 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -106,10 +106,10 @@ class DisplayBuffer extends Model emitChanged: (eventProperties, refreshMarkers=true) -> if refreshMarkers - @pauseMarkerObservers() + @pauseMarkerChangeEvents() @refreshMarkerScreenPositions() @emit 'changed', eventProperties - @resumeMarkerObservers() + @resumeMarkerChangeEvents() updateWrappedScreenLines: -> start = 0 @@ -788,10 +788,10 @@ class DisplayBuffer extends Model decorateMarker: (marker, decorationParams) -> marker = @getMarker(marker.id) - @decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', => + @decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker.onDidDestroy => @removeAllDecorationsForMarker(marker) - @decorationMarkerChangedSubscriptions[marker.id] ?= @subscribe marker, 'changed', (event) => + @decorationMarkerChangedSubscriptions[marker.id] ?= @subscribe marker.onDidChange (event) => decorations = @decorationsByMarkerId[marker.id] # Why check existence? Markers may get destroyed or decorations removed @@ -825,8 +825,8 @@ class DisplayBuffer extends Model @removedAllMarkerDecorations(marker) removedAllMarkerDecorations: (marker) -> - @decorationMarkerChangedSubscriptions[marker.id].off() - @decorationMarkerDestroyedSubscriptions[marker.id].off() + @decorationMarkerChangedSubscriptions[marker.id].dispose() + @decorationMarkerDestroyedSubscriptions[marker.id].dispose() delete @decorationsByMarkerId[marker.id] delete @decorationMarkerChangedSubscriptions[marker.id] @@ -977,11 +977,11 @@ class DisplayBuffer extends Model getFoldMarkerAttributes: (attributes={}) -> _.extend(attributes, class: 'fold', displayBufferId: @id) - pauseMarkerObservers: -> - marker.pauseEvents() for marker in @getMarkers() + pauseMarkerChangeEvents: -> + marker.pauseChangeEvents() for marker in @getMarkers() - resumeMarkerObservers: -> - marker.resumeEvents() for marker in @getMarkers() + resumeMarkerChangeEvents: -> + marker.resumeChangeEvents() for marker in @getMarkers() @emit 'markers-updated' refreshMarkerScreenPositions: -> @@ -1024,7 +1024,7 @@ class DisplayBuffer extends Model bufferDelta: bufferDelta if options.delayChangeEvent - @pauseMarkerObservers() + @pauseMarkerChangeEvents() @pendingChangeEvent = changeEvent else @emitChanged(changeEvent, options.refreshMarkers) From 56687027b6c6e954b6868007fdd9313773d926e4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 14:09:21 -0600 Subject: [PATCH 127/355] Add Cursor::onDidChangePosition and ::onDidDestroy and deprecate ::on --- src/cursor.coffee | 22 ++++++++++++++++++++++ src/editor-component.coffee | 3 +-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 95807d978..a35cf4d68 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -1,6 +1,8 @@ {Point, Range} = require 'text-buffer' {Model} = require 'theorist' +{Emitter} = require 'event-kit' _ = require 'underscore-plus' +Grim = require 'grim' # Extended: The `Cursor` class represents the little blinking line identifying # where text can be inserted. @@ -42,6 +44,8 @@ class Cursor extends Model # Instantiated by an {Editor} constructor: ({@editor, @marker, id}) -> + @emitter = new Emitter + @assignId(id) @updateVisibility() @marker.onDidChange (e) => @@ -65,13 +69,31 @@ class Cursor extends Model textChanged: textChanged @emit 'moved', movedEvent + @emitter.emit 'did-change-position' @editor.cursorMoved(this, movedEvent) @marker.onDidDestroy => @destroyed = true @editor.removeCursor(this) @emit 'destroyed' + @emitter.emit 'did-destroy' + @emitter.dispose() @needsAutoscroll = true + onDidChangePosition: (callback) -> + @emitter.on 'did-change-position', callback + + onDidDestroy: (callback) -> + @emitter.on 'did-destroy', callback + + on: (eventName) -> + switch eventName + when 'moved' + Grim.deprecate("Use Cursor::onDidChangePosition instead") + when 'destroyed' + Grim.deprecate("Use Cursor::onDidDestroy instead") + + super + destroy: -> @marker.destroy() diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 88bea3e83..5987bb684 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -753,8 +753,7 @@ EditorComponent = React.createClass onStoppedScrollingAfterDelay: null # created lazily onCursorAdded: (cursor) -> - @subscribe cursor, 'moved', @onCursorMoved - @subscribe cursor, 'destroyed', => @unsubscribe(cursor) + @subscribe cursor.onDidChangePosition @onCursorMoved onCursorMoved: -> @cursorMoved = true From 6ad9531e5c111d73361810344fa00abd9665817d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 14:40:12 -0600 Subject: [PATCH 128/355] Add Selection::onDidChangeRange and ::onDidDestroy and deprecate ::on --- spec/editor-spec.coffee | 2 +- spec/selection-spec.coffee | 4 ++-- src/editor-component.coffee | 4 ++-- src/selection.coffee | 32 +++++++++++++++++++++++++++----- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 3e5bd6460..8b992a2aa 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1889,7 +1889,7 @@ describe "Editor", -> beforeEach -> selection = editor.getLastSelection() changeScreenRangeHandler = jasmine.createSpy('changeScreenRangeHandler') - selection.on 'screen-range-changed', changeScreenRangeHandler + selection.onDidChangeRange changeScreenRangeHandler describe "when the cursor is on the middle of the line", -> it "removes the character before the cursor", -> diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index 020dffa86..cbaf3be86 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -57,10 +57,10 @@ describe "Selection", -> expect(selection.isReversed()).toBeFalsy() describe "when only the selection's tail is moved (regression)", -> - it "emits the 'screen-range-changed' event", -> + it "notifies ::onDidChangeRange observers", -> selection.setBufferRange([[2, 0], [2, 10]], reversed: true) changeScreenRangeHandler = jasmine.createSpy('changeScreenRangeHandler') - selection.on 'screen-range-changed', changeScreenRangeHandler + selection.onDidChangeRange changeScreenRangeHandler buffer.insert([2, 5], 'abc') expect(changeScreenRangeHandler).toHaveBeenCalled() diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 5987bb684..016324b46 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -722,8 +722,8 @@ EditorComponent = React.createClass onSelectionAdded: (selection) -> {editor} = @props - @subscribe selection, 'screen-range-changed', => @onSelectionChanged(selection) - @subscribe selection, 'destroyed', => + @subscribe selection.onDidChangeRange => @onSelectionChanged(selection) + @subscribe selection.onDidDestroy => @onSelectionChanged(selection) @unsubscribe(selection) diff --git a/src/selection.coffee b/src/selection.coffee index a071f8d83..3be1869fe 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -1,6 +1,8 @@ {Point, Range} = require 'text-buffer' {Model} = require 'theorist' {pick} = require 'underscore-plus' +{Emitter} = require 'event-kit' +Grim = require 'grim' # Extended: Represents a selection in the {Editor}. # @@ -26,15 +28,35 @@ class Selection extends Model needsAutoscroll: null constructor: ({@cursor, @marker, @editor, id}) -> + @emitter = new Emitter + @assignId(id) @cursor.selection = this @decoration = @editor.decorateMarker(@marker, type: 'highlight', class: 'selection') @marker.onDidChange => @screenRangeChanged() @marker.onDidDestroy => - @destroyed = true - @editor.removeSelection(this) - @emit 'destroyed' unless @editor.isDestroyed() + unless @editor.isDestroyed() + @destroyed = true + @editor.removeSelection(this) + @emit 'destroyed' + @emitter.emit 'did-destroy' + @emitter.dispose() + + onDidChangeRange: (callback) -> + @emitter.on 'did-change-range', callback + + onDidDestroy: (callback) -> + @emitter.on 'did-destroy', callback + + on: (eventName) -> + switch eventName + when 'screen-range-changed' + Grim.deprecate("Use Selection::onDidChangeRange instead. Call ::getScreenRange() yourself in your callback if you need the range.") + when 'destroyed' + Grim.deprecate("Use Selection::onDidDestroy instead.") + + super destroy: -> @marker.destroy() @@ -665,6 +687,6 @@ class Selection extends Model @getBufferRange().compare(otherSelection.getBufferRange()) screenRangeChanged: -> - screenRange = @getScreenRange() - @emit 'screen-range-changed', screenRange + @emit 'screen-range-changed', @getScreenRange() + @emitter.emit 'did-change-range' @editor.selectionScreenRangeChanged(this) From 569c403d560eea8ca2d1d0b4abd4e13c28d226a2 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:08:35 -0700 Subject: [PATCH 129/355] Update the events on decorations --- src/decoration.coffee | 54 +++++++++++++++++++++++----------- src/highlight-component.coffee | 5 ++-- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/decoration.coffee b/src/decoration.coffee index 3d888ab34..f3c4604de 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -1,5 +1,7 @@ _ = require 'underscore-plus' -{Subscriber, Emitter} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' +Grim = require 'grim' idCounter = 0 nextId = -> idCounter++ @@ -26,24 +28,9 @@ nextId = -> idCounter++ # # You should only use {Decoration::destroy} when you still need or do not own # the marker. -# -# ## Events -# -# ### updated -# -# Extended: When the {Decoration} is updated via {Decoration::update}. -# -# * `event` {Object} -# * `oldParams` {Object} the old parameters the decoration used to have -# * `newParams` {Object} the new parameters the decoration now has -# -# ### destroyed -# -# Extended: When the {Decoration} is destroyed -# module.exports = class Decoration - Emitter.includeInto(this) + EmitterMixin.includeInto(this) # Extended: Check if the `decorationParams.type` matches `type` # @@ -60,6 +47,7 @@ class Decoration type is decorationParams.type constructor: (@marker, @displayBuffer, @params) -> + @emitter = new Emitter @id = nextId() @params.id = @id @flashQueue = null @@ -84,6 +72,14 @@ class Decoration isType: (type) -> Decoration.isType(@params, type) + # Essential: When the {Decoration} is updated via {Decoration::update}. + # + # * `event` {Object} + # * `oldParams` {Object} the old parameters the decoration used to have + # * `newParams` {Object} the new parameters the decoration now has + onDidUpdate: (callback) -> + @emitter.on 'did-update', callback + # Essential: Update the marker with new params. Allows you to change the decoration's class. # # ## Examples @@ -100,6 +96,11 @@ class Decoration @params.id = @id @displayBuffer.decorationUpdated(this) @emit 'updated', {oldParams, newParams} + @emitter.emit 'did-update', {oldParams, newParams} + + # Essential: Invoke the given callback when the {Decoration} is destroyed + onDidDestroy: (callback) -> + @emitter.on 'did-destroy', callback # Essential: Destroy this marker. # @@ -110,6 +111,8 @@ class Decoration @isDestroyed = true @displayBuffer.removeDecoration(this) @emit 'destroyed' + @emitter.emit 'did-destroy' + @emitter.dispose() matchesPattern: (decorationPattern) -> return false unless decorationPattern? @@ -117,12 +120,29 @@ class Decoration return false if @params[key] != value true + onDidFlash: (callback) -> + @emitter.on 'did-flash', callback + flash: (klass, duration=500) -> flashObject = {class: klass, duration} @flashQueue ?= [] @flashQueue.push(flashObject) @emit 'flash' + @emitter.emit 'did-flash' consumeNextFlash: -> return @flashQueue.shift() if @flashQueue?.length > 0 null + + on: (eventName) -> + switch eventName + when 'updated' + Grim.deprecate("Use Decoration::onDidUpdate instead") + when 'destroyed' + Grim.deprecate("Use Decoration::onDidDestroy instead") + when 'flash' + Grim.deprecate("Use Decoration::onDidFlash instead") + else + Grim.deprecate("Decoration::on is deprecated. Use event subscription methods instead.") + + EmitterMixin::on.apply(this, arguments) diff --git a/src/highlight-component.coffee b/src/highlight-component.coffee index a26cb528b..b33a41974 100644 --- a/src/highlight-component.coffee +++ b/src/highlight-component.coffee @@ -22,11 +22,12 @@ HighlightComponent = React.createClass {editor, decoration} = @props if decoration.id? @decoration = editor.decorationForId(decoration.id) - @decoration.on 'flash', @startFlashAnimation + @decorationDisposable = @decoration.onDidFlash @startFlashAnimation @startFlashAnimation() componentWillUnmount: -> - @decoration?.off 'flash', @startFlashAnimation + @decorationDisposable?.dispose() + @decorationDisposable = null startFlashAnimation: -> return unless flash = @decoration.consumeNextFlash() From 9435f852dd6f9662f4d0ae02d9b200a089db6a91 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:25:14 -0700 Subject: [PATCH 130/355] Use new decoration updated event method --- spec/display-buffer-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index acdaa1136..e0e34d973 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -1074,7 +1074,7 @@ describe "DisplayBuffer", -> describe "when a decoration is updated via Decoration::update()", -> it "emits an 'updated' event containing the new and old params", -> - decoration.on 'updated', updatedSpy = jasmine.createSpy() + decoration.onDidUpdate updatedSpy = jasmine.createSpy() decoration.update type: 'gutter', class: 'two' {oldParams, newParams} = updatedSpy.mostRecentCall.args[0] From bcc6adff4fcf3301b1422f479040628a18ac6c01 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:26:06 -0700 Subject: [PATCH 131/355] No longer need this as the event method passes it through --- src/display-buffer.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 456aea179..9d0cccc92 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -56,7 +56,6 @@ class DisplayBuffer extends Model @decorationMarkerDestroyedSubscriptions = {} @updateAllScreenLines() @createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes()) - @subscribe @tokenizedBuffer.onDidChangeGrammar (grammar) => @emit 'grammar-changed', grammar @subscribe @tokenizedBuffer, 'tokenized', => @emit 'tokenized' @subscribe @tokenizedBuffer, 'changed', @handleTokenizedBufferChange @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated From 48a68d87f5d3d499cb46693adaf7197f76d2eaa1 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:26:54 -0700 Subject: [PATCH 132/355] Add TextBuffer::onDidChange --- src/display-buffer.coffee | 2 +- src/tokenized-buffer.coffee | 28 +++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 9d0cccc92..6c5a4fb80 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -57,7 +57,7 @@ class DisplayBuffer extends Model @updateAllScreenLines() @createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes()) @subscribe @tokenizedBuffer, 'tokenized', => @emit 'tokenized' - @subscribe @tokenizedBuffer, 'changed', @handleTokenizedBufferChange + @subscribe @tokenizedBuffer.onDidChange @handleTokenizedBufferChange @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated @subscribe @buffer.onDidCreateMarker @handleBufferMarkerCreated diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 25ad8d90f..4c2a688ae 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -1,10 +1,12 @@ _ = require 'underscore-plus' {Model} = require 'theorist' +EmitterMixin = require('emissary').Emitter {Emitter} = require 'event-kit' {Point, Range} = require 'text-buffer' Serializable = require 'serializable' TokenizedLine = require './tokenized-line' Token = require './token' +Grim = require 'grim' module.exports = class TokenizedBuffer extends Model @@ -54,6 +56,20 @@ class TokenizedBuffer extends Model onDidChangeGrammar: (callback) -> @emitter.on 'did-change-grammar', callback + onDidChange: (callback) -> + @emitter.on 'did-change', callback + + on: (eventName) -> + switch eventName + when 'changed' + Grim.deprecate("Use DisplayBuffer::onDidChange instead") + when 'grammar-changed' + Grim.deprecate("Use DisplayBuffer::onDidChangeGrammar instead") + # else + # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") + + EmitterMixin::on.apply(this, arguments) + setGrammar: (grammar, score) -> return if grammar is @grammar @unsubscribe(@grammar) if @grammar @@ -82,7 +98,9 @@ class TokenizedBuffer extends Model @invalidRows = [] @invalidateRow(0) @fullyTokenized = false - @emit "changed", {start: 0, end: lastRow, delta: 0} + event = {start: 0, end: lastRow, delta: 0} + @emit 'changed', event + @emitter.emit 'did-change', event setVisible: (@visible) -> @tokenizeInBackground() if @visible @@ -132,7 +150,9 @@ class TokenizedBuffer extends Model @validateRow(row) @invalidateRow(row + 1) unless filledRegion - @emit "changed", { start: invalidRow, end: row, delta: 0 } + event = { start: invalidRow, end: row, delta: 0 } + @emit 'changed', event + @emitter.emit 'did-change', event if @firstInvalidRow()? @tokenizeInBackground() @@ -178,7 +198,9 @@ class TokenizedBuffer extends Model if newEndStack and not _.isEqual(newEndStack, previousEndStack) @invalidateRow(end + delta + 1) - @emit "changed", { start, end, delta, bufferChange: e } + event = { start, end, delta, bufferChange: e } + @emit 'changed', event + @emitter.emit 'did-change', event retokenizeWhitespaceRowsIfIndentLevelChanged: (row, increment) -> line = @tokenizedLines[row] From a2adbff3e9b5338015653c5fab44764f47371370 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:33:28 -0700 Subject: [PATCH 133/355] Add TokenizedBuffer::onDidTokenize --- spec/tokenized-buffer-spec.coffee | 6 +++--- src/display-buffer.coffee | 4 +++- src/editor.coffee | 2 +- src/tokenized-buffer.coffee | 9 ++++++++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index ad90c4ded..64c06c482 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -468,7 +468,7 @@ describe "TokenizedBuffer", -> runs -> tokenizedBuffer = editor.displayBuffer.tokenizedBuffer - tokenizedBuffer.on 'tokenized', tokenizedHandler + tokenizedBuffer.onDidTokenize tokenizedHandler fullyTokenize(tokenizedBuffer) expect(tokenizedHandler.callCount).toBe(1) @@ -483,7 +483,7 @@ describe "TokenizedBuffer", -> tokenizedBuffer = editor.displayBuffer.tokenizedBuffer fullyTokenize(tokenizedBuffer) - tokenizedBuffer.on 'tokenized', tokenizedHandler + tokenizedBuffer.onDidTokenize tokenizedHandler editor.getBuffer().insert([0, 0], "'") fullyTokenize(tokenizedBuffer) expect(tokenizedHandler).not.toHaveBeenCalled() @@ -499,7 +499,7 @@ describe "TokenizedBuffer", -> runs -> tokenizedBuffer = editor.displayBuffer.tokenizedBuffer - tokenizedBuffer.on 'tokenized', tokenizedHandler + tokenizedBuffer.onDidTokenize tokenizedHandler fullyTokenize(tokenizedBuffer) tokenizedHandler.reset() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 6c5a4fb80..a00778a5b 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -56,7 +56,6 @@ class DisplayBuffer extends Model @decorationMarkerDestroyedSubscriptions = {} @updateAllScreenLines() @createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes()) - @subscribe @tokenizedBuffer, 'tokenized', => @emit 'tokenized' @subscribe @tokenizedBuffer.onDidChange @handleTokenizedBufferChange @subscribe @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated @subscribe @buffer.onDidCreateMarker @handleBufferMarkerCreated @@ -103,6 +102,9 @@ class DisplayBuffer extends Model onDidChangeGrammar: (callback) -> @tokenizedBuffer.onDidChangeGrammar(callback) + onDidTokenize: (callback) -> + @tokenizedBuffer.onDidTokenize(callback) + emitChanged: (eventProperties, refreshMarkers=true) -> if refreshMarkers @pauseMarkerChangeEvents() diff --git a/src/editor.coffee b/src/editor.coffee index 3a548a713..734187c84 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -273,7 +273,7 @@ class Editor extends Model @subscribe @displayBuffer, "changed", (e) => @emit 'screen-lines-changed', e @subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections() @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() - @subscribe @displayBuffer, 'tokenized', => @handleTokenization() + @subscribe @displayBuffer.onDidTokenize => @handleTokenization() @subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args... @subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args... @subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args... diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 4c2a688ae..9273e21de 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -59,12 +59,17 @@ class TokenizedBuffer extends Model onDidChange: (callback) -> @emitter.on 'did-change', callback + onDidTokenize: (callback) -> + @emitter.on 'did-tokenize', callback + on: (eventName) -> switch eventName when 'changed' Grim.deprecate("Use DisplayBuffer::onDidChange instead") when 'grammar-changed' Grim.deprecate("Use DisplayBuffer::onDidChangeGrammar instead") + when 'tokenized' + Grim.deprecate("Use DisplayBuffer::onDidTokenize instead") # else # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") @@ -157,7 +162,9 @@ class TokenizedBuffer extends Model if @firstInvalidRow()? @tokenizeInBackground() else - @emit "tokenized" unless @fullyTokenized + unless @fullyTokenized + @emit 'tokenized' + @emitter.emit 'did-tokenize' @fullyTokenized = true firstInvalidRow: -> From 53fbfb8b2773e2dee6a38a315dcb78c7a9f527dc Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:35:52 -0700 Subject: [PATCH 134/355] Merge decoration-changed and decoration-updated Only emit the decorations from the events --- src/display-buffer.coffee | 8 ++++---- src/editor-component.coffee | 1 - src/editor.coffee | 9 --------- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index a00778a5b..82372cb33 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -799,13 +799,13 @@ class DisplayBuffer extends Model # in the change handler. Bookmarks does this. if decorations? for decoration in decorations - @emit 'decoration-changed', marker, decoration, event + @emit 'decoration-updated', decoration decoration = new Decoration(marker, this, decorationParams) @decorationsByMarkerId[marker.id] ?= [] @decorationsByMarkerId[marker.id].push(decoration) @decorationsById[decoration.id] = decoration - @emit 'decoration-added', marker, decoration + @emit 'decoration-added', decoration decoration removeDecoration: (decoration) -> @@ -816,13 +816,13 @@ class DisplayBuffer extends Model if index > -1 decorations.splice(index, 1) delete @decorationsById[decoration.id] - @emit 'decoration-removed', marker, decoration + @emit 'decoration-removed', decoration @removedAllMarkerDecorations(marker) if decorations.length is 0 removeAllDecorationsForMarker: (marker) -> decorations = @decorationsByMarkerId[marker.id].slice() for decoration in decorations - @emit 'decoration-removed', marker, decoration + @emit 'decoration-removed', decoration @removedAllMarkerDecorations(marker) removedAllMarkerDecorations: (marker) -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 016324b46..cfadc9b65 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -349,7 +349,6 @@ EditorComponent = React.createClass @subscribe editor.onDidAddSelection(@onSelectionAdded) @subscribe editor, 'decoration-added', @onDecorationChanged @subscribe editor, 'decoration-removed', @onDecorationChanged - @subscribe editor, 'decoration-changed', @onDecorationChanged @subscribe editor, 'decoration-updated', @onDecorationChanged @subscribe editor, 'character-widths-changed', @onCharacterWidthsChanged @subscribe editor.$scrollTop.changes, @onScrollTopChanged diff --git a/src/editor.coffee b/src/editor.coffee index 734187c84..55199defa 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -165,14 +165,6 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # # * `decoration` {Decoration} that was removed # -# ### decoration-changed -# -# Extended: Emit when a {Decoration}'s underlying marker changes. Say the user -# inserts newlines above a decoration. That action will move the marker down, -# and fire this event. -# -# * `decoration` {Decoration} that was added -# # ### decoration-updated # # Extended: Emit when a {Decoration} is updated via the {Decoration::update} method. @@ -277,7 +269,6 @@ class Editor extends Model @subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args... @subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args... @subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args... - @subscribe @displayBuffer, "decoration-changed", (args...) => @emit 'decoration-changed', args... @subscribe @displayBuffer, "decoration-updated", (args...) => @emit 'decoration-updated', args... @subscribe @displayBuffer, "character-widths-changed", (changeCount) => @emit 'character-widths-changed', changeCount From 6d498aad3b6d50742020012f7e7e3c7ca07829f3 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Fri, 5 Sep 2014 21:40:11 +0200 Subject: [PATCH 135/355] Explain capital letters in keystrokes --- dot-atom/keymap.cson | 1 + 1 file changed, 1 insertion(+) diff --git a/dot-atom/keymap.cson b/dot-atom/keymap.cson index 43ec6951d..9e5fc6742 100644 --- a/dot-atom/keymap.cson +++ b/dot-atom/keymap.cson @@ -16,3 +16,4 @@ # 'ctrl-P': 'core:move-up' # 'ctrl-p': 'core:move-down' # +# In the example above, 'ctrl-P' is equivalent to 'ctrl-shift-p'. From 289b22c7825be3beb1938478378918642bf9066d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:40:14 -0700 Subject: [PATCH 136/355] Use event methods in TokenizedBuffer spec --- spec/tokenized-buffer-spec.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index 64c06c482..ec1dc5009 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -41,7 +41,7 @@ describe "TokenizedBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') tokenizedBuffer = new TokenizedBuffer({buffer}) startTokenizing(tokenizedBuffer) - tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler') + tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') afterEach -> tokenizedBuffer.destroy() @@ -753,7 +753,7 @@ describe "TokenizedBuffer", -> expect(tokenizedBuffer.tokenizedLineForRow(10).indentLevel).toBe 3 expect(tokenizedBuffer.tokenizedLineForRow(11).indentLevel).toBe 2 - tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler') + tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') buffer.setTextInRange([[7, 0], [8, 65]], ' one\n two\n three\n four') @@ -771,7 +771,7 @@ describe "TokenizedBuffer", -> buffer.insert([7, 0], '\n\n') buffer.insert([5, 0], '\n\n') - tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler') + tokenizedBuffer.onDidChange changeHandler = jasmine.createSpy('changeHandler') buffer.setTextInRange([[7, 0], [8, 65]], ' ok') From 0a920b18d701260eb5c43ed7851501329ae4cf63 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:40:33 -0700 Subject: [PATCH 137/355] Update TokenizedBUffer::on deprecations --- src/tokenized-buffer.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 9273e21de..db64f597a 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -65,13 +65,13 @@ class TokenizedBuffer extends Model on: (eventName) -> switch eventName when 'changed' - Grim.deprecate("Use DisplayBuffer::onDidChange instead") + Grim.deprecate("Use TokenizedBuffer::onDidChange instead") when 'grammar-changed' - Grim.deprecate("Use DisplayBuffer::onDidChangeGrammar instead") + Grim.deprecate("Use TokenizedBuffer::onDidChangeGrammar instead") when 'tokenized' - Grim.deprecate("Use DisplayBuffer::onDidTokenize instead") - # else - # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") + Grim.deprecate("Use TokenizedBuffer::onDidTokenize instead") + else + Grim.deprecate("TokenizedBuffer::on is deprecated. Use event subscription methods instead.") EmitterMixin::on.apply(this, arguments) From b1fdb48e9e69938be4d4781eede20781202ae2cf Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Fri, 5 Sep 2014 21:40:54 +0200 Subject: [PATCH 138/355] Link to relevant docs in keymap.cson file --- dot-atom/keymap.cson | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dot-atom/keymap.cson b/dot-atom/keymap.cson index 9e5fc6742..732932a22 100644 --- a/dot-atom/keymap.cson +++ b/dot-atom/keymap.cson @@ -17,3 +17,7 @@ # 'ctrl-p': 'core:move-down' # # In the example above, 'ctrl-P' is equivalent to 'ctrl-shift-p'. +# +# You can find more information about keymaps in these guides: +# * https://atom.io/docs/latest/customizing-atom#customizing-key-bindings +# * https://atom.io/docs/latest/advanced/keymaps From 557562d8c89f32a5c6e4aad24ed19d6126dc473a Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:42:33 -0700 Subject: [PATCH 139/355] Fix linter error --- src/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 55199defa..360185f75 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -294,7 +294,7 @@ class Editor extends Model onDidChangeSoftWrapped: (callback) -> @displayBuffer.onDidChangeSoftWrapped(callback) - onDidChangeGrammar: (callback)-> + onDidChangeGrammar: (callback) -> @displayBuffer.onDidChangeGrammar(callback) onDidStopChanging: (callback) -> From db84b7952c6ed17aab7137f3269b5b3131ab1702 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 12:44:56 -0700 Subject: [PATCH 140/355] fix another linter error --- spec/editor-spec.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 8b992a2aa..8b0b06f25 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -149,13 +149,13 @@ describe "Editor", -> describe "path", -> it "notifies ::onDidChangePath observers when the underlying buffer path changes", -> - observed = [] - editor.onDidChangePath (filePath) -> observed.push(filePath) + observed = [] + editor.onDidChangePath (filePath) -> observed.push(filePath) - buffer.setPath('/foo/bar/baz.txt') - buffer.setPath(undefined) + buffer.setPath('/foo/bar/baz.txt') + buffer.setPath(undefined) - expect(observed).toEqual ['/foo/bar/baz.txt', undefined] + expect(observed).toEqual ['/foo/bar/baz.txt', undefined] describe "cursor", -> describe ".getLastCursor()", -> From 733e06fa8c5e1424aa267f3f4a2475c2aa3d7c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C5=BDu=C5=BEak?= Date: Fri, 5 Sep 2014 22:24:42 +0200 Subject: [PATCH 141/355] Use shift in the example rather than explaining the difference --- dot-atom/keymap.cson | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dot-atom/keymap.cson b/dot-atom/keymap.cson index 732932a22..fd683364a 100644 --- a/dot-atom/keymap.cson +++ b/dot-atom/keymap.cson @@ -13,11 +13,9 @@ # 'enter': 'editor:newline' # # '.workspace': -# 'ctrl-P': 'core:move-up' +# 'ctrl-shift-p': 'core:move-up' # 'ctrl-p': 'core:move-down' # -# In the example above, 'ctrl-P' is equivalent to 'ctrl-shift-p'. -# # You can find more information about keymaps in these guides: # * https://atom.io/docs/latest/customizing-atom#customizing-key-bindings # * https://atom.io/docs/latest/advanced/keymaps From 21e4d8a06415559a5f57926da55aeee83b506eb6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 13:30:59 -0700 Subject: [PATCH 142/355] Add DisplayBuffer::onDidChange --- spec/display-buffer-spec.coffee | 8 ++++---- src/display-buffer.coffee | 28 +++++++++++++++++++++++----- src/editor.coffee | 2 +- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index e0e34d973..806aaba2c 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -9,7 +9,7 @@ describe "DisplayBuffer", -> buffer = atom.project.bufferForPathSync('sample.js') displayBuffer = new DisplayBuffer({buffer, tabLength}) changeHandler = jasmine.createSpy 'changeHandler' - displayBuffer.on 'changed', changeHandler + displayBuffer.onDidChange changeHandler waitsForPromise -> atom.packages.activatePackage('language-javascript') @@ -234,7 +234,7 @@ describe "DisplayBuffer", -> buffer.release() buffer = atom.project.bufferForPathSync('two-hundred.txt') displayBuffer = new DisplayBuffer({buffer, tabLength}) - displayBuffer.on 'changed', changeHandler + displayBuffer.onDidChange changeHandler describe "when folds are created and destroyed", -> describe "when a fold spans multiple lines", -> @@ -860,7 +860,7 @@ describe "DisplayBuffer", -> it "updates markers before emitting buffer change events, but does not notify their observers until the change event", -> marker2 = displayBuffer.markBufferRange([[8, 1], [8, 1]]) marker2.onDidChange marker2ChangedHandler = jasmine.createSpy("marker2ChangedHandler") - displayBuffer.on 'changed', changeHandler = jasmine.createSpy("changeHandler").andCallFake -> onDisplayBufferChange() + displayBuffer.onDidChange changeHandler = jasmine.createSpy("changeHandler").andCallFake -> onDisplayBufferChange() # New change ---- @@ -932,7 +932,7 @@ describe "DisplayBuffer", -> expect(marker3ChangedHandler).toHaveBeenCalled() it "updates the position of markers before emitting change events that aren't caused by a buffer change", -> - displayBuffer.on 'changed', changeHandler = jasmine.createSpy("changeHandler").andCallFake -> + displayBuffer.onDidChange changeHandler = jasmine.createSpy("changeHandler").andCallFake -> # calls change handler first expect(markerChangedHandler).not.toHaveBeenCalled() # but still updates the markers diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 82372cb33..31d77860e 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -1,5 +1,5 @@ _ = require 'underscore-plus' -{Emitter} = require 'emissary' +EmitterMixin = require('emissary').Emitter guid = require 'guid' Serializable = require 'serializable' {Model} = require 'theorist' @@ -11,6 +11,7 @@ Fold = require './fold' Token = require './token' Decoration = require './decoration' DisplayBufferMarker = require './display-buffer-marker' +Grim = require 'grim' class BufferToScreenConversionError extends Error constructor: (@message, @metadata) -> @@ -105,11 +106,28 @@ class DisplayBuffer extends Model onDidTokenize: (callback) -> @tokenizedBuffer.onDidTokenize(callback) - emitChanged: (eventProperties, refreshMarkers=true) -> + onDidChange: (callback) -> + @emitter.on 'did-change', callback + + on: (eventName) -> + switch eventName + when 'changed' + Grim.deprecate("Use DisplayBuffer::onDidChange instead") + when 'grammar-changed' + Grim.deprecate("Use DisplayBuffer::onDidChangeGrammar instead") + when 'soft-wrap-changed' + Grim.deprecate("Use DisplayBuffer::onDidChangeSoftWrap instead") + # else + # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") + + EmitterMixin::on.apply(this, arguments) + + emitDidChange: (eventProperties, refreshMarkers=true) -> if refreshMarkers @pauseMarkerChangeEvents() @refreshMarkerScreenPositions() @emit 'changed', eventProperties + @emitter.emit 'did-change', eventProperties @resumeMarkerChangeEvents() updateWrappedScreenLines: -> @@ -118,7 +136,7 @@ class DisplayBuffer extends Model @updateAllScreenLines() screenDelta = @getLastRow() - end bufferDelta = 0 - @emitChanged({ start, end, screenDelta, bufferDelta }) + @emitDidChange({ start, end, screenDelta, bufferDelta }) # Sets the visibility of the tokenized buffer. # @@ -1028,7 +1046,7 @@ class DisplayBuffer extends Model @pauseMarkerChangeEvents() @pendingChangeEvent = changeEvent else - @emitChanged(changeEvent, options.refreshMarkers) + @emitDidChange(changeEvent, options.refreshMarkers) buildScreenLines: (startBufferRow, endBufferRow) -> screenLines = [] @@ -1106,7 +1124,7 @@ class DisplayBuffer extends Model handleBufferMarkersUpdated: => if event = @pendingChangeEvent @pendingChangeEvent = null - @emitChanged(event, false) + @emitDidChange(event, false) handleBufferMarkerCreated: (marker) => @createFoldForMarker(marker) if marker.matchesAttributes(@getFoldMarkerAttributes()) diff --git a/src/editor.coffee b/src/editor.coffee index 360185f75..6e6291ff9 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -262,7 +262,7 @@ class Editor extends Model subscribeToDisplayBuffer: -> @subscribe @displayBuffer, 'marker-created', @handleMarkerCreated - @subscribe @displayBuffer, "changed", (e) => @emit 'screen-lines-changed', e + @subscribe @displayBuffer.onDidChange (e) => @emit 'screen-lines-changed', e @subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections() @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @subscribe @displayBuffer.onDidTokenize => @handleTokenization() From 6e8a626de22cc7769ac6306e172b2f3a53b097b3 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 13:41:46 -0700 Subject: [PATCH 143/355] Add ::onDidChangeSoftWrapped to DisplayBuffer and Editor --- spec/display-buffer-spec.coffee | 2 +- src/display-buffer.coffee | 6 ++++++ src/editor-component.coffee | 2 +- src/editor.coffee | 4 +++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 806aaba2c..5716b47b9 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -1172,7 +1172,7 @@ describe "DisplayBuffer", -> it "recomputes the scroll width when the scoped character widths change in a batch", -> operatorWidth = 20 - displayBuffer.on 'character-widths-changed', changedSpy = jasmine.createSpy() + displayBuffer.onDidChangeCharacterWidths changedSpy = jasmine.createSpy() displayBuffer.batchCharacterMeasurement -> displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 31d77860e..df7291ac4 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -109,6 +109,9 @@ class DisplayBuffer extends Model onDidChange: (callback) -> @emitter.on 'did-change', callback + onDidChangeCharacterWidths: (callback) -> + @emitter.on 'did-change-character-widths', callback + on: (eventName) -> switch eventName when 'changed' @@ -117,6 +120,8 @@ class DisplayBuffer extends Model Grim.deprecate("Use DisplayBuffer::onDidChangeGrammar instead") when 'soft-wrap-changed' Grim.deprecate("Use DisplayBuffer::onDidChangeSoftWrap instead") + when 'character-widths-changed' + Grim.deprecate("Use DisplayBuffer::onDidChangeCharacterWidths instead") # else # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") @@ -278,6 +283,7 @@ class DisplayBuffer extends Model characterWidthsChanged: -> @computeScrollWidth() @emit 'character-widths-changed', @scopedCharacterWidthsChangeCount + @emitter.emit 'did-change-character-widths', @scopedCharacterWidthsChangeCount clearScopedCharWidths: -> @charWidthsByScope = {} diff --git a/src/editor-component.coffee b/src/editor-component.coffee index cfadc9b65..8824a8b0b 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -350,7 +350,7 @@ EditorComponent = React.createClass @subscribe editor, 'decoration-added', @onDecorationChanged @subscribe editor, 'decoration-removed', @onDecorationChanged @subscribe editor, 'decoration-updated', @onDecorationChanged - @subscribe editor, 'character-widths-changed', @onCharacterWidthsChanged + @subscribe editor.onDidChangeCharacterWidths @onCharacterWidthsChanged @subscribe editor.$scrollTop.changes, @onScrollTopChanged @subscribe editor.$scrollLeft.changes, @requestUpdate @subscribe editor.$verticalScrollbarWidth.changes, @requestUpdate diff --git a/src/editor.coffee b/src/editor.coffee index 6e6291ff9..35e5b9170 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -270,7 +270,6 @@ class Editor extends Model @subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args... @subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args... @subscribe @displayBuffer, "decoration-updated", (args...) => @emit 'decoration-updated', args... - @subscribe @displayBuffer, "character-widths-changed", (changeCount) => @emit 'character-widths-changed', changeCount getViewClass: -> require './editor-view' @@ -297,6 +296,9 @@ class Editor extends Model onDidChangeGrammar: (callback) -> @displayBuffer.onDidChangeGrammar(callback) + onDidChangeCharacterWidths: (callback) -> + @displayBuffer.onDidChangeCharacterWidths(callback) + onDidStopChanging: (callback) -> @getBuffer().onDidStopChanging(callback) From f3e8f11d076059885858ff4a055c2e71bc31f548 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 13:42:11 -0700 Subject: [PATCH 144/355] Use DisplayBuffer::onDidChangeSoftWrapped in Editor --- src/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 35e5b9170..15ea875f6 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -266,7 +266,7 @@ class Editor extends Model @subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections() @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @subscribe @displayBuffer.onDidTokenize => @handleTokenization() - @subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args... + @subscribe @displayBuffer.onDidChangeSoftWrapped (args...) => @emit 'soft-wrap-changed', args... @subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args... @subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args... @subscribe @displayBuffer, "decoration-updated", (args...) => @emit 'decoration-updated', args... From e6e60286833f70b720a419bc17c8075fb01ccb1a Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 15:14:27 -0700 Subject: [PATCH 145/355] Deprecate decoration events --- spec/display-buffer-spec.coffee | 2 +- src/decoration.coffee | 10 +++++----- src/display-buffer.coffee | 29 ++++++++++++++++++++++++++--- src/editor-component.coffee | 6 +++--- src/editor.coffee | 19 +++++++++++++++---- 5 files changed, 50 insertions(+), 16 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 5716b47b9..2916d7139 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -1074,7 +1074,7 @@ describe "DisplayBuffer", -> describe "when a decoration is updated via Decoration::update()", -> it "emits an 'updated' event containing the new and old params", -> - decoration.onDidUpdate updatedSpy = jasmine.createSpy() + decoration.onDidChange updatedSpy = jasmine.createSpy() decoration.update type: 'gutter', class: 'two' {oldParams, newParams} = updatedSpy.mostRecentCall.args[0] diff --git a/src/decoration.coffee b/src/decoration.coffee index f3c4604de..4b467f4a9 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -77,8 +77,8 @@ class Decoration # * `event` {Object} # * `oldParams` {Object} the old parameters the decoration used to have # * `newParams` {Object} the new parameters the decoration now has - onDidUpdate: (callback) -> - @emitter.on 'did-update', callback + onDidChange: (callback) -> + @emitter.on 'did-change', callback # Essential: Update the marker with new params. Allows you to change the decoration's class. # @@ -94,9 +94,9 @@ class Decoration oldParams = @params @params = newParams @params.id = @id - @displayBuffer.decorationUpdated(this) + @displayBuffer.decorationChanged(this) @emit 'updated', {oldParams, newParams} - @emitter.emit 'did-update', {oldParams, newParams} + @emitter.emit 'did-change', {oldParams, newParams} # Essential: Invoke the given callback when the {Decoration} is destroyed onDidDestroy: (callback) -> @@ -137,7 +137,7 @@ class Decoration on: (eventName) -> switch eventName when 'updated' - Grim.deprecate("Use Decoration::onDidUpdate instead") + Grim.deprecate("Use Decoration::onDidChange instead") when 'destroyed' Grim.deprecate("Use Decoration::onDidDestroy instead") when 'flash' diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index df7291ac4..43c36877f 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -112,6 +112,15 @@ class DisplayBuffer extends Model onDidChangeCharacterWidths: (callback) -> @emitter.on 'did-change-character-widths', callback + onDidAddDecoration: (callback) -> + @emitter.on 'did-add-decoration', callback + + onDidRemoveDecoration: (callback) -> + @emitter.on 'did-remove-decoration', callback + + onDidChangeDecoration: (callback) -> + @emitter.on 'did-change-decoration', callback + on: (eventName) -> switch eventName when 'changed' @@ -122,6 +131,14 @@ class DisplayBuffer extends Model Grim.deprecate("Use DisplayBuffer::onDidChangeSoftWrap instead") when 'character-widths-changed' Grim.deprecate("Use DisplayBuffer::onDidChangeCharacterWidths instead") + when 'decoration-added' + Grim.deprecate("Use DisplayBuffer::onDidAddDecoration instead") + when 'decoration-removed' + Grim.deprecate("Use DisplayBuffer::onDidRemoveDecoration instead") + when 'decoration-changed' + Grim.deprecate("Use DisplayBuffer::onDidChangeDecoration instead") + when 'decoration-updated' + Grim.deprecate("Use DisplayBuffer::onDidChangeDecoration instead") # else # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") @@ -823,13 +840,15 @@ class DisplayBuffer extends Model # in the change handler. Bookmarks does this. if decorations? for decoration in decorations - @emit 'decoration-updated', decoration + @emit 'decoration-changed', decoration + @emitter.emit 'did-change-decoration', decoration decoration = new Decoration(marker, this, decorationParams) @decorationsByMarkerId[marker.id] ?= [] @decorationsByMarkerId[marker.id].push(decoration) @decorationsById[decoration.id] = decoration @emit 'decoration-added', decoration + @emitter.emit 'did-add-decoration', decoration decoration removeDecoration: (decoration) -> @@ -841,12 +860,14 @@ class DisplayBuffer extends Model decorations.splice(index, 1) delete @decorationsById[decoration.id] @emit 'decoration-removed', decoration + @emitter.emit 'did-remove-decoration', decoration @removedAllMarkerDecorations(marker) if decorations.length is 0 removeAllDecorationsForMarker: (marker) -> decorations = @decorationsByMarkerId[marker.id].slice() for decoration in decorations @emit 'decoration-removed', decoration + @emitter.emit 'did-remove-decoration', decoration @removedAllMarkerDecorations(marker) removedAllMarkerDecorations: (marker) -> @@ -857,8 +878,10 @@ class DisplayBuffer extends Model delete @decorationMarkerChangedSubscriptions[marker.id] delete @decorationMarkerDestroyedSubscriptions[marker.id] - decorationUpdated: (decoration) -> - @emit 'decoration-updated', decoration + # Called by the decoration + decorationChanged: (decoration) -> + @emit 'decoration-changed', decoration + @emitter.emit 'did-change-decoration', decoration # Retrieves a {DisplayBufferMarker} based on its id. # diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 8824a8b0b..f596e3063 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -347,9 +347,9 @@ EditorComponent = React.createClass @subscribe editor, 'screen-lines-changed', @onScreenLinesChanged @subscribe editor.onDidAddCursor(@onCursorAdded) @subscribe editor.onDidAddSelection(@onSelectionAdded) - @subscribe editor, 'decoration-added', @onDecorationChanged - @subscribe editor, 'decoration-removed', @onDecorationChanged - @subscribe editor, 'decoration-updated', @onDecorationChanged + @subscribe editor.onDidAddDecoration @onDecorationChanged + @subscribe editor.onDidRemoveDecoration @onDecorationChanged + @subscribe editor.onDidChangeDecoration @onDecorationChanged @subscribe editor.onDidChangeCharacterWidths @onCharacterWidthsChanged @subscribe editor.$scrollTop.changes, @onScrollTopChanged @subscribe editor.$scrollLeft.changes, @requestUpdate diff --git a/src/editor.coffee b/src/editor.coffee index 15ea875f6..5d1a68b3d 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -266,10 +266,12 @@ class Editor extends Model @subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections() @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @subscribe @displayBuffer.onDidTokenize => @handleTokenization() - @subscribe @displayBuffer.onDidChangeSoftWrapped (args...) => @emit 'soft-wrap-changed', args... - @subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args... - @subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args... - @subscribe @displayBuffer, "decoration-updated", (args...) => @emit 'decoration-updated', args... + + # TODO: remove these when we remove the deprecations. Though, no one is likely using them + @subscribe @displayBuffer.onDidChangeSoftWrapped (softWrapped) => @emit 'soft-wrap-changed', softWrapped + @subscribe @displayBuffer.onDidAddDecoration (decoration) => @emit 'decoration-added', decoration + @subscribe @displayBuffer.onDidRemoveDecoration (decoration) => @emit 'decoration-removed', decoration + @subscribe @displayBuffer.onDidChangeDecoration (decoration) => @emit 'decoration-changed', decoration getViewClass: -> require './editor-view' @@ -323,6 +325,15 @@ class Editor extends Model onDidRemoveSelection: (callback) -> @emitter.on 'did-remove-selection', callback + onDidAddDecoration: (callback) -> + @displayBuffer.onDidAddDecoration(callback) + + onDidRemoveDecoration: (callback) -> + @displayBuffer.onDidRemoveDecoration(callback) + + onDidChangeDecoration: (callback) -> + @displayBuffer.onDidChangeDecoration(callback) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 7ae25d34e773990cd01bb57c791dc81ab08fec2d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 16:18:30 -0700 Subject: [PATCH 146/355] Decoration Params -> Properties --- spec/display-buffer-spec.coffee | 18 ++++----- src/decoration.coffee | 66 ++++++++++++++++++--------------- src/editor-component.coffee | 4 +- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 2916d7139..1f2fd18ea 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -1051,15 +1051,15 @@ describe "DisplayBuffer", -> expect(markerCreated2).not.toHaveBeenCalled() describe "decorations", -> - [marker, decoration, decorationParams] = [] + [marker, decoration, decorationProperties] = [] beforeEach -> marker = displayBuffer.markBufferRange([[2, 13], [3, 15]]) - decorationParams = {type: 'gutter', class: 'one'} - decoration = displayBuffer.decorateMarker(marker, decorationParams) + decorationProperties = {type: 'gutter', class: 'one'} + decoration = displayBuffer.decorateMarker(marker, decorationProperties) it "can add decorations associated with markers and remove them", -> expect(decoration).toBeDefined() - expect(decoration.getParams()).toBe decorationParams + expect(decoration.getProperties()).toBe decorationProperties expect(displayBuffer.decorationForId(decoration.id)).toBe decoration expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id][0]).toBe decoration @@ -1074,12 +1074,12 @@ describe "DisplayBuffer", -> describe "when a decoration is updated via Decoration::update()", -> it "emits an 'updated' event containing the new and old params", -> - decoration.onDidChange updatedSpy = jasmine.createSpy() - decoration.update type: 'gutter', class: 'two' + decoration.onDidChangeProperties updatedSpy = jasmine.createSpy() + decoration.setProperties type: 'gutter', class: 'two' - {oldParams, newParams} = updatedSpy.mostRecentCall.args[0] - expect(oldParams).toEqual decorationParams - expect(newParams).toEqual type: 'gutter', class: 'two', id: decoration.id + {oldProperties, newProperties} = updatedSpy.mostRecentCall.args[0] + expect(oldProperties).toEqual decorationProperties + expect(newProperties).toEqual type: 'gutter', class: 'two', id: decoration.id describe "::setScrollTop", -> beforeEach -> diff --git a/src/decoration.coffee b/src/decoration.coffee index 4b467f4a9..35972bd25 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -32,24 +32,24 @@ module.exports = class Decoration EmitterMixin.includeInto(this) - # Extended: Check if the `decorationParams.type` matches `type` + # Extended: Check if the `decorationProperties.type` matches `type` # - # * `decorationParams` {Object} eg. `{type: 'gutter', class: 'my-new-class'}` + # * `decorationProperties` {Object} eg. `{type: 'gutter', class: 'my-new-class'}` # * `type` {String} type like `'gutter'`, `'line'`, etc. `type` can also # be an {Array} of {String}s, where it will return true if the decoration's # type matches any in the array. # # Returns {Boolean} - @isType: (decorationParams, type) -> - if _.isArray(decorationParams.type) - type in decorationParams.type + @isType: (decorationProperties, type) -> + if _.isArray(decorationProperties.type) + type in decorationProperties.type else - type is decorationParams.type + type is decorationProperties.type - constructor: (@marker, @displayBuffer, @params) -> + constructor: (@marker, @displayBuffer, @properties) -> @emitter = new Emitter @id = nextId() - @params.id = @id + @properties.id = @id @flashQueue = null @isDestroyed = false @@ -59,9 +59,6 @@ class Decoration # Essential: Returns the marker associated with this {Decoration} getMarker: -> @marker - # Essential: Returns the {Decoration}'s params. - getParams: -> @params - # Public: Check if this decoration is of type `type` # # * `type` {String} type like `'gutter'`, `'line'`, etc. `type` can also @@ -70,17 +67,24 @@ class Decoration # # Returns {Boolean} isType: (type) -> - Decoration.isType(@params, type) + Decoration.isType(@properties, type) # Essential: When the {Decoration} is updated via {Decoration::update}. # # * `event` {Object} - # * `oldParams` {Object} the old parameters the decoration used to have - # * `newParams` {Object} the new parameters the decoration now has - onDidChange: (callback) -> - @emitter.on 'did-change', callback + # * `oldProperties` {Object} the old parameters the decoration used to have + # * `newProperties` {Object} the new parameters the decoration now has + onDidChangeProperties: (callback) -> + @emitter.on 'did-change-properties', callback - # Essential: Update the marker with new params. Allows you to change the decoration's class. + # Essential: Returns the {Decoration}'s properties. + getProperties: -> + @properties + getParams: -> + Grim.deprecate 'Use Decoration::getProperties instead' + @getProperties() + + # Essential: Update the marker with new Properties. Allows you to change the decoration's class. # # ## Examples # @@ -88,15 +92,17 @@ class Decoration # decoration.update({type: 'gutter', class: 'my-new-class'}) # ``` # - # * `newParams` {Object} eg. `{type: 'gutter', class: 'my-new-class'}` - update: (newParams) -> + # * `newProperties` {Object} eg. `{type: 'gutter', class: 'my-new-class'}` + setProperties: (newProperties) -> return if @isDestroyed - oldParams = @params - @params = newParams - @params.id = @id - @displayBuffer.decorationChanged(this) - @emit 'updated', {oldParams, newParams} - @emitter.emit 'did-change', {oldParams, newParams} + oldProperties = @properties + @properties = newProperties + @properties.id = @id + @emit 'updated', {oldParams: oldProperties, newParams: newProperties} + @emitter.emit 'did-change-properties', {oldProperties, newProperties} + update: (newProperties) -> + Grim.deprecate 'Use Decoration::setProperties instead' + @setProperties(newProperties) # Essential: Invoke the given callback when the {Decoration} is destroyed onDidDestroy: (callback) -> @@ -117,7 +123,7 @@ class Decoration matchesPattern: (decorationPattern) -> return false unless decorationPattern? for key, value of decorationPattern - return false if @params[key] != value + return false if @properties[key] != value true onDidFlash: (callback) -> @@ -137,12 +143,12 @@ class Decoration on: (eventName) -> switch eventName when 'updated' - Grim.deprecate("Use Decoration::onDidChange instead") + Grim.deprecate 'Use Decoration::onDidChangeProperties instead' when 'destroyed' - Grim.deprecate("Use Decoration::onDidDestroy instead") + Grim.deprecate 'Use Decoration::onDidDestroy instead' when 'flash' - Grim.deprecate("Use Decoration::onDidFlash instead") + Grim.deprecate 'Use Decoration::onDidFlash instead' else - Grim.deprecate("Decoration::on is deprecated. Use event subscription methods instead.") + Grim.deprecate 'Decoration::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index f596e3063..ee6b0bdcd 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -305,7 +305,7 @@ EditorComponent = React.createClass if marker.isValid() for decoration in decorations if decoration.isType('gutter') or decoration.isType('line') - decorationParams = decoration.getParams() + decorationParams = decoration.getProperties() screenRange ?= marker.getScreenRange() headScreenRow ?= marker.getHeadScreenPosition().row startRow = screenRange.start.row @@ -332,7 +332,7 @@ EditorComponent = React.createClass if marker.isValid() and not screenRange.isEmpty() for decoration in decorations if decoration.isType('highlight') - decorationParams = decoration.getParams() + decorationParams = decoration.getProperties() filteredDecorations[markerId] ?= id: markerId startPixelPosition: editor.pixelPositionForScreenPosition(screenRange.start) From aeffef30c66c634700b3d85b230f4f01ee85cad8 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 16:35:55 -0700 Subject: [PATCH 147/355] Directly subscribe to the decorations in EditorComponent --- spec/editor-component-spec.coffee | 2 +- src/display-buffer.coffee | 29 ++++++++++------------------- src/editor-component.coffee | 13 ++++++++++--- src/editor.coffee | 3 +++ 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 7aa902834..1d6be5136 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -1134,7 +1134,7 @@ describe "EditorComponent", -> it "renders the decoration's new params", -> expect(componentNode.querySelector('.test-highlight')).toBeTruthy() - decoration.update(type: 'highlight', class: 'new-test-highlight') + decoration.setProperties(type: 'highlight', class: 'new-test-highlight') nextAnimationFrame() expect(componentNode.querySelector('.test-highlight')).toBeFalsy() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 43c36877f..a013b9687 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -53,7 +53,6 @@ class DisplayBuffer extends Model @foldsByMarkerId = {} @decorationsById = {} @decorationsByMarkerId = {} - @decorationMarkerChangedSubscriptions = {} @decorationMarkerDestroyedSubscriptions = {} @updateAllScreenLines() @createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes()) @@ -112,6 +111,10 @@ class DisplayBuffer extends Model onDidChangeCharacterWidths: (callback) -> @emitter.on 'did-change-character-widths', callback + observeDecorations: (callback) -> + callback(decoration) for decoration in @getDecorations() + @onDidAddDecoration(callback) + onDidAddDecoration: (callback) -> @emitter.on 'did-add-decoration', callback @@ -820,6 +823,12 @@ class DisplayBuffer extends Model decorationForId: (id) -> @decorationsById[id] + getDecorations: -> + allDecorations = [] + for markerId, decorations of @decorationsByMarkerId + allDecorations = allDecorations.concat(decorations) if decorations? + allDecorations + decorationsForScreenRowRange: (startScreenRow, endScreenRow) -> decorationsByMarkerId = {} for marker in @findMarkers(intersectsScreenRowRange: [startScreenRow, endScreenRow]) @@ -833,16 +842,6 @@ class DisplayBuffer extends Model @decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker.onDidDestroy => @removeAllDecorationsForMarker(marker) - @decorationMarkerChangedSubscriptions[marker.id] ?= @subscribe marker.onDidChange (event) => - decorations = @decorationsByMarkerId[marker.id] - - # Why check existence? Markers may get destroyed or decorations removed - # in the change handler. Bookmarks does this. - if decorations? - for decoration in decorations - @emit 'decoration-changed', decoration - @emitter.emit 'did-change-decoration', decoration - decoration = new Decoration(marker, this, decorationParams) @decorationsByMarkerId[marker.id] ?= [] @decorationsByMarkerId[marker.id].push(decoration) @@ -871,18 +870,10 @@ class DisplayBuffer extends Model @removedAllMarkerDecorations(marker) removedAllMarkerDecorations: (marker) -> - @decorationMarkerChangedSubscriptions[marker.id].dispose() @decorationMarkerDestroyedSubscriptions[marker.id].dispose() - delete @decorationsByMarkerId[marker.id] - delete @decorationMarkerChangedSubscriptions[marker.id] delete @decorationMarkerDestroyedSubscriptions[marker.id] - # Called by the decoration - decorationChanged: (decoration) -> - @emit 'decoration-changed', decoration - @emitter.emit 'did-change-decoration', decoration - # Retrieves a {DisplayBufferMarker} based on its id. # # id - A {Number} representing a marker id diff --git a/src/editor-component.coffee b/src/editor-component.coffee index ee6b0bdcd..b97127ee2 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -347,9 +347,8 @@ EditorComponent = React.createClass @subscribe editor, 'screen-lines-changed', @onScreenLinesChanged @subscribe editor.onDidAddCursor(@onCursorAdded) @subscribe editor.onDidAddSelection(@onSelectionAdded) - @subscribe editor.onDidAddDecoration @onDecorationChanged - @subscribe editor.onDidRemoveDecoration @onDecorationChanged - @subscribe editor.onDidChangeDecoration @onDecorationChanged + @subscribe editor.observeDecorations(@onDecorationAdded) + @subscribe editor.onDidRemoveDecoration(@onDecorationRemoved) @subscribe editor.onDidChangeCharacterWidths @onCharacterWidthsChanged @subscribe editor.$scrollTop.changes, @onScrollTopChanged @subscribe editor.$scrollLeft.changes, @requestUpdate @@ -758,9 +757,17 @@ EditorComponent = React.createClass @cursorMoved = true @requestUpdate() + onDecorationAdded: (decoration) -> + @subscribe decoration.onDidChangeProperties(@onDecorationChanged) + @subscribe decoration.getMarker().onDidChange(@onDecorationChanged) + @requestUpdate() + onDecorationChanged: -> @requestUpdate() + onDecorationRemoved: -> + @requestUpdate() + onCharacterWidthsChanged: (@scopedCharacterWidthsChangeCount) -> @requestUpdate() diff --git a/src/editor.coffee b/src/editor.coffee index 5d1a68b3d..bf782bb97 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -325,6 +325,9 @@ class Editor extends Model onDidRemoveSelection: (callback) -> @emitter.on 'did-remove-selection', callback + observeDecorations: (callback) -> + @displayBuffer.observeDecorations(callback) + onDidAddDecoration: (callback) -> @displayBuffer.onDidAddDecoration(callback) From 86e9778adb7a3571e5d41bed9741671988ef12e9 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 16:51:26 -0700 Subject: [PATCH 148/355] Remove the decoration changed event --- src/display-buffer.coffee | 3 --- src/editor.coffee | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index a013b9687..7a69cc508 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -121,9 +121,6 @@ class DisplayBuffer extends Model onDidRemoveDecoration: (callback) -> @emitter.on 'did-remove-decoration', callback - onDidChangeDecoration: (callback) -> - @emitter.on 'did-change-decoration', callback - on: (eventName) -> switch eventName when 'changed' diff --git a/src/editor.coffee b/src/editor.coffee index bf782bb97..4f92e503a 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -271,7 +271,6 @@ class Editor extends Model @subscribe @displayBuffer.onDidChangeSoftWrapped (softWrapped) => @emit 'soft-wrap-changed', softWrapped @subscribe @displayBuffer.onDidAddDecoration (decoration) => @emit 'decoration-added', decoration @subscribe @displayBuffer.onDidRemoveDecoration (decoration) => @emit 'decoration-removed', decoration - @subscribe @displayBuffer.onDidChangeDecoration (decoration) => @emit 'decoration-changed', decoration getViewClass: -> require './editor-view' @@ -334,9 +333,6 @@ class Editor extends Model onDidRemoveDecoration: (callback) -> @displayBuffer.onDidRemoveDecoration(callback) - onDidChangeDecoration: (callback) -> - @displayBuffer.onDidChangeDecoration(callback) - # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From 47ef54a07268e3df44d681bab3668f9d2eb0954d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 16:53:35 -0700 Subject: [PATCH 149/355] Subscribe directly to the decoration destroy for removal --- src/decoration.coffee | 5 ++++- src/display-buffer.coffee | 24 ++++-------------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/decoration.coffee b/src/decoration.coffee index 35972bd25..ed027011c 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -53,6 +53,8 @@ class Decoration @flashQueue = null @isDestroyed = false + @markerDestroyDisposable = @marker.onDidDestroy => @destroy() + # Essential: An id unique across all {Decoration} objects getId: -> @id @@ -114,8 +116,9 @@ class Decoration # this decoration. destroy: -> return if @isDestroyed + @markerDestroyDisposable.dispose() + @markerDestroyDisposable = null @isDestroyed = true - @displayBuffer.removeDecoration(this) @emit 'destroyed' @emitter.emit 'did-destroy' @emitter.dispose() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 7a69cc508..a85695bca 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -53,7 +53,6 @@ class DisplayBuffer extends Model @foldsByMarkerId = {} @decorationsById = {} @decorationsByMarkerId = {} - @decorationMarkerDestroyedSubscriptions = {} @updateAllScreenLines() @createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes()) @subscribe @tokenizedBuffer.onDidChange @handleTokenizedBufferChange @@ -136,9 +135,9 @@ class DisplayBuffer extends Model when 'decoration-removed' Grim.deprecate("Use DisplayBuffer::onDidRemoveDecoration instead") when 'decoration-changed' - Grim.deprecate("Use DisplayBuffer::onDidChangeDecoration instead") + Grim.deprecate("Use decoration.getMarker().onDidChange() instead") when 'decoration-updated' - Grim.deprecate("Use DisplayBuffer::onDidChangeDecoration instead") + Grim.deprecate("Use Decoration::onDidChangeProperties instead") # else # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") @@ -835,11 +834,8 @@ class DisplayBuffer extends Model decorateMarker: (marker, decorationParams) -> marker = @getMarker(marker.id) - - @decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker.onDidDestroy => - @removeAllDecorationsForMarker(marker) - decoration = new Decoration(marker, this, decorationParams) + @subscribe decoration.onDidDestroy => @removeDecoration(decoration) @decorationsByMarkerId[marker.id] ?= [] @decorationsByMarkerId[marker.id].push(decoration) @decorationsById[decoration.id] = decoration @@ -857,19 +853,7 @@ class DisplayBuffer extends Model delete @decorationsById[decoration.id] @emit 'decoration-removed', decoration @emitter.emit 'did-remove-decoration', decoration - @removedAllMarkerDecorations(marker) if decorations.length is 0 - - removeAllDecorationsForMarker: (marker) -> - decorations = @decorationsByMarkerId[marker.id].slice() - for decoration in decorations - @emit 'decoration-removed', decoration - @emitter.emit 'did-remove-decoration', decoration - @removedAllMarkerDecorations(marker) - - removedAllMarkerDecorations: (marker) -> - @decorationMarkerDestroyedSubscriptions[marker.id].dispose() - delete @decorationsByMarkerId[marker.id] - delete @decorationMarkerDestroyedSubscriptions[marker.id] + delete @decorationsByMarkerId[marker.id] if decorations.length is 0 # Retrieves a {DisplayBufferMarker} based on its id. # From e6dbea09feba58d3fa55a9a869d8745698ef5054 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 17:22:49 -0700 Subject: [PATCH 150/355] Add onDidCreateMarker and onDidUpdateMarkers --- spec/display-buffer-spec.coffee | 7 +++---- src/display-buffer.coffee | 12 ++++++++++++ src/editor.coffee | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 1f2fd18ea..9f00eff3a 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -686,7 +686,7 @@ describe "DisplayBuffer", -> expect(marker2.getScreenRange()).toEqual [[5, 4], [5, 10]] it "emits a 'marker-created' event on the DisplayBuffer whenever a marker is created", -> - displayBuffer.on 'marker-created', markerCreatedHandler = jasmine.createSpy("markerCreatedHandler") + displayBuffer.onDidCreateMarker markerCreatedHandler = jasmine.createSpy("markerCreatedHandler") marker1 = displayBuffer.markScreenRange([[5, 4], [5, 10]]) expect(markerCreatedHandler).toHaveBeenCalledWith(marker1) @@ -1041,9 +1041,8 @@ describe "DisplayBuffer", -> describe 'when a marker is created', -> it 'the second display buffer will not emit a marker-created event when the marker has been deleted in the first marker-created event', -> displayBuffer2 = new DisplayBuffer({buffer, tabLength}) - displayBuffer.on 'marker-created', markerCreated1 = jasmine.createSpy().andCallFake (marker) -> - marker.destroy() - displayBuffer2.on 'marker-created', markerCreated2 = jasmine.createSpy() + displayBuffer.onDidCreateMarker markerCreated1 = jasmine.createSpy().andCallFake (marker) -> marker.destroy() + displayBuffer2.onDidCreateMarker markerCreated2 = jasmine.createSpy() displayBuffer.markBufferRange([[0, 0], [1, 5]], {}) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index a85695bca..8e1aa8a19 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -120,6 +120,12 @@ class DisplayBuffer extends Model onDidRemoveDecoration: (callback) -> @emitter.on 'did-remove-decoration', callback + onDidCreateMarker: (callback) -> + @emitter.on 'did-create-marker', callback + + onDidUpdateMarkers: (callback) -> + @emitter.on 'did-update-markers', callback + on: (eventName) -> switch eventName when 'changed' @@ -138,6 +144,10 @@ class DisplayBuffer extends Model Grim.deprecate("Use decoration.getMarker().onDidChange() instead") when 'decoration-updated' Grim.deprecate("Use Decoration::onDidChangeProperties instead") + when 'marker-created' + Grim.deprecate("Use Decoration::onDidCreateMarker instead") + when 'markers-updated' + Grim.deprecate("Use Decoration::onDidUpdateMarkers instead") # else # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") @@ -1003,6 +1013,7 @@ class DisplayBuffer extends Model resumeMarkerChangeEvents: -> marker.resumeChangeEvents() for marker in @getMarkers() @emit 'markers-updated' + @emitter.emit 'did-update-markers' refreshMarkerScreenPositions: -> for marker in @getMarkers() @@ -1133,6 +1144,7 @@ class DisplayBuffer extends Model # The marker might have been removed in some other handler called before # this one. Only emit when the marker still exists. @emit 'marker-created', displayBufferMarker + @emitter.emit 'did-create-marker', displayBufferMarker createFoldForMarker: (marker) -> @decorateMarker(marker, type: 'gutter', class: 'folded') diff --git a/src/editor.coffee b/src/editor.coffee index 4f92e503a..1093c1479 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -261,9 +261,9 @@ class Editor extends Model @preserveCursorPositionOnBufferReload() subscribeToDisplayBuffer: -> - @subscribe @displayBuffer, 'marker-created', @handleMarkerCreated + @subscribe @displayBuffer.onDidCreateMarker @handleMarkerCreated @subscribe @displayBuffer.onDidChange (e) => @emit 'screen-lines-changed', e - @subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections() + @subscribe @displayBuffer.onDidUpdateMarkers => @mergeIntersectingSelections() @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @subscribe @displayBuffer.onDidTokenize => @handleTokenization() From 250c21f00a59aab03fd5dcf87dc143bf5afa5551 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 5 Sep 2014 17:26:41 -0700 Subject: [PATCH 151/355] Deprecate all events from ::on --- src/display-buffer.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 8e1aa8a19..a2c9817a3 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -148,8 +148,8 @@ class DisplayBuffer extends Model Grim.deprecate("Use Decoration::onDidCreateMarker instead") when 'markers-updated' Grim.deprecate("Use Decoration::onDidUpdateMarkers instead") - # else - # Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") + else + Grim.deprecate("DisplayBuffer::on is deprecated. Use event subscription methods instead.") EmitterMixin::on.apply(this, arguments) From fe74dfdf4eb47597d76c3a4d5ca41d23f6245dd9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 17:57:46 -0700 Subject: [PATCH 152/355] Upgrade to apm 0.92.1 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index a47620ea2..7468fed7c 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "0.92.0" + "atom-package-manager": "0.92.1" } } From 5237e687eea449662ffa7349833df111187784e4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 18:15:54 -0700 Subject: [PATCH 153/355] :penguin: Add separator after preference items Closes #3471 --- menus/linux.cson | 1 + 1 file changed, 1 insertion(+) diff --git a/menus/linux.cson b/menus/linux.cson index 2f2396b85..ba87732dd 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -85,6 +85,7 @@ { label: 'Open Your Keymap', command: 'application:open-your-keymap' } { label: 'Open Your Snippets', command: 'application:open-your-snippets' } { label: 'Open Your Stylesheet', command: 'application:open-your-stylesheet' } + { type: 'separator' } ] } From 571ce5bddd3830c5b5a5e15b19f34616f08c0e9e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 18:33:09 -0700 Subject: [PATCH 154/355] Upgrade to tree-view@0.115 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea9e5cee2..7c1f60940 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.114.0", + "tree-view": "0.115.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From c01a24f29397d90e428beea6487ca571f5571227 Mon Sep 17 00:00:00 2001 From: pinak222 Date: Sat, 6 Sep 2014 10:59:01 +0530 Subject: [PATCH 155/355] Add MimeType text/plain to .desktop file This adds Atom in open with menu in KDE (possibly other DE's) for text files therefore providing better integration. --- resources/linux/Atom.desktop.in | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/linux/Atom.desktop.in b/resources/linux/Atom.desktop.in index 0694c0cfb..0543049ea 100644 --- a/resources/linux/Atom.desktop.in +++ b/resources/linux/Atom.desktop.in @@ -6,3 +6,4 @@ Icon=<%= iconName %> Type=Application StartupNotify=true Categories=GNOME;GTK;Utility;TextEditor; +MimeType=text/plain; From 1c5acc059e113e895b004f10b1d90dbc55d5f000 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Sep 2014 10:24:35 +0800 Subject: [PATCH 156/355] Upgrade to atom-shell@0.16.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c1f60940..0f6557cd7 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "url": "http://github.com/atom/atom/raw/master/LICENSE.md" } ], - "atomShellVersion": "0.15.9", + "atomShellVersion": "0.16.0", "dependencies": { "async": "0.2.6", "atom-keymap": "^2.0.5", From 4134f5efe4fc862473a1d11683603c59147a87a4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Sep 2014 10:26:44 +0800 Subject: [PATCH 157/355] Upgrade to apm@0.93.0 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 7468fed7c..be5c54e9f 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "0.92.1" + "atom-package-manager": "0.93.0" } } From a8e463861219ebc74a440f5b206716443a8f0e7c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Sep 2014 12:31:45 +0800 Subject: [PATCH 158/355] :apple: Add "Services" menu, fixes #3204 --- menus/darwin.cson | 2 ++ 1 file changed, 2 insertions(+) diff --git a/menus/darwin.cson b/menus/darwin.cson index 900e42ce7..b892c56cc 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -18,6 +18,8 @@ { type: 'separator' } { label: 'Install Shell Commands', command: 'window:install-shell-commands' } { type: 'separator' } + { label: 'Services', submenu: [] } + { type: 'separator' } { label: 'Hide Atom', command: 'application:hide' } { label: 'Hide Others', command: 'application:hide-other-applications' } { label: 'Show All', command: 'application:unhide-all-applications' } From 846d81abf53f46ecd25096008fe0fa942dd20886 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Sep 2014 18:18:13 +0800 Subject: [PATCH 159/355] Upgrade to atom-shell@0.16.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f6557cd7..b830dc21f 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "url": "http://github.com/atom/atom/raw/master/LICENSE.md" } ], - "atomShellVersion": "0.16.0", + "atomShellVersion": "0.16.1", "dependencies": { "async": "0.2.6", "atom-keymap": "^2.0.5", From de4936efc8e1390623bc11032c026a8f5e3f8c69 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Sep 2014 18:27:24 +0800 Subject: [PATCH 160/355] Upgrade to apm@0.93.1 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index be5c54e9f..2717d82f6 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "0.93.0" + "atom-package-manager": "0.93.1" } } From 9e21ea39bd7526a9cd5196f8374ad87ab928012a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 08:33:48 -0700 Subject: [PATCH 161/355] Upgrade to language-xml@0.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c1f60940..28b1fa093 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "language-text": "0.6.0", "language-todo": "0.11.0", "language-toml": "0.12.0", - "language-xml": "0.19.0", + "language-xml": "0.20.0", "language-yaml": "0.17.0" }, "private": true, From abbb21bf47544848948d8133640eb7503d6a70db Mon Sep 17 00:00:00 2001 From: alandarev Date: Sun, 7 Sep 2014 17:08:55 +0100 Subject: [PATCH 162/355] :penguin: Add Category 'Development' to linux desktop file Closes #2827 Closes #3482 Closes #3488 --- resources/linux/Atom.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/linux/Atom.desktop.in b/resources/linux/Atom.desktop.in index 0543049ea..84e8eb808 100644 --- a/resources/linux/Atom.desktop.in +++ b/resources/linux/Atom.desktop.in @@ -5,5 +5,5 @@ Exec=<%= installDir %>/share/atom/atom %U Icon=<%= iconName %> Type=Application StartupNotify=true -Categories=GNOME;GTK;Utility;TextEditor; +Categories=GNOME;GTK;Utility;TextEditor;Development; MimeType=text/plain; From 7eba55d009674d4330b1dd9f0e5940a2b53d4866 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 09:27:06 -0700 Subject: [PATCH 163/355] Add initial browser process startup benchmark --- benchmark/browser-process-startup.coffee | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 benchmark/browser-process-startup.coffee diff --git a/benchmark/browser-process-startup.coffee b/benchmark/browser-process-startup.coffee new file mode 100644 index 000000000..3b83f185f --- /dev/null +++ b/benchmark/browser-process-startup.coffee @@ -0,0 +1,48 @@ +#!/usr/bin/env coffee + +{spawn, exec} = require 'child_process' +os = require 'os' +path = require 'path' +_ = require 'underscore-plus' +temp = require 'temp' + +directoryToOpen = temp.mkdirSync('browser-process-startup-') +socketPath = path.join(os.tmpdir(), 'atom.sock') +numberOfRuns = 10 + +launchAtom = (callback) -> + cmd = 'atom' + args = ['--safe', '--new-window', '--foreground', directoryToOpen] + atomProcess = spawn(cmd, args) + + output = '' + startupTimes = [] + + dataListener = (data) -> + output += data + if match = /App load time: (\d+)/.exec(output) + atomProcess.stderr.removeListener 'data', dataListener + atomProcess.kill() + exec 'pkill -9 Atom', -> + try + fs.unlinkSync(socketPath) + + callback(parseInt(match[1])) + + atomProcess.stderr.on 'data', dataListener + +startupTimes = [] +collector = (startupTime) -> + startupTimes.push(startupTime) + if startupTimes.length < numberOfRuns + launchAtom(collector) + else + maxTime = _.max(startupTimes) + minTime = _.min(startupTimes) + totalTime = startupTimes.reduce (previousValue=0, currentValue) -> previousValue + currentValue + console.log "Startup Runs: #{startupTimes.length}" + console.log "Max time: #{maxTime}ms" + console.log "Min time: #{minTime}ms" + console.log "Average time: #{Math.round(totalTime/startupTimes.length)}ms" + +launchAtom(collector) From b5dfaff426696e2b7c025114a65f319224d10dd0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 09:36:19 -0700 Subject: [PATCH 164/355] Remove unused requires from main.coffee --- src/browser/main.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 8955ab0a7..87d7b0601 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -3,11 +3,9 @@ global.shellStartTime = Date.now() crashReporter = require 'crash-reporter' app = require 'app' fs = require 'fs' -module = require 'module' path = require 'path' optimist = require 'optimist' nslog = require 'nslog' -dialog = require 'dialog' console.log = nslog From 4b867ddc7a8de99894ebf00fe633f73bc2242228 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 09:43:59 -0700 Subject: [PATCH 165/355] Properly delete socket file in benchmark --- benchmark/browser-process-startup.coffee | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/benchmark/browser-process-startup.coffee b/benchmark/browser-process-startup.coffee index 3b83f185f..06f2a0d48 100644 --- a/benchmark/browser-process-startup.coffee +++ b/benchmark/browser-process-startup.coffee @@ -1,6 +1,7 @@ #!/usr/bin/env coffee {spawn, exec} = require 'child_process' +fs = require 'fs' os = require 'os' path = require 'path' _ = require 'underscore-plus' @@ -10,24 +11,30 @@ directoryToOpen = temp.mkdirSync('browser-process-startup-') socketPath = path.join(os.tmpdir(), 'atom.sock') numberOfRuns = 10 +deleteSocketFile = -> + try + fs.unlinkSync(socketPath) if fs.existsSync(socketPath) + catch error + console.error(error) + launchAtom = (callback) -> + deleteSocketFile() + cmd = 'atom' args = ['--safe', '--new-window', '--foreground', directoryToOpen] atomProcess = spawn(cmd, args) output = '' startupTimes = [] - dataListener = (data) -> output += data if match = /App load time: (\d+)/.exec(output) + startupTime = parseInt(match[1]) atomProcess.stderr.removeListener 'data', dataListener atomProcess.kill() - exec 'pkill -9 Atom', -> - try - fs.unlinkSync(socketPath) - - callback(parseInt(match[1])) + exec 'pkill -9 Atom', (error) -> + console.error(error) if error? + callback(startupTime) atomProcess.stderr.on 'data', dataListener @@ -41,6 +48,7 @@ collector = (startupTime) -> minTime = _.min(startupTimes) totalTime = startupTimes.reduce (previousValue=0, currentValue) -> previousValue + currentValue console.log "Startup Runs: #{startupTimes.length}" + console.log "First run time: #{startupTimes[0]}ms" console.log "Max time: #{maxTime}ms" console.log "Min time: #{minTime}ms" console.log "Average time: #{Math.round(totalTime/startupTimes.length)}ms" From d7106a6b4c3e9dad08f4d4d7829e589b588cbf9a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 10:06:50 -0700 Subject: [PATCH 166/355] Make browser process benchmark executable --- benchmark/browser-process-startup.coffee | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 benchmark/browser-process-startup.coffee diff --git a/benchmark/browser-process-startup.coffee b/benchmark/browser-process-startup.coffee old mode 100644 new mode 100755 From d4ed8a0b735e4980702625dc6b8baf281fe2ed0e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 10:10:04 -0700 Subject: [PATCH 167/355] Defer requiring CoffeeScript Requiring it up front adds about 30-40ms to startup. --- src/browser/main.coffee | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 87d7b0601..12a8cad90 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -38,7 +38,7 @@ start = -> args.pathsToOpen = args.pathsToOpen.map (pathToOpen) -> path.resolve(args.executedFrom ? process.cwd(), pathToOpen.toString()) - require('coffee-script').register() + setupCoffeeScript() if args.devMode require(path.join(args.resourcePath, 'src', 'coffee-cache')).register() AtomApplication = require path.join(args.resourcePath, 'src', 'browser', 'atom-application') @@ -55,6 +55,15 @@ global.devResourcePath = path.normalize(global.devResourcePath) if global.devRes setupCrashReporter = -> crashReporter.start(productName: 'Atom', companyName: 'GitHub') +setupCoffeeScript = -> + CoffeeScript = null + + require.extensions['.coffee'] = (module, filePath) -> + CoffeeScript ?= require('coffee-script') + coffee = fs.readFileSync(filePath, 'utf8') + {js} = CoffeeScript.compile(coffee, filename: filePath) + module._compile(js, filePath) + parseCommandLine = -> version = app.getVersion() options = optimist(process.argv[1..]) From 163b52efb023eed0f3ca7ebb5388d9554d90ca0f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 10:16:56 -0700 Subject: [PATCH 168/355] CoffeeScript.compile returns a string --- src/browser/main.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 12a8cad90..0583fbc08 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -61,7 +61,7 @@ setupCoffeeScript = -> require.extensions['.coffee'] = (module, filePath) -> CoffeeScript ?= require('coffee-script') coffee = fs.readFileSync(filePath, 'utf8') - {js} = CoffeeScript.compile(coffee, filename: filePath) + js = CoffeeScript.compile(coffee, filename: filePath) module._compile(js, filePath) parseCommandLine = -> From fc59d9c503a147fa9fa29fb54d35de721a0c1a33 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:00:21 -0700 Subject: [PATCH 169/355] Require https on a next tick This require is heavy in node for some reason so only require it on Windows since it is only used there and only after a next tick so that it doesn't affect startup --- src/browser/auto-update-manager.coffee | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index 01151f2a9..eeeae1a47 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -48,18 +48,24 @@ class AutoUpdateManager # Windows doesn't have an auto-updater, so use this method to shim the events. checkForUpdatesShim: -> autoUpdater.emit 'checking-for-update' - request = https.get @feedUrl, (response) -> - if response.statusCode == 200 - body = "" - response.on 'data', (chunk) -> body += chunk - response.on 'end', -> - {notes, name} = JSON.parse(body) - autoUpdater.emit 'update-downloaded', null, notes, name - else - autoUpdater.emit 'update-not-available' - request.on 'error', (error) -> - autoUpdater.emit 'error', null, error.message + # Do this in a next tick since requiring https can be slow the first time + # and this check shouldn't interfere with startup time. + process.nextTick => + https = require 'https' + + request = https.get @feedUrl, (response) -> + if response.statusCode == 200 + body = "" + response.on 'data', (chunk) -> body += chunk + response.on 'end', -> + {notes, name} = JSON.parse(body) + autoUpdater.emit 'update-downloaded', null, notes, name + else + autoUpdater.emit 'update-not-available' + + request.on 'error', (error) -> + autoUpdater.emit 'error', null, error.message emitUpdateAvailableEvent: (windows...) -> return unless @releaseVersion? and @releaseNotes From 6e7968861dedfd80dff9d62a316f8d981944fd08 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:01:35 -0700 Subject: [PATCH 170/355] Use fs instead of fs-plus Since only an is file check is performed fs is sufficient --- src/browser/atom-protocol-handler.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/atom-protocol-handler.coffee b/src/browser/atom-protocol-handler.coffee index 786d50243..6777a21ee 100644 --- a/src/browser/atom-protocol-handler.coffee +++ b/src/browser/atom-protocol-handler.coffee @@ -1,5 +1,5 @@ app = require 'app' -fs = require 'fs-plus' +fs = require 'fs' path = require 'path' protocol = require 'protocol' @@ -24,5 +24,5 @@ class AtomProtocolHandler relativePath = path.normalize(request.url.substr(7)) for loadPath in @loadPaths filePath = path.join(loadPath, relativePath) - break if fs.isFileSync(filePath) + break if fs.statSyncNoException(filePath).isFile?() return new protocol.RequestFileJob(filePath) From 4fa6f631a9d0a0867fa92cecd6fa91d0529ca1be Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:03:14 -0700 Subject: [PATCH 171/355] Defer ContextMenu require until requested --- src/browser/atom-window.coffee | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 1022f6f76..a2736077a 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -1,5 +1,4 @@ BrowserWindow = require 'browser-window' -ContextMenu = require './context-menu' app = require 'app' dialog = require 'dialog' path = require 'path' @@ -73,6 +72,13 @@ class AtomWindow getInitialPath: -> @browserWindow.loadSettings.initialPath + setupContextMenu: -> + ContextMenu = null + + @browserWindow.on 'context-menu', (menuTemplate) => + ContextMenu ?= require './context-menu' + new ContextMenu(menuTemplate, this) + containsPath: (pathToCheck) -> initialPath = @getInitialPath() if not initialPath @@ -114,8 +120,7 @@ class AtomWindow when 0 then @browserWindow.destroy() when 1 then @browserWindow.restart() - @browserWindow.on 'context-menu', (menuTemplate) => - new ContextMenu(menuTemplate, this) + @setupContextMenu() if @isSpec # Workaround for https://github.com/atom/atom-shell/issues/380 From 27bf096fbcc0322cf2ac96cd2397b1aa5664b97b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:03:57 -0700 Subject: [PATCH 172/355] Remove require that is now inlined where used --- src/browser/auto-update-manager.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index eeeae1a47..e20d4e575 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -1,4 +1,3 @@ -https = require 'https' autoUpdater = require 'auto-updater' dialog = require 'dialog' _ = require 'underscore-plus' From b2638c8bada8bba9af5d69d085130cf22bd85634 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:06:32 -0700 Subject: [PATCH 173/355] :lipstick: --- src/browser/auto-update-manager.coffee | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index e20d4e575..3ab2b37c2 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -3,19 +3,19 @@ dialog = require 'dialog' _ = require 'underscore-plus' {EventEmitter} = require 'events' -IDLE_STATE='idle' -CHECKING_STATE='checking' -DOWNLOADING_STATE='downloading' -UPDATE_AVAILABLE_STATE='update-available' -NO_UPDATE_AVAILABLE_STATE='no-update-available' -ERROR_STATE='error' +IdleState = 'idle' +CheckingState = 'checking' +DownladingState = 'downloading' +UpdateAvailableState = 'update-available' +NoUpdateAvailableState = 'no-update-available' +ErrorState = 'error' module.exports = class AutoUpdateManager _.extend @prototype, EventEmitter.prototype constructor: (@version) -> - @state = IDLE_STATE + @state = IdleState @feedUrl = "https://atom.io/api/updates?version=#{@version}" if process.platform is 'win32' @@ -24,20 +24,20 @@ class AutoUpdateManager autoUpdater.setFeedUrl @feedUrl autoUpdater.on 'checking-for-update', => - @setState(CHECKING_STATE) + @setState(CheckingState) autoUpdater.on 'update-not-available', => - @setState(NO_UPDATE_AVAILABLE_STATE) + @setState(NoUpdateAvailableState) autoUpdater.on 'update-available', => - @setState(DOWNLOADING_STATE) + @setState(DownladingState) autoUpdater.on 'error', (event, message) => - @setState(ERROR_STATE) + @setState(ErrorState) console.error "Error Downloading Update: #{message}" autoUpdater.on 'update-downloaded', (event, @releaseNotes, @releaseVersion) => - @setState(UPDATE_AVAILABLE_STATE) + @setState(UpdateAvailableState) @emitUpdateAvailableEvent(@getWindows()...) # Only released versions should check for updates. From 417134c799809c6decc765381f5f30f526ae66a3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:13:04 -0700 Subject: [PATCH 174/355] Require dialog when used --- src/browser/atom-application.coffee | 3 ++- src/browser/atom-window.coffee | 3 ++- src/browser/auto-update-manager.coffee | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index d47bba1d9..72807b08c 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -5,7 +5,6 @@ AutoUpdateManager = require './auto-update-manager' BrowserWindow = require 'browser-window' Menu = require 'menu' app = require 'app' -dialog = require 'dialog' fs = require 'fs' ipc = require 'ipc' path = require 'path' @@ -484,5 +483,7 @@ class AtomApplication when 'folder' then ['openDirectory'] when 'all' then ['openFile', 'openDirectory'] else throw new Error("#{type} is an invalid type for promptForPath") + + dialog = require 'dialog' dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) => @openPaths({pathsToOpen, devMode, safeMode, window}) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index a2736077a..166b971d0 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -1,6 +1,5 @@ BrowserWindow = require 'browser-window' app = require 'app' -dialog = require 'dialog' path = require 'path' fs = require 'fs' url = require 'url' @@ -101,6 +100,7 @@ class AtomWindow @browserWindow.on 'unresponsive', => return if @isSpec + dialog = require 'dialog' chosen = dialog.showMessageBox @browserWindow, type: 'warning' buttons: ['Close', 'Keep Waiting'] @@ -111,6 +111,7 @@ class AtomWindow @browserWindow.webContents.on 'crashed', => global.atomApplication.exit(100) if @exitWhenDone + dialog = require 'dialog' chosen = dialog.showMessageBox @browserWindow, type: 'warning' buttons: ['Close Window', 'Reload', 'Keep It Open'] diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index 3ab2b37c2..35c6b562c 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -1,5 +1,4 @@ autoUpdater = require 'auto-updater' -dialog = require 'dialog' _ = require 'underscore-plus' {EventEmitter} = require 'events' @@ -91,10 +90,12 @@ class AutoUpdateManager onUpdateNotAvailable: => autoUpdater.removeListener 'error', @onUpdateError + dialog = require 'dialog' dialog.showMessageBox type: 'info', buttons: ['OK'], message: 'No update available.', detail: "Version #{@version} is the latest version." onUpdateError: (event, message) => autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable + dialog = require 'dialog' dialog.showMessageBox type: 'warning', buttons: ['OK'], message: 'There was an error checking for updates.', detail: message getWindows: -> From 4e0928600f30bdc62f24add923aa1806d381cb17 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:35:26 -0700 Subject: [PATCH 175/355] :lipstick: --- src/browser/auto-update-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index 35c6b562c..a4c4da16d 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -71,7 +71,7 @@ class AutoUpdateManager atomWindow.sendCommand('window:update-available', [@releaseVersion, @releaseNotes]) setState: (state) -> - return unless @state != state + return if @state is state @state = state @emit 'state-changed', @state From 3a7564b59ef7af8e4d804887b45168298c9de1fa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:38:24 -0700 Subject: [PATCH 176/355] Start auto updater on the next tick This prevents it from adding time to first window startup --- src/browser/auto-update-manager.coffee | 35 +++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index a4c4da16d..30e961281 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -1,4 +1,4 @@ -autoUpdater = require 'auto-updater' +autoUpdater = null _ = require 'underscore-plus' {EventEmitter} = require 'events' @@ -17,6 +17,11 @@ class AutoUpdateManager @state = IdleState @feedUrl = "https://atom.io/api/updates?version=#{@version}" + process.nextTick => @setupAutoUpdater() + + setupAutoUpdater: -> + autoUpdater ?= require 'auto-updater' + if process.platform is 'win32' autoUpdater.checkForUpdates = => @checkForUpdatesShim() @@ -47,23 +52,19 @@ class AutoUpdateManager checkForUpdatesShim: -> autoUpdater.emit 'checking-for-update' - # Do this in a next tick since requiring https can be slow the first time - # and this check shouldn't interfere with startup time. - process.nextTick => - https = require 'https' + https = require 'https' + request = https.get @feedUrl, (response) -> + if response.statusCode == 200 + body = "" + response.on 'data', (chunk) -> body += chunk + response.on 'end', -> + {notes, name} = JSON.parse(body) + autoUpdater.emit 'update-downloaded', null, notes, name + else + autoUpdater.emit 'update-not-available' - request = https.get @feedUrl, (response) -> - if response.statusCode == 200 - body = "" - response.on 'data', (chunk) -> body += chunk - response.on 'end', -> - {notes, name} = JSON.parse(body) - autoUpdater.emit 'update-downloaded', null, notes, name - else - autoUpdater.emit 'update-not-available' - - request.on 'error', (error) -> - autoUpdater.emit 'error', null, error.message + request.on 'error', (error) -> + autoUpdater.emit 'error', null, error.message emitUpdateAvailableEvent: (windows...) -> return unless @releaseVersion? and @releaseNotes From 13956edfb55ded2bc3a81d9c6f63a802e724bfa6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:40:34 -0700 Subject: [PATCH 177/355] Always assign to autoUpdater --- src/browser/auto-update-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/auto-update-manager.coffee b/src/browser/auto-update-manager.coffee index 30e961281..828af310d 100644 --- a/src/browser/auto-update-manager.coffee +++ b/src/browser/auto-update-manager.coffee @@ -20,7 +20,7 @@ class AutoUpdateManager process.nextTick => @setupAutoUpdater() setupAutoUpdater: -> - autoUpdater ?= require 'auto-updater' + autoUpdater = require 'auto-updater' if process.platform is 'win32' autoUpdater.checkForUpdates = => @checkForUpdatesShim() From 68801aacdbf2e1a4a9cf09848092262c442bdd58 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 11:43:01 -0700 Subject: [PATCH 178/355] Don't require shell until it is used --- src/browser/atom-application.coffee | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 72807b08c..1849fb6cd 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -10,7 +10,6 @@ ipc = require 'ipc' path = require 'path' os = require 'os' net = require 'net' -shell = require 'shell' url = require 'url' {EventEmitter} = require 'events' _ = require 'underscore-plus' @@ -154,8 +153,8 @@ class AtomApplication atomWindow ?= @focusedWindow() atomWindow?.browserWindow.inspectElement(x, y) - @on 'application:open-documentation', -> shell.openExternal('https://atom.io/docs/latest/?app') - @on 'application:open-terms-of-use', -> shell.openExternal('https://atom.io/terms') + @on 'application:open-documentation', -> require('shell').openExternal('https://atom.io/docs/latest/?app') + @on 'application:open-terms-of-use', -> require('shell').openExternal('https://atom.io/terms') @on 'application:install-update', -> @autoUpdateManager.install() @on 'application:check-for-update', => @autoUpdateManager.check() From e7e4196fa6051d36448f44fe57f5bf04b8a6c386 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 14:54:19 -0700 Subject: [PATCH 179/355] Use fs.statSyncNoException --- src/browser/main.coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 0583fbc08..019dd991d 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -116,9 +116,7 @@ parseCommandLine = -> else if devMode resourcePath = global.devResourcePath - try - fs.statSync resourcePath - catch + unless fs.statSyncNoException(resourcePath) resourcePath = path.dirname(path.dirname(__dirname)) {resourcePath, pathsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, logFile} From 42f3605465d9af41f8a21e780a7a7b7dd11d5c63 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 15:08:50 -0700 Subject: [PATCH 180/355] finish-launching -> ready --- src/browser/main.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 019dd991d..f9afb0c30 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -31,7 +31,7 @@ start = -> app.on 'will-finish-launching', -> setupCrashReporter() - app.on 'finish-launching', -> + app.on 'ready', -> app.removeListener 'open-file', addPathToOpen app.removeListener 'open-url', addUrlToOpen From 5e2f8a3ae3af8cc698728a45e5951731c7e94cb8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 17:30:14 -0700 Subject: [PATCH 181/355] :racehorse: Use DOM APIs to apply stylesheets Previously jQuery was used, but using the DOM APIs directly takes 1/3 of the time. --- src/theme-manager.coffee | 44 ++++++++++++++++++++++----------------- src/workspace-view.coffee | 4 ++-- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index fa254f31f..a9dbd5595 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -197,8 +197,8 @@ class ThemeManager if nativeStylesheetPath = fs.resolveOnLoadPath(process.platform, ['css', 'less']) @requireStylesheet(nativeStylesheetPath) - stylesheetElementForId: (id, htmlElement=$('html')) -> - htmlElement.find("""head style[id="#{id}"]""") + stylesheetElementForId: (id) -> + document.head.querySelector("""style[id="#{id}"]""") resolveStylesheet: (stylesheetPath) -> if path.extname(stylesheetPath).length > 0 @@ -214,10 +214,10 @@ class ThemeManager # path or a relative path that will be resolved against the load path. # # Returns the absolute path to the required stylesheet. - requireStylesheet: (stylesheetPath, type = 'bundled', htmlElement) -> + requireStylesheet: (stylesheetPath, type='bundled') -> if fullPath = @resolveStylesheet(stylesheetPath) content = @loadStylesheet(fullPath) - @applyStylesheet(fullPath, content, type = 'bundled', htmlElement) + @applyStylesheet(fullPath, content, type) else throw new Error("Could not find a file at path '#{stylesheetPath}'") @@ -257,23 +257,29 @@ class ThemeManager removeStylesheet: (stylesheetPath) -> fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath element = @stylesheetElementForId(@stringToId(fullPath)) - if element.length > 0 - stylesheet = element[0].sheet + if element? element.remove() - @emit 'stylesheet-removed', stylesheet + @emit 'stylesheet-removed', element.sheet @emit 'stylesheets-changed' - applyStylesheet: (path, text, type = 'bundled', htmlElement=$('html')) -> - styleElement = @stylesheetElementForId(@stringToId(path), htmlElement) - if styleElement.length - @emit 'stylesheet-removed', styleElement[0].sheet - styleElement.text(text) - else - styleElement = $("") - if htmlElement.find("head style.#{type}").length - htmlElement.find("head style.#{type}:last").after(styleElement) - else - htmlElement.find("head").append(styleElement) + applyStylesheet: (path, text, type='bundled') -> + styleElement = null - @emit 'stylesheet-added', styleElement[0].sheet + styleId = @stringToId(path) + styleElement = @stylesheetElementForId(styleId) + if styleElement? + @emit 'stylesheet-removed', styleElement.sheet + styleElement.textContent = text + else + styleElement = document.createElement('style') + styleElement.setAttribute('class', type) + styleElement.setAttribute('id', styleId) + styleElement.textContent = text + parentElement = _.last(document.head.querySelectorAll("style.#{type}"))?.parentElement + if parentElement? + parentElement.appendChild(styleElement) + else + document.head.appendChild(styleElement) + + @emit 'stylesheet-added', styleElement.sheet @emit 'stylesheets-changed' diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index b4ae47318..3bccbb228 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -381,9 +381,9 @@ class WorkspaceView extends View @setEditorStyle('line-height', lineHeight) setEditorStyle: (property, value) -> - unless styleNode = atom.themes.stylesheetElementForId('global-editor-styles')[0] + unless styleNode = atom.themes.stylesheetElementForId('global-editor-styles') atom.themes.applyStylesheet('global-editor-styles', '.editor {}') - styleNode = atom.themes.stylesheetElementForId('global-editor-styles')[0] + styleNode = atom.themes.stylesheetElementForId('global-editor-styles') {sheet} = styleNode editorRule = sheet.cssRules[0] From 7e6b7ada54a4ecf8f3a75f0fe10362b6bcebc50e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 17:40:53 -0700 Subject: [PATCH 182/355] Preserve ordering within type class --- src/theme-manager.coffee | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index a9dbd5595..c15858805 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -275,9 +275,10 @@ class ThemeManager styleElement.setAttribute('class', type) styleElement.setAttribute('id', styleId) styleElement.textContent = text - parentElement = _.last(document.head.querySelectorAll("style.#{type}"))?.parentElement - if parentElement? - parentElement.appendChild(styleElement) + + elementToInsertBefore = _.last(document.head.querySelectorAll("style.#{type}"))?.nextElementSibling + if elementToInsertBefore? + document.head.insertBefore(styleElement, elementToInsertBefore) else document.head.appendChild(styleElement) From f7103bbed6a55423c54fa3b2eb450dd12f4b6c4b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 18:00:38 -0700 Subject: [PATCH 183/355] Store sheet before it goes away --- src/theme-manager.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index c15858805..b6ca08d8e 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -258,8 +258,9 @@ class ThemeManager fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath element = @stylesheetElementForId(@stringToId(fullPath)) if element? + {sheet} = element element.remove() - @emit 'stylesheet-removed', element.sheet + @emit 'stylesheet-removed', sheet @emit 'stylesheets-changed' applyStylesheet: (path, text, type='bundled') -> From 35a48f0cfbd23b51ff0fbeacdf1003c2133a42cf Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 5 Sep 2014 18:14:03 -0700 Subject: [PATCH 184/355] Update specs to expect an element --- spec/atom-spec.coffee | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 4dc934587..54a94c9a8 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -241,15 +241,15 @@ describe "the `atom` global", -> two = atom.themes.stringToId(two) three = atom.themes.stringToId(three) - expect(atom.themes.stylesheetElementForId(one)).not.toExist() - expect(atom.themes.stylesheetElementForId(two)).not.toExist() - expect(atom.themes.stylesheetElementForId(three)).not.toExist() + expect(atom.themes.stylesheetElementForId(one)).toBeNull() + expect(atom.themes.stylesheetElementForId(two)).toBeNull() + expect(atom.themes.stylesheetElementForId(three)).toBeNull() atom.packages.activatePackage("package-with-stylesheets-manifest") - expect(atom.themes.stylesheetElementForId(one)).toExist() - expect(atom.themes.stylesheetElementForId(two)).toExist() - expect(atom.themes.stylesheetElementForId(three)).not.toExist() + expect(atom.themes.stylesheetElementForId(one)).not.toBeNull() + expect(atom.themes.stylesheetElementForId(two)).not.toBeNull() + expect(atom.themes.stylesheetElementForId(three)).toBeNull() expect($('#jasmine-content').css('font-size')).toBe '1px' describe "when the metadata does not contain a 'stylesheets' manifest", -> @@ -263,14 +263,14 @@ describe "the `atom` global", -> two = atom.themes.stringToId(two) three = atom.themes.stringToId(three) - expect(atom.themes.stylesheetElementForId(one)).not.toExist() - expect(atom.themes.stylesheetElementForId(two)).not.toExist() - expect(atom.themes.stylesheetElementForId(three)).not.toExist() + expect(atom.themes.stylesheetElementForId(one)).toBeNull() + expect(atom.themes.stylesheetElementForId(two)).toBeNull() + expect(atom.themes.stylesheetElementForId(three)).toBeNull() atom.packages.activatePackage("package-with-stylesheets") - expect(atom.themes.stylesheetElementForId(one)).toExist() - expect(atom.themes.stylesheetElementForId(two)).toExist() - expect(atom.themes.stylesheetElementForId(three)).toExist() + expect(atom.themes.stylesheetElementForId(one)).not.toBeNull() + expect(atom.themes.stylesheetElementForId(two)).not.toBeNull() + expect(atom.themes.stylesheetElementForId(three)).not.toBeNull() expect($('#jasmine-content').css('font-size')).toBe '3px' describe "grammar loading", -> From 01d62653f297eb94465e0bd17174ef2b463bdc41 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 09:23:53 -0700 Subject: [PATCH 185/355] Remove unused require --- src/theme-manager.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index b6ca08d8e..9a1838e24 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -5,7 +5,6 @@ _ = require 'underscore-plus' fs = require 'fs-plus' Q = require 'q' -{$} = require './space-pen-extensions' Package = require './package' {File} = require 'pathwatcher' From f8949adf3838921213282124cf9e3321f02eb4c8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 09:34:31 -0700 Subject: [PATCH 186/355] :lipstick: Sort requires --- src/theme-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 9a1838e24..92680589d 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -2,11 +2,11 @@ path = require 'path' _ = require 'underscore-plus' {Emitter} = require 'emissary' +{File} = require 'pathwatcher' fs = require 'fs-plus' Q = require 'q' Package = require './package' -{File} = require 'pathwatcher' # Extended: Handles loading and activating available themes. # From 522d446366d2f2b37b793512fb736432209effb1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 09:35:05 -0700 Subject: [PATCH 187/355] :memo: Emit -> Emitted --- src/theme-manager.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 92680589d..653fe48f1 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -16,23 +16,23 @@ Package = require './package' # # ### reloaded # -# Extended: Emit when all styles have been reloaded. +# Extended: Emitted when all styles have been reloaded. # # ### stylesheet-added # -# Extended: Emit when a stylesheet has been added. +# Extended: Emitted when a stylesheet has been added. # # * `stylesheet` {StyleSheet} object that was removed # # ### stylesheet-removed # -# Extended: Emit when a stylesheet has been removed. +# Extended: Emitted when a stylesheet has been removed. # # * `stylesheet` {StyleSheet} object that was removed # # ### stylesheets-changed # -# Extended: Emit anytime any style sheet is added or removed from the editor +# Extended: Emitted anytime any style sheet is added or removed from the editor # module.exports = class ThemeManager From 444eb0e5e5328837821605449c524644ab1813c5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 09:37:39 -0700 Subject: [PATCH 188/355] :lipstick: e -> error --- src/theme-manager.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 653fe48f1..0ef3d4f09 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -243,11 +243,11 @@ class ThemeManager @lessCache.cssForFile(lessStylesheetPath, [baseVarImports, less].join('\n')) else @lessCache.read(lessStylesheetPath) - catch e + catch error console.error """ Error compiling less stylesheet: #{lessStylesheetPath} - Line number: #{e.line} - #{e.message} + Line number: #{error.line} + #{error.message} """ stringToId: (string) -> From 359491fc3ff31bdaf931edcba0f3b4626c1b21ad Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 09:40:06 -0700 Subject: [PATCH 189/355] Remove nulled variable --- src/theme-manager.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 0ef3d4f09..45ca37e4e 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -263,10 +263,9 @@ class ThemeManager @emit 'stylesheets-changed' applyStylesheet: (path, text, type='bundled') -> - styleElement = null - styleId = @stringToId(path) styleElement = @stylesheetElementForId(styleId) + if styleElement? @emit 'stylesheet-removed', styleElement.sheet styleElement.textContent = text From ab75f3122fd6409464d428404b7c311135c59bcc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 09:43:50 -0700 Subject: [PATCH 190/355] :lipstick: Use proper Less --- src/theme-manager.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 45ca37e4e..6ed3e764a 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -207,7 +207,7 @@ class ThemeManager # Public: Resolve and apply the stylesheet specified by the path. # - # This supports both CSS and LESS stylsheets. + # This supports both CSS and Less stylsheets. # # * `stylesheetPath` A {String} path to the stylesheet that can be an absolute # path or a relative path that will be resolved against the load path. @@ -245,7 +245,7 @@ class ThemeManager @lessCache.read(lessStylesheetPath) catch error console.error """ - Error compiling less stylesheet: #{lessStylesheetPath} + Error compiling Less stylesheet: #{lessStylesheetPath} Line number: #{error.line} #{error.message} """ From 30ae93b9d9ce13a0182dad0a91d7dc5a7e0d3ec5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 10:12:31 -0700 Subject: [PATCH 191/355] Upgrade to apm 0.92.3 Refs #3492 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 7468fed7c..134e9aa08 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "0.92.1" + "atom-package-manager": "0.92.3" } } From 70dd3675e649a0e2b8592ea5e5c2aa5a900de7ec Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 12:05:25 -0700 Subject: [PATCH 192/355] Upgrade to minidump 0.8 --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index ea8514acb..bbad40c40 100644 --- a/build/package.json +++ b/build/package.json @@ -27,7 +27,7 @@ "harmony-collections": "~0.3.8", "json-front-matter": "~0.1.3", "legal-eagle": "~0.4.0", - "minidump": "~0.7", + "minidump": "~0.8", "normalize-package-data": "0.2.12", "npm": "~1.4.5", "rcedit": "~0.1.2", From efc730dc2fac17087f7c27ac3da3e953cc1ab21f Mon Sep 17 00:00:00 2001 From: Jordon Bedwell Date: Mon, 8 Sep 2014 14:39:47 -0500 Subject: [PATCH 193/355] Add alternatives alternative to symlinks. --- docs/build-instructions/linux.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 40bf03780..f603aca98 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -100,6 +100,16 @@ have Node.js installed, or node isn't identified as Node.js on your machine. If it's the latter, entering `sudo ln -s /usr/bin/nodejs /usr/bin/node` into your terminal may fix the issue. +## You can also use Alternatives: + +On some variants it's preferrable for you to use Alternatives so can easily +rollback and change the binary paths: + +``` +sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 1 \ + --slave /usr/bin/js js /usr/bin/nodejs +``` + ### Linux build error reports in atom/atom * Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Alinux&type=Issues) to get a list of reports about build errors on Linux. From 2d3ae1b44de2a66ade5a6c8eab23a5ba9ae5e556 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 8 Sep 2014 17:00:46 -0600 Subject: [PATCH 194/355] Upgrade event-kit for api docs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28b1fa093..86a61140d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.1", - "event-kit": "0.5.0", + "event-kit": "0.6.0", "first-mate": "^2.0.5", "fs-plus": "^2.2.6", "fstream": "0.1.24", From 8aa1784c4a3dec81c8d2e2ca54a47dc9fd5749b0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:04:43 -0700 Subject: [PATCH 195/355] Add Editor::onDidChangeScreenLines --- spec/editor-component-spec.coffee | 2 +- src/editor-component.coffee | 2 +- src/editor.coffee | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 1d6be5136..86f70e9d1 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -2195,7 +2195,7 @@ describe "EditorComponent", -> editor.setSoftWrapped(true) callingOrder = [] - editor.on 'screen-lines-changed', -> callingOrder.push 'screen-lines-changed' + editor.onDidChangeScreenLines -> callingOrder.push 'screen-lines-changed' wrapperView.on 'editor:display-updated', -> callingOrder.push 'editor:display-updated' editor.insertText("HELLO! HELLO!\n HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! HELLO! ") nextAnimationFrame() diff --git a/src/editor-component.coffee b/src/editor-component.coffee index b97127ee2..e15a6b069 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -344,7 +344,7 @@ EditorComponent = React.createClass observeEditor: -> {editor} = @props - @subscribe editor, 'screen-lines-changed', @onScreenLinesChanged + @subscribe editor.onDidChangeScreenLines(@onScreenLinesChanged) @subscribe editor.onDidAddCursor(@onCursorAdded) @subscribe editor.onDidAddSelection(@onSelectionAdded) @subscribe editor.observeDecorations(@onDecorationAdded) diff --git a/src/editor.coffee b/src/editor.coffee index 1093c1479..ab23b5968 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -4,6 +4,7 @@ Serializable = require 'serializable' Delegator = require 'delegato' {deprecate} = require 'grim' {Model} = require 'theorist' +EmitterMixin = require('emissary').Emitter {Emitter} = require 'event-kit' {Point, Range} = require 'text-buffer' LanguageMode = require './language-mode' @@ -262,10 +263,12 @@ class Editor extends Model subscribeToDisplayBuffer: -> @subscribe @displayBuffer.onDidCreateMarker @handleMarkerCreated - @subscribe @displayBuffer.onDidChange (e) => @emit 'screen-lines-changed', e @subscribe @displayBuffer.onDidUpdateMarkers => @mergeIntersectingSelections() @subscribe @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @subscribe @displayBuffer.onDidTokenize => @handleTokenization() + @subscribe @displayBuffer.onDidChange (e) => + @emit 'screen-lines-changed', e + @emitter.emit 'did-change-screen-lines', e # TODO: remove these when we remove the deprecations. Though, no one is likely using them @subscribe @displayBuffer.onDidChangeSoftWrapped (softWrapped) => @emit 'soft-wrap-changed', softWrapped @@ -333,6 +336,17 @@ class Editor extends Model onDidRemoveDecoration: (callback) -> @displayBuffer.onDidRemoveDecoration(callback) + onDidChangeScreenLines: (callback) -> + @emitter.on 'did-change-screen-lines', callback + + on: (eventName) -> + switch eventName + + when 'screen-lines-changed' + deprecate("Use Editor::onDidChangeScreenLines instead") + + EmitterMixin::on.apply(this, arguments) + # Retrieves the current {TextBuffer}. getBuffer: -> @buffer From efea16848aec0139574a55cee6040708f988e791 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:05:07 -0700 Subject: [PATCH 196/355] Add deprecation warnings for all the other converted events --- src/editor.coffee | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index ab23b5968..17128e8b0 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -341,6 +341,46 @@ class Editor extends Model on: (eventName) -> switch eventName + when 'title-changed' + deprecate("Use Editor::onDidChangeTitle instead") + when 'path-changed' + deprecate("Use Editor::onDidChangePath instead") + when 'modified-status-changed' + deprecate("Use Editor::onDidChangeModified instead") + when 'soft-wrap-changed' + deprecate("Use Editor::onDidChangeSoftWrapped instead") + when 'grammar-changed' + deprecate("Use Editor::onDidChangeGrammar instead") + when 'character-widths-changed' + deprecate("Use Editor::onDidChangeCharacterWidths instead") + when 'contents-modified' + deprecate("Use Editor::onDidStopChanging instead") + when 'contents-conflicted' + deprecate("Use Editor::onDidConflict instead") + + when 'will-insert-text' + deprecate("Use Editor::onWillInsertText instead") + when 'did-insert-text' + deprecate("Use Editor::onDidInsertText instead") + + when 'cursor-added' + deprecate("Use Editor::onDidAddCursor instead") + when 'cursor-removed' + deprecate("Use Editor::onDidRemoveCursor instead") + + when 'selection-added' + deprecate("Use Editor::onDidAddSelection instead") + when 'selection-removed' + deprecate("Use Editor::onDidRemoveSelection instead") + + when 'decoration-added' + deprecate("Use Editor::onDidAddDecoration instead") + when 'decoration-removed' + deprecate("Use Editor::onDidRemoveDecoration instead") + when 'decoration-updated' + deprecate("Use Decoration::onDidChangeProperties instead. You will get the decoration back from `Editor::decorateMarker()`") + when 'decoration-changed' + deprecate("Use Marker::onDidChange instead. eg. `editor::decorateMarker(...).getMarker().onDidChange()`") when 'screen-lines-changed' deprecate("Use Editor::onDidChangeScreenLines instead") From b6a9e1b5765d15505bcc8b85313b7973099771f1 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:05:21 -0700 Subject: [PATCH 197/355] Fix deprecation warning --- src/editor-view.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index e7c7d97e9..4c95882f4 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -147,8 +147,7 @@ class EditorView extends View @focus() if @focusOnAttach @addGrammarScopeAttribute() - @subscribe @editor, 'grammar-changed', => - @addGrammarScopeAttribute() + @subscribe @editor.onDidChangeGrammar => @addGrammarScopeAttribute() @trigger 'editor:attached', [this] From 6f9f087e111207a3ba7b954acc6f7dc831838968 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:05:31 -0700 Subject: [PATCH 198/355] :lipstick: consistency --- src/editor-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index e15a6b069..f2d4cbc65 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -349,7 +349,7 @@ EditorComponent = React.createClass @subscribe editor.onDidAddSelection(@onSelectionAdded) @subscribe editor.observeDecorations(@onDecorationAdded) @subscribe editor.onDidRemoveDecoration(@onDecorationRemoved) - @subscribe editor.onDidChangeCharacterWidths @onCharacterWidthsChanged + @subscribe editor.onDidChangeCharacterWidths(@onCharacterWidthsChanged) @subscribe editor.$scrollTop.changes, @onScrollTopChanged @subscribe editor.$scrollLeft.changes, @requestUpdate @subscribe editor.$verticalScrollbarWidth.changes, @requestUpdate From d4835e1d8e18d2da042b8aa108ccb0b25d439105 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:17:06 -0700 Subject: [PATCH 199/355] Add Editor:onScrollTopChanged and Editor:onScrollLeftChanged --- src/editor.coffee | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 17128e8b0..ac755924c 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -226,8 +226,12 @@ class Editor extends Model @languageMode = new LanguageMode(this) - @subscribe @$scrollTop, (scrollTop) => @emit 'scroll-top-changed', scrollTop - @subscribe @$scrollLeft, (scrollLeft) => @emit 'scroll-left-changed', scrollLeft + @subscribe @$scrollTop, (scrollTop) => + @emit 'scroll-top-changed', scrollTop + @emitter.emit 'did-change-scroll-top', scrollTop + @subscribe @$scrollLeft, (scrollLeft) => + @emit 'scroll-left-changed', scrollLeft + @emitter.emit 'did-change-scroll-left', scrollLeft @subscribe atom.config.observe 'editor.showInvisibles', callNow: false, (show) => @updateInvisibles() @subscribe atom.config.observe 'editor.invisibles', callNow: false, => @updateInvisibles() @@ -255,10 +259,13 @@ class Editor extends Model @emitter.emit 'did-change-title', @getTitle() @emit "path-changed" @emitter.emit 'did-change-path', @getPath() + @subscribe @buffer.onDidDestroy => @destroy() + + # TODO: remove these thwne we remove the deprecations. They are old events. @subscribe @buffer.onDidStopChanging => @emit "contents-modified" @subscribe @buffer.onDidConflict => @emit "contents-conflicted" @subscribe @buffer.onDidChangeModified => @emit "modified-status-changed" - @subscribe @buffer.onDidDestroy => @destroy() + @preserveCursorPositionOnBufferReload() subscribeToDisplayBuffer: -> @@ -339,6 +346,12 @@ class Editor extends Model onDidChangeScreenLines: (callback) -> @emitter.on 'did-change-screen-lines', callback + onDidChangeScrollTop: (callback) -> + @emitter.on 'did-change-scroll-top', callback + + onDidChangeScrollLeft: (callback) -> + @emitter.on 'did-change-scroll-left', callback + on: (eventName) -> switch eventName when 'title-changed' @@ -385,6 +398,11 @@ class Editor extends Model when 'screen-lines-changed' deprecate("Use Editor::onDidChangeScreenLines instead") + when 'scroll-top-changed' + deprecate("Use Editor::onDidChangeScrollTop instead") + when 'scroll-left-changed' + deprecate("Use Editor::onDidChangeScrollLeft instead") + EmitterMixin::on.apply(this, arguments) # Retrieves the current {TextBuffer}. From 601b311496489fb34df2bdfae32aa448eaa4f321 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:20:54 -0700 Subject: [PATCH 200/355] Add Editor::onDidMoveCursor --- src/editor.coffee | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index ac755924c..6182b2d97 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -328,6 +328,9 @@ class Editor extends Model onDidRemoveCursor: (callback) -> @emitter.on 'did-remove-cursor', callback + onDidMoveCursor: (callback) -> + @emitter.on 'did-move-cursor', callback + onDidAddSelection: (callback) -> @emitter.on 'did-add-selection', callback @@ -380,6 +383,8 @@ class Editor extends Model deprecate("Use Editor::onDidAddCursor instead") when 'cursor-removed' deprecate("Use Editor::onDidRemoveCursor instead") + when 'cursor-moved' + deprecate("Use Editor::onDidMoveCursor instead") when 'selection-added' deprecate("Use Editor::onDidAddSelection instead") @@ -1941,6 +1946,7 @@ class Editor extends Model cursorMoved: (cursor, event) -> @emit 'cursor-moved', event + @emitter.emit 'did-move-cursor', event # Merge cursors that have the same screen position mergeCursors: -> From 1d073173d4d27610c1405d34942698d18f8b8376 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:25:35 -0700 Subject: [PATCH 201/355] Add Editor::onDidChangeSelectedScreenRange --- src/editor.coffee | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 6182b2d97..55b8feaef 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -337,6 +337,9 @@ class Editor extends Model onDidRemoveSelection: (callback) -> @emitter.on 'did-remove-selection', callback + onDidChangeSelectionScreenRange: (callback) -> + @emitter.on 'did-change-selection-screen-range', callback + observeDecorations: (callback) -> @displayBuffer.observeDecorations(callback) @@ -390,6 +393,8 @@ class Editor extends Model deprecate("Use Editor::onDidAddSelection instead") when 'selection-removed' deprecate("Use Editor::onDidRemoveSelection instead") + when 'selection-screen-range-changed' + deprecate("Use Editor::onDidChangeSelectionScreenRange instead") when 'decoration-added' deprecate("Use Editor::onDidAddDecoration instead") @@ -2428,6 +2433,7 @@ class Editor extends Model selectionScreenRangeChanged: (selection) -> @emit 'selection-screen-range-changed', selection + @emitter.emit 'did-change-selection-screen-range', selection ### From 5883e27c60b3ba6fe610773e6fcb224410bb3bca Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 8 Sep 2014 16:32:43 -0700 Subject: [PATCH 202/355] Make Editor::onDidChangeGrammar emit from Editor Seems like the initial implementation was to handle the event, unfold all then, re-emit the grammar-changed event. --- src/editor.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 55b8feaef..055b6d94b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -305,7 +305,7 @@ class Editor extends Model @displayBuffer.onDidChangeSoftWrapped(callback) onDidChangeGrammar: (callback) -> - @displayBuffer.onDidChangeGrammar(callback) + @emitter.on 'did-change-grammar', callback onDidChangeCharacterWidths: (callback) -> @displayBuffer.onDidChangeCharacterWidths(callback) @@ -2534,6 +2534,7 @@ class Editor extends Model handleGrammarChange: -> @unfoldAll() @emit 'grammar-changed' + @emitter.emit 'did-change-grammar' handleMarkerCreated: (marker) => if marker.matchesAttributes(@getSelectionMarkerAttributes()) From bb5a44065189627e0b41b5eadbaea8438b8430b5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 16:55:59 -0700 Subject: [PATCH 203/355] :racehorse Upgrade to atom-keymap@2.0.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 86a61140d..6184d9061 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "atomShellVersion": "0.15.9", "dependencies": { "async": "0.2.6", - "atom-keymap": "^2.0.5", + "atom-keymap": "^2.0.6", "bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372", "clear-cut": "0.4.0", "coffee-script": "1.7.0", From 408cac46329fe2fae163043293d0600a1a962ae7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 17:10:30 -0700 Subject: [PATCH 204/355] :racehorse: Use DOM APIs to find editor views --- src/workspace-view.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 3bccbb228..067600eb0 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -240,7 +240,8 @@ class WorkspaceView extends View # # Returns an {Array} of {EditorView}s. getEditorViews: -> - @panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray() + for editorElement in @panes.element.querySelectorAll('.pane > .item-views > .editor') + $(editorElement).view() # Public: Prepend an element or view to the panels at the top of the # workspace. From f6545d400205505694f4ac89948d1ff56ae13aec Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 8 Sep 2014 17:27:34 -0700 Subject: [PATCH 205/355] Check if name matches before resolving path Path resolution hits the filesystem so check for a name match first. --- src/package-manager.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 4935804dd..14da123a7 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -161,6 +161,8 @@ class PackageManager @emit 'loaded' loadPackage: (nameOrPath) -> + return pack if pack = @getLoadedPackage(nameOrPath) + if packagePath = @resolvePackagePath(nameOrPath) name = path.basename(nameOrPath) return pack if pack = @getLoadedPackage(name) From 3487ab9b11ceeb6af2a2259e4663be198434b1ca Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Sep 2014 20:44:49 +0800 Subject: [PATCH 206/355] Upgrade to atom-shell@0.16.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b830dc21f..96c5748c8 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "url": "http://github.com/atom/atom/raw/master/LICENSE.md" } ], - "atomShellVersion": "0.16.1", + "atomShellVersion": "0.16.2", "dependencies": { "async": "0.2.6", "atom-keymap": "^2.0.5", From 3e10f491b484f0d596b779819f5ee95ef455c830 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Sep 2014 20:46:33 +0800 Subject: [PATCH 207/355] Disable subpixel font scaling. --- src/browser/atom-window.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 1022f6f76..ab7e71b04 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -25,7 +25,12 @@ class AtomWindow # Normalize to make sure drive letter case is consistent on Windows @resourcePath = path.normalize(@resourcePath) if @resourcePath - @browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath + @browserWindow = new BrowserWindow + show: false + title: 'Atom' + icon: @constructor.iconPath + 'web-preferences': + 'subpixel-font-scaling': false global.atomApplication.addWindow(this) @handleEvents() From 17aa6f958cc68e2b4b4f59f1fc651ec3760d99aa Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 9 Sep 2014 10:18:19 -0600 Subject: [PATCH 208/355] Upgrade autocomplete to fix specs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 96c5748c8..5227e7096 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "solarized-dark-syntax": "0.22.0", "solarized-light-syntax": "0.12.0", "archive-view": "0.36.0", - "autocomplete": "0.31.0", + "autocomplete": "0.32.0", "autoflow": "0.18.0", "autosave": "0.15.0", "background-tips": "0.16.0", From 7b1f8cc7da21367a2fc6de0cafe88e931fa62200 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Sep 2014 09:55:31 -0700 Subject: [PATCH 209/355] Set project path for window:open-path files The project path will now be set to the parent directory if it isn't already set when a file path is specified via the window:open-path event. Closes atom/tree-view#217 --- spec/window-spec.coffee | 32 ++++++++++++++++++++++++++++++++ src/window-event-handler.coffee | 9 ++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/spec/window-spec.coffee b/spec/window-spec.coffee index 6a449cc5c..6c588ec2d 100644 --- a/spec/window-spec.coffee +++ b/spec/window-spec.coffee @@ -256,3 +256,35 @@ describe "Window", -> elements.trigger "core:focus-previous" expect(elements.find("[tabindex=1]:focus")).toExist() + + describe "the window:open-path event", -> + beforeEach -> + spyOn(atom.workspace, 'open') + + describe "when the project does not have a path", -> + beforeEach -> + atom.project.setPath() + + describe "when the opened path exists", -> + it "sets the project path to the opened path", -> + $(window).trigger('window:open-path', [{pathToOpen: __filename}]) + + expect(atom.project.getPath()).toBe __dirname + + describe "when the opened path does not exist but its parent directory does", -> + it "sets the project path to the opened path's parent directory", -> + $(window).trigger('window:open-path', [{pathToOpen: path.join(__dirname, 'this-path-does-not-exist.txt')}]) + + expect(atom.project.getPath()).toBe __dirname + + describe "when the opened path is a file", -> + it "opens it in the workspace", -> + $(window).trigger('window:open-path', [{pathToOpen: __filename}]) + + expect(atom.workspace.open.mostRecentCall.args[0]).toBe __filename + + describe "when the opened path is a directory", -> + it "does not open it in the workspace", -> + $(window).trigger('window:open-path', [{pathToOpen: __dirname}]) + + expect(atom.workspace.open.callCount).toBe 0 diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 5f2b09b62..5fe4a9ec6 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -1,3 +1,4 @@ +path = require 'path' {$} = require './space-pen-extensions' _ = require 'underscore-plus' ipc = require 'ipc' @@ -28,9 +29,11 @@ class WindowEventHandler @subscribe $(window), 'blur', -> document.body.classList.add('is-blurred') @subscribe $(window), 'window:open-path', (event, {pathToOpen, initialLine, initialColumn}) -> - if fs.isDirectorySync(pathToOpen) - atom.project.setPath(pathToOpen) unless atom.project.getPath() - else + unless atom.project?.getPath() + if fs.existsSync(pathToOpen) or fs.existsSync(path.dirname(pathToOpen)) + atom.project?.setPath(pathToOpen) + + unless fs.isDirectorySync(pathToOpen) atom.workspace?.open(pathToOpen, {initialLine, initialColumn}) @subscribe $(window), 'beforeunload', => From aebdfb4cf607e15b86fde8fa4528c2b7083accf4 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:39:41 -0700 Subject: [PATCH 210/355] Event docs --- src/editor.coffee | 214 +++++++++++++++++++--------------------------- 1 file changed, 88 insertions(+), 126 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 055b6d94b..cb95f3e14 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -52,126 +52,6 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # # **When in doubt, just default to buffer coordinates**, then experiment with # soft wraps and folds to ensure your code interacts with them correctly. -# -# ## Events -# -# ### path-changed -# -# Essential: Emit when the buffer's path, and therefore title, has changed. -# -# ### title-changed -# -# Essential: Emit when the buffer's path, and therefore title, has changed. -# -# ### modified-status-changed -# -# Extended: Emit when the result of {::isModified} changes. -# -# ### soft-wrap-changed -# -# Extended: Emit when soft wrap was enabled or disabled. -# -# * `softWrapped` {Boolean} indicating whether soft wrap is enabled or disabled. -# -# ### grammar-changed -# -# Extended: Emit when the grammar that interprets and colorizes the text has -# been changed. -# -# -# -# ### contents-modified -# -# Essential: Emit when the buffer's contents change. It is emit asynchronously -# 300ms after the last buffer change. This is a good place to handle changes to -# the buffer without compromising typing performance. -# -# ### contents-conflicted -# -# Extended: Emitted when the buffer's underlying file changes on disk at a -# moment when the result of {::isModified} is true. -# -# ### will-insert-text -# -# Extended: Emit before the text has been inserted. -# -# * `event` event {Object} -# * `text` {String} text to be inserted -# * `cancel` {Function} Call to prevent the text from being inserted -# -# ### did-insert-text -# -# Extended: Emit after the text has been inserted. -# -# * `event` event {Object} -# * `text` {String} text to be inserted -# -# -# -# ### cursor-moved -# -# Essential: Emit when a cursor has been moved. If there are multiple cursors, -# it will be emit for each cursor. -# -# * `event` {Object} -# * `oldBufferPosition` {Point} -# * `oldScreenPosition` {Point} -# * `newBufferPosition` {Point} -# * `newScreenPosition` {Point} -# * `textChanged` {Boolean} -# -# ### cursor-added -# -# Extended: Emit when a cursor has been added. -# -# * `cursor` {Cursor} that was added -# -# ### cursor-removed -# -# Extended: Emit when a cursor has been removed. -# -# * `cursor` {Cursor} that was removed -# -# -# -# ### selection-screen-range-changed -# -# Essential: Emit when a selection's screen range changes. -# -# * `selection`: {Selection} object that has a changed range -# -# ### selection-added -# -# Extended: Emit when a selection's was added. -# -# * `selection`: {Selection} object that was added -# -# ### selection-removed -# -# Extended: Emit when a selection's was removed. -# -# * `selection`: {Selection} object that was removed -# -# -# -# ### decoration-added -# -# Extended: Emit when a {Decoration} is added to the editor. -# -# * `decoration` {Decoration} that was added -# -# ### decoration-removed -# -# Extended: Emit when a {Decoration} is removed from the editor. -# -# * `decoration` {Decoration} that was removed -# -# ### decoration-updated -# -# Extended: Emit when a {Decoration} is updated via the {Decoration::update} method. -# -# * `decoration` {Decoration} that was updated -# module.exports = class Editor extends Model Serializable.includeInto(this) @@ -292,63 +172,145 @@ class Editor extends Model @displayBuffer.destroy() @languageMode.destroy() + ### + Section: Events + ### + + # Essential: Calls your `callback` when the buffer's title has changed. + # + # * `callback` {Function} onDidChangeTitle: (callback) -> @emitter.on 'did-change-title', callback + # Essential: Calls your `callback` when the buffer's path, and therefore title, has changed. + # + # * `callback` {Function} onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback - onDidChangeModified: (callback) -> - @getBuffer().onDidChangeModified(callback) - + # Extended: Calls your `callback` when soft wrap was enabled or disabled. + # + # * `callback` {Function} onDidChangeSoftWrapped: (callback) -> @displayBuffer.onDidChangeSoftWrapped(callback) + # Extended: Calls your `callback` when the grammar that interprets and colorizes the text has + # been changed. + # + # * `callback` {Function} onDidChangeGrammar: (callback) -> @emitter.on 'did-change-grammar', callback - onDidChangeCharacterWidths: (callback) -> - @displayBuffer.onDidChangeCharacterWidths(callback) - + # Essential: Calls your `callback` when the buffer's contents change. It is + # emit asynchronously 300ms after the last buffer change. This is a good place + # to handle changes to the buffer without compromising typing performance. + # + # * `callback` {Function} onDidStopChanging: (callback) -> @getBuffer().onDidStopChanging(callback) + # Extended: Calls your `callback` when the result of {::isModified} changes. + # + # * `callback` {Function} + onDidChangeModified: (callback) -> + @getBuffer().onDidChangeModified(callback) + + # Extended: Calls your `callback` when the buffer's underlying file changes on + # disk at a moment when the result of {::isModified} is true. + # + # * `callback` {Function} onDidConflict: (callback) -> @getBuffer().onDidConflict(callback) + # Extended: Calls your `callback` before text has been inserted. + # + # * `callback` {Function} + # * `event` event {Object} + # * `text` {String} text to be inserted + # * `cancel` {Function} Call to prevent the text from being inserted onWillInsertText: (callback) -> @emitter.on 'will-insert-text', callback + # Extended: Calls your `callback` adter text has been inserted. + # + # * `callback` {Function} + # * `event` event {Object} + # * `text` {String} text to be inserted onDidInsertText: (callback) -> @emitter.on 'did-insert-text', callback + # Extended: Calls your `callback` when a {Cursor} is added to the editor. + # + # * `callback` {Function} + # * `cursor` {Cursor} that was added onDidAddCursor: (callback) -> @emitter.on 'did-add-cursor', callback + # Extended: Calls your `callback` when a {Cursor} is removed to the editor. + # + # * `callback` {Function} + # * `cursor` {Cursor} that was removed onDidRemoveCursor: (callback) -> @emitter.on 'did-remove-cursor', callback + # Essential: Calls your `callback` when a {Cursor} is removed to the editor. + # + # * `callback` {Function} + # * `event` {Object} + # * `oldBufferPosition` {Point} + # * `oldScreenPosition` {Point} + # * `newBufferPosition` {Point} + # * `newScreenPosition` {Point} + # * `textChanged` {Boolean} onDidMoveCursor: (callback) -> @emitter.on 'did-move-cursor', callback + # Extended: Calls your `callback` when a {Selection} is added to the editor. + # + # * `callback` {Function} + # * `selection` {Selection} that was added onDidAddSelection: (callback) -> @emitter.on 'did-add-selection', callback + # Extended: Calls your `callback` when a {Selection} is removed from the editor. + # + # * `callback` {Function} + # * `selection` {Selection} that was removed onDidRemoveSelection: (callback) -> @emitter.on 'did-remove-selection', callback + # Essential: Calls your `callback` when a selection's screen range changes. + # + # * `callback` {Function} + # * `selection` {Selection} that moved onDidChangeSelectionScreenRange: (callback) -> @emitter.on 'did-change-selection-screen-range', callback + # Extended: Calls your `callback` with each {Decoration} added to the editor. + # Calls your `callback` immediately for any existing decorations. + # + # * `callback` {Function} + # * `decoration` {Decoration} observeDecorations: (callback) -> @displayBuffer.observeDecorations(callback) + # Extended: Calls your `callback` when a {Decoration} is added to the editor. + # + # * `callback` {Function} + # * `decoration` {Decoration} that was added onDidAddDecoration: (callback) -> @displayBuffer.onDidAddDecoration(callback) + # Extended: Calls your `callback` when a {Decoration} is removed from the editor. + # + # * `callback` {Function} + # * `decoration` {Decoration} that was removed onDidRemoveDecoration: (callback) -> @displayBuffer.onDidRemoveDecoration(callback) + onDidChangeCharacterWidths: (callback) -> + @displayBuffer.onDidChangeCharacterWidths(callback) + onDidChangeScreenLines: (callback) -> @emitter.on 'did-change-screen-lines', callback From 7198a919bfbbe74a3dedeb6837c78db33895fa6f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:43:25 -0700 Subject: [PATCH 211/355] onDidMoveCursor -> onDidChangeCursorPosition --- src/editor.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index cb95f3e14..6da726893 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -262,8 +262,8 @@ class Editor extends Model # * `newBufferPosition` {Point} # * `newScreenPosition` {Point} # * `textChanged` {Boolean} - onDidMoveCursor: (callback) -> - @emitter.on 'did-move-cursor', callback + onDidChangeCursorPosition: (callback) -> + @emitter.on 'did-change-cursor-position', callback # Extended: Calls your `callback` when a {Selection} is added to the editor. # @@ -349,7 +349,7 @@ class Editor extends Model when 'cursor-removed' deprecate("Use Editor::onDidRemoveCursor instead") when 'cursor-moved' - deprecate("Use Editor::onDidMoveCursor instead") + deprecate("Use Editor::onDidChangeCursorPosition instead") when 'selection-added' deprecate("Use Editor::onDidAddSelection instead") @@ -1913,7 +1913,7 @@ class Editor extends Model cursorMoved: (cursor, event) -> @emit 'cursor-moved', event - @emitter.emit 'did-move-cursor', event + @emitter.emit 'did-change-cursor-position', event # Merge cursors that have the same screen position mergeCursors: -> From c7525e8cff74c87d34526b9478f0cba226792c2e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:51:35 -0700 Subject: [PATCH 212/355] :lipstick: doc strings --- src/editor.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 6da726893..1cd5315bd 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -246,14 +246,15 @@ class Editor extends Model onDidAddCursor: (callback) -> @emitter.on 'did-add-cursor', callback - # Extended: Calls your `callback` when a {Cursor} is removed to the editor. + # Extended: Calls your `callback` when a {Cursor} is removed from the editor. # # * `callback` {Function} # * `cursor` {Cursor} that was removed onDidRemoveCursor: (callback) -> @emitter.on 'did-remove-cursor', callback - # Essential: Calls your `callback` when a {Cursor} is removed to the editor. + # Essential: Calls your `callback` when a {Cursor} is moved. If there are + # multiple cursors, your callback will be called for each cursor. # # * `callback` {Function} # * `event` {Object} From 9db804b413a36b678ca867003c0b85222f70b186 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:51:46 -0700 Subject: [PATCH 213/355] Doc events in `Cursor` --- src/cursor.coffee | 50 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index a35cf4d68..ce7061fef 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -9,31 +9,6 @@ Grim = require 'grim' # # Cursors belong to {Editor}s and have some metadata attached in the form # of a {Marker}. -# -# ## Events -# -# ### moved -# -# Extended: Emit when a cursor has been moved. If there are multiple cursors, -# it will be emit for each cursor. -# -# * `event` {Object} -# * `oldBufferPosition` {Point} -# * `oldScreenPosition` {Point} -# * `newBufferPosition` {Point} -# * `newScreenPosition` {Point} -# * `textChanged` {Boolean} -# -# ### destroyed -# -# Extended: Emit when the cursor is destroyed -# -# ### visibility-changed -# -# Extended: Emit when the Cursor is hidden or shown -# -# * `visible` {Boolean} true when cursor is visible -# module.exports = class Cursor extends Model screenPosition: null @@ -79,19 +54,41 @@ class Cursor extends Model @emitter.dispose() @needsAutoscroll = true + # Essential: Calls your `callback` when the cursor has been moved. + # + # * `callback` {Function} + # * `event` {Object} + # * `oldBufferPosition` {Point} + # * `oldScreenPosition` {Point} + # * `newBufferPosition` {Point} + # * `newScreenPosition` {Point} + # * `textChanged` {Boolean} onDidChangePosition: (callback) -> @emitter.on 'did-change-position', callback + # Extended: Calls your `callback` when the cursor is destroyed + # + # * `callback` {Function} onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback + # Extended: Calls your `callback` when the cursor's visibility has changed + # + # * `callback` {Function} + # * `visibility` {Boolean} + onDidChangeVisibility: (callback) -> + @emitter.on 'did-change-visibility', callback + on: (eventName) -> switch eventName when 'moved' Grim.deprecate("Use Cursor::onDidChangePosition instead") when 'destroyed' Grim.deprecate("Use Cursor::onDidDestroy instead") - + when 'destroyed' + Grim.deprecate("Use Cursor::onDidDestroy instead") + else + Grim.deprecate("::on is no longer supported. Use the event subscription methods instead") super destroy: -> @@ -153,6 +150,7 @@ class Cursor extends Model @visible = visible @needsAutoscroll ?= true if @visible and @isLastCursor() @emit 'visibility-changed', @visible + @emitter.emit 'did-change-visibility', @visible # Public: Returns the visibility of the cursor. isVisible: -> @visible From 858ac5bf79c806720d4a8370c220c563af4d641e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:54:51 -0700 Subject: [PATCH 214/355] onDidChangeSelectionScreenRange -> onDidChangeSelectionRange for consistency --- src/editor.coffee | 11 ++++++----- src/selection.coffee | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 1cd5315bd..b661d3ffe 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -284,8 +284,8 @@ class Editor extends Model # # * `callback` {Function} # * `selection` {Selection} that moved - onDidChangeSelectionScreenRange: (callback) -> - @emitter.on 'did-change-selection-screen-range', callback + onDidChangeSelectionRange: (callback) -> + @emitter.on 'did-change-selection-range', callback # Extended: Calls your `callback` with each {Decoration} added to the editor. # Calls your `callback` immediately for any existing decorations. @@ -357,7 +357,7 @@ class Editor extends Model when 'selection-removed' deprecate("Use Editor::onDidRemoveSelection instead") when 'selection-screen-range-changed' - deprecate("Use Editor::onDidChangeSelectionScreenRange instead") + deprecate("Use Editor::onDidChangeSelectionRange instead") when 'decoration-added' deprecate("Use Editor::onDidAddDecoration instead") @@ -2394,9 +2394,10 @@ class Editor extends Model else false - selectionScreenRangeChanged: (selection) -> + # Called by the selection + selectionRangeChanged: (selection) -> @emit 'selection-screen-range-changed', selection - @emitter.emit 'did-change-selection-screen-range', selection + @emitter.emit 'did-change-selection-range', selection ### diff --git a/src/selection.coffee b/src/selection.coffee index 3be1869fe..cd7a65b10 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -689,4 +689,4 @@ class Selection extends Model screenRangeChanged: -> @emit 'screen-range-changed', @getScreenRange() @emitter.emit 'did-change-range' - @editor.selectionScreenRangeChanged(this) + @editor.selectionRangeChanged(this) From 789d9c8eff0751c38d227b51f2d9377da33043ef Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:56:44 -0700 Subject: [PATCH 215/355] :memo: Selection event methods --- src/selection.coffee | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/selection.coffee b/src/selection.coffee index cd7a65b10..b7d3adb2d 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -5,19 +5,6 @@ Grim = require 'grim' # Extended: Represents a selection in the {Editor}. -# -# ## Events -# -# ### screen-range-changed -# -# Extended: Emit when the selection was moved. -# -# * `screenRange` {Range} indicating the new screenrange -# -# ### destroyed -# -# Extended: Emit when the selection was destroyed -# module.exports = class Selection extends Model cursor: null @@ -43,9 +30,16 @@ class Selection extends Model @emitter.emit 'did-destroy' @emitter.dispose() + # Extended: Calls your `callback` when the selection was moved. + # + # * `callback` {Function} + # * `screenRange` {Range} indicating the new screenrange onDidChangeRange: (callback) -> @emitter.on 'did-change-range', callback + # Extended: Calls your `callback` when the selection was destroyed + # + # * `callback` {Function} onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback From 72be16736cab4f76bc7b8fab26c282560394d4f7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 10:58:12 -0700 Subject: [PATCH 216/355] isDestroyed -> destroyed --- src/decoration.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/decoration.coffee b/src/decoration.coffee index ed027011c..f6e443b51 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -51,7 +51,7 @@ class Decoration @id = nextId() @properties.id = @id @flashQueue = null - @isDestroyed = false + @destroyed = false @markerDestroyDisposable = @marker.onDidDestroy => @destroy() @@ -96,7 +96,7 @@ class Decoration # # * `newProperties` {Object} eg. `{type: 'gutter', class: 'my-new-class'}` setProperties: (newProperties) -> - return if @isDestroyed + return if @destroyed oldProperties = @properties @properties = newProperties @properties.id = @id @@ -115,10 +115,10 @@ class Decoration # If you own the marker, you should use {Marker::destroy} which will destroy # this decoration. destroy: -> - return if @isDestroyed + return if @destroyed @markerDestroyDisposable.dispose() @markerDestroyDisposable = null - @isDestroyed = true + @destroyed = true @emit 'destroyed' @emitter.emit 'did-destroy' @emitter.dispose() From 84deefb6b1c9d737bdb64b86af1f7d09e71b0573 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 9 Sep 2014 12:31:48 -0600 Subject: [PATCH 217/355] Upgrade atom-shell to incorporate changes in 92.2 and 92.3 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 2717d82f6..9a1db364f 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "0.93.1" + "atom-package-manager": "0.93.2" } } From 3e5666f183d93a29ca8201316f1364baf85c55b0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 12:08:12 -0700 Subject: [PATCH 218/355] use getPaneView rather than getPane --- src/editor-view.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 4c95882f4..a1ec8a8b6 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -135,7 +135,7 @@ class EditorView extends View Object.defineProperty @::, 'charWidth', get: -> @editor.getDefaultCharWidth() Object.defineProperty @::, 'firstRenderedScreenRow', get: -> @component.getRenderedRowRange()[0] Object.defineProperty @::, 'lastRenderedScreenRow', get: -> @component.getRenderedRowRange()[1] - Object.defineProperty @::, 'active', get: -> @is(@getPane()?.activeView) + Object.defineProperty @::, 'active', get: -> @is(@getPaneView()?.activeView) Object.defineProperty @::, 'isFocused', get: -> @component?.state.focused Object.defineProperty @::, 'mini', get: -> @component?.props.mini @@ -218,7 +218,7 @@ class EditorView extends View To duplicate this editor into the split use: editorView.getPaneView().getModel().splitLeft(copyActiveItem: true) """ - pane = @getPane() + pane = @getPaneView() pane?.splitLeft(pane?.copyActiveItem()).activeView splitRight: -> @@ -227,7 +227,7 @@ class EditorView extends View To duplicate this editor into the split use: editorView.getPaneView().getModel().splitRight(copyActiveItem: true) """ - pane = @getPane() + pane = @getPaneView() pane?.splitRight(pane?.copyActiveItem()).activeView splitUp: -> @@ -236,7 +236,7 @@ class EditorView extends View To duplicate this editor into the split use: editorView.getPaneView().getModel().splitUp(copyActiveItem: true) """ - pane = @getPane() + pane = @getPaneView() pane?.splitUp(pane?.copyActiveItem()).activeView splitDown: -> @@ -245,7 +245,7 @@ class EditorView extends View To duplicate this editor into the split use: editorView.getPaneView().getModel().splitDown(copyActiveItem: true) """ - pane = @getPane() + pane = @getPaneView() pane?.splitDown(pane?.copyActiveItem()).activeView # Public: Get this {EditorView}'s {PaneView}. From 0f83fe54f97ccfa28112f7e5f5bd552d096ca4fd Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 12:08:43 -0700 Subject: [PATCH 219/355] Add and use Editor::observeSelections() and ::observeCursors() --- src/editor-component.coffee | 4 ++-- src/editor.coffee | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index f2d4cbc65..d70cf9a14 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -345,8 +345,8 @@ EditorComponent = React.createClass observeEditor: -> {editor} = @props @subscribe editor.onDidChangeScreenLines(@onScreenLinesChanged) - @subscribe editor.onDidAddCursor(@onCursorAdded) - @subscribe editor.onDidAddSelection(@onSelectionAdded) + @subscribe editor.observeCursors(@onCursorAdded) + @subscribe editor.observeSelections(@onSelectionAdded) @subscribe editor.observeDecorations(@onDecorationAdded) @subscribe editor.onDidRemoveDecoration(@onDecorationRemoved) @subscribe editor.onDidChangeCharacterWidths(@onCharacterWidthsChanged) diff --git a/src/editor.coffee b/src/editor.coffee index b661d3ffe..bf40518bf 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -239,6 +239,15 @@ class Editor extends Model onDidInsertText: (callback) -> @emitter.on 'did-insert-text', callback + # Extended: Calls your `callback` when a {Cursor} is added to the editor. + # Immediately calls your callback for each existing cursor. + # + # * `callback` {Function} + # * `selection` {Selection} that was added + observeCursors: (callback) -> + callback(cursor) for cursor in @getCursors() + @onDidAddCursor(callback) + # Extended: Calls your `callback` when a {Cursor} is added to the editor. # # * `callback` {Function} @@ -266,6 +275,15 @@ class Editor extends Model onDidChangeCursorPosition: (callback) -> @emitter.on 'did-change-cursor-position', callback + # Extended: Calls your `callback` when a {Selection} is added to the editor. + # Immediately calls your callback for each existing selection. + # + # * `callback` {Function} + # * `selection` {Selection} that was added + observeSelections: (callback) -> + callback(selection) for selection in @getSelections() + @onDidAddSelection(callback) + # Extended: Calls your `callback` when a {Selection} is added to the editor. # # * `callback` {Function} From e452b88fec23043f46c45873477368e8b3c439e6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 12:30:43 -0700 Subject: [PATCH 220/355] Add sections for events --- src/cursor.coffee | 8 ++++++++ src/selection.coffee | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/cursor.coffee b/src/cursor.coffee index ce7061fef..1126ad790 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -54,6 +54,10 @@ class Cursor extends Model @emitter.dispose() @needsAutoscroll = true + ### + Section: Events + ### + # Essential: Calls your `callback` when the cursor has been moved. # # * `callback` {Function} @@ -91,6 +95,10 @@ class Cursor extends Model Grim.deprecate("::on is no longer supported. Use the event subscription methods instead") super + ### + Section: Methods + ### + destroy: -> @marker.destroy() diff --git a/src/selection.coffee b/src/selection.coffee index b7d3adb2d..5e2118bee 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -30,6 +30,10 @@ class Selection extends Model @emitter.emit 'did-destroy' @emitter.dispose() + ### + Section: Events + ### + # Extended: Calls your `callback` when the selection was moved. # # * `callback` {Function} @@ -52,6 +56,10 @@ class Selection extends Model super + ### + Section: Methods + ### + destroy: -> @marker.destroy() From 2a02375c4d07e2a06f2201b922a814997375f215 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 12:31:01 -0700 Subject: [PATCH 221/355] Move the Decoration events to an events section --- src/decoration.coffee | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/decoration.coffee b/src/decoration.coffee index f6e443b51..cd5035e5f 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -55,6 +55,26 @@ class Decoration @markerDestroyDisposable = @marker.onDidDestroy => @destroy() + ### + Section: Events + ### + + # Essential: When the {Decoration} is updated via {Decoration::update}. + # + # * `event` {Object} + # * `oldProperties` {Object} the old parameters the decoration used to have + # * `newProperties` {Object} the new parameters the decoration now has + onDidChangeProperties: (callback) -> + @emitter.on 'did-change-properties', callback + + # Essential: Invoke the given callback when the {Decoration} is destroyed + onDidDestroy: (callback) -> + @emitter.on 'did-destroy', callback + + ### + Section: Methods + ### + # Essential: An id unique across all {Decoration} objects getId: -> @id @@ -71,14 +91,6 @@ class Decoration isType: (type) -> Decoration.isType(@properties, type) - # Essential: When the {Decoration} is updated via {Decoration::update}. - # - # * `event` {Object} - # * `oldProperties` {Object} the old parameters the decoration used to have - # * `newProperties` {Object} the new parameters the decoration now has - onDidChangeProperties: (callback) -> - @emitter.on 'did-change-properties', callback - # Essential: Returns the {Decoration}'s properties. getProperties: -> @properties @@ -106,10 +118,6 @@ class Decoration Grim.deprecate 'Use Decoration::setProperties instead' @setProperties(newProperties) - # Essential: Invoke the given callback when the {Decoration} is destroyed - onDidDestroy: (callback) -> - @emitter.on 'did-destroy', callback - # Essential: Destroy this marker. # # If you own the marker, you should use {Marker::destroy} which will destroy From ab96e5b5fdfd57f942d6e9ff5b21368b30068257 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 13:58:01 -0700 Subject: [PATCH 222/355] :lipstick: Fix doc string --- src/decoration.coffee | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/decoration.coffee b/src/decoration.coffee index cd5035e5f..7216aee18 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -61,13 +61,16 @@ class Decoration # Essential: When the {Decoration} is updated via {Decoration::update}. # - # * `event` {Object} - # * `oldProperties` {Object} the old parameters the decoration used to have - # * `newProperties` {Object} the new parameters the decoration now has + # * `callback` {Function} + # * `event` {Object} + # * `oldProperties` {Object} the old parameters the decoration used to have + # * `newProperties` {Object} the new parameters the decoration now has onDidChangeProperties: (callback) -> @emitter.on 'did-change-properties', callback # Essential: Invoke the given callback when the {Decoration} is destroyed + # + # * `callback` {Function} onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback From ed4acb02d8d07eb12b36a7e4d4d5be9db322112b Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 13:58:23 -0700 Subject: [PATCH 223/355] Add Project::onDidChangePath() --- src/project.coffee | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index a34a442a5..4cf76cf94 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -6,7 +6,9 @@ fs = require 'fs-plus' Q = require 'q' {deprecate} = require 'grim' {Model} = require 'theorist' -{Emitter, Subscriber} = require 'emissary' +{Subscriber} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' Serializable = require 'serializable' TextBuffer = require 'text-buffer' {Directory} = require 'pathwatcher' @@ -46,6 +48,7 @@ class Project extends Model constructor: ({path, @buffers}={}) -> @buffers ?= [] + @emitter = new Emitter for buffer in @buffers do (buffer) => @@ -53,6 +56,25 @@ class Project extends Model @setPath(path) + ### + Section: Events + ### + + # Essential: Invoke the given callback when the project's path has changed. + # + # * `callback` {Function} + # * `path` the new path + onDidChangePath: (callback) -> + @emitter.on 'did-change-path', callback + + on: (eventName) -> + switch eventName + when 'path-changed' + deprecate 'Use Project::onDidChangePath instead' + else + deprecate 'Project::on is deprecated. Use event subscription methods instead.' + EmitterMixin::on.apply(this, arguments) + serializeParams: -> path: @path buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained()) @@ -98,7 +120,8 @@ class Project extends Model else @rootDirectory = null - @emit "path-changed" + @emit 'path-changed' + @emitter.emit 'did-change-path', @getPath() # Public: Returns the root {Directory} object for this project. getRootDirectory: -> From 4070e5fb25a1c001ee781c28a932c105a5ab1598 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:12:49 -0700 Subject: [PATCH 224/355] Add Project::onDidCreateBuffer --- spec/project-spec.coffee | 2 +- src/project.coffee | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 06e3ee29d..b1fed60ee 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -58,7 +58,7 @@ describe "Project", -> beforeEach -> absolutePath = require.resolve('./fixtures/dir/a') newBufferHandler = jasmine.createSpy('newBufferHandler') - atom.project.on 'buffer-created', newBufferHandler + atom.project.onDidCreateBuffer newBufferHandler describe "when given an absolute path that isn't currently open", -> it "returns a new edit session for the given path and emits 'buffer-created'", -> diff --git a/src/project.coffee b/src/project.coffee index 4cf76cf94..fb6cc6cfe 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -67,10 +67,21 @@ class Project extends Model onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback + + # Extended: Invoke the given callback when a new buffer has been created. For + # example, when {::open} is called, this is fired. + # + # * `callback` {Function} + # * `buffer` {TextBuffer} the new buffer + onDidCreateBuffer: (callback) -> + @emitter.on 'did-create-buffer', callback + on: (eventName) -> switch eventName when 'path-changed' deprecate 'Use Project::onDidChangePath instead' + when 'buffer-created' + deprecate 'Use Project::onDidCreateBuffer instead' else deprecate 'Project::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) @@ -245,6 +256,7 @@ class Project extends Model @buffers.splice(index, 0, buffer) buffer.onDidDestroy => @removeBuffer(buffer) @emit 'buffer-created', buffer + @emitter.emit 'did-create-buffer', buffer buffer # Removes a {TextBuffer} association from the project. From b6fe72ef9e416723f66c775049381c8b28c927f3 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:13:26 -0700 Subject: [PATCH 225/355] Add Project::observeBuffers --- spec/project-spec.coffee | 6 +++--- src/git.coffee | 2 +- src/project.coffee | 20 +++++++++++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index b1fed60ee..7c705b8a4 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -479,7 +479,7 @@ describe "Project", -> runs -> expect(results).toHaveLength 0 - describe ".eachBuffer(callback)", -> + describe ".observeBuffers(callback)", -> beforeEach -> atom.project.bufferForPathSync('a') @@ -490,7 +490,7 @@ describe "Project", -> callback = (buffer) -> callbackBuffer = buffer count++ - atom.project.eachBuffer(callback) + atom.project.observeBuffers(callback) expect(count).toBe 1 expect(callbackBuffer).toBe atom.project.getBuffers()[0] @@ -501,7 +501,7 @@ describe "Project", -> callbackBuffer = buffer count++ - atom.project.eachBuffer(callback) + atom.project.observeBuffers(callback) count = 0 callbackBuffer = null atom.project.bufferForPathSync(require.resolve('./fixtures/sample.txt')) diff --git a/src/git.coffee b/src/git.coffee index 0e5273aa9..d3c811440 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -86,7 +86,7 @@ class Git @refreshStatus() if @project? - @subscribe @project.eachBuffer (buffer) => @subscribeToBuffer(buffer) + @subscribe @project.observeBuffers (buffer) => @subscribeToBuffer(buffer) # Subscribes to buffer events. subscribeToBuffer: (buffer) -> diff --git a/src/project.coffee b/src/project.coffee index fb6cc6cfe..f21e65c5e 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -67,6 +67,15 @@ class Project extends Model onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback + # Extended: Immediately invoke the given callback for all existing buffers. + # Then invoke the given callback when a new buffer has been created. For + # example, when {::open} is called, this is fired. + # + # * `callback` {Function} + # * `buffer` {TextBuffer} the new buffer + observeBuffers: (callback) -> + callback(buffer) for buffer in @getBuffers() + @onDidCreateBuffer(callback) # Extended: Invoke the given callback when a new buffer has been created. For # example, when {::open} is called, this is fired. @@ -363,11 +372,12 @@ class Project extends Model subscriber = args.shift() if args.length > 1 callback = args.shift() - callback(buffer) for buffer in @getBuffers() - if subscriber - subscriber.subscribe this, 'buffer-created', (buffer) -> callback(buffer) - else - @on 'buffer-created', (buffer) -> callback(buffer) + message = 'Use Project::observeBuffers instead' + message += '; Project::observeBuffers no longer accepts a subscriber parameter. Call `subscriber.subscribe(atom.project.observeBuffers(cb))`' if subscriber? + + disposable = observeBuffers(callback) + subscriber.subscribe(disposable) if subscriber? + disposable # Deprecated: delegate registerOpener: (opener) -> From ffbb18a0f8750064271bc2494089f52b3cd4371b Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:16:10 -0700 Subject: [PATCH 226/355] Remove event comments, add method section comment --- src/project.coffee | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index f21e65c5e..ddf09ab6e 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -20,19 +20,6 @@ Git = require './git' # Extended: Represents a project that's opened in Atom. # # An instance of this class is always available as the `atom.project` global. -# -# ## Events -# -# ### path-changed -# -# Extended: Emit when the project's path has changed. Use {::getPath} to get the new path -# -# ### buffer-created -# -# Extended: Emit when a buffer is created. For example, when {::open} is called, this is fired. -# -# * `buffer` {TextBuffer} the new buffer that was created. -# module.exports = class Project extends Model atom.deserializers.add(this) @@ -95,6 +82,10 @@ class Project extends Model deprecate 'Project::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) + ### + Section: Methods + ### + serializeParams: -> path: @path buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained()) From 05f54d427d4d8ed2e1dac2bec7ead8d7adcdc9ba Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:28:30 -0700 Subject: [PATCH 227/355] Add Git::onDidChangeStatus --- spec/git-spec.coffee | 24 ++++++++++++------------ src/git.coffee | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index 2de1d2e16..4e3bb7de3 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -111,10 +111,10 @@ describe "Git", -> fs.writeFileSync(filePath, 'ch ch changes') repo.getPathStatus(filePath) statusHandler = jasmine.createSpy('statusHandler') - repo.on 'status-changed', statusHandler + repo.onDidChangeStatus statusHandler repo.checkoutHead(filePath) expect(statusHandler.callCount).toBe 1 - expect(statusHandler.argsForCall[0][0..1]).toEqual [filePath, 0] + expect(statusHandler.argsForCall[0][0]).toEqual {path: filePath, pathStatus: 0} repo.checkoutHead(filePath) expect(statusHandler.callCount).toBe 1 @@ -167,11 +167,11 @@ describe "Git", -> it "trigger a status-changed event when the new status differs from the last cached one", -> statusHandler = jasmine.createSpy("statusHandler") - repo.on 'status-changed', statusHandler + repo.onDidChangeStatus statusHandler fs.writeFileSync(filePath, '') status = repo.getPathStatus(filePath) expect(statusHandler.callCount).toBe 1 - expect(statusHandler.argsForCall[0][0..1]).toEqual [filePath, status] + expect(statusHandler.argsForCall[0][0]).toEqual {path: filePath, pathStatus: status} fs.writeFileSync(filePath, 'abc') status = repo.getPathStatus(filePath) @@ -232,19 +232,19 @@ describe "Git", -> editor.insertNewline() statusHandler = jasmine.createSpy('statusHandler') - atom.project.getRepo().on 'status-changed', statusHandler + atom.project.getRepo().onDidChangeStatus statusHandler editor.save() expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 + expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256} it "emits a status-changed event when a buffer is reloaded", -> fs.writeFileSync(editor.getPath(), 'changed') statusHandler = jasmine.createSpy('statusHandler') - atom.project.getRepo().on 'status-changed', statusHandler + atom.project.getRepo().onDidChangeStatus statusHandler editor.getBuffer().reload() expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 + expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256} editor.getBuffer().reload() expect(statusHandler.callCount).toBe 1 @@ -252,10 +252,10 @@ describe "Git", -> fs.writeFileSync(editor.getPath(), 'changed') statusHandler = jasmine.createSpy('statusHandler') - atom.project.getRepo().on 'status-changed', statusHandler + atom.project.getRepo().onDidChangeStatus statusHandler editor.getBuffer().emitter.emit 'did-change-path' expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 + expect(statusHandler).toHaveBeenCalledWith {path: editor.getPath(), pathStatus: 256} editor.getBuffer().emitter.emit 'did-change-path' expect(statusHandler.callCount).toBe 1 @@ -283,7 +283,7 @@ describe "Git", -> buffer.append('changes') statusHandler = jasmine.createSpy('statusHandler') - project2.getRepo().on 'status-changed', statusHandler + project2.getRepo().onDidChangeStatus statusHandler buffer.save() expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith buffer.getPath(), 256 + expect(statusHandler).toHaveBeenCalledWith {path: buffer.getPath(), pathStatus: 256} diff --git a/src/git.coffee b/src/git.coffee index d3c811440..bfabcf829 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -1,9 +1,12 @@ {basename, join} = require 'path' _ = require 'underscore-plus' -{Emitter, Subscriber} = require 'emissary' +{Subscriber} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' fs = require 'fs-plus' GitUtils = require 'git-utils' +{deprecate} = require 'grim' Task = require './task' @@ -41,7 +44,7 @@ Task = require './task' # ``` module.exports = class Git - Emitter.includeInto(this) + EmitterMixin.includeInto(this) Subscriber.includeInto(this) # Public: Creates a new Git instance. @@ -67,6 +70,7 @@ class Git false constructor: (path, options={}) -> + @emitter = new Emitter @repo = GitUtils.open(path) unless @repo? throw new Error("No Git repository found searching path: #{path}") @@ -88,6 +92,32 @@ class Git if @project? @subscribe @project.observeBuffers (buffer) => @subscribeToBuffer(buffer) + ### + Section: Events + ### + + # Essential: When the {Decoration} is updated via {Decoration::update}. + # + # * `callback` {Function} + # * `event` {Object} + # * `path` {String} the old parameters the decoration used to have + # * `pathStatus` {Number} representing the status. This value can be passed to + # {::isStatusModified} or {::isStatusNew} to get more information. + onDidChangeStatus: (callback) -> + @emitter.on 'did-change-status', callback + + on: (eventName) -> + switch eventName + when 'status-changed' + deprecate 'Use Git::onDidChangeStatus instead' + else + deprecate 'Git::on is deprecated. Use event subscription methods instead.' + EmitterMixin::on.apply(this, arguments) + + ### + Section: Methods + ### + # Subscribes to buffer events. subscribeToBuffer: (buffer) -> getBufferPathStatus = => @@ -171,6 +201,8 @@ class Git delete @statuses[relativePath] if currentPathStatus isnt pathStatus @emit 'status-changed', path, pathStatus + @emitter.emit 'did-change-status', {path, pathStatus} + pathStatus # Public: Is the given path ignored? From dddd17c11b02d8e4214a9684cfb3e6a968317085 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:29:14 -0700 Subject: [PATCH 228/355] Fix observeBuffers --- src/project.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index ddf09ab6e..1fe38577f 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -366,7 +366,7 @@ class Project extends Model message = 'Use Project::observeBuffers instead' message += '; Project::observeBuffers no longer accepts a subscriber parameter. Call `subscriber.subscribe(atom.project.observeBuffers(cb))`' if subscriber? - disposable = observeBuffers(callback) + disposable = @observeBuffers(callback) subscriber.subscribe(disposable) if subscriber? disposable From 66b27ad52ac3112571c9879582907c8148de9598 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Sep 2014 14:30:09 -0700 Subject: [PATCH 229/355] Upgrade to snippets@0.52 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da2194ed1..53deaaf71 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "package-generator": "0.31.0", "release-notes": "0.36.0", "settings-view": "0.142.0", - "snippets": "0.51.0", + "snippets": "0.52.0", "spell-check": "0.42.0", "status-bar": "0.44.0", "styleguide": "0.30.0", From ae4f92cc5253ea3b79ea9193fcd51048e7aa3779 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:45:31 -0700 Subject: [PATCH 230/355] Add onDidChangeStatuses --- spec/git-spec.coffee | 2 +- src/git.coffee | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index 4e3bb7de3..2cc0a6239 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -208,7 +208,7 @@ describe "Git", -> it "returns status information for all new and modified files", -> fs.writeFileSync(modifiedPath, 'making this path modified') statusHandler = jasmine.createSpy('statusHandler') - repo.on 'statuses-changed', statusHandler + repo.onDidChangeStatuses statusHandler repo.refreshStatus() waitsFor -> diff --git a/src/git.coffee b/src/git.coffee index bfabcf829..34beb474e 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -106,10 +106,21 @@ class Git onDidChangeStatus: (callback) -> @emitter.on 'did-change-status', callback + # Essential: Invoke the given callback when a multiple files' statuses have + # changed. For example, on window focus, the status of all the paths in the + # repo is checked. If any of them have changed, this will be fired. Call + # {::getPathStatus(path)} to get the status for your path of choice. + # + # * `callback` {Function} + onDidChangeStatuses: (callback) -> + @emitter.on 'did-change-statuses', callback + on: (eventName) -> switch eventName when 'status-changed' deprecate 'Use Git::onDidChangeStatus instead' + when 'statuses-changed' + deprecate 'Use Git::onDidChangeStatuses instead' else deprecate 'Git::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) @@ -423,4 +434,6 @@ class Git for submodulePath, submoduleRepo of @getRepo().submodules submoduleRepo.upstream = submodules[submodulePath]?.upstream ? {ahead: 0, behind: 0} - @emit 'statuses-changed' unless statusesUnchanged + unless statusesUnchanged + @emit 'statuses-changed' + @emitter.emit 'did-change-statuses' From af1b0b5736a8884581763b3a5028dc63779e7c6d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 14:45:41 -0700 Subject: [PATCH 231/355] Fix Doc String --- src/git.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/git.coffee b/src/git.coffee index 34beb474e..7f9d28007 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -96,7 +96,9 @@ class Git Section: Events ### - # Essential: When the {Decoration} is updated via {Decoration::update}. + # Essential: Invoke the given callback when a specific file's status has + # changed. When a file is updated, reloaded, etc, and the status changes, this + # will be fired. # # * `callback` {Function} # * `event` {Object} From 229277f764c1e9c35206eaf5d2cc63ea98e60006 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:03:45 -0700 Subject: [PATCH 232/355] Add PackageManager::onDidActivateAll() --- src/atom.coffee | 2 +- src/menu-manager.coffee | 2 +- src/package-manager.coffee | 30 +++++++++++++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 4fb113302..697a92c4b 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -187,7 +187,7 @@ class Atom extends Model @syntax = @deserializers.deserialize(@state.syntax) ? new Syntax() - @subscribe @packages, 'activated', => @watchThemes() + @subscribe @packages.onDidActivateAll => @watchThemes() Project = require './project' TextBuffer = require 'text-buffer' diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index b9f64a2fc..5c7d955d0 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -15,7 +15,7 @@ class MenuManager @pendingUpdateOperation = null @template = [] atom.keymaps.on 'bundled-keymaps-loaded', => @loadPlatformItems() - atom.packages.on 'activated', => @sortPackagesMenu() + atom.packages.onDidActivateAll => @sortPackagesMenu() # Public: Adds the given items to the application menu. # diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 14da123a7..98416806f 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -1,14 +1,16 @@ path = require 'path' _ = require 'underscore-plus' -{Emitter} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' fs = require 'fs-plus' Q = require 'q' +{deprecate} = require 'grim' Package = require './package' ThemePackage = require './theme-package' -# Public: Package manager for coordinating the lifecycle of Atom packages. +# Extended: Package manager for coordinating the lifecycle of Atom packages. # # An instance of this class is always available as the `atom.packages` global. # @@ -25,9 +27,10 @@ ThemePackage = require './theme-package' # settings and also by calling `enablePackage()/disablePackage()`. module.exports = class PackageManager - Emitter.includeInto(this) + EmitterMixin.includeInto(this) constructor: ({configDirPath, devMode, safeMode, @resourcePath}) -> + @emitter = new Emitter @packageDirPaths = [] unless safeMode if devMode @@ -41,6 +44,26 @@ class PackageManager @packageActivators = [] @registerPackageActivator(this, ['atom', 'textmate']) + # Essential: Invoke the given callback when all packages have been activated. + # + # * `callback` {Function} + onDidActivateAll: (callback) -> + @emitter.on 'did-activate-all', callback + + on: (eventName) -> + switch eventName + when 'loaded' + deprecate 'Use PackageManager::onDidLoadAll instead' + when 'activated' + deprecate 'Use PackageManager::onDidActivateAll instead' + else + deprecate 'PackageManager::on is deprecated. Use event subscription methods instead.' + EmitterMixin::on.apply(this, arguments) + + ### + Section: Methods + ### + # Extended: Get the path to the apm command. # # Return a {String} file path to apm. @@ -83,6 +106,7 @@ class PackageManager packages = @getLoadedPackagesForTypes(types) activator.activatePackages(packages) @emit 'activated' + @emitter.emit 'did-activate-all' # another type of package manager can handle other package types. # See ThemeManager From 55b5debd7f1042353cfa8d091b915b88efeac860 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:04:13 -0700 Subject: [PATCH 233/355] Add PackageManager::onDidLoadAll --- src/package-manager.coffee | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 98416806f..7fd2bcd16 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -44,6 +44,16 @@ class PackageManager @packageActivators = [] @registerPackageActivator(this, ['atom', 'textmate']) + ### + Section: Events + ### + + # Essential: Invoke the given callback when all packages have been activated. + # + # * `callback` {Function} + onDidLoadAll: (callback) -> + @emitter.on 'did-load-all', callback + # Essential: Invoke the given callback when all packages have been activated. # # * `callback` {Function} @@ -183,6 +193,7 @@ class PackageManager packagePaths = _.uniq packagePaths, (packagePath) -> path.basename(packagePath) @loadPackage(packagePath) for packagePath in packagePaths @emit 'loaded' + @emitter.emit 'did-load-all' loadPackage: (nameOrPath) -> return pack if pack = @getLoadedPackage(nameOrPath) From 0afd8a139231e69df83fc182f6ac7fa06e146bff Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:09:18 -0700 Subject: [PATCH 234/355] Add Package::onDidDeactivate --- spec/package-spec.coffee | 2 +- src/package.coffee | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee index bbb00ca81..b94f86a0f 100644 --- a/spec/package-spec.coffee +++ b/spec/package-spec.coffee @@ -102,6 +102,6 @@ describe "Package", -> theme.activate() it "deactivated event fires on .deactivate()", -> - theme.on 'deactivated', spy = jasmine.createSpy() + theme.onDidDeactivate spy = jasmine.createSpy() theme.deactivate() expect(spy).toHaveBeenCalled() diff --git a/src/package.coffee b/src/package.coffee index 707e7b591..7a8133466 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -4,8 +4,10 @@ _ = require 'underscore-plus' async = require 'async' CSON = require 'season' fs = require 'fs-plus' -{Emitter} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' Q = require 'q' +{deprecate} = require 'grim' $ = null # Defer require in case this is in the window-less browser process ScopedProperties = require './scoped-properties' @@ -14,7 +16,7 @@ ScopedProperties = require './scoped-properties' # stylesheets, keymaps, grammar, editor properties, and menus. module.exports = class Package - Emitter.includeInto(this) + EmitterMixin.includeInto(this) @stylesheetsDir: 'stylesheets' @@ -38,10 +40,33 @@ class Package mainModule: null constructor: (@path, @metadata) -> + @emitter = new Emitter @metadata ?= Package.loadMetadata(@path) @name = @metadata?.name ? path.basename(@path) @reset() + ### + Section: Events + ### + + # Essential: Invoke the given callback when all packages have been activated. + # + # * `callback` {Function} + onDidDeactivate: (callback) -> + @emitter.on 'did-deactivate', callback + + on: (eventName) -> + switch eventName + when 'deactivated' + deprecate 'Use Package::onDidDeactivate instead' + else + deprecate 'Package::on is deprecated. Use event subscription methods instead.' + EmitterMixin::on.apply(this, arguments) + + ### + Section: Methods + ### + enable: -> atom.config.removeAtKeyPath('core.disabledPackages', @name) @@ -243,7 +268,8 @@ class Package @deactivateResources() @deactivateConfig() @mainModule?.deactivate?() if @mainActivated - @emit('deactivated') + @emit 'deactivated' + @emitter.emit 'did-deactivate' deactivateConfig: -> @mainModule?.deactivateConfig?() From 3bf348e51feadaf194889a83c82ab3a1a37cbddb Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:24:55 -0700 Subject: [PATCH 235/355] Add ThemeManager::onDidReloadAll --- spec/theme-manager-spec.coffee | 2 +- src/theme-manager.coffee | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index d3a30c589..ebb8e1c6e 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -69,7 +69,7 @@ describe "ThemeManager", -> describe "when the core.themes config value changes", -> it "add/removes stylesheets to reflect the new config value", -> - themeManager.on 'reloaded', reloadHandler = jasmine.createSpy() + themeManager.onDidReloadAll reloadHandler = jasmine.createSpy() spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null waitsForPromise -> diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 6ed3e764a..e3da5377b 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -1,10 +1,12 @@ path = require 'path' _ = require 'underscore-plus' -{Emitter} = require 'emissary' +EmitterMixin = require('emissary').Emitter +{Emitter} = require 'event-kit' {File} = require 'pathwatcher' fs = require 'fs-plus' Q = require 'q' +{deprecate} = require 'grim' Package = require './package' @@ -36,12 +38,35 @@ Package = require './package' # module.exports = class ThemeManager - Emitter.includeInto(this) + EmitterMixin.includeInto(this) constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode}) -> + @emitter = new Emitter @lessCache = null @packageManager.registerPackageActivator(this, ['theme']) + ### + Section: Events + ### + + # Essential: Invoke `callback` when all styles have been reloaded. + # + # * `callback` {Function} + onDidReloadAll: (callback) -> + @emitter.on 'did-reload-all', callback + + on: (eventName) -> + switch eventName + when 'reloaded' + deprecate 'Use ThemeManager::onDidReloadAll instead' + else + deprecate 'ThemeManager::on is deprecated. Use event subscription methods instead.' + EmitterMixin::on.apply(this, arguments) + + ### + Section: Methods + ### + getAvailableNames: -> # TODO: Maybe should change to list all the available themes out there? @getLoadedNames() @@ -121,6 +146,7 @@ class ThemeManager @loadUserStylesheet() @reloadBaseStylesheets() @emit 'reloaded' + @emitter.emit 'did-reload-all' deferred.resolve() deferred.promise From 5ba5215f5d53305e73c75d0fc7e315d67ecebc95 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:35:00 -0700 Subject: [PATCH 236/355] Add event subscription methods to ThemeManager --- spec/theme-manager-spec.coffee | 24 +++++++++++++----------- src/theme-manager.coffee | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index ebb8e1c6e..7028d7c95 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -131,8 +131,8 @@ describe "ThemeManager", -> describe "requireStylesheet(path)", -> it "synchronously loads css at the given path and installs a style tag for it in the head", -> - themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler") - themeManager.on 'stylesheet-added', stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler") + themeManager.onDidChangeStylesheets stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler") + themeManager.onDidAddStylesheet stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler") cssPath = atom.project.resolve('css.css') lengthBefore = $('head style').length @@ -193,8 +193,8 @@ describe "ThemeManager", -> themeManager.requireStylesheet(cssPath) expect($(document.body).css('font-weight')).toBe("bold") - themeManager.on 'stylesheet-removed', stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler") - themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler") + themeManager.onDidRemoveStylesheet stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler") + themeManager.onDidChangeStylesheets stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler") themeManager.removeStylesheet(cssPath) @@ -217,7 +217,7 @@ describe "ThemeManager", -> themeManager.activateThemes() it "loads the correct values from the theme's ui-variables file", -> - themeManager.on 'reloaded', reloadHandler = jasmine.createSpy() + themeManager.onDidReloadAll reloadHandler = jasmine.createSpy() atom.config.set('core.themes', ['theme-with-ui-variables']) waitsFor -> @@ -234,7 +234,7 @@ describe "ThemeManager", -> describe "when there is a theme with incomplete variables", -> it "loads the correct values from the fallback ui-variables", -> - themeManager.on 'reloaded', reloadHandler = jasmine.createSpy() + themeManager.onDidReloadAll reloadHandler = jasmine.createSpy() atom.config.set('core.themes', ['theme-with-incomplete-ui-variables']) waitsFor -> @@ -251,7 +251,7 @@ describe "ThemeManager", -> it 'adds theme-* classes to the workspace for each active theme', -> expect(atom.workspaceView).toHaveClass 'theme-atom-dark-ui' - themeManager.on 'reloaded', reloadHandler = jasmine.createSpy() + themeManager.onDidReloadAll reloadHandler = jasmine.createSpy() atom.config.set('core.themes', ['theme-with-ui-variables']) waitsFor -> @@ -273,9 +273,9 @@ describe "ThemeManager", -> themeManager.activateThemes() runs -> - themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler") - themeManager.on 'stylesheet-removed', stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler") - themeManager.on 'stylesheet-added', stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler") + themeManager.onDidChangeStylesheets stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler") + themeManager.onDidRemoveStylesheet stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler") + themeManager.onDidAddStylesheet stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler") spyOn(themeManager, 'loadUserStylesheet').andCallThrough() expect($(document.body).css('border-style')).toBe 'dotted' @@ -316,7 +316,9 @@ describe "ThemeManager", -> themeManager.activateThemes() runs -> - themeManager.once 'reloaded', -> reloaded = true + disposable = themeManager.onDidReloadAll -> + disposable.dispose() + reloaded = true spyOn(console, 'warn') expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow() diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index e3da5377b..ee48d555f 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -55,10 +55,36 @@ class ThemeManager onDidReloadAll: (callback) -> @emitter.on 'did-reload-all', callback + # Essential: Invoke `callback` when a stylesheet has been added to the dom. + # + # * `callback` {Function} + # * `stylesheet` {HTMLElement} the style node + onDidAddStylesheet: (callback) -> + @emitter.on 'did-add-stylesheet', callback + + # Essential: Invoke `callback` when a stylesheet has been removed from the dom. + # + # * `callback` {Function} + # * `stylesheet` {HTMLElement} the style node + onDidRemoveStylesheet: (callback) -> + @emitter.on 'did-remove-stylesheet', callback + + # Essential: Invoke `callback` when any stylesheet has been updated, added, or removed. + # + # * `callback` {Function} + onDidChangeStylesheets: (callback) -> + @emitter.on 'did-change-stylesheets', callback + on: (eventName) -> switch eventName when 'reloaded' deprecate 'Use ThemeManager::onDidReloadAll instead' + when 'stylesheet-added' + deprecate 'Use ThemeManager::onDidAddStylesheet instead' + when 'stylesheet-removed' + deprecate 'Use ThemeManager::onDidRemoveStylesheet instead' + when 'stylesheets-changed' + deprecate 'Use ThemeManager::onDidChangeStylesheets instead' else deprecate 'ThemeManager::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) @@ -286,7 +312,9 @@ class ThemeManager {sheet} = element element.remove() @emit 'stylesheet-removed', sheet + @emitter.emit 'did-remove-stylesheet', sheet @emit 'stylesheets-changed' + @emitter.emit 'did-change-stylesheets' applyStylesheet: (path, text, type='bundled') -> styleId = @stringToId(path) @@ -294,6 +322,7 @@ class ThemeManager if styleElement? @emit 'stylesheet-removed', styleElement.sheet + @emitter.emit 'did-remove-stylesheet', styleElement.sheet styleElement.textContent = text else styleElement = document.createElement('style') @@ -308,4 +337,6 @@ class ThemeManager document.head.appendChild(styleElement) @emit 'stylesheet-added', styleElement.sheet + @emitter.emit 'did-add-stylesheet', styleElement.sheet @emit 'stylesheets-changed' + @emitter.emit 'did-change-stylesheets' From 10ceb344266b33099b68aa0d7fbafbdb8b748e2b Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:43:12 -0700 Subject: [PATCH 237/355] Fix docs --- src/theme-manager.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index ee48d555f..e4ae4c626 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -58,14 +58,14 @@ class ThemeManager # Essential: Invoke `callback` when a stylesheet has been added to the dom. # # * `callback` {Function} - # * `stylesheet` {HTMLElement} the style node + # * `stylesheet` {StyleSheet} the style node onDidAddStylesheet: (callback) -> @emitter.on 'did-add-stylesheet', callback # Essential: Invoke `callback` when a stylesheet has been removed from the dom. # # * `callback` {Function} - # * `stylesheet` {HTMLElement} the style node + # * `stylesheet` {StyleSheet} the style node onDidRemoveStylesheet: (callback) -> @emitter.on 'did-remove-stylesheet', callback From 09fbd468695c252bc2d964b3f0065f81c7a48d4f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:43:35 -0700 Subject: [PATCH 238/355] Remove event docs --- src/theme-manager.coffee | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index e4ae4c626..7ada908f9 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -13,29 +13,6 @@ Package = require './package' # Extended: Handles loading and activating available themes. # # An instance of this class is always available as the `atom.themes` global. -# -# ## Events -# -# ### reloaded -# -# Extended: Emitted when all styles have been reloaded. -# -# ### stylesheet-added -# -# Extended: Emitted when a stylesheet has been added. -# -# * `stylesheet` {StyleSheet} object that was removed -# -# ### stylesheet-removed -# -# Extended: Emitted when a stylesheet has been removed. -# -# * `stylesheet` {StyleSheet} object that was removed -# -# ### stylesheets-changed -# -# Extended: Emitted anytime any style sheet is added or removed from the editor -# module.exports = class ThemeManager EmitterMixin.includeInto(this) From 2e219f288d5b926a5dd1f1d952d84cbc99d668d1 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 15:55:47 -0700 Subject: [PATCH 239/355] Add sections for docs clarity --- src/cursor.coffee | 2 +- src/decoration.coffee | 2 +- src/editor.coffee | 2 +- src/git.coffee | 10 +++++++++- src/package-manager.coffee | 4 ++-- src/package.coffee | 12 ++++++++++-- src/project.coffee | 2 +- src/selection.coffee | 2 +- src/theme-manager.coffee | 2 +- 9 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 1126ad790..a165ebfef 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -55,7 +55,7 @@ class Cursor extends Model @needsAutoscroll = true ### - Section: Events + Section: Event Subscription ### # Essential: Calls your `callback` when the cursor has been moved. diff --git a/src/decoration.coffee b/src/decoration.coffee index 7216aee18..3cf4822d2 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -56,7 +56,7 @@ class Decoration @markerDestroyDisposable = @marker.onDidDestroy => @destroy() ### - Section: Events + Section: Event Subscription ### # Essential: When the {Decoration} is updated via {Decoration::update}. diff --git a/src/editor.coffee b/src/editor.coffee index bf40518bf..a1b86a0c4 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -173,7 +173,7 @@ class Editor extends Model @languageMode.destroy() ### - Section: Events + Section: Event Subscription ### # Essential: Calls your `callback` when the buffer's title has changed. diff --git a/src/git.coffee b/src/git.coffee index 7f9d28007..b2907eefc 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -47,6 +47,10 @@ class Git EmitterMixin.includeInto(this) Subscriber.includeInto(this) + ### + Section: Class Methods + ### + # Public: Creates a new Git instance. # # * `path` The {String} path to the Git repository to open. @@ -69,6 +73,10 @@ class Git else false + ### + Section: Construction + ### + constructor: (path, options={}) -> @emitter = new Emitter @repo = GitUtils.open(path) @@ -93,7 +101,7 @@ class Git @subscribe @project.observeBuffers (buffer) => @subscribeToBuffer(buffer) ### - Section: Events + Section: Event Subscription ### # Essential: Invoke the given callback when a specific file's status has diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 7fd2bcd16..e3b9d9f3b 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -45,7 +45,7 @@ class PackageManager @registerPackageActivator(this, ['atom', 'textmate']) ### - Section: Events + Section: Event ### # Essential: Invoke the given callback when all packages have been activated. @@ -71,7 +71,7 @@ class PackageManager EmitterMixin::on.apply(this, arguments) ### - Section: Methods + Section: Instance Methods ### # Extended: Get the path to the apm command. diff --git a/src/package.coffee b/src/package.coffee index 7a8133466..bb443329a 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -20,6 +20,10 @@ class Package @stylesheetsDir: 'stylesheets' + ### + Section: Class Methods + ### + @loadMetadata: (packagePath, ignoreErrors=false) -> if metadataPath = CSON.resolve(path.join(packagePath, 'package')) try @@ -39,6 +43,10 @@ class Package resolvedMainModulePath: false mainModule: null + ### + Section: Construction + ### + constructor: (@path, @metadata) -> @emitter = new Emitter @metadata ?= Package.loadMetadata(@path) @@ -46,7 +54,7 @@ class Package @reset() ### - Section: Events + Section: Event Subscription ### # Essential: Invoke the given callback when all packages have been activated. @@ -64,7 +72,7 @@ class Package EmitterMixin::on.apply(this, arguments) ### - Section: Methods + Section: Instance Methods ### enable: -> diff --git a/src/project.coffee b/src/project.coffee index 1fe38577f..f2743be18 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -44,7 +44,7 @@ class Project extends Model @setPath(path) ### - Section: Events + Section: Event Subscription ### # Essential: Invoke the given callback when the project's path has changed. diff --git a/src/selection.coffee b/src/selection.coffee index 5e2118bee..47f87b31c 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -31,7 +31,7 @@ class Selection extends Model @emitter.dispose() ### - Section: Events + Section: Event Subscription ### # Extended: Calls your `callback` when the selection was moved. diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 7ada908f9..562bcdd5a 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -23,7 +23,7 @@ class ThemeManager @packageManager.registerPackageActivator(this, ['theme']) ### - Section: Events + Section: Event Subscription ### # Essential: Invoke `callback` when all styles have been reloaded. From 55ac855de199e2855f1e957a4ccb09b9d9f676f9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Sep 2014 16:12:20 -0700 Subject: [PATCH 240/355] Upgrade to pathwatcher 2.0.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 53deaaf71..c34793b61 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "nslog": "^1.0.1", "oniguruma": "^3.0.4", "optimist": "0.4.0", - "pathwatcher": "^2.0.10", + "pathwatcher": "^2.0.11", "property-accessors": "^1", "q": "^1.0.1", "random-words": "0.0.1", From 40eaf69ab0e0d0239783eb779fdfe89a8ce64573 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Sep 2014 16:25:44 -0700 Subject: [PATCH 241/355] Upgrade to metrics@0.34 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c34793b61..e4ed9cb62 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "keybinding-resolver": "0.19.0", "link": "0.25.0", "markdown-preview": "0.101.0", - "metrics": "0.33.0", + "metrics": "0.34.0", "open-on-github": "0.30.0", "package-generator": "0.31.0", "release-notes": "0.36.0", From 291bf7fe082c841d6328d48f642cc0555b7e35ae Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Sep 2014 16:31:00 -0700 Subject: [PATCH 242/355] Upgrade to pathwatcher 2.0.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4ed9cb62..5e8fe4570 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "nslog": "^1.0.1", "oniguruma": "^3.0.4", "optimist": "0.4.0", - "pathwatcher": "^2.0.11", + "pathwatcher": "^2.0.12", "property-accessors": "^1", "q": "^1.0.1", "random-words": "0.0.1", From 335339ef6104f7740fbf499eca772f1b09039ac2 Mon Sep 17 00:00:00 2001 From: Jordon Bedwell Date: Tue, 9 Sep 2014 20:20:39 -0500 Subject: [PATCH 243/355] Change language and make the command one line. --- docs/build-instructions/linux.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index f603aca98..c589ae9a6 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -100,14 +100,13 @@ have Node.js installed, or node isn't identified as Node.js on your machine. If it's the latter, entering `sudo ln -s /usr/bin/nodejs /usr/bin/node` into your terminal may fix the issue. -## You can also use Alternatives: +#### You can also use Alternatives -On some variants it's preferrable for you to use Alternatives so can easily -rollback and change the binary paths: +On some variants (mostly Debian based Distros) it's preferrable for you to use +Alternatives so that changes the binary paths can be fixed or alterered easily: ``` -sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 1 \ - --slave /usr/bin/js js /usr/bin/nodejs +sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 1 --slave /usr/bin/js js /usr/bin/nodejs ``` ### Linux build error reports in atom/atom From b0c17aa98f1097701ccbb08463b4ac162c9b75e3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 9 Sep 2014 18:32:37 -0700 Subject: [PATCH 244/355] :memo: Correct misspellings --- docs/build-instructions/linux.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index c589ae9a6..8d230ff88 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -102,10 +102,10 @@ your terminal may fix the issue. #### You can also use Alternatives -On some variants (mostly Debian based Distros) it's preferrable for you to use -Alternatives so that changes the binary paths can be fixed or alterered easily: +On some variants (mostly Debian based distros) it's preferable for you to use +Alternatives so that changes to the binary paths can be fixed or altered easily: -``` +```sh sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 1 --slave /usr/bin/js js /usr/bin/nodejs ``` From 5a64b09924e59d3a0e5ca9ff16a502be2632297a Mon Sep 17 00:00:00 2001 From: Jordon Bedwell Date: Tue, 9 Sep 2014 20:36:40 -0500 Subject: [PATCH 245/355] Proc requires super user permissions on Linux. --- docs/build-instructions/linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 8d230ff88..e5d54069e 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -88,7 +88,7 @@ this is the reason for this error you can issue and restart Atom. If Atom now works fine, you can make this setting permanent: ```sh - echo 32768 > /proc/sys/fs/inotify/max_user_watches + echo 32768 | sudo tee -a /proc/sys/fs/inotify/max_user_watches ``` See also https://github.com/atom/atom/issues/2082. From a3f3b7e032ca901af62d348bb2f0cf943770ca51 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 10 Sep 2014 09:45:06 -0600 Subject: [PATCH 246/355] Upgrade text-buffer to fix null exception --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e8fe4570..13ab58f32 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "serializable": "^1", "space-pen": "3.4.6", "temp": "0.7.0", - "text-buffer": "^3.2.0", + "text-buffer": "^3.2.2", "theorist": "^1.0.2", "underscore-plus": "^1.5.1", "vm-compatibility-layer": "0.1.0" From d1bdda5b3ec0e8ac8df1063ba7f3224c562c98bc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Sep 2014 09:40:55 -0700 Subject: [PATCH 247/355] Upgrade to language-html@0.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13ab58f32..68af6b3dd 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "language-gfm": "0.48.0", "language-git": "0.9.0", "language-go": "0.17.0", - "language-html": "0.25.0", + "language-html": "0.26.0", "language-hyperlink": "0.12.0", "language-java": "0.11.0", "language-javascript": "0.39.0", From d9b1b7b39976d65ae6542b1fd0a02e1eea1c66f3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Sep 2014 10:08:06 -0700 Subject: [PATCH 248/355] Don't dump symbols on Windows CI for now Currently errors and isn't uploaded yet anyway as a release asset --- build/Gruntfile.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 876964a20..a014dc3c9 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -225,9 +225,14 @@ module.exports = (grunt) -> grunt.registerTask('compile', ['coffee', 'prebuild-less', 'cson', 'peg']) grunt.registerTask('lint', ['coffeelint', 'csslint', 'lesslint']) grunt.registerTask('test', ['shell:kill-atom', 'run-specs']) - grunt.registerTask('ci', ['output-disk-space', 'download-atom-shell', 'build', 'dump-symbols', 'set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build']) grunt.registerTask('docs', ['markdown:guides', 'build-docs']) + + ciTasks = ['output-disk-space', 'download-atom-shell', 'build'] + ciTasks.push('dump-symbols') unless process.platform is 'win32' + ciTasks.push('set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build') + grunt.registerTask('ci', ciTasks) + defaultTasks = ['download-atom-shell', 'build', 'set-version'] defaultTasks.push 'install' unless process.platform is 'linux' grunt.registerTask('default', defaultTasks) From 883f7e1f5ab539f418d61374e38394072743ef19 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Sep 2014 10:22:48 -0700 Subject: [PATCH 249/355] Use cross-platform path in specs --- spec/editor-spec.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 8b0b06f25..d54ff5598 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -152,10 +152,10 @@ describe "Editor", -> observed = [] editor.onDidChangePath (filePath) -> observed.push(filePath) - buffer.setPath('/foo/bar/baz.txt') + buffer.setPath(__filename) buffer.setPath(undefined) - expect(observed).toEqual ['/foo/bar/baz.txt', undefined] + expect(observed).toEqual [__filename, undefined] describe "cursor", -> describe ".getLastCursor()", -> From 9c24e5a23d23aa8b473fc020e458531fb4196f96 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Sep 2014 11:02:57 -0700 Subject: [PATCH 250/355] Prepare 0.127 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68af6b3dd..c8348da2b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.126.0", + "version": "0.127.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 61166bf3650b4caabcf23226c8609b9489dda67c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Sep 2014 11:14:08 -0700 Subject: [PATCH 251/355] Don't track focus for spec windows --- src/browser/atom-application.coffee | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 1849fb6cd..1011a660b 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -101,11 +101,12 @@ class AtomApplication window.once 'window:loaded', => @autoUpdateManager.emitUpdateAvailableEvent(window) - focusHandler = => @lastFocusedWindow = window - window.browserWindow.on 'focus', focusHandler - window.browserWindow.once 'closed', => - @lastFocusedWindow = null if window is @lastFocusedWindow - window.browserWindow.removeListener 'focus', focusHandler + unless window.isSpec + focusHandler = => @lastFocusedWindow = window + window.browserWindow.on 'focus', focusHandler + window.browserWindow.once 'closed', => + @lastFocusedWindow = null if window is @lastFocusedWindow + window.browserWindow.removeListener 'focus', focusHandler # Creates server to listen for additional atom application launches. # From c141448e9f0a2db0418716f7dd5e4b0fca795415 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 10 Sep 2014 11:19:02 -0700 Subject: [PATCH 252/355] Wrap HTML elements in $ so matchers still work --- vendor/jasmine-jquery.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/jasmine-jquery.js b/vendor/jasmine-jquery.js index 02599fd3c..5fe347b9f 100644 --- a/vendor/jasmine-jquery.js +++ b/vendor/jasmine-jquery.js @@ -138,6 +138,9 @@ jasmine.JQuery.matchersClass = {}; var builtInMatcher = jasmine.Matchers.prototype[methodName]; jasmine.JQuery.matchersClass[methodName] = function() { + if (this.actual instanceof HTMLElement) { + this.actual = jQuery(this.actual); + } if (this.actual instanceof jQuery) { var result = jQueryMatchers[methodName].apply(this, arguments); this.actual = jasmine.JQuery.elementToString(this.actual); From 6a0a842de440fa88981d9fa0e1065b1a0f5d80ab Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 11:52:57 -0700 Subject: [PATCH 253/355] Update section comments --- src/package-manager.coffee | 2 +- src/package.coffee | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index e3b9d9f3b..4151869ec 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -45,7 +45,7 @@ class PackageManager @registerPackageActivator(this, ['atom', 'textmate']) ### - Section: Event + Section: Event Subscription ### # Essential: Invoke the given callback when all packages have been activated. diff --git a/src/package.coffee b/src/package.coffee index bb443329a..e21182f0b 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -20,10 +20,6 @@ class Package @stylesheetsDir: 'stylesheets' - ### - Section: Class Methods - ### - @loadMetadata: (packagePath, ignoreErrors=false) -> if metadataPath = CSON.resolve(path.join(packagePath, 'package')) try From 61fa1c4230527849406be6212dc5b00cb5ce65bf Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 11:55:26 -0700 Subject: [PATCH 254/355] Revert "Add Project::observeBuffers" This reverts commit b6fe72ef9e416723f66c775049381c8b28c927f3. Conflicts: src/project.coffee --- spec/project-spec.coffee | 6 +++--- src/git.coffee | 2 +- src/project.coffee | 20 +++++--------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 7c705b8a4..b1fed60ee 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -479,7 +479,7 @@ describe "Project", -> runs -> expect(results).toHaveLength 0 - describe ".observeBuffers(callback)", -> + describe ".eachBuffer(callback)", -> beforeEach -> atom.project.bufferForPathSync('a') @@ -490,7 +490,7 @@ describe "Project", -> callback = (buffer) -> callbackBuffer = buffer count++ - atom.project.observeBuffers(callback) + atom.project.eachBuffer(callback) expect(count).toBe 1 expect(callbackBuffer).toBe atom.project.getBuffers()[0] @@ -501,7 +501,7 @@ describe "Project", -> callbackBuffer = buffer count++ - atom.project.observeBuffers(callback) + atom.project.eachBuffer(callback) count = 0 callbackBuffer = null atom.project.bufferForPathSync(require.resolve('./fixtures/sample.txt')) diff --git a/src/git.coffee b/src/git.coffee index b2907eefc..fb458c995 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -98,7 +98,7 @@ class Git @refreshStatus() if @project? - @subscribe @project.observeBuffers (buffer) => @subscribeToBuffer(buffer) + @subscribe @project.eachBuffer (buffer) => @subscribeToBuffer(buffer) ### Section: Event Subscription diff --git a/src/project.coffee b/src/project.coffee index f2743be18..96da3da5e 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -54,15 +54,6 @@ class Project extends Model onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback - # Extended: Immediately invoke the given callback for all existing buffers. - # Then invoke the given callback when a new buffer has been created. For - # example, when {::open} is called, this is fired. - # - # * `callback` {Function} - # * `buffer` {TextBuffer} the new buffer - observeBuffers: (callback) -> - callback(buffer) for buffer in @getBuffers() - @onDidCreateBuffer(callback) # Extended: Invoke the given callback when a new buffer has been created. For # example, when {::open} is called, this is fired. @@ -363,12 +354,11 @@ class Project extends Model subscriber = args.shift() if args.length > 1 callback = args.shift() - message = 'Use Project::observeBuffers instead' - message += '; Project::observeBuffers no longer accepts a subscriber parameter. Call `subscriber.subscribe(atom.project.observeBuffers(cb))`' if subscriber? - - disposable = @observeBuffers(callback) - subscriber.subscribe(disposable) if subscriber? - disposable + callback(buffer) for buffer in @getBuffers() + if subscriber + subscriber.subscribe this, 'buffer-created', (buffer) -> callback(buffer) + else + @on 'buffer-created', (buffer) -> callback(buffer) # Deprecated: delegate registerOpener: (opener) -> From 40b32930cf497030eb8d97dafd09dc5721a3d213 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 11:55:41 -0700 Subject: [PATCH 255/355] Revert "Add Project::onDidCreateBuffer" This reverts commit 4070e5fb25a1c001ee781c28a932c105a5ab1598. --- spec/project-spec.coffee | 2 +- src/project.coffee | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index b1fed60ee..06e3ee29d 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -58,7 +58,7 @@ describe "Project", -> beforeEach -> absolutePath = require.resolve('./fixtures/dir/a') newBufferHandler = jasmine.createSpy('newBufferHandler') - atom.project.onDidCreateBuffer newBufferHandler + atom.project.on 'buffer-created', newBufferHandler describe "when given an absolute path that isn't currently open", -> it "returns a new edit session for the given path and emits 'buffer-created'", -> diff --git a/src/project.coffee b/src/project.coffee index 96da3da5e..3f8d7ce37 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -54,21 +54,10 @@ class Project extends Model onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback - - # Extended: Invoke the given callback when a new buffer has been created. For - # example, when {::open} is called, this is fired. - # - # * `callback` {Function} - # * `buffer` {TextBuffer} the new buffer - onDidCreateBuffer: (callback) -> - @emitter.on 'did-create-buffer', callback - on: (eventName) -> switch eventName when 'path-changed' deprecate 'Use Project::onDidChangePath instead' - when 'buffer-created' - deprecate 'Use Project::onDidCreateBuffer instead' else deprecate 'Project::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) @@ -247,7 +236,6 @@ class Project extends Model @buffers.splice(index, 0, buffer) buffer.onDidDestroy => @removeBuffer(buffer) @emit 'buffer-created', buffer - @emitter.emit 'did-create-buffer', buffer buffer # Removes a {TextBuffer} association from the project. From 49937b2956dd62b756fb9029b994bd059feae2e0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 11:56:38 -0700 Subject: [PATCH 256/355] Revert "Add Project::onDidChangePath()" This reverts commit ed4acb02d8d07eb12b36a7e4d4d5be9db322112b. Conflicts: src/project.coffee --- src/project.coffee | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/project.coffee b/src/project.coffee index 3f8d7ce37..371a7af3e 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -6,9 +6,7 @@ fs = require 'fs-plus' Q = require 'q' {deprecate} = require 'grim' {Model} = require 'theorist' -{Subscriber} = require 'emissary' -EmitterMixin = require('emissary').Emitter -{Emitter} = require 'event-kit' +{Emitter, Subscriber} = require 'emissary' Serializable = require 'serializable' TextBuffer = require 'text-buffer' {Directory} = require 'pathwatcher' @@ -35,7 +33,6 @@ class Project extends Model constructor: ({path, @buffers}={}) -> @buffers ?= [] - @emitter = new Emitter for buffer in @buffers do (buffer) => @@ -43,29 +40,6 @@ class Project extends Model @setPath(path) - ### - Section: Event Subscription - ### - - # Essential: Invoke the given callback when the project's path has changed. - # - # * `callback` {Function} - # * `path` the new path - onDidChangePath: (callback) -> - @emitter.on 'did-change-path', callback - - on: (eventName) -> - switch eventName - when 'path-changed' - deprecate 'Use Project::onDidChangePath instead' - else - deprecate 'Project::on is deprecated. Use event subscription methods instead.' - EmitterMixin::on.apply(this, arguments) - - ### - Section: Methods - ### - serializeParams: -> path: @path buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained()) @@ -111,8 +85,7 @@ class Project extends Model else @rootDirectory = null - @emit 'path-changed' - @emitter.emit 'did-change-path', @getPath() + @emit "path-changed" # Public: Returns the root {Directory} object for this project. getRootDirectory: -> From 8f8165e289423e05d78d78a87d6efd82587a6b2f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 9 Sep 2014 16:30:39 -0700 Subject: [PATCH 257/355] Fix doc strings in Atom class --- src/atom.coffee | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 697a92c4b..dd87eb6a4 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -408,20 +408,19 @@ class Atom extends Model # ## Examples # # ```coffee - # atom.confirm - # message: 'How you feeling?' - # detailedMessage: 'Be honest.' - # buttons: - # Good: -> window.alert('good to hear') - # Bad: -> window.alert('bummer') + # atom.confirm + # message: 'How you feeling?' + # detailedMessage: 'Be honest.' + # buttons: + # Good: -> window.alert('good to hear') + # Bad: -> window.alert('bummer') # ``` # # * `options` An {Object} with the following keys: # * `message` The {String} message to display. # * `detailedMessage` The {String} detailed message to display. # * `buttons` Either an array of strings or an object where keys are - # button names and the values are callbacks to invoke when - # clicked. + # button names and the values are callbacks to invoke when clicked. # # Returns the chosen button index {Number} if the buttons option was an array. confirm: ({message, detailedMessage, buttons}={}) -> From 60a3cebfab5146552fa92818dc9c5c2e660b24f4 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 12:13:04 -0700 Subject: [PATCH 258/355] Fix section name in git class --- src/git.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git.coffee b/src/git.coffee index fb458c995..8b9507e43 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -136,7 +136,7 @@ class Git EmitterMixin::on.apply(this, arguments) ### - Section: Methods + Section: Instance Methods ### # Subscribes to buffer events. From 238cf608829a8daf71d56ba498f91c2375f0e34e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 10 Sep 2014 14:58:21 -0600 Subject: [PATCH 259/355] Upgrade pathwatcher for explicit event subscription methods --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c8348da2b..c6e931ff8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "atomShellVersion": "0.16.2", "dependencies": { "async": "0.2.6", - "atom-keymap": "^2.0.6", + "atom-keymap": "^2.0.7", "bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372", "clear-cut": "0.4.0", "coffee-script": "1.7.0", @@ -42,7 +42,7 @@ "nslog": "^1.0.1", "oniguruma": "^3.0.4", "optimist": "0.4.0", - "pathwatcher": "^2.0.12", + "pathwatcher": "^2.1.0", "property-accessors": "^1", "q": "^1.0.1", "random-words": "0.0.1", @@ -57,7 +57,7 @@ "serializable": "^1", "space-pen": "3.4.6", "temp": "0.7.0", - "text-buffer": "^3.2.2", + "text-buffer": "^3.2.3", "theorist": "^1.0.2", "underscore-plus": "^1.5.1", "vm-compatibility-layer": "0.1.0" From be1d4ee5dc7c125bcd7ffb0f97af6414bcba6e7d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 14:35:05 -0700 Subject: [PATCH 260/355] Use explicit versions of donna and tello in build package.json --- build/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/package.json b/build/package.json index bbad40c40..e77040261 100644 --- a/build/package.json +++ b/build/package.json @@ -7,8 +7,8 @@ }, "dependencies": { "async": "~0.2.9", - "donna": "~1.0", - "tello": "~0.2", + "donna": "1.0.1", + "tello": "1.0.2", "formidable": "~1.0.14", "fs-plus": "2.x", "github-releases": "~0.2.0", From 465c13e2921b78f24dec307e060583e756b96cae Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 15:36:48 -0700 Subject: [PATCH 261/355] Update packages that use atomdoc to force update of atomdoc --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index c6e931ff8..8ec03158b 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,15 @@ "atomShellVersion": "0.16.2", "dependencies": { "async": "0.2.6", - "atom-keymap": "^2.0.7", + "atom-keymap": "^2.0.8", "bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372", "clear-cut": "0.4.0", "coffee-script": "1.7.0", "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.1", - "event-kit": "0.6.0", - "first-mate": "^2.0.5", + "event-kit": "0.7.1", + "first-mate": "^2.0.6", "fs-plus": "^2.2.6", "fstream": "0.1.24", "fuzzaldrin": "^2.1", @@ -42,7 +42,7 @@ "nslog": "^1.0.1", "oniguruma": "^3.0.4", "optimist": "0.4.0", - "pathwatcher": "^2.1.0", + "pathwatcher": "^2.1.1", "property-accessors": "^1", "q": "^1.0.1", "random-words": "0.0.1", @@ -55,9 +55,9 @@ "season": "^1.0.2", "semver": "1.1.4", "serializable": "^1", - "space-pen": "3.4.6", + "space-pen": "3.4.7", "temp": "0.7.0", - "text-buffer": "^3.2.3", + "text-buffer": "^3.2.4", "theorist": "^1.0.2", "underscore-plus": "^1.5.1", "vm-compatibility-layer": "0.1.0" From f0a19e3f670e2b95b92d9a0c654245589fb8e3b2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 10 Sep 2014 16:40:41 -0600 Subject: [PATCH 262/355] Upgrade atom-keymap for event subscription methods --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ec03158b..2b95a2b34 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "atomShellVersion": "0.16.2", "dependencies": { "async": "0.2.6", - "atom-keymap": "^2.0.8", + "atom-keymap": "^2.1.0", "bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372", "clear-cut": "0.4.0", "coffee-script": "1.7.0", From d55f5cba785b64fc87f2129721fddecc69939274 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 10 Sep 2014 17:24:55 -0600 Subject: [PATCH 263/355] Upgrade first-mate for event subscription methods --- package.json | 2 +- spec/spec-helper.coffee | 2 +- src/tokenized-buffer.coffee | 17 ++++++++++------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 2b95a2b34..ec30ddedb 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "delegato": "^1", "emissary": "^1.3.1", "event-kit": "0.7.1", - "first-mate": "^2.0.6", + "first-mate": "^2.1.0", "fs-plus": "^2.2.6", "fstream": "0.1.24", "fuzzaldrin": "^2.1", diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 46d43ed7d..4bad73ee7 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -137,7 +137,7 @@ afterEach -> jasmine.unspy(atom, 'saveSync') ensureNoPathSubscriptions() - atom.syntax.off() + atom.syntax.clearObservers() waits(0) # yield to ui thread to make screen update more frequently ensureNoPathSubscriptions = -> diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index db64f597a..8872b6e01 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -27,12 +27,8 @@ class TokenizedBuffer extends Model @tabLength ?= atom.config.getPositiveInt('editor.tabLength', 2) - @subscribe atom.syntax, 'grammar-added grammar-updated', (grammar) => - if grammar.injectionSelector? - @retokenizeLines() if @hasTokenForSelector(grammar.injectionSelector) - else - newScore = grammar.getScore(@buffer.getPath(), @buffer.getText()) - @setGrammar(grammar, newScore) if newScore > @currentGrammarScore + @subscribe atom.syntax.onDidAddGrammar(@grammarAddedOrUpdated) + @subscribe atom.syntax.onDidUpdateGrammar(@grammarAddedOrUpdated) @subscribe @buffer.onDidChange (e) => @handleBufferChange(e) @subscribe @buffer.onDidChangePath (@bufferPath) => @reloadGrammar() @@ -75,12 +71,19 @@ class TokenizedBuffer extends Model EmitterMixin::on.apply(this, arguments) + grammarAddedOrUpdated: (grammar) => + if grammar.injectionSelector? + @retokenizeLines() if @hasTokenForSelector(grammar.injectionSelector) + else + newScore = grammar.getScore(@buffer.getPath(), @buffer.getText()) + @setGrammar(grammar, newScore) if newScore > @currentGrammarScore + setGrammar: (grammar, score) -> return if grammar is @grammar @unsubscribe(@grammar) if @grammar @grammar = grammar @currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText()) - @subscribe @grammar, 'grammar-updated', => @retokenizeLines() + @subscribe @grammar.onDidUpdate => @retokenizeLines() @retokenizeLines() @emit 'grammar-changed', grammar @emitter.emit 'did-change-grammar', grammar From f8b17b6b3c26d7f8884e38cf3ca9b2653e849c2f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 17:06:51 -0700 Subject: [PATCH 264/355] Add Returns line to all the event subscription methods --- src/cursor.coffee | 6 ++++++ src/decoration.coffee | 4 ++++ src/editor.coffee | 40 ++++++++++++++++++++++++++++++++++++++ src/git.coffee | 4 ++++ src/package-manager.coffee | 4 ++++ src/package.coffee | 2 ++ src/selection.coffee | 4 ++++ src/theme-manager.coffee | 6 ++++++ 8 files changed, 70 insertions(+) diff --git a/src/cursor.coffee b/src/cursor.coffee index a165ebfef..b736dd424 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -67,12 +67,16 @@ class Cursor extends Model # * `newBufferPosition` {Point} # * `newScreenPosition` {Point} # * `textChanged` {Boolean} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangePosition: (callback) -> @emitter.on 'did-change-position', callback # Extended: Calls your `callback` when the cursor is destroyed # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback @@ -80,6 +84,8 @@ class Cursor extends Model # # * `callback` {Function} # * `visibility` {Boolean} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeVisibility: (callback) -> @emitter.on 'did-change-visibility', callback diff --git a/src/decoration.coffee b/src/decoration.coffee index 3cf4822d2..075641058 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -65,12 +65,16 @@ class Decoration # * `event` {Object} # * `oldProperties` {Object} the old parameters the decoration used to have # * `newProperties` {Object} the new parameters the decoration now has + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeProperties: (callback) -> @emitter.on 'did-change-properties', callback # Essential: Invoke the given callback when the {Decoration} is destroyed # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback diff --git a/src/editor.coffee b/src/editor.coffee index a1b86a0c4..92af3ed11 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -179,18 +179,24 @@ class Editor extends Model # Essential: Calls your `callback` when the buffer's title has changed. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeTitle: (callback) -> @emitter.on 'did-change-title', callback # Essential: Calls your `callback` when the buffer's path, and therefore title, has changed. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangePath: (callback) -> @emitter.on 'did-change-path', callback # Extended: Calls your `callback` when soft wrap was enabled or disabled. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeSoftWrapped: (callback) -> @displayBuffer.onDidChangeSoftWrapped(callback) @@ -198,6 +204,8 @@ class Editor extends Model # been changed. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeGrammar: (callback) -> @emitter.on 'did-change-grammar', callback @@ -206,12 +214,16 @@ class Editor extends Model # to handle changes to the buffer without compromising typing performance. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidStopChanging: (callback) -> @getBuffer().onDidStopChanging(callback) # Extended: Calls your `callback` when the result of {::isModified} changes. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeModified: (callback) -> @getBuffer().onDidChangeModified(callback) @@ -219,6 +231,8 @@ class Editor extends Model # disk at a moment when the result of {::isModified} is true. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidConflict: (callback) -> @getBuffer().onDidConflict(callback) @@ -228,6 +242,8 @@ class Editor extends Model # * `event` event {Object} # * `text` {String} text to be inserted # * `cancel` {Function} Call to prevent the text from being inserted + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onWillInsertText: (callback) -> @emitter.on 'will-insert-text', callback @@ -236,6 +252,8 @@ class Editor extends Model # * `callback` {Function} # * `event` event {Object} # * `text` {String} text to be inserted + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidInsertText: (callback) -> @emitter.on 'did-insert-text', callback @@ -244,6 +262,8 @@ class Editor extends Model # # * `callback` {Function} # * `selection` {Selection} that was added + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observeCursors: (callback) -> callback(cursor) for cursor in @getCursors() @onDidAddCursor(callback) @@ -252,6 +272,8 @@ class Editor extends Model # # * `callback` {Function} # * `cursor` {Cursor} that was added + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddCursor: (callback) -> @emitter.on 'did-add-cursor', callback @@ -259,6 +281,8 @@ class Editor extends Model # # * `callback` {Function} # * `cursor` {Cursor} that was removed + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidRemoveCursor: (callback) -> @emitter.on 'did-remove-cursor', callback @@ -272,6 +296,8 @@ class Editor extends Model # * `newBufferPosition` {Point} # * `newScreenPosition` {Point} # * `textChanged` {Boolean} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeCursorPosition: (callback) -> @emitter.on 'did-change-cursor-position', callback @@ -280,6 +306,8 @@ class Editor extends Model # # * `callback` {Function} # * `selection` {Selection} that was added + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observeSelections: (callback) -> callback(selection) for selection in @getSelections() @onDidAddSelection(callback) @@ -288,6 +316,8 @@ class Editor extends Model # # * `callback` {Function} # * `selection` {Selection} that was added + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddSelection: (callback) -> @emitter.on 'did-add-selection', callback @@ -295,6 +325,8 @@ class Editor extends Model # # * `callback` {Function} # * `selection` {Selection} that was removed + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidRemoveSelection: (callback) -> @emitter.on 'did-remove-selection', callback @@ -302,6 +334,8 @@ class Editor extends Model # # * `callback` {Function} # * `selection` {Selection} that moved + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeSelectionRange: (callback) -> @emitter.on 'did-change-selection-range', callback @@ -310,6 +344,8 @@ class Editor extends Model # # * `callback` {Function} # * `decoration` {Decoration} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observeDecorations: (callback) -> @displayBuffer.observeDecorations(callback) @@ -317,6 +353,8 @@ class Editor extends Model # # * `callback` {Function} # * `decoration` {Decoration} that was added + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddDecoration: (callback) -> @displayBuffer.onDidAddDecoration(callback) @@ -324,6 +362,8 @@ class Editor extends Model # # * `callback` {Function} # * `decoration` {Decoration} that was removed + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidRemoveDecoration: (callback) -> @displayBuffer.onDidRemoveDecoration(callback) diff --git a/src/git.coffee b/src/git.coffee index 8b9507e43..78916d343 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -113,6 +113,8 @@ class Git # * `path` {String} the old parameters the decoration used to have # * `pathStatus` {Number} representing the status. This value can be passed to # {::isStatusModified} or {::isStatusNew} to get more information. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeStatus: (callback) -> @emitter.on 'did-change-status', callback @@ -122,6 +124,8 @@ class Git # {::getPathStatus(path)} to get the status for your path of choice. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeStatuses: (callback) -> @emitter.on 'did-change-statuses', callback diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 4151869ec..f95073e10 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -51,12 +51,16 @@ class PackageManager # Essential: Invoke the given callback when all packages have been activated. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidLoadAll: (callback) -> @emitter.on 'did-load-all', callback # Essential: Invoke the given callback when all packages have been activated. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidActivateAll: (callback) -> @emitter.on 'did-activate-all', callback diff --git a/src/package.coffee b/src/package.coffee index e21182f0b..6a104eccb 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -56,6 +56,8 @@ class Package # Essential: Invoke the given callback when all packages have been activated. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidDeactivate: (callback) -> @emitter.on 'did-deactivate', callback diff --git a/src/selection.coffee b/src/selection.coffee index 47f87b31c..c381d4994 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -38,12 +38,16 @@ class Selection extends Model # # * `callback` {Function} # * `screenRange` {Range} indicating the new screenrange + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeRange: (callback) -> @emitter.on 'did-change-range', callback # Extended: Calls your `callback` when the selection was destroyed # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidDestroy: (callback) -> @emitter.on 'did-destroy', callback diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 562bcdd5a..ae528607d 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -36,6 +36,8 @@ class ThemeManager # # * `callback` {Function} # * `stylesheet` {StyleSheet} the style node + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddStylesheet: (callback) -> @emitter.on 'did-add-stylesheet', callback @@ -43,12 +45,16 @@ class ThemeManager # # * `callback` {Function} # * `stylesheet` {StyleSheet} the style node + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidRemoveStylesheet: (callback) -> @emitter.on 'did-remove-stylesheet', callback # Essential: Invoke `callback` when any stylesheet has been updated, added, or removed. # # * `callback` {Function} + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeStylesheets: (callback) -> @emitter.on 'did-change-stylesheets', callback From 6e3c945fa29aacb549fd99b1cf071f7bc15c9b48 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 17:26:08 -0700 Subject: [PATCH 265/355] Use event methods for theme subscriptions --- spec/atom-spec.coffee | 2 +- src/atom.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 54a94c9a8..d1c7ef6df 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -520,7 +520,7 @@ describe "the `atom` global", -> reloadedHandler = jasmine.createSpy('reloadedHandler') reloadedHandler.reset() - atom.themes.on('reloaded', reloadedHandler) + atom.themes.onDidReloadAll reloadedHandler pack = atom.packages.disablePackage(packageName) diff --git a/src/atom.coffee b/src/atom.coffee index dd87eb6a4..9d0faab5d 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -373,7 +373,7 @@ class Atom extends Model @themes.load() watchThemes: -> - @themes.on 'reloaded', => + @themes.onDidReloadAll => # Only reload stylesheets from non-theme packages for pack in @packages.getActivePackages() when pack.getType() isnt 'theme' pack.reloadStylesheets?() From 7625e5352d0d469c6851732511687bf2a56998b9 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 17:28:26 -0700 Subject: [PATCH 266/355] Use event methods in EditorComponent --- src/editor-component.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index d70cf9a14..d1ee08c9a 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -176,7 +176,8 @@ EditorComponent = React.createClass @listenForDOMEvents() @listenForCommands() - @subscribe atom.themes, 'stylesheet-added stylesheet-removed stylesheet-updated', @onStylesheetsChanged + @subscribe atom.themes.onDidAddStylesheet @onStylesheetsChanged + @subscribe atom.themes.onDidRemoveStylesheet @onStylesheetsChanged @subscribe scrollbarStyle.changes, @refreshScrollbars @domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval) From 70e1d14f9664474987e06b41acf08300f06296ea Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 17:28:47 -0700 Subject: [PATCH 267/355] Add KeymapManager::onDidLoadBundledKeymaps --- src/context-menu-manager.coffee | 2 +- src/keymap-extensions.coffee | 6 +++++- src/menu-manager.coffee | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/context-menu-manager.coffee b/src/context-menu-manager.coffee index 91cfe04db..5aa8392a6 100644 --- a/src/context-menu-manager.coffee +++ b/src/context-menu-manager.coffee @@ -24,7 +24,7 @@ class ContextMenuManager @commandOptions = x: e.pageX, y: e.pageY ] - atom.keymaps.on 'bundled-keymaps-loaded', => @loadPlatformItems() + atom.keymaps.onDidLoadBundledKeymaps => @loadPlatformItems() loadPlatformItems: -> menusDirPath = path.join(@resourcePath, 'menus') diff --git a/src/keymap-extensions.coffee b/src/keymap-extensions.coffee index a4153de92..754bd502a 100644 --- a/src/keymap-extensions.coffee +++ b/src/keymap-extensions.coffee @@ -4,9 +4,13 @@ KeymapManager = require 'atom-keymap' CSON = require 'season' {jQuery} = require 'space-pen' +KeymapManager::onDidLoadBundledKeymaps = (callback) -> + @emitter.on 'did-load-bundled-keymaps', callback + KeymapManager::loadBundledKeymaps = -> @loadKeymap(path.join(@resourcePath, 'keymaps')) - @emit('bundled-keymaps-loaded') + @emit 'bundled-keymaps-loaded' + @emitter.emit 'did-load-bundled-keymaps' KeymapManager::getUserKeymapPath = -> if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap')) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index 5c7d955d0..da5ae6507 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -14,7 +14,7 @@ class MenuManager constructor: ({@resourcePath}) -> @pendingUpdateOperation = null @template = [] - atom.keymaps.on 'bundled-keymaps-loaded', => @loadPlatformItems() + atom.keymaps.onDidLoadBundledKeymaps => @loadPlatformItems() atom.packages.onDidActivateAll => @sortPackagesMenu() # Public: Adds the given items to the application menu. From c1f8065caf50746b05460325754107e391ac7077 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 17:41:38 -0700 Subject: [PATCH 268/355] Use the new split*() methods on Pane model in WorkspaceView specs --- spec/workspace-view-spec.coffee | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/spec/workspace-view-spec.coffee b/spec/workspace-view-spec.coffee index c6aa502b3..8adbc69e5 100644 --- a/spec/workspace-view-spec.coffee +++ b/spec/workspace-view-spec.coffee @@ -42,7 +42,7 @@ describe "WorkspaceView", -> runs -> editorView1 = atom.workspaceView.getActiveView() buffer = editorView1.getEditor().getBuffer() - editorView1.splitRight() + editorView1.getPaneView().getModel().splitRight(copyActiveItem: true) expect(atom.workspaceView.getActivePaneView()).toBe atom.workspaceView.getPaneViews()[1] simulateReload() @@ -196,7 +196,8 @@ describe "WorkspaceView", -> atom.workspaceView.attachToDom() rightEditorView = atom.workspaceView.getActiveView() rightEditorView.getEditor().setText("\t \n") - leftEditorView = rightEditorView.splitLeft() + rightEditorView.getPaneView().getModel().splitLeft(copyActiveItem: true) + leftEditorView = atom.workspaceView.getActiveView() expect(rightEditorView.find(".line:first").text()).toBe " " expect(leftEditorView.find(".line:first").text()).toBe " " @@ -207,14 +208,16 @@ describe "WorkspaceView", -> expect(rightEditorView.find(".line:first").text()).toBe withInvisiblesShowing expect(leftEditorView.find(".line:first").text()).toBe withInvisiblesShowing - lowerLeftEditorView = leftEditorView.splitDown() + leftEditorView.getPaneView().getModel().splitDown(copyActiveItem: true) + lowerLeftEditorView = atom.workspaceView.getActiveView() expect(lowerLeftEditorView.find(".line:first").text()).toBe withInvisiblesShowing atom.workspaceView.trigger "window:toggle-invisibles" expect(rightEditorView.find(".line:first").text()).toBe " " expect(leftEditorView.find(".line:first").text()).toBe " " - lowerRightEditorView = rightEditorView.splitDown() + rightEditorView.getPaneView().getModel().splitDown(copyActiveItem: true) + lowerRightEditorView = atom.workspaceView.getActiveView() expect(lowerRightEditorView.find(".line:first").text()).toBe " " describe ".eachEditorView(callback)", -> @@ -241,7 +244,7 @@ describe "WorkspaceView", -> atom.workspaceView.eachEditorView(callback) count = 0 callbackEditor = null - atom.workspaceView.getActiveView().splitRight() + atom.workspaceView.getActiveView().getPaneView().getModel().splitRight(copyActiveItem: true) expect(count).toBe 1 expect(callbackEditor).toBe atom.workspaceView.getActiveView() @@ -259,10 +262,10 @@ describe "WorkspaceView", -> subscription = atom.workspaceView.eachEditorView(callback) expect(count).toBe 1 - atom.workspaceView.getActiveView().splitRight() + atom.workspaceView.getActiveView().getPaneView().getModel().splitRight(copyActiveItem: true) expect(count).toBe 2 subscription.off() - atom.workspaceView.getActiveView().splitRight() + atom.workspaceView.getActiveView().getPaneView().getModel().splitRight(copyActiveItem: true) expect(count).toBe 2 describe "core:close", -> @@ -271,7 +274,7 @@ describe "WorkspaceView", -> paneView1 = atom.workspaceView.getActivePaneView() editorView = atom.workspaceView.getActiveView() - editorView.splitRight() + editorView.getPaneView().getModel().splitRight(copyActiveItem: true) paneView2 = atom.workspaceView.getActivePaneView() expect(paneView1).not.toBe paneView2 From 667315aff5db3aed9191806cfde523d3d554bb85 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 18:01:27 -0700 Subject: [PATCH 269/355] Add ThemeManager::onDidUpdateStylesheet --- src/editor-component.coffee | 1 + src/theme-manager.coffee | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index d1ee08c9a..b5216b2bd 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -177,6 +177,7 @@ EditorComponent = React.createClass @listenForCommands() @subscribe atom.themes.onDidAddStylesheet @onStylesheetsChanged + @subscribe atom.themes.onDidUpdateStylesheet @onStylesheetsChanged @subscribe atom.themes.onDidRemoveStylesheet @onStylesheetsChanged @subscribe scrollbarStyle.changes, @refreshScrollbars diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index ae528607d..139103346 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -50,6 +50,15 @@ class ThemeManager onDidRemoveStylesheet: (callback) -> @emitter.on 'did-remove-stylesheet', callback + # Essential: Invoke `callback` when a stylesheet has been updated. + # + # * `callback` {Function} + # * `stylesheet` {StyleSheet} the style node + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidUpdateStylesheet: (callback) -> + @emitter.on 'did-update-stylesheet', callback + # Essential: Invoke `callback` when any stylesheet has been updated, added, or removed. # # * `callback` {Function} @@ -66,6 +75,8 @@ class ThemeManager deprecate 'Use ThemeManager::onDidAddStylesheet instead' when 'stylesheet-removed' deprecate 'Use ThemeManager::onDidRemoveStylesheet instead' + when 'stylesheet-updated' + deprecate 'Use ThemeManager::onDidUpdateStylesheet instead' when 'stylesheets-changed' deprecate 'Use ThemeManager::onDidChangeStylesheets instead' else From 025c6111b315f19d0f1396abbdf576451b43a7ea Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 10 Sep 2014 18:01:45 -0700 Subject: [PATCH 270/355] Move global editor stylesheet updating into the ThemeManager --- src/theme-manager.coffee | 16 +++++++++++++++- src/workspace-view.coffee | 17 +++-------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 139103346..42ad5ac02 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -84,7 +84,7 @@ class ThemeManager EmitterMixin::on.apply(this, arguments) ### - Section: Methods + Section: Instance Methods ### getAvailableNames: -> @@ -334,3 +334,17 @@ class ThemeManager @emitter.emit 'did-add-stylesheet', styleElement.sheet @emit 'stylesheets-changed' @emitter.emit 'did-change-stylesheets' + + updateGlobalEditorStyle: (property, value) -> + unless styleNode = @stylesheetElementForId('global-editor-styles') + @applyStylesheet('global-editor-styles', '.editor {}') + styleNode = @stylesheetElementForId('global-editor-styles') + + {sheet} = styleNode + editorRule = sheet.cssRules[0] + editorRule.style[property] = value + + @emit 'stylesheet-updated', sheet + @emitter.emit 'did-update-stylesheet', sheet + @emit 'stylesheets-changed' + @emitter.emit 'did-change-stylesheets' diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 067600eb0..0398b42b4 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -373,24 +373,13 @@ class WorkspaceView extends View @model.destroy() setEditorFontSize: (fontSize) => - @setEditorStyle('font-size', fontSize + 'px') + atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px') setEditorFontFamily: (fontFamily) => - @setEditorStyle('font-family', fontFamily) + atom.themes.updateGlobalEditorStyle('font-family', fontFamily) setEditorLineHeight: (lineHeight) => - @setEditorStyle('line-height', lineHeight) - - setEditorStyle: (property, value) -> - unless styleNode = atom.themes.stylesheetElementForId('global-editor-styles') - atom.themes.applyStylesheet('global-editor-styles', '.editor {}') - styleNode = atom.themes.stylesheetElementForId('global-editor-styles') - - {sheet} = styleNode - editorRule = sheet.cssRules[0] - editorRule.style[property] = value - atom.themes.emit 'stylesheet-updated', sheet - atom.themes.emit 'stylesheets-changed' + atom.themes.updateGlobalEditorStyle('line-height', lineHeight) # Deprecated eachPane: (callback) -> From 40570c0b996cb479e9f0d0878f0fcfe9118f4929 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Thu, 11 Sep 2014 11:14:41 -0400 Subject: [PATCH 271/355] Force visibility-change checking in EditorView. When an `EditorView` becomes attached, if hardware acceleration is enabled, the call to `pollDOM` is a no-op because there's already a refresh pending. This can cause problems, because then the initial measurements don't happen and (for example) the lineHeight is left as null - it'll be set on the next rendering, but not before subscribers to `workspaceView.eachEditorView` are notified. --- src/editor-view.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index a1ec8a8b6..47c6ced78 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -144,6 +144,11 @@ class EditorView extends View return if @attached @attached = true @component.pollDOM() + + # Ensure that editor measurements like lineHeight are taken here, even if pollDOM() was a no-op + # because an update was requested. + @component.checkForVisibilityChange() + @focus() if @focusOnAttach @addGrammarScopeAttribute() From 36aa3834d396400a6452b50f47f4f40e242dece5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 11 Sep 2014 10:38:36 -0600 Subject: [PATCH 272/355] Only call ::checkForVisibilityChange on editor attachment, not ::pollDOM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I’m pretty sure ::pollDOM is subsumed by ::checkForVisibilityChange because there’s no reason the editor would be considered visible prior to being attached. --- src/editor-view.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 47c6ced78..dc0e42364 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -143,10 +143,6 @@ class EditorView extends View return unless onDom return if @attached @attached = true - @component.pollDOM() - - # Ensure that editor measurements like lineHeight are taken here, even if pollDOM() was a no-op - # because an update was requested. @component.checkForVisibilityChange() @focus() if @focusOnAttach From 435e0814024e6074c5e078ea0a65161d6376b23f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 11 Sep 2014 11:20:15 -0600 Subject: [PATCH 273/355] Upgrade autosave to autosave all items on window blur --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec30ddedb..d4a88c46f 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "archive-view": "0.36.0", "autocomplete": "0.32.0", "autoflow": "0.18.0", - "autosave": "0.15.0", + "autosave": "0.16.0", "background-tips": "0.16.0", "bookmarks": "0.28.0", "bracket-matcher": "0.55.0", From f39114a95cac785de87d9233e763ff656fe4ae67 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 10:48:03 -0700 Subject: [PATCH 274/355] Subscribe to items via event methods. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add deprecation warnings when they don’t return a disposable --- spec/pane-view-spec.coffee | 33 +++++++++++++++++++++++++++++++++ src/pane-view.coffee | 27 ++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee index 63c812621..8fd9838cc 100644 --- a/spec/pane-view-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -1,6 +1,7 @@ PaneContainerView = require '../src/pane-container-view' PaneView = require '../src/pane-view' fs = require 'fs-plus' +{Emitter} = require 'event-kit' {$, View} = require 'atom' path = require 'path' temp = require 'temp' @@ -162,6 +163,38 @@ describe "PaneView", -> view2.trigger 'title-changed' expect(activeItemTitleChangedHandler).toHaveBeenCalled() + describe 'when there is a onDidChangeTitle method', -> + beforeEach -> + TestView::changeTitle = -> + @emitter.emit 'did-change-title', 'title' + TestView::onDidChangeTitle = (callback) -> + @emitter.on 'did-change-title', callback + + view1.emitter = new Emitter + view2.emitter = new Emitter + + view1.id = 1 + view2.id = 2 + + pane.activateItem(view2) + pane.activateItem(view1) + + fffit "emits pane:active-item-title-changed", -> + activeItemTitleChangedHandler = jasmine.createSpy("activeItemTitleChangedHandler") + pane.on 'pane:active-item-title-changed', activeItemTitleChangedHandler + + expect(pane.getActiveItem()).toBe view1 + view2.changeTitle() + expect(activeItemTitleChangedHandler).not.toHaveBeenCalled() + + view1.changeTitle() + expect(activeItemTitleChangedHandler).toHaveBeenCalled() + activeItemTitleChangedHandler.reset() + + pane.activateItem(view2) + view2.changeTitle() + expect(activeItemTitleChangedHandler).toHaveBeenCalled() + describe "when an unmodifed buffer's path is deleted", -> it "removes the pane item", -> editor = null diff --git a/src/pane-view.coffee b/src/pane-view.coffee index 0de2ca7f1..41224e2d3 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -147,6 +147,9 @@ class PaneView extends View @activeItem onActiveItemChanged: (item) => + @activeItemDisposables.dispose() if @activeItemDisposables? + @activeItemDisposables = new CompositeDisposable() + if @previousActiveItem?.off? @previousActiveItem.off 'title-changed', @activeItemTitleChanged @previousActiveItem.off 'modified-status-changed', @activeItemModifiedChanged @@ -154,15 +157,29 @@ class PaneView extends View return unless item? - hasFocus = @hasFocus() - if item.on? - item.on 'title-changed', @activeItemTitleChanged - item.on 'modified-status-changed', @activeItemModifiedChanged + if item.onDidChangeTitle? + disposable = item.onDidChangeTitle(@activeItemTitleChanged) + deprecate 'Please return a Disposable object from your ::onDidChangeTitle method!' unless disposable?.dispose? + @activeItemDisposables.add(disposable) if disposable?.dispose? + else if item.on? + disposable = item.on('title-changed', @activeItemTitleChanged) + deprecate 'Please return a Disposable object from your ::on method. Your ::off method will not be called soon!' unless disposable?.dispose? + @activeItemDisposables.add(disposable) if disposable?.dispose? + + if item.onDidChangeModified? + disposable = item.onDidChangeModified(@activeItemModifiedChanged) + deprecate 'Please return a Disposable object from your ::onDidChangeModified method!' unless disposable?.dispose? + @activeItemDisposables.add(disposable) if disposable?.dispose? + else if item.on? + item.on('modified-status-changed', @activeItemModifiedChanged) + deprecate 'Please return a Disposable object from your ::on method. Your ::off method will not be called soon!' unless disposable?.dispose? + @activeItemDisposables.add(disposable) if disposable?.dispose? + view = @viewForItem(item) otherView.hide() for otherView in @itemViews.children().not(view).views() @itemViews.append(view) unless view.parent().is(@itemViews) view.show() if @attached - view.focus() if hasFocus + view.focus() if @hasFocus() @trigger 'pane:active-item-changed', [item] From 04caea9bb0a1cb3c78950d41dcbeae74ce341e1a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 11 Sep 2014 11:56:36 -0600 Subject: [PATCH 275/355] Upgrade autosave to suppress autosave when opening menus inside editor --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d4a88c46f..93931377e 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "archive-view": "0.36.0", "autocomplete": "0.32.0", "autoflow": "0.18.0", - "autosave": "0.16.0", + "autosave": "0.17.0", "background-tips": "0.16.0", "bookmarks": "0.28.0", "bracket-matcher": "0.55.0", From f38fb2a9247e3bee0d03d97d8119711965bba2a4 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 11:11:15 -0700 Subject: [PATCH 276/355] nof --- spec/pane-view-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee index 8fd9838cc..01f690bfd 100644 --- a/spec/pane-view-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -179,7 +179,7 @@ describe "PaneView", -> pane.activateItem(view2) pane.activateItem(view1) - fffit "emits pane:active-item-title-changed", -> + it "emits pane:active-item-title-changed", -> activeItemTitleChangedHandler = jasmine.createSpy("activeItemTitleChangedHandler") pane.on 'pane:active-item-title-changed', activeItemTitleChangedHandler From 04c08248225bf90c0b7c81219f7119ce2fe443af Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 11:28:21 -0700 Subject: [PATCH 277/355] Fix / clean up specs --- spec/pane-view-spec.coffee | 54 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee index 01f690bfd..56cb6ddc8 100644 --- a/spec/pane-view-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -13,9 +13,14 @@ describe "PaneView", -> @deserialize: ({id, text}) -> new TestView({id, text}) @content: ({id, text}) -> @div class: 'test-view', id: id, tabindex: -1, text initialize: ({@id, @text}) -> + @emitter = new Emitter serialize: -> { deserializer: 'TestView', @id, @text } getUri: -> @id isEqual: (other) -> other? and @id == other.id and @text == other.text + changeTitle: -> + @emitter.emit 'did-change-title', 'title' + onDidChangeTitle: (callback) -> + @emitter.on 'did-change-title', callback beforeEach -> atom.deserializers.add(TestView) @@ -146,39 +151,32 @@ describe "PaneView", -> expect(view1.data('preservative')).toBe 1234 describe "when the title of the active item changes", -> - it "emits pane:active-item-title-changed", -> - activeItemTitleChangedHandler = jasmine.createSpy("activeItemTitleChangedHandler") - pane.on 'pane:active-item-title-changed', activeItemTitleChangedHandler - - expect(pane.getActiveItem()).toBe view1 - - view2.trigger 'title-changed' - expect(activeItemTitleChangedHandler).not.toHaveBeenCalled() - - view1.trigger 'title-changed' - expect(activeItemTitleChangedHandler).toHaveBeenCalled() - activeItemTitleChangedHandler.reset() - - pane.activateItem(view2) - view2.trigger 'title-changed' - expect(activeItemTitleChangedHandler).toHaveBeenCalled() - - describe 'when there is a onDidChangeTitle method', -> + describe 'when there is no onDidChangeTitle method', -> beforeEach -> - TestView::changeTitle = -> - @emitter.emit 'did-change-title', 'title' - TestView::onDidChangeTitle = (callback) -> - @emitter.on 'did-change-title', callback - - view1.emitter = new Emitter - view2.emitter = new Emitter - - view1.id = 1 - view2.id = 2 + view1.onDidChangeTitle = null + view2.onDidChangeTitle = null pane.activateItem(view2) pane.activateItem(view1) + it "emits pane:active-item-title-changed", -> + activeItemTitleChangedHandler = jasmine.createSpy("activeItemTitleChangedHandler") + pane.on 'pane:active-item-title-changed', activeItemTitleChangedHandler + + expect(pane.getActiveItem()).toBe view1 + + view2.trigger 'title-changed' + expect(activeItemTitleChangedHandler).not.toHaveBeenCalled() + + view1.trigger 'title-changed' + expect(activeItemTitleChangedHandler).toHaveBeenCalled() + activeItemTitleChangedHandler.reset() + + pane.activateItem(view2) + view2.trigger 'title-changed' + expect(activeItemTitleChangedHandler).toHaveBeenCalled() + + describe 'when there is a onDidChangeTitle method', -> it "emits pane:active-item-title-changed", -> activeItemTitleChangedHandler = jasmine.createSpy("activeItemTitleChangedHandler") pane.on 'pane:active-item-title-changed', activeItemTitleChangedHandler From ff308d366cf5120c8ce5d2c9fa65580d5721cad0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 13:27:17 -0700 Subject: [PATCH 278/355] Upgrade to language-ruby@0.36 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93931377e..097809a60 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "language-php": "0.15.0", "language-property-list": "0.7.0", "language-python": "0.19.0", - "language-ruby": "0.35.0", + "language-ruby": "0.36.0", "language-ruby-on-rails": "0.18.0", "language-sass": "0.21.0", "language-shellscript": "0.8.0", From 3f3284a8dbf6940bd755948681244658477e76ca Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 13:33:50 -0700 Subject: [PATCH 279/355] Move the deprecations --- src/pane-view.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pane-view.coffee b/src/pane-view.coffee index 41224e2d3..21f4c8cfa 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -162,8 +162,8 @@ class PaneView extends View deprecate 'Please return a Disposable object from your ::onDidChangeTitle method!' unless disposable?.dispose? @activeItemDisposables.add(disposable) if disposable?.dispose? else if item.on? + deprecate '::on methods for items are no longer supported. If you would like your item to title change behavior, please implement a ::onDidChangeTitle() method.' disposable = item.on('title-changed', @activeItemTitleChanged) - deprecate 'Please return a Disposable object from your ::on method. Your ::off method will not be called soon!' unless disposable?.dispose? @activeItemDisposables.add(disposable) if disposable?.dispose? if item.onDidChangeModified? @@ -171,8 +171,8 @@ class PaneView extends View deprecate 'Please return a Disposable object from your ::onDidChangeModified method!' unless disposable?.dispose? @activeItemDisposables.add(disposable) if disposable?.dispose? else if item.on? + deprecate '::on methods for items are no longer supported. If you would like your item to support modified behavior, please implement a ::onDidChangeModified() method.' item.on('modified-status-changed', @activeItemModifiedChanged) - deprecate 'Please return a Disposable object from your ::on method. Your ::off method will not be called soon!' unless disposable?.dispose? @activeItemDisposables.add(disposable) if disposable?.dispose? view = @viewForItem(item) From f8ba40bcfe864d2a245734ae4552a08f6d062906 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 14:00:34 -0700 Subject: [PATCH 280/355] Deprecate font-size, font-family, line-height methods on EditorView. --- src/editor-view.coffee | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index dc0e42364..aeea1feda 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -282,41 +282,29 @@ class EditorView extends View deprecate 'Use Editor::getLastVisibleScreenRow instead. You can get the editor via editorView.getModel()' @editor.getLastVisibleScreenRow() - # Public: Gets the font family for the editor. - # - # Returns a {String} identifying the CSS `font-family`. getFontFamily: -> + deprecate 'This is going away. Use atom.config.get("editor.fontFamily") instead' @component?.getFontFamily() - # Public: Sets the font family for the editor. - # - # * `fontFamily` A {String} identifying the CSS `font-family`. setFontFamily: (fontFamily) -> + deprecate 'This is going away. Use atom.config.set("editor.fontFamily", "my-font") instead' @component?.setFontFamily(fontFamily) - # Public: Retrieves the font size for the editor. - # - # Returns a {Number} indicating the font size in pixels. getFontSize: -> + deprecate 'This is going away. Use atom.config.get("editor.fontSize") instead' @component?.getFontSize() - # Public: Sets the font size for the editor. - # - # * `fontSize` A {Number} indicating the font size in pixels. setFontSize: (fontSize) -> + deprecate 'This is going away. Use atom.config.set("editor.fontSize", 12) instead' @component?.setFontSize(fontSize) + setLineHeight: (lineHeight) -> + deprecate 'This is going away. Use atom.config.set("editor.lineHeight", 1.5) instead' + @component.setLineHeight(lineHeight) + setWidthInChars: (widthInChars) -> @component.getDOMNode().style.width = (@editor.getDefaultCharWidth() * widthInChars) + 'px' - # Public: Sets the line height of the editor. - # - # Calling this method has no effect when called on a mini editor. - # - # * `lineHeight` A {Number} without a unit suffix identifying the CSS `line-height`. - setLineHeight: (lineHeight) -> - @component.setLineHeight(lineHeight) - # Public: Sets whether you want to show the indentation guides. # # * `showIndentGuide` A {Boolean} you can set to `true` if you want to see the From 5ef31e00a20c838143cd28cf0719e4abf04b0c09 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 14:10:17 -0700 Subject: [PATCH 281/355] Deprecate EditorView::setShowIndentGuide --- src/editor-view.coffee | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index aeea1feda..9c299a1cc 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -305,11 +305,8 @@ class EditorView extends View setWidthInChars: (widthInChars) -> @component.getDOMNode().style.width = (@editor.getDefaultCharWidth() * widthInChars) + 'px' - # Public: Sets whether you want to show the indentation guides. - # - # * `showIndentGuide` A {Boolean} you can set to `true` if you want to see the - # indentation guides. setShowIndentGuide: (showIndentGuide) -> + deprecate 'This is going away. Use atom.config.set("editor.showIndentGuide", true|false) instead' @component.setShowIndentGuide(showIndentGuide) setSoftWrap: (softWrapped) -> From 6a2c161bf21e156dbdf1b382b00c7a81a7ac76c4 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 14:10:33 -0700 Subject: [PATCH 282/355] Deprecate setShowInvisibles --- src/editor-view.coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 9c299a1cc..7617567f6 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -313,10 +313,8 @@ class EditorView extends View deprecate 'Use Editor::setSoftWrapped instead. You can get the editor via editorView.getModel()' @editor.setSoftWrapped(softWrapped) - # Public: Set whether invisible characters are shown. - # - # * `showInvisibles` A {Boolean} which, if `true`, show invisible characters. setShowInvisibles: (showInvisibles) -> + deprecate 'This is going away. Use atom.config.set("editor.showInvisibles", true|false) instead' @component.setShowInvisibles(showInvisibles) getText: -> From aee496346b2d1b78aada1bf607daa6525ea2e9e0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 14:10:44 -0700 Subject: [PATCH 283/355] Prepare 0.128 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 097809a60..e3114f48d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.127.0", + "version": "0.128.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 54ef5acdc6f8c4bb240b05b7f2c0706de194d791 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 14:58:55 -0700 Subject: [PATCH 284/355] Upgrade first-mate with new docs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3114f48d..ea41c4390 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "delegato": "^1", "emissary": "^1.3.1", "event-kit": "0.7.1", - "first-mate": "^2.1.0", + "first-mate": "^2.1.1", "fs-plus": "^2.2.6", "fstream": "0.1.24", "fuzzaldrin": "^2.1", From 7b1a38bf8b8baef2f945311eab5fad5c63a03f2b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 15:31:39 -0700 Subject: [PATCH 285/355] Upgrade to wrap-guide@0.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea41c4390..1d3858e6c 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", - "wrap-guide": "0.21.0", + "wrap-guide": "0.22.0", "language-c": "0.28.0", "language-coffee-script": "0.30.0", "language-css": "0.17.0", From 844fd29dadb13900de64cfd88fdc35ab5995fda1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 15:10:18 -0700 Subject: [PATCH 286/355] Remove unused param --- src/theme-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index 42ad5ac02..ac76e8ea0 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -107,7 +107,7 @@ class ThemeManager getLoadedThemes: -> pack for pack in @packageManager.getLoadedPackages() when pack.isTheme() - activatePackages: (themePackages) -> @activateThemes() + activatePackages: -> @activateThemes() # Get the enabled theme names from the config. # From dc5eb95a39e1d78e22917d2d8bf2d75e81721858 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 15:19:49 -0700 Subject: [PATCH 287/355] Wait for initial stylesheet load to complete Instead of measuring on each stylesheet load at startup, wait for the initial load of all the stylesheets to complete and then do the necessary measurments. --- src/editor-component.coffee | 3 +++ src/theme-manager.coffee | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index b5216b2bd..723c8f498 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -179,6 +179,8 @@ EditorComponent = React.createClass @subscribe atom.themes.onDidAddStylesheet @onStylesheetsChanged @subscribe atom.themes.onDidUpdateStylesheet @onStylesheetsChanged @subscribe atom.themes.onDidRemoveStylesheet @onStylesheetsChanged + unless atom.themes.isInitialLoadComplete() + @subscribe atom.themes.onDidReloadAll @onStylesheetsChanged @subscribe scrollbarStyle.changes, @refreshScrollbars @domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval) @@ -708,6 +710,7 @@ EditorComponent = React.createClass onStylesheetsChanged: (stylesheet) -> return unless @performedInitialMeasurement + return unless atom.themes.isInitialLoadComplete() @refreshScrollbars() if @containsScrollbarSelector(stylesheet) @sampleFontStyling() diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index ac76e8ea0..23c630043 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -20,6 +20,7 @@ class ThemeManager constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode}) -> @emitter = new Emitter @lessCache = null + @initialLoadComplete = false @packageManager.registerPackageActivator(this, ['theme']) ### @@ -165,6 +166,7 @@ class ThemeManager @refreshLessCache() # Update cache again now that @getActiveThemes() is populated @loadUserStylesheet() @reloadBaseStylesheets() + @initialLoadComplete = true @emit 'reloaded' @emitter.emit 'did-reload-all' deferred.resolve() @@ -177,6 +179,8 @@ class ThemeManager @packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes() null + isInitialLoadComplete: -> @initialLoadComplete + addActiveThemeClasses: -> for pack in @getActiveThemes() atom.workspaceView?[0]?.classList.add("theme-#{pack.name}") From 4a1f048d52e3593e664807790350ecb8b01e2b34 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 15:44:30 -0700 Subject: [PATCH 288/355] Refresh scrollbars when no stylesheet is specified --- src/editor-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 723c8f498..47aa320b0 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -712,7 +712,7 @@ EditorComponent = React.createClass return unless @performedInitialMeasurement return unless atom.themes.isInitialLoadComplete() - @refreshScrollbars() if @containsScrollbarSelector(stylesheet) + @refreshScrollbars() if not stylesheet or @containsScrollbarSelector(stylesheet) @sampleFontStyling() @sampleBackgroundColors() @remeasureCharacterWidths() From e6252546c4aba6a08450fdc870f27d641693daf7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 15:49:44 -0700 Subject: [PATCH 289/355] Set initialLoadComplete to true in specs --- spec/spec-helper.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 4bad73ee7..530367518 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -21,6 +21,7 @@ clipboard = require 'clipboard' atom.themes.loadBaseStylesheets() atom.themes.requireStylesheet '../static/jasmine' +atom.themes.initialLoadComplete = true fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') atom.packages.packageDirPaths.unshift(fixturePackagesPath) From c161e93b9674dba476a5b5ed6927fdc1cc2381ae Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 16:08:04 -0700 Subject: [PATCH 290/355] :lipstick: Add ? --- src/editor-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 47aa320b0..e190776e7 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -712,7 +712,7 @@ EditorComponent = React.createClass return unless @performedInitialMeasurement return unless atom.themes.isInitialLoadComplete() - @refreshScrollbars() if not stylesheet or @containsScrollbarSelector(stylesheet) + @refreshScrollbars() if not stylesheet? or @containsScrollbarSelector(stylesheet) @sampleFontStyling() @sampleBackgroundColors() @remeasureCharacterWidths() From 24d1a45fd9d843936fb9f1a4782f271e0075ec39 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 16:29:34 -0700 Subject: [PATCH 291/355] Upgrade to pathwather with better doc organization --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d3858e6c..4acaa9b13 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "nslog": "^1.0.1", "oniguruma": "^3.0.4", "optimist": "0.4.0", - "pathwatcher": "^2.1.1", + "pathwatcher": "^2.1.2", "property-accessors": "^1", "q": "^1.0.1", "random-words": "0.0.1", From 137b926f54712e25f189ed275f18e5add3d339cc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 17:15:22 -0700 Subject: [PATCH 292/355] Upgrade to archive-view@0.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4acaa9b13..8b0bffb5f 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "base16-tomorrow-light-theme": "0.4.0", "solarized-dark-syntax": "0.22.0", "solarized-light-syntax": "0.12.0", - "archive-view": "0.36.0", + "archive-view": "0.37.0", "autocomplete": "0.32.0", "autoflow": "0.18.0", "autosave": "0.17.0", From 9a534f0b6dcd62a4b68ca1b62cd530cc32b2a631 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 17:35:07 -0700 Subject: [PATCH 293/355] Upgrade to tree-view@0.116 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b0bffb5f..1e7efb6e4 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.115.0", + "tree-view": "0.116.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 8847b35931b826ffb386e16854c3073964433bf8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 18:11:16 -0700 Subject: [PATCH 294/355] Upgrade to tree-view@0.117 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e7efb6e4..4ea35c0c0 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.116.0", + "tree-view": "0.117.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From d0033b2d4037a17f5581175b1d9a4250d26c2eb6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 18:23:12 -0700 Subject: [PATCH 295/355] Upgrade tello for bugfix --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index e77040261..422a48693 100644 --- a/build/package.json +++ b/build/package.json @@ -8,7 +8,7 @@ "dependencies": { "async": "~0.2.9", "donna": "1.0.1", - "tello": "1.0.2", + "tello": "1.0.3", "formidable": "~1.0.14", "fs-plus": "2.x", "github-releases": "~0.2.0", From 0643aa66c9ed7f0083084bfa43f5f99c751c545e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 11 Sep 2014 18:23:31 -0700 Subject: [PATCH 296/355] Upgrade atom-keymap for new docs organization --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4ea35c0c0..4079b1486 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "atomShellVersion": "0.16.2", "dependencies": { "async": "0.2.6", - "atom-keymap": "^2.1.0", + "atom-keymap": "^2.1.1", "bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372", "clear-cut": "0.4.0", "coffee-script": "1.7.0", From 8cffb8006a327f0242823d07841868b9915ffc87 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 11 Sep 2014 21:41:15 -0700 Subject: [PATCH 297/355] Upgrade to language-gfm@0.49 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4079b1486..a38a24d82 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "language-c": "0.28.0", "language-coffee-script": "0.30.0", "language-css": "0.17.0", - "language-gfm": "0.48.0", + "language-gfm": "0.49.0", "language-git": "0.9.0", "language-go": "0.17.0", "language-html": "0.26.0", From 901ba725578fb0fb30dcd0758084db8779e2f02e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 12 Sep 2014 21:43:01 +0800 Subject: [PATCH 298/355] Show the open dialog as child window on Windows and Linux. On Mac the open dialog is still showed as independent dialog, this matches most native apps' behavior. Fixes #3401. --- src/browser/atom-application.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 1011a660b..7460952a1 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -484,6 +484,14 @@ class AtomApplication when 'all' then ['openFile', 'openDirectory'] else throw new Error("#{type} is an invalid type for promptForPath") + # Show the open dialog as child window on Windows and Linux, and as + # independent dialog on OS X. This matches most native apps. + parentWindow = + if process.platform is 'darwin' + null + else + BrowserWindow.getFocusedWindow() + dialog = require 'dialog' - dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) => + dialog.showOpenDialog parentWindow, title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) => @openPaths({pathsToOpen, devMode, safeMode, window}) From 61e01c39848dc03f12a1e179832ba0d400e094c6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 09:11:42 -0700 Subject: [PATCH 299/355] Upgrade to language-ruby@0.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a38a24d82..c153de4cb 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "language-php": "0.15.0", "language-property-list": "0.7.0", "language-python": "0.19.0", - "language-ruby": "0.36.0", + "language-ruby": "0.37.0", "language-ruby-on-rails": "0.18.0", "language-sass": "0.21.0", "language-shellscript": "0.8.0", From ceb48b7f4fc0126cad881ace597d140c4d48189a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 09:51:01 -0700 Subject: [PATCH 300/355] Upgrade to tree-view@0.118 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c153de4cb..a8fcb0607 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.117.0", + "tree-view": "0.118.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From ee8b01e46a2b41de5d4e71d69920599da960b760 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 10:10:04 -0700 Subject: [PATCH 301/355] Upgrade to find-and-replace@0.135 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8fcb0607..b95694c34 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.134.0", + "find-and-replace": "0.135.0", "fuzzy-finder": "0.58.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From 050a79e5b9dba35f09146fd4013439e62f04e30c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 10:29:01 -0700 Subject: [PATCH 302/355] Upgrade to find-and-replace@0.136 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b95694c34..3357d9d95 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.135.0", + "find-and-replace": "0.136.0", "fuzzy-finder": "0.58.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From c24bf5bd0cbe5b73b1b660d8a90ae969b83936c4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 10:34:59 -0700 Subject: [PATCH 303/355] Upgrade to find-and-replace@0.137 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3357d9d95..d20b25bf9 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.136.0", + "find-and-replace": "0.137.0", "fuzzy-finder": "0.58.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From 591d9068d8b4bea2fafbaa8e914354904c92eeb3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 10:43:15 -0700 Subject: [PATCH 304/355] Upgrade to tree-view@0.119 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d20b25bf9..453ffea85 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.118.0", + "tree-view": "0.119.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 7c1cab77895850df7ca5e93423fc5288ad797235 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 12 Sep 2014 10:49:45 -0700 Subject: [PATCH 305/355] =?UTF-8?q?Don=E2=80=99t=20recurse=20into=20depend?= =?UTF-8?q?encies=20of=20dependencies.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We always want the top level module! --- build/tasks/docs-task.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tasks/docs-task.coffee b/build/tasks/docs-task.coffee index 605269933..75e21de8a 100644 --- a/build/tasks/docs-task.coffee +++ b/build/tasks/docs-task.coffee @@ -11,6 +11,7 @@ module.exports = (grunt) -> modulesPath = path.resolve(__dirname, '..', '..', 'node_modules') classes = {} fs.traverseTreeSync modulesPath, (modulePath) -> + return false if modulePath.match(/node_modules/g).length > 1 # dont need the dependencies of the dependencies return true unless path.basename(modulePath) is 'package.json' return true unless fs.isFileSync(modulePath) From 1c57a8b0cd1d4c90a30566d63cd8b117fb810a47 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Fri, 12 Sep 2014 11:19:37 -0700 Subject: [PATCH 306/355] Update event-kit with better organization in docs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 453ffea85..67e0a5e4f 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coffeestack": "0.7.0", "delegato": "^1", "emissary": "^1.3.1", - "event-kit": "0.7.1", + "event-kit": "0.7.2", "first-mate": "^2.1.1", "fs-plus": "^2.2.6", "fstream": "0.1.24", From a060eff478ffd8a0d0784501eecb33a49846089c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:22:55 -0700 Subject: [PATCH 307/355] Use skinny arrows --- src/workspace-view.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 0398b42b4..458d6d311 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -372,13 +372,13 @@ class WorkspaceView extends View beforeRemove: -> @model.destroy() - setEditorFontSize: (fontSize) => + setEditorFontSize: (fontSize) -> atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px') - setEditorFontFamily: (fontFamily) => + setEditorFontFamily: (fontFamily) -> atom.themes.updateGlobalEditorStyle('font-family', fontFamily) - setEditorLineHeight: (lineHeight) => + setEditorLineHeight: (lineHeight) -> atom.themes.updateGlobalEditorStyle('line-height', lineHeight) # Deprecated From f14ad9955837aea8b9cb87962e57559dab361bb5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Sep 2014 15:23:23 -0700 Subject: [PATCH 308/355] Remove linux check --- script/cibuild | 3 --- 1 file changed, 3 deletions(-) diff --git a/script/cibuild b/script/cibuild index 6e76d8831..6134f6a9b 100755 --- a/script/cibuild +++ b/script/cibuild @@ -5,9 +5,6 @@ var path = require('path'); process.chdir(path.dirname(__dirname)); -if (process.platform == 'linux') - throw new Error('cibuild can not run on linux yet!'); - var homeDir = process.platform == 'win32' ? process.env.USERPROFILE : process.env.HOME; function loadEnvironmentVariables(filePath) { From 04cc11fa8193d6c8e0897aebadb30fd7fb207984 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Sep 2014 15:23:52 -0700 Subject: [PATCH 309/355] Don't read env var files on Linux --- script/cibuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/cibuild b/script/cibuild index 6134f6a9b..863478ec1 100755 --- a/script/cibuild +++ b/script/cibuild @@ -24,7 +24,7 @@ function loadEnvironmentVariables(filePath) { function readEnvironmentVariables() { if (process.platform === 'win32') loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials')); - else { + else if (process.platform === 'darwin') { loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials'); loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain'); } From c72ce458202fb8f967353452c554db1bf25ea162 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Sep 2014 15:50:16 -0700 Subject: [PATCH 310/355] Log installed node version --- script/utils/verify-requirements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/utils/verify-requirements.js b/script/utils/verify-requirements.js index fa65a339e..554c27dd0 100644 --- a/script/utils/verify-requirements.js +++ b/script/utils/verify-requirements.js @@ -31,7 +31,7 @@ function verifyNode(cb) { var nodeMajorVersion = +versionArray[0]; var nodeMinorVersion = +versionArray[1]; if (nodeMajorVersion === 0 && nodeMinorVersion < 10) { - error = "node v0.10 is required to build Atom."; + error = "node v0.10 is required to build Atom, node " + nodeVersion + " is installed."; cb(error); } else { From 68e11fed111b2367d36da5dad47b840fa378d290 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 12:57:33 -0700 Subject: [PATCH 311/355] Add .node-version file with 0.10.21 --- .node-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 .node-version diff --git a/.node-version b/.node-version new file mode 100644 index 000000000..4e9918e86 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +v0.10.21 From e060d0b5620ebdf340b73502d3e64255c4959e30 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 13:25:28 -0700 Subject: [PATCH 312/355] Add initial Linux CI build script --- script/cibuild-atom-linux | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100755 script/cibuild-atom-linux diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux new file mode 100755 index 000000000..6d5277eac --- /dev/null +++ b/script/cibuild-atom-linux @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +if [ -d /usr/local/share/nodenv ]; then + export NODENV_ROOT=/usr/local/share/nodenv + export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH + export NODENV_VERSION="v0.10.21" +fi + +script/cibuild From 735d1a912e3f1b14f6e6277a534e4f5b0d528ce3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 4 Sep 2014 13:26:34 -0700 Subject: [PATCH 313/355] Log debug output --- script/cibuild-atom-linux | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index 6d5277eac..0bc37e2de 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -2,6 +2,8 @@ set -e +echo "HERE?" + if [ -d /usr/local/share/nodenv ]; then export NODENV_ROOT=/usr/local/share/nodenv export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH From a1e177c7dcb4432a178125f7e8b03bf977fc9a1b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:01:23 -0700 Subject: [PATCH 314/355] Set ATOM_ACCESS_TOKEN --- script/cibuild-atom-linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index 0bc37e2de..c4e957189 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -2,7 +2,7 @@ set -e -echo "HERE?" +export ATOM_ACCESS_TOKEN=$BUILD_ATOM_LINUX_ACCESS_TOKEN if [ -d /usr/local/share/nodenv ]; then export NODENV_ROOT=/usr/local/share/nodenv From 24206d45a7461ac68a884bb46a4fafe4a0a2ed4a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:04:37 -0700 Subject: [PATCH 315/355] Run mkdeb task on Linux CI --- build/Gruntfile.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index a014dc3c9..00fd904c7 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -230,6 +230,7 @@ module.exports = (grunt) -> ciTasks = ['output-disk-space', 'download-atom-shell', 'build'] ciTasks.push('dump-symbols') unless process.platform is 'win32' + ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build') grunt.registerTask('ci', ciTasks) From 9717d973a78b50724326bbc010f6720f842f3f90 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:12:10 -0700 Subject: [PATCH 316/355] Upload .deb asset during publish --- build/tasks/publish-build-task.coffee | 29 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 69ba1b20b..7e9803605 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -20,7 +20,7 @@ module.exports = (gruntObject) -> {cp} = require('./task-helpers')(grunt) grunt.registerTask 'publish-build', 'Publish the built app', -> - return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'master' + return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'ks-add-debian-asset' tasks = ['upload-assets'] tasks.unshift('build-docs', 'prepare-docs') if process.platform is 'darwin' grunt.task.run(tasks) @@ -45,16 +45,23 @@ module.exports = (gruntObject) -> uploadAssets(release, buildDir, assets, done) getAssets = -> - if process.platform is 'darwin' - [ - {assetName: 'atom-mac.zip', sourcePath: 'Atom.app'} - {assetName: 'atom-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'} - {assetName: 'atom-api.json', sourcePath: 'atom-api.json'} - ] - else - [ - {assetName: 'atom-windows.zip', sourcePath: 'Atom'} - ] + switch process.platform + when 'darwin' + [ + {assetName: 'atom-mac.zip', sourcePath: 'Atom.app'} + {assetName: 'atom-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'} + {assetName: 'atom-api.json', sourcePath: 'atom-api.json'} + ] + when 'win32' + [ + {assetName: 'atom-windows.zip', sourcePath: 'Atom'} + ] + when 'linux' + buildDir = grunt.config.get('atom.buildDir') + debAsset = fs.listSync(buildDir, '.deb')[0] + [ + {assetName: path.basename(debAsset), sourcePath: debAsset} + ] logError = (message, error, details) -> grunt.log.error(message) From dc0bdef36c117ed744b845dfba7f344ec5a85a0c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:14:08 -0700 Subject: [PATCH 317/355] Don't run specs on Linux CI for now --- build/Gruntfile.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 00fd904c7..c1ba7a2d7 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -227,11 +227,12 @@ module.exports = (grunt) -> grunt.registerTask('test', ['shell:kill-atom', 'run-specs']) grunt.registerTask('docs', ['markdown:guides', 'build-docs']) - ciTasks = ['output-disk-space', 'download-atom-shell', 'build'] - ciTasks.push('dump-symbols') unless process.platform is 'win32' + ciTasks.push('dump-symbols') if process.platform isnt 'win32' ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build') + ciTasks.push('test') if process.platform isnt 'linux' + ciTasks.push('codesign', 'publish-build') grunt.registerTask('ci', ciTasks) defaultTasks = ['download-atom-shell', 'build', 'set-version'] From 38eda4ca14a4dc44b703739253b3d4694bb213ef Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:24:44 -0700 Subject: [PATCH 318/355] Remove duplidate tasks in CI tasks array --- build/Gruntfile.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index c1ba7a2d7..7e70d9753 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -230,7 +230,7 @@ module.exports = (grunt) -> ciTasks = ['output-disk-space', 'download-atom-shell', 'build'] ciTasks.push('dump-symbols') if process.platform isnt 'win32' ciTasks.push('mkdeb') if process.platform is 'linux' - ciTasks.push('set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build') + ciTasks.push('set-version', 'check-licenses', 'lint') ciTasks.push('test') if process.platform isnt 'linux' ciTasks.push('codesign', 'publish-build') grunt.registerTask('ci', ciTasks) From e00ff30cd74f9d04d49512b39fe4b5963b139bcb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:40:33 -0700 Subject: [PATCH 319/355] Extensions should be an array --- build/tasks/publish-build-task.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 7e9803605..85a5ee3c6 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -58,7 +58,7 @@ getAssets = -> ] when 'linux' buildDir = grunt.config.get('atom.buildDir') - debAsset = fs.listSync(buildDir, '.deb')[0] + debAsset = fs.listSync(buildDir, ['.deb'])[0] [ {assetName: path.basename(debAsset), sourcePath: debAsset} ] From 3a2c155afc84d8bdcf2a90e2eede5908ef0ab7f1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 11:45:08 -0700 Subject: [PATCH 320/355] Log token --- script/cibuild-atom-linux | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index c4e957189..4d33f3d8d 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -2,6 +2,10 @@ set -e +echo "the" +echo $BUILD_ATOM_LINUX_ACCESS_TOKEN +echo "token" + export ATOM_ACCESS_TOKEN=$BUILD_ATOM_LINUX_ACCESS_TOKEN if [ -d /usr/local/share/nodenv ]; then From 8dcd45440124cc3fdd67015c60581d610647a1fa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 12:02:23 -0700 Subject: [PATCH 321/355] Remove token logging --- script/cibuild-atom-linux | 4 ---- 1 file changed, 4 deletions(-) diff --git a/script/cibuild-atom-linux b/script/cibuild-atom-linux index 4d33f3d8d..c4e957189 100755 --- a/script/cibuild-atom-linux +++ b/script/cibuild-atom-linux @@ -2,10 +2,6 @@ set -e -echo "the" -echo $BUILD_ATOM_LINUX_ACCESS_TOKEN -echo "token" - export ATOM_ACCESS_TOKEN=$BUILD_ATOM_LINUX_ACCESS_TOKEN if [ -d /usr/local/share/nodenv ]; then From bf76a3f1e785c43dcf4ebbcd9a28d639db3d5e3a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 12:07:30 -0700 Subject: [PATCH 322/355] Only publish on Linux for now --- build/tasks/publish-build-task.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 85a5ee3c6..077588621 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -20,6 +20,7 @@ module.exports = (gruntObject) -> {cp} = require('./task-helpers')(grunt) grunt.registerTask 'publish-build', 'Publish the built app', -> + return unless process.platform is 'linux' return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'ks-add-debian-asset' tasks = ['upload-assets'] tasks.unshift('build-docs', 'prepare-docs') if process.platform is 'darwin' From b1a6772105dc97e80f64912919b30e9aab521a32 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 12:34:51 -0700 Subject: [PATCH 323/355] Don't include version in .deb asset name --- build/tasks/publish-build-task.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 077588621..9660e797d 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -59,9 +59,13 @@ getAssets = -> ] when 'linux' buildDir = grunt.config.get('atom.buildDir') + if process.arch is 'ia32' + arch = 'i386' + else + arch = 'amd64' debAsset = fs.listSync(buildDir, ['.deb'])[0] [ - {assetName: path.basename(debAsset), sourcePath: debAsset} + {assetName: "atom-#{arch}.deb", sourcePath: debAsset} ] logError = (message, error, details) -> From 1bfda1fc6123d2ba438c2e896364117ee3c325a7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 12:52:36 -0700 Subject: [PATCH 324/355] Copy .deb file to proper upload path --- build/tasks/publish-build-task.coffee | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 9660e797d..d5f1284c0 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -29,7 +29,7 @@ module.exports = (gruntObject) -> grunt.registerTask 'prepare-docs', 'Move api.json to atom-api.json', -> docsOutputDir = grunt.config.get('docsOutputDir') buildDir = grunt.config.get('atom.buildDir') - cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json') + cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json') grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', -> done = @async() @@ -59,13 +59,15 @@ getAssets = -> ] when 'linux' buildDir = grunt.config.get('atom.buildDir') + sourcePath = fs.listSync(buildDir, ['.deb'])[0] if process.arch is 'ia32' arch = 'i386' else arch = 'amd64' - debAsset = fs.listSync(buildDir, ['.deb'])[0] + assetName = "atom-#{arch}.deb" + cp sourcePath, path.join(buildDir, assetName) [ - {assetName: "atom-#{arch}.deb", sourcePath: debAsset} + {assetName, sourcePath} ] logError = (message, error, details) -> From 97e7d24f43997c5f5b5c7ceac8eddf5d0f0a6aa8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 13:21:11 -0700 Subject: [PATCH 325/355] Add missing task helpers require --- build/tasks/publish-build-task.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index d5f1284c0..db7e95c98 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -60,12 +60,15 @@ getAssets = -> when 'linux' buildDir = grunt.config.get('atom.buildDir') sourcePath = fs.listSync(buildDir, ['.deb'])[0] - if process.arch is 'ia32' + if process.arch is 'ia32g' arch = 'i386' else arch = 'amd64' assetName = "atom-#{arch}.deb" + + {cp} = require('./task-helpers')(grunt) cp sourcePath, path.join(buildDir, assetName) + [ {assetName, sourcePath} ] From 6d1d6de8ffb4ae8503f8abb737c2f19f9f39dd7d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 13:28:10 -0700 Subject: [PATCH 326/355] Restore only uploading from master --- build/tasks/publish-build-task.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index db7e95c98..b1d8a5802 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -20,8 +20,7 @@ module.exports = (gruntObject) -> {cp} = require('./task-helpers')(grunt) grunt.registerTask 'publish-build', 'Publish the built app', -> - return unless process.platform is 'linux' - return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'ks-add-debian-asset' + return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'master' tasks = ['upload-assets'] tasks.unshift('build-docs', 'prepare-docs') if process.platform is 'darwin' grunt.task.run(tasks) From 54c1dd5225ccf37be1b0af03c76218440091d08e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 12 Sep 2014 15:10:04 -0700 Subject: [PATCH 327/355] Upgrade to language-php@0.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67e0a5e4f..2cbfc8ecf 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "language-mustache": "0.10.0", "language-objective-c": "0.11.0", "language-perl": "0.9.0", - "language-php": "0.15.0", + "language-php": "0.16.0", "language-property-list": "0.7.0", "language-python": "0.19.0", "language-ruby": "0.37.0", From ca8153b56b72dfa59542856939514707ad2358c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bengt=20L=C3=BCers?= Date: Sun, 14 Sep 2014 15:15:52 +0200 Subject: [PATCH 328/355] Elaborate getting a current working copy. The `git checkout` step from #3098 got removed by some merge, so here it is again. --- docs/build-instructions/linux.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index e5d54069e..a2715184c 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -33,8 +33,28 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. If you have problems with permissions don't forget to prefix with `sudo` -From the cloned repository directory: + 0. Get a current working copy: + If you have not done so before, clone the repository to a local directory. + + ```sh + git clone https://github.com/atom/atom + cd atom + ``` + + If you cloned the repository before, update your clone to the remote. + + ```sh + cd atom + git fetch + ``` + + In any case, check out the latest tag: + + ```sh + git checkout $(git describe --tags `git rev-list --tags --max-count=1`) + ``` + 1. Build: ```sh From f872583c81a422a639d140ef8a75c8e503d6c54c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Sun, 14 Sep 2014 09:37:26 -0700 Subject: [PATCH 329/355] Upgrade to tree-view@0.120 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2cbfc8ecf..abe1dcde7 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.119.0", + "tree-view": "0.120.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 10762d6440614f66634129ab0e64a9a6f2eb82c0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 08:21:19 -0700 Subject: [PATCH 330/355] Upgrade to language-gfm@0.50 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index abe1dcde7..5a0df9a59 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "language-c": "0.28.0", "language-coffee-script": "0.30.0", "language-css": "0.17.0", - "language-gfm": "0.49.0", + "language-gfm": "0.50.0", "language-git": "0.9.0", "language-go": "0.17.0", "language-html": "0.26.0", From 8c2bcf39431133da43f365df46c4ddd4099f0e40 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 08:34:21 -0700 Subject: [PATCH 331/355] Catch and log deactivate errors Closes #3538 --- spec/atom-spec.coffee | 12 +++++++++++- .../package-that-throws-on-deactivate/index.coffee | 4 ++++ src/package.coffee | 6 +++++- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/packages/package-that-throws-on-deactivate/index.coffee diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index d1c7ef6df..7b1ae1618 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -350,7 +350,7 @@ describe "the `atom` global", -> atom.packages.deactivatePackage("package-that-throws-on-activate") expect(badPack.mainModule.serialize).not.toHaveBeenCalled() - it "absorbs exceptions that are thrown by the package module's serialize methods", -> + it "absorbs exceptions that are thrown by the package module's serialize method", -> spyOn(console, 'error') waitsForPromise -> @@ -365,6 +365,16 @@ describe "the `atom` global", -> expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1 expect(console.error).toHaveBeenCalled() + it "absorbs exceptions that are thrown by the package module's deactivate method", -> + spyOn(console, 'error') + + waitsForPromise -> + atom.packages.activatePackage("package-that-throws-on-deactivate") + + runs -> + expect(-> atom.packages.deactivatePackage("package-that-throws-on-deactivate")).not.toThrow() + expect(console.error).toHaveBeenCalled() + it "removes the package's grammars", -> waitsForPromise -> atom.packages.activatePackage('package-with-grammars') diff --git a/spec/fixtures/packages/package-that-throws-on-deactivate/index.coffee b/spec/fixtures/packages/package-that-throws-on-deactivate/index.coffee new file mode 100644 index 000000000..5def0ed2d --- /dev/null +++ b/spec/fixtures/packages/package-that-throws-on-deactivate/index.coffee @@ -0,0 +1,4 @@ +module.exports = + activate: -> + deactivate: -> throw new Error('Top that') + serialize: -> diff --git a/src/package.coffee b/src/package.coffee index 6a104eccb..c005ae664 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -273,7 +273,11 @@ class Package @unsubscribeFromActivationEvents() @deactivateResources() @deactivateConfig() - @mainModule?.deactivate?() if @mainActivated + if @mainActivated + try + @mainModule?.deactivate?() + catch e + console.error "Error deactivating package '#{@name}'", e.stack @emit 'deactivated' @emitter.emit 'did-deactivate' From cea7d89129034f42f47c1e23379d1957168f2a83 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 08:50:16 -0700 Subject: [PATCH 332/355] :memo: :penguin: Tweak Linux instructions --- docs/build-instructions/linux.md | 35 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index a2715184c..7380d2a1d 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -33,46 +33,41 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. If you have problems with permissions don't forget to prefix with `sudo` - 0. Get a current working copy: + 1. Clone the Atom repository: - If you have not done so before, clone the repository to a local directory. - ```sh git clone https://github.com/atom/atom cd atom ``` - - If you cloned the repository before, update your clone to the remote. - + + 2. Checkout the latest Atom release: + ```sh - cd atom git fetch - ``` - - In any case, check out the latest tag: - - ```sh git checkout $(git describe --tags `git rev-list --tags --max-count=1`) ``` - - 1. Build: + + 3. Build Atom: ```sh - $ script/build + script/build ``` + This will create the atom application at `$TMPDIR/atom-build/Atom`. - 2. Install the `atom` and `apm` commands to `/usr/local/bin` by executing: + + 4. Install the `atom` and `apm` commands to `/usr/local/bin` by executing: ```sh - $ sudo script/grunt install + sudo script/grunt install ``` - 3. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`: + + 5. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`: ```sh - $ script/grunt mkdeb + script/grunt mkdeb ``` -Use the newly installed atom by restarting any running atom instances. +Use the newly installed Atom by fully quitting Atom and then reopening. ## Advanced Options From 863362ffeddf681ce2058acd556a5993da4d2fc8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 08:51:10 -0700 Subject: [PATCH 333/355] :memo: Outdent ordered list --- docs/build-instructions/linux.md | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 7380d2a1d..6230f9b96 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -33,39 +33,39 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. If you have problems with permissions don't forget to prefix with `sudo` - 1. Clone the Atom repository: +1. Clone the Atom repository: - ```sh - git clone https://github.com/atom/atom - cd atom - ``` + ```sh + git clone https://github.com/atom/atom + cd atom + ``` - 2. Checkout the latest Atom release: +2. Checkout the latest Atom release: - ```sh - git fetch - git checkout $(git describe --tags `git rev-list --tags --max-count=1`) - ``` + ```sh + git fetch + git checkout $(git describe --tags `git rev-list --tags --max-count=1`) + ``` - 3. Build Atom: +3. Build Atom: - ```sh - script/build - ``` + ```sh + script/build + ``` - This will create the atom application at `$TMPDIR/atom-build/Atom`. + This will create the atom application at `$TMPDIR/atom-build/Atom`. - 4. Install the `atom` and `apm` commands to `/usr/local/bin` by executing: +4. Install the `atom` and `apm` commands to `/usr/local/bin` by executing: - ```sh - sudo script/grunt install - ``` + ```sh + sudo script/grunt install + ``` - 5. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`: +5. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`: - ```sh - script/grunt mkdeb - ``` + ```sh + script/grunt mkdeb + ``` Use the newly installed Atom by fully quitting Atom and then reopening. From 6ee82d493724dd8aa67d32a4af58f5e1872b5f85 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 10:56:01 -0700 Subject: [PATCH 334/355] Upgrade to tree-view@0.121 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a0df9a59..748841dc7 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.120.0", + "tree-view": "0.121.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 5e5235767432946aa6daa36c2036f3835e2dba78 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 11:05:39 -0700 Subject: [PATCH 335/355] Upgrade to markdown-preview@0.102 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 748841dc7..70ecd6dc0 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "incompatible-packages": "0.9.0", "keybinding-resolver": "0.19.0", "link": "0.25.0", - "markdown-preview": "0.101.0", + "markdown-preview": "0.102.0", "metrics": "0.34.0", "open-on-github": "0.30.0", "package-generator": "0.31.0", From 7d61330b9f21318a2a7deeed76512ee0ac89e54f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 11:07:49 -0700 Subject: [PATCH 336/355] Upgrade to tree-view@0.122 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 70ecd6dc0..1698bed25 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.121.0", + "tree-view": "0.122.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 17a62564838b181320b1bd3dedc64334f162d97f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 11:10:35 -0700 Subject: [PATCH 337/355] Upgrade to find-and-replace@0.138 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1698bed25..3c02d8685 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.137.0", + "find-and-replace": "0.138.0", "fuzzy-finder": "0.58.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From 274a36e2636a676af77b9a682128c75f40dfc3bb Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 15 Sep 2014 11:18:51 -0700 Subject: [PATCH 338/355] Upgrade UI themes to fix tabs --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3c02d8685..1ac4fb703 100644 --- a/package.json +++ b/package.json @@ -64,9 +64,9 @@ }, "packageDependencies": { "atom-dark-syntax": "0.19.0", - "atom-dark-ui": "0.34.0", + "atom-dark-ui": "0.35.0", "atom-light-syntax": "0.20.0", - "atom-light-ui": "0.29.0", + "atom-light-ui": "0.30.0", "base16-tomorrow-dark-theme": "0.21.0", "base16-tomorrow-light-theme": "0.4.0", "solarized-dark-syntax": "0.22.0", From 804f290cd3e2b65b809076afb9fe7546e081d135 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 12:57:53 -0700 Subject: [PATCH 339/355] Memoize comment scope selector --- src/editor.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 92af3ed11..9084a5b06 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1365,7 +1365,8 @@ class Editor extends Model isBufferRowCommented: (bufferRow) -> if match = @lineTextForBufferRow(bufferRow).match(/\S/) scopes = @tokenForBufferPosition([bufferRow, match.index]).scopes - new TextMateScopeSelector('comment.*').matches(scopes) + @commentScopeSelector ?= new TextMateScopeSelector('comment.*') + @commentScopeSelector.matches(scopes) # Public: Toggle line comments for rows intersecting selections. # From 69480385e683eb39f1f376066a058a5014f8d393 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 13:02:21 -0700 Subject: [PATCH 340/355] Upgrade to tree-view@0.123 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ac4fb703..4c0620b35 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.122.0", + "tree-view": "0.123.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From a0edb92e16270db4aeddd27d1dd84e21859cb793 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 15 Sep 2014 14:33:11 -0600 Subject: [PATCH 341/355] Rename editor.softWrapped config option back to editor.softWrap --- docs/customizing-atom.md | 2 +- spec/editor-spec.coffee | 6 +++--- src/display-buffer.coffee | 2 +- src/editor-view.coffee | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/customizing-atom.md b/docs/customizing-atom.md index 0b86298d6..d83e960be 100644 --- a/docs/customizing-atom.md +++ b/docs/customizing-atom.md @@ -123,7 +123,7 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu. - `showInvisibles`: Whether to render placeholders for invisible characters (defaults to `false`) - `showIndentGuide`: Show/hide indent indicators within the editor - `showLineNumbers`: Show/hide line numbers within the gutter - - `softWrapped`: Enable/disable soft wrapping of text within the editor + - `softWrap`: Enable/disable soft wrapping of text within the editor - `softWrapAtPreferredLineLength`: Enable/disable soft line wrapping at `preferredLineLength` - `tabLength`: Number of spaces within a tab (defaults to `2`) - `fuzzyFinder` diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index d54ff5598..6ff0aa304 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -98,11 +98,11 @@ describe "Editor", -> expect(editor2.isFoldedAtBufferRow(4)).not.toBe editor.isFoldedAtBufferRow(4) describe "config defaults", -> - it "uses the `editor.tabLength`, `editor.softWrapped`, and `editor.softTabs` config values", -> + it "uses the `editor.tabLength`, `editor.softWrap`, and `editor.softTabs` config values", -> editor1 = null editor2 = null atom.config.set('editor.tabLength', 4) - atom.config.set('editor.softWrapped', true) + atom.config.set('editor.softWrap', true) atom.config.set('editor.softTabs', false) waitsForPromise -> @@ -114,7 +114,7 @@ describe "Editor", -> expect(editor1.getSoftTabs()).toBe false atom.config.set('editor.tabLength', 100) - atom.config.set('editor.softWrapped', false) + atom.config.set('editor.softWrap', false) atom.config.set('editor.softTabs', true) waitsForPromise -> diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index a2c9817a3..c86324b35 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -45,7 +45,7 @@ class DisplayBuffer extends Model @emitter = new Emitter - @softWrapped ?= atom.config.get('editor.softWrapped') ? false + @softWrapped ?= atom.config.get('editor.softWrap') ? false @tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, @invisibles}) @buffer = @tokenizedBuffer.buffer @charWidthsByScope = {} diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 7617567f6..e91d69caa 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -47,7 +47,7 @@ class EditorView extends View nonWordCharacters: "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" preferredLineLength: 80 tabLength: 2 - softWrapped: false + softWrap: false softTabs: true softWrapAtPreferredLineLength: false scrollSensitivity: 40 From 3faf566a48daf05754fdae60e85c2867fa225ef7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 15 Sep 2014 14:34:22 -0600 Subject: [PATCH 342/355] Rename editor:toggle-soft-wrapped back to editor:toggle-soft-wrap --- menus/darwin.cson | 2 +- menus/linux.cson | 2 +- menus/win32.cson | 2 +- src/editor-component.coffee | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/menus/darwin.cson b/menus/darwin.cson index 6e079ad0d..b892c56cc 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -166,7 +166,7 @@ ] } { type: 'separator' } - { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrapped' } + { label: 'Toggle Soft Wrap', command: 'editor:toggle-soft-wrap' } ] } diff --git a/menus/linux.cson b/menus/linux.cson index f0320fd23..ba87732dd 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -104,7 +104,7 @@ ] } { type: 'separator' } - { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrapped' } + { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' } ] } diff --git a/menus/win32.cson b/menus/win32.cson index f428acf4c..d002c2428 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -122,7 +122,7 @@ ] } { type: 'separator' } - { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrapped' } + { label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' } ] } diff --git a/src/editor-component.coffee b/src/editor-component.coffee index e190776e7..7714665da 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -478,7 +478,7 @@ EditorComponent = React.createClass 'editor:add-selection-above': -> editor.addSelectionAbove() 'editor:split-selections-into-lines': -> editor.splitSelectionsIntoLines() 'editor:toggle-soft-tabs': -> editor.toggleSoftTabs() - 'editor:toggle-soft-wrapped': -> editor.toggleSoftWrapped() + 'editor:toggle-soft-wrap': -> editor.toggleSoftWrapped() 'editor:fold-all': -> editor.foldAll() 'editor:unfold-all': -> editor.unfoldAll() 'editor:fold-current-row': -> editor.foldCurrentRow() From 647f6c5b24c0620bd1627cb030521af9cc10119c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 15 Sep 2014 15:44:17 -0600 Subject: [PATCH 343/355] Upgrade keybinding resolver to fix deprecation warnings in specs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c0620b35..8bd9610b3 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "grammar-selector": "0.29.0", "image-view": "0.36.0", "incompatible-packages": "0.9.0", - "keybinding-resolver": "0.19.0", + "keybinding-resolver": "0.20.0", "link": "0.25.0", "markdown-preview": "0.102.0", "metrics": "0.34.0", From ebe116d724f25cd03f28b75b31ba0fdc2f43f059 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 15 Sep 2014 16:03:36 -0600 Subject: [PATCH 344/355] Update parent view `is-focused` and `mini` classes on editor mount Fixes #3526 --- src/editor-component.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 7714665da..646ff690c 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -184,6 +184,8 @@ EditorComponent = React.createClass @subscribe scrollbarStyle.changes, @refreshScrollbars @domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval) + @updateParentViewFocusedClassIfNeeded({}) + @updateParentViewMiniClassIfNeeded({}) @checkForVisibilityChange() componentWillUnmount: -> From 94e285611c60a5e94f14b8ce2e5700145d4fc256 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 16:30:50 -0700 Subject: [PATCH 345/355] getActiveItem -> getActivePaneItem --- src/workspace.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 47d0cbe17..6515609ab 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -362,7 +362,7 @@ class Workspace extends Model # Returns an {Editor} or `undefined` if the current active item is not an # {Editor}. getActiveTextEditor: -> - activeItem = @getActiveItem() + activeItem = @getActivePaneItem() activeItem if activeItem instanceof Editor # Deprecated: From 82a906cce5f1e5e427b752b3dd66f5d08997fb8f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 16:39:53 -0700 Subject: [PATCH 346/355] Add Workspace::onDidChangeActivePaneItem Closes #3546 --- src/workspace.coffee | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 6515609ab..3862b91e0 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -113,7 +113,7 @@ class Workspace extends Model # Extended: Invoke the given callback when a pane item is added to the # workspace. # - # * `callback` {Function} to be called panes are added. + # * `callback` {Function} to be called when panes are added. # * `event` {Object} with the following keys: # * `item` The added pane item. # * `pane` {Pane} containing the added item. @@ -122,6 +122,15 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddPaneItem: (callback) -> @paneContainer.onDidAddPaneItem(callback) + # Extended: Invoke the given callback when the active pane item changes. + # + # * `callback` {Function} to be called when the active pane item changes. + # * `event` {Object} with the following keys: + # * `activeItem` The active pane item. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidChangeActivePaneItem: (callback) -> @paneContainer.onDidChangeActivePaneItem(callback) + # Extended: Invoke the given callback with all current and future panes items in # the workspace. # From 5c77b06d2ae7fd491a2ab8c9f997db3341d21d27 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 15 Sep 2014 18:25:29 -0700 Subject: [PATCH 347/355] Add Editor:onDidSave --- src/editor.coffee | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 9084a5b06..e66110d8e 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -257,6 +257,16 @@ class Editor extends Model onDidInsertText: (callback) -> @emitter.on 'did-insert-text', callback + # Public: Invoke the given callback after the buffer is saved to disk. + # + # * `callback` {Function} to be called after the buffer is saved. + # * `event` {Object} with the following keys: + # * `path` The path to which the buffer was saved. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidSave: (callback) -> + @getBuffer().onDidSave(callback) + # Extended: Calls your `callback` when a {Cursor} is added to the editor. # Immediately calls your callback for each existing cursor. # From 33ad0a9b931fbdb0844bc5cb0920f57e11423ebe Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 16 Sep 2014 09:19:07 -0600 Subject: [PATCH 348/355] Delegate ::onDidChangeActivePane and ::observeActivePane --- src/workspace.coffee | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/workspace.coffee b/src/workspace.coffee index 3862b91e0..64ea6404b 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -110,6 +110,24 @@ class Workspace extends Model # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. observePanes: (callback) -> @paneContainer.observePanes(callback) + # Extended: Invoke the given callback when the active pane changes. + # + # * `callback` {Function} to be called when the active pane changes. + # * `pane` A {Pane} that is the current return value of {::getActivePane}. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + onDidChangeActivePane: (callback) -> @paneContainer.onDidChangeActivePane(callback) + + # Extended: Invoke the given callback with the current active pane and when + # the active pane changes. + # + # * `callback` {Function} to be called with the current and future active# + # panes. + # * `pane` A {Pane} that is the current return value of {::getActivePane}. + # + # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. + observeActivePane: (callback) -> @paneContainer.observeActivePane(callback) + # Extended: Invoke the given callback when a pane item is added to the # workspace. # From dc88f080a3bb49dead6b28601277357e4472678a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Sep 2014 09:00:17 -0700 Subject: [PATCH 349/355] Upgrade to tree-view@0.124 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8bd9610b3..18f6f97e3 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.123.0", + "tree-view": "0.124.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From c7ca3e66fd02d1d2630e52e956dab9f58411765e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Sep 2014 09:27:02 -0700 Subject: [PATCH 350/355] Prepare 0.129 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18f6f97e3..258c0d0e5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.128.0", + "version": "0.129.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 16c9c419787403cdba2e0fde7da3504063d49db0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Sep 2014 10:02:45 -0700 Subject: [PATCH 351/355] Upgrade to tree-view@0.125 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 258c0d0e5..bf8e03d0a 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.124.0", + "tree-view": "0.125.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 73253d37bc8b6fc1e78e9f2b5efaa1bb9dd37f4d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Sep 2014 10:19:32 -0700 Subject: [PATCH 352/355] Prepare 0.130 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bf8e03d0a..589cb67eb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.129.0", + "version": "0.130.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 4a20f13162f65afc816b512ad7201e528c3443d7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 16 Sep 2014 10:25:25 -0700 Subject: [PATCH 353/355] Upgrade scandal to handle negate syntax !*.coffee --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 589cb67eb..c02428d37 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "react-atom-fork": "^0.11.1", "reactionary-atom-fork": "^1.0.0", "runas": "1.0.1", - "scandal": "1.0.0", + "scandal": "1.0.2", "scoped-property-store": "^0.9.0", "scrollbar-style": "^1.0.2", "season": "^1.0.2", From c747ab411c46f4702180a252665adf161290df37 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Sep 2014 10:40:07 -0700 Subject: [PATCH 354/355] Upgrade to tabs@0.51 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c02428d37..0518dfdd5 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "status-bar": "0.44.0", "styleguide": "0.30.0", "symbols-view": "0.63.0", - "tabs": "0.50.0", + "tabs": "0.51.0", "timecop": "0.22.0", "tree-view": "0.125.0", "update-package-dependencies": "0.6.0", From 0098ac67efff2ba92e1a89f44d27b4dfedde0c0d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 16 Sep 2014 14:23:38 -0700 Subject: [PATCH 355/355] Upgrade to markdown-preview@0.103 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0518dfdd5..135144923 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "incompatible-packages": "0.9.0", "keybinding-resolver": "0.20.0", "link": "0.25.0", - "markdown-preview": "0.102.0", + "markdown-preview": "0.103.0", "metrics": "0.34.0", "open-on-github": "0.30.0", "package-generator": "0.31.0",