From ebb02bcd37b297180a6ed5cf65461f94329c33c3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 26 Aug 2014 20:21:20 -0600 Subject: [PATCH 001/135] 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 002/135] 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 003/135] 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 004/135] 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 005/135] 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 006/135] 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 007/135] 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 008/135] 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 009/135] 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 010/135] 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 011/135] =?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 012/135] =?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 013/135] 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 014/135] :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 015/135] 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 016/135] 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 017/135] 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 018/135] =?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 019/135] =?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 020/135] 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 021/135] 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 022/135] 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 023/135] 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 024/135] :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 025/135] 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 026/135] 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 027/135] 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 028/135] :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 029/135] 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 030/135] 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 031/135] 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 032/135] 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 033/135] 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 034/135] =?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 035/135] 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 036/135] 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 a4a25576a290d75038ce5449122c762ef1c76de0 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 14:35:39 -0700 Subject: [PATCH 037/135] Split cursor methods into essential and extended --- src/editor.coffee | 277 +++++++++++++++++++++++----------------------- 1 file changed, 139 insertions(+), 138 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index ced7a5448..db1584334 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1510,30 +1510,156 @@ class Editor extends Model Section: Cursors ### - # Public: Determine if there are multiple cursors. + # Essential: Determine if there are multiple cursors. hasMultipleCursors: -> @getCursors().length > 1 - # Public: Get an Array of all {Cursor}s. - getCursors: -> new Array(@cursors...) + # Essential: Add a cursor at the given position in buffer coordinates. + # + # Returns a {Cursor}. + addCursorAtBufferPosition: (bufferPosition) -> + @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes()) + @getLastSelection().cursor - # Public: Get the most recently added {Cursor}. - getCursor: -> - _.last(@cursors) - - # Public: Add a cursor at the position in screen coordinates. + # Essential: Add a cursor at the position in screen coordinates. # # Returns a {Cursor}. addCursorAtScreenPosition: (screenPosition) -> @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) @getLastSelection().cursor - # Public: Add a cursor at the given position in buffer coordinates. + # Essential: Move the cursor to the given position in screen coordinates. # - # Returns a {Cursor}. - addCursorAtBufferPosition: (bufferPosition) -> - @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes()) - @getLastSelection().cursor + # If there are multiple cursors, they will be consolidated to a single cursor. + # + # * `position` A {Point} or {Array} of `[row, column]` + # * `options` (optional) An {Object} combining options for {::clipScreenPosition} with: + # * `autoscroll` Determines whether the editor scrolls to the new cursor's + # position. Defaults to true. + setCursorScreenPosition: (position, options) -> + @moveCursors (cursor) -> cursor.setScreenPosition(position, options) + + # Essential: Get the position of the most recently added cursor in screen + # coordinates. + # + # Returns a {Point}. + getCursorScreenPosition: -> + @getCursor().getScreenPosition() + + # Essential: Move the cursor to the given position in buffer coordinates. + # + # If there are multiple cursors, they will be consolidated to a single cursor. + # + # * `position` A {Point} or {Array} of `[row, column]` + # * `options` (optional) An {Object} combining options for {::clipScreenPosition} with: + # * `autoscroll` Determines whether the editor scrolls to the new cursor's + # position. Defaults to true. + setCursorBufferPosition: (position, options) -> + @moveCursors (cursor) -> cursor.setBufferPosition(position, options) + + # Essential: Get the position of the most recently added cursor in buffer + # coordinates. + # + # Returns a {Point}. + getCursorBufferPosition: -> + @getCursor().getBufferPosition() + + # Essential: Move every cursor up one row in screen coordinates. + moveCursorUp: (lineCount) -> + @moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true) + + # Essential: Move every cursor down one row in screen coordinates. + moveCursorDown: (lineCount) -> + @moveCursors (cursor) -> cursor.moveDown(lineCount, moveToEndOfSelection: true) + + # Essential: Move every cursor left one column. + moveCursorLeft: -> + @moveCursors (cursor) -> cursor.moveLeft(moveToEndOfSelection: true) + + # Essential: Move every cursor right one column. + moveCursorRight: -> + @moveCursors (cursor) -> cursor.moveRight(moveToEndOfSelection: true) + + # Essential: Move every cursor to the beginning of its line in buffer coordinates. + moveCursorToBeginningOfLine: -> + @moveCursors (cursor) -> cursor.moveToBeginningOfLine() + + # Essential: Move every cursor to the beginning of its line in screen coordinates. + moveCursorToBeginningOfScreenLine: -> + @moveCursors (cursor) -> cursor.moveToBeginningOfScreenLine() + + # Essential: Move every cursor to the first non-whitespace character of its line. + moveCursorToFirstCharacterOfLine: -> + @moveCursors (cursor) -> cursor.moveToFirstCharacterOfLine() + + # Essential: Move every cursor to the end of its line in buffer coordinates. + moveCursorToEndOfLine: -> + @moveCursors (cursor) -> cursor.moveToEndOfLine() + + # Essential: Move every cursor to the end of its line in screen coordinates. + moveCursorToEndOfScreenLine: -> + @moveCursors (cursor) -> cursor.moveToEndOfScreenLine() + + # Essential: Move every cursor to the beginning of its surrounding word. + moveCursorToBeginningOfWord: -> + @moveCursors (cursor) -> cursor.moveToBeginningOfWord() + + # Essential: Move every cursor to the end of its surrounding word. + moveCursorToEndOfWord: -> + @moveCursors (cursor) -> cursor.moveToEndOfWord() + + # Cursor Extended + + # Extended: Move every cursor to the top of the buffer. + # + # If there are multiple cursors, they will be merged into a single cursor. + moveCursorToTop: -> + @moveCursors (cursor) -> cursor.moveToTop() + + # Extended: Move every cursor to the bottom of the buffer. + # + # If there are multiple cursors, they will be merged into a single cursor. + moveCursorToBottom: -> + @moveCursors (cursor) -> cursor.moveToBottom() + + # Extended: Move every cursor to the beginning of the next word. + moveCursorToBeginningOfNextWord: -> + @moveCursors (cursor) -> cursor.moveToBeginningOfNextWord() + + # Extended: Move every cursor to the previous word boundary. + moveCursorToPreviousWordBoundary: -> + @moveCursors (cursor) -> cursor.moveToPreviousWordBoundary() + + # Extended: Move every cursor to the next word boundary. + moveCursorToNextWordBoundary: -> + @moveCursors (cursor) -> cursor.moveToNextWordBoundary() + + # Extended: Move every cursor to the beginning of the next paragraph. + moveCursorToBeginningOfNextParagraph: -> + @moveCursors (cursor) -> cursor.moveToBeginningOfNextParagraph() + + # Extended: Move every cursor to the beginning of the previous paragraph. + moveCursorToBeginningOfPreviousParagraph: -> + @moveCursors (cursor) -> cursor.moveToBeginningOfPreviousParagraph() + + # Extended: Get the row of the most recently added cursor in screen coordinates. + # + # Returns the screen row {Number}. + getCursorScreenRow: -> + @getCursor().getScreenRow() + + # Extended: Returns the word surrounding the most recently added cursor. + # + # * `options` (optional) See {Cursor::getBeginningOfCurrentWordBufferPosition}. + getWordUnderCursor: (options) -> + @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) + + # Extended: Get an Array of all {Cursor}s. + getCursors: -> new Array(@cursors...) + + # Extended: Get the most recently added {Cursor}. + getCursor: -> + _.last(@cursors) # Add a cursor based on the given {DisplayBufferMarker}. addCursor: (marker) -> @@ -1550,130 +1676,6 @@ class Editor extends Model _.remove(@cursors, cursor) @emit 'cursor-removed', cursor - # Public: Move the cursor to the given position in screen coordinates. - # - # If there are multiple cursors, they will be consolidated to a single cursor. - # - # * `position` A {Point} or {Array} of `[row, column]` - # * `options` (optional) An {Object} combining options for {::clipScreenPosition} with: - # * `autoscroll` Determines whether the editor scrolls to the new cursor's - # position. Defaults to true. - setCursorScreenPosition: (position, options) -> - @moveCursors (cursor) -> cursor.setScreenPosition(position, options) - - # Public: Get the position of the most recently added cursor in screen - # coordinates. - # - # Returns a {Point}. - getCursorScreenPosition: -> - @getCursor().getScreenPosition() - - # Public: Get the row of the most recently added cursor in screen coordinates. - # - # Returns the screen row {Number}. - getCursorScreenRow: -> - @getCursor().getScreenRow() - - # Public: Move the cursor to the given position in buffer coordinates. - # - # If there are multiple cursors, they will be consolidated to a single cursor. - # - # * `position` A {Point} or {Array} of `[row, column]` - # * `options` (optional) An {Object} combining options for {::clipScreenPosition} with: - # * `autoscroll` Determines whether the editor scrolls to the new cursor's - # position. Defaults to true. - setCursorBufferPosition: (position, options) -> - @moveCursors (cursor) -> cursor.setBufferPosition(position, options) - - # Public: Get the position of the most recently added cursor in buffer - # coordinates. - # - # Returns a {Point}. - getCursorBufferPosition: -> - @getCursor().getBufferPosition() - - # Public: Returns the word surrounding the most recently added cursor. - # - # * `options` (optional) See {Cursor::getBeginningOfCurrentWordBufferPosition}. - getWordUnderCursor: (options) -> - @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) - - # Public: Move every cursor up one row in screen coordinates. - moveCursorUp: (lineCount) -> - @moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true) - - # Public: Move every cursor down one row in screen coordinates. - moveCursorDown: (lineCount) -> - @moveCursors (cursor) -> cursor.moveDown(lineCount, moveToEndOfSelection: true) - - # Public: Move every cursor left one column. - moveCursorLeft: -> - @moveCursors (cursor) -> cursor.moveLeft(moveToEndOfSelection: true) - - # Public: Move every cursor right one column. - moveCursorRight: -> - @moveCursors (cursor) -> cursor.moveRight(moveToEndOfSelection: true) - - # Public: Move every cursor to the top of the buffer. - # - # If there are multiple cursors, they will be merged into a single cursor. - moveCursorToTop: -> - @moveCursors (cursor) -> cursor.moveToTop() - - # Public: Move every cursor to the bottom of the buffer. - # - # If there are multiple cursors, they will be merged into a single cursor. - moveCursorToBottom: -> - @moveCursors (cursor) -> cursor.moveToBottom() - - # Public: Move every cursor to the beginning of its line in screen coordinates. - moveCursorToBeginningOfScreenLine: -> - @moveCursors (cursor) -> cursor.moveToBeginningOfScreenLine() - - # Public: Move every cursor to the beginning of its line in buffer coordinates. - moveCursorToBeginningOfLine: -> - @moveCursors (cursor) -> cursor.moveToBeginningOfLine() - - # Public: Move every cursor to the first non-whitespace character of its line. - moveCursorToFirstCharacterOfLine: -> - @moveCursors (cursor) -> cursor.moveToFirstCharacterOfLine() - - # Public: Move every cursor to the end of its line in screen coordinates. - moveCursorToEndOfScreenLine: -> - @moveCursors (cursor) -> cursor.moveToEndOfScreenLine() - - # Public: Move every cursor to the end of its line in buffer coordinates. - moveCursorToEndOfLine: -> - @moveCursors (cursor) -> cursor.moveToEndOfLine() - - # Public: Move every cursor to the beginning of its surrounding word. - moveCursorToBeginningOfWord: -> - @moveCursors (cursor) -> cursor.moveToBeginningOfWord() - - # Public: Move every cursor to the end of its surrounding word. - moveCursorToEndOfWord: -> - @moveCursors (cursor) -> cursor.moveToEndOfWord() - - # Public: Move every cursor to the beginning of the next word. - moveCursorToBeginningOfNextWord: -> - @moveCursors (cursor) -> cursor.moveToBeginningOfNextWord() - - # Public: Move every cursor to the previous word boundary. - moveCursorToPreviousWordBoundary: -> - @moveCursors (cursor) -> cursor.moveToPreviousWordBoundary() - - # Public: Move every cursor to the next word boundary. - moveCursorToNextWordBoundary: -> - @moveCursors (cursor) -> cursor.moveToNextWordBoundary() - - # Public: Move every cursor to the beginning of the next paragraph. - moveCursorToBeginningOfNextParagraph: -> - @moveCursors (cursor) -> cursor.moveToBeginningOfNextParagraph() - - # Public: Move every cursor to the beginning of the previous paragraph. - moveCursorToBeginningOfPreviousParagraph: -> - @moveCursors (cursor) -> cursor.moveToBeginningOfPreviousParagraph() - moveCursors: (fn) -> @movingCursors = true fn(cursor) for cursor in @getCursors() @@ -1703,7 +1705,6 @@ class Editor extends Model @setCursorBufferPosition(cursorPosition) if cursorPosition cursorPosition = null - ### Section: Selections ### From db83375293d603326a11bc912d8375903eea5c27 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 14:38:58 -0700 Subject: [PATCH 038/135] Buffer before screen, get before set --- src/editor.coffee | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index db1584334..d13761a28 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1528,23 +1528,12 @@ class Editor extends Model @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) @getLastSelection().cursor - # Essential: Move the cursor to the given position in screen coordinates. - # - # If there are multiple cursors, they will be consolidated to a single cursor. - # - # * `position` A {Point} or {Array} of `[row, column]` - # * `options` (optional) An {Object} combining options for {::clipScreenPosition} with: - # * `autoscroll` Determines whether the editor scrolls to the new cursor's - # position. Defaults to true. - setCursorScreenPosition: (position, options) -> - @moveCursors (cursor) -> cursor.setScreenPosition(position, options) - - # Essential: Get the position of the most recently added cursor in screen + # Essential: Get the position of the most recently added cursor in buffer # coordinates. # # Returns a {Point}. - getCursorScreenPosition: -> - @getCursor().getScreenPosition() + getCursorBufferPosition: -> + @getCursor().getBufferPosition() # Essential: Move the cursor to the given position in buffer coordinates. # @@ -1557,12 +1546,23 @@ class Editor extends Model setCursorBufferPosition: (position, options) -> @moveCursors (cursor) -> cursor.setBufferPosition(position, options) - # Essential: Get the position of the most recently added cursor in buffer + # Essential: Get the position of the most recently added cursor in screen # coordinates. # # Returns a {Point}. - getCursorBufferPosition: -> - @getCursor().getBufferPosition() + getCursorScreenPosition: -> + @getCursor().getScreenPosition() + + # Essential: Move the cursor to the given position in screen coordinates. + # + # If there are multiple cursors, they will be consolidated to a single cursor. + # + # * `position` A {Point} or {Array} of `[row, column]` + # * `options` (optional) An {Object} combining options for {::clipScreenPosition} with: + # * `autoscroll` Determines whether the editor scrolls to the new cursor's + # position. Defaults to true. + setCursorScreenPosition: (position, options) -> + @moveCursors (cursor) -> cursor.setScreenPosition(position, options) # Essential: Move every cursor up one row in screen coordinates. moveCursorUp: (lineCount) -> From 45a9bd21fc39272c7941f8fc107ae00e0a1db708 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 14:43:36 -0700 Subject: [PATCH 039/135] Deprecate getCursorScreenRow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s out of place, and unnecessary. --- src/editor.coffee | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index d13761a28..aac77bda1 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1330,7 +1330,7 @@ class Editor extends Model # # Returns a {Boolean}. isFoldedAtCursorRow: -> - @isFoldedAtScreenRow(@getCursorScreenRow()) + @isFoldedAtScreenRow(@getCursorScreenPosition().row) # Public: Determine whether the given row in buffer coordinates is folded. # @@ -1553,6 +1553,13 @@ class Editor extends Model getCursorScreenPosition: -> @getCursor().getScreenPosition() + # Get the row of the most recently added cursor in screen coordinates. + # + # Returns the screen row {Number}. + getCursorScreenRow: -> + deprecate('Use `editor.getCursorScreenPosition().row` instead') + @getCursorScreenPosition().row + # Essential: Move the cursor to the given position in screen coordinates. # # If there are multiple cursors, they will be consolidated to a single cursor. @@ -1642,12 +1649,6 @@ class Editor extends Model moveCursorToBeginningOfPreviousParagraph: -> @moveCursors (cursor) -> cursor.moveToBeginningOfPreviousParagraph() - # Extended: Get the row of the most recently added cursor in screen coordinates. - # - # Returns the screen row {Number}. - getCursorScreenRow: -> - @getCursor().getScreenRow() - # Extended: Returns the word surrounding the most recently added cursor. # # * `options` (optional) See {Cursor::getBeginningOfCurrentWordBufferPosition}. From 01b48d2a0aede777f508eaed90d6716ecab5b1f8 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 14:44:23 -0700 Subject: [PATCH 040/135] Move adding cursor functions under more heavily used functions --- src/editor.coffee | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index aac77bda1..c24a7bc76 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1514,20 +1514,6 @@ class Editor extends Model hasMultipleCursors: -> @getCursors().length > 1 - # Essential: Add a cursor at the given position in buffer coordinates. - # - # Returns a {Cursor}. - addCursorAtBufferPosition: (bufferPosition) -> - @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes()) - @getLastSelection().cursor - - # Essential: Add a cursor at the position in screen coordinates. - # - # Returns a {Cursor}. - addCursorAtScreenPosition: (screenPosition) -> - @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) - @getLastSelection().cursor - # Essential: Get the position of the most recently added cursor in buffer # coordinates. # @@ -1571,6 +1557,20 @@ class Editor extends Model setCursorScreenPosition: (position, options) -> @moveCursors (cursor) -> cursor.setScreenPosition(position, options) + # Essential: Add a cursor at the given position in buffer coordinates. + # + # Returns a {Cursor}. + addCursorAtBufferPosition: (bufferPosition) -> + @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes()) + @getLastSelection().cursor + + # Essential: Add a cursor at the position in screen coordinates. + # + # Returns a {Cursor}. + addCursorAtScreenPosition: (screenPosition) -> + @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) + @getLastSelection().cursor + # Essential: Move every cursor up one row in screen coordinates. moveCursorUp: (lineCount) -> @moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true) From 78c24fb737371047546e5ebd084fbf56ac76a4d1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 15:54:16 -0600 Subject: [PATCH 041/135] 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 042/135] 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 043/135] 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 370ad23f7ca3073ea4d73c3e4b792282ac0beac7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 15:25:12 -0700 Subject: [PATCH 044/135] Remove `Cursor` from `::moveCursor*` methods --- benchmark/benchmark-suite.coffee | 8 +- docs/advanced/keymaps.md | 2 +- spec/editor-component-spec.coffee | 2 +- spec/editor-spec.coffee | 238 +++++++++++++++--------------- src/editor-component.coffee | 38 ++--- src/editor.coffee | 108 ++++++++++---- 6 files changed, 227 insertions(+), 169 deletions(-) diff --git a/benchmark/benchmark-suite.coffee b/benchmark/benchmark-suite.coffee index 99f5c60d8..2984c007e 100644 --- a/benchmark/benchmark-suite.coffee +++ b/benchmark/benchmark-suite.coffee @@ -53,7 +53,7 @@ describe "editorView.", -> describe "at-end.", -> beforeEach -> - editorView.moveCursorToBottom() + editorView.moveToBottom() benchmark "insert-delete", -> editorView.insertText('"') @@ -178,7 +178,7 @@ describe "editorView.", -> atom.workspaceView.openSync('huge.js') benchmark "moving-to-eof.", 1, -> - editorView.moveCursorToBottom() + editorView.moveToBottom() describe "on-first-line.", -> benchmark "inserting-newline", 5, -> @@ -195,11 +195,11 @@ describe "editorView.", -> endPosition = null beforeEach -> - editorView.moveCursorToBottom() + editorView.moveToBottom() endPosition = editorView.getCursorScreenPosition() benchmark "move-to-beginning-of-word", -> - editorView.moveCursorToBeginningOfWord() + editorView.moveToBeginningOfWord() editorView.setCursorScreenPosition(endPosition) benchmark "insert", -> diff --git a/docs/advanced/keymaps.md b/docs/advanced/keymaps.md index 24e76f2b1..cd05f0b95 100644 --- a/docs/advanced/keymaps.md +++ b/docs/advanced/keymaps.md @@ -56,7 +56,7 @@ character of the current line: class EditorView listenForEvents: -> @command 'editor:move-to-first-character-of-line', => - @editor.moveCursorToFirstCharacterOfLine() + @editor.moveToFirstCharacterOfLine() ``` The `::command` method is basically an enhanced version of jQuery's `::on` diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index d80396d23..7f3458172 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -710,7 +710,7 @@ describe "EditorComponent", -> expect(cursorsNode.classList.contains('blink-off')).toBe false # Stop blinking after moving the cursor - editor.moveCursorRight() + editor.moveRight() expect(cursorsNode.classList.contains('blink-off')).toBe false advanceClock(component.props.cursorBlinkResumeDelay) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index fdcddab9d..4b92c7ba4 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -158,20 +158,20 @@ describe "Editor", -> editor.setText('b') editor.setCursorBufferPosition([0,0]) editor.insertNewline() - editor.moveCursorUp() + editor.moveUp() editor.insertText('a') - editor.moveCursorDown() + 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.moveCursorDown() + editor.moveDown() expect(cursorsMovedHandler.callCount).toBe 1 cursorsMovedHandler.reset() editor.addCursorAtScreenPosition([3, 0]) - editor.moveCursorDown() + editor.moveDown() expect(cursorsMovedHandler.callCount).toBe 1 cursorsMovedHandler.reset() @@ -182,14 +182,14 @@ describe "Editor", -> it "clears a goal column established by vertical movement", -> # set a goal column by moving down editor.setCursorScreenPosition(row: 3, column: lineLengths[3]) - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition().column).not.toBe 6 # clear the goal column by explicitly setting the cursor position editor.setCursorScreenPosition([4,6]) expect(editor.getCursorScreenPosition().column).toBe 6 - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition().column).toBe 6 it "merges multiple cursors", -> @@ -211,32 +211,32 @@ describe "Editor", -> editor.setCursorScreenPosition([9, 0]) expect(editor.getCursorBufferPosition()).toEqual [8, 11] - describe ".moveCursorUp()", -> + describe ".moveUp()", -> it "moves the cursor up", -> editor.setCursorScreenPosition([2, 2]) - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursorScreenPosition()).toEqual [1, 2] it "retains the goal column across lines of differing length", -> expect(lineLengths[6]).toBeGreaterThan(32) editor.setCursorScreenPosition(row: 6, column: 32) - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursorScreenPosition().column).toBe lineLengths[5] - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursorScreenPosition().column).toBe lineLengths[4] - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursorScreenPosition().column).toBe 32 describe "when the cursor is on the first line", -> it "moves the cursor to the beginning of the line, but retains the goal column", -> editor.setCursorScreenPosition([0, 4]) - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursorScreenPosition()).toEqual([0, 0]) - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition()).toEqual([1, 4]) describe "when there is a selection", -> @@ -245,33 +245,33 @@ describe "Editor", -> it "moves above the selection", -> cursor = editor.getCursor() - editor.moveCursorUp() + editor.moveUp() expect(cursor.getBufferPosition()).toEqual [3, 9] it "merges cursors when they overlap", -> editor.addCursorAtScreenPosition([1, 0]) [cursor1, cursor2] = editor.getCursors() - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [0,0] - describe ".moveCursorDown()", -> + describe ".moveDown()", -> it "moves the cursor down", -> editor.setCursorScreenPosition([2, 2]) - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition()).toEqual [3, 2] it "retains the goal column across lines of differing length", -> editor.setCursorScreenPosition(row: 3, column: lineLengths[3]) - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition().column).toBe lineLengths[4] - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition().column).toBe lineLengths[5] - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition().column).toBe lineLengths[3] describe "when the cursor is on the last line", -> @@ -281,10 +281,10 @@ describe "Editor", -> expect(lastLine.length).toBeGreaterThan(0) editor.setCursorScreenPosition(row: lastLineIndex, column: editor.getTabLength()) - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursorScreenPosition()).toEqual(row: lastLineIndex, column: lastLine.length) - editor.moveCursorUp() + editor.moveUp() expect(editor.getCursorScreenPosition().column).toBe editor.getTabLength() it "retains a goal column of 0 when moving back up", -> @@ -293,8 +293,8 @@ describe "Editor", -> expect(lastLine.length).toBeGreaterThan(0) editor.setCursorScreenPosition(row: lastLineIndex, column: 0) - editor.moveCursorDown() - editor.moveCursorUp() + editor.moveDown() + editor.moveUp() expect(editor.getCursorScreenPosition().column).toBe 0 describe "when there is a selection", -> @@ -303,7 +303,7 @@ describe "Editor", -> it "moves below the selection", -> cursor = editor.getCursor() - editor.moveCursorDown() + editor.moveDown() expect(cursor.getBufferPosition()).toEqual [6, 10] it "merges cursors when they overlap", -> @@ -311,34 +311,34 @@ describe "Editor", -> editor.addCursorAtScreenPosition([11, 2]) [cursor1, cursor2] = editor.getCursors() - editor.moveCursorDown() + editor.moveDown() expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [12,2] - describe ".moveCursorLeft()", -> + describe ".moveLeft()", -> it "moves the cursor by one column to the left", -> editor.setCursorScreenPosition([1, 8]) - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual [1, 7] 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", -> editor.setCursorScreenPosition(row: 1, column: 0) - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: buffer.lineForRow(0).length) describe "when the cursor is on the first line", -> it "remains in the same position (0,0)", -> editor.setCursorScreenPosition(row: 0, column: 0) - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 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]) - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorBufferPosition()).toEqual [5, 4] describe "when there is a selection", -> @@ -347,10 +347,10 @@ describe "Editor", -> it "moves to the left of the selection", -> cursor = editor.getCursor() - editor.moveCursorLeft() + editor.moveLeft() expect(cursor.getBufferPosition()).toEqual [5, 22] - editor.moveCursorLeft() + editor.moveLeft() expect(cursor.getBufferPosition()).toEqual [5, 21] it "merges cursors when they overlap", -> @@ -358,21 +358,21 @@ describe "Editor", -> editor.addCursorAtScreenPosition([0, 1]) [cursor1, cursor2] = editor.getCursors() - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [0,0] - describe ".moveCursorRight()", -> + describe ".moveRight()", -> it "moves the cursor by one column to the right", -> editor.setCursorScreenPosition([3, 3]) - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursorScreenPosition()).toEqual [3, 4] 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", -> editor.setCursorScreenPosition([0, buffer.lineForRow(0).length]) - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursorScreenPosition()).toEqual [1, 0] describe "when the cursor is on the last line", -> @@ -383,7 +383,7 @@ describe "Editor", -> lastPosition = { row: lastLineIndex, column: lastLine.length } editor.setCursorScreenPosition(lastPosition) - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursorScreenPosition()).toEqual(lastPosition) @@ -393,10 +393,10 @@ describe "Editor", -> it "moves to the left of the selection", -> cursor = editor.getCursor() - editor.moveCursorRight() + editor.moveRight() expect(cursor.getBufferPosition()).toEqual [5, 27] - editor.moveCursorRight() + editor.moveRight() expect(cursor.getBufferPosition()).toEqual [5, 28] it "merges cursors when they overlap", -> @@ -404,33 +404,33 @@ describe "Editor", -> editor.addCursorAtScreenPosition([12, 1]) [cursor1, cursor2] = editor.getCursors() - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [12,2] - describe ".moveCursorToTop()", -> + describe ".moveToTop()", -> it "moves the cursor to the top of the buffer", -> editor.setCursorScreenPosition [11,1] editor.addCursorAtScreenPosition [12,0] - editor.moveCursorToTop() + editor.moveToTop() expect(editor.getCursors().length).toBe 1 expect(editor.getCursorBufferPosition()).toEqual [0,0] - describe ".moveCursorToBottom()", -> + describe ".moveToBottom()", -> it "moves the cusor to the bottom of the buffer", -> editor.setCursorScreenPosition [0,0] editor.addCursorAtScreenPosition [1,0] - editor.moveCursorToBottom() + editor.moveToBottom() expect(editor.getCursors().length).toBe 1 expect(editor.getCursorBufferPosition()).toEqual [12,2] - describe ".moveCursorToBeginningOfScreenLine()", -> + describe ".moveToBeginningOfScreenLine()", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> editor.setSoftWrap(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) - editor.moveCursorToBeginningOfScreenLine() + editor.moveToBeginningOfScreenLine() cursor = editor.getCursor() expect(cursor.getScreenPosition()).toEqual [1, 0] @@ -438,19 +438,19 @@ describe "Editor", -> it "moves cursor to the beginning of then line", -> editor.setCursorScreenPosition [0,5] editor.addCursorAtScreenPosition [1,7] - editor.moveCursorToBeginningOfScreenLine() + editor.moveToBeginningOfScreenLine() expect(editor.getCursors().length).toBe 2 [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,0] - describe ".moveCursorToEndOfScreenLine()", -> + describe ".moveToEndOfScreenLine()", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> editor.setSoftWrap(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) - editor.moveCursorToEndOfScreenLine() + editor.moveToEndOfScreenLine() cursor = editor.getCursor() expect(cursor.getScreenPosition()).toEqual [1, 9] @@ -458,31 +458,31 @@ describe "Editor", -> it "moves cursor to the end of line", -> editor.setCursorScreenPosition [0,0] editor.addCursorAtScreenPosition [1,0] - editor.moveCursorToEndOfScreenLine() + editor.moveToEndOfScreenLine() expect(editor.getCursors().length).toBe 2 [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,29] expect(cursor2.getBufferPosition()).toEqual [1,30] - describe ".moveCursorToBeginningOfLine()", -> + describe ".moveToBeginningOfLine()", -> it "moves cursor to the beginning of the buffer line", -> editor.setSoftWrap(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) - editor.moveCursorToBeginningOfLine() + editor.moveToBeginningOfLine() cursor = editor.getCursor() expect(cursor.getScreenPosition()).toEqual [0, 0] - describe ".moveCursorToEndOfLine()", -> + describe ".moveToEndOfLine()", -> it "moves cursor to the end of the buffer line", -> editor.setSoftWrap(true) editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([0, 2]) - editor.moveCursorToEndOfLine() + editor.moveToEndOfLine() cursor = editor.getCursor() expect(cursor.getScreenPosition()).toEqual [3, 4] - describe ".moveCursorToFirstCharacterOfLine()", -> + 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) @@ -490,12 +490,12 @@ describe "Editor", -> editor.setCursorScreenPosition [2,5] editor.addCursorAtScreenPosition [8,7] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() [cursor1, cursor2] = editor.getCursors() expect(cursor1.getScreenPosition()).toEqual [2,0] expect(cursor2.getScreenPosition()).toEqual [8,4] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() expect(cursor1.getScreenPosition()).toEqual [2,0] expect(cursor2.getScreenPosition()).toEqual [8,0] @@ -504,19 +504,19 @@ describe "Editor", -> editor.setCursorScreenPosition [0,5] editor.addCursorAtScreenPosition [1,7] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,2] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,0] it "moves to the beginning of the line if it only contains whitespace ", -> editor.setText("first\n \nthird") editor.setCursorScreenPosition [1,2] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() cursor = editor.getCursor() expect(cursor.getBufferPosition()).toEqual [1,0] @@ -524,9 +524,9 @@ describe "Editor", -> it "moves to the first character of the current line without being confused by the invisible characters", -> atom.config.set('editor.showInvisibles', true) editor.setCursorScreenPosition [1,7] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() expect(editor.getCursorBufferPosition()).toEqual [1,2] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() expect(editor.getCursorBufferPosition()).toEqual [1,0] describe "when invisible characters are enabled with hard tabs", -> @@ -535,19 +535,19 @@ describe "Editor", -> buffer.setTextInRange([[1, 0], [1, Infinity]], '\t\t\ta', false) editor.setCursorScreenPosition [1,7] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() expect(editor.getCursorBufferPosition()).toEqual [1,3] - editor.moveCursorToFirstCharacterOfLine() + editor.moveToFirstCharacterOfLine() expect(editor.getCursorBufferPosition()).toEqual [1,0] - describe ".moveCursorToBeginningOfWord()", -> + describe ".moveToBeginningOfWord()", -> it "moves the cursor to the beginning of the word", -> editor.setCursorBufferPosition [0, 8] editor.addCursorAtBufferPosition [1, 12] editor.addCursorAtBufferPosition [3, 0] [cursor1, cursor2, cursor3] = editor.getCursors() - editor.moveCursorToBeginningOfWord() + editor.moveToBeginningOfWord() expect(cursor1.getBufferPosition()).toEqual [0, 4] expect(cursor2.getBufferPosition()).toEqual [1, 11] @@ -555,19 +555,19 @@ describe "Editor", -> it "does not fail at position [0, 0]", -> editor.setCursorBufferPosition([0, 0]) - editor.moveCursorToBeginningOfWord() + editor.moveToBeginningOfWord() it "treats lines with only whitespace as a word", -> editor.setCursorBufferPosition([11, 0]) - editor.moveCursorToBeginningOfWord() + editor.moveToBeginningOfWord() expect(editor.getCursorBufferPosition()).toEqual [10, 0] it "works when the current line is blank", -> editor.setCursorBufferPosition([10, 0]) - editor.moveCursorToBeginningOfWord() + editor.moveToBeginningOfWord() expect(editor.getCursorBufferPosition()).toEqual [9, 2] - describe ".moveCursorToPreviousWordBoundary()", -> + describe ".moveToPreviousWordBoundary()", -> it "moves the cursor to the previous word boundary", -> editor.setCursorBufferPosition [0, 8] editor.addCursorAtBufferPosition [2, 0] @@ -575,14 +575,14 @@ describe "Editor", -> editor.addCursorAtBufferPosition [3, 14] [cursor1, cursor2, cursor3, cursor4] = editor.getCursors() - editor.moveCursorToPreviousWordBoundary() + editor.moveToPreviousWordBoundary() expect(cursor1.getBufferPosition()).toEqual [0, 4] expect(cursor2.getBufferPosition()).toEqual [1, 30] expect(cursor3.getBufferPosition()).toEqual [2, 0] expect(cursor4.getBufferPosition()).toEqual [3, 13] - describe ".moveCursorToNextWordBoundary()", -> + describe ".moveToNextWordBoundary()", -> it "moves the cursor to the previous word boundary", -> editor.setCursorBufferPosition [0, 8] editor.addCursorAtBufferPosition [2, 40] @@ -590,21 +590,21 @@ describe "Editor", -> editor.addCursorAtBufferPosition [3, 30] [cursor1, cursor2, cursor3, cursor4] = editor.getCursors() - editor.moveCursorToNextWordBoundary() + editor.moveToNextWordBoundary() expect(cursor1.getBufferPosition()).toEqual [0, 13] expect(cursor2.getBufferPosition()).toEqual [3, 0] expect(cursor3.getBufferPosition()).toEqual [3, 4] expect(cursor4.getBufferPosition()).toEqual [3, 31] - describe ".moveCursorToEndOfWord()", -> + describe ".moveToEndOfWord()", -> it "moves the cursor to the end of the word", -> editor.setCursorBufferPosition [0, 6] editor.addCursorAtBufferPosition [1, 10] editor.addCursorAtBufferPosition [2, 40] [cursor1, cursor2, cursor3] = editor.getCursors() - editor.moveCursorToEndOfWord() + editor.moveToEndOfWord() expect(cursor1.getBufferPosition()).toEqual [0, 13] expect(cursor2.getBufferPosition()).toEqual [1, 12] @@ -613,27 +613,27 @@ describe "Editor", -> it "does not blow up when there is no next word", -> editor.setCursorBufferPosition [Infinity, Infinity] endPosition = editor.getCursorBufferPosition() - editor.moveCursorToEndOfWord() + editor.moveToEndOfWord() expect(editor.getCursorBufferPosition()).toEqual endPosition it "treats lines with only whitespace as a word", -> editor.setCursorBufferPosition([9, 4]) - editor.moveCursorToEndOfWord() + editor.moveToEndOfWord() expect(editor.getCursorBufferPosition()).toEqual [10, 0] it "works when the current line is blank", -> editor.setCursorBufferPosition([10, 0]) - editor.moveCursorToEndOfWord() + editor.moveToEndOfWord() expect(editor.getCursorBufferPosition()).toEqual [11, 8] - describe ".moveCursorToBeginningOfNextWord()", -> + describe ".moveToBeginningOfNextWord()", -> it "moves the cursor before the first character of the next word", -> editor.setCursorBufferPosition [0,6] editor.addCursorAtBufferPosition [1,11] editor.addCursorAtBufferPosition [2,0] [cursor1, cursor2, cursor3] = editor.getCursors() - editor.moveCursorToBeginningOfNextWord() + editor.moveToBeginningOfNextWord() expect(cursor1.getBufferPosition()).toEqual [0, 14] expect(cursor2.getBufferPosition()).toEqual [1, 13] @@ -643,55 +643,55 @@ describe "Editor", -> editor.setText("ab cde- ") editor.setCursorBufferPosition [0,2] cursor = editor.getCursor() - editor.moveCursorToBeginningOfNextWord() + editor.moveToBeginningOfNextWord() expect(cursor.getBufferPosition()).toEqual [0, 3] it "does not blow up when there is no next word", -> editor.setCursorBufferPosition [Infinity, Infinity] endPosition = editor.getCursorBufferPosition() - editor.moveCursorToBeginningOfNextWord() + editor.moveToBeginningOfNextWord() expect(editor.getCursorBufferPosition()).toEqual endPosition it "treats lines with only whitespace as a word", -> editor.setCursorBufferPosition([9, 4]) - editor.moveCursorToBeginningOfNextWord() + editor.moveToBeginningOfNextWord() expect(editor.getCursorBufferPosition()).toEqual [10, 0] it "works when the current line is blank", -> editor.setCursorBufferPosition([10, 0]) - editor.moveCursorToBeginningOfNextWord() + editor.moveToBeginningOfNextWord() expect(editor.getCursorBufferPosition()).toEqual [11, 9] - describe ".moveCursorToBeginningOfNextParagraph()", -> + describe ".moveToBeginningOfNextParagraph()", -> it "moves the cursor before the first line of the next paragraph", -> editor.setCursorBufferPosition [0,6] cursor = editor.getCursor() - editor.moveCursorToBeginningOfNextParagraph() + editor.moveToBeginningOfNextParagraph() expect(cursor.getBufferPosition()).toEqual { row : 10, column : 0 } editor.setText("") editor.setCursorBufferPosition [0,0] cursor = editor.getCursor() - editor.moveCursorToBeginningOfNextParagraph() + editor.moveToBeginningOfNextParagraph() expect(cursor.getBufferPosition()).toEqual [0, 0] - describe ".moveCursorToBeginningOfPreviousParagraph()", -> + describe ".moveToBeginningOfPreviousParagraph()", -> it "moves the cursor before the first line of the pevious paragraph", -> editor.setCursorBufferPosition [10,0] cursor = editor.getCursor() - editor.moveCursorToBeginningOfPreviousParagraph() + editor.moveToBeginningOfPreviousParagraph() expect(cursor.getBufferPosition()).toEqual { row : 0, column : 0 } editor.setText("") editor.setCursorBufferPosition [0,0] cursor = editor.getCursor() - editor.moveCursorToBeginningOfPreviousParagraph() + editor.moveToBeginningOfPreviousParagraph() expect(cursor.getBufferPosition()).toEqual [0, 0] @@ -782,23 +782,23 @@ describe "Editor", -> editor.setCursorScreenPosition([2, 0]) expect(editor.getScrollBottom()).toBe 5.5 * 10 - editor.moveCursorDown() + editor.moveDown() expect(editor.getScrollBottom()).toBe 6 * 10 - editor.moveCursorDown() + editor.moveDown() expect(editor.getScrollBottom()).toBe 7 * 10 it "scrolls up when the last cursor gets closer than ::verticalScrollMargin to the top of the editor", -> editor.setCursorScreenPosition([11, 0]) editor.setScrollBottom(editor.getScrollHeight()) - editor.moveCursorUp() + editor.moveUp() expect(editor.getScrollBottom()).toBe editor.getScrollHeight() - editor.moveCursorUp() + editor.moveUp() expect(editor.getScrollTop()).toBe 7 * 10 - editor.moveCursorUp() + editor.moveUp() expect(editor.getScrollTop()).toBe 6 * 10 it "scrolls right when the last cursor gets closer than ::horizontalScrollMargin to the right of the editor", -> @@ -808,10 +808,10 @@ describe "Editor", -> editor.setCursorScreenPosition([0, 2]) expect(editor.getScrollRight()).toBe 5.5 * 10 - editor.moveCursorRight() + editor.moveRight() expect(editor.getScrollRight()).toBe 6 * 10 - editor.moveCursorRight() + editor.moveRight() expect(editor.getScrollRight()).toBe 7 * 10 it "scrolls left when the last cursor gets closer than ::horizontalScrollMargin to the left of the editor", -> @@ -820,10 +820,10 @@ describe "Editor", -> expect(editor.getScrollRight()).toBe editor.getScrollWidth() - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getScrollLeft()).toBe 59 * 10 - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getScrollLeft()).toBe 58 * 10 it "scrolls down when inserting lines makes the document longer than the editor's height", -> @@ -1169,7 +1169,7 @@ describe "Editor", -> describe "when the cursor is at the end of the text", -> it "select the previous word", -> editor.buffer.append 'word' - editor.moveCursorToBottom() + editor.moveToBottom() editor.selectWord() expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]] @@ -1480,19 +1480,19 @@ describe "Editor", -> it "clears the selection", -> makeSelection() - editor.moveCursorDown() + editor.moveDown() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editor.moveCursorUp() + editor.moveUp() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editor.moveCursorLeft() + editor.moveLeft() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editor.moveCursorRight() + editor.moveRight() expect(selection.isEmpty()).toBeTruthy() makeSelection() @@ -2576,7 +2576,7 @@ describe "Editor", -> editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe "// " - editor.moveCursorToBeginningOfLine() + editor.moveToBeginningOfLine() editor.insertText(" ") editor.setSelectedBufferRange([[10, 0], [10, 0]]) editor.toggleLineCommentsInSelection() @@ -2660,7 +2660,7 @@ describe "Editor", -> editor.beginTransaction() editor.delete() - editor.moveCursorToEndOfLine() + editor.moveToEndOfLine() editor.insertText('5') expect(buffer.getText()).toBe '145' @@ -3239,7 +3239,7 @@ describe "Editor", -> describe "when the edit session contains surrogate pair characters", -> it "correctly backspaces over them", -> editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97') - editor.moveCursorToBottom() + editor.moveToBottom() editor.backspace() expect(editor.getText()).toBe '\uD835\uDF97\uD835\uDF97' editor.backspace() @@ -3249,7 +3249,7 @@ describe "Editor", -> it "correctly deletes over them", -> editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97') - editor.moveCursorToTop() + editor.moveToTop() editor.delete() expect(editor.getText()).toBe '\uD835\uDF97\uD835\uDF97' editor.delete() @@ -3259,22 +3259,22 @@ describe "Editor", -> it "correctly moves over them", -> editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97\n') - editor.moveCursorToTop() - editor.moveCursorRight() + editor.moveToTop() + editor.moveRight() expect(editor.getCursorBufferPosition()).toEqual [0, 2] - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursorBufferPosition()).toEqual [0, 4] - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursorBufferPosition()).toEqual [0, 6] - editor.moveCursorRight() + editor.moveRight() expect(editor.getCursorBufferPosition()).toEqual [1, 0] - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorBufferPosition()).toEqual [0, 6] - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorBufferPosition()).toEqual [0, 4] - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorBufferPosition()).toEqual [0, 2] - editor.moveCursorLeft() + editor.moveLeft() expect(editor.getCursorBufferPosition()).toEqual [0, 0] describe ".setIndentationForBufferRow", -> @@ -3458,7 +3458,7 @@ describe "Editor", -> expect(editor.getScrollTop()).toBe 80 expect(editor.getSelectedBufferRanges()).toEqual [[[0,0], [12,2]]] - editor.moveCursorToBottom() + editor.moveToBottom() editor.selectPageUp() expect(editor.getScrollTop()).toBe 50 expect(editor.getSelectedBufferRanges()).toEqual [[[7,0], [12,2]]] diff --git a/src/editor-component.coffee b/src/editor-component.coffee index b14a169b8..be7eb57aa 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -403,8 +403,8 @@ EditorComponent = React.createClass {parentView, editor, mini} = @props @addCommandListeners - 'core:move-left': -> editor.moveCursorLeft() - 'core:move-right': -> editor.moveCursorRight() + 'core:move-left': -> editor.moveLeft() + 'core:move-right': -> editor.moveRight() 'core:select-left': -> editor.selectLeft() 'core:select-right': -> editor.selectRight() 'core:select-all': -> editor.selectAll() @@ -415,7 +415,7 @@ EditorComponent = React.createClass 'core:cut': -> editor.cutSelectedText() 'core:copy': -> editor.copySelectedText() 'core:paste': -> editor.pasteText() - 'editor:move-to-previous-word': -> editor.moveCursorToPreviousWord() + 'editor:move-to-previous-word': -> editor.moveToPreviousWord() 'editor:select-word': -> editor.selectWord() 'editor:consolidate-selections': @consolidateSelections 'editor:delete-to-beginning-of-word': -> editor.deleteToBeginningOfWord() @@ -424,18 +424,18 @@ EditorComponent = React.createClass 'editor:delete-to-end-of-word': -> editor.deleteToEndOfWord() 'editor:delete-line': -> editor.deleteLine() 'editor:cut-to-end-of-line': -> editor.cutToEndOfLine() - 'editor:move-to-beginning-of-next-paragraph': -> editor.moveCursorToBeginningOfNextParagraph() - 'editor:move-to-beginning-of-previous-paragraph': -> editor.moveCursorToBeginningOfPreviousParagraph() - 'editor:move-to-beginning-of-screen-line': -> editor.moveCursorToBeginningOfScreenLine() - 'editor:move-to-beginning-of-line': -> editor.moveCursorToBeginningOfLine() - 'editor:move-to-end-of-screen-line': -> editor.moveCursorToEndOfScreenLine() - 'editor:move-to-end-of-line': -> editor.moveCursorToEndOfLine() - 'editor:move-to-first-character-of-line': -> editor.moveCursorToFirstCharacterOfLine() - 'editor:move-to-beginning-of-word': -> editor.moveCursorToBeginningOfWord() - 'editor:move-to-end-of-word': -> editor.moveCursorToEndOfWord() - 'editor:move-to-beginning-of-next-word': -> editor.moveCursorToBeginningOfNextWord() - 'editor:move-to-previous-word-boundary': -> editor.moveCursorToPreviousWordBoundary() - 'editor:move-to-next-word-boundary': -> editor.moveCursorToNextWordBoundary() + 'editor:move-to-beginning-of-next-paragraph': -> editor.moveToBeginningOfNextParagraph() + 'editor:move-to-beginning-of-previous-paragraph': -> editor.moveToBeginningOfPreviousParagraph() + 'editor:move-to-beginning-of-screen-line': -> editor.moveToBeginningOfScreenLine() + 'editor:move-to-beginning-of-line': -> editor.moveToBeginningOfLine() + 'editor:move-to-end-of-screen-line': -> editor.moveToEndOfScreenLine() + 'editor:move-to-end-of-line': -> editor.moveToEndOfLine() + 'editor:move-to-first-character-of-line': -> editor.moveToFirstCharacterOfLine() + 'editor:move-to-beginning-of-word': -> editor.moveToBeginningOfWord() + 'editor:move-to-end-of-word': -> editor.moveToEndOfWord() + 'editor:move-to-beginning-of-next-word': -> editor.moveToBeginningOfNextWord() + 'editor:move-to-previous-word-boundary': -> editor.moveToPreviousWordBoundary() + 'editor:move-to-next-word-boundary': -> editor.moveToNextWordBoundary() 'editor:select-to-beginning-of-next-paragraph': -> editor.selectToBeginningOfNextParagraph() 'editor:select-to-beginning-of-previous-paragraph': -> editor.selectToBeginningOfPreviousParagraph() 'editor:select-to-end-of-line': -> editor.selectToEndOfLine() @@ -453,10 +453,10 @@ EditorComponent = React.createClass unless mini @addCommandListeners - 'core:move-up': -> editor.moveCursorUp() - 'core:move-down': -> editor.moveCursorDown() - 'core:move-to-top': -> editor.moveCursorToTop() - 'core:move-to-bottom': -> editor.moveCursorToBottom() + 'core:move-up': -> editor.moveUp() + 'core:move-down': -> editor.moveDown() + 'core:move-to-top': -> editor.moveToTop() + 'core:move-to-bottom': -> editor.moveToBottom() 'core:page-up': -> editor.pageUp() 'core:page-down': -> editor.pageDown() 'core:select-up': -> editor.selectUp() diff --git a/src/editor.coffee b/src/editor.coffee index c24a7bc76..538aea1e9 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -733,7 +733,7 @@ class Editor extends Model # Public: For each cursor, insert a newline at beginning the following line. insertNewlineBelow: -> @transact => - @moveCursorToEndOfLine() + @moveToEndOfLine() @insertNewline() # Public: For each cursor, insert a newline at the end of the preceding line. @@ -743,16 +743,16 @@ class Editor extends Model indentLevel = @indentationForBufferRow(bufferRow) onFirstLine = bufferRow is 0 - @moveCursorToBeginningOfLine() - @moveCursorLeft() + @moveToBeginningOfLine() + @moveLeft() @insertNewline() if @shouldAutoIndent() and @indentationForBufferRow(bufferRow) < indentLevel @setIndentationForBufferRow(bufferRow, indentLevel) if onFirstLine - @moveCursorUp() - @moveCursorToEndOfLine() + @moveUp() + @moveToEndOfLine() ### Section: Removing Text @@ -1572,82 +1572,140 @@ class Editor extends Model @getLastSelection().cursor # Essential: Move every cursor up one row in screen coordinates. - moveCursorUp: (lineCount) -> + # + # * `lineCount` {Number} number of lines to move + moveUp: (lineCount) -> @moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true) + moveCursorUp: (lineCount) -> + deprecate("Use Editor::moveUp() instead") + @moveUp(lineCount) # Essential: Move every cursor down one row in screen coordinates. - moveCursorDown: (lineCount) -> + # + # * `lineCount` {Number} number of lines to move + moveDown: (lineCount) -> @moveCursors (cursor) -> cursor.moveDown(lineCount, moveToEndOfSelection: true) + moveCursorDown: (lineCount) -> + deprecate("Use Editor::moveDown() instead") + @moveDown(lineCount) # Essential: Move every cursor left one column. - moveCursorLeft: -> + moveLeft: -> @moveCursors (cursor) -> cursor.moveLeft(moveToEndOfSelection: true) + moveCursorLeft: -> + deprecate("Use Editor::moveLeft() instead") + @moveLeft() # Essential: Move every cursor right one column. - moveCursorRight: -> + moveRight: -> @moveCursors (cursor) -> cursor.moveRight(moveToEndOfSelection: true) + moveCursorRight: -> + deprecate("Use Editor::moveRight() instead") + @moveRight() # Essential: Move every cursor to the beginning of its line in buffer coordinates. - moveCursorToBeginningOfLine: -> + moveToBeginningOfLine: -> @moveCursors (cursor) -> cursor.moveToBeginningOfLine() + moveCursorToBeginningOfLine: -> + deprecate("Use Editor::moveToBeginningOfLine() instead") + @moveToBeginningOfLine() # Essential: Move every cursor to the beginning of its line in screen coordinates. - moveCursorToBeginningOfScreenLine: -> + moveToBeginningOfScreenLine: -> @moveCursors (cursor) -> cursor.moveToBeginningOfScreenLine() + moveCursorToBeginningOfScreenLine: -> + deprecate("Use Editor::moveToBeginningOfScreenLine() instead") + @moveToBeginningOfScreenLine() # Essential: Move every cursor to the first non-whitespace character of its line. - moveCursorToFirstCharacterOfLine: -> + moveToFirstCharacterOfLine: -> @moveCursors (cursor) -> cursor.moveToFirstCharacterOfLine() + moveCursorToFirstCharacterOfLine: -> + deprecate("Use Editor::moveToFirstCharacterOfLine() instead") + @moveToFirstCharacterOfLine() # Essential: Move every cursor to the end of its line in buffer coordinates. - moveCursorToEndOfLine: -> + moveToEndOfLine: -> @moveCursors (cursor) -> cursor.moveToEndOfLine() + moveCursorToEndOfLine: -> + deprecate("Use Editor::moveToEndOfLine() instead") + @moveToEndOfLine() # Essential: Move every cursor to the end of its line in screen coordinates. - moveCursorToEndOfScreenLine: -> + moveToEndOfScreenLine: -> @moveCursors (cursor) -> cursor.moveToEndOfScreenLine() + moveCursorToEndOfScreenLine: -> + deprecate("Use Editor::moveToEndOfScreenLine() instead") + @moveToEndOfScreenLine() # Essential: Move every cursor to the beginning of its surrounding word. - moveCursorToBeginningOfWord: -> + moveToBeginningOfWord: -> @moveCursors (cursor) -> cursor.moveToBeginningOfWord() + moveCursorToBeginningOfWord: -> + deprecate("Use Editor::moveToBeginningOfWord() instead") + @moveToBeginningOfWord() # Essential: Move every cursor to the end of its surrounding word. - moveCursorToEndOfWord: -> + moveToEndOfWord: -> @moveCursors (cursor) -> cursor.moveToEndOfWord() + moveCursorToEndOfWord: -> + deprecate("Use Editor::moveToEndOfWord() instead") + @moveToEndOfWord() # Cursor Extended # Extended: Move every cursor to the top of the buffer. # # If there are multiple cursors, they will be merged into a single cursor. - moveCursorToTop: -> + moveToTop: -> @moveCursors (cursor) -> cursor.moveToTop() + moveCursorToTop: -> + deprecate("Use Editor::moveToTop() instead") + @moveToTop() # Extended: Move every cursor to the bottom of the buffer. # # If there are multiple cursors, they will be merged into a single cursor. - moveCursorToBottom: -> + moveToBottom: -> @moveCursors (cursor) -> cursor.moveToBottom() + moveCursorToBottom: -> + deprecate("Use Editor::moveToBottom() instead") + @moveToBottom() # Extended: Move every cursor to the beginning of the next word. - moveCursorToBeginningOfNextWord: -> + moveToBeginningOfNextWord: -> @moveCursors (cursor) -> cursor.moveToBeginningOfNextWord() + moveCursorToBeginningOfNextWord: -> + deprecate("Use Editor::moveToBeginningOfNextWord() instead") + @moveToBeginningOfNextWord() # Extended: Move every cursor to the previous word boundary. - moveCursorToPreviousWordBoundary: -> + moveToPreviousWordBoundary: -> @moveCursors (cursor) -> cursor.moveToPreviousWordBoundary() + moveCursorToPreviousWordBoundary: -> + deprecate("Use Editor::moveToPreviousWordBoundary() instead") + @moveToPreviousWordBoundary() # Extended: Move every cursor to the next word boundary. - moveCursorToNextWordBoundary: -> + moveToNextWordBoundary: -> @moveCursors (cursor) -> cursor.moveToNextWordBoundary() + moveCursorToNextWordBoundary: -> + deprecate("Use Editor::moveToNextWordBoundary() instead") + @moveToNextWordBoundary() # Extended: Move every cursor to the beginning of the next paragraph. - moveCursorToBeginningOfNextParagraph: -> + moveToBeginningOfNextParagraph: -> @moveCursors (cursor) -> cursor.moveToBeginningOfNextParagraph() + moveCursorToBeginningOfNextParagraph: -> + deprecate("Use Editor::moveToBeginningOfNextParagraph() instead") + @moveToBeginningOfNextParagraph() # Extended: Move every cursor to the beginning of the previous paragraph. - moveCursorToBeginningOfPreviousParagraph: -> + moveToBeginningOfPreviousParagraph: -> @moveCursors (cursor) -> cursor.moveToBeginningOfPreviousParagraph() + moveCursorToBeginningOfPreviousParagraph: -> + deprecate("Use Editor::moveToBeginningOfPreviousParagraph() instead") + @moveToBeginningOfPreviousParagraph() # Extended: Returns the word surrounding the most recently added cursor. # @@ -2123,12 +2181,12 @@ class Editor extends Model pageUp: -> newScrollTop = @getScrollTop() - @getHeight() - @moveCursorUp(@getRowsPerPage()) + @moveUp(@getRowsPerPage()) @setScrollTop(newScrollTop) pageDown: -> newScrollTop = @getScrollTop() + @getHeight() - @moveCursorDown(@getRowsPerPage()) + @moveDown(@getRowsPerPage()) @setScrollTop(newScrollTop) selectPageUp: -> From 65ba95a4494a7c24fbe4697da7cd242f11d97b76 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 15:25:23 -0700 Subject: [PATCH 045/135] Add missing docs --- src/editor.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 538aea1e9..2a8f88adb 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1559,6 +1559,8 @@ class Editor extends Model # Essential: Add a cursor at the given position in buffer coordinates. # + # * `bufferPosition` A {Point} or {Array} of `[row, column]` + # # Returns a {Cursor}. addCursorAtBufferPosition: (bufferPosition) -> @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes()) @@ -1566,6 +1568,8 @@ class Editor extends Model # Essential: Add a cursor at the position in screen coordinates. # + # * `screenPosition` A {Point} or {Array} of `[row, column]` + # # Returns a {Cursor}. addCursorAtScreenPosition: (screenPosition) -> @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) From e74244fc25e1d817d5294d66d9cfc6ee1697bbd6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 15:25:35 -0700 Subject: [PATCH 046/135] Move less used function down in the order --- src/editor.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 2a8f88adb..b6a9054a0 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1510,10 +1510,6 @@ class Editor extends Model Section: Cursors ### - # Essential: Determine if there are multiple cursors. - hasMultipleCursors: -> - @getCursors().length > 1 - # Essential: Get the position of the most recently added cursor in buffer # coordinates. # @@ -1575,6 +1571,10 @@ class Editor extends Model @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) @getLastSelection().cursor + # Essential: Returns {Boolean} indicating whether or not there are multiple cursors. + hasMultipleCursors: -> + @getCursors().length > 1 + # Essential: Move every cursor up one row in screen coordinates. # # * `lineCount` {Number} number of lines to move From 12f78dd95782a8b928eb6f49dbe1fae9a6c703ef Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 16:27:20 -0600 Subject: [PATCH 047/135] :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 048/135] 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 049/135] 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 7ca5ece68aff73989637777b9f1b062c08b09083 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:06:44 -0700 Subject: [PATCH 050/135] Add methods to be symmetrical with selections * getCursorsOrderedByBufferPosition * getCursorBufferPositions * getCursorScreenPositions --- spec/editor-spec.coffee | 20 ++++++++++++++++++++ src/cursor.coffee | 8 ++++++++ src/editor.coffee | 27 +++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 4b92c7ba4..f2cf94142 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -750,6 +750,26 @@ describe "Editor", -> buffer.insert([8, 0], '...') expect(cursorMovedHandler).not.toHaveBeenCalled() + describe "::getCursorBufferPositions()", -> + it "returns the existing cursor", -> + cursor1 = editor.addCursorAtBufferPosition([8, 5]) + cursor2 = editor.addCursorAtBufferPosition([4, 5]) + expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [4, 5], [8, 5]] + + describe "::getCursorScreenPositions()", -> + it "returns the existing cursor", -> + editor.foldBufferRow(4) + cursor1 = editor.addCursorAtBufferPosition([8, 5]) + cursor2 = editor.addCursorAtBufferPosition([3, 5]) + expect(editor.getCursorScreenPositions()).toEqual [[0, 0], [3, 5], [5, 5]] + + describe "::getCursorsOrderedByBufferPosition()", -> + it "returns all cursors ordered by buffer positions", -> + originalCursor = editor.getCursor() + cursor1 = editor.addCursorAtBufferPosition([8, 5]) + cursor2 = editor.addCursorAtBufferPosition([4, 5]) + expect(editor.getCursorsOrderedByBufferPosition()).toEqual [originalCursor, cursor2, cursor1] + describe "addCursorAtScreenPosition(screenPosition)", -> describe "when a cursor already exists at the position", -> it "returns the existing cursor", -> diff --git a/src/cursor.coffee b/src/cursor.coffee index 968b965dd..7cc5e6484 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -569,3 +569,11 @@ class Cursor extends Model false else bufferPosition.column > firstCharacterColumn + + # Public: Compare this cursor's buffer position to another cursor's buffer position. + # + # See {Point::compare} for more details. + # + # * `otherCursor`{Cursor} to compare against + compare: (otherCursor) -> + @getBufferPosition().compare(otherCursor.getBufferPosition()) diff --git a/src/editor.coffee b/src/editor.coffee index b6a9054a0..2939df441 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1513,10 +1513,16 @@ class Editor extends Model # Essential: Get the position of the most recently added cursor in buffer # coordinates. # - # Returns a {Point}. + # Returns a {Point} getCursorBufferPosition: -> @getCursor().getBufferPosition() + # Essential: Get the position of all the cursor positions in buffer coordinates. + # + # Returns {Array} of {Point}s + getCursorBufferPositions: -> + cursor.getBufferPosition() for cursor in @getCursorsOrderedByBufferPosition() + # Essential: Move the cursor to the given position in buffer coordinates. # # If there are multiple cursors, they will be consolidated to a single cursor. @@ -1535,6 +1541,12 @@ class Editor extends Model getCursorScreenPosition: -> @getCursor().getScreenPosition() + # Essential: Get the position of all the cursor positions in screen coordinates. + # + # Returns {Array} of {Point}s + getCursorScreenPositions: -> + cursor.getScreenPosition() for cursor in @getCursorsOrderedByBufferPosition() + # Get the row of the most recently added cursor in screen coordinates. # # Returns the screen row {Number}. @@ -1717,13 +1729,20 @@ class Editor extends Model getWordUnderCursor: (options) -> @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) - # Extended: Get an Array of all {Cursor}s. - getCursors: -> new Array(@cursors...) - # Extended: Get the most recently added {Cursor}. getCursor: -> _.last(@cursors) + # Extended: Get an Array of all {Cursor}s. + getCursors: -> new Array(@cursors...) + + # Extended: Get all {Cursors}s, ordered by their position in the buffer + # instead of the order in which they were added. + # + # Returns an {Array} of {Selection}s. + getCursorsOrderedByBufferPosition: -> + @getCursors().sort (a, b) -> a.compare(b) + # Add a cursor based on the given {DisplayBufferMarker}. addCursor: (marker) -> cursor = new Cursor(editor: this, marker: marker) From cee7539e35a7e030756dbdf84b09ba3fd3f25a3f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:14:15 -0600 Subject: [PATCH 051/135] 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 052/135] 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 2551313b58de4a4e2bb007ce1db1cb9d7bf16c1c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:31:10 -0700 Subject: [PATCH 053/135] Deprecate methods on cursor --- src/cursor.coffee | 115 +++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 7cc5e6484..d4d0c54a0 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -1,6 +1,7 @@ {Point, Range} = require 'text-buffer' {Model} = require 'theorist' _ = require 'underscore-plus' +{deprecate} = require 'grim' # Extended: The `Cursor` class represents the little blinking line identifying # where text can be inserted. @@ -225,7 +226,7 @@ class Cursor extends Model @editor.lineForBufferRow(@getBufferRow()) # Public: Moves the cursor up one screen row. - moveUp: (rowCount = 1, {moveToEndOfSelection}={}) -> + moveUp: (rowCount=1, {moveToEndOfSelection}={}) -> range = @marker.getScreenRange() if moveToEndOfSelection and not range.isEmpty() { row, column } = range.start @@ -235,6 +236,9 @@ class Cursor extends Model column = @goalColumn if @goalColumn? @setScreenPosition({row: row - rowCount, column: column}) @goalColumn = column + moveCursorUp: (rowCount=1, options) -> + deprecate("Use Cursor::moveUp() instead. `Cursor` has been removed from these methods.") + @moveUp(rowCount, options) # Public: Moves the cursor down one screen row. moveDown: (rowCount = 1, {moveToEndOfSelection}={}) -> @@ -247,6 +251,9 @@ class Cursor extends Model column = @goalColumn if @goalColumn? @setScreenPosition({row: row + rowCount, column: column}) @goalColumn = column + moveCursorUp: (rowCount=1, options) -> + deprecate("Use Cursor::moveUp() instead. `Cursor` has been removed from these methods.") + @moveUp(rowCount, options) # Public: Moves the cursor left one screen column. # @@ -261,6 +268,9 @@ class Cursor extends Model {row, column} = @getScreenPosition() [row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity] @setScreenPosition({row, column}) + moveCursorUp: (rowCount=1, options) -> + deprecate("Use Cursor::moveUp() instead. `Cursor` has been removed from these methods.") + @moveUp(rowCount, options) # Public: Moves the cursor right one screen column. # @@ -274,22 +284,37 @@ class Cursor extends Model else { row, column } = @getScreenPosition() @setScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true) + moveCursorRight: (rowCount=1, options) -> + deprecate("Use Cursor::moveRight() instead. `Cursor` has been removed from these methods.") + @moveRight(rowCount, options) # Public: Moves the cursor to the top of the buffer. moveToTop: -> @setBufferPosition([0,0]) + moveCursorToTop: (rowCount=1, options) -> + deprecate("Use Cursor::moveToTop() instead. `Cursor` has been removed from these methods.") + @moveToTop(rowCount, options) # Public: Moves the cursor to the bottom of the buffer. moveToBottom: -> @setBufferPosition(@editor.getEofBufferPosition()) + moveCursorToBottom: (rowCount=1, options) -> + deprecate("Use Cursor::moveToBottom() instead. `Cursor` has been removed from these methods.") + @moveToBottom(rowCount, options) # Public: Moves the cursor to the beginning of the line. moveToBeginningOfScreenLine: -> @setScreenPosition([@getScreenRow(), 0]) + moveCursorToBeginningOfScreenLine: (rowCount=1, options) -> + deprecate("Use Cursor::moveToBeginningOfScreenLine() instead. `Cursor` has been removed from these methods.") + @moveToBeginningOfScreenLine(rowCount, options) # Public: Moves the cursor to the beginning of the buffer line. moveToBeginningOfLine: -> @setBufferPosition([@getBufferRow(), 0]) + moveCursorToBeginningOfLine: (rowCount=1, options) -> + deprecate("Use Cursor::moveToBeginningOfLine() instead. `Cursor` has been removed from these methods.") + @moveToBeginningOfLine(rowCount, options) # Public: Moves the cursor to the beginning of the first character in the # line. @@ -308,6 +333,62 @@ class Cursor extends Model targetBufferColumn = lineBufferRange.start.column @setBufferPosition([lineBufferRange.start.row, targetBufferColumn]) + moveCursorToFirstCharacterOfLine: (rowCount=1, options) -> + deprecate("Use Cursor::moveToFirstCharacterOfLine() instead. `Cursor` has been removed from these methods.") + @moveToFirstCharacterOfLine(rowCount, options) + + # Public: Moves the cursor to the end of the line. + moveToEndOfScreenLine: -> + @setScreenPosition([@getScreenRow(), Infinity]) + moveCursorToEndOfScreenLine: (rowCount=1, options) -> + deprecate("Use Cursor::moveToEndOfScreenLine() instead. `Cursor` has been removed from these methods.") + @moveToEndOfScreenLine(rowCount, options) + + # Public: Moves the cursor to the end of the buffer line. + moveToEndOfLine: -> + @setBufferPosition([@getBufferRow(), Infinity]) + moveCursorToEndOfLine: (rowCount=1, options) -> + deprecate("Use Cursor::moveToEndOfLine() instead. `Cursor` has been removed from these methods.") + @moveToEndOfLine(rowCount, options) + + # Public: Moves the cursor to the beginning of the word. + moveToBeginningOfWord: -> + @setBufferPosition(@getBeginningOfCurrentWordBufferPosition()) + moveCursorToBeginningOfWord: (rowCount=1, options) -> + deprecate("Use Cursor::moveToBeginningOfWord() instead. `Cursor` has been removed from these methods.") + @moveToBeginningOfWord(rowCount, options) + + # Public: Moves the cursor to the end of the word. + moveToEndOfWord: -> + if position = @getEndOfCurrentWordBufferPosition() + @setBufferPosition(position) + moveCursorToEndOfWord: (rowCount=1, options) -> + deprecate("Use Cursor::moveToEndOfWord() instead. `Cursor` has been removed from these methods.") + @moveToEndOfWord(rowCount, options) + + # Public: Moves the cursor to the beginning of the next word. + moveToBeginningOfNextWord: -> + if position = @getBeginningOfNextWordBufferPosition() + @setBufferPosition(position) + moveCursorToBeginningOfNextWord: (rowCount=1, options) -> + deprecate("Use Cursor::moveToBeginningOfNextWord() instead. `Cursor` has been removed from these methods.") + @moveToBeginningOfNextWord(rowCount, options) + + # Public: Moves the cursor to the previous word boundary. + moveToPreviousWordBoundary: -> + if position = @getPreviousWordBoundaryBufferPosition() + @setBufferPosition(position) + moveCursorToPreviousWordBoundary: (rowCount=1, options) -> + deprecate("Use Cursor::moveToPreviousWordBoundary() instead. `Cursor` has been removed from these methods.") + @moveToPreviousWordBoundary(rowCount, options) + + # Public: Moves the cursor to the next word boundary. + moveToNextWordBoundary: -> + if position = @getMoveNextWordBoundaryBufferPosition() + @setBufferPosition(position) + moveCursorToNextWordBoundary: (rowCount=1, options) -> + deprecate("Use Cursor::moveToNextWordBoundary() instead. `Cursor` has been removed from these methods.") + @moveToNextWordBoundary(rowCount, options) # Public: Moves the cursor to the beginning of the buffer line, skipping all # whitespace. @@ -320,38 +401,6 @@ class Cursor extends Model @setBufferPosition(endOfLeadingWhitespace) if endOfLeadingWhitespace.isGreaterThan(position) - # Public: Moves the cursor to the end of the line. - moveToEndOfScreenLine: -> - @setScreenPosition([@getScreenRow(), Infinity]) - - # Public: Moves the cursor to the end of the buffer line. - moveToEndOfLine: -> - @setBufferPosition([@getBufferRow(), Infinity]) - - # Public: Moves the cursor to the beginning of the word. - moveToBeginningOfWord: -> - @setBufferPosition(@getBeginningOfCurrentWordBufferPosition()) - - # Public: Moves the cursor to the end of the word. - moveToEndOfWord: -> - if position = @getEndOfCurrentWordBufferPosition() - @setBufferPosition(position) - - # Public: Moves the cursor to the beginning of the next word. - moveToBeginningOfNextWord: -> - if position = @getBeginningOfNextWordBufferPosition() - @setBufferPosition(position) - - # Public: Moves the cursor to the previous word boundary. - moveToPreviousWordBoundary: -> - if position = @getPreviousWordBoundaryBufferPosition() - @setBufferPosition(position) - - # Public: Moves the cursor to the next word boundary. - moveToNextWordBoundary: -> - if position = @getMoveNextWordBoundaryBufferPosition() - @setBufferPosition(position) - # Public: Retrieves the buffer position of where the current word starts. # # * `options` (optional) An {Object} with the following keys: From a33706ddbcffa7ad53137973fbabcf8419625af0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:42:12 -0600 Subject: [PATCH 054/135] 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 713d82a89571c721faff5b69db3da7479cf9fc49 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:51:31 -0700 Subject: [PATCH 055/135] Reorder selections section --- src/editor.coffee | 395 +++++++++++++++++++++++----------------------- 1 file changed, 199 insertions(+), 196 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 2939df441..ad7de8390 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1723,16 +1723,16 @@ class Editor extends Model deprecate("Use Editor::moveToBeginningOfPreviousParagraph() instead") @moveToBeginningOfPreviousParagraph() + # Extended: Get the most recently added {Cursor}. + getCursor: -> + _.last(@cursors) + # Extended: Returns the word surrounding the most recently added cursor. # # * `options` (optional) See {Cursor::getBeginningOfCurrentWordBufferPosition}. getWordUnderCursor: (options) -> @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) - # Extended: Get the most recently added {Cursor}. - getCursor: -> - _.last(@cursors) - # Extended: Get an Array of all {Cursor}s. getCursors: -> new Array(@cursors...) @@ -1791,41 +1791,26 @@ class Editor extends Model Section: Selections ### - # Add a {Selection} based on the given {DisplayBufferMarker}. + # Public: Get the selected text of the most recently added selection. # - # * `marker` The {DisplayBufferMarker} to highlight - # * `options` (optional) An {Object} that pertains to the {Selection} constructor. - # - # Returns the new {Selection}. - addSelection: (marker, options={}) -> - unless marker.getAttributes().preserveFolds - @destroyFoldsIntersectingBufferRange(marker.getBufferRange()) - cursor = @addCursor(marker) - selection = new Selection(_.extend({editor: this, marker, cursor}, options)) - @selections.push(selection) - selectionBufferRange = selection.getBufferRange() - @mergeIntersectingSelections() - if selection.destroyed - for selection in @getSelections() - if selection.intersectsBufferRange(selectionBufferRange) - return selection - else - @emit 'selection-added', selection - selection + # Returns a {String}. + getSelectedText: -> + @getLastSelection().getText() - # Public: Add a selection for the given range in buffer coordinates. + # Public: Get the {Range} of the most recently added selection in buffer + # coordinates. # - # * `bufferRange` A {Range} - # * `options` (optional) An options {Object}: - # * `reversed` A {Boolean} indicating whether to create the selection in a - # reversed orientation. + # Returns a {Range}. + getSelectedBufferRange: -> + @getLastSelection().getBufferRange() + + # Public: Get the {Range}s of all selections in buffer coordinates. # - # Returns the added {Selection}. - addSelectionForBufferRange: (bufferRange, options={}) -> - @markBufferRange(bufferRange, _.defaults(@getSelectionMarkerAttributes(), options)) - selection = @getLastSelection() - selection.autoscroll() if @manageScrollPosition - selection + # The ranges are sorted by their position in the buffer. + # + # Returns an {Array} of {Range}s. + getSelectedBufferRanges: -> + selection.getBufferRange() for selection in @getSelectionsOrderedByBufferPosition() # Public: Set the selected range in buffer coordinates. If there are multiple # selections, they are reduced to a single selection with the given range. @@ -1837,16 +1822,6 @@ class Editor extends Model setSelectedBufferRange: (bufferRange, options) -> @setSelectedBufferRanges([bufferRange], options) - # Public: Set the selected range in screen coordinates. If there are multiple - # selections, they are reduced to a single selection with the given range. - # - # * `screenRange` A {Range} or range-compatible {Array}. - # * `options` (optional) An options {Object}: - # * `reversed` A {Boolean} indicating whether to create the selection in a - # reversed orientation. - setSelectedScreenRange: (screenRange, options) -> - @setSelectedBufferRange(@bufferRangeForScreenRange(screenRange, options), options) - # Public: Set the selected ranges in buffer coordinates. If there are multiple # selections, they are replaced by new selections with the given ranges. # @@ -1868,78 +1843,6 @@ class Editor extends Model else @addSelectionForBufferRange(bufferRange, options) - # Remove the given selection. - removeSelection: (selection) -> - _.remove(@selections, selection) - @emit 'selection-removed', selection - - # Reduce one or more selections to a single empty selection based on the most - # recently added cursor. - clearSelections: -> - @consolidateSelections() - @getSelection().clear() - - # Reduce multiple selections to the most recently added selection. - consolidateSelections: -> - selections = @getSelections() - if selections.length > 1 - selection.destroy() for selection in selections[0...-1] - true - else - false - - selectionScreenRangeChanged: (selection) -> - @emit 'selection-screen-range-changed', selection - - # Public: Get current {Selection}s. - # - # Returns: An {Array} of {Selection}s. - getSelections: -> new Array(@selections...) - - selectionsForScreenRows: (startRow, endRow) -> - @getSelections().filter (selection) -> selection.intersectsScreenRowRange(startRow, endRow) - - # Public: Get the most recent {Selection} or the selection at the given - # index. - # - # * `index` (optional) The index of the selection to return, based on the order - # in which the selections were added. - # - # Returns a {Selection}. - # or the at the specified index. - getSelection: (index) -> - index ?= @selections.length - 1 - @selections[index] - - # Public: Get the most recently added {Selection}. - # - # Returns a {Selection}. - getLastSelection: -> - _.last(@selections) - - # Public: Get all {Selection}s, ordered by their position in the buffer - # instead of the order in which they were added. - # - # Returns an {Array} of {Selection}s. - getSelectionsOrderedByBufferPosition: -> - @getSelections().sort (a, b) -> a.compare(b) - - # Public: Get the last {Selection} based on its position in the buffer. - # - # Returns a {Selection}. - getLastSelectionInBuffer: -> - _.last(@getSelectionsOrderedByBufferPosition()) - - # Public: Determine if a given range in buffer coordinates intersects a - # selection. - # - # * `bufferRange` A {Range} or range-compatible {Array}. - # - # Returns a {Boolean}. - selectionIntersectsBufferRange: (bufferRange) -> - _.any @getSelections(), (selection) -> - selection.intersectsBufferRange(bufferRange) - # Public: Get the {Range} of the most recently added selection in screen # coordinates. # @@ -1947,21 +1850,6 @@ class Editor extends Model getSelectedScreenRange: -> @getLastSelection().getScreenRange() - # Public: Get the {Range} of the most recently added selection in buffer - # coordinates. - # - # Returns a {Range}. - getSelectedBufferRange: -> - @getLastSelection().getBufferRange() - - # Public: Get the {Range}s of all selections in buffer coordinates. - # - # The ranges are sorted by their position in the buffer. - # - # Returns an {Array} of {Range}s. - getSelectedBufferRanges: -> - selection.getBufferRange() for selection in @getSelectionsOrderedByBufferPosition() - # Public: Get the {Range}s of all selections in screen coordinates. # # The ranges are sorted by their position in the buffer. @@ -1970,11 +1858,29 @@ class Editor extends Model getSelectedScreenRanges: -> selection.getScreenRange() for selection in @getSelectionsOrderedByBufferPosition() - # Public: Get the selected text of the most recently added selection. + # Public: Set the selected range in screen coordinates. If there are multiple + # selections, they are reduced to a single selection with the given range. # - # Returns a {String}. - getSelectedText: -> - @getLastSelection().getText() + # * `screenRange` A {Range} or range-compatible {Array}. + # * `options` (optional) An options {Object}: + # * `reversed` A {Boolean} indicating whether to create the selection in a + # reversed orientation. + setSelectedScreenRange: (screenRange, options) -> + @setSelectedBufferRange(@bufferRangeForScreenRange(screenRange, options), options) + + # Public: Add a selection for the given range in buffer coordinates. + # + # * `bufferRange` A {Range} + # * `options` (optional) An options {Object}: + # * `reversed` A {Boolean} indicating whether to create the selection in a + # reversed orientation. + # + # Returns the added {Selection}. + addSelectionForBufferRange: (bufferRange, options={}) -> + @markBufferRange(bufferRange, _.defaults(@getSelectionMarkerAttributes(), options)) + selection = @getLastSelection() + selection.autoscroll() if @manageScrollPosition + selection # Public: Select from the current cursor position to the given position in # screen coordinates. @@ -1987,20 +1893,6 @@ class Editor extends Model lastSelection.selectToScreenPosition(position) @mergeIntersectingSelections(reversed: lastSelection.isReversed()) - # Public: Move the cursor of each selection one character rightward while - # preserving the selection's tail position. - # - # This method may merge selections that end up intesecting. - selectRight: -> - @expandSelectionsForward (selection) -> selection.selectRight() - - # Public: Move the cursor of each selection one character leftward while - # preserving the selection's tail position. - # - # This method may merge selections that end up intesecting. - selectLeft: -> - @expandSelectionsBackward (selection) -> selection.selectLeft() - # Public: Move the cursor of each selection one character upward while # preserving the selection's tail position. # @@ -2015,6 +1907,20 @@ class Editor extends Model selectDown: (rowCount) -> @expandSelectionsForward (selection) -> selection.selectDown(rowCount) + # Public: Move the cursor of each selection one character leftward while + # preserving the selection's tail position. + # + # This method may merge selections that end up intesecting. + selectLeft: -> + @expandSelectionsBackward (selection) -> selection.selectLeft() + + # Public: Move the cursor of each selection one character rightward while + # preserving the selection's tail position. + # + # This method may merge selections that end up intesecting. + selectRight: -> + @expandSelectionsForward (selection) -> selection.selectRight() + # Public: Select from the top of the buffer to the end of the last selection # in the buffer. # @@ -2058,48 +1964,6 @@ class Editor extends Model selectToEndOfLine: -> @expandSelectionsForward (selection) -> selection.selectToEndOfLine() - # Public: For each selection, move its cursor to the preceding word boundary - # while maintaining the selection's tail position. - # - # This method may merge selections that end up intersecting. - selectToPreviousWordBoundary: -> - @expandSelectionsBackward (selection) -> selection.selectToPreviousWordBoundary() - - # Public: For each selection, move its cursor to the next word boundary while - # maintaining the selection's tail position. - # - # This method may merge selections that end up intersecting. - selectToNextWordBoundary: -> - @expandSelectionsForward (selection) -> selection.selectToNextWordBoundary() - - # Public: For each cursor, select the containing line. - # - # This method merges selections on successive lines. - selectLine: -> - @expandSelectionsForward (selection) -> selection.selectLine() - - # Public: Add a similarly-shaped selection to the next eligible line below - # each selection. - # - # Operates on all selections. If the selection is empty, adds an empty - # selection to the next following non-empty line as close to the current - # selection's column as possible. If the selection is non-empty, adds a - # selection to the next line that is long enough for a non-empty selection - # starting at the same column as the current selection to be added to it. - addSelectionBelow: -> - @expandSelectionsForward (selection) -> selection.addSelectionBelow() - - # Public: Add a similarly-shaped selection to the next eligible line above - # each selection. - # - # Operates on all selections. If the selection is empty, adds an empty - # selection to the next preceding non-empty line as close to the current - # selection's column as possible. If the selection is non-empty, adds a - # selection to the next line that is long enough for a non-empty selection - # starting at the same column as the current selection to be added to it. - addSelectionAbove: -> - @expandSelectionsBackward (selection) -> selection.addSelectionAbove() - # Public: Expand selections to the beginning of their containing word. # # Operates on all selections. Moves the cursor to the beginning of the @@ -2114,6 +1978,32 @@ class Editor extends Model selectToEndOfWord: -> @expandSelectionsForward (selection) -> selection.selectToEndOfWord() + # Public: For each cursor, select the containing line. + # + # This method merges selections on successive lines. + selectLine: -> + @expandSelectionsForward (selection) -> selection.selectLine() + + # Public: Select the word containing each cursor. + selectWord: -> + @expandSelectionsForward (selection) -> selection.selectWord() + + # Selection Extended + + # Public: For each selection, move its cursor to the preceding word boundary + # while maintaining the selection's tail position. + # + # This method may merge selections that end up intersecting. + selectToPreviousWordBoundary: -> + @expandSelectionsBackward (selection) -> selection.selectToPreviousWordBoundary() + + # Public: For each selection, move its cursor to the next word boundary while + # maintaining the selection's tail position. + # + # This method may merge selections that end up intersecting. + selectToNextWordBoundary: -> + @expandSelectionsForward (selection) -> selection.selectToNextWordBoundary() + # Public: Expand selections to the beginning of the next word. # # Operates on all selections. Moves the cursor to the beginning of the next @@ -2121,10 +2011,6 @@ class Editor extends Model selectToBeginningOfNextWord: -> @expandSelectionsForward (selection) -> selection.selectToBeginningOfNextWord() - # Public: Select the word containing each cursor. - selectWord: -> - @expandSelectionsForward (selection) -> selection.selectWord() - # Public: Expand selections to the beginning of the next paragraph. # # Operates on all selections. Moves the cursor to the beginning of the next @@ -2150,6 +2036,76 @@ class Editor extends Model @setSelectedBufferRange(range) range + # Public: Get the most recently added {Selection}. + # + # Returns a {Selection}. + getLastSelection: -> + _.last(@selections) + + # Public: Get the most recent {Selection} or the selection at the given + # index. + # + # * `index` (optional) The index of the selection to return, based on the order + # in which the selections were added. + # + # Returns a {Selection}. + # or the at the specified index. + getSelection: (index) -> + index ?= @selections.length - 1 + @selections[index] + + # Public: Get current {Selection}s. + # + # Returns: An {Array} of {Selection}s. + getSelections: -> new Array(@selections...) + + # Public: Get all {Selection}s, ordered by their position in the buffer + # instead of the order in which they were added. + # + # Returns an {Array} of {Selection}s. + getSelectionsOrderedByBufferPosition: -> + @getSelections().sort (a, b) -> a.compare(b) + + # Public: Get the last {Selection} based on its position in the buffer. + # + # Returns a {Selection}. + getLastSelectionInBuffer: -> + _.last(@getSelectionsOrderedByBufferPosition()) + + # Public: Determine if a given range in buffer coordinates intersects a + # selection. + # + # * `bufferRange` A {Range} or range-compatible {Array}. + # + # Returns a {Boolean}. + selectionIntersectsBufferRange: (bufferRange) -> + _.any @getSelections(), (selection) -> + selection.intersectsBufferRange(bufferRange) + + # Selections Private + + # Public: Add a similarly-shaped selection to the next eligible line below + # each selection. + # + # Operates on all selections. If the selection is empty, adds an empty + # selection to the next following non-empty line as close to the current + # selection's column as possible. If the selection is non-empty, adds a + # selection to the next line that is long enough for a non-empty selection + # starting at the same column as the current selection to be added to it. + addSelectionBelow: -> + @expandSelectionsForward (selection) -> selection.addSelectionBelow() + + # Public: Add a similarly-shaped selection to the next eligible line above + # each selection. + # + # Operates on all selections. If the selection is empty, adds an empty + # selection to the next preceding non-empty line as close to the current + # selection's column as possible. If the selection is non-empty, adds a + # selection to the next line that is long enough for a non-empty selection + # starting at the same column as the current selection to be added to it. + addSelectionAbove: -> + @expandSelectionsBackward (selection) -> selection.addSelectionAbove() + # Calls the given function with each selection, then merges selections expandSelectionsForward: (fn) -> @mergeIntersectingSelections => @@ -2164,6 +2120,9 @@ class Editor extends Model finalizeSelections: -> selection.finalize() for selection in @getSelections() + selectionsForScreenRows: (startRow, endRow) -> + @getSelections().filter (selection) -> selection.intersectsScreenRowRange(startRow, endRow) + # Merges intersecting selections. If passed a function, it executes # the function with merging suppressed, then merges intersecting selections # afterward. @@ -2188,6 +2147,50 @@ class Editor extends Model _.reduce(@getSelections(), reducer, []) + # Add a {Selection} based on the given {DisplayBufferMarker}. + # + # * `marker` The {DisplayBufferMarker} to highlight + # * `options` (optional) An {Object} that pertains to the {Selection} constructor. + # + # Returns the new {Selection}. + addSelection: (marker, options={}) -> + unless marker.getAttributes().preserveFolds + @destroyFoldsIntersectingBufferRange(marker.getBufferRange()) + cursor = @addCursor(marker) + selection = new Selection(_.extend({editor: this, marker, cursor}, options)) + @selections.push(selection) + selectionBufferRange = selection.getBufferRange() + @mergeIntersectingSelections() + if selection.destroyed + for selection in @getSelections() + if selection.intersectsBufferRange(selectionBufferRange) + return selection + else + @emit 'selection-added', selection + selection + + # Remove the given selection. + removeSelection: (selection) -> + _.remove(@selections, selection) + @emit 'selection-removed', selection + + # Reduce one or more selections to a single empty selection based on the most + # recently added cursor. + clearSelections: -> + @consolidateSelections() + @getSelection().clear() + + # Reduce multiple selections to the most recently added selection. + consolidateSelections: -> + selections = @getSelections() + if selections.length > 1 + selection.destroy() for selection in selections[0...-1] + true + else + false + + selectionScreenRangeChanged: (selection) -> + @emit 'selection-screen-range-changed', selection ### From acb9bdaf330fbec27d2fec2a109898d4f140233f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 17:52:30 -0600 Subject: [PATCH 056/135] 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 882261e7825fd0eb7ffef9a04552135521696ed6 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:53:21 -0700 Subject: [PATCH 057/135] Break into Essential and extended --- src/editor.coffee | 72 +++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index ad7de8390..fbb97b79c 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1791,20 +1791,20 @@ class Editor extends Model Section: Selections ### - # Public: Get the selected text of the most recently added selection. + # Essential: Get the selected text of the most recently added selection. # # Returns a {String}. getSelectedText: -> @getLastSelection().getText() - # Public: Get the {Range} of the most recently added selection in buffer + # Essential: Get the {Range} of the most recently added selection in buffer # coordinates. # # Returns a {Range}. getSelectedBufferRange: -> @getLastSelection().getBufferRange() - # Public: Get the {Range}s of all selections in buffer coordinates. + # Essential: Get the {Range}s of all selections in buffer coordinates. # # The ranges are sorted by their position in the buffer. # @@ -1812,7 +1812,7 @@ class Editor extends Model getSelectedBufferRanges: -> selection.getBufferRange() for selection in @getSelectionsOrderedByBufferPosition() - # Public: Set the selected range in buffer coordinates. If there are multiple + # Essential: Set the selected range in buffer coordinates. If there are multiple # selections, they are reduced to a single selection with the given range. # # * `bufferRange` A {Range} or range-compatible {Array}. @@ -1822,7 +1822,7 @@ class Editor extends Model setSelectedBufferRange: (bufferRange, options) -> @setSelectedBufferRanges([bufferRange], options) - # Public: Set the selected ranges in buffer coordinates. If there are multiple + # Essential: Set the selected ranges in buffer coordinates. If there are multiple # selections, they are replaced by new selections with the given ranges. # # * `bufferRanges` An {Array} of {Range}s or range-compatible {Array}s. @@ -1843,14 +1843,14 @@ class Editor extends Model else @addSelectionForBufferRange(bufferRange, options) - # Public: Get the {Range} of the most recently added selection in screen + # Essential: Get the {Range} of the most recently added selection in screen # coordinates. # # Returns a {Range}. getSelectedScreenRange: -> @getLastSelection().getScreenRange() - # Public: Get the {Range}s of all selections in screen coordinates. + # Essential: Get the {Range}s of all selections in screen coordinates. # # The ranges are sorted by their position in the buffer. # @@ -1858,7 +1858,7 @@ class Editor extends Model getSelectedScreenRanges: -> selection.getScreenRange() for selection in @getSelectionsOrderedByBufferPosition() - # Public: Set the selected range in screen coordinates. If there are multiple + # Essential: Set the selected range in screen coordinates. If there are multiple # selections, they are reduced to a single selection with the given range. # # * `screenRange` A {Range} or range-compatible {Array}. @@ -1868,7 +1868,7 @@ class Editor extends Model setSelectedScreenRange: (screenRange, options) -> @setSelectedBufferRange(@bufferRangeForScreenRange(screenRange, options), options) - # Public: Add a selection for the given range in buffer coordinates. + # Essential: Add a selection for the given range in buffer coordinates. # # * `bufferRange` A {Range} # * `options` (optional) An options {Object}: @@ -1882,7 +1882,7 @@ class Editor extends Model selection.autoscroll() if @manageScrollPosition selection - # Public: Select from the current cursor position to the given position in + # Essential: Select from the current cursor position to the given position in # screen coordinates. # # This method may merge selections that end up intesecting. @@ -1893,62 +1893,62 @@ class Editor extends Model lastSelection.selectToScreenPosition(position) @mergeIntersectingSelections(reversed: lastSelection.isReversed()) - # Public: Move the cursor of each selection one character upward while + # Essential: Move the cursor of each selection one character upward while # preserving the selection's tail position. # # This method may merge selections that end up intesecting. selectUp: (rowCount) -> @expandSelectionsBackward (selection) -> selection.selectUp(rowCount) - # Public: Move the cursor of each selection one character downward while + # Essential: Move the cursor of each selection one character downward while # preserving the selection's tail position. # # This method may merge selections that end up intesecting. selectDown: (rowCount) -> @expandSelectionsForward (selection) -> selection.selectDown(rowCount) - # Public: Move the cursor of each selection one character leftward while + # Essential: Move the cursor of each selection one character leftward while # preserving the selection's tail position. # # This method may merge selections that end up intesecting. selectLeft: -> @expandSelectionsBackward (selection) -> selection.selectLeft() - # Public: Move the cursor of each selection one character rightward while + # Essential: Move the cursor of each selection one character rightward while # preserving the selection's tail position. # # This method may merge selections that end up intesecting. selectRight: -> @expandSelectionsForward (selection) -> selection.selectRight() - # Public: Select from the top of the buffer to the end of the last selection + # Essential: Select from the top of the buffer to the end of the last selection # in the buffer. # # This method merges multiple selections into a single selection. selectToTop: -> @expandSelectionsBackward (selection) -> selection.selectToTop() - # Public: Select all text in the buffer. + # Essential: Select all text in the buffer. # # This method merges multiple selections into a single selection. selectAll: -> @expandSelectionsForward (selection) -> selection.selectAll() - # Public: Selects from the top of the first selection in the buffer to the end + # Essential: Selects from the top of the first selection in the buffer to the end # of the buffer. # # This method merges multiple selections into a single selection. selectToBottom: -> @expandSelectionsForward (selection) -> selection.selectToBottom() - # Public: Move the cursor of each selection to the beginning of its line + # Essential: Move the cursor of each selection to the beginning of its line # while preserving the selection's tail position. # # This method may merge selections that end up intesecting. selectToBeginningOfLine: -> @expandSelectionsBackward (selection) -> selection.selectToBeginningOfLine() - # Public: Move the cursor of each selection to the first non-whitespace + # Essential: Move the cursor of each selection to the first non-whitespace # character of its line while preserving the selection's tail position. If the # cursor is already on the first character of the line, move it to the # beginning of the line. @@ -1957,75 +1957,75 @@ class Editor extends Model selectToFirstCharacterOfLine: -> @expandSelectionsBackward (selection) -> selection.selectToFirstCharacterOfLine() - # Public: Move the cursor of each selection to the end of its line while + # Essential: Move the cursor of each selection to the end of its line while # preserving the selection's tail position. # # This method may merge selections that end up intersecting. selectToEndOfLine: -> @expandSelectionsForward (selection) -> selection.selectToEndOfLine() - # Public: Expand selections to the beginning of their containing word. + # Essential: Expand selections to the beginning of their containing word. # # Operates on all selections. Moves the cursor to the beginning of the # containing word while preserving the selection's tail position. selectToBeginningOfWord: -> @expandSelectionsBackward (selection) -> selection.selectToBeginningOfWord() - # Public: Expand selections to the end of their containing word. + # Essential: Expand selections to the end of their containing word. # # Operates on all selections. Moves the cursor to the end of the containing # word while preserving the selection's tail position. selectToEndOfWord: -> @expandSelectionsForward (selection) -> selection.selectToEndOfWord() - # Public: For each cursor, select the containing line. + # Essential: For each cursor, select the containing line. # # This method merges selections on successive lines. selectLine: -> @expandSelectionsForward (selection) -> selection.selectLine() - # Public: Select the word containing each cursor. + # Essential: Select the word containing each cursor. selectWord: -> @expandSelectionsForward (selection) -> selection.selectWord() # Selection Extended - # Public: For each selection, move its cursor to the preceding word boundary + # Extended: For each selection, move its cursor to the preceding word boundary # while maintaining the selection's tail position. # # This method may merge selections that end up intersecting. selectToPreviousWordBoundary: -> @expandSelectionsBackward (selection) -> selection.selectToPreviousWordBoundary() - # Public: For each selection, move its cursor to the next word boundary while + # Extended: For each selection, move its cursor to the next word boundary while # maintaining the selection's tail position. # # This method may merge selections that end up intersecting. selectToNextWordBoundary: -> @expandSelectionsForward (selection) -> selection.selectToNextWordBoundary() - # Public: Expand selections to the beginning of the next word. + # Extended: Expand selections to the beginning of the next word. # # Operates on all selections. Moves the cursor to the beginning of the next # word while preserving the selection's tail position. selectToBeginningOfNextWord: -> @expandSelectionsForward (selection) -> selection.selectToBeginningOfNextWord() - # Public: Expand selections to the beginning of the next paragraph. + # Extended: Expand selections to the beginning of the next paragraph. # # Operates on all selections. Moves the cursor to the beginning of the next # paragraph while preserving the selection's tail position. selectToBeginningOfNextParagraph: -> @expandSelectionsForward (selection) -> selection.selectToBeginningOfNextParagraph() - # Public: Expand selections to the beginning of the next paragraph. + # Extended: Expand selections to the beginning of the next paragraph. # # Operates on all selections. Moves the cursor to the beginning of the next # paragraph while preserving the selection's tail position. selectToBeginningOfPreviousParagraph: -> @expandSelectionsBackward (selection) -> selection.selectToBeginningOfPreviousParagraph() - # Public: Select the range of the given marker if it is valid. + # Extended: Select the range of the given marker if it is valid. # # * `marker` A {DisplayBufferMarker} # @@ -2036,13 +2036,13 @@ class Editor extends Model @setSelectedBufferRange(range) range - # Public: Get the most recently added {Selection}. + # Extended: Get the most recently added {Selection}. # # Returns a {Selection}. getLastSelection: -> _.last(@selections) - # Public: Get the most recent {Selection} or the selection at the given + # Extended: Get the most recent {Selection} or the selection at the given # index. # # * `index` (optional) The index of the selection to return, based on the order @@ -2054,25 +2054,25 @@ class Editor extends Model index ?= @selections.length - 1 @selections[index] - # Public: Get current {Selection}s. + # Extended: Get current {Selection}s. # # Returns: An {Array} of {Selection}s. getSelections: -> new Array(@selections...) - # Public: Get all {Selection}s, ordered by their position in the buffer + # Extended: Get all {Selection}s, ordered by their position in the buffer # instead of the order in which they were added. # # Returns an {Array} of {Selection}s. getSelectionsOrderedByBufferPosition: -> @getSelections().sort (a, b) -> a.compare(b) - # Public: Get the last {Selection} based on its position in the buffer. + # Extended: Get the last {Selection} based on its position in the buffer. # # Returns a {Selection}. getLastSelectionInBuffer: -> _.last(@getSelectionsOrderedByBufferPosition()) - # Public: Determine if a given range in buffer coordinates intersects a + # Extended: Determine if a given range in buffer coordinates intersects a # selection. # # * `bufferRange` A {Range} or range-compatible {Array}. From 14dcf50683452af950c74d36fe4cfff4cb40129c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:53:44 -0700 Subject: [PATCH 058/135] De-public a couple unused methods --- src/editor.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index fbb97b79c..d3d7d649b 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2084,7 +2084,7 @@ class Editor extends Model # Selections Private - # Public: Add a similarly-shaped selection to the next eligible line below + # Add a similarly-shaped selection to the next eligible line below # each selection. # # Operates on all selections. If the selection is empty, adds an empty @@ -2095,7 +2095,7 @@ class Editor extends Model addSelectionBelow: -> @expandSelectionsForward (selection) -> selection.addSelectionBelow() - # Public: Add a similarly-shaped selection to the next eligible line above + # Add a similarly-shaped selection to the next eligible line above # each selection. # # Operates on all selections. If the selection is empty, adds an empty From 535724fa84972e093c6034ce13bf5fc2e567f30c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:58:59 -0700 Subject: [PATCH 059/135] Nothing uses this function, not internal nor packages. --- src/editor.coffee | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index d3d7d649b..5c7633b11 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2066,12 +2066,6 @@ class Editor extends Model getSelectionsOrderedByBufferPosition: -> @getSelections().sort (a, b) -> a.compare(b) - # Extended: Get the last {Selection} based on its position in the buffer. - # - # Returns a {Selection}. - getLastSelectionInBuffer: -> - _.last(@getSelectionsOrderedByBufferPosition()) - # Extended: Determine if a given range in buffer coordinates intersects a # selection. # From c6a76e6c62bf858538e3420549c3ae3cd949f70b Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 16:59:10 -0700 Subject: [PATCH 060/135] De public a non-used method --- src/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 5c7633b11..6ed2e4e53 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -642,7 +642,7 @@ class Editor extends Model selection.insertText(fn(text)) selection.setBufferRange(range) - # Public: Split multi-line selections into one selection per line. + # Split multi-line selections into one selection per line. # # Operates on all selections. This method breaks apart all multi-line # selections to create multiple single-line selections that cumulatively cover From 70a23b010762c68e0f6611e6d60671a08ea1a862 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 18:27:13 -0600 Subject: [PATCH 061/135] 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 062/135] 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 271af5dd9948fe2e3a06b95c5b787eaec3903f61 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 17:28:24 -0700 Subject: [PATCH 063/135] Add Editor::setSelectedScreenRanges() --- spec/editor-spec.coffee | 23 +++++++++++++++++++++++ src/editor.coffee | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index f2cf94142..007dc52f6 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1261,6 +1261,29 @@ describe "Editor", -> expect(editor.isFoldedAtBufferRow(1)).toBeTruthy() expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() + describe ".setSelectedScreenRanges(ranges)", -> + beforeEach -> + editor.foldBufferRow(4) + + it "clears existing selections and creates selections for each of the given ranges", -> + editor.setSelectedScreenRanges([[[3, 4], [3, 7]], [[5, 4], [5, 7]]]) + expect(editor.getSelectedBufferRanges()).toEqual [[[3, 4], [3, 7]], [[8, 4], [8, 7]]] + + editor.setSelectedScreenRanges([[[6, 2], [6, 4]]]) + expect(editor.getSelectedScreenRanges()).toEqual [[[6, 2], [6, 4]]] + + it "merges intersecting selections and unfolds the fold", -> + editor.setSelectedScreenRanges([[[2, 2], [3, 3]], [[3, 0], [5, 5]]]) + expect(editor.getSelectedScreenRanges()).toEqual [[[2, 2], [8, 5]]] + + it "recyles existing selection instances", -> + selection = editor.getSelection() + editor.setSelectedScreenRanges([[[2, 2], [3, 4]], [[4, 4], [5, 5]]]) + + [selection1, selection2] = editor.getSelections() + expect(selection1).toBe selection + expect(selection1.getScreenRange()).toEqual [[2, 2], [3, 4]] + describe ".setSelectedBufferRange(range)", -> describe "when the 'autoscroll' option is true", -> it "autoscrolls to the selection", -> diff --git a/src/editor.coffee b/src/editor.coffee index 6ed2e4e53..f405e88ad 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1868,6 +1868,27 @@ class Editor extends Model setSelectedScreenRange: (screenRange, options) -> @setSelectedBufferRange(@bufferRangeForScreenRange(screenRange, options), options) + # Essential: Set the selected ranges in screen coordinates. If there are multiple + # selections, they are replaced by new selections with the given ranges. + # + # * `screenRanges` An {Array} of {Range}s or range-compatible {Array}s. + # * `options` (optional) An options {Object}: + # * `reversed` A {Boolean} indicating whether to create the selection in a + # reversed orientation. + setSelectedScreenRanges: (screenRanges, options={}) -> + throw new Error("Passed an empty array to setSelectedScreenRanges") unless screenRanges.length + + selections = @getSelections() + selection.destroy() for selection in selections[screenRanges.length...] + + @mergeIntersectingSelections options, => + for screenRange, i in screenRanges + screenRange = Range.fromObject(screenRange) + if selections[i] + selections[i].setScreenRange(screenRange, options) + else + @addSelectionForScreenRange(screenRange, options) + # Essential: Add a selection for the given range in buffer coordinates. # # * `bufferRange` A {Range} @@ -1882,6 +1903,20 @@ class Editor extends Model selection.autoscroll() if @manageScrollPosition selection + # Essential: Add a selection for the given range in screen coordinates. + # + # * `screenRange` A {Range} + # * `options` (optional) An options {Object}: + # * `reversed` A {Boolean} indicating whether to create the selection in a + # reversed orientation. + # + # Returns the added {Selection}. + addSelectionForScreenRange: (screenRange, options={}) -> + @markScreenRange(screenRange, _.defaults(@getSelectionMarkerAttributes(), options)) + selection = @getLastSelection() + selection.autoscroll() if @manageScrollPosition + selection + # Essential: Select from the current cursor position to the given position in # screen coordinates. # From 2fced0c1bc854bb2ff37dbb333190945acb1819e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 17:51:16 -0700 Subject: [PATCH 064/135] Deprecate getSelection --- docs/your-first-package.md | 2 +- spec/editor-component-spec.coffee | 4 ++-- spec/editor-spec.coffee | 34 +++++++++++++++---------------- spec/selection-spec.coffee | 2 +- src/editor-component.coffee | 4 ++-- src/editor.coffee | 25 +++++++++++++++-------- 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/docs/your-first-package.md b/docs/your-first-package.md index 4fc41d044..02cb98379 100644 --- a/docs/your-first-package.md +++ b/docs/your-first-package.md @@ -132,7 +132,7 @@ inserting 'Hello, World!' convert the selected text to ASCII art. convert: -> # This assumes the active pane item is an editor editor = atom.workspace.activePaneItem - selection = editor.getSelection() + selection = editor.getLastSelection() figlet = require 'figlet' figlet selection.getText(), {font: "Larry 3D 2"}, (error, asciiArt) -> diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 7f3458172..c5332151b 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -814,8 +814,8 @@ describe "EditorComponent", -> it "does not render empty selections", -> editor.addSelectionForBufferRange([[2, 2], [2, 2]]) nextAnimationFrame() - expect(editor.getSelection(0).isEmpty()).toBe true - expect(editor.getSelection(1).isEmpty()).toBe true + expect(editor.getSelectionAtIndex(0).isEmpty()).toBe true + expect(editor.getSelectionAtIndex(1).isEmpty()).toBe true expect(componentNode.querySelectorAll('.selection').length).toBe 0 diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 007dc52f6..fc70df6fb 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -30,7 +30,7 @@ describe "Editor", -> expect(editor2.id).toBe editor.id expect(editor2.getBuffer().getPath()).toBe editor.getBuffer().getPath() expect(editor2.getSelectedBufferRanges()).toEqual [[[1, 2], [3, 4]], [[5, 6], [7, 5]]] - expect(editor2.getSelection(1).isReversed()).toBeTruthy() + expect(editor2.getSelectionAtIndex(1).isReversed()).toBeTruthy() expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy() editor2.destroy() @@ -88,11 +88,11 @@ describe "Editor", -> editor2 = editor.copy() expect(editor2.id).not.toBe editor.id expect(editor2.getSelectedBufferRanges()).toEqual editor.getSelectedBufferRanges() - expect(editor2.getSelection(1).isReversed()).toBeTruthy() + expect(editor2.getSelectionAtIndex(1).isReversed()).toBeTruthy() expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy() # editor2 can now diverge from its origin edit session - editor2.getSelection().setBufferRange([[2, 1], [4, 3]]) + editor2.getLastSelection().setBufferRange([[2, 1], [4, 3]]) expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges() editor2.unfoldBufferRow(4) expect(editor2.isFoldedAtBufferRow(4)).not.toBe editor.isFoldedAtBufferRow(4) @@ -863,7 +863,7 @@ describe "Editor", -> selection = null beforeEach -> - selection = editor.getSelection() + selection = editor.getLastSelection() describe ".selectUp/Down/Left/Right()", -> it "expands each selection to its cursor's new location", -> @@ -989,8 +989,8 @@ describe "Editor", -> editor.selectToTop() expect(editor.getCursors().length).toBe 1 expect(editor.getCursorBufferPosition()).toEqual [0,0] - expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [11,2]] - expect(editor.getSelection().isReversed()).toBeTruthy() + expect(editor.getLastSelection().getBufferRange()).toEqual [[0,0], [11,2]] + expect(editor.getLastSelection().isReversed()).toBeTruthy() describe ".selectToBottom()", -> it "selects text from cusor position to the bottom of the buffer", -> @@ -999,13 +999,13 @@ describe "Editor", -> editor.selectToBottom() expect(editor.getCursors().length).toBe 1 expect(editor.getCursorBufferPosition()).toEqual [12,2] - expect(editor.getSelection().getBufferRange()).toEqual [[9,3], [12,2]] - expect(editor.getSelection().isReversed()).toBeFalsy() + expect(editor.getLastSelection().getBufferRange()).toEqual [[9,3], [12,2]] + expect(editor.getLastSelection().isReversed()).toBeFalsy() describe ".selectAll()", -> it "selects the entire buffer", -> editor.selectAll() - expect(editor.getSelection().getBufferRange()).toEqual buffer.getRange() + expect(editor.getLastSelection().getBufferRange()).toEqual buffer.getRange() describe ".selectToBeginningOfLine()", -> it "selects text from cusor position to beginning of line", -> @@ -1231,7 +1231,7 @@ describe "Editor", -> expect(editor.getSelectedBufferRanges()).toEqual [[[2, 2], [5, 5]]] it "recyles existing selection instances", -> - selection = editor.getSelection() + selection = editor.getLastSelection() editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]]) [selection1, selection2] = editor.getSelections() @@ -1277,7 +1277,7 @@ describe "Editor", -> expect(editor.getSelectedScreenRanges()).toEqual [[[2, 2], [8, 5]]] it "recyles existing selection instances", -> - selection = editor.getSelection() + selection = editor.getLastSelection() editor.setSelectedScreenRanges([[[2, 2], [3, 4]], [[4, 4], [5, 5]]]) [selection1, selection2] = editor.getSelections() @@ -1507,7 +1507,7 @@ describe "Editor", -> describe ".consolidateSelections()", -> it "destroys all selections but the most recent, returning true if any selections were destroyed", -> editor.setSelectedBufferRange([[3, 16], [3, 21]]) - selection1 = editor.getSelection() + selection1 = editor.getLastSelection() selection2 = editor.addSelectionForBufferRange([[3, 25], [3, 34]]) selection3 = editor.addSelectionForBufferRange([[8, 4], [8, 10]]) @@ -2172,7 +2172,7 @@ describe "Editor", -> editor.delete() expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {' expect(buffer.lineForRow(2)).toBe 'if (items.length <= 1) return items;' - expect(editor.getSelection().isEmpty()).toBeTruthy() + expect(editor.getLastSelection().isEmpty()).toBeTruthy() describe "when there are multiple selections", -> describe "when selections are on the same line", -> @@ -2295,7 +2295,7 @@ describe "Editor", -> describe "when the selection is not empty", -> it "indents the selected lines", -> editor.setSelectedBufferRange([[0, 0], [10, 0]]) - selection = editor.getSelection() + selection = editor.getLastSelection() spyOn(selection, "indentSelectedRows") editor.indent() expect(selection.indentSelectedRows).toHaveBeenCalled() @@ -2588,7 +2588,7 @@ describe "Editor", -> it "preserves selection emptiness", -> editor.setCursorBufferPosition([4, 0]) editor.toggleLineCommentsInSelection() - expect(editor.getSelection().isEmpty()).toBeTruthy() + expect(editor.getLastSelection().isEmpty()).toBeTruthy() it "does not explode if the current language mode has no comment regex", -> editor.destroy() @@ -2979,7 +2979,7 @@ describe "Editor", -> editor.insertText(text) numberOfNewlines = text.match(/\n/g)?.length endColumn = text.match(/[^\n]*$/)[0]?.length - editor.getSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]]) + editor.getLastSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]]) editor.cutSelectedText() describe "editor.autoIndent", -> @@ -3139,7 +3139,7 @@ describe "Editor", -> it "autoIndentSelectedRows auto-indents the selection", -> editor.setCursorBufferPosition([2, 0]) editor.insertText("function() {\ninside=true\n}\n i=1\n") - editor.getSelection().setBufferRange([[2,0], [6,0]]) + editor.getLastSelection().setBufferRange([[2,0], [6,0]]) editor.autoIndentSelectedRows() expect(editor.lineForBufferRow(2)).toBe " function() {" diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index 2448cbc02..020dffa86 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -6,7 +6,7 @@ describe "Selection", -> beforeEach -> buffer = atom.project.bufferForPathSync('sample.js') editor = new Editor(buffer: buffer, tabLength: 2) - selection = editor.getSelection() + selection = editor.getLastSelection() afterEach -> buffer.destroy() diff --git a/src/editor-component.coffee b/src/editor-component.coffee index be7eb57aa..ccbac195c 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -51,7 +51,7 @@ EditorComponent = React.createClass {focused, showIndentGuide, showLineNumbers, visible} = @state {editor, mini, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props maxLineNumberDigits = editor.getLineCount().toString().length - hasSelection = editor.getSelection()? and !editor.getSelection().isEmpty() + hasSelection = editor.getLastSelection()? and !editor.getLastSelection().isEmpty() style = {} if @performedInitialMeasurement @@ -661,7 +661,7 @@ EditorComponent = React.createClass onGutterShiftClick: (event) -> {editor} = @props clickedRow = @screenPositionForMouseEvent(event).row - tailPosition = editor.getSelection().getTailScreenPosition() + tailPosition = editor.getLastSelection().getTailScreenPosition() if clickedRow < tailPosition.row editor.selectToScreenPosition([clickedRow, 0]) diff --git a/src/editor.coffee b/src/editor.coffee index f405e88ad..0c2f403cb 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2077,22 +2077,29 @@ class Editor extends Model getLastSelection: -> _.last(@selections) - # Extended: Get the most recent {Selection} or the selection at the given - # index. + # Extended: Gets the selection at the given index. # - # * `index` (optional) The index of the selection to return, based on the order - # in which the selections were added. + # * `index` The index of the selection to return, based on the order in which + # the selections were added. # # Returns a {Selection}. - # or the at the specified index. - getSelection: (index) -> - index ?= @selections.length - 1 + getSelectionAtIndex: (index) -> @selections[index] + # Deprecated: + getSelection: (index) -> + if index? + deprecate("Use Editor::getSelectionAtIndex(index) instead when getting a specific selection at an index") + @getSelectionAtIndex(index) + else + deprecate("Use Editor::getLastSelection() instead") + @getLastSelection() + # Extended: Get current {Selection}s. # # Returns: An {Array} of {Selection}s. - getSelections: -> new Array(@selections...) + getSelections: -> + selection for selection in @selections # Extended: Get all {Selection}s, ordered by their position in the buffer # instead of the order in which they were added. @@ -2207,7 +2214,7 @@ class Editor extends Model # recently added cursor. clearSelections: -> @consolidateSelections() - @getSelection().clear() + @getLastSelection().clear() # Reduce multiple selections to the most recently added selection. consolidateSelections: -> From c9e5ff66061788135bcb9ee49640863d1964fa0a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Aug 2014 19:06:57 -0600 Subject: [PATCH 065/135] 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 9c53d6f014f011955f5e6ab7f53d501fada22402 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 18:10:18 -0700 Subject: [PATCH 066/135] Deprecate getCursor() --- spec/editor-component-spec.coffee | 4 +-- spec/editor-spec.coffee | 60 +++++++++++++++---------------- src/cursor.coffee | 2 +- src/editor-component.coffee | 4 +-- src/editor.coffee | 30 +++++++++------- 5 files changed, 53 insertions(+), 47 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index c5332151b..00793dbf2 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -601,7 +601,7 @@ describe "EditorComponent", -> describe "cursor rendering", -> it "renders the currently visible cursors, translated relative to the scroll position", -> - cursor1 = editor.getCursor() + cursor1 = editor.getLastCursor() cursor1.setScreenPosition([0, 5]) wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px' @@ -1437,7 +1437,7 @@ describe "EditorComponent", -> cursor = null beforeEach -> - cursor = editor.getCursor() + cursor = editor.getLastCursor() cursor.setScreenPosition([0, 0]) it "adds the 'has-selection' class to the editor when there is a selection", -> diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index fc70df6fb..fa59c59b0 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -63,8 +63,8 @@ describe "Editor", -> runs -> buffer = editor.buffer - expect(editor.getCursor().getBufferPosition().row).toEqual 5 - expect(editor.getCursor().getBufferPosition().column).toEqual 0 + expect(editor.getLastCursor().getBufferPosition().row).toEqual 5 + expect(editor.getLastCursor().getBufferPosition().column).toEqual 0 describe "when the editor is constructed with an initialColumn option", -> it "positions the cursor on the specified column", -> @@ -75,8 +75,8 @@ describe "Editor", -> runs -> buffer = editor.buffer - expect(editor.getCursor().getBufferPosition().row).toEqual 0 - expect(editor.getCursor().getBufferPosition().column).toEqual 8 + expect(editor.getLastCursor().getBufferPosition().row).toEqual 0 + expect(editor.getLastCursor().getBufferPosition().column).toEqual 8 describe ".copy()", -> it "returns a different edit session with the same initial state", -> @@ -147,11 +147,11 @@ describe "Editor", -> expect(titleChangedHandler.callCount).toBe 2 describe "cursor", -> - describe ".getCursor()", -> + describe ".getLastCursor()", -> it "returns the most recently created cursor", -> editor.addCursorAtScreenPosition([1, 0]) lastCursor = editor.addCursorAtScreenPosition([2, 0]) - expect(editor.getCursor()).toBe lastCursor + expect(editor.getLastCursor()).toBe lastCursor describe "when the cursor moves", -> it "clears a goal column established by vertical movement", -> @@ -175,7 +175,7 @@ describe "Editor", -> expect(cursorsMovedHandler.callCount).toBe 1 cursorsMovedHandler.reset() - editor.getCursor().moveDown() + editor.getLastCursor().moveDown() expect(cursorsMovedHandler.callCount).toBe 1 describe ".setCursorScreenPosition(screenPosition)", -> @@ -244,7 +244,7 @@ describe "Editor", -> editor.setSelectedBufferRange([[4, 9],[5, 10]]) it "moves above the selection", -> - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveUp() expect(cursor.getBufferPosition()).toEqual [3, 9] @@ -302,7 +302,7 @@ describe "Editor", -> editor.setSelectedBufferRange([[4, 9],[5, 10]]) it "moves below the selection", -> - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveDown() expect(cursor.getBufferPosition()).toEqual [6, 10] @@ -346,7 +346,7 @@ describe "Editor", -> editor.setSelectedBufferRange([[5, 22],[5, 27]]) it "moves to the left of the selection", -> - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveLeft() expect(cursor.getBufferPosition()).toEqual [5, 22] @@ -392,7 +392,7 @@ describe "Editor", -> editor.setSelectedBufferRange([[5, 22],[5, 27]]) it "moves to the left of the selection", -> - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveRight() expect(cursor.getBufferPosition()).toEqual [5, 27] @@ -431,7 +431,7 @@ describe "Editor", -> editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToBeginningOfScreenLine() - cursor = editor.getCursor() + cursor = editor.getLastCursor() expect(cursor.getScreenPosition()).toEqual [1, 0] describe "when soft wrap is off", -> @@ -451,7 +451,7 @@ describe "Editor", -> editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToEndOfScreenLine() - cursor = editor.getCursor() + cursor = editor.getLastCursor() expect(cursor.getScreenPosition()).toEqual [1, 9] describe "when soft wrap is off", -> @@ -470,7 +470,7 @@ describe "Editor", -> editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([1, 2]) editor.moveToBeginningOfLine() - cursor = editor.getCursor() + cursor = editor.getLastCursor() expect(cursor.getScreenPosition()).toEqual [0, 0] describe ".moveToEndOfLine()", -> @@ -479,7 +479,7 @@ describe "Editor", -> editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([0, 2]) editor.moveToEndOfLine() - cursor = editor.getCursor() + cursor = editor.getLastCursor() expect(cursor.getScreenPosition()).toEqual [3, 4] describe ".moveToFirstCharacterOfLine()", -> @@ -517,7 +517,7 @@ describe "Editor", -> editor.setText("first\n \nthird") editor.setCursorScreenPosition [1,2] editor.moveToFirstCharacterOfLine() - cursor = editor.getCursor() + cursor = editor.getLastCursor() expect(cursor.getBufferPosition()).toEqual [1,0] describe "when invisible characters are enabled with soft tabs", -> @@ -642,7 +642,7 @@ describe "Editor", -> # When the cursor is on whitespace editor.setText("ab cde- ") editor.setCursorBufferPosition [0,2] - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveToBeginningOfNextWord() expect(cursor.getBufferPosition()).toEqual [0, 3] @@ -666,7 +666,7 @@ describe "Editor", -> describe ".moveToBeginningOfNextParagraph()", -> it "moves the cursor before the first line of the next paragraph", -> editor.setCursorBufferPosition [0,6] - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveToBeginningOfNextParagraph() @@ -674,7 +674,7 @@ describe "Editor", -> editor.setText("") editor.setCursorBufferPosition [0,0] - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveToBeginningOfNextParagraph() expect(cursor.getBufferPosition()).toEqual [0, 0] @@ -682,7 +682,7 @@ describe "Editor", -> describe ".moveToBeginningOfPreviousParagraph()", -> it "moves the cursor before the first line of the pevious paragraph", -> editor.setCursorBufferPosition [10,0] - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveToBeginningOfPreviousParagraph() @@ -690,7 +690,7 @@ describe "Editor", -> editor.setText("") editor.setCursorBufferPosition [0,0] - cursor = editor.getCursor() + cursor = editor.getLastCursor() editor.moveToBeginningOfPreviousParagraph() expect(cursor.getBufferPosition()).toEqual [0, 0] @@ -765,7 +765,7 @@ describe "Editor", -> describe "::getCursorsOrderedByBufferPosition()", -> it "returns all cursors ordered by buffer positions", -> - originalCursor = editor.getCursor() + originalCursor = editor.getLastCursor() cursor1 = editor.addCursorAtBufferPosition([8, 5]) cursor2 = editor.addCursorAtBufferPosition([4, 5]) expect(editor.getCursorsOrderedByBufferPosition()).toEqual [originalCursor, cursor2, cursor1] @@ -1844,7 +1844,7 @@ describe "Editor", -> expect(line).toBe " var ort = function(items) {" expect(editor.getCursorScreenPosition()).toEqual {row: 1, column: 6} expect(changeScreenRangeHandler).toHaveBeenCalled() - expect(editor.getCursor().isVisible()).toBeTruthy() + expect(editor.getLastCursor().isVisible()).toBeTruthy() describe "when the cursor is at the beginning of a line", -> it "joins it with the line above", -> @@ -2731,7 +2731,7 @@ describe "Editor", -> expect(cursor3.getScreenPosition()).toEqual [1, 0] it "does not destroy cursors or selections when a change encompasses them", -> - cursor = editor.getCursor() + cursor = editor.getLastCursor() cursor.setBufferPosition [3, 3] editor.buffer.delete([[3, 1], [3, 5]]) expect(cursor.getBufferPosition()).toEqual [3, 1] @@ -2760,7 +2760,7 @@ describe "Editor", -> describe ".deleteLine()", -> it "deletes the first line when the cursor is there", -> - editor.getCursor().moveToTop() + editor.getLastCursor().moveToTop() line1 = buffer.lineForRow(1) count = buffer.getLineCount() expect(buffer.lineForRow(0)).not.toBe(line1) @@ -2772,7 +2772,7 @@ describe "Editor", -> count = buffer.getLineCount() secondToLastLine = buffer.lineForRow(count - 2) expect(buffer.lineForRow(count - 1)).not.toBe(secondToLastLine) - editor.getCursor().moveToBottom() + editor.getLastCursor().moveToBottom() editor.deleteLine() newCount = buffer.getLineCount() expect(buffer.lineForRow(newCount - 1)).toBe(secondToLastLine) @@ -2799,8 +2799,8 @@ describe "Editor", -> it "deletes the entire region when invoke on a folded region", -> editor.foldBufferRow(1) - editor.getCursor().moveToTop() - editor.getCursor().moveDown() + editor.getLastCursor().moveToTop() + editor.getLastCursor().moveDown() expect(buffer.getLineCount()).toBe(13) editor.deleteLine() expect(buffer.getLineCount()).toBe(4) @@ -2809,7 +2809,7 @@ describe "Editor", -> count = buffer.getLineCount() expect(count).toBeGreaterThan(0) for line in [0...count] - editor.getCursor().moveToBottom() + editor.getLastCursor().moveToBottom() editor.deleteLine() expect(buffer.getLineCount()).toBe(1) expect(buffer.getText()).toBe('') @@ -2818,7 +2818,7 @@ describe "Editor", -> count = buffer.getLineCount() expect(count).toBeGreaterThan(0) for line in [0...count] - editor.getCursor().moveToTop() + editor.getLastCursor().moveToTop() editor.deleteLine() expect(buffer.getLineCount()).toBe(1) expect(buffer.getText()).toBe('') diff --git a/src/cursor.coffee b/src/cursor.coffee index d4d0c54a0..4a0c4c79c 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -158,7 +158,7 @@ class Cursor extends Model # # Returns a {Boolean}. isLastCursor: -> - this == @editor.getCursor() + this == @editor.getLastCursor() # Public: Identifies if the cursor is surrounded by whitespace. # diff --git a/src/editor-component.coffee b/src/editor-component.coffee index ccbac195c..0bd82de70 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -258,9 +258,9 @@ EditorComponent = React.createClass getHiddenInputPosition: -> {editor} = @props {focused} = @state - return {top: 0, left: 0} unless @isMounted() and focused and editor.getCursor()? + return {top: 0, left: 0} unless @isMounted() and focused and editor.getLastCursor()? - {top, left, height, width} = editor.getCursor().getPixelRect() + {top, left, height, width} = editor.getLastCursor().getPixelRect() width = 2 if width is 0 # Prevent autoscroll at the end of longest line top -= editor.getScrollTop() left -= editor.getScrollLeft() diff --git a/src/editor.coffee b/src/editor.coffee index 0c2f403cb..1b50cbf0e 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -462,7 +462,7 @@ class Editor extends Model # # Returns a {Range}. getCurrentParagraphBufferRange: -> - @getCursor().getCurrentParagraphBufferRange() + @getLastCursor().getCurrentParagraphBufferRange() ### @@ -978,12 +978,12 @@ class Editor extends Model # Public: Undo the last change. undo: -> - @getCursor().needsAutoscroll = true + @getLastCursor().needsAutoscroll = true @buffer.undo(this) # Public: Redo the last change. redo: -> - @getCursor().needsAutoscroll = true + @getLastCursor().needsAutoscroll = true @buffer.redo(this) ### @@ -1159,7 +1159,7 @@ class Editor extends Model # position. See {::scopesForBufferPosition} for more information. # # Returns an {Array} of {String}s. - getCursorScopes: -> @getCursor().getScopes() + getCursorScopes: -> @getLastCursor().getScopes() logCursorScope: -> console.log @getCursorScopes() @@ -1217,7 +1217,7 @@ class Editor extends Model return else if atom.config.get("editor.normalizeIndentOnPaste") and metadata?.indentBasis? - if !@getCursor().hasPrecedingCharactersOnLine() or containsNewlines + if !@getLastCursor().hasPrecedingCharactersOnLine() or containsNewlines options.indentBasis ?= metadata.indentBasis @insertText(text, options) @@ -1515,7 +1515,7 @@ class Editor extends Model # # Returns a {Point} getCursorBufferPosition: -> - @getCursor().getBufferPosition() + @getLastCursor().getBufferPosition() # Essential: Get the position of all the cursor positions in buffer coordinates. # @@ -1539,7 +1539,7 @@ class Editor extends Model # # Returns a {Point}. getCursorScreenPosition: -> - @getCursor().getScreenPosition() + @getLastCursor().getScreenPosition() # Essential: Get the position of all the cursor positions in screen coordinates. # @@ -1723,18 +1723,24 @@ class Editor extends Model deprecate("Use Editor::moveToBeginningOfPreviousParagraph() instead") @moveToBeginningOfPreviousParagraph() - # Extended: Get the most recently added {Cursor}. - getCursor: -> + # Extended: Returns the most recently added {Cursor} + getLastCursor: -> _.last(@cursors) + # Deprecated: + getCursor: -> + deprecate("Use Editor::getLastCursor() instead") + @getLastCursor() + # Extended: Returns the word surrounding the most recently added cursor. # # * `options` (optional) See {Cursor::getBeginningOfCurrentWordBufferPosition}. getWordUnderCursor: (options) -> - @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) + @getTextInBufferRange(@getLastCursor().getCurrentWordBufferRange(options)) # Extended: Get an Array of all {Cursor}s. - getCursors: -> new Array(@cursors...) + getCursors: -> + cursor for cursor in @cursors # Extended: Get all {Cursors}s, ordered by their position in the buffer # instead of the order in which they were added. @@ -2239,7 +2245,7 @@ class Editor extends Model # * `options` (optional) {Object} # * `center` Center the editor around the cursor if possible. Defauls to true. scrollToCursorPosition: (options) -> - @getCursor().autoscroll(center: options?.center ? true) + @getLastCursor().autoscroll(center: options?.center ? true) pageUp: -> newScrollTop = @getScrollTop() - @getHeight() From 08388d87c0591e19fc4dce5836ec9f3009e30fde Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 18:16:33 -0700 Subject: [PATCH 067/135] Remove getSelectionAtIndex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We’re going to eventually get rid of the clone in getSelections / getCursors freeze those properties and return them directly. Then they can operate on the list garbage free. --- spec/editor-component-spec.coffee | 4 ++-- spec/editor-spec.coffee | 4 ++-- src/editor.coffee | 11 +---------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 00793dbf2..4d874eb0a 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -814,8 +814,8 @@ describe "EditorComponent", -> it "does not render empty selections", -> editor.addSelectionForBufferRange([[2, 2], [2, 2]]) nextAnimationFrame() - expect(editor.getSelectionAtIndex(0).isEmpty()).toBe true - expect(editor.getSelectionAtIndex(1).isEmpty()).toBe true + expect(editor.getSelections()[0].isEmpty()).toBe true + expect(editor.getSelections()[1].isEmpty()).toBe true expect(componentNode.querySelectorAll('.selection').length).toBe 0 diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index fa59c59b0..fae2bf1fc 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -30,7 +30,7 @@ describe "Editor", -> expect(editor2.id).toBe editor.id expect(editor2.getBuffer().getPath()).toBe editor.getBuffer().getPath() expect(editor2.getSelectedBufferRanges()).toEqual [[[1, 2], [3, 4]], [[5, 6], [7, 5]]] - expect(editor2.getSelectionAtIndex(1).isReversed()).toBeTruthy() + expect(editor2.getSelections()[1].isReversed()).toBeTruthy() expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy() editor2.destroy() @@ -88,7 +88,7 @@ describe "Editor", -> editor2 = editor.copy() expect(editor2.id).not.toBe editor.id expect(editor2.getSelectedBufferRanges()).toEqual editor.getSelectedBufferRanges() - expect(editor2.getSelectionAtIndex(1).isReversed()).toBeTruthy() + expect(editor2.getSelections()[1].isReversed()).toBeTruthy() expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy() # editor2 can now diverge from its origin edit session diff --git a/src/editor.coffee b/src/editor.coffee index 1b50cbf0e..9d3ba15f6 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2083,19 +2083,10 @@ class Editor extends Model getLastSelection: -> _.last(@selections) - # Extended: Gets the selection at the given index. - # - # * `index` The index of the selection to return, based on the order in which - # the selections were added. - # - # Returns a {Selection}. - getSelectionAtIndex: (index) -> - @selections[index] - # Deprecated: getSelection: (index) -> if index? - deprecate("Use Editor::getSelectionAtIndex(index) instead when getting a specific selection at an index") + deprecate("Use Editor::getSelections()[index] instead when getting a specific selection") @getSelectionAtIndex(index) else deprecate("Use Editor::getLastSelection() instead") From 5163d0f8108317c3d09fa622e582cff70bd85a41 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 18:19:12 -0700 Subject: [PATCH 068/135] Fix dupe functions --- src/cursor.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 4a0c4c79c..975ef9e11 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -251,9 +251,9 @@ class Cursor extends Model column = @goalColumn if @goalColumn? @setScreenPosition({row: row + rowCount, column: column}) @goalColumn = column - moveCursorUp: (rowCount=1, options) -> - deprecate("Use Cursor::moveUp() instead. `Cursor` has been removed from these methods.") - @moveUp(rowCount, options) + moveCursorDown: (rowCount=1, options) -> + deprecate("Use Cursor::moveDown() instead. `Cursor` has been removed from these methods.") + @moveDown(rowCount, options) # Public: Moves the cursor left one screen column. # @@ -268,9 +268,9 @@ class Cursor extends Model {row, column} = @getScreenPosition() [row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity] @setScreenPosition({row, column}) - moveCursorUp: (rowCount=1, options) -> - deprecate("Use Cursor::moveUp() instead. `Cursor` has been removed from these methods.") - @moveUp(rowCount, options) + moveCursorLeft: (rowCount=1, options) -> + deprecate("Use Cursor::moveLeft() instead. `Cursor` has been removed from these methods.") + @moveLeft(rowCount, options) # Public: Moves the cursor right one screen column. # From 4b4af946cfc5acd86347c1830d29ac32b9fa21a7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 28 Aug 2014 18:30:08 -0700 Subject: [PATCH 069/135] Fix specs --- src/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 9d3ba15f6..6aac1d646 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2087,7 +2087,7 @@ class Editor extends Model getSelection: (index) -> if index? deprecate("Use Editor::getSelections()[index] instead when getting a specific selection") - @getSelectionAtIndex(index) + @getSelections()[index] else deprecate("Use Editor::getLastSelection() instead") @getLastSelection() From 5a3698893012781f82055b721d2e5253fe62cccf Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 08:49:06 -0700 Subject: [PATCH 070/135] Upgrade to language-xml@0.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f92b4967..4d25b3d24 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "language-text": "0.6.0", "language-todo": "0.10.0", "language-toml": "0.12.0", - "language-xml": "0.18.0", + "language-xml": "0.19.0", "language-yaml": "0.17.0" }, "private": true, From 8fa8519924a2e05837ab2c2c737277cb578d9c8e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 08:56:04 -0700 Subject: [PATCH 071/135] Upgrade to language-python@0.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d25b3d24..5ee6fd0b7 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "language-perl": "0.9.0", "language-php": "0.15.0", "language-property-list": "0.7.0", - "language-python": "0.18.0", + "language-python": "0.19.0", "language-ruby": "0.35.0", "language-ruby-on-rails": "0.18.0", "language-sass": "0.20.0", From fbcef99aacaa4e50115984797479446f67c79dfe Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 09:04:49 -0700 Subject: [PATCH 072/135] Upgrade to language-todo@0.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ee6fd0b7..c95628f82 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "language-source": "0.8.0", "language-sql": "0.10.0", "language-text": "0.6.0", - "language-todo": "0.10.0", + "language-todo": "0.11.0", "language-toml": "0.12.0", "language-xml": "0.19.0", "language-yaml": "0.17.0" From c5aa446bc2bbaf426bacfdb14effe03e2c0b0220 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 2 Sep 2014 11:37:46 -0600 Subject: [PATCH 073/135] Prevent focusout events on hidden input when clicking focused editors Fixes #3384 This is achieved by calling .preventDefault() on mousedown events when the editor is already focused, which prevents the moving of focus to the editor itself. --- src/editor-component.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index b14a169b8..732a0da88 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -614,6 +614,9 @@ EditorComponent = React.createClass # CTRL+click brings up the context menu on OSX, so don't handle those either return if ctrlKey and process.platform is 'darwin' + # Prevent focusout event on hidden input if editor is already focused + event.preventDefault() if @state.focused + screenPosition = @screenPositionForMouseEvent(event) if event.target?.classList.contains('fold-marker') From 24add494ae0beb2948eb376bff61be824d636484 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 10:47:05 -0700 Subject: [PATCH 074/135] Normalize project path in Project::setPath This will remove consecutive slashes as well as . and .. characters and make path comparisons accurate. Closes atom/tree-view#191 --- spec/project-spec.coffee | 5 +++++ src/project.coffee | 1 + 2 files changed, 6 insertions(+) diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 09ad8fb91..06e3ee29d 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -190,6 +190,11 @@ describe "Project", -> expect(atom.project.getPath()?).toBeFalsy() expect(atom.project.getRootDirectory()?).toBeFalsy() + it "normalizes the path to remove consecutive slashes, ., and .. segments", -> + atom.project.setPath("#{require.resolve('./fixtures/dir/a')}#{path.sep}b#{path.sep}#{path.sep}..") + expect(atom.project.getPath()).toEqual path.dirname(require.resolve('./fixtures/dir/a')) + expect(atom.project.getRootDirectory().path).toEqual path.dirname(require.resolve('./fixtures/dir/a')) + describe ".replace()", -> [filePath, commentFilePath, sampleContent, sampleCommentContent] = [] diff --git a/src/project.coffee b/src/project.coffee index c0b81ddd0..bf2adf2c3 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -84,6 +84,7 @@ class Project extends Model # # * `projectPath` {String} path setPath: (projectPath) -> + projectPath = path.normalize(projectPath) if projectPath @path = projectPath @rootDirectory?.off() From 03a6d10703d611a63ee0dfa2689c929ef772bca9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 13:44:13 -0700 Subject: [PATCH 075/135] Upgrade to tree-view@0.114 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c95628f82..1ffb1091e 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "symbols-view": "0.63.0", "tabs": "0.50.0", "timecop": "0.22.0", - "tree-view": "0.113.0", + "tree-view": "0.114.0", "update-package-dependencies": "0.6.0", "welcome": "0.18.0", "whitespace": "0.25.0", From 1aa391a2075e8757cfc1b2418c758c3e0a07f25a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 13:50:20 -0700 Subject: [PATCH 076/135] Don't load ~/.atom/init.coffee in safe mode This ensures the code from the init script isn't causing issues when trying to reproduce something in safe mode. Refs #2772 --- src/atom.coffee | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 47bbbaa98..316fc945d 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -321,8 +321,9 @@ class Atom extends Model # Call this method when establishing a real application window. startEditorWindow: -> + {resourcePath, safeMode} = @getLoadSettings() + CommandInstaller = require './command-installer' - resourcePath = atom.getLoadSettings().resourcePath CommandInstaller.installAtomCommand resourcePath, false, (error) -> console.warn error.message if error? CommandInstaller.installApmCommand resourcePath, false, (error) -> @@ -341,7 +342,7 @@ class Atom extends Model @packages.activate() @keymaps.loadUserKeymap() - @requireUserInitScript() + @requireUserInitScript() unless safeMode @menu.update() maximize = dimensions?.maximized and process.platform isnt 'darwin' From 70af6198bdfc7147719a710c4d28d7b1b204a303 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 13:59:48 -0700 Subject: [PATCH 077/135] selectLine -> selectLinesContainingCursors --- spec/editor-spec.coffee | 10 +++++----- src/editor-component.coffee | 2 +- src/editor.coffee | 5 ++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index fae2bf1fc..76605519d 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1045,20 +1045,20 @@ describe "Editor", -> expect(selection2.getBufferRange()).toEqual [[11,3], [11,44]] expect(selection2.isReversed()).toBeFalsy() - describe ".selectLine()", -> + describe ".selectLinesContainingCursors()", -> it "selects the entire line (including newlines) at given row", -> editor.setCursorScreenPosition([1, 2]) - editor.selectLine() + editor.selectLinesContainingCursors() expect(editor.getSelectedBufferRange()).toEqual [[1,0], [2,0]] expect(editor.getSelectedText()).toBe " var sort = function(items) {\n" editor.setCursorScreenPosition([12, 2]) - editor.selectLine() + editor.selectLinesContainingCursors() expect(editor.getSelectedBufferRange()).toEqual [[12,0], [12,2]] editor.setCursorBufferPosition([0, 2]) - editor.selectLine() - editor.selectLine() + editor.selectLinesContainingCursors() + editor.selectLinesContainingCursors() expect(editor.getSelectedBufferRange()).toEqual [[0,0], [2,0]] describe ".selectToBeginningOfWord()", -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 0bd82de70..f31264dd2 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -446,7 +446,7 @@ EditorComponent = React.createClass 'editor:select-to-next-word-boundary': -> editor.selectToNextWordBoundary() 'editor:select-to-previous-word-boundary': -> editor.selectToPreviousWordBoundary() 'editor:select-to-first-character-of-line': -> editor.selectToFirstCharacterOfLine() - 'editor:select-line': -> editor.selectLine() + 'editor:select-line': -> editor.selectLinesContainingCursors() 'editor:transpose': -> editor.transpose() 'editor:upper-case': -> editor.upperCase() 'editor:lower-case': -> editor.lowerCase() diff --git a/src/editor.coffee b/src/editor.coffee index 6aac1d646..98bb53cd6 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2022,8 +2022,11 @@ class Editor extends Model # Essential: For each cursor, select the containing line. # # This method merges selections on successive lines. - selectLine: -> + selectLinesContainingCursors: -> @expandSelectionsForward (selection) -> selection.selectLine() + selectLine: -> + deprecate('Use Editor::selectLinesContainingCursors instead') + @selectLinesContainingCursors() # Essential: Select the word containing each cursor. selectWord: -> From 5ea64f8b115d9b325c7b4cb21aee1aa303264ecc Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:03:57 -0700 Subject: [PATCH 078/135] selectWord() -> selectWordsContainingCursors() --- spec/editor-spec.coffee | 14 +++++++------- src/editor-component.coffee | 2 +- src/editor.coffee | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 76605519d..2ccc4ca40 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1158,39 +1158,39 @@ describe "Editor", -> expect(selection4.getBufferRange()).toEqual [[3,30], [3,31]] expect(selection4.isReversed()).toBeFalsy() - describe ".selectWord()", -> + describe ".selectWordsContainingCursors()", -> describe "when the cursor is inside a word", -> it "selects the entire word", -> editor.setCursorScreenPosition([0, 8]) - editor.selectWord() + editor.selectWordsContainingCursors() expect(editor.getSelectedText()).toBe 'quicksort' describe "when the cursor is between two words", -> it "selects the word the cursor is on", -> editor.setCursorScreenPosition([0, 4]) - editor.selectWord() + editor.selectWordsContainingCursors() expect(editor.getSelectedText()).toBe 'quicksort' editor.setCursorScreenPosition([0, 3]) - editor.selectWord() + editor.selectWordsContainingCursors() expect(editor.getSelectedText()).toBe 'var' describe "when the cursor is inside a region of whitespace", -> it "selects the whitespace region", -> editor.setCursorScreenPosition([5, 2]) - editor.selectWord() + editor.selectWordsContainingCursors() expect(editor.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]] editor.setCursorScreenPosition([5, 0]) - editor.selectWord() + editor.selectWordsContainingCursors() expect(editor.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]] describe "when the cursor is at the end of the text", -> it "select the previous word", -> editor.buffer.append 'word' editor.moveToBottom() - editor.selectWord() + editor.selectWordsContainingCursors() expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]] describe ".selectToFirstCharacterOfLine()", -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index f31264dd2..ca04de86c 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -416,7 +416,7 @@ EditorComponent = React.createClass 'core:copy': -> editor.copySelectedText() 'core:paste': -> editor.pasteText() 'editor:move-to-previous-word': -> editor.moveToPreviousWord() - 'editor:select-word': -> editor.selectWord() + 'editor:select-word': -> editor.selectWordsContainingCursors() 'editor:consolidate-selections': @consolidateSelections 'editor:delete-to-beginning-of-word': -> editor.deleteToBeginningOfWord() 'editor:delete-to-beginning-of-line': -> editor.deleteToBeginningOfLine() diff --git a/src/editor.coffee b/src/editor.coffee index 98bb53cd6..3d47bcc8d 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2028,9 +2028,12 @@ class Editor extends Model deprecate('Use Editor::selectLinesContainingCursors instead') @selectLinesContainingCursors() - # Essential: Select the word containing each cursor. - selectWord: -> + # Essential: Select the word surrounding each cursor. + selectWordsContainingCursors: -> @expandSelectionsForward (selection) -> selection.selectWord() + selectWord: -> + deprecate('Use Editor::selectWordsContainingCursors instead') + @selectWordsContainingCursors() # Selection Extended From 659c05c8259bf943f01a2febbb3e671b62ccd5fe Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:09:56 -0700 Subject: [PATCH 079/135] Add selectToBufferPosition --- spec/editor-spec.coffee | 12 ++++++++++++ src/editor.coffee | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 2ccc4ca40..3d6bdada8 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -925,6 +925,18 @@ describe "Editor", -> expect(selection1.getScreenRange()).toEqual([[0, 9], [1, 21]]) expect(selection1.isReversed()).toBeFalsy() + describe ".selectToBufferPosition(bufferPosition)", -> + it "expands the last selection to the given position", -> + editor.setSelectedBufferRange([[3, 0], [4, 5]]) + editor.addCursorAtBufferPosition([5, 6]) + editor.selectToBufferPosition([6, 2]) + + selections = editor.getSelections() + expect(selections.length).toBe 2 + [selection1, selection2] = selections + expect(selection1.getBufferRange()).toEqual [[3, 0], [4, 5]] + expect(selection2.getBufferRange()).toEqual [[5, 6], [6, 2]] + describe ".selectToScreenPosition(screenPosition)", -> 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 3d47bcc8d..f71597fb6 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1923,6 +1923,17 @@ class Editor extends Model selection.autoscroll() if @manageScrollPosition selection + # Essential: Select from the current cursor position to the given position in + # buffer coordinates. + # + # This method may merge selections that end up intesecting. + # + # * `position` An instance of {Point}, with a given `row` and `column`. + selectToBufferPosition: (position) -> + lastSelection = @getLastSelection() + lastSelection.selectToBufferPosition(position) + @mergeIntersectingSelections(reversed: lastSelection.isReversed()) + # Essential: Select from the current cursor position to the given position in # screen coordinates. # From a9227b5f43b8e30ee98d6b7575e86f1b028aec1b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 14:22:51 -0700 Subject: [PATCH 080/135] Upgrade to language-less@0.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ffb1091e..f9938f0b2 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "language-java": "0.11.0", "language-javascript": "0.39.0", "language-json": "0.8.0", - "language-less": "0.14.0", + "language-less": "0.15.0", "language-make": "0.12.0", "language-mustache": "0.10.0", "language-objective-c": "0.11.0", From 3bd7edb94ec2e38cc2ef4f0ab2be4a529aa855a2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 2 Sep 2014 14:25:40 -0700 Subject: [PATCH 081/135] Upgrade to language-sass@0.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f9938f0b2..e5dd4b587 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,7 @@ "language-python": "0.19.0", "language-ruby": "0.35.0", "language-ruby-on-rails": "0.18.0", - "language-sass": "0.20.0", + "language-sass": "0.21.0", "language-shellscript": "0.8.0", "language-source": "0.8.0", "language-sql": "0.10.0", From a7db555030f8b5696d6d7fc19f8843834ea3852c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:38:11 -0700 Subject: [PATCH 082/135] Order the getting ranges / positions by their insertion order --- spec/editor-spec.coffee | 8 ++++---- src/editor.coffee | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 3d6bdada8..89d02b2c6 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -751,17 +751,17 @@ describe "Editor", -> expect(cursorMovedHandler).not.toHaveBeenCalled() describe "::getCursorBufferPositions()", -> - it "returns the existing cursor", -> + 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], [4, 5], [8, 5]] + expect(editor.getCursorBufferPositions()).toEqual [[0, 0], [8, 5], [4, 5]] describe "::getCursorScreenPositions()", -> - it "returns the existing cursor", -> + it "returns the cursor positions in the order they were added", -> editor.foldBufferRow(4) cursor1 = editor.addCursorAtBufferPosition([8, 5]) cursor2 = editor.addCursorAtBufferPosition([3, 5]) - expect(editor.getCursorScreenPositions()).toEqual [[0, 0], [3, 5], [5, 5]] + expect(editor.getCursorScreenPositions()).toEqual [[0, 0], [5, 5], [3, 5]] describe "::getCursorsOrderedByBufferPosition()", -> it "returns all cursors ordered by buffer positions", -> diff --git a/src/editor.coffee b/src/editor.coffee index f71597fb6..3782037fb 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1519,9 +1519,9 @@ class Editor extends Model # Essential: Get the position of all the cursor positions in buffer coordinates. # - # Returns {Array} of {Point}s + # Returns {Array} of {Point}s in the order they were added getCursorBufferPositions: -> - cursor.getBufferPosition() for cursor in @getCursorsOrderedByBufferPosition() + cursor.getBufferPosition() for cursor in @getCursors() # Essential: Move the cursor to the given position in buffer coordinates. # @@ -1543,9 +1543,9 @@ class Editor extends Model # Essential: Get the position of all the cursor positions in screen coordinates. # - # Returns {Array} of {Point}s + # Returns {Array} of {Point}s in the order the cursors were added getCursorScreenPositions: -> - cursor.getScreenPosition() for cursor in @getCursorsOrderedByBufferPosition() + cursor.getScreenPosition() for cursor in @getCursors() # Get the row of the most recently added cursor in screen coordinates. # @@ -1816,7 +1816,7 @@ class Editor extends Model # # Returns an {Array} of {Range}s. getSelectedBufferRanges: -> - selection.getBufferRange() for selection in @getSelectionsOrderedByBufferPosition() + selection.getBufferRange() for selection in @getSelections() # Essential: Set the selected range in buffer coordinates. If there are multiple # selections, they are reduced to a single selection with the given range. @@ -1862,7 +1862,7 @@ class Editor extends Model # # Returns an {Array} of {Range}s. getSelectedScreenRanges: -> - selection.getScreenRange() for selection in @getSelectionsOrderedByBufferPosition() + selection.getScreenRange() for selection in @getSelections() # Essential: Set the selected range in screen coordinates. If there are multiple # selections, they are reduced to a single selection with the given range. From 3f67252757a6b2b7e95cf21893597dfd97ac3335 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:50:15 -0700 Subject: [PATCH 083/135] Add row count docs --- src/editor.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/editor.coffee b/src/editor.coffee index 3782037fb..58e38ac27 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1948,6 +1948,8 @@ 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 + # # This method may merge selections that end up intesecting. selectUp: (rowCount) -> @expandSelectionsBackward (selection) -> selection.selectUp(rowCount) @@ -1955,6 +1957,8 @@ 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 + # # This method may merge selections that end up intesecting. selectDown: (rowCount) -> @expandSelectionsForward (selection) -> selection.selectDown(rowCount) From dca36d13071eda9370f45d0089c7a7d332db0b42 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:55:02 -0700 Subject: [PATCH 084/135] Reorder return values of getSelectedBufferRanges The implementation does not depend on a specific order, just the test --- spec/editor-spec.coffee | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 89d02b2c6..9419c6a0b 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1431,17 +1431,17 @@ describe "Editor", -> [[10, 0], [10, 0]] ] - describe ".addSelectionAbove()", -> + fdescribe ".addSelectionAbove()", -> describe "when the selection is non-empty", -> it "selects the same region of the line above current selections if possible", -> editor.setSelectedBufferRange([[3, 16], [3, 21]]) editor.addSelectionForBufferRange([[3, 37], [3, 44]]) editor.addSelectionAbove() expect(editor.getSelectedBufferRanges()).toEqual [ - [[2, 16], [2, 21]] - [[2, 37], [2, 40]] [[3, 16], [3, 21]] [[3, 37], [3, 44]] + [[2, 16], [2, 21]] + [[2, 37], [2, 40]] ] for cursor in editor.getCursors() expect(cursor.isVisible()).toBeFalsy() @@ -1450,8 +1450,8 @@ describe "Editor", -> editor.setSelectedBufferRange([[6, 31], [6, 38]]) editor.addSelectionAbove() expect(editor.getSelectedBufferRanges()).toEqual [ - [[3, 31], [3, 38]] [[6, 31], [6, 38]] + [[3, 31], [3, 38]] ] it "honors the original selection's range (goal range) when adding across shorter lines", -> @@ -1460,10 +1460,10 @@ describe "Editor", -> editor.addSelectionAbove() editor.addSelectionAbove() expect(editor.getSelectedBufferRanges()).toEqual [ - [[3, 22], [3, 38]] - [[4, 22], [4, 29]] - [[5, 22], [5, 30]] [[6, 22], [6, 38]] + [[5, 22], [5, 30]] + [[4, 22], [4, 29]] + [[3, 22], [3, 38]] ] describe "when the selection is empty", -> @@ -1473,26 +1473,26 @@ describe "Editor", -> editor.addSelectionAbove() editor.addSelectionAbove() expect(editor.getSelectedBufferRanges()).toEqual [ - [[3, 36], [3, 36]] - [[4, 29], [4, 29]] - [[5, 30], [5, 30]] [[6, 36], [6, 36]] + [[5, 30], [5, 30]] + [[4, 29], [4, 29]] + [[3, 36], [3, 36]] ] it "skips empty lines when the column is non-zero", -> editor.setCursorBufferPosition([11, 4]) editor.addSelectionAbove() expect(editor.getSelectedBufferRanges()).toEqual [ - [[9, 4], [9, 4]] [[11, 4], [11, 4]] + [[9, 4], [9, 4]] ] it "does not skip empty lines when the column is zero", -> editor.setCursorBufferPosition([10, 0]) editor.addSelectionAbove() expect(editor.getSelectedBufferRanges()).toEqual [ - [[9, 0], [9, 0]] [[10, 0], [10, 0]] + [[9, 0], [9, 0]] ] describe ".splitSelectionsIntoLines()", -> From a564da1eb00fb79d65ba13febba4b21f479fb051 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:58:20 -0700 Subject: [PATCH 085/135] Remove unnecessary deprecated methods --- src/cursor.coffee | 48 ----------------------------------------------- 1 file changed, 48 deletions(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 975ef9e11..22a60a8ef 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -236,9 +236,6 @@ class Cursor extends Model column = @goalColumn if @goalColumn? @setScreenPosition({row: row - rowCount, column: column}) @goalColumn = column - moveCursorUp: (rowCount=1, options) -> - deprecate("Use Cursor::moveUp() instead. `Cursor` has been removed from these methods.") - @moveUp(rowCount, options) # Public: Moves the cursor down one screen row. moveDown: (rowCount = 1, {moveToEndOfSelection}={}) -> @@ -251,9 +248,6 @@ class Cursor extends Model column = @goalColumn if @goalColumn? @setScreenPosition({row: row + rowCount, column: column}) @goalColumn = column - moveCursorDown: (rowCount=1, options) -> - deprecate("Use Cursor::moveDown() instead. `Cursor` has been removed from these methods.") - @moveDown(rowCount, options) # Public: Moves the cursor left one screen column. # @@ -268,9 +262,6 @@ class Cursor extends Model {row, column} = @getScreenPosition() [row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity] @setScreenPosition({row, column}) - moveCursorLeft: (rowCount=1, options) -> - deprecate("Use Cursor::moveLeft() instead. `Cursor` has been removed from these methods.") - @moveLeft(rowCount, options) # Public: Moves the cursor right one screen column. # @@ -284,37 +275,22 @@ class Cursor extends Model else { row, column } = @getScreenPosition() @setScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true) - moveCursorRight: (rowCount=1, options) -> - deprecate("Use Cursor::moveRight() instead. `Cursor` has been removed from these methods.") - @moveRight(rowCount, options) # Public: Moves the cursor to the top of the buffer. moveToTop: -> @setBufferPosition([0,0]) - moveCursorToTop: (rowCount=1, options) -> - deprecate("Use Cursor::moveToTop() instead. `Cursor` has been removed from these methods.") - @moveToTop(rowCount, options) # Public: Moves the cursor to the bottom of the buffer. moveToBottom: -> @setBufferPosition(@editor.getEofBufferPosition()) - moveCursorToBottom: (rowCount=1, options) -> - deprecate("Use Cursor::moveToBottom() instead. `Cursor` has been removed from these methods.") - @moveToBottom(rowCount, options) # Public: Moves the cursor to the beginning of the line. moveToBeginningOfScreenLine: -> @setScreenPosition([@getScreenRow(), 0]) - moveCursorToBeginningOfScreenLine: (rowCount=1, options) -> - deprecate("Use Cursor::moveToBeginningOfScreenLine() instead. `Cursor` has been removed from these methods.") - @moveToBeginningOfScreenLine(rowCount, options) # Public: Moves the cursor to the beginning of the buffer line. moveToBeginningOfLine: -> @setBufferPosition([@getBufferRow(), 0]) - moveCursorToBeginningOfLine: (rowCount=1, options) -> - deprecate("Use Cursor::moveToBeginningOfLine() instead. `Cursor` has been removed from these methods.") - @moveToBeginningOfLine(rowCount, options) # Public: Moves the cursor to the beginning of the first character in the # line. @@ -333,62 +309,38 @@ class Cursor extends Model targetBufferColumn = lineBufferRange.start.column @setBufferPosition([lineBufferRange.start.row, targetBufferColumn]) - moveCursorToFirstCharacterOfLine: (rowCount=1, options) -> - deprecate("Use Cursor::moveToFirstCharacterOfLine() instead. `Cursor` has been removed from these methods.") - @moveToFirstCharacterOfLine(rowCount, options) # Public: Moves the cursor to the end of the line. moveToEndOfScreenLine: -> @setScreenPosition([@getScreenRow(), Infinity]) - moveCursorToEndOfScreenLine: (rowCount=1, options) -> - deprecate("Use Cursor::moveToEndOfScreenLine() instead. `Cursor` has been removed from these methods.") - @moveToEndOfScreenLine(rowCount, options) # Public: Moves the cursor to the end of the buffer line. moveToEndOfLine: -> @setBufferPosition([@getBufferRow(), Infinity]) - moveCursorToEndOfLine: (rowCount=1, options) -> - deprecate("Use Cursor::moveToEndOfLine() instead. `Cursor` has been removed from these methods.") - @moveToEndOfLine(rowCount, options) # Public: Moves the cursor to the beginning of the word. moveToBeginningOfWord: -> @setBufferPosition(@getBeginningOfCurrentWordBufferPosition()) - moveCursorToBeginningOfWord: (rowCount=1, options) -> - deprecate("Use Cursor::moveToBeginningOfWord() instead. `Cursor` has been removed from these methods.") - @moveToBeginningOfWord(rowCount, options) # Public: Moves the cursor to the end of the word. moveToEndOfWord: -> if position = @getEndOfCurrentWordBufferPosition() @setBufferPosition(position) - moveCursorToEndOfWord: (rowCount=1, options) -> - deprecate("Use Cursor::moveToEndOfWord() instead. `Cursor` has been removed from these methods.") - @moveToEndOfWord(rowCount, options) # Public: Moves the cursor to the beginning of the next word. moveToBeginningOfNextWord: -> if position = @getBeginningOfNextWordBufferPosition() @setBufferPosition(position) - moveCursorToBeginningOfNextWord: (rowCount=1, options) -> - deprecate("Use Cursor::moveToBeginningOfNextWord() instead. `Cursor` has been removed from these methods.") - @moveToBeginningOfNextWord(rowCount, options) # Public: Moves the cursor to the previous word boundary. moveToPreviousWordBoundary: -> if position = @getPreviousWordBoundaryBufferPosition() @setBufferPosition(position) - moveCursorToPreviousWordBoundary: (rowCount=1, options) -> - deprecate("Use Cursor::moveToPreviousWordBoundary() instead. `Cursor` has been removed from these methods.") - @moveToPreviousWordBoundary(rowCount, options) # Public: Moves the cursor to the next word boundary. moveToNextWordBoundary: -> if position = @getMoveNextWordBoundaryBufferPosition() @setBufferPosition(position) - moveCursorToNextWordBoundary: (rowCount=1, options) -> - deprecate("Use Cursor::moveToNextWordBoundary() instead. `Cursor` has been removed from these methods.") - @moveToNextWordBoundary(rowCount, options) # Public: Moves the cursor to the beginning of the buffer line, skipping all # whitespace. From 1f925078e97bd3ef26f965fe3e21cc8fdb0b682e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 14:59:06 -0700 Subject: [PATCH 086/135] Remove deprecation --- src/cursor.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cursor.coffee b/src/cursor.coffee index 22a60a8ef..9341d8b8a 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -1,7 +1,6 @@ {Point, Range} = require 'text-buffer' {Model} = require 'theorist' _ = require 'underscore-plus' -{deprecate} = require 'grim' # Extended: The `Cursor` class represents the little blinking line identifying # where text can be inserted. From 539e4e07454a3886c32e6296b009369a9cc3c4ad Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 15:10:38 -0700 Subject: [PATCH 087/135] Upgrade fnr to fix specs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c1fcef62c..15920b259 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", - "find-and-replace": "0.131.1", + "find-and-replace": "0.132.0", "fuzzy-finder": "0.57.0", "git-diff": "0.39.0", "go-to-line": "0.25.0", From 81532d52f711bfa30fa4fe3fb4c8adc7136d867f Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 16:45:49 -0700 Subject: [PATCH 088/135] Move select all fn so docs read better --- src/editor.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/editor.coffee b/src/editor.coffee index 06503efb2..0ac028065 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1985,12 +1985,6 @@ class Editor extends Model selectToTop: -> @expandSelectionsBackward (selection) -> selection.selectToTop() - # Essential: Select all text in the buffer. - # - # This method merges multiple selections into a single selection. - selectAll: -> - @expandSelectionsForward (selection) -> selection.selectAll() - # Essential: Selects from the top of the first selection in the buffer to the end # of the buffer. # @@ -1998,6 +1992,12 @@ class Editor extends Model selectToBottom: -> @expandSelectionsForward (selection) -> selection.selectToBottom() + # Essential: Select all text in the buffer. + # + # This method merges multiple selections into a single selection. + selectAll: -> + @expandSelectionsForward (selection) -> selection.selectAll() + # Essential: Move the cursor of each selection to the beginning of its line # while preserving the selection's tail position. # From 3d8f3883d1fb2a1178d0cf6038bcc9bc8cec4be2 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 16:52:22 -0700 Subject: [PATCH 089/135] Upgrade deprecation cop to remove the status bar icon. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ca3245e0b..65249173d 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "bookmarks": "0.28.0", "bracket-matcher": "0.54.0", "command-palette": "0.24.0", - "deprecation-cop": "0.9.0", + "deprecation-cop": "0.10.0", "dev-live-reload": "0.34.0", "exception-reporting": "0.20.0", "feedback": "0.33.0", From ae0bffc4ea86025e298dd1a762dbf33bafa47493 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:01:20 -0700 Subject: [PATCH 090/135] Fix some doc strings --- src/editor.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index 0ac028065..3dc730e6d 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1047,11 +1047,15 @@ class Editor extends Model # Public: Convert a range in buffer-coordinates to screen-coordinates. # + # * `bufferRange` {Range} in buffer coordinates to translate into screen coordinates. + # # Returns a {Range}. screenRangeForBufferRange: (bufferRange) -> @displayBuffer.screenRangeForBufferRange(bufferRange) # Public: Convert a range in screen-coordinates to buffer-coordinates. # + # * `screenRange` {Range} in screen coordinates to translate into buffer coordinates. + # # Returns a {Range}. bufferRangeForScreenRange: (screenRange) -> @displayBuffer.bufferRangeForScreenRange(screenRange) @@ -1100,7 +1104,11 @@ class Editor extends Model # editor.clipScreenPosition([2, Infinity]) # -> `[2, 10]` # ``` # - # * `bufferPosition` The {Point} representing the position to clip. + # * `screenPosition` The {Point} representing the position to clip. + # * `options` (optional) {Object} + # * `wrapBeyondNewlines` {Boolean} if `true`, continues wrapping past newlines + # * `wrapAtSoftNewlines` {Boolean} if `true`, continues wrapping past soft newlines + # * `screenLine` {Boolean} if `true`, indicates that you're using a line number, not a row number # # Returns a {Point}. clipScreenPosition: (screenPosition, options) -> @displayBuffer.clipScreenPosition(screenPosition, options) From cfd27223484374754315142177cf59ad608c4f4c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 2 Sep 2014 15:32:14 -0600 Subject: [PATCH 091/135] =?UTF-8?q?Don=E2=80=99t=20merge=20adjacent=20non-?= =?UTF-8?q?empty=20selections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This improves the behavior of #3433 --- package.json | 2 +- spec/editor-spec.coffee | 9 ++++++--- src/editor.coffee | 6 +++++- src/selection.coffee | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index c95628f82..01a7102e3 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "serializable": "^1", "space-pen": "3.4.6", "temp": "0.7.0", - "text-buffer": "^3.0.4", + "text-buffer": "^3.1.0", "theorist": "^1.0.2", "underscore-plus": "^1.5.1", "vm-compatibility-layer": "0.1.0" diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 07f88bea1..ae58696dc 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -881,14 +881,13 @@ describe "Editor", -> [selection1, selection2] = editor.getSelections() editor.selectUp() - expect(editor.getSelections().length).toBe 1 expect(editor.getSelections()).toEqual [selection1] expect(selection1.getScreenRange()).toEqual([[0, 0], [1, 20]]) expect(selection1.isReversed()).toBeTruthy() it "merges selections when they intersect when moving left", -> - editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], reversed: true) + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,13], [1,20]]], reversed: true) [selection1, selection2] = editor.getSelections() editor.selectLeft() @@ -897,7 +896,7 @@ describe "Editor", -> expect(selection1.isReversed()).toBeTruthy() it "merges selections when they intersect when moving right", -> - editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]]) + editor.setSelectedBufferRanges([[[0,9], [0,14]], [[0,14], [1,20]]]) [selection1, selection2] = editor.getSelections() editor.selectRight() @@ -1210,6 +1209,10 @@ describe "Editor", -> editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[3, 0], [5, 5]]]) expect(editor.getSelectedBufferRanges()).toEqual [[[2, 2], [5, 5]]] + it "does not merge non-empty adjacent selections", -> + editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[3, 3], [5, 5]]]) + expect(editor.getSelectedBufferRanges()).toEqual [[[2, 2], [3, 3]], [[3, 3], [5, 5]]] + it "recyles existing selection instances", -> selection = editor.getSelection() editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]]) diff --git a/src/editor.coffee b/src/editor.coffee index 9753ad409..a393f80c5 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -2097,7 +2097,11 @@ class Editor extends Model @suppressSelectionMerging = false reducer = (disjointSelections, selection) -> - intersectingSelection = _.find(disjointSelections, (s) -> s.intersectsWith(selection)) + intersectingSelection = _.find disjointSelections, (otherSelection) -> + exclusive = not selection.isEmpty() and not otherSelection.isEmpty() + intersects = otherSelection.intersectsWith(selection, exclusive) + intersects + if intersectingSelection? intersectingSelection.merge(selection, options) disjointSelections diff --git a/src/selection.coffee b/src/selection.coffee index efbb40592..a0db277c1 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -629,8 +629,8 @@ class Selection extends Model # * `otherSelection` A {Selection} to check against. # # Returns a {Boolean} - intersectsWith: (otherSelection) -> - @getBufferRange().intersectsWith(otherSelection.getBufferRange()) + intersectsWith: (otherSelection, exclusive) -> + @getBufferRange().intersectsWith(otherSelection.getBufferRange(), exclusive) # Public: Combines the given selection into this selection and then destroys # the given selection. From 1e4fb5b4bc1a7d7189be85965f0fd9928fa0a6e3 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:44:01 -0700 Subject: [PATCH 092/135] nof --- spec/editor-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index a8d246fc5..c0f5b2646 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1431,7 +1431,7 @@ describe "Editor", -> [[10, 0], [10, 0]] ] - fdescribe ".addSelectionAbove()", -> + describe ".addSelectionAbove()", -> describe "when the selection is non-empty", -> it "selects the same region of the line above current selections if possible", -> editor.setSelectedBufferRange([[3, 16], [3, 21]]) From d3422786c37f72e8576dce09fed21ad405c271c2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 10:53:41 -0600 Subject: [PATCH 093/135] Unmount component when EditorView is detached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #3431 When a pane item is moved to another pane, we *detach* the associated view but we don’t fully remove it. This was to prevent removing a view when it was used as the pane item directly. However, this was causing the editor component not to be unmounted, which caused leaks and incorrect measurements. We need to unmount the component, but we don’t want to destroy the editor. So I’ve moved editor destruction to the wrapper view for now, and I only do it when the view is actually removed. Ultimately, we need to have a 1:1 relationship with pane items and their views and only allow a pane item to appear once in the pane tree. Then we can recycle the same view and avoid this confusing situation where the old view is detached and a new view is created. --- src/editor-component.coffee | 5 +++-- src/editor-view.coffee | 12 +++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index d72fccbf7..870a984fa 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -183,12 +183,13 @@ EditorComponent = React.createClass @checkForVisibilityChange() componentWillUnmount: -> - @props.parentView.trigger 'editor:will-be-removed', [@props.parentView] + {editor, parentView} = @props + + parentView.trigger 'editor:will-be-removed', [parentView] @unsubscribe() window.removeEventListener 'resize', @requestHeightAndWidthMeasurement clearInterval(@domPollingIntervalId) @domPollingIntervalId = null - @props.editor.destroy() componentWillReceiveProps: (newProps) -> @props.editor.setMini(newProps.mini) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index cc18f7e9e..2f945f458 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -215,12 +215,22 @@ class EditorView extends View view.css('z-index', 1) @find('.lines').prepend(view) + detach: -> + return unless @attached + super + @attached = false + @unmountComponent() + beforeRemove: -> return unless @attached @attached = false - React.unmountComponentAtNode(@element) if @component.isMounted() + @unmountComponent() + @editor.destroy() @trigger 'editor:detached', this + unmountComponent: -> + React.unmountComponentAtNode(@element) if @component.isMounted() + # Public: Split the editor view left. splitLeft: -> pane = @getPane() From 1ff9da5f7a08e0ce2fe1d0d66cfeaf40d2e18616 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 3 Sep 2014 11:31:41 -0700 Subject: [PATCH 094/135] Upgrade to markdown-preview@0.101 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d6ce2ce5..d24ca30de 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "incompatible-packages": "0.9.0", "keybinding-resolver": "0.19.0", "link": "0.25.0", - "markdown-preview": "0.100.0", + "markdown-preview": "0.101.0", "metrics": "0.33.0", "open-on-github": "0.30.0", "package-generator": "0.31.0", From d3c2cd756a79c5eb5e78c17153c64becbc581730 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 12:01:36 -0700 Subject: [PATCH 095/135] Fix comment --- src/atom.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atom.coffee b/src/atom.coffee index 316fc945d..4fb113302 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -24,7 +24,7 @@ class Atom extends Model # Public: Load or create the Atom environment in the given mode. # # * `mode` A {String} mode that is either 'editor' or 'spec' depending on the - # kind of environment you want to build. + # kind of environment you want to build. # # Returns an Atom instance, fully initialized @loadOrCreate: (mode) -> From c0e2ed4282091d1fac4349a3a5c9ddc423052e0e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 12:04:21 -0700 Subject: [PATCH 096/135] Fix comments --- src/clipboard.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clipboard.coffee b/src/clipboard.coffee index 03d53d574..48bfb8dd5 100644 --- a/src/clipboard.coffee +++ b/src/clipboard.coffee @@ -47,8 +47,8 @@ class Clipboard # associated metadata. # # Returns an {Object} with the following keys: - # * `text` The {String} clipboard text. - # * `metadata` The metadata stored by an earlier call to {::write}. + # * `text` The {String} clipboard text. + # * `metadata` The metadata stored by an earlier call to {::write}. readWithMetadata: -> text = @read() if @signatureForMetadata is @md5(text) From 05bbc480b0802178dbe68657c349f88e0ac82bbe Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:42:04 -0700 Subject: [PATCH 097/135] displayBuffer::lineForRow -> tokenizedLineForRow --- spec/display-buffer-spec.coffee | 190 ++++++++++++++++---------------- src/display-buffer.coffee | 16 +-- 2 files changed, 103 insertions(+), 103 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 34b75f54f..59ac6b6b2 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -67,48 +67,48 @@ describe "DisplayBuffer", -> it "uses the preferred line length as the soft wrap column when it is less than the configured soft wrap column", -> atom.config.set('editor.preferredLineLength', 100) atom.config.set('editor.softWrapAtPreferredLineLength', true) - expect(displayBuffer.lineForRow(10).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' return ' atom.config.set('editor.preferredLineLength', 5) - expect(displayBuffer.lineForRow(10).text).toBe 'funct' + expect(displayBuffer.tokenizedLineForRow(10).text).toBe 'funct' atom.config.set('editor.softWrapAtPreferredLineLength', false) - expect(displayBuffer.lineForRow(10).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' return ' describe "when the line is shorter than the max line length", -> it "renders the line unchanged", -> - expect(displayBuffer.lineForRow(0).text).toBe buffer.lineForRow(0) + expect(displayBuffer.tokenizedLineForRow(0).text).toBe buffer.lineForRow(0) describe "when the line is empty", -> it "renders the empty line", -> - expect(displayBuffer.lineForRow(13).text).toBe '' + expect(displayBuffer.tokenizedLineForRow(13).text).toBe '' describe "when there is a non-whitespace character at the max length boundary", -> describe "when there is whitespace before the boundary", -> it "wraps the line at the end of the first whitespace preceding the boundary", -> - expect(displayBuffer.lineForRow(10).text).toBe ' return ' - expect(displayBuffer.lineForRow(11).text).toBe 'sort(left).concat(pivot).concat(sort(right));' + expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForRow(11).text).toBe 'sort(left).concat(pivot).concat(sort(right));' describe "when there is no whitespace before the boundary", -> it "wraps the line exactly at the boundary since there's no more graceful place to wrap it", -> buffer.setTextInRange([[0, 0], [1, 0]], 'abcdefghijklmnopqrstuvwxyz\n') displayBuffer.setEditorWidthInChars(10) - expect(displayBuffer.lineForRow(0).text).toBe 'abcdefghij' - expect(displayBuffer.lineForRow(1).text).toBe 'klmnopqrst' - expect(displayBuffer.lineForRow(2).text).toBe 'uvwxyz' + expect(displayBuffer.tokenizedLineForRow(0).text).toBe 'abcdefghij' + expect(displayBuffer.tokenizedLineForRow(1).text).toBe 'klmnopqrst' + expect(displayBuffer.tokenizedLineForRow(2).text).toBe 'uvwxyz' describe "when there is a whitespace character at the max length boundary", -> it "wraps the line at the first non-whitespace character following the boundary", -> - expect(displayBuffer.lineForRow(3).text).toBe ' var pivot = items.shift(), current, left = [], ' - expect(displayBuffer.lineForRow(4).text).toBe 'right = [];' + expect(displayBuffer.tokenizedLineForRow(3).text).toBe ' var pivot = items.shift(), current, left = [], ' + expect(displayBuffer.tokenizedLineForRow(4).text).toBe 'right = [];' describe "when there are hard tabs", -> beforeEach -> buffer.setText(buffer.getText().replace(new RegExp(' ', 'g'), '\t')) it "correctly tokenizes the hard tabs", -> - expect(displayBuffer.lineForRow(3).tokens[0].isHardTab).toBeTruthy() - expect(displayBuffer.lineForRow(3).tokens[1].isHardTab).toBeTruthy() + expect(displayBuffer.tokenizedLineForRow(3).tokens[0].isHardTab).toBeTruthy() + expect(displayBuffer.tokenizedLineForRow(3).tokens[1].isHardTab).toBeTruthy() describe "when the buffer changes", -> describe "when buffer lines are updated", -> @@ -121,8 +121,8 @@ describe "DisplayBuffer", -> describe "when the update makes a soft-wrapped line shorter than the max line length", -> it "rewraps the line and emits a change event", -> buffer.delete([[6, 24], [6, 42]]) - expect(displayBuffer.lineForRow(7).text).toBe ' current < pivot ? : right.push(current);' - expect(displayBuffer.lineForRow(8).text).toBe ' }' + expect(displayBuffer.tokenizedLineForRow(7).text).toBe ' current < pivot ? : right.push(current);' + expect(displayBuffer.tokenizedLineForRow(8).text).toBe ' }' expect(changeHandler).toHaveBeenCalled() [[event]]= changeHandler.argsForCall @@ -132,30 +132,30 @@ describe "DisplayBuffer", -> describe "when the update causes a line to softwrap an additional time", -> it "rewraps the line and emits a change event", -> buffer.insert([6, 28], '1234567890') - expect(displayBuffer.lineForRow(7).text).toBe ' current < pivot ? ' - expect(displayBuffer.lineForRow(8).text).toBe 'left1234567890.push(current) : ' - expect(displayBuffer.lineForRow(9).text).toBe 'right.push(current);' - expect(displayBuffer.lineForRow(10).text).toBe ' }' + expect(displayBuffer.tokenizedLineForRow(7).text).toBe ' current < pivot ? ' + expect(displayBuffer.tokenizedLineForRow(8).text).toBe 'left1234567890.push(current) : ' + expect(displayBuffer.tokenizedLineForRow(9).text).toBe 'right.push(current);' + expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' }' expect(changeHandler).toHaveBeenCalledWith(start: 7, end: 8, screenDelta: 1, bufferDelta: 0) describe "when buffer lines are inserted", -> it "inserts / updates wrapped lines and emits a change event", -> buffer.insert([6, 21], '1234567890 abcdefghij 1234567890\nabcdefghij') - expect(displayBuffer.lineForRow(7).text).toBe ' current < pivot1234567890 abcdefghij ' - expect(displayBuffer.lineForRow(8).text).toBe '1234567890' - expect(displayBuffer.lineForRow(9).text).toBe 'abcdefghij ? left.push(current) : ' - expect(displayBuffer.lineForRow(10).text).toBe 'right.push(current);' + expect(displayBuffer.tokenizedLineForRow(7).text).toBe ' current < pivot1234567890 abcdefghij ' + expect(displayBuffer.tokenizedLineForRow(8).text).toBe '1234567890' + expect(displayBuffer.tokenizedLineForRow(9).text).toBe 'abcdefghij ? left.push(current) : ' + expect(displayBuffer.tokenizedLineForRow(10).text).toBe 'right.push(current);' expect(changeHandler).toHaveBeenCalledWith(start: 7, end: 8, screenDelta: 2, bufferDelta: 1) describe "when buffer lines are removed", -> it "removes lines and emits a change event", -> buffer.setTextInRange([[3, 21], [7, 5]], ';') - expect(displayBuffer.lineForRow(3).text).toBe ' var pivot = items;' - expect(displayBuffer.lineForRow(4).text).toBe ' return ' - expect(displayBuffer.lineForRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));' - expect(displayBuffer.lineForRow(6).text).toBe ' };' + expect(displayBuffer.tokenizedLineForRow(3).text).toBe ' var pivot = items;' + expect(displayBuffer.tokenizedLineForRow(4).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));' + expect(displayBuffer.tokenizedLineForRow(6).text).toBe ' };' expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 9, screenDelta: -6, bufferDelta: -4) @@ -169,9 +169,9 @@ describe "DisplayBuffer", -> buffer.delete([[0, Infinity], [1, 0]]) buffer.insert([0, Infinity], '\n') - expect(displayBuffer.lineForRow(0).text).toBe "the quick brown fox jumps over " - expect(displayBuffer.lineForRow(1).text).toBe "the lazy dog." - expect(displayBuffer.lineForRow(2).text).toBe "" + expect(displayBuffer.tokenizedLineForRow(0).text).toBe "the quick brown fox jumps over " + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "the lazy dog." + expect(displayBuffer.tokenizedLineForRow(2).text).toBe "" describe "position translation", -> it "translates positions accounting for wrapped lines", -> @@ -204,9 +204,9 @@ describe "DisplayBuffer", -> describe ".setEditorWidthInChars(length)", -> it "changes the length at which lines are wrapped and emits a change event for all screen lines", -> displayBuffer.setEditorWidthInChars(40) - expect(tokensText displayBuffer.lineForRow(4).tokens).toBe 'left = [], right = [];' - expect(tokensText displayBuffer.lineForRow(5).tokens).toBe ' while(items.length > 0) {' - expect(tokensText displayBuffer.lineForRow(12).tokens).toBe 'sort(left).concat(pivot).concat(sort(rig' + expect(tokensText displayBuffer.tokenizedLineForRow(4).tokens).toBe 'left = [], right = [];' + expect(tokensText displayBuffer.tokenizedLineForRow(5).tokens).toBe ' while(items.length > 0) {' + expect(tokensText displayBuffer.tokenizedLineForRow(12).tokens).toBe 'sort(left).concat(pivot).concat(sort(rig' expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 15, screenDelta: 3, bufferDelta: 0) it "only allows positive widths to be assigned", -> @@ -342,8 +342,8 @@ describe "DisplayBuffer", -> fold2 = displayBuffer.createFold(4, 9) fold1 = displayBuffer.createFold(0, 4) - expect(displayBuffer.lineForRow(0).text).toMatch /^0/ - expect(displayBuffer.lineForRow(1).text).toMatch /^10/ + expect(displayBuffer.tokenizedLineForRow(0).text).toMatch /^0/ + expect(displayBuffer.tokenizedLineForRow(1).text).toMatch /^10/ describe "when there is another display buffer pointing to the same buffer", -> it "does not create folds in the other display buffer", -> @@ -363,19 +363,19 @@ describe "DisplayBuffer", -> buffer.setTextInRange([[1, 0], [5, 1]], 'party!') it "removes the fold and replaces the selection with the new text", -> - expect(displayBuffer.lineForRow(0).text).toBe "0" - expect(displayBuffer.lineForRow(1).text).toBe "party!" - expect(displayBuffer.lineForRow(2).fold).toBe fold2 - expect(displayBuffer.lineForRow(3).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(0).text).toBe "0" + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "party!" + expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(3).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 3, screenDelta: -2, bufferDelta: -4) describe "when the changes is subsequently undone", -> xit "restores destroyed folds", -> buffer.undo() - expect(displayBuffer.lineForRow(2).text).toBe '2' - expect(displayBuffer.lineForRow(2).fold).toBe fold1 - expect(displayBuffer.lineForRow(3).text).toBe '5' + expect(displayBuffer.tokenizedLineForRow(2).text).toBe '2' + expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForRow(3).text).toBe '5' describe "when the old range surrounds two nested folds", -> it "removes both folds and replaces the selection with the new text", -> @@ -384,9 +384,9 @@ describe "DisplayBuffer", -> buffer.setTextInRange([[1, 0], [10, 0]], 'goodbye') - expect(displayBuffer.lineForRow(0).text).toBe "0" - expect(displayBuffer.lineForRow(1).text).toBe "goodbye10" - expect(displayBuffer.lineForRow(2).text).toBe "11" + expect(displayBuffer.tokenizedLineForRow(0).text).toBe "0" + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "goodbye10" + expect(displayBuffer.tokenizedLineForRow(2).text).toBe "11" expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 3, screenDelta: -2, bufferDelta: -9) @@ -403,42 +403,42 @@ describe "DisplayBuffer", -> it "updates the buffer and re-positions subsequent folds", -> buffer.setTextInRange([[0, 0], [1, 1]], 'abc') - expect(displayBuffer.lineForRow(0).text).toBe "abc" - expect(displayBuffer.lineForRow(1).fold).toBe fold1 - expect(displayBuffer.lineForRow(2).text).toBe "5" - expect(displayBuffer.lineForRow(3).fold).toBe fold2 - expect(displayBuffer.lineForRow(4).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(0).text).toBe "abc" + expect(displayBuffer.tokenizedLineForRow(1).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForRow(2).text).toBe "5" + expect(displayBuffer.tokenizedLineForRow(3).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(4).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 1, screenDelta: -1, bufferDelta: -1) changeHandler.reset() fold1.destroy() - expect(displayBuffer.lineForRow(0).text).toBe "abc" - expect(displayBuffer.lineForRow(1).text).toBe "2" - expect(displayBuffer.lineForRow(3).text).toMatch /^4-+/ - expect(displayBuffer.lineForRow(4).text).toBe "5" - expect(displayBuffer.lineForRow(5).fold).toBe fold2 - expect(displayBuffer.lineForRow(6).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(0).text).toBe "abc" + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "2" + expect(displayBuffer.tokenizedLineForRow(3).text).toMatch /^4-+/ + expect(displayBuffer.tokenizedLineForRow(4).text).toBe "5" + expect(displayBuffer.tokenizedLineForRow(5).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(6).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 1, screenDelta: 2, bufferDelta: 0) describe "when the old range straddles the beginning of a fold", -> it "destroys the fold", -> buffer.setTextInRange([[1, 1], [3, 0]], "a\nb\nc\nd\n") - expect(displayBuffer.lineForRow(1).text).toBe '1a' - expect(displayBuffer.lineForRow(2).text).toBe 'b' - expect(displayBuffer.lineForRow(2).fold).toBeUndefined() - expect(displayBuffer.lineForRow(3).text).toBe 'c' + expect(displayBuffer.tokenizedLineForRow(1).text).toBe '1a' + expect(displayBuffer.tokenizedLineForRow(2).text).toBe 'b' + expect(displayBuffer.tokenizedLineForRow(2).fold).toBeUndefined() + expect(displayBuffer.tokenizedLineForRow(3).text).toBe 'c' describe "when the old range follows a fold", -> it "re-positions the screen ranges for the change event based on the preceding fold", -> buffer.setTextInRange([[10, 0], [11, 0]], 'abc') - expect(displayBuffer.lineForRow(1).text).toBe "1" - expect(displayBuffer.lineForRow(2).fold).toBe fold1 - expect(displayBuffer.lineForRow(3).text).toBe "5" - expect(displayBuffer.lineForRow(4).fold).toBe fold2 - expect(displayBuffer.lineForRow(5).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForRow(3).text).toBe "5" + expect(displayBuffer.tokenizedLineForRow(4).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(5).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 6, end: 7, screenDelta: -1, bufferDelta: -1) @@ -449,12 +449,12 @@ describe "DisplayBuffer", -> expect(fold1.getStartRow()).toBe 2 expect(fold1.getEndRow()).toBe 5 - expect(displayBuffer.lineForRow(1).text).toBe "1" - expect(displayBuffer.lineForRow(2).text).toBe "2" - expect(displayBuffer.lineForRow(2).fold).toBe fold1 - expect(displayBuffer.lineForRow(3).text).toMatch "5" - expect(displayBuffer.lineForRow(4).fold).toBe fold2 - expect(displayBuffer.lineForRow(5).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForRow(2).text).toBe "2" + expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForRow(3).text).toMatch "5" + expect(displayBuffer.tokenizedLineForRow(4).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(5).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 2, screenDelta: 0, bufferDelta: 1) @@ -464,12 +464,12 @@ describe "DisplayBuffer", -> expect(fold1.getStartRow()).toBe 2 expect(fold1.getEndRow()).toBe 7 - expect(displayBuffer.lineForRow(1).text).toBe "1" - expect(displayBuffer.lineForRow(2).text).toBe "2" - expect(displayBuffer.lineForRow(2).fold).toBe fold1 - expect(displayBuffer.lineForRow(3).text).toMatch "5" - expect(displayBuffer.lineForRow(4).fold).toBe fold2 - expect(displayBuffer.lineForRow(5).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForRow(2).text).toBe "2" + expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForRow(3).text).toMatch "5" + expect(displayBuffer.tokenizedLineForRow(4).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(5).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 2, screenDelta: 0, bufferDelta: 3) @@ -478,21 +478,21 @@ describe "DisplayBuffer", -> it "destroys the fold", -> fold2.destroy() buffer.setTextInRange([[3, 0], [6, 0]], 'a\n') - expect(displayBuffer.lineForRow(2).text).toBe '2' - expect(displayBuffer.lineForRow(2).fold).toBeUndefined() - expect(displayBuffer.lineForRow(3).text).toBe 'a' - expect(displayBuffer.lineForRow(4).text).toBe '6' + expect(displayBuffer.tokenizedLineForRow(2).text).toBe '2' + expect(displayBuffer.tokenizedLineForRow(2).fold).toBeUndefined() + expect(displayBuffer.tokenizedLineForRow(3).text).toBe 'a' + expect(displayBuffer.tokenizedLineForRow(4).text).toBe '6' describe "when the old range is contained to a single line in-between two folds", -> it "re-renders the line with the placeholder and re-positions the second fold", -> buffer.insert([5, 0], 'abc\n') - expect(displayBuffer.lineForRow(1).text).toBe "1" - expect(displayBuffer.lineForRow(2).fold).toBe fold1 - expect(displayBuffer.lineForRow(3).text).toMatch "abc" - expect(displayBuffer.lineForRow(4).text).toBe "5" - expect(displayBuffer.lineForRow(5).fold).toBe fold2 - expect(displayBuffer.lineForRow(6).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForRow(3).text).toMatch "abc" + expect(displayBuffer.tokenizedLineForRow(4).text).toBe "5" + expect(displayBuffer.tokenizedLineForRow(5).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForRow(6).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 3, screenDelta: 1, bufferDelta: 1) @@ -545,15 +545,15 @@ describe "DisplayBuffer", -> displayBuffer.createFold(1, 9) displayBuffer.createFold(11, 12) - expect(displayBuffer.lineForRow(1).text).toBe '1' - expect(displayBuffer.lineForRow(2).text).toBe '10' + expect(displayBuffer.tokenizedLineForRow(1).text).toBe '1' + expect(displayBuffer.tokenizedLineForRow(2).text).toBe '10' displayBuffer.unfoldBufferRow(2) - expect(displayBuffer.lineForRow(1).text).toBe '1' - expect(displayBuffer.lineForRow(2).text).toBe '2' - expect(displayBuffer.lineForRow(7).fold).toBeDefined() - expect(displayBuffer.lineForRow(8).text).toMatch /^9-+/ - expect(displayBuffer.lineForRow(10).fold).toBeDefined() + expect(displayBuffer.tokenizedLineForRow(1).text).toBe '1' + expect(displayBuffer.tokenizedLineForRow(2).text).toBe '2' + expect(displayBuffer.tokenizedLineForRow(7).fold).toBeDefined() + expect(displayBuffer.tokenizedLineForRow(8).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForRow(10).fold).toBeDefined() describe ".outermostFoldsInBufferRowRange(startRow, endRow)", -> it "returns the outermost folds entirely contained in the given row range, exclusive of end row", -> diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 0b7121acc..8a7cbe3b4 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -377,10 +377,10 @@ class DisplayBuffer extends Model # Gets the screen line for the given screen row. # - # screenRow - A {Number} indicating the screen row. + # * `row` - A {Number} indicating the screen row. # - # Returns a {ScreenLine}. - lineForRow: (row) -> + # Returns {TokenizedLine} + tokenizedLineForRow: (row) -> @screenLines[row] # Gets the screen lines for the given screen row range. @@ -388,13 +388,13 @@ class DisplayBuffer extends Model # startRow - A {Number} indicating the beginning screen row. # endRow - A {Number} indicating the ending screen row. # - # Returns an {Array} of {ScreenLine}s. + # Returns an {Array} of {TokenizedLine}s. linesForRows: (startRow, endRow) -> @screenLines[startRow..endRow] # Gets all the screen lines. # - # Returns an {Array} of {ScreenLines}s. + # Returns an {Array} of {TokenizedLine}s. getLines: -> new Array(@screenLines...) @@ -555,7 +555,7 @@ class DisplayBuffer extends Model top = targetRow * @lineHeightInPixels left = 0 column = 0 - for token in @lineForRow(targetRow).tokens + for token in @tokenizedLineForRow(targetRow).tokens charWidths = @getScopedCharWidths(token.scopes) for char in token.value return {top, left} if column is targetColumn @@ -573,7 +573,7 @@ class DisplayBuffer extends Model left = 0 column = 0 - for token in @lineForRow(row).tokens + for token in @tokenizedLineForRow(row).tokens charWidths = @getScopedCharWidths(token.scopes) for char in token.value charWidth = charWidths[char] ? defaultCharWidth @@ -983,7 +983,7 @@ class DisplayBuffer extends Model logLines: (start=0, end=@getLastRow()) -> for row in [start..end] - line = @lineForRow(row).text + line = @tokenizedLineForRow(row).text console.log row, @bufferRowForScreenRow(row), line, line.length handleTokenizedBufferChange: (tokenizedBufferChange) => From b516f5a74d0589ed0e84627008e04f53871d4e38 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:42:43 -0700 Subject: [PATCH 098/135] lineForBufferRow -> lineTextForBufferRow --- src/editor.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/editor.coffee b/src/editor.coffee index eb4857a17..6edc16814 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -413,7 +413,10 @@ class Editor extends Model # given buffer row. # # * `row` A {Number} representing a zero-indexed buffer row. - lineForBufferRow: (row) -> @buffer.lineForRow(row) + lineTextForBufferRow: (row) -> @buffer.lineForRow(row) + lineForBufferRow: (row) -> + deprecate 'Use Editor::lineTextForBufferRow(row) instead' + @lineTextForBufferRow(row) # {Delegates to: DisplayBuffer.lineForRow} lineForScreenRow: (row) -> @displayBuffer.lineForRow(row) From 2b9b4a48efa53ee4249576affe83121fdcd85675 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 2 Sep 2014 17:46:43 -0700 Subject: [PATCH 099/135] tokenizedLineForRow -> tokenizedLineForScreenRow --- spec/display-buffer-spec.coffee | 190 ++++++++++++++++---------------- src/display-buffer.coffee | 12 +- 2 files changed, 101 insertions(+), 101 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 59ac6b6b2..f838e52f3 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -67,48 +67,48 @@ describe "DisplayBuffer", -> it "uses the preferred line length as the soft wrap column when it is less than the configured soft wrap column", -> atom.config.set('editor.preferredLineLength', 100) atom.config.set('editor.softWrapAtPreferredLineLength', true) - expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe ' return ' atom.config.set('editor.preferredLineLength', 5) - expect(displayBuffer.tokenizedLineForRow(10).text).toBe 'funct' + expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe 'funct' atom.config.set('editor.softWrapAtPreferredLineLength', false) - expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe ' return ' describe "when the line is shorter than the max line length", -> it "renders the line unchanged", -> - expect(displayBuffer.tokenizedLineForRow(0).text).toBe buffer.lineForRow(0) + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe buffer.lineForRow(0) describe "when the line is empty", -> it "renders the empty line", -> - expect(displayBuffer.tokenizedLineForRow(13).text).toBe '' + expect(displayBuffer.tokenizedLineForScreenRow(13).text).toBe '' describe "when there is a non-whitespace character at the max length boundary", -> describe "when there is whitespace before the boundary", -> it "wraps the line at the end of the first whitespace preceding the boundary", -> - expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' return ' - expect(displayBuffer.tokenizedLineForRow(11).text).toBe 'sort(left).concat(pivot).concat(sort(right));' + expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForScreenRow(11).text).toBe 'sort(left).concat(pivot).concat(sort(right));' describe "when there is no whitespace before the boundary", -> it "wraps the line exactly at the boundary since there's no more graceful place to wrap it", -> buffer.setTextInRange([[0, 0], [1, 0]], 'abcdefghijklmnopqrstuvwxyz\n') displayBuffer.setEditorWidthInChars(10) - expect(displayBuffer.tokenizedLineForRow(0).text).toBe 'abcdefghij' - expect(displayBuffer.tokenizedLineForRow(1).text).toBe 'klmnopqrst' - expect(displayBuffer.tokenizedLineForRow(2).text).toBe 'uvwxyz' + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe 'abcdefghij' + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe 'klmnopqrst' + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe 'uvwxyz' describe "when there is a whitespace character at the max length boundary", -> it "wraps the line at the first non-whitespace character following the boundary", -> - expect(displayBuffer.tokenizedLineForRow(3).text).toBe ' var pivot = items.shift(), current, left = [], ' - expect(displayBuffer.tokenizedLineForRow(4).text).toBe 'right = [];' + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe ' var pivot = items.shift(), current, left = [], ' + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe 'right = [];' describe "when there are hard tabs", -> beforeEach -> buffer.setText(buffer.getText().replace(new RegExp(' ', 'g'), '\t')) it "correctly tokenizes the hard tabs", -> - expect(displayBuffer.tokenizedLineForRow(3).tokens[0].isHardTab).toBeTruthy() - expect(displayBuffer.tokenizedLineForRow(3).tokens[1].isHardTab).toBeTruthy() + expect(displayBuffer.tokenizedLineForScreenRow(3).tokens[0].isHardTab).toBeTruthy() + expect(displayBuffer.tokenizedLineForScreenRow(3).tokens[1].isHardTab).toBeTruthy() describe "when the buffer changes", -> describe "when buffer lines are updated", -> @@ -121,8 +121,8 @@ describe "DisplayBuffer", -> describe "when the update makes a soft-wrapped line shorter than the max line length", -> it "rewraps the line and emits a change event", -> buffer.delete([[6, 24], [6, 42]]) - expect(displayBuffer.tokenizedLineForRow(7).text).toBe ' current < pivot ? : right.push(current);' - expect(displayBuffer.tokenizedLineForRow(8).text).toBe ' }' + expect(displayBuffer.tokenizedLineForScreenRow(7).text).toBe ' current < pivot ? : right.push(current);' + expect(displayBuffer.tokenizedLineForScreenRow(8).text).toBe ' }' expect(changeHandler).toHaveBeenCalled() [[event]]= changeHandler.argsForCall @@ -132,30 +132,30 @@ describe "DisplayBuffer", -> describe "when the update causes a line to softwrap an additional time", -> it "rewraps the line and emits a change event", -> buffer.insert([6, 28], '1234567890') - expect(displayBuffer.tokenizedLineForRow(7).text).toBe ' current < pivot ? ' - expect(displayBuffer.tokenizedLineForRow(8).text).toBe 'left1234567890.push(current) : ' - expect(displayBuffer.tokenizedLineForRow(9).text).toBe 'right.push(current);' - expect(displayBuffer.tokenizedLineForRow(10).text).toBe ' }' + expect(displayBuffer.tokenizedLineForScreenRow(7).text).toBe ' current < pivot ? ' + expect(displayBuffer.tokenizedLineForScreenRow(8).text).toBe 'left1234567890.push(current) : ' + expect(displayBuffer.tokenizedLineForScreenRow(9).text).toBe 'right.push(current);' + expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe ' }' expect(changeHandler).toHaveBeenCalledWith(start: 7, end: 8, screenDelta: 1, bufferDelta: 0) describe "when buffer lines are inserted", -> it "inserts / updates wrapped lines and emits a change event", -> buffer.insert([6, 21], '1234567890 abcdefghij 1234567890\nabcdefghij') - expect(displayBuffer.tokenizedLineForRow(7).text).toBe ' current < pivot1234567890 abcdefghij ' - expect(displayBuffer.tokenizedLineForRow(8).text).toBe '1234567890' - expect(displayBuffer.tokenizedLineForRow(9).text).toBe 'abcdefghij ? left.push(current) : ' - expect(displayBuffer.tokenizedLineForRow(10).text).toBe 'right.push(current);' + expect(displayBuffer.tokenizedLineForScreenRow(7).text).toBe ' current < pivot1234567890 abcdefghij ' + expect(displayBuffer.tokenizedLineForScreenRow(8).text).toBe '1234567890' + expect(displayBuffer.tokenizedLineForScreenRow(9).text).toBe 'abcdefghij ? left.push(current) : ' + expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe 'right.push(current);' expect(changeHandler).toHaveBeenCalledWith(start: 7, end: 8, screenDelta: 2, bufferDelta: 1) describe "when buffer lines are removed", -> it "removes lines and emits a change event", -> buffer.setTextInRange([[3, 21], [7, 5]], ';') - expect(displayBuffer.tokenizedLineForRow(3).text).toBe ' var pivot = items;' - expect(displayBuffer.tokenizedLineForRow(4).text).toBe ' return ' - expect(displayBuffer.tokenizedLineForRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));' - expect(displayBuffer.tokenizedLineForRow(6).text).toBe ' };' + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe ' var pivot = items;' + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe ' return ' + expect(displayBuffer.tokenizedLineForScreenRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));' + expect(displayBuffer.tokenizedLineForScreenRow(6).text).toBe ' };' expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 9, screenDelta: -6, bufferDelta: -4) @@ -169,9 +169,9 @@ describe "DisplayBuffer", -> buffer.delete([[0, Infinity], [1, 0]]) buffer.insert([0, Infinity], '\n') - expect(displayBuffer.tokenizedLineForRow(0).text).toBe "the quick brown fox jumps over " - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "the lazy dog." - expect(displayBuffer.tokenizedLineForRow(2).text).toBe "" + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe "the quick brown fox jumps over " + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "the lazy dog." + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe "" describe "position translation", -> it "translates positions accounting for wrapped lines", -> @@ -204,9 +204,9 @@ describe "DisplayBuffer", -> describe ".setEditorWidthInChars(length)", -> it "changes the length at which lines are wrapped and emits a change event for all screen lines", -> displayBuffer.setEditorWidthInChars(40) - expect(tokensText displayBuffer.tokenizedLineForRow(4).tokens).toBe 'left = [], right = [];' - expect(tokensText displayBuffer.tokenizedLineForRow(5).tokens).toBe ' while(items.length > 0) {' - expect(tokensText displayBuffer.tokenizedLineForRow(12).tokens).toBe 'sort(left).concat(pivot).concat(sort(rig' + expect(tokensText displayBuffer.tokenizedLineForScreenRow(4).tokens).toBe 'left = [], right = [];' + expect(tokensText displayBuffer.tokenizedLineForScreenRow(5).tokens).toBe ' while(items.length > 0) {' + expect(tokensText displayBuffer.tokenizedLineForScreenRow(12).tokens).toBe 'sort(left).concat(pivot).concat(sort(rig' expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 15, screenDelta: 3, bufferDelta: 0) it "only allows positive widths to be assigned", -> @@ -342,8 +342,8 @@ describe "DisplayBuffer", -> fold2 = displayBuffer.createFold(4, 9) fold1 = displayBuffer.createFold(0, 4) - expect(displayBuffer.tokenizedLineForRow(0).text).toMatch /^0/ - expect(displayBuffer.tokenizedLineForRow(1).text).toMatch /^10/ + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toMatch /^0/ + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toMatch /^10/ describe "when there is another display buffer pointing to the same buffer", -> it "does not create folds in the other display buffer", -> @@ -363,19 +363,19 @@ describe "DisplayBuffer", -> buffer.setTextInRange([[1, 0], [5, 1]], 'party!') it "removes the fold and replaces the selection with the new text", -> - expect(displayBuffer.tokenizedLineForRow(0).text).toBe "0" - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "party!" - expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(3).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe "0" + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "party!" + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 3, screenDelta: -2, bufferDelta: -4) describe "when the changes is subsequently undone", -> xit "restores destroyed folds", -> buffer.undo() - expect(displayBuffer.tokenizedLineForRow(2).text).toBe '2' - expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 - expect(displayBuffer.tokenizedLineForRow(3).text).toBe '5' + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe '2' + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe '5' describe "when the old range surrounds two nested folds", -> it "removes both folds and replaces the selection with the new text", -> @@ -384,9 +384,9 @@ describe "DisplayBuffer", -> buffer.setTextInRange([[1, 0], [10, 0]], 'goodbye') - expect(displayBuffer.tokenizedLineForRow(0).text).toBe "0" - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "goodbye10" - expect(displayBuffer.tokenizedLineForRow(2).text).toBe "11" + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe "0" + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "goodbye10" + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe "11" expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 3, screenDelta: -2, bufferDelta: -9) @@ -403,42 +403,42 @@ describe "DisplayBuffer", -> it "updates the buffer and re-positions subsequent folds", -> buffer.setTextInRange([[0, 0], [1, 1]], 'abc') - expect(displayBuffer.tokenizedLineForRow(0).text).toBe "abc" - expect(displayBuffer.tokenizedLineForRow(1).fold).toBe fold1 - expect(displayBuffer.tokenizedLineForRow(2).text).toBe "5" - expect(displayBuffer.tokenizedLineForRow(3).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(4).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe "abc" + expect(displayBuffer.tokenizedLineForScreenRow(1).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe "5" + expect(displayBuffer.tokenizedLineForScreenRow(3).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 1, screenDelta: -1, bufferDelta: -1) changeHandler.reset() fold1.destroy() - expect(displayBuffer.tokenizedLineForRow(0).text).toBe "abc" - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "2" - expect(displayBuffer.tokenizedLineForRow(3).text).toMatch /^4-+/ - expect(displayBuffer.tokenizedLineForRow(4).text).toBe "5" - expect(displayBuffer.tokenizedLineForRow(5).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(6).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe "abc" + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "2" + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toMatch /^4-+/ + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe "5" + expect(displayBuffer.tokenizedLineForScreenRow(5).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(6).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 1, screenDelta: 2, bufferDelta: 0) describe "when the old range straddles the beginning of a fold", -> it "destroys the fold", -> buffer.setTextInRange([[1, 1], [3, 0]], "a\nb\nc\nd\n") - expect(displayBuffer.tokenizedLineForRow(1).text).toBe '1a' - expect(displayBuffer.tokenizedLineForRow(2).text).toBe 'b' - expect(displayBuffer.tokenizedLineForRow(2).fold).toBeUndefined() - expect(displayBuffer.tokenizedLineForRow(3).text).toBe 'c' + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe '1a' + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe 'b' + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBeUndefined() + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe 'c' describe "when the old range follows a fold", -> it "re-positions the screen ranges for the change event based on the preceding fold", -> buffer.setTextInRange([[10, 0], [11, 0]], 'abc') - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" - expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 - expect(displayBuffer.tokenizedLineForRow(3).text).toBe "5" - expect(displayBuffer.tokenizedLineForRow(4).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(5).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe "5" + expect(displayBuffer.tokenizedLineForScreenRow(4).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(5).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 6, end: 7, screenDelta: -1, bufferDelta: -1) @@ -449,12 +449,12 @@ describe "DisplayBuffer", -> expect(fold1.getStartRow()).toBe 2 expect(fold1.getEndRow()).toBe 5 - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" - expect(displayBuffer.tokenizedLineForRow(2).text).toBe "2" - expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 - expect(displayBuffer.tokenizedLineForRow(3).text).toMatch "5" - expect(displayBuffer.tokenizedLineForRow(4).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(5).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe "2" + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toMatch "5" + expect(displayBuffer.tokenizedLineForScreenRow(4).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(5).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 2, screenDelta: 0, bufferDelta: 1) @@ -464,12 +464,12 @@ describe "DisplayBuffer", -> expect(fold1.getStartRow()).toBe 2 expect(fold1.getEndRow()).toBe 7 - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" - expect(displayBuffer.tokenizedLineForRow(2).text).toBe "2" - expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 - expect(displayBuffer.tokenizedLineForRow(3).text).toMatch "5" - expect(displayBuffer.tokenizedLineForRow(4).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(5).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe "2" + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toMatch "5" + expect(displayBuffer.tokenizedLineForScreenRow(4).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(5).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 2, screenDelta: 0, bufferDelta: 3) @@ -478,21 +478,21 @@ describe "DisplayBuffer", -> it "destroys the fold", -> fold2.destroy() buffer.setTextInRange([[3, 0], [6, 0]], 'a\n') - expect(displayBuffer.tokenizedLineForRow(2).text).toBe '2' - expect(displayBuffer.tokenizedLineForRow(2).fold).toBeUndefined() - expect(displayBuffer.tokenizedLineForRow(3).text).toBe 'a' - expect(displayBuffer.tokenizedLineForRow(4).text).toBe '6' + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe '2' + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBeUndefined() + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe 'a' + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe '6' describe "when the old range is contained to a single line in-between two folds", -> it "re-renders the line with the placeholder and re-positions the second fold", -> buffer.insert([5, 0], 'abc\n') - expect(displayBuffer.tokenizedLineForRow(1).text).toBe "1" - expect(displayBuffer.tokenizedLineForRow(2).fold).toBe fold1 - expect(displayBuffer.tokenizedLineForRow(3).text).toMatch "abc" - expect(displayBuffer.tokenizedLineForRow(4).text).toBe "5" - expect(displayBuffer.tokenizedLineForRow(5).fold).toBe fold2 - expect(displayBuffer.tokenizedLineForRow(6).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe "1" + expect(displayBuffer.tokenizedLineForScreenRow(2).fold).toBe fold1 + expect(displayBuffer.tokenizedLineForScreenRow(3).text).toMatch "abc" + expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe "5" + expect(displayBuffer.tokenizedLineForScreenRow(5).fold).toBe fold2 + expect(displayBuffer.tokenizedLineForScreenRow(6).text).toMatch /^9-+/ expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 3, screenDelta: 1, bufferDelta: 1) @@ -545,15 +545,15 @@ describe "DisplayBuffer", -> displayBuffer.createFold(1, 9) displayBuffer.createFold(11, 12) - expect(displayBuffer.tokenizedLineForRow(1).text).toBe '1' - expect(displayBuffer.tokenizedLineForRow(2).text).toBe '10' + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe '1' + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe '10' displayBuffer.unfoldBufferRow(2) - expect(displayBuffer.tokenizedLineForRow(1).text).toBe '1' - expect(displayBuffer.tokenizedLineForRow(2).text).toBe '2' - expect(displayBuffer.tokenizedLineForRow(7).fold).toBeDefined() - expect(displayBuffer.tokenizedLineForRow(8).text).toMatch /^9-+/ - expect(displayBuffer.tokenizedLineForRow(10).fold).toBeDefined() + expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe '1' + expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe '2' + expect(displayBuffer.tokenizedLineForScreenRow(7).fold).toBeDefined() + expect(displayBuffer.tokenizedLineForScreenRow(8).text).toMatch /^9-+/ + expect(displayBuffer.tokenizedLineForScreenRow(10).fold).toBeDefined() describe ".outermostFoldsInBufferRowRange(startRow, endRow)", -> it "returns the outermost folds entirely contained in the given row range, exclusive of end row", -> diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 8a7cbe3b4..5b05663d4 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -377,11 +377,11 @@ class DisplayBuffer extends Model # Gets the screen line for the given screen row. # - # * `row` - A {Number} indicating the screen row. + # * `screenRow` - A {Number} indicating the screen row. # # Returns {TokenizedLine} - tokenizedLineForRow: (row) -> - @screenLines[row] + tokenizedLineForScreenRow: (screenRow) -> + @screenLines[screenRow] # Gets the screen lines for the given screen row range. # @@ -555,7 +555,7 @@ class DisplayBuffer extends Model top = targetRow * @lineHeightInPixels left = 0 column = 0 - for token in @tokenizedLineForRow(targetRow).tokens + for token in @tokenizedLineForScreenRow(targetRow).tokens charWidths = @getScopedCharWidths(token.scopes) for char in token.value return {top, left} if column is targetColumn @@ -573,7 +573,7 @@ class DisplayBuffer extends Model left = 0 column = 0 - for token in @tokenizedLineForRow(row).tokens + for token in @tokenizedLineForScreenRow(row).tokens charWidths = @getScopedCharWidths(token.scopes) for char in token.value charWidth = charWidths[char] ? defaultCharWidth @@ -983,7 +983,7 @@ class DisplayBuffer extends Model logLines: (start=0, end=@getLastRow()) -> for row in [start..end] - line = @tokenizedLineForRow(row).text + line = @tokenizedLineForScreenRow(row).text console.log row, @bufferRowForScreenRow(row), line, line.length handleTokenizedBufferChange: (tokenizedBufferChange) => From 99f899dc4aa46ee29c8ad5e73dd5daf98cead298 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:32:23 -0700 Subject: [PATCH 100/135] lineForScreenRow -> tokenizedLineForRow The method was severely mislabeled --- spec/random-editor-spec.coffee | 2 +- spec/tokenized-buffer-spec.coffee | 309 +++++++++++++++--------------- src/display-buffer.coffee | 2 +- src/editor.coffee | 2 +- src/language-mode.coffee | 8 +- src/tokenized-buffer.coffee | 6 +- 6 files changed, 163 insertions(+), 166 deletions(-) diff --git a/spec/random-editor-spec.coffee b/spec/random-editor-spec.coffee index 1f19ec5c7..96d4f7fd0 100644 --- a/spec/random-editor-spec.coffee +++ b/spec/random-editor-spec.coffee @@ -83,7 +83,7 @@ describe "Editor", -> screenLines = [] bufferRows = [] for bufferRow in [0..tokenizedBuffer.getLastRow()] - for screenLine in softWrapLine(tokenizedBuffer.lineForScreenRow(bufferRow)) + for screenLine in softWrapLine(tokenizedBuffer.tokenizedLineForRow(bufferRow)) screenLines.push(screenLine) bufferRows.push(bufferRow) else diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index 063f75ba1..ad90c4ded 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -49,38 +49,38 @@ describe "TokenizedBuffer", -> describe "on construction", -> it "initially creates un-tokenized screen lines, then tokenizes lines chunk at a time in the background", -> - line0 = tokenizedBuffer.lineForScreenRow(0) + line0 = tokenizedBuffer.tokenizedLineForRow(0) expect(line0.tokens.length).toBe 1 expect(line0.tokens[0]).toEqual(value: line0.text, scopes: ['source.js']) - line11 = tokenizedBuffer.lineForScreenRow(11) + line11 = tokenizedBuffer.tokenizedLineForRow(11) expect(line11.tokens.length).toBe 2 expect(line11.tokens[0]).toEqual(value: " ", scopes: ['source.js'], isAtomic: true) expect(line11.tokens[1]).toEqual(value: "return sort(Array.apply(this, arguments));", scopes: ['source.js']) # background tokenization has not begun - expect(tokenizedBuffer.lineForScreenRow(0).ruleStack).toBeUndefined() + expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack).toBeUndefined() # tokenize chunk 1 advanceClock() - expect(tokenizedBuffer.lineForScreenRow(0).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(4).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(5).ruleStack?).toBeFalsy() + expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(4).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeFalsy() expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 4, delta: 0) changeHandler.reset() # tokenize chunk 2 advanceClock() - expect(tokenizedBuffer.lineForScreenRow(5).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(9).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(10).ruleStack?).toBeFalsy() + expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(9).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(10).ruleStack?).toBeFalsy() expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 9, delta: 0) changeHandler.reset() # tokenize last chunk advanceClock() - expect(tokenizedBuffer.lineForScreenRow(10).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(12).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(10).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(12).ruleStack?).toBeTruthy() expect(changeHandler).toHaveBeenCalledWith(start: 10, end: 12, delta: 0) describe "when the buffer is partially tokenized", -> @@ -134,8 +134,8 @@ describe "TokenizedBuffer", -> expect(tokenizedBuffer.firstInvalidRow()).toBe 5 buffer.setTextInRange([[6, 0], [7, 0]], "\n\n\n") - expect(tokenizedBuffer.lineForScreenRow(6).ruleStack?).toBeFalsy() - expect(tokenizedBuffer.lineForScreenRow(7).ruleStack?).toBeFalsy() + expect(tokenizedBuffer.tokenizedLineForRow(6).ruleStack?).toBeFalsy() + expect(tokenizedBuffer.tokenizedLineForRow(7).ruleStack?).toBeFalsy() changeHandler.reset() expect(tokenizedBuffer.firstInvalidRow()).toBe 5 @@ -149,10 +149,10 @@ describe "TokenizedBuffer", -> it "updates tokens to reflect the change", -> buffer.setTextInRange([[0, 0], [2, 0]], "foo()\n7\n") - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.brace.round.js']) - expect(tokenizedBuffer.lineForScreenRow(1).tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.js']) + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.brace.round.js']) + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.js']) # line 2 is unchanged - expect(tokenizedBuffer.lineForScreenRow(2).tokens[2]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js']) + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js']) expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] @@ -164,7 +164,7 @@ describe "TokenizedBuffer", -> buffer.insert([5, 30], '/* */') changeHandler.reset() buffer.insert([2, 0], '/*') - expect(tokenizedBuffer.lineForScreenRow(3).tokens[0].scopes).toEqual ['source.js'] + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js'] expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] delete event.bufferChange @@ -172,9 +172,9 @@ describe "TokenizedBuffer", -> changeHandler.reset() advanceClock() - expect(tokenizedBuffer.lineForScreenRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] delete event.bufferChange @@ -185,23 +185,23 @@ describe "TokenizedBuffer", -> buffer.insert([5, 0], '*/') buffer.insert([1, 0], 'var ') - expect(tokenizedBuffer.lineForScreenRow(1).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] describe "when lines are both updated and removed", -> it "updates tokens to reflect the change", -> buffer.setTextInRange([[1, 0], [3, 0]], "foo()") # previous line 0 remains - expect(tokenizedBuffer.lineForScreenRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js']) + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js']) # previous line 3 should be combined with input to form line 1 - expect(tokenizedBuffer.lineForScreenRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js']) - expect(tokenizedBuffer.lineForScreenRow(1).tokens[6]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js']) + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js']) + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[6]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js']) # lines below deleted regions should be shifted upward - expect(tokenizedBuffer.lineForScreenRow(2).tokens[2]).toEqual(value: 'while', scopes: ['source.js', 'keyword.control.js']) - expect(tokenizedBuffer.lineForScreenRow(3).tokens[4]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js']) - expect(tokenizedBuffer.lineForScreenRow(4).tokens[4]).toEqual(value: '<', scopes: ['source.js', 'keyword.operator.js']) + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'while', scopes: ['source.js', 'keyword.control.js']) + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[4]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js']) + expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: '<', scopes: ['source.js', 'keyword.operator.js']) expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] @@ -214,8 +214,8 @@ describe "TokenizedBuffer", -> changeHandler.reset() buffer.setTextInRange([[2, 0], [3, 0]], '/*') - expect(tokenizedBuffer.lineForScreenRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js'] - expect(tokenizedBuffer.lineForScreenRow(3).tokens[0].scopes).toEqual ['source.js'] + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js'] + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js'] expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] delete event.bufferChange @@ -223,8 +223,8 @@ describe "TokenizedBuffer", -> changeHandler.reset() advanceClock() - expect(tokenizedBuffer.lineForScreenRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] delete event.bufferChange @@ -235,19 +235,19 @@ describe "TokenizedBuffer", -> buffer.setTextInRange([[1, 0], [2, 0]], "foo()\nbar()\nbaz()\nquux()") # previous line 0 remains - expect(tokenizedBuffer.lineForScreenRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.modifier.js']) + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.modifier.js']) # 3 new lines inserted - expect(tokenizedBuffer.lineForScreenRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js']) - expect(tokenizedBuffer.lineForScreenRow(2).tokens[0]).toEqual(value: 'bar', scopes: ['source.js']) - expect(tokenizedBuffer.lineForScreenRow(3).tokens[0]).toEqual(value: 'baz', scopes: ['source.js']) + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js']) + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0]).toEqual(value: 'bar', scopes: ['source.js']) + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0]).toEqual(value: 'baz', scopes: ['source.js']) # previous line 2 is joined with quux() on line 4 - expect(tokenizedBuffer.lineForScreenRow(4).tokens[0]).toEqual(value: 'quux', scopes: ['source.js']) - expect(tokenizedBuffer.lineForScreenRow(4).tokens[4]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js']) + expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0]).toEqual(value: 'quux', scopes: ['source.js']) + expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js']) # previous line 3 is pushed down to become line 5 - expect(tokenizedBuffer.lineForScreenRow(5).tokens[4]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js']) + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[4]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js']) expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] @@ -264,17 +264,17 @@ describe "TokenizedBuffer", -> [event] = changeHandler.argsForCall[0] delete event.bufferChange expect(event).toEqual(start: 2, end: 2, delta: 2) - expect(tokenizedBuffer.lineForScreenRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js'] - expect(tokenizedBuffer.lineForScreenRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].scopes).toEqual ['source.js'] + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js'] + expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js'] changeHandler.reset() advanceClock() # tokenize invalidated lines in background - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(6).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(7).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] - expect(tokenizedBuffer.lineForScreenRow(8).tokens[0].scopes).not.toBe ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(6).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(7).tokens[0].scopes).toEqual ['source.js', 'comment.block.js'] + expect(tokenizedBuffer.tokenizedLineForRow(8).tokens[0].scopes).not.toBe ['source.js', 'comment.block.js'] expect(changeHandler).toHaveBeenCalled() [event] = changeHandler.argsForCall[0] @@ -285,13 +285,13 @@ describe "TokenizedBuffer", -> it "tokenizes the initial chunk synchronously, then tokenizes the remaining lines in the background", -> commentBlock = _.multiplyString("// a comment\n", tokenizedBuffer.chunkSize + 2) buffer.insert([0,0], commentBlock) - expect(tokenizedBuffer.lineForScreenRow(0).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(4).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(5).ruleStack?).toBeFalsy() + expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(4).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeFalsy() advanceClock() - expect(tokenizedBuffer.lineForScreenRow(5).ruleStack?).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(6).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(6).ruleStack?).toBeTruthy() describe ".findOpeningBracket(closingBufferPosition)", -> it "returns the position of the matching bracket, skipping any nested brackets", -> @@ -302,18 +302,18 @@ describe "TokenizedBuffer", -> expect(tokenizedBuffer.findClosingBracket([1, 29])).toEqual [9, 2] it "tokenizes leading whitespace based on the new tab length", -> - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].isAtomic).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].value).toBe " " - expect(tokenizedBuffer.lineForScreenRow(5).tokens[1].isAtomic).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(5).tokens[1].value).toBe " " + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].isAtomic).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].value).toBe " " + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[1].isAtomic).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[1].value).toBe " " tokenizedBuffer.setTabLength(4) fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].isAtomic).toBeTruthy() - expect(tokenizedBuffer.lineForScreenRow(5).tokens[0].value).toBe " " - expect(tokenizedBuffer.lineForScreenRow(5).tokens[1].isAtomic).toBeFalsy() - expect(tokenizedBuffer.lineForScreenRow(5).tokens[1].value).toBe " current " + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].isAtomic).toBeTruthy() + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].value).toBe " " + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[1].isAtomic).toBeFalsy() + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[1].value).toBe " current " describe "when the buffer contains hard-tabs", -> beforeEach -> @@ -335,7 +335,7 @@ describe "TokenizedBuffer", -> it "renders each tab as its own atomic token with a value of size tabLength", -> tabAsSpaces = _.multiplyString(' ', tokenizedBuffer.getTabLength()) - screenLine0 = tokenizedBuffer.lineForScreenRow(0) + screenLine0 = tokenizedBuffer.tokenizedLineForRow(0) expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}" { tokens } = screenLine0 @@ -347,7 +347,7 @@ describe "TokenizedBuffer", -> expect(tokens[2].isAtomic).toBeTruthy() expect(tokens[3].value).toBe "" - expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "#{tabAsSpaces} buy()#{tabAsSpaces}while supply > demand" + expect(tokenizedBuffer.tokenizedLineForRow(2).text).toBe "#{tabAsSpaces} buy()#{tabAsSpaces}while supply > demand" it "aligns the hard tabs to the correct tab stop column", -> buffer.setText """ @@ -359,62 +359,62 @@ describe "TokenizedBuffer", -> tokenizedBuffer.setTabLength(4) fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1 2 3 4" - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].screenDelta).toBe 3 + expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe "1 2 3 4" + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].screenDelta).toBe 3 - expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12 3 4 5" - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].screenDelta).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(1).text).toBe "12 3 4 5" + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].screenDelta).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4 5 6" - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).text).toBe "123 4 5 6" + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].screenDelta).toBe 1 tokenizedBuffer.setTabLength(3) fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1 2 3 4" - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].screenDelta).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe "1 2 3 4" + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].screenDelta).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12 3 4 5" - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(1).text).toBe "12 3 4 5" + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].screenDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4 5 6" - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].screenDelta).toBe 3 + expect(tokenizedBuffer.tokenizedLineForRow(2).text).toBe "123 4 5 6" + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].screenDelta).toBe 3 tokenizedBuffer.setTabLength(2) fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1 2 3 4" - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe "1 2 3 4" + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].screenDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12 3 4 5" - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].screenDelta).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(1).text).toBe "12 3 4 5" + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].screenDelta).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4 5 6" - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).text).toBe "123 4 5 6" + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].screenDelta).toBe 1 tokenizedBuffer.setTabLength(1) fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "1 2 3 4" - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(0).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe "1 2 3 4" + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1].screenDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(1).text).toBe "12 3 4 5" - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(1).text).toBe "12 3 4 5" + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].screenDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "123 4 5 6" - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].bufferDelta).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].screenDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).text).toBe "123 4 5 6" + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].bufferDelta).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].screenDelta).toBe 1 describe "when the buffer contains UTF-8 surrogate pairs", -> beforeEach -> @@ -435,7 +435,7 @@ describe "TokenizedBuffer", -> buffer.release() it "renders each UTF-8 surrogate pair as its own atomic token", -> - screenLine0 = tokenizedBuffer.lineForScreenRow(0) + screenLine0 = tokenizedBuffer.tokenizedLineForRow(0) expect(screenLine0.text).toBe "'abc\uD835\uDF97def'" { tokens } = screenLine0 @@ -447,7 +447,7 @@ describe "TokenizedBuffer", -> expect(tokens[3].value).toBe "def" expect(tokens[4].value).toBe "'" - screenLine1 = tokenizedBuffer.lineForScreenRow(1) + screenLine1 = tokenizedBuffer.tokenizedLineForRow(1) expect(screenLine1.text).toBe "//\uD835\uDF97xyz" { tokens } = screenLine1 @@ -525,7 +525,7 @@ describe "TokenizedBuffer", -> tokenizedBuffer.setGrammar(atom.syntax.selectGrammar('test.erb')) fullyTokenize(tokenizedBuffer) - {tokens} = tokenizedBuffer.lineForScreenRow(0) + {tokens} = tokenizedBuffer.tokenizedLineForRow(0) expect(tokens[0]).toEqual value: "
", scopes: ["text.html.ruby"] waitsForPromise -> @@ -533,7 +533,7 @@ describe "TokenizedBuffer", -> runs -> fullyTokenize(tokenizedBuffer) - {tokens} = tokenizedBuffer.lineForScreenRow(0) + {tokens} = tokenizedBuffer.tokenizedLineForRow(0) expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"] describe ".tokenForPosition(position)", -> @@ -599,9 +599,9 @@ describe "TokenizedBuffer", -> tokenizedBuffer.setInvisibles(space: 'S', tab: 'T') fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(0).text).toBe "SST Sa line with tabsTand T spacesSTS" + expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe "SST Sa line with tabsTand T spacesSTS" # Also needs to work for copies - expect(tokenizedBuffer.lineForScreenRow(0).copy().text).toBe "SST Sa line with tabsTand T spacesSTS" + expect(tokenizedBuffer.tokenizedLineForRow(0).copy().text).toBe "SST Sa line with tabsTand T spacesSTS" it "assigns endOfLineInvisibles to tokenized lines", -> buffer = new TextBuffer(text: "a line that ends in a carriage-return-line-feed \r\na line that ends in just a line-feed\na line with no ending") @@ -611,17 +611,17 @@ describe "TokenizedBuffer", -> tokenizedBuffer.setInvisibles(cr: 'R', eol: 'N') fullyTokenize(tokenizedBuffer) - expect(tokenizedBuffer.lineForScreenRow(0).endOfLineInvisibles).toEqual ['R', 'N'] - expect(tokenizedBuffer.lineForScreenRow(1).endOfLineInvisibles).toEqual ['N'] + expect(tokenizedBuffer.tokenizedLineForRow(0).endOfLineInvisibles).toEqual ['R', 'N'] + expect(tokenizedBuffer.tokenizedLineForRow(1).endOfLineInvisibles).toEqual ['N'] # Lines ending in soft wraps get no invisibles - [left, right] = tokenizedBuffer.lineForScreenRow(0).softWrapAt(20) + [left, right] = tokenizedBuffer.tokenizedLineForRow(0).softWrapAt(20) expect(left.endOfLineInvisibles).toBe null expect(right.endOfLineInvisibles).toEqual ['R', 'N'] tokenizedBuffer.setInvisibles(cr: 'R', eol: false) - expect(tokenizedBuffer.lineForScreenRow(0).endOfLineInvisibles).toEqual ['R'] - expect(tokenizedBuffer.lineForScreenRow(1).endOfLineInvisibles).toEqual [] + expect(tokenizedBuffer.tokenizedLineForRow(0).endOfLineInvisibles).toEqual ['R'] + expect(tokenizedBuffer.tokenizedLineForRow(1).endOfLineInvisibles).toEqual [] describe "leading and trailing whitespace", -> beforeEach -> @@ -630,41 +630,40 @@ describe "TokenizedBuffer", -> fullyTokenize(tokenizedBuffer) it "assigns ::firstNonWhitespaceIndex on tokens that have leading whitespace", -> - expect(tokenizedBuffer.lineForScreenRow(0).tokens[0].firstNonWhitespaceIndex).toBe null - expect(tokenizedBuffer.lineForScreenRow(1).tokens[0].firstNonWhitespaceIndex).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(1).tokens[1].firstNonWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0].firstNonWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].firstNonWhitespaceIndex).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[1].firstNonWhitespaceIndex).toBe null - expect(tokenizedBuffer.lineForScreenRow(2).tokens[0].firstNonWhitespaceIndex).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].firstNonWhitespaceIndex).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(2).tokens[2].firstNonWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].firstNonWhitespaceIndex).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1].firstNonWhitespaceIndex).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2].firstNonWhitespaceIndex).toBe null # The 4th token *has* leading whitespace, but isn't entirely whitespace buffer.insert([5, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(5).tokens[3].firstNonWhitespaceIndex).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(5).tokens[4].firstNonWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[3].firstNonWhitespaceIndex).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[4].firstNonWhitespaceIndex).toBe null # Lines that are *only* whitespace are not considered to have leading whitespace buffer.insert([10, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(10).tokens[0].firstNonWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(10).tokens[0].firstNonWhitespaceIndex).toBe null it "assigns ::firstTrailingWhitespaceIndex on tokens that have trailing whitespace", -> buffer.insert([0, Infinity], ' ') - expect(tokenizedBuffer.lineForScreenRow(0).tokens[11].firstTrailingWhitespaceIndex).toBe null - expect(tokenizedBuffer.lineForScreenRow(0).tokens[12].firstTrailingWhitespaceIndex).toBe 0 + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[11].firstTrailingWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[12].firstTrailingWhitespaceIndex).toBe 0 # The last token *has* trailing whitespace, but isn't entirely whitespace buffer.setTextInRange([[2, 39], [2, 40]], ' ') - expect(tokenizedBuffer.lineForScreenRow(2).tokens[14].firstTrailingWhitespaceIndex).toBe null - console.log tokenizedBuffer.lineForScreenRow(2).tokens[15] - expect(tokenizedBuffer.lineForScreenRow(2).tokens[15].firstTrailingWhitespaceIndex).toBe 6 + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[14].firstTrailingWhitespaceIndex).toBe null + expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[15].firstTrailingWhitespaceIndex).toBe 6 # Lines that are *only* whitespace are considered to have trailing whitespace buffer.insert([10, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(10).tokens[0].firstTrailingWhitespaceIndex).toBe 0 + expect(tokenizedBuffer.tokenizedLineForRow(10).tokens[0].firstTrailingWhitespaceIndex).toBe 0 it "only marks trailing whitespace on the last segment of a soft-wrapped line", -> buffer.insert([0, Infinity], ' ') - tokenizedLine = tokenizedBuffer.lineForScreenRow(0) + tokenizedLine = tokenizedBuffer.tokenizedLineForRow(0) [segment1, segment2] = tokenizedLine.softWrapAt(16) expect(segment1.tokens[5].value).toBe ' ' expect(segment1.tokens[5].firstTrailingWhitespaceIndex).toBe null @@ -677,7 +676,7 @@ describe "TokenizedBuffer", -> tokenizedBuffer.setInvisibles(space: 'S', tab: 'T') fullyTokenize(tokenizedBuffer) - line = tokenizedBuffer.lineForScreenRow(0).copy() + line = tokenizedBuffer.tokenizedLineForRow(0).copy() expect(line.tokens[0].firstNonWhitespaceIndex).toBe 2 expect(line.tokens[line.tokens.length - 1].firstTrailingWhitespaceIndex).toBe 0 @@ -704,55 +703,55 @@ describe "TokenizedBuffer", -> describe "when the line is non-empty", -> it "has an indent level based on the leading whitespace on the line", -> - expect(tokenizedBuffer.lineForScreenRow(0).indentLevel).toBe 0 - expect(tokenizedBuffer.lineForScreenRow(1).indentLevel).toBe 1 - expect(tokenizedBuffer.lineForScreenRow(2).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(0).indentLevel).toBe 0 + expect(tokenizedBuffer.tokenizedLineForRow(1).indentLevel).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(2).indentLevel).toBe 2 buffer.insert([2, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(2).indentLevel).toBe 2.5 + expect(tokenizedBuffer.tokenizedLineForRow(2).indentLevel).toBe 2.5 describe "when the line is empty", -> it "assumes the indentation level of the first non-empty line below or above if one exists", -> buffer.insert([12, 0], ' ') buffer.insert([12, Infinity], '\n\n') - expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(14).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(13).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(14).indentLevel).toBe 2 buffer.insert([1, Infinity], '\n\n') - expect(tokenizedBuffer.lineForScreenRow(2).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(3).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(2).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(3).indentLevel).toBe 2 buffer.setText('\n\n\n') - expect(tokenizedBuffer.lineForScreenRow(1).indentLevel).toBe 0 + expect(tokenizedBuffer.tokenizedLineForRow(1).indentLevel).toBe 0 describe "when the changed lines are surrounded by whitespace-only lines", -> it "updates the indentLevel of empty lines that precede the change", -> - expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 0 + expect(tokenizedBuffer.tokenizedLineForRow(12).indentLevel).toBe 0 buffer.insert([12, 0], '\n') buffer.insert([13, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(12).indentLevel).toBe 1 it "updates empty line indent guides when the empty line is the last line", -> buffer.insert([12, 2], '\n') # The newline and he tab need to be in two different operations to surface the bug buffer.insert([12, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 1 + expect(tokenizedBuffer.tokenizedLineForRow(13).indentLevel).toBe 1 buffer.insert([12, 0], ' ') - expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(14)).not.toBeDefined() + expect(tokenizedBuffer.tokenizedLineForRow(13).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(14)).not.toBeDefined() it "updates the indentLevel of empty lines surrounding a change that inserts lines", -> # create some new lines buffer.insert([7, 0], '\n\n') buffer.insert([5, 0], '\n\n') - expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 3 - expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 3 - expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 3 - expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 3 - expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(5).indentLevel).toBe 3 + expect(tokenizedBuffer.tokenizedLineForRow(6).indentLevel).toBe 3 + expect(tokenizedBuffer.tokenizedLineForRow(9).indentLevel).toBe 3 + expect(tokenizedBuffer.tokenizedLineForRow(10).indentLevel).toBe 3 + expect(tokenizedBuffer.tokenizedLineForRow(11).indentLevel).toBe 2 tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler') @@ -761,11 +760,11 @@ describe "TokenizedBuffer", -> delete changeHandler.argsForCall[0][0].bufferChange expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: 2) - expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 4 - expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 4 - expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 4 - expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 4 - expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(5).indentLevel).toBe 4 + expect(tokenizedBuffer.tokenizedLineForRow(6).indentLevel).toBe 4 + expect(tokenizedBuffer.tokenizedLineForRow(11).indentLevel).toBe 4 + expect(tokenizedBuffer.tokenizedLineForRow(12).indentLevel).toBe 4 + expect(tokenizedBuffer.tokenizedLineForRow(13).indentLevel).toBe 2 it "updates the indentLevel of empty lines surrounding a change that removes lines", -> # create some new lines @@ -779,9 +778,9 @@ describe "TokenizedBuffer", -> delete changeHandler.argsForCall[0][0].bufferChange expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 10, delta: -1) - expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(7).indentLevel).toBe 2 # new text - expect(tokenizedBuffer.lineForScreenRow(8).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 2 - expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 2 # } + expect(tokenizedBuffer.tokenizedLineForRow(5).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(6).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(7).indentLevel).toBe 2 # new text + expect(tokenizedBuffer.tokenizedLineForRow(8).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(9).indentLevel).toBe 2 + expect(tokenizedBuffer.tokenizedLineForRow(10).indentLevel).toBe 2 # } diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 5b05663d4..8bfb4d5b0 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -1024,7 +1024,7 @@ class DisplayBuffer extends Model bufferRow = startBufferRow while bufferRow < endBufferRow - tokenizedLine = @tokenizedBuffer.lineForScreenRow(bufferRow) + tokenizedLine = @tokenizedBuffer.tokenizedLineForRow(bufferRow) if fold = @largestFoldStartingAtBufferRow(bufferRow) foldLine = tokenizedLine.copy() diff --git a/src/editor.coffee b/src/editor.coffee index 6edc16814..9fd68096a 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -837,7 +837,7 @@ class Editor extends Model # whitespace. usesSoftTabs: -> for bufferRow in [0..@buffer.getLastRow()] - continue if @displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment() + continue if @displayBuffer.tokenizedBuffer.tokenizedLineForRow(bufferRow).isComment() line = @buffer.lineForRow(bufferRow) return true if line[0] is ' ' diff --git a/src/language-mode.coffee b/src/language-mode.coffee index 4bbffcc73..acd96508f 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -145,17 +145,17 @@ class LanguageMode rowRange rowRangeForCommentAtBufferRow: (bufferRow) -> - return unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment() + return unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(bufferRow).isComment() startRow = bufferRow for currentRow in [bufferRow-1..0] break if @buffer.isRowBlank(currentRow) - break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment() + break unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(currentRow).isComment() startRow = currentRow endRow = bufferRow for currentRow in [bufferRow+1..@buffer.getLastRow()] break if @buffer.isRowBlank(currentRow) - break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment() + break unless @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(currentRow).isComment() endRow = currentRow return [startRow, endRow] if startRow isnt endRow @@ -201,7 +201,7 @@ class LanguageMode # row is a comment. isLineCommentedAtBufferRow: (bufferRow) -> return false unless 0 <= bufferRow <= @editor.getLastBufferRow() - @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment() + @editor.displayBuffer.tokenizedBuffer.tokenizedLineForRow(bufferRow).isComment() # Find a row range for a 'paragraph' around specified bufferRow. # Right now, a paragraph is a block of text bounded by and empty line or a diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 89abf98d5..82058a47c 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -221,10 +221,8 @@ class TokenizedBuffer extends Model {tokens, ruleStack} = @grammar.tokenizeLine(line, ruleStack, row is 0) new TokenizedLine({tokens, ruleStack, tabLength, lineEnding, indentLevel, @invisibles}) - # FIXME: benogle says: These are actually buffer rows as all buffer rows are - # accounted for in @tokenizedLines - lineForScreenRow: (row) -> - @linesForScreenRows(row, row)[0] + tokenizedLineForRow: (bufferRow) -> + @tokenizedLines[bufferRow] # FIXME: benogle says: These are actually buffer rows as all buffer rows are # accounted for in @tokenizedLines From dbb0ff9830236c6fc241b2ffb2e6f6536d8563f1 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:32:58 -0700 Subject: [PATCH 101/135] Remove unused method --- src/tokenized-buffer.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 82058a47c..9b26703bf 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -224,10 +224,6 @@ class TokenizedBuffer extends Model tokenizedLineForRow: (bufferRow) -> @tokenizedLines[bufferRow] - # FIXME: benogle says: These are actually buffer rows as all buffer rows are - # accounted for in @tokenizedLines - linesForScreenRows: (startRow, endRow) -> - @tokenizedLines[startRow..endRow] stackForRow: (row) -> @tokenizedLines[row]?.ruleStack From cdbbec91f06e8d3765acbe366336ef500435f448 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:33:10 -0700 Subject: [PATCH 102/135] row -> bufferRow for clarity --- src/tokenized-buffer.coffee | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 9b26703bf..8ec1435ac 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -224,16 +224,15 @@ class TokenizedBuffer extends Model tokenizedLineForRow: (bufferRow) -> @tokenizedLines[bufferRow] + stackForRow: (bufferRow) -> + @tokenizedLines[bufferRow]?.ruleStack - stackForRow: (row) -> - @tokenizedLines[row]?.ruleStack - - indentLevelForRow: (row) -> - line = @buffer.lineForRow(row) + indentLevelForRow: (bufferRow) -> + line = @buffer.lineForRow(bufferRow) indentLevel = 0 if line is '' - nextRow = row + 1 + nextRow = bufferRow + 1 lineCount = @getLineCount() while nextRow < lineCount nextLine = @buffer.lineForRow(nextRow) @@ -242,7 +241,7 @@ class TokenizedBuffer extends Model break nextRow++ - previousRow = row - 1 + previousRow = bufferRow - 1 while previousRow >= 0 previousLine = @buffer.lineForRow(previousRow) unless previousLine is '' From ae49fd50b7edacb4a6202245dfea71c51ec48b12 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:41:26 -0700 Subject: [PATCH 103/135] DisplayBuffer::linesForRows -> ::tokenizedLinesForScreenRows Clarity! --- spec/display-buffer-spec.coffee | 18 +++++++++--------- src/display-buffer.coffee | 2 +- src/editor.coffee | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index f838e52f3..75e906376 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -242,7 +242,7 @@ describe "DisplayBuffer", -> fold = displayBuffer.createFold(4, 7) expect(fold).toBeDefined() - [line4, line5] = displayBuffer.linesForRows(4, 5) + [line4, line5] = displayBuffer.tokenizedLinesForScreenRows(4, 5) expect(line4.fold).toBe fold expect(line4.text).toMatch /^4-+/ expect(line5.text).toBe '8' @@ -251,7 +251,7 @@ describe "DisplayBuffer", -> changeHandler.reset() fold.destroy() - [line4, line5] = displayBuffer.linesForRows(4, 5) + [line4, line5] = displayBuffer.tokenizedLinesForScreenRows(4, 5) expect(line4.fold).toBeUndefined() expect(line4.text).toMatch /^4-+/ expect(line5.text).toBe '5' @@ -262,7 +262,7 @@ describe "DisplayBuffer", -> it "renders a fold placeholder for the folded line but does not skip any lines", -> fold = displayBuffer.createFold(4, 4) - [line4, line5] = displayBuffer.linesForRows(4, 5) + [line4, line5] = displayBuffer.tokenizedLinesForScreenRows(4, 5) expect(line4.fold).toBe fold expect(line4.text).toMatch /^4-+/ expect(line5.text).toBe '5' @@ -275,7 +275,7 @@ describe "DisplayBuffer", -> fold.destroy() - [line4, line5] = displayBuffer.linesForRows(4, 5) + [line4, line5] = displayBuffer.tokenizedLinesForScreenRows(4, 5) expect(line4.fold).toBeUndefined() expect(line4.text).toMatch /^4-+/ expect(line5.text).toBe '5' @@ -287,13 +287,13 @@ describe "DisplayBuffer", -> innerFold = displayBuffer.createFold(6, 7) outerFold = displayBuffer.createFold(4, 8) - [line4, line5] = displayBuffer.linesForRows(4, 5) + [line4, line5] = displayBuffer.tokenizedLinesForScreenRows(4, 5) expect(line4.fold).toBe outerFold expect(line4.text).toMatch /4-+/ expect(line5.text).toMatch /9-+/ outerFold.destroy() - [line4, line5, line6, line7] = displayBuffer.linesForRows(4, 7) + [line4, line5, line6, line7] = displayBuffer.tokenizedLinesForScreenRows(4, 7) expect(line4.fold).toBeUndefined() expect(line4.text).toMatch /^4-+/ expect(line5.text).toBe '5' @@ -305,7 +305,7 @@ describe "DisplayBuffer", -> innerFold = displayBuffer.createFold(4, 6) outerFold = displayBuffer.createFold(4, 8) - [line4, line5] = displayBuffer.linesForRows(4, 5) + [line4, line5] = displayBuffer.tokenizedLinesForScreenRows(4, 5) expect(line4.fold).toBe outerFold expect(line4.text).toMatch /4-+/ expect(line5.text).toMatch /9-+/ @@ -326,14 +326,14 @@ describe "DisplayBuffer", -> innerFold = displayBuffer.createFold(2, 5) expect(changeHandler).not.toHaveBeenCalled() - [line0, line1] = displayBuffer.linesForRows(0, 1) + [line0, line1] = displayBuffer.tokenizedLinesForScreenRows(0, 1) expect(line0.fold).toBe outerFold expect(line1.fold).toBeUndefined() changeHandler.reset() innerFold.destroy() expect(changeHandler).not.toHaveBeenCalled() - [line0, line1] = displayBuffer.linesForRows(0, 1) + [line0, line1] = displayBuffer.tokenizedLinesForScreenRows(0, 1) expect(line0.fold).toBe outerFold expect(line1.fold).toBeUndefined() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 8bfb4d5b0..ef5b4e9ad 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -389,7 +389,7 @@ class DisplayBuffer extends Model # endRow - A {Number} indicating the ending screen row. # # Returns an {Array} of {TokenizedLine}s. - linesForRows: (startRow, endRow) -> + tokenizedLinesForScreenRows: (startRow, endRow) -> @screenLines[startRow..endRow] # Gets all the screen lines. diff --git a/src/editor.coffee b/src/editor.coffee index 9fd68096a..d37a159a9 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -421,8 +421,8 @@ class Editor extends Model # {Delegates to: DisplayBuffer.lineForRow} lineForScreenRow: (row) -> @displayBuffer.lineForRow(row) - # {Delegates to: DisplayBuffer.linesForRows} - linesForScreenRows: (start, end) -> @displayBuffer.linesForRows(start, end) + # {Delegates to: DisplayBuffer.tokenizedLinesForScreenRows} + linesForScreenRows: (start, end) -> @displayBuffer.tokenizedLinesForScreenRows(start, end) # Public: Returns a {Number} representing the line length for the given # buffer row, exclusive of its line-ending character(s). From c4265776b3b3410938785e1a1449377c10d4d594 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:42:16 -0700 Subject: [PATCH 104/135] Rename unused method --- src/display-buffer.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index ef5b4e9ad..5146f1816 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -395,7 +395,7 @@ class DisplayBuffer extends Model # Gets all the screen lines. # # Returns an {Array} of {TokenizedLine}s. - getLines: -> + getTokenizedLines: -> new Array(@screenLines...) indentLevelForLine: (line) -> From e3a0339fe30cc6f49972f91abed07ac0cd187787 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:49:52 -0700 Subject: [PATCH 105/135] Editor::lineForScreenRow -> ::tokenizedLineForScreenRow --- spec/editor-component-spec.coffee | 12 ++++----- spec/editor-spec.coffee | 42 +++++++++++++++---------------- spec/language-mode-spec.coffee | 36 +++++++++++++------------- spec/random-editor-spec.coffee | 2 +- spec/tokenized-line-spec.coffee | 14 +++++------ src/editor.coffee | 9 +++++++ src/tokenized-buffer.coffee | 2 +- 7 files changed, 63 insertions(+), 54 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 4d874eb0a..330ed6577 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -65,9 +65,9 @@ describe "EditorComponent", -> linesNode = componentNode.querySelector('.lines') expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)" expect(componentNode.querySelectorAll('.line').length).toBe 6 + 2 # no margin above - expect(component.lineNodeForScreenRow(0).textContent).toBe editor.lineForScreenRow(0).text + expect(component.lineNodeForScreenRow(0).textContent).toBe editor.tokenizedLineForScreenRow(0).text expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0 - expect(component.lineNodeForScreenRow(5).textContent).toBe editor.lineForScreenRow(5).text + expect(component.lineNodeForScreenRow(5).textContent).toBe editor.tokenizedLineForScreenRow(5).text expect(component.lineNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels @@ -77,9 +77,9 @@ describe "EditorComponent", -> expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, #{-4.5 * lineHeightInPixels}px, 0px)" expect(componentNode.querySelectorAll('.line').length).toBe 6 + 4 # margin above and below expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels - expect(component.lineNodeForScreenRow(2).textContent).toBe editor.lineForScreenRow(2).text + expect(component.lineNodeForScreenRow(2).textContent).toBe editor.tokenizedLineForScreenRow(2).text expect(component.lineNodeForScreenRow(9).offsetTop).toBe 9 * lineHeightInPixels - expect(component.lineNodeForScreenRow(9).textContent).toBe editor.lineForScreenRow(9).text + expect(component.lineNodeForScreenRow(9).textContent).toBe editor.tokenizedLineForScreenRow(9).text it "updates the top position of subsequent lines when lines are inserted or removed", -> editor.getBuffer().deleteRows(0, 1) @@ -111,11 +111,11 @@ describe "EditorComponent", -> buffer.insert([0, 0], '\n\n') nextAnimationFrame() - expect(component.lineNodeForScreenRow(3).textContent).toBe editor.lineForScreenRow(3).text + expect(component.lineNodeForScreenRow(3).textContent).toBe editor.tokenizedLineForScreenRow(3).text buffer.delete([[0, 0], [3, 0]]) nextAnimationFrame() - expect(component.lineNodeForScreenRow(3).textContent).toBe editor.lineForScreenRow(3).text + expect(component.lineNodeForScreenRow(3).textContent).toBe editor.tokenizedLineForScreenRow(3).text it "updates the top position of lines when the line height changes", -> initialLineHeightInPixels = editor.getLineHeightInPixels() diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 89e4f8480..b41e32a6e 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1262,10 +1262,10 @@ describe "Editor", -> editor.createFold(10, 11) editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[6, 6], [7, 7]]]) - expect(editor.lineForScreenRow(1).fold).toBeUndefined() - expect(editor.lineForScreenRow(2).fold).toBeUndefined() - expect(editor.lineForScreenRow(6).fold).toBeUndefined() - expect(editor.lineForScreenRow(10).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(1).fold).toBeUndefined() + expect(editor.tokenizedLineForScreenRow(2).fold).toBeUndefined() + expect(editor.tokenizedLineForScreenRow(6).fold).toBeUndefined() + expect(editor.tokenizedLineForScreenRow(10).fold).toBeDefined() describe "when the 'preserveFolds' option is true", -> it "does not remove folds that contain the selections", -> @@ -1653,7 +1653,7 @@ describe "Editor", -> editor.createFold(2,4) editor.setSelectedBufferRange([[1,0], [2,0]]) editor.insertText('holy cow') - expect(editor.lineForScreenRow(2).fold).toBeUndefined() + expect(editor.tokenizedLineForScreenRow(2).fold).toBeUndefined() describe "when will-insert-text and did-insert-text events are used", -> beforeEach -> @@ -1978,7 +1978,7 @@ describe "Editor", -> editor.backspace() expect(buffer.lineForRow(3)).toBe " while(items.length > 0) {" - expect(editor.lineForScreenRow(3).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(3).fold).toBeDefined() describe "when there are multiple selections", -> it "removes all selected text", -> @@ -2116,7 +2116,7 @@ describe "Editor", -> editor.delete() expect(buffer.lineForRow(3)).toBe " ar pivot = items.shift(), current, left = [], right = [];" - expect(editor.lineForScreenRow(4).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(4).fold).toBeDefined() expect(editor.getCursorScreenPosition()).toEqual [3, 4] describe "when the cursor is on a folded line", -> @@ -2128,8 +2128,8 @@ describe "Editor", -> oldLine8 = buffer.lineForRow(8) editor.delete() - expect(editor.lineForScreenRow(2).text).toBe oldLine7 - expect(editor.lineForScreenRow(3).text).toBe oldLine8 + expect(editor.tokenizedLineForScreenRow(2).text).toBe oldLine7 + expect(editor.tokenizedLineForScreenRow(3).text).toBe oldLine8 describe "when there are multiple cursors", -> describe "when cursors are on the same line", -> @@ -2348,7 +2348,7 @@ describe "Editor", -> editor.setEditorWidthInChars(10) editor.setCursorScreenPosition([2, 2]) editor.cutToEndOfLine() - expect(editor.lineForScreenRow(2).text).toBe '= () {' + expect(editor.tokenizedLineForScreenRow(2).text).toBe '= () {' describe "when soft wrap is off", -> describe "when nothing is selected", -> @@ -2981,11 +2981,11 @@ describe "Editor", -> runs -> expect(editor.getGrammar()).toBe atom.syntax.nullGrammar - expect(editor.lineForScreenRow(0).tokens.length).toBe 1 + expect(editor.tokenizedLineForScreenRow(0).tokens.length).toBe 1 atom.syntax.addGrammar(jsGrammar) expect(editor.getGrammar()).toBe jsGrammar - expect(editor.lineForScreenRow(0).tokens.length).toBeGreaterThan 1 + expect(editor.tokenizedLineForScreenRow(0).tokens.length).toBeGreaterThan 1 describe "auto-indent", -> copyText = (text, {startColumn}={}) -> @@ -3242,10 +3242,10 @@ describe "Editor", -> expect(editor.getSelectedBufferRanges()).toEqual [[[3, 5], [3, 5]], [[9, 0], [14, 0]]] # folds are also duplicated - expect(editor.lineForScreenRow(5).fold).toBeDefined() - expect(editor.lineForScreenRow(7).fold).toBeDefined() - expect(editor.lineForScreenRow(7).text).toBe " while(items.length > 0) {" - expect(editor.lineForScreenRow(8).text).toBe " return sort(left).concat(pivot).concat(sort(right));" + expect(editor.tokenizedLineForScreenRow(5).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(7).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(7).text).toBe " while(items.length > 0) {" + expect(editor.tokenizedLineForScreenRow(8).text).toBe " return sort(left).concat(pivot).concat(sort(right));" it "duplicates all folded lines for empty selections on folded lines", -> editor.foldBufferRow(4) @@ -3394,7 +3394,7 @@ describe "Editor", -> runs -> editor.setText("// http://github.com") - {tokens} = editor.lineForScreenRow(0) + {tokens} = editor.tokenizedLineForScreenRow(0) expect(tokens[1].value).toBe " http://github.com" expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] @@ -3402,7 +3402,7 @@ describe "Editor", -> atom.packages.activatePackage('language-hyperlink') runs -> - {tokens} = editor.lineForScreenRow(0) + {tokens} = editor.tokenizedLineForScreenRow(0) expect(tokens[2].value).toBe "http://github.com" expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"] @@ -3414,7 +3414,7 @@ describe "Editor", -> runs -> editor.setText("// SELECT * FROM OCTOCATS") - {tokens} = editor.lineForScreenRow(0) + {tokens} = editor.tokenizedLineForScreenRow(0) expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS" expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] @@ -3422,7 +3422,7 @@ describe "Editor", -> atom.packages.activatePackage('package-with-injection-selector') runs -> - {tokens} = editor.lineForScreenRow(0) + {tokens} = editor.tokenizedLineForScreenRow(0) expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS" expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] @@ -3430,7 +3430,7 @@ describe "Editor", -> atom.packages.activatePackage('language-sql') runs -> - {tokens} = editor.lineForScreenRow(0) + {tokens} = editor.tokenizedLineForScreenRow(0) expect(tokens[2].value).toBe "SELECT" expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"] diff --git a/spec/language-mode-spec.coffee b/spec/language-mode-spec.coffee index b20ded983..fd3a4a478 100644 --- a/spec/language-mode-spec.coffee +++ b/spec/language-mode-spec.coffee @@ -275,46 +275,46 @@ describe "LanguageMode", -> it "folds every foldable line", -> languageMode.foldAll() - fold1 = editor.lineForScreenRow(0).fold + fold1 = editor.tokenizedLineForScreenRow(0).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 12] fold1.destroy() - fold2 = editor.lineForScreenRow(1).fold + fold2 = editor.tokenizedLineForScreenRow(1).fold expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 9] fold2.destroy() - fold3 = editor.lineForScreenRow(4).fold + fold3 = editor.tokenizedLineForScreenRow(4).fold expect([fold3.getStartRow(), fold3.getEndRow()]).toEqual [4, 7] describe ".foldBufferRow(bufferRow)", -> describe "when bufferRow can be folded", -> it "creates a fold based on the syntactic region starting at the given row", -> languageMode.foldBufferRow(1) - fold = editor.lineForScreenRow(1).fold + fold = editor.tokenizedLineForScreenRow(1).fold expect(fold.getStartRow()).toBe 1 expect(fold.getEndRow()).toBe 9 describe "when bufferRow can't be folded", -> it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", -> languageMode.foldBufferRow(8) - fold = editor.lineForScreenRow(1).fold + fold = editor.tokenizedLineForScreenRow(1).fold expect(fold.getStartRow()).toBe 1 expect(fold.getEndRow()).toBe 9 describe "when the bufferRow is already folded", -> it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", -> languageMode.foldBufferRow(2) - expect(editor.lineForScreenRow(1).fold).toBeDefined() - expect(editor.lineForScreenRow(0).fold).not.toBeDefined() + expect(editor.tokenizedLineForScreenRow(1).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(0).fold).not.toBeDefined() languageMode.foldBufferRow(1) - expect(editor.lineForScreenRow(0).fold).toBeDefined() + expect(editor.tokenizedLineForScreenRow(0).fold).toBeDefined() describe "when the bufferRow is in a multi-line comment", -> it "searches upward and downward for surrounding comment lines and folds them as a single fold", -> buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment") languageMode.foldBufferRow(1) - fold = editor.lineForScreenRow(1).fold + fold = editor.tokenizedLineForScreenRow(1).fold expect(fold.getStartRow()).toBe 1 expect(fold.getEndRow()).toBe 3 @@ -322,7 +322,7 @@ describe "LanguageMode", -> it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", -> buffer.insert([1,0], " //this is a single line comment\n") languageMode.foldBufferRow(1) - fold = editor.lineForScreenRow(0).fold + fold = editor.tokenizedLineForScreenRow(0).fold expect(fold.getStartRow()).toBe 0 expect(fold.getEndRow()).toBe 13 @@ -357,38 +357,38 @@ describe "LanguageMode", -> it "folds every foldable line", -> languageMode.foldAll() - fold1 = editor.lineForScreenRow(0).fold + fold1 = editor.tokenizedLineForScreenRow(0).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19] fold1.destroy() - fold2 = editor.lineForScreenRow(1).fold + fold2 = editor.tokenizedLineForScreenRow(1).fold expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 4] - fold3 = editor.lineForScreenRow(2).fold.destroy() + fold3 = editor.tokenizedLineForScreenRow(2).fold.destroy() - fold4 = editor.lineForScreenRow(3).fold + fold4 = editor.tokenizedLineForScreenRow(3).fold expect([fold4.getStartRow(), fold4.getEndRow()]).toEqual [6, 8] describe ".foldAllAtIndentLevel()", -> it "folds every foldable range at a given indentLevel", -> languageMode.foldAllAtIndentLevel(2) - fold1 = editor.lineForScreenRow(6).fold + fold1 = editor.tokenizedLineForScreenRow(6).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [6, 8] fold1.destroy() - fold2 = editor.lineForScreenRow(11).fold + fold2 = editor.tokenizedLineForScreenRow(11).fold expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [11, 14] fold2.destroy() it "does not fold anything but the indentLevel", -> languageMode.foldAllAtIndentLevel(0) - fold1 = editor.lineForScreenRow(0).fold + fold1 = editor.tokenizedLineForScreenRow(0).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19] fold1.destroy() - fold2 = editor.lineForScreenRow(5).fold + fold2 = editor.tokenizedLineForScreenRow(5).fold expect(fold2).toBeFalsy() describe ".isFoldableAtBufferRow(bufferRow)", -> diff --git a/spec/random-editor-spec.coffee b/spec/random-editor-spec.coffee index 96d4f7fd0..33d941115 100644 --- a/spec/random-editor-spec.coffee +++ b/spec/random-editor-spec.coffee @@ -35,7 +35,7 @@ describe "Editor", -> logLines() throw new Error("Invalid buffer row #{actualBufferRow} for screen row #{screenRow}", ) - actualScreenLine = editor.lineForScreenRow(screenRow) + actualScreenLine = editor.tokenizedLineForScreenRow(screenRow) unless actualScreenLine.text is referenceScreenLine.text logLines() throw new Error("Invalid line text at screen row #{screenRow}") diff --git a/spec/tokenized-line-spec.coffee b/spec/tokenized-line-spec.coffee index 9e1507468..ec03524be 100644 --- a/spec/tokenized-line-spec.coffee +++ b/spec/tokenized-line-spec.coffee @@ -10,13 +10,13 @@ describe "TokenizedLine", -> atom.project.open('coffee.coffee').then (o) -> editor = o it "returns true when the line is only whitespace", -> - expect(editor.lineForScreenRow(3).isOnlyWhitespace()).toBe true - expect(editor.lineForScreenRow(7).isOnlyWhitespace()).toBe true - expect(editor.lineForScreenRow(23).isOnlyWhitespace()).toBe true + expect(editor.tokenizedLineForScreenRow(3).isOnlyWhitespace()).toBe true + expect(editor.tokenizedLineForScreenRow(7).isOnlyWhitespace()).toBe true + expect(editor.tokenizedLineForScreenRow(23).isOnlyWhitespace()).toBe true it "returns false when the line is not only whitespace", -> - expect(editor.lineForScreenRow(0).isOnlyWhitespace()).toBe false - expect(editor.lineForScreenRow(2).isOnlyWhitespace()).toBe false + expect(editor.tokenizedLineForScreenRow(0).isOnlyWhitespace()).toBe false + expect(editor.tokenizedLineForScreenRow(2).isOnlyWhitespace()).toBe false describe "::getScopeTree()", -> it "returns a tree whose inner nodes are scopes and whose leaf nodes are tokens in those scopes", -> @@ -35,6 +35,6 @@ describe "TokenizedLine", -> runs -> tokenIndex = 0 - tokens = editor.lineForScreenRow(1).tokens - scopeTree = editor.lineForScreenRow(1).getScopeTree() + tokens = editor.tokenizedLineForScreenRow(1).tokens + scopeTree = editor.tokenizedLineForScreenRow(1).getScopeTree() ensureValidScopeTree(scopeTree) diff --git a/src/editor.coffee b/src/editor.coffee index d37a159a9..f756b4842 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -420,6 +420,15 @@ class Editor extends Model # {Delegates to: DisplayBuffer.lineForRow} lineForScreenRow: (row) -> @displayBuffer.lineForRow(row) + # Gets the screen line for the given screen row. + # + # * `screenRow` - A {Number} indicating the screen row. + # + # Returns {TokenizedLine} + tokenizedLineForScreenRow: (screenRow) -> @displayBuffer.tokenizedLineForScreenRow(screenRow) + lineForScreenRow: (screenRow) -> + deprecate "Editor::tokenizedLineForScreenRow(bufferRow) is the new name. But it's private. Try to use Editor::lineTextForScreenRow instead" + @tokenizedLineForScreenRow(screenRow) # {Delegates to: DisplayBuffer.tokenizedLinesForScreenRows} linesForScreenRows: (start, end) -> @displayBuffer.tokenizedLinesForScreenRows(start, end) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 8ec1435ac..79dcba5f7 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -366,5 +366,5 @@ class TokenizedBuffer extends Model logLines: (start=0, end=@buffer.getLastRow()) -> for row in [start..end] - line = @lineForScreenRow(row).text + line = @tokenizedLineForRow(row).text console.log row, line, line.length From c0c941b8dbd02f1596ba9a9bf428bbd616e9013b Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:51:57 -0700 Subject: [PATCH 106/135] lineForBufferRow -> lineTextForBufferRow --- spec/editor-component-spec.coffee | 42 ++++---- spec/editor-spec.coffee | 168 +++++++++++++++--------------- src/cursor.coffee | 4 +- src/editor.coffee | 18 ++-- src/language-mode.coffee | 8 +- 5 files changed, 119 insertions(+), 121 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 330ed6577..2cdb306e9 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -1783,28 +1783,28 @@ describe "EditorComponent", -> it "inserts the newest character in the input's value into the buffer", -> componentNode.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode)) nextAnimationFrame() - expect(editor.lineForBufferRow(0)).toBe 'xvar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'xvar quicksort = function () {' componentNode.dispatchEvent(buildTextInputEvent(data: 'y', target: inputNode)) nextAnimationFrame() - expect(editor.lineForBufferRow(0)).toBe 'xyvar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'xyvar quicksort = function () {' it "replaces the last character if the length of the input's value doesn't increase, as occurs with the accented character menu", -> componentNode.dispatchEvent(buildTextInputEvent(data: 'u', target: inputNode)) nextAnimationFrame() - expect(editor.lineForBufferRow(0)).toBe 'uvar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'uvar quicksort = function () {' # simulate the accented character suggestion's selection of the previous character inputNode.setSelectionRange(0, 1) componentNode.dispatchEvent(buildTextInputEvent(data: 'ü', target: inputNode)) nextAnimationFrame() - expect(editor.lineForBufferRow(0)).toBe 'üvar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'üvar quicksort = function () {' it "does not handle input events when input is disabled", -> component.setInputEnabled(false) componentNode.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode)) expect(nextAnimationFrame).toBe noAnimationFrame - expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () {' describe "when IME composition is used to insert international characters", -> inputNode = null @@ -1822,46 +1822,46 @@ describe "EditorComponent", -> it "inserts the chosen completion", -> componentNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode)) componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 's', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'svar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'svar quicksort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 'sd', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'sdvar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'sdvar quicksort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionend', target: inputNode)) componentNode.dispatchEvent(buildTextInputEvent(data: '速度', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe '速度var quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe '速度var quicksort = function () {' it "reverts back to the original text when the completion helper is dismissed", -> componentNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode)) componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 's', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'svar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'svar quicksort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 'sd', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'sdvar quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'sdvar quicksort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionend', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () {' it "allows multiple accented character to be inserted with the ' on a US international layout", -> inputNode.value = "'" inputNode.setSelectionRange(0, 1) componentNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode)) componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: "'", target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe "'var quicksort = function () {" + expect(editor.lineTextForBufferRow(0)).toBe "'var quicksort = function () {" componentNode.dispatchEvent(buildIMECompositionEvent('compositionend', target: inputNode)) componentNode.dispatchEvent(buildTextInputEvent(data: 'á', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe "ávar quicksort = function () {" + expect(editor.lineTextForBufferRow(0)).toBe "ávar quicksort = function () {" inputNode.value = "'" inputNode.setSelectionRange(0, 1) componentNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode)) componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: "'", target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe "á'var quicksort = function () {" + expect(editor.lineTextForBufferRow(0)).toBe "á'var quicksort = function () {" componentNode.dispatchEvent(buildIMECompositionEvent('compositionend', target: inputNode)) componentNode.dispatchEvent(buildTextInputEvent(data: 'á', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe "áávar quicksort = function () {" + expect(editor.lineTextForBufferRow(0)).toBe "áávar quicksort = function () {" describe "when a string is selected", -> beforeEach -> @@ -1870,25 +1870,25 @@ describe "EditorComponent", -> it "inserts the chosen completion", -> componentNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode)) componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 's', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var ssort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var ssort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 'sd', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var sdsort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var sdsort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionend', target: inputNode)) componentNode.dispatchEvent(buildTextInputEvent(data: '速度', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var 速度sort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var 速度sort = function () {' it "reverts back to the original text when the completion helper is dismissed", -> componentNode.dispatchEvent(buildIMECompositionEvent('compositionstart', target: inputNode)) componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 's', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var ssort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var ssort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionupdate', data: 'sd', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var sdsort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var sdsort = function () {' componentNode.dispatchEvent(buildIMECompositionEvent('compositionend', target: inputNode)) - expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () {' describe "commands", -> describe "editor:consolidate-selections", -> diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index b41e32a6e..2852af9e1 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1631,7 +1631,7 @@ describe "Editor", -> expect(selection1.isEmpty()).toBeTruthy() expect(selection2.isEmpty()).toBeTruthy() - expect(editor.lineForBufferRow(0)).toBe "var x = functix () {" + expect(editor.lineTextForBufferRow(0)).toBe "var x = functix () {" describe "when the selections are on different lines", -> it "replaces each selection with the given text, clears the selections, and places the cursor at the end of each selection's inserted text", -> @@ -1738,10 +1738,10 @@ describe "Editor", -> editor.insertNewline() - expect(editor.lineForBufferRow(3)).toBe " var pivot" - expect(editor.lineForBufferRow(4)).toBe " = items.shift(), current" - expect(editor.lineForBufferRow(5)).toBe ", left = [], right = [];" - expect(editor.lineForBufferRow(6)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(3)).toBe " var pivot" + expect(editor.lineTextForBufferRow(4)).toBe " = items.shift(), current" + expect(editor.lineTextForBufferRow(5)).toBe ", left = [], right = [];" + expect(editor.lineTextForBufferRow(6)).toBe " while(items.length > 0) {" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [4, 0] @@ -1753,13 +1753,13 @@ describe "Editor", -> editor.addCursorAtScreenPosition([6, 0]) editor.insertText("\n") - expect(editor.lineForBufferRow(3)).toBe "" - expect(editor.lineForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];" - expect(editor.lineForBufferRow(5)).toBe " while(items.length > 0) {" - expect(editor.lineForBufferRow(6)).toBe " current = items.shift();" - expect(editor.lineForBufferRow(7)).toBe "" - expect(editor.lineForBufferRow(8)).toBe " current < pivot ? left.push(current) : right.push(current);" - expect(editor.lineForBufferRow(9)).toBe " }" + expect(editor.lineTextForBufferRow(3)).toBe "" + expect(editor.lineTextForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(5)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(6)).toBe " current = items.shift();" + expect(editor.lineTextForBufferRow(7)).toBe "" + expect(editor.lineTextForBufferRow(8)).toBe " current < pivot ? left.push(current) : right.push(current);" + expect(editor.lineTextForBufferRow(9)).toBe " }" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [4,0] @@ -1787,8 +1787,8 @@ describe "Editor", -> editor.setCursorBufferPosition([0]) editor.insertNewlineAbove() expect(editor.getCursorBufferPosition()).toEqual [0,0] - expect(editor.lineForBufferRow(0)).toBe '' - expect(editor.lineForBufferRow(1)).toBe 'var quicksort = function () {' + expect(editor.lineTextForBufferRow(0)).toBe '' + expect(editor.lineTextForBufferRow(1)).toBe 'var quicksort = function () {' expect(editor.buffer.getLineCount()).toBe 14 describe "when the cursor is not on the first line", -> @@ -1796,8 +1796,8 @@ describe "Editor", -> editor.setCursorBufferPosition([3,4]) editor.insertNewlineAbove() expect(editor.getCursorBufferPosition()).toEqual [3,0] - expect(editor.lineForBufferRow(3)).toBe '' - expect(editor.lineForBufferRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(editor.lineTextForBufferRow(3)).toBe '' + expect(editor.lineTextForBufferRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' expect(editor.buffer.getLineCount()).toBe 14 editor.undo() @@ -1811,33 +1811,33 @@ describe "Editor", -> editor.insertNewlineAbove() expect(editor.getCursorBufferPosition()).toEqual [0,2] - expect(editor.lineForBufferRow(0)).toBe ' ' - expect(editor.lineForBufferRow(1)).toBe ' var test' + expect(editor.lineTextForBufferRow(0)).toBe ' ' + expect(editor.lineTextForBufferRow(1)).toBe ' var test' editor.setText('\n var test') editor.setCursorBufferPosition([1,2]) editor.insertNewlineAbove() expect(editor.getCursorBufferPosition()).toEqual [1,2] - expect(editor.lineForBufferRow(0)).toBe '' - expect(editor.lineForBufferRow(1)).toBe ' ' - expect(editor.lineForBufferRow(2)).toBe ' var test' + expect(editor.lineTextForBufferRow(0)).toBe '' + expect(editor.lineTextForBufferRow(1)).toBe ' ' + expect(editor.lineTextForBufferRow(2)).toBe ' var test' editor.setText('function() {\n}') editor.setCursorBufferPosition([1,1]) editor.insertNewlineAbove() expect(editor.getCursorBufferPosition()).toEqual [1,2] - expect(editor.lineForBufferRow(0)).toBe 'function() {' - expect(editor.lineForBufferRow(1)).toBe ' ' - expect(editor.lineForBufferRow(2)).toBe '}' + expect(editor.lineTextForBufferRow(0)).toBe 'function() {' + expect(editor.lineTextForBufferRow(1)).toBe ' ' + expect(editor.lineTextForBufferRow(2)).toBe '}' describe "when a new line is appended before a closing tag (e.g. by pressing enter before a selection)", -> it "moves the line down and keeps the indentation level the same when editor.autoIndent is true", -> atom.config.set('editor.autoIndent', true) editor.setCursorBufferPosition([9,2]) editor.insertNewline() - expect(editor.lineForBufferRow(10)).toBe ' };' + expect(editor.lineTextForBufferRow(10)).toBe ' };' describe ".backspace()", -> describe "when there is a single cursor", -> @@ -1921,7 +1921,7 @@ describe "Editor", -> editor.backspace() - expect(editor.lineForBufferRow(3)).toBe " var pivo = items.shift(), curren, left = [], right = [];" + expect(editor.lineTextForBufferRow(3)).toBe " var pivo = items.shift(), curren, left = [], right = [];" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 12] @@ -1939,8 +1939,8 @@ describe "Editor", -> editor.backspace() - expect(editor.lineForBufferRow(3)).toBe " var pivo = items.shift(), current, left = [], right = [];" - expect(editor.lineForBufferRow(4)).toBe " whileitems.length > 0) {" + expect(editor.lineTextForBufferRow(3)).toBe " var pivo = items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(4)).toBe " whileitems.length > 0) {" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 12] @@ -1956,10 +1956,10 @@ describe "Editor", -> editor.addCursorAtScreenPosition([6, 0]) editor.backspace() - expect(editor.lineForBufferRow(2)).toBe " if (items.length <= 1) return items; var pivot = items.shift(), current, left = [], right = [];" - expect(editor.lineForBufferRow(3)).toBe " while(items.length > 0) {" - expect(editor.lineForBufferRow(4)).toBe " current = items.shift(); current < pivot ? left.push(current) : right.push(current);" - expect(editor.lineForBufferRow(5)).toBe " }" + expect(editor.lineTextForBufferRow(2)).toBe " if (items.length <= 1) return items; var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(3)).toBe " while(items.length > 0) {" + expect(editor.lineTextForBufferRow(4)).toBe " current = items.shift(); current < pivot ? left.push(current) : right.push(current);" + expect(editor.lineTextForBufferRow(5)).toBe " }" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [2,40] @@ -1984,7 +1984,7 @@ describe "Editor", -> it "removes all selected text", -> editor.setSelectedBufferRanges([[[0,4], [0,13]], [[0,16], [0,24]]]) editor.backspace() - expect(editor.lineForBufferRow(0)).toBe 'var = () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var = () {' describe ".deleteToBeginningOfWord()", -> describe "when no text is selected", -> @@ -2139,7 +2139,7 @@ describe "Editor", -> editor.delete() - expect(editor.lineForBufferRow(3)).toBe " var pivot= items.shift(), current left = [], right = [];" + expect(editor.lineTextForBufferRow(3)).toBe " var pivot= items.shift(), current left = [], right = [];" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 13] @@ -2157,8 +2157,8 @@ describe "Editor", -> editor.delete() - expect(editor.lineForBufferRow(3)).toBe " var pivot= items.shift(), current, left = [], right = [];" - expect(editor.lineForBufferRow(4)).toBe " while(tems.length > 0) {" + expect(editor.lineTextForBufferRow(3)).toBe " var pivot= items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(4)).toBe " while(tems.length > 0) {" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 13] @@ -2175,7 +2175,7 @@ describe "Editor", -> editor.delete() - expect(editor.lineForBufferRow(0)).toBe "var quicksort = function () { var sort = function(items) { if (items.length <= 1) return items;" + expect(editor.lineTextForBufferRow(0)).toBe "var quicksort = function () { var sort = function(items) { if (items.length <= 1) return items;" [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,29] @@ -2194,7 +2194,7 @@ describe "Editor", -> it "removes all selected text", -> editor.setSelectedBufferRanges([[[0,4], [0,13]], [[0,16], [0,24]]]) editor.delete() - expect(editor.lineForBufferRow(0)).toBe 'var = () {' + expect(editor.lineTextForBufferRow(0)).toBe 'var = () {' describe ".deleteToEndOfWord()", -> describe "when no text is selected", -> @@ -2389,27 +2389,27 @@ describe "Editor", -> it "pastes text into the buffer", -> atom.clipboard.write('first') editor.pasteText() - expect(editor.lineForBufferRow(0)).toBe "var first = function () {" - expect(editor.lineForBufferRow(1)).toBe " var first = function(items) {" + expect(editor.lineTextForBufferRow(0)).toBe "var first = function () {" + expect(editor.lineTextForBufferRow(1)).toBe " var first = function(items) {" describe 'when the clipboard has many selections', -> it "pastes each selection separately into the buffer", -> atom.clipboard.write('first\nsecond', {selections: ['first', 'second'] }) editor.pasteText() - expect(editor.lineForBufferRow(0)).toBe "var first = function () {" - expect(editor.lineForBufferRow(1)).toBe " var second = function(items) {" + expect(editor.lineTextForBufferRow(0)).toBe "var first = function () {" + expect(editor.lineTextForBufferRow(1)).toBe " var second = function(items) {" describe 'and the selections count does not match', -> it "pastes the whole text into the buffer", -> atom.clipboard.write('first\nsecond\nthird', {selections: ['first', 'second', 'third'] }) editor.pasteText() - expect(editor.lineForBufferRow(0)).toBe "var first" - expect(editor.lineForBufferRow(1)).toBe "second" - expect(editor.lineForBufferRow(2)).toBe "third = function () {" + expect(editor.lineTextForBufferRow(0)).toBe "var first" + expect(editor.lineTextForBufferRow(1)).toBe "second" + expect(editor.lineTextForBufferRow(2)).toBe "third = function () {" - expect(editor.lineForBufferRow(3)).toBe " var first" - expect(editor.lineForBufferRow(4)).toBe "second" - expect(editor.lineForBufferRow(5)).toBe "third = function(items) {" + expect(editor.lineTextForBufferRow(3)).toBe " var first" + expect(editor.lineTextForBufferRow(4)).toBe "second" + expect(editor.lineTextForBufferRow(5)).toBe "third = function(items) {" describe ".indentSelectedRows()", -> describe "when nothing is selected", -> @@ -2889,13 +2889,13 @@ describe "Editor", -> editor.buffer.setText("abc") editor.setCursorScreenPosition([0, 1]) editor.transpose() - expect(editor.lineForBufferRow(0)).toBe 'bac' + expect(editor.lineTextForBufferRow(0)).toBe 'bac' it "reverses a selection", -> editor.buffer.setText("xabcz") editor.setSelectedBufferRange([[0, 1], [0, 4]]) editor.transpose() - expect(editor.lineForBufferRow(0)).toBe 'xcbaz' + expect(editor.lineTextForBufferRow(0)).toBe 'xcbaz' describe ".upperCase()", -> describe "when there is no selection", -> @@ -2903,7 +2903,7 @@ describe "Editor", -> editor.buffer.setText("aBc") editor.setCursorScreenPosition([0, 1]) editor.upperCase() - expect(editor.lineForBufferRow(0)).toBe 'ABC' + expect(editor.lineTextForBufferRow(0)).toBe 'ABC' expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]] describe "when there is a selection", -> @@ -2911,7 +2911,7 @@ describe "Editor", -> editor.buffer.setText("abc") editor.setSelectedBufferRange([[0,0], [0,2]]) editor.upperCase() - expect(editor.lineForBufferRow(0)).toBe 'ABc' + expect(editor.lineTextForBufferRow(0)).toBe 'ABc' expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]] describe ".lowerCase()", -> @@ -2920,7 +2920,7 @@ describe "Editor", -> editor.buffer.setText("aBC") editor.setCursorScreenPosition([0, 1]) editor.lowerCase() - expect(editor.lineForBufferRow(0)).toBe 'abc' + expect(editor.lineTextForBufferRow(0)).toBe 'abc' expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]] describe "when there is a selection", -> @@ -2928,7 +2928,7 @@ describe "Editor", -> editor.buffer.setText("ABC") editor.setSelectedBufferRange([[0,0], [0,2]]) editor.lowerCase() - expect(editor.lineForBufferRow(0)).toBe 'abC' + expect(editor.lineTextForBufferRow(0)).toBe 'abC' expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]] describe "soft-tabs detection", -> @@ -3003,11 +3003,11 @@ describe "Editor", -> it "does not auto-indent the line", -> editor.setCursorBufferPosition([1, 30]) editor.insertText("\n ") - expect(editor.lineForBufferRow(2)).toBe " " + expect(editor.lineTextForBufferRow(2)).toBe " " atom.config.set("editor.autoIndent", false) editor.indent() - expect(editor.lineForBufferRow(2)).toBe " " + expect(editor.lineTextForBufferRow(2)).toBe " " describe "when editor.autoIndent is true", -> beforeEach -> @@ -3017,11 +3017,11 @@ describe "Editor", -> it "auto-indents the line", -> editor.setCursorBufferPosition([1, 30]) editor.insertText("\n ") - expect(editor.lineForBufferRow(2)).toBe " " + expect(editor.lineTextForBufferRow(2)).toBe " " atom.config.set("editor.autoIndent", true) editor.indent() - expect(editor.lineForBufferRow(2)).toBe " " + expect(editor.lineTextForBufferRow(2)).toBe " " describe "when a newline is added", -> describe "when the line preceding the newline adds a new level of indentation", -> @@ -3085,15 +3085,15 @@ describe "Editor", -> it "doesn't break when decreasing the indentation on a row that has no indentation", -> editor.setCursorBufferPosition([12, Infinity]) editor.insertText("\n}; # too many closing brackets!") - expect(editor.lineForBufferRow(13)).toBe "}; # too many closing brackets!" + expect(editor.lineTextForBufferRow(13)).toBe "}; # too many closing brackets!" describe "when inserted text does not match a decrease indent pattern", -> it "does not decrease the indentation", -> editor.setCursorBufferPosition([12, 0]) editor.insertText(' ') - expect(editor.lineForBufferRow(12)).toBe ' };' + expect(editor.lineTextForBufferRow(12)).toBe ' };' editor.insertText('\t\t') - expect(editor.lineForBufferRow(12)).toBe ' \t\t};' + expect(editor.lineTextForBufferRow(12)).toBe ' \t\t};' describe "when the current line does not match a decrease indent pattern", -> it "leaves the line unchanged", -> @@ -3111,22 +3111,22 @@ describe "Editor", -> atom.config.set('editor.normalizeIndentOnPaste', false) editor.setCursorBufferPosition([5, 2]) editor.pasteText() - expect(editor.lineForBufferRow(5)).toBe " function() {" - expect(editor.lineForBufferRow(6)).toBe "var cool = 1;" - expect(editor.lineForBufferRow(7)).toBe " }" + expect(editor.lineTextForBufferRow(5)).toBe " function() {" + expect(editor.lineTextForBufferRow(6)).toBe "var cool = 1;" + expect(editor.lineTextForBufferRow(7)).toBe " }" describe "when the inserted text contains no newlines", -> it "does not adjust the indentation level of the text", -> editor.setCursorBufferPosition([5, 2]) editor.insertText("foo", indentBasis: 5) - expect(editor.lineForBufferRow(5)).toBe " foo current = items.shift();" + expect(editor.lineTextForBufferRow(5)).toBe " foo current = items.shift();" it "does not adjust the whitespace if there are preceding characters", -> copyText(" foo") editor.setCursorBufferPosition([5, 30]) editor.pasteText() - expect(editor.lineForBufferRow(5)).toBe " current = items.shift(); foo" + expect(editor.lineTextForBufferRow(5)).toBe " current = items.shift(); foo" describe "when the inserted text contains newlines", -> describe "when the cursor is preceded only by whitespace characters", -> @@ -3135,10 +3135,10 @@ describe "Editor", -> editor.setCursorBufferPosition([3, 4]) editor.pasteText() - expect(editor.lineForBufferRow(3)).toBe " while (true) {" - expect(editor.lineForBufferRow(4)).toBe " foo();" - expect(editor.lineForBufferRow(5)).toBe " }" - expect(editor.lineForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineTextForBufferRow(3)).toBe " while (true) {" + expect(editor.lineTextForBufferRow(4)).toBe " foo();" + expect(editor.lineTextForBufferRow(5)).toBe " }" + expect(editor.lineTextForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];" describe "when the cursor is preceded by non-whitespace characters", -> it "normalizes the indentation level of all lines based on the level of the existing first line", -> @@ -3146,10 +3146,10 @@ describe "Editor", -> editor.setCursorBufferPosition([1, Infinity]) editor.pasteText() - expect(editor.lineForBufferRow(1)).toBe " var sort = function(items) {while (true) {" - expect(editor.lineForBufferRow(2)).toBe " foo();" - expect(editor.lineForBufferRow(3)).toBe " }" - expect(editor.lineForBufferRow(4)).toBe "" + expect(editor.lineTextForBufferRow(1)).toBe " var sort = function(items) {while (true) {" + expect(editor.lineTextForBufferRow(2)).toBe " foo();" + expect(editor.lineTextForBufferRow(3)).toBe " }" + expect(editor.lineTextForBufferRow(4)).toBe "" it "autoIndentSelectedRows auto-indents the selection", -> editor.setCursorBufferPosition([2, 0]) @@ -3157,10 +3157,10 @@ describe "Editor", -> editor.getLastSelection().setBufferRange([[2,0], [6,0]]) editor.autoIndentSelectedRows() - expect(editor.lineForBufferRow(2)).toBe " function() {" - expect(editor.lineForBufferRow(3)).toBe " inside=true" - expect(editor.lineForBufferRow(4)).toBe " }" - expect(editor.lineForBufferRow(5)).toBe " i=1" + expect(editor.lineTextForBufferRow(2)).toBe " function() {" + expect(editor.lineTextForBufferRow(3)).toBe " inside=true" + expect(editor.lineTextForBufferRow(4)).toBe " }" + expect(editor.lineTextForBufferRow(5)).toBe " i=1" describe "soft and hard tabs", -> it "resets the tab style when tokenization is complete", -> @@ -3185,36 +3185,36 @@ describe "Editor", -> describe "when the line below isn't empty", -> it "joins the line below with the current line separated by a space and moves the cursor to the start of line that was moved up", -> editor.joinLines() - expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' + expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' expect(editor.getCursorBufferPosition()).toEqual [0, 30] describe "when the line below is empty", -> it "deletes the line below and moves the cursor to the end of the line", -> editor.setCursorBufferPosition([9]) editor.joinLines() - expect(editor.lineForBufferRow(9)).toBe ' };' - expect(editor.lineForBufferRow(10)).toBe ' return sort(Array.apply(this, arguments));' + expect(editor.lineTextForBufferRow(9)).toBe ' };' + expect(editor.lineTextForBufferRow(10)).toBe ' return sort(Array.apply(this, arguments));' expect(editor.getCursorBufferPosition()).toEqual [9, 4] describe "when the cursor is on the last row", -> it "does nothing", -> editor.setCursorBufferPosition([Infinity, Infinity]) editor.joinLines() - expect(editor.lineForBufferRow(12)).toBe '};' + expect(editor.lineTextForBufferRow(12)).toBe '};' describe "when text is selected", -> describe "when the selection does not span multiple lines", -> it "joins the line below with the current line separated by a space and retains the selected text", -> editor.setSelectedBufferRange([[0, 1], [0, 3]]) editor.joinLines() - expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' + expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 3]] describe "when the selection spans multiple lines", -> it "joins all selected lines separated by a space and retains the selected text", -> editor.setSelectedBufferRange([[9, 3], [12, 1]]) editor.joinLines() - expect(editor.lineForBufferRow(9)).toBe ' }; return sort(Array.apply(this, arguments)); };' + expect(editor.lineTextForBufferRow(9)).toBe ' }; return sort(Array.apply(this, arguments)); };' expect(editor.getSelectedBufferRange()).toEqual [[9, 3], [9, 49]] describe ".duplicateLines()", -> diff --git a/src/cursor.coffee b/src/cursor.coffee index 9341d8b8a..f86721d6d 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -222,7 +222,7 @@ class Cursor extends Model # Public: Returns the cursor's current buffer row of text excluding its line # ending. getCurrentBufferLine: -> - @editor.lineForBufferRow(@getBufferRow()) + @editor.lineTextForBufferRow(@getBufferRow()) # Public: Moves the cursor up one screen row. moveUp: (rowCount=1, {moveToEndOfSelection}={}) -> @@ -562,7 +562,7 @@ class Cursor extends Model # its current position. hasPrecedingCharactersOnLine: -> bufferPosition = @getBufferPosition() - line = @editor.lineForBufferRow(bufferPosition.row) + line = @editor.lineTextForBufferRow(bufferPosition.row) firstCharacterColumn = line.search(/\S/) if firstCharacterColumn is -1 diff --git a/src/editor.coffee b/src/editor.coffee index f756b4842..6503fd671 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -412,14 +412,12 @@ class Editor extends Model # Public: Returns a {String} representing the contents of the line at the # given buffer row. # - # * `row` A {Number} representing a zero-indexed buffer row. - lineTextForBufferRow: (row) -> @buffer.lineForRow(row) - lineForBufferRow: (row) -> - deprecate 'Use Editor::lineTextForBufferRow(row) instead' - @lineTextForBufferRow(row) + # * `bufferRow` A {Number} representing a zero-indexed buffer row. + lineTextForBufferRow: (bufferRow) -> @buffer.lineForRow(bufferRow) + lineForBufferRow: (bufferRow) -> + deprecate 'Use Editor::lineTextForBufferRow(bufferRow) instead' + @lineTextForBufferRow(bufferRow) - # {Delegates to: DisplayBuffer.lineForRow} - lineForScreenRow: (row) -> @displayBuffer.lineForRow(row) # Gets the screen line for the given screen row. # # * `screenRow` - A {Number} indicating the screen row. @@ -923,7 +921,7 @@ class Editor extends Model # # Returns a {Number}. indentationForBufferRow: (bufferRow) -> - @indentLevelForLine(@lineForBufferRow(bufferRow)) + @indentLevelForLine(@lineTextForBufferRow(bufferRow)) # Public: Set the indentation level for the given buffer row. # @@ -941,7 +939,7 @@ class Editor extends Model if preserveLeadingWhitespace endColumn = 0 else - endColumn = @lineForBufferRow(bufferRow).match(/^\s*/)[0].length + endColumn = @lineTextForBufferRow(bufferRow).match(/^\s*/)[0].length newIndentString = @buildIndentString(newLevel) @buffer.setTextInRange([[bufferRow, 0], [bufferRow, endColumn]], newIndentString) @@ -1188,7 +1186,7 @@ class Editor extends Model # Public: Determine if the given row is entirely a comment isBufferRowCommented: (bufferRow) -> - if match = @lineForBufferRow(bufferRow).match(/\S/) + if match = @lineTextForBufferRow(bufferRow).match(/\S/) scopes = @tokenForBufferPosition([bufferRow, match.index]).scopes new TextMateScopeSelector('comment.*').matches(scopes) diff --git a/src/language-mode.coffee b/src/language-mode.coffee index acd96508f..b224fd631 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -168,7 +168,7 @@ class LanguageMode continue if @editor.isBufferRowBlank(row) indentation = @editor.indentationForBufferRow(row) if indentation <= startIndentLevel - includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.searchSync(@editor.lineForBufferRow(row)) + includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.searchSync(@editor.lineTextForBufferRow(row)) foldEndRow = row if includeRowInFold break @@ -207,7 +207,7 @@ class LanguageMode # Right now, a paragraph is a block of text bounded by and empty line or a # block of text that is not the same type (comments next to source code). rowRangeForParagraphAtBufferRow: (bufferRow) -> - return unless /\w/.test(@editor.lineForBufferRow(bufferRow)) + return unless /\w/.test(@editor.lineTextForBufferRow(bufferRow)) if @isLineCommentedAtBufferRow(bufferRow) isOriginalRowComment = true @@ -220,14 +220,14 @@ class LanguageMode startRow = bufferRow while startRow > firstRow break if @isLineCommentedAtBufferRow(startRow - 1) != isOriginalRowComment - break unless /\w/.test(@editor.lineForBufferRow(startRow - 1)) + break unless /\w/.test(@editor.lineTextForBufferRow(startRow - 1)) startRow-- endRow = bufferRow lastRow = @editor.getLastBufferRow() while endRow < lastRow break if @isLineCommentedAtBufferRow(endRow + 1) != isOriginalRowComment - break unless /\w/.test(@editor.lineForBufferRow(endRow + 1)) + break unless /\w/.test(@editor.lineTextForBufferRow(endRow + 1)) endRow++ new Range([startRow, 0], [endRow, @editor.lineLengthForBufferRow(endRow)]) From 0703788209ed2e4d633282e6bba8461b3d738ccf Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 13:56:57 -0700 Subject: [PATCH 107/135] Editor::linesForScreenRows -> ::tokenizedLinesForScreenRows --- src/editor-component.coffee | 2 +- src/editor.coffee | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 870a984fa..3446bb6a2 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -59,7 +59,7 @@ EditorComponent = React.createClass [renderedStartRow, renderedEndRow] = renderedRowRange cursorPixelRects = @getCursorPixelRects(renderedRowRange) - tokenizedLines = editor.linesForScreenRows(renderedStartRow, renderedEndRow - 1) + tokenizedLines = editor.tokenizedLinesForScreenRows(renderedStartRow, renderedEndRow - 1) decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow) highlightDecorations = @getHighlightDecorations(decorations) diff --git a/src/editor.coffee b/src/editor.coffee index 6503fd671..7f78610cb 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -429,7 +429,10 @@ class Editor extends Model @tokenizedLineForScreenRow(screenRow) # {Delegates to: DisplayBuffer.tokenizedLinesForScreenRows} - linesForScreenRows: (start, end) -> @displayBuffer.tokenizedLinesForScreenRows(start, end) + tokenizedLinesForScreenRows: (start, end) -> @displayBuffer.tokenizedLinesForScreenRows(start, end) + linesForScreenRows: (start, end) -> + deprecate "Use Editor::tokenizedLinesForScreenRows instead" + @tokenizedLinesForScreenRows(start, end) # Public: Returns a {Number} representing the line length for the given # buffer row, exclusive of its line-ending character(s). From 5e21d1ca5b9004360b396cffd319b8676ddcff47 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 14:03:04 -0700 Subject: [PATCH 108/135] Deprecate Editor::lineLengthForBufferRow --- benchmark/benchmark-suite.coffee | 2 +- src/editor.coffee | 6 ++++-- src/language-mode.coffee | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/benchmark/benchmark-suite.coffee b/benchmark/benchmark-suite.coffee index 2984c007e..c60811985 100644 --- a/benchmark/benchmark-suite.coffee +++ b/benchmark/benchmark-suite.coffee @@ -103,7 +103,7 @@ describe "editorView.", -> benchmark "cache-entire-visible-area", 100, -> for i in [firstRow..lastRow] line = editorView.lineElementForScreenRow(i)[0] - editorView.positionLeftForLineAndColumn(line, i, Math.max(0, editorView.lineLengthForBufferRow(i))) + editorView.positionLeftForLineAndColumn(line, i, Math.max(0, editorView.getModel().lineTextForBufferRow(i).length)) describe "text-rendering.", -> beforeEach -> diff --git a/src/editor.coffee b/src/editor.coffee index 7f78610cb..8ce5c6de4 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -434,11 +434,13 @@ class Editor extends Model deprecate "Use Editor::tokenizedLinesForScreenRows instead" @tokenizedLinesForScreenRows(start, end) - # Public: Returns a {Number} representing the line length for the given + # Returns a {Number} representing the line length for the given # buffer row, exclusive of its line-ending character(s). # # * `row` A {Number} indicating the buffer row. - lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row) + lineLengthForBufferRow: (row) -> + deprecate "Use editor.lineTextForBufferRow(row).length instead" + @lineTextForBufferRow(row).length bufferRowForScreenRow: (row) -> @displayBuffer.bufferRowForScreenRow(row) diff --git a/src/language-mode.coffee b/src/language-mode.coffee index b224fd631..de1a5b928 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -230,7 +230,7 @@ class LanguageMode break unless /\w/.test(@editor.lineTextForBufferRow(endRow + 1)) endRow++ - new Range([startRow, 0], [endRow, @editor.lineLengthForBufferRow(endRow)]) + new Range([startRow, 0], [endRow, @editor.lineTextForBufferRow(endRow).length]) # Given a buffer row, this returns a suggested indentation level. # From 523a255e48ee9ee93efb663acc15a3544838a684 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 14:08:43 -0700 Subject: [PATCH 109/135] Add Editor::lineTextForScreenRow() Closes #3055 --- spec/editor-spec.coffee | 5 +++++ src/editor.coffee | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 2852af9e1..18f0b33b4 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -2773,6 +2773,11 @@ describe "Editor", -> expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor3.getBufferPosition()).toEqual [1,2] + describe 'reading text', -> + it '.lineTextForScreenRow(row)', -> + editor.foldBufferRow(4) + expect(editor.lineTextForScreenRow(5)).toEqual ' return sort(left).concat(pivot).concat(sort(right));' + describe ".deleteLine()", -> it "deletes the first line when the cursor is there", -> editor.getLastCursor().moveToTop() diff --git a/src/editor.coffee b/src/editor.coffee index 8ce5c6de4..1e809dc52 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -418,6 +418,12 @@ class Editor extends Model deprecate 'Use Editor::lineTextForBufferRow(bufferRow) instead' @lineTextForBufferRow(bufferRow) + # Public: Returns a {String} representing the contents of the line at the + # given screen row. + # + # * `screenRow` A {Number} representing a zero-indexed screen row. + lineTextForScreenRow: (screenRow) -> @displayBuffer.tokenizedLineForScreenRow(screenRow).text + # Gets the screen line for the given screen row. # # * `screenRow` - A {Number} indicating the screen row. From 873818ee52c0be8f898e1b62970e4499c7fe102d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 16:19:21 -0600 Subject: [PATCH 110/135] 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 111/135] 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 112/135] :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 113/135] 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 114/135] 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 115/135] :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 b90670ff2d50506231931b7ad1a42a53994862e2 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Wed, 3 Sep 2014 16:00:57 -0700 Subject: [PATCH 116/135] Gracefully handle the case when there is no screenline --- spec/editor-spec.coffee | 1 + src/editor.coffee | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 18f0b33b4..36eb57bee 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -2777,6 +2777,7 @@ describe "Editor", -> it '.lineTextForScreenRow(row)', -> editor.foldBufferRow(4) expect(editor.lineTextForScreenRow(5)).toEqual ' return sort(left).concat(pivot).concat(sort(right));' + expect(editor.lineTextForScreenRow(100)).not.toBeDefined() describe ".deleteLine()", -> it "deletes the first line when the cursor is there", -> diff --git a/src/editor.coffee b/src/editor.coffee index 1e809dc52..337b5da9d 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -422,7 +422,7 @@ class Editor extends Model # given screen row. # # * `screenRow` A {Number} representing a zero-indexed screen row. - lineTextForScreenRow: (screenRow) -> @displayBuffer.tokenizedLineForScreenRow(screenRow).text + lineTextForScreenRow: (screenRow) -> @displayBuffer.tokenizedLineForScreenRow(screenRow)?.text # Gets the screen line for the given screen row. # From f87f7c358a54f65e8479013062a4405679f50d34 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 3 Sep 2014 17:08:13 -0600 Subject: [PATCH 117/135] 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 118/135] 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 119/135] 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 120/135] 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 121/135] 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 122/135] 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 123/135] 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 124/135] 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 125/135] 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 126/135] 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 127/135] =?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 128/135] =?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 129/135] 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 130/135] 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 57699e62455358fa85bd8fc58f6e9a3ecf517c87 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 4 Sep 2014 06:57:46 -0600 Subject: [PATCH 131/135] 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 132/135] 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 133/135] 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 134/135] 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 135/135] 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') # ``` #