From 04f4a9a7659b52932dbf6da575aa537e361e894f Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 22 May 2012 19:02:13 -0700 Subject: [PATCH] WIP: Handle buffer change events correctly with respect to folded lines We're handling changes that straddle the start row and are in the middle of the fold, but we're still screwing up when the old range straddles the end row. --- spec/app/renderer-spec.coffee | 81 ++++++++++++++++++++++++++++------- src/app/fold.coffee | 39 ++++++++++++----- src/app/renderer.coffee | 6 ++- 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/spec/app/renderer-spec.coffee b/spec/app/renderer-spec.coffee index 2c890ddcc..a79fa8512 100644 --- a/spec/app/renderer-spec.coffee +++ b/spec/app/renderer-spec.coffee @@ -1,7 +1,7 @@ Renderer = require 'renderer' Buffer = require 'buffer' -describe "Renderer", -> +fdescribe "Renderer", -> [renderer, buffer, changeHandler, tabText] = [] beforeEach -> tabText = ' ' @@ -303,23 +303,52 @@ describe "Renderer", -> expect(event.newRange).toEqual [[3, 0], [4, 1]] describe "when the old range is inside a fold", -> - it "does not trigger a change event, but updates the fold and ensures the change is present when the fold is destroyed", -> - buffer.insert([2, 0], '\n') - expect(fold1.startRow).toBe 2 - expect(fold1.endRow).toBe 5 + describe "when the end of the new range precedes the end of the fold", -> + it "updates the fold and ensures the change is present when the fold is destroyed", -> + buffer.insert([3, 0], '\n') + expect(fold1.startRow).toBe 2 + expect(fold1.endRow).toBe 5 + + buffer.logLines(0, 10) + renderer.logLines(0, 10) + + expect(renderer.lineForRow(1).text).toBe "1" + expect(renderer.lineForRow(2).text).toBe "2" + expect(renderer.lineForRow(2).fold).toBe fold1 + expect(renderer.lineForRow(2).bufferDelta).toEqual [4, 0] + expect(renderer.lineForRow(3).text).toMatch "5" + expect(renderer.lineForRow(4).fold).toBe fold2 + expect(renderer.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]] + + describe "when the end of the new range exceeds the end of the fold", -> + ffit "expands the fold to contain all the inserted lines", -> + buffer.change([[3, 0], [4, 0]], 'a\nb\nc\nd\n') + expect(fold1.startRow).toBe 2 + expect(fold1.endRow).toBe 7 + + # buffer.logLines(0, 10) + # renderer.logLines(0, 10) + + # expect(renderer.lineForRow(1).text).toBe "1" + # expect(renderer.lineForRow(2).text).toBe "2" + # expect(renderer.lineForRow(2).fold).toBe fold1 + # expect(renderer.lineForRow(2).bufferDelta).toEqual [4, 0] + # expect(renderer.lineForRow(3).text).toMatch "5" + # expect(renderer.lineForRow(4).fold).toBe fold2 + # expect(renderer.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(renderer.lineForRow(1).text).toBe "1" - expect(renderer.lineForRow(2).text).toBe "" - expect(renderer.lineForRow(2).fold).toBe fold1 - expect(renderer.lineForRow(2).bufferDelta).toEqual [4, 0] - expect(renderer.lineForRow(3).text).toMatch "5" - expect(renderer.lineForRow(4).fold).toBe fold2 - expect(renderer.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, 0]] describe "when the old range surrounds a fold", -> it "removes the fold and replaces the fold placeholder with the new text", -> @@ -351,6 +380,26 @@ describe "Renderer", -> expect(event.oldRange).toEqual [[1, 0], [3, 2]] expect(event.newRange).toEqual [[1, 0], [1, 9]] + describe "when the old range straddles the beginning of a fold", -> + describe "when lines are added to the buffer", -> + it "replaces lines in the portion of the range that precedes the fold and adjusts the end of the fold to encompass additional lines", -> + buffer.change([[1, 1], [3, 0]], "a\nb\nc\nd\n") + + expect(fold1.startRow).toBe 2 + expect(fold1.endRow).toBe 6 + buffer.logLines(0, 10) + console.log "================================================" + renderer.logLines(0, 10) + + expect(renderer.lineForRow(1).text).toBe '1a' + expect(renderer.lineForRow(2).text).toBe 'b' + expect(renderer.lineForRow(2).fold).toBe fold1 + + + describe "when lines are removed from the buffer", -> + + + describe "position translation", -> it "translates positions to account for folded lines and characters and the placeholder", -> renderer.createFold(4, 7) diff --git a/src/app/fold.coffee b/src/app/fold.coffee index c8058d92e..6d71004a2 100644 --- a/src/app/fold.coffee +++ b/src/app/fold.coffee @@ -15,18 +15,19 @@ class Fold destroy: -> @renderer.destroyFold(this) + inspect: -> + "Fold(#{@startRow}, #{@endRow})" + getBufferDelta: -> new Point(@endRow - @startRow + 1, 0) handleBufferChange: (event) -> oldStartRow = @startRow - { oldRange } = event - if oldRange.start.row <= @startRow and oldRange.end.row >= @endRow - @renderer.unregisterFold(oldStartRow, this) + if @isContainedByRange(event.oldRange) + @renderer.unregisterFold(@startRow, this) return - changeInsideFold = @startRow <= oldRange.start.row and @endRow >= oldRange.end.row @updateStartRow(event) @updateEndRow(event) @@ -34,18 +35,34 @@ class Fold @renderer.unregisterFold(oldStartRow, this) @renderer.registerFold(@startRow, this) - changeInsideFold + isContainedByRange: (range) -> + range.start.row <= @startRow and @endRow <= range.end.row updateStartRow: (event) -> { newRange, oldRange } = event - return if oldRange.start.row >= @startRow - deltaFromOldRangeEndRow = @startRow - oldRange.end.row - @startRow = newRange.end.row + deltaFromOldRangeEndRow + if oldRange.end.row < @startRow + delta = newRange.end.row - oldRange.end.row + else if newRange.end.row < @startRow + delta = newRange.end.row - @startRow + else + delta = 0 + + console.log "start row delta", delta + + @startRow += delta updateEndRow: (event) -> { newRange, oldRange } = event - return if oldRange.start.row > @endRow - deltaFromOldRangeEndRow = @endRow - oldRange.end.row - @endRow = newRange.end.row + deltaFromOldRangeEndRow + if oldRange.end.row <= @endRow + delta = newRange.end.row - oldRange.end.row + else if newRange.end.row <= @endRow + console.log "newRange.end.row", newRange.end.row, " - @endRow", @endRow + delta = newRange.end.row - @endRow + else + delta = 0 + + console.log "end row delta", delta + + @endRow += delta diff --git a/src/app/renderer.coffee b/src/app/renderer.coffee index ccd0b054c..ac1f7c1d1 100644 --- a/src/app/renderer.coffee +++ b/src/app/renderer.coffee @@ -111,12 +111,15 @@ class Renderer @handleHighlighterChange(@lastHighlighterChangeEvent) handleHighlighterChange: (e) -> - { oldRange, newRange } = e + oldRange = @bufferRangeForScreenRange(@screenRangeForBufferRange(e.oldRange.copy())) + newRange = @bufferRangeForScreenRange(@screenRangeForBufferRange(e.newRange.copy())) oldScreenRange = @screenLineRangeForBufferRange(oldRange) + newScreenLines = @buildLinesForBufferRows(newRange.start.row, newRange.end.row) @lineMap.replaceScreenRows oldScreenRange.start.row, oldScreenRange.end.row, newScreenLines newScreenRange = @screenLineRangeForBufferRange(newRange) + console.log "New Screen Range", newScreenRange.inspect() @trigger 'change', { oldRange: oldScreenRange, newRange: newScreenRange, bufferChanged: true } @@ -176,6 +179,7 @@ class Renderer @foldsById[fold.id] = fold unregisterFold: (bufferRow, fold) -> + console.log "unregistering fold", fold.id folds = @activeFolds[bufferRow] _.remove(folds, fold) delete @foldsById[fold.id]