mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
WIP: Start handling buffer updates w/ LineFolder
Still a ways to go here, but folds are moved correctly when there are buffer updates. Many unfinished specs.
This commit is contained in:
@@ -155,6 +155,55 @@ describe "LineFolder", ->
|
||||
expect(event.oldRange).toEqual [[7, 0], [7, 28]]
|
||||
expect(event.newRange).toEqual [[7, 0], [8, 56]]
|
||||
|
||||
describe "when the buffer changes", ->
|
||||
[fold1, fold2] = []
|
||||
beforeEach ->
|
||||
fold1 = folder.createFold(new Range([4, 29], [7, 4]))
|
||||
fold2 = folder.createFold(new Range([7, 5], [8, 36]))
|
||||
changeHandler.reset()
|
||||
|
||||
describe "when the old range precedes a fold", ->
|
||||
it "updates the buffer and re-positions subsequent folds", ->
|
||||
buffer.change(new Range([1, 5], [2, 10]), 'abc')
|
||||
|
||||
expect(folder.lineForScreenRow(1).text).toBe ' varabcems.length <= 1) return items;'
|
||||
expect(folder.lineForScreenRow(3).text).toBe ' while(items.length > 0) {...}...concat(sort(right));'
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[[event]] = changeHandler.argsForCall
|
||||
expect(event.oldRange).toEqual [[1, 0], [2, 40]]
|
||||
expect(event.newRange).toEqual [[1, 0], [1, 38]]
|
||||
changeHandler.reset()
|
||||
|
||||
fold1.destroy()
|
||||
expect(folder.lineForScreenRow(3).text).toBe ' while(items.length > 0) {'
|
||||
expect(folder.lineForScreenRow(6).text).toBe ' }...concat(sort(right));'
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[[event]] = changeHandler.argsForCall
|
||||
expect(event.oldRange).toEqual [[3, 0], [3, 56]]
|
||||
expect(event.newRange).toEqual [[3, 0], [6, 28]]
|
||||
|
||||
describe "when the old range follows a fold", ->
|
||||
it "re-positions the change based on the preceding fold", ->
|
||||
|
||||
describe "when the old range is contained to a single line in-between two fold placeholders", ->
|
||||
describe "when the line is updated", ->
|
||||
|
||||
describe "when lines are inserted", ->
|
||||
|
||||
describe "when the old range is inside a fold", ->
|
||||
it "does not trigger a change event, but ensures the change is present when the fold is destroyed", ->
|
||||
|
||||
describe "when the old range surrounds a fold", ->
|
||||
it "removes the fold and replaces the placeholder with the new text", ->
|
||||
|
||||
describe "when the old range straddles the start of a fold", ->
|
||||
it "moves the start of the fold to the end of the new range", ->
|
||||
|
||||
describe "when the old region straddles the end of a fold", ->
|
||||
it "moves the start of the fold to the beginning of the new range", ->
|
||||
|
||||
describe "position translation", ->
|
||||
describe "when there is single fold spanning multiple lines", ->
|
||||
it "translates positions to account for folded lines and characters and the placeholder", ->
|
||||
|
||||
@@ -10,15 +10,20 @@ class LineFolder
|
||||
constructor: (@highlighter) ->
|
||||
@activeFolds = {}
|
||||
@buildLineMap()
|
||||
@highlighter.buffer.on 'change', (e) => @handleBufferChange(e)
|
||||
@highlighter.on 'change', (e) => @handleHighlighterChange(e)
|
||||
|
||||
buildLineMap: ->
|
||||
@lineMap = new LineMap
|
||||
@lineMap.insertAtBufferRow(0, @highlighter.screenLines)
|
||||
|
||||
logLines: (start=0, end=@lastRow())->
|
||||
for row in [start..end]
|
||||
console.log row, @lineForScreenRow(row).text
|
||||
|
||||
createFold: (bufferRange) ->
|
||||
fold = new Fold(this, bufferRange)
|
||||
@activeFolds[bufferRange.start.row] ?= []
|
||||
@activeFolds[bufferRange.start.row].push(fold)
|
||||
@registerFold(bufferRange.start.row, fold)
|
||||
oldScreenRange = @expandScreenRangeToLineEnds(@screenRangeForBufferRange(bufferRange))
|
||||
|
||||
lineWithFold = @buildLine(oldScreenRange.start.row)
|
||||
@@ -33,11 +38,8 @@ class LineFolder
|
||||
fold
|
||||
|
||||
destroyFold: (fold) ->
|
||||
bufferRange = fold.range
|
||||
folds = @activeFolds[bufferRange.start.row]
|
||||
foldIndex = folds.indexOf(fold)
|
||||
folds[foldIndex..foldIndex] = []
|
||||
|
||||
bufferRange = fold.getRange()
|
||||
@unregisterFold(bufferRange.start.row, fold)
|
||||
startScreenRow = @screenRowForBufferRow(bufferRange.start.row)
|
||||
|
||||
oldScreenRange = new Range()
|
||||
@@ -51,6 +53,26 @@ class LineFolder
|
||||
|
||||
@trigger 'change', oldRange: oldScreenRange, newRange: newScreenRange
|
||||
|
||||
registerFold: (bufferRow, fold) ->
|
||||
@activeFolds[bufferRow] ?= []
|
||||
@activeFolds[bufferRow].push(fold)
|
||||
|
||||
unregisterFold: (bufferRow, fold) ->
|
||||
folds = @activeFolds[bufferRow]
|
||||
folds.splice(folds.indexOf(fold), 1)
|
||||
|
||||
handleBufferChange: (e) ->
|
||||
for row, folds of @activeFolds
|
||||
fold.handleBufferChange(e) for fold in folds
|
||||
|
||||
handleHighlighterChange: (e) ->
|
||||
oldScreenRange = @expandScreenRangeToLineEnds(@screenRangeForBufferRange(e.oldRange))
|
||||
lines = @buildLinesForBufferRows(e.newRange.start.row, e.newRange.end.row)
|
||||
@lineMap.replaceScreenRows(e.oldRange.start.row, e.oldRange.end.row, lines)
|
||||
newScreenRange = @expandScreenRangeToLineEnds(@screenRangeForBufferRange(e.newRange))
|
||||
|
||||
@trigger 'change', oldRange: oldScreenRange, newRange: newScreenRange
|
||||
|
||||
buildLinesForBufferRows: (start, end) ->
|
||||
lines = [@buildLine(@screenRowForBufferRow(start))]
|
||||
if end > start
|
||||
@@ -64,7 +86,7 @@ class LineFolder
|
||||
buildLineForBufferRow: (bufferRow, startColumn=0) ->
|
||||
screenLine = @highlighter.lineForScreenRow(bufferRow).splitAt(startColumn)[1]
|
||||
for fold in @foldsForBufferRow(bufferRow)
|
||||
{ start, end } = fold.range
|
||||
{ start, end } = fold.getRange()
|
||||
if start.column > startColumn
|
||||
prefix = screenLine.splitAt(start.column - startColumn)[0]
|
||||
suffix = @buildLineForBufferRow(end.row, end.column)
|
||||
@@ -72,7 +94,7 @@ class LineFolder
|
||||
screenLine
|
||||
|
||||
buildFoldPlaceholder: (fold) ->
|
||||
new ScreenLineFragment([{value: '...', type: 'fold-placeholder'}], '...', [0, 3], fold.range.toDelta(), isAtomic: true)
|
||||
new ScreenLineFragment([{value: '...', type: 'fold-placeholder'}], '...', [0, 3], fold.getRange().toDelta(), isAtomic: true)
|
||||
|
||||
foldsForBufferRow: (bufferRow) ->
|
||||
@activeFolds[bufferRow] or []
|
||||
@@ -80,6 +102,9 @@ class LineFolder
|
||||
linesForScreenRows: (startRow, endRow) ->
|
||||
@lineMap.linesForScreenRows(startRow, endRow)
|
||||
|
||||
lineForScreenRow: (screenRow) ->
|
||||
@lineMap.lineForScreenRow(screenRow)
|
||||
|
||||
getLines: ->
|
||||
@lineMap.getScreenLines()
|
||||
|
||||
@@ -111,8 +136,29 @@ class LineFolder
|
||||
_.extend LineFolder.prototype, EventEmitter
|
||||
|
||||
class Fold
|
||||
constructor: (@lineFolder, @range) ->
|
||||
constructor: (@lineFolder, {start, end}) ->
|
||||
@start = new Anchor(start)
|
||||
@end = new Anchor(end)
|
||||
|
||||
destroy: ->
|
||||
@lineFolder.destroyFold(this)
|
||||
|
||||
getRange: ->
|
||||
new Range(@start.position, @end.position)
|
||||
|
||||
handleBufferChange: (event) ->
|
||||
oldStartRow = @start.position.row
|
||||
@start.handleBufferChange(event)
|
||||
@end.handleBufferChange(event)
|
||||
newStartRow = @start.position.row
|
||||
|
||||
if newStartRow != oldStartRow
|
||||
@lineFolder.unregisterFold(oldStartRow, this)
|
||||
@lineFolder.registerFold(newStartRow, this)
|
||||
|
||||
class Anchor
|
||||
constructor: (@position) ->
|
||||
|
||||
handleBufferChange: (e) ->
|
||||
@position = e.newRange.end.add(@position.subtract(e.oldRange.end))
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ class Point
|
||||
constructor: (@row=0, @column=0) ->
|
||||
|
||||
add: (other) ->
|
||||
debugger unless other
|
||||
row = @row + other.row
|
||||
if other.row == 0
|
||||
column = @column + other.column
|
||||
@@ -23,6 +22,15 @@ class Point
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
subtract: (other) ->
|
||||
row = @row - other.row
|
||||
if @row == other.row
|
||||
column = @column - other.column
|
||||
else
|
||||
column = @column
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
splitAt: (column) ->
|
||||
if @row == 0
|
||||
rightColumn = @column - column
|
||||
|
||||
@@ -17,6 +17,7 @@ class ScreenLineFragment
|
||||
leftTokens = []
|
||||
leftTextLength = 0
|
||||
while leftTextLength < column
|
||||
debugger unless rightTokens[0]
|
||||
if leftTextLength + rightTokens[0].value.length > column
|
||||
rightTokens[0..0] = @splitTokenAt(rightTokens[0], column - leftTextLength)
|
||||
nextToken = rightTokens.shift()
|
||||
|
||||
Reference in New Issue
Block a user