Make TokenizedBuffer emit row-oriented change events

This commit is contained in:
Nathan Sobo
2012-11-16 08:57:46 -07:00
parent f7b1f0521a
commit a441ddec7c
3 changed files with 40 additions and 43 deletions

View File

@@ -42,15 +42,13 @@ describe "TokenizedBuffer", ->
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'])
# line 2 is unchanged
expect(tokenizedBuffer.lineForScreenRow(2).tokens[2]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.oldRange).toEqual range
expect(event.newRange).toEqual new Range([0, 0], [2,0])
# line 2 is unchanged
expect(tokenizedBuffer.lineForScreenRow(2).tokens[2]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
delete event.bufferChange
expect(event).toEqual(start: 0, end: 2, delta: 0)
it "updates tokens for lines beyond the changed lines if needed", ->
buffer.insert([5, 30], '/* */')
@@ -63,8 +61,8 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.oldRange).toEqual new Range([2, 0], [5, buffer.lineForRow(5).length])
expect(event.newRange).toEqual new Range([2, 0], [5, buffer.lineForRow(5).length])
delete event.bufferChange
expect(event).toEqual(start: 2, end: 5, delta: 0)
it "resumes highlighting with the state of the previous line", ->
buffer.insert([0, 0], '/*')
@@ -92,8 +90,8 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.oldRange).toEqual range
expect(event.newRange).toEqual new Range([1, 0], [1, 5])
delete event.bufferChange
expect(event).toEqual(start: 1, end: 3, delta: -2)
it "updates tokens for lines beyond the changed lines if needed", ->
buffer.insert([5, 30], '/* */')
@@ -106,8 +104,8 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.oldRange).toEqual new Range([2, 0], [5, buffer.lineForRow(4).length])
expect(event.newRange).toEqual new Range([2, 0], [4, buffer.lineForRow(4).length])
delete event.bufferChange
expect(event).toEqual(start: 2, end: 5, delta: -1)
describe "when lines are both updated and inserted", ->
it "updates tokens to reflect the inserted lines", ->
@@ -131,8 +129,8 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.oldRange).toEqual range
expect(event.newRange).toEqual new Range([1, 0], [4, 6])
delete event.bufferChange
expect(event).toEqual(start: 1, end: 2, delta: 2)
it "updates tokens for lines beyond the changed lines if needed", ->
buffer.insert([5, 30], '/* */')
@@ -149,8 +147,9 @@ describe "TokenizedBuffer", ->
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.oldRange).toEqual new Range([2, 0], [5, buffer.lineForRow(7).length])
expect(event.newRange).toEqual new Range([2, 0], [7, buffer.lineForRow(7).length])
delete event.bufferChange
expect(event).toEqual(start: 2, end: 5, delta: 2)
describe "when the buffer contains tab characters", ->
editSession2 = null

View File

@@ -162,6 +162,9 @@ class DisplayBuffer
screenRowForBufferRow: (bufferRow) ->
@lineMap.screenPositionForBufferPosition([bufferRow, 0]).row
lastScreenRowForBufferRow: (bufferRow) ->
@lineMap.screenPositionForBufferPosition([bufferRow, Infinity]).row
bufferRowForScreenRow: (screenRow) ->
@lineMap.bufferPositionForScreenPosition([screenRow, 0]).row
@@ -203,33 +206,25 @@ class DisplayBuffer
allFolds.push(folds...) for row, folds of @activeFolds
fold.handleBufferChange(e) for fold in allFolds
handleTokenizedBufferChange: (e) ->
@handleBufferChange(e.bufferChange) if e.bufferChange
handleTokenizedBufferChange: (tokenizedBufferChange) ->
if bufferChange = tokenizedBufferChange.bufferChange
@handleBufferChange(bufferChange)
bufferDelta = bufferChange.newRange.end.row - bufferChange.oldRange.end.row
{ oldRange, newRange } = e
oldRange = oldRange.copy()
newRange = newRange.copy()
foldAdjustedStartRow = @bufferRowForScreenRow(@screenRowForBufferRow(newRange.start.row))
oldRange.start.row = foldAdjustedStartRow
newRange.start.row = foldAdjustedStartRow
tokenizedBufferStart = @bufferRowForScreenRow(@screenRowForBufferRow(tokenizedBufferChange.start))
tokenizedBufferEnd = tokenizedBufferChange.end
tokenizedBufferDelta = tokenizedBufferChange.delta
oldScreenRange = @screenLineRangeForBufferRange(oldRange)
newScreenLines = @buildLinesForBufferRows(newRange.start.row, newRange.end.row)
@lineMap.replaceScreenRows oldScreenRange.start.row, oldScreenRange.end.row, newScreenLines
newScreenRange = @screenLineRangeForBufferRange(newRange)
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
start = @screenRowForBufferRow(tokenizedBufferStart)
end = @lastScreenRowForBufferRow(tokenizedBufferEnd)
newScreenLines = @buildLinesForBufferRows(tokenizedBufferStart, tokenizedBufferEnd + tokenizedBufferDelta)
@lineMap.replaceScreenRows(start, end, newScreenLines)
screenDelta = @lastScreenRowForBufferRow(tokenizedBufferEnd + tokenizedBufferDelta) - end
@trigger 'change', { start, end, screenDelta, bufferDelta }
buildLineForBufferRow: (bufferRow) ->
@buildLinesForBufferRows(bufferRow, bufferRow)

View File

@@ -50,14 +50,20 @@ class TokenizedBuffer
newRange.end.column = endColumn
oldRange.end.column = endColumn
@trigger "change", {oldRange, newRange, bufferChange: e}
start = oldRange.start.row
end = oldRange.end.row
delta = newRange.end.row - oldRange.end.row
bufferChange = e
@trigger "change", { start, end, delta, bufferChange }
getTabLength: ->
@tabLength
setTabLength: (@tabLength) ->
@screenLines = @buildScreenLinesForRows(0, @buffer.getLastRow())
@trigger "change", {oldRange: @buffer.getRange(), newRange: @buffer.getRange()}
lastRow = @buffer.getLastRow()
@screenLines = @buildScreenLinesForRows(0, lastRow)
@trigger "change", { start: 0, end: lastRow, delta: 0 }
buildScreenLinesForRows: (startRow, endRow, startingStack) ->
ruleStack = startingStack
@@ -68,10 +74,7 @@ class TokenizedBuffer
buildScreenLineForRow: (row, ruleStack) ->
line = @buffer.lineForRow(row)
val = @languageMode.tokenizeLine(line, {ruleStack, @tabLength})
console.log val, line unless val.ruleStack
new ScreenLine(val)
new ScreenLine(@languageMode.tokenizeLine(line, {ruleStack, @tabLength}))
lineForScreenRow: (row) ->
@screenLines[row]