mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user