From f7b1f0521a128c881adfeedb3d6b7b5ca3b92a59 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 16 Nov 2012 07:36:13 -0700 Subject: [PATCH] Emit row-oriented events from `DisplayBuffer` --- spec/app/display-buffer-spec.coffee | 85 ++++++----------------------- spec/app/undo-manager-spec.coffee | 2 +- src/app/display-buffer.coffee | 34 +++++++++--- src/app/edit-session.coffee | 13 +---- 4 files changed, 46 insertions(+), 88 deletions(-) diff --git a/spec/app/display-buffer-spec.coffee b/spec/app/display-buffer-spec.coffee index b4d57ef52..1443b2d53 100644 --- a/spec/app/display-buffer-spec.coffee +++ b/spec/app/display-buffer-spec.coffee @@ -63,8 +63,8 @@ describe "DisplayBuffer", -> expect(changeHandler).toHaveBeenCalled() [[event]]= changeHandler.argsForCall - expect(event.oldRange).toEqual([[7, 0], [8, 20]]) - expect(event.newRange).toEqual([[7, 0], [7, 47]]) + + expect(event).toEqual(start: 7, end: 8, screenDelta: -1, bufferDelta: 0) describe "when the update causes a line to softwrap an additional time", -> it "rewraps the line and emits a change event", -> @@ -74,10 +74,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(9).text).toBe 'right.push(current);' expect(displayBuffer.lineForRow(10).text).toBe ' }' - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual([[7, 0], [8, 20]]) - expect(event.newRange).toEqual([[7, 0], [9, 20]]) + 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", -> @@ -87,10 +84,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(9).text).toBe 'abcdefghij ? left.push(current) : ' expect(displayBuffer.lineForRow(10).text).toBe 'right.push(current);' - expect(changeHandler).toHaveBeenCalled() - [event] = changeHandler.argsForCall[0] - expect(event.oldRange).toEqual([[7, 0], [8, 20]]) - expect(event.newRange).toEqual([[7, 0], [10, 20]]) + 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", -> @@ -100,10 +94,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(5).text).toBe 'sort(left).concat(pivot).concat(sort(right));' expect(displayBuffer.lineForRow(6).text).toBe ' };' - expect(changeHandler).toHaveBeenCalled() - [event] = changeHandler.argsForCall[0] - expect(event.oldRange).toEqual([[3, 0], [9, 5]]) - expect(event.newRange).toEqual([[3, 0], [3, 22]]) + expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 9, screenDelta: -6, bufferDelta: -4) describe "position translation", -> it "translates positions accounting for wrapped lines", -> @@ -134,10 +125,7 @@ describe "DisplayBuffer", -> 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(changeHandler).toHaveBeenCalled() - [event] = changeHandler.argsForCall[0] - expect(event.oldRange).toEqual([[0, 0], [15, 2]]) - expect(event.newRange).toEqual([[0, 0], [18, 2]]) + expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 15, screenDelta: 3, bufferDelta: 0) describe "structural folding", -> describe ".unfoldAll()", -> @@ -228,10 +216,7 @@ describe "DisplayBuffer", -> expect(line4.bufferRows).toBe 4 expect(line5.text).toBe '8' - expect(changeHandler).toHaveBeenCalled() - [event] = changeHandler.argsForCall[0] - expect(event.oldRange).toEqual [[4, 0], [7, 1]] - expect(event.newRange).toEqual [[4, 0], [4, 101]] + expect(changeHandler).toHaveBeenCalledWith(start: 4, end: 7, screenDelta: -3, bufferDelta: 0) changeHandler.reset() fold.destroy() @@ -241,10 +226,7 @@ describe "DisplayBuffer", -> expect(line4.bufferRows).toEqual 1 expect(line5.text).toBe '5' - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[4, 0], [4, 101]] - expect(event.newRange).toEqual [[4, 0], [7, 1]] + expect(changeHandler).toHaveBeenCalledWith(start: 4, end: 4, screenDelta: 3, bufferDelta: 0) describe "when a fold spans a single line", -> it "renders a fold placeholder for the folded line but does not skip any lines", -> @@ -256,10 +238,7 @@ describe "DisplayBuffer", -> expect(line4.bufferRows).toEqual 1 expect(line5.text).toBe '5' - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[4, 0], [4, 101]] - expect(event.newRange).toEqual [[4, 0], [4, 101]] + expect(changeHandler).toHaveBeenCalledWith(start: 4, end: 4, screenDelta: 0, bufferDelta: 0) # Line numbers don't actually change, but it's not worth the complexity to have this # be false for single line folds since they are so rare @@ -273,11 +252,7 @@ describe "DisplayBuffer", -> expect(line4.bufferRows).toEqual 1 expect(line5.text).toBe '5' - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[4, 0], [4, 101]] - expect(event.newRange).toEqual [[4, 0], [4, 101]] - changeHandler.reset() + expect(changeHandler).toHaveBeenCalledWith(start: 4, end: 4, screenDelta: 0, bufferDelta: 0) describe "when a fold is nested within another fold", -> it "does not render the placeholder for the inner fold until the outer fold is destroyed", -> @@ -355,10 +330,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(2).fold).toBe fold2 expect(displayBuffer.lineForRow(3).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[1, 0], [3, 1]] - expect(event.newRange).toEqual [[1, 0], [1, 6]] + expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 3, screenDelta: -2, bufferDelta: -4) describe "when the old range surrounds two nested folds", -> it "removes both folds and replaces the selection with the new text", -> @@ -371,10 +343,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(1).text).toBe "goodbye10" expect(displayBuffer.lineForRow(2).text).toBe "11" - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[1, 0], [3, 2]] - expect(event.newRange).toEqual [[1, 0], [1, 9]] + expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 3, screenDelta: -2, bufferDelta: -9) describe "when multiple changes happen above the fold", -> it "repositions folds correctly", -> @@ -395,10 +364,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(3).fold).toBe fold2 expect(displayBuffer.lineForRow(4).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[0, 0], [1, 1]] - expect(event.newRange).toEqual [[0, 0], [0, 3]] + expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 1, screenDelta: -1, bufferDelta: -1) changeHandler.reset() fold1.destroy() @@ -409,10 +375,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(5).fold).toBe fold2 expect(displayBuffer.lineForRow(6).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[1, 0], [1, 1]] - expect(event.newRange).toEqual [[1, 0], [3, 101]] + expect(changeHandler).toHaveBeenCalledWith(start: 1, end: 1, screenDelta: 2, bufferDelta: 0) describe "when the old range straddles the beginning of a fold", -> it "replaces lines in the portion of the range that precedes the fold and adjusts the end of the fold to encompass additional lines", -> @@ -435,10 +398,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(4).fold).toBe fold2 expect(displayBuffer.lineForRow(5).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[6, 0], [7, 2]] # Expands ranges to encompes entire line - expect(event.newRange).toEqual [[6, 0], [6, 5]] + expect(changeHandler).toHaveBeenCalledWith(start: 6, end: 7, screenDelta: -1, bufferDelta: -1) describe "when the old range is inside a fold", -> describe "when the end of the new range precedes the end of the fold", -> @@ -455,10 +415,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(4).fold).toBe fold2 expect(displayBuffer.lineForRow(5).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[2, 0], [2, 1]] - expect(event.newRange).toEqual [[2, 0], [2, 1]] + expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 2, screenDelta: 0, bufferDelta: 1) describe "when the end of the new range exceeds the end of the fold", -> it "expands the fold to contain all the inserted lines", -> @@ -474,10 +431,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(4).fold).toBe fold2 expect(displayBuffer.lineForRow(5).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[2, 0], [2, 1]] - expect(event.newRange).toEqual [[2, 0], [2, 1]] + expect(changeHandler).toHaveBeenCalledWith(start: 2, end: 2, screenDelta: 0, bufferDelta: 3) describe "when the old range straddles the end of the fold", -> describe "when the end of the new range precedes the end of the fold", -> @@ -499,10 +453,7 @@ describe "DisplayBuffer", -> expect(displayBuffer.lineForRow(5).fold).toBe fold2 expect(displayBuffer.lineForRow(6).text).toMatch /^9-+/ - expect(changeHandler).toHaveBeenCalled() - [[event]] = changeHandler.argsForCall - expect(event.oldRange).toEqual [[3, 0], [3, 1]] - expect(event.newRange).toEqual [[3, 0], [4, 1]] + expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 3, screenDelta: 1, bufferDelta: 1) describe "position translation", -> it "translates positions to account for folded lines and characters and the placeholder", -> diff --git a/spec/app/undo-manager-spec.coffee b/spec/app/undo-manager-spec.coffee index d4933f612..cd3fc0c9c 100644 --- a/spec/app/undo-manager-spec.coffee +++ b/spec/app/undo-manager-spec.coffee @@ -151,4 +151,4 @@ describe "UndoManager", -> undoManager.undo() undoManager.redo() expect(console.error).toHaveBeenCalled() - expect(buffer.lineForRow(0)).toBe "1word" \ No newline at end of file + expect(buffer.lineForRow(0)).toBe "1word" diff --git a/src/app/display-buffer.coffee b/src/app/display-buffer.coffee index 2610bd685..47f710ad0 100644 --- a/src/app/display-buffer.coffee +++ b/src/app/display-buffer.coffee @@ -32,10 +32,12 @@ class DisplayBuffer @lineMap.insertAtScreenRow 0, @buildLinesForBufferRows(0, @buffer.getLastRow()) setSoftWrapColumn: (@softWrapColumn) -> - oldRange = @rangeForAllLines() + start = 0 + end = @getLastRow() @buildLineMap() - newRange = @rangeForAllLines() - @trigger 'change', { oldRange, newRange } + screenDelta = @getLastRow() - end + bufferDelta = 0 + @trigger 'change', { start, end, screenDelta, bufferDelta } lineForRow: (row) -> @lineMap.lineForScreenRow(row) @@ -87,7 +89,11 @@ class DisplayBuffer @lineMap.replaceScreenRows(oldScreenRange.start.row, oldScreenRange.end.row, lines) newScreenRange = @screenLineRangeForBufferRange(bufferRange) - @trigger 'change', oldRange: oldScreenRange, newRange: newScreenRange + start = oldScreenRange.start.row + end = oldScreenRange.end.row + screenDelta = newScreenRange.end.row - oldScreenRange.end.row + bufferDelta = 0 + @trigger 'change', { start, end, screenDelta, bufferDelta } fold @@ -111,7 +117,12 @@ class DisplayBuffer @lineMap.replaceScreenRows(oldScreenRange.start.row, oldScreenRange.end.row, lines) newScreenRange = @screenLineRangeForBufferRange(bufferRange) - @trigger 'change', oldRange: oldScreenRange, newRange: newScreenRange + start = oldScreenRange.start.row + end = oldScreenRange.end.row + screenDelta = newScreenRange.end.row - oldScreenRange.end.row + bufferDelta = 0 + + @trigger 'change', { start, end, screenDelta, bufferDelta } destroyFoldsContainingBufferRow: (bufferRow) -> for row, folds of @activeFolds @@ -209,10 +220,15 @@ class DisplayBuffer @lineMap.replaceScreenRows oldScreenRange.start.row, oldScreenRange.end.row, newScreenLines newScreenRange = @screenLineRangeForBufferRange(newRange) - @trigger 'change', - oldRange: oldScreenRange - newRange: newScreenRange - bufferChange: e.bufferChange + start = oldScreenRange.start.row + end = oldScreenRange.end.row + screenDelta = newScreenRange.end.row - oldScreenRange.end.row + + if e.bufferChange + bufferDelta = e.bufferChange.newRange.end.row - e.bufferChange.oldRange.end.row + + @trigger 'change', { start, end, screenDelta, bufferDelta } + buildLineForBufferRow: (bufferRow) -> @buildLinesForBufferRows(bufferRow, bufferRow) diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 31f24307e..7d1390b3f 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -60,17 +60,8 @@ class EditSession @mergeCursors() @displayBuffer.on "change.edit-session-#{@id}", (e) => - @refreshAnchorScreenPositions() unless e.bufferChange - - { oldRange, newRange } = e - start = oldRange.start.row - end = oldRange.end.row - screenDelta = newRange.end.row - oldRange.end.row - - if bufferChange = e.bufferChange - bufferDelta = bufferChange.newRange.end.row - bufferChange.oldRange.end.row - - @trigger 'screen-lines-change', {start, end, screenDelta, bufferDelta} + @refreshAnchorScreenPositions() unless e.bufferDelta + @trigger 'screen-lines-change', e destroy: -> throw new Error("Edit session already destroyed") if @destroyed