mirror of
https://github.com/atom/atom.git
synced 2026-02-19 02:44:29 -05:00
Fix lurking soft-wrap bugs
This commit adds two important things: 1. An editor spec that randomly mutates a buffer and toggles soft wrap on and off, then compares the screen lines to a simple reference implementation to ensure everything stays in a correct state. 2. A new and radically simpler implementation of RowMap that eliminates failures in the randomized test.
This commit is contained in:
112
spec/random-editor-spec.coffee
Normal file
112
spec/random-editor-spec.coffee
Normal file
@@ -0,0 +1,112 @@
|
||||
{times, random} = require 'underscore-plus'
|
||||
randomWords = require 'random-words'
|
||||
Editor = require '../src/editor'
|
||||
TextBuffer = require '../src/text-buffer'
|
||||
|
||||
describe "Editor", ->
|
||||
[editor, tokenizedBuffer, buffer, steps, previousSteps] = []
|
||||
|
||||
softWrapColumn = 80
|
||||
|
||||
beforeEach ->
|
||||
atom.config.set('editor.softWrapAtPreferredLineLength', true)
|
||||
atom.config.set('editor.preferredLineLength', softWrapColumn)
|
||||
|
||||
it "properly renders soft-wrapped lines when randomly mutated", ->
|
||||
previousSteps = JSON.parse(localStorage.steps ? '[]')
|
||||
|
||||
times 10, (i) ->
|
||||
buffer = new TextBuffer
|
||||
editor = new Editor({buffer})
|
||||
editor.setEditorWidthInChars(80)
|
||||
tokenizedBuffer = editor.displayBuffer.tokenizedBuffer
|
||||
steps = []
|
||||
|
||||
times 30, ->
|
||||
randomlyMutateEditor()
|
||||
verifyLines()
|
||||
|
||||
verifyLines = ->
|
||||
{bufferRows, screenLines} = getReferenceScreenLines()
|
||||
for referenceBufferRow, screenRow in bufferRows
|
||||
referenceScreenLine = screenLines[screenRow]
|
||||
actualBufferRow = editor.bufferRowForScreenRow(screenRow)
|
||||
unless actualBufferRow is referenceBufferRow
|
||||
logLines()
|
||||
throw new Error("Invalid buffer row #{actualBufferRow} for screen row #{screenRow}", )
|
||||
|
||||
actualScreenLine = editor.lineForScreenRow(screenRow)
|
||||
unless actualScreenLine.text is referenceScreenLine.text
|
||||
logLines()
|
||||
throw new Error("Invalid line text at screen row #{screenRow}")
|
||||
|
||||
logLines = ->
|
||||
console.log "==== screen lines ===="
|
||||
editor.logScreenLines()
|
||||
console.log "==== reference lines ===="
|
||||
{bufferRows, screenLines} = getReferenceScreenLines()
|
||||
for bufferRow, screenRow in bufferRows
|
||||
console.log screenRow, bufferRow, screenLines[screenRow].text
|
||||
|
||||
randomlyMutateEditor = ->
|
||||
if Math.random() < .2
|
||||
softWrap = not editor.getSoftWrap()
|
||||
steps.push(['setSoftWrap', softWrap])
|
||||
editor.setSoftWrap(softWrap)
|
||||
else
|
||||
range = getRandomRange()
|
||||
text = getRandomText()
|
||||
steps.push(['setTextInBufferRange', range, text])
|
||||
editor.setTextInBufferRange(range, text)
|
||||
|
||||
getRandomRange = ->
|
||||
startRow = random(0, buffer.getLastRow())
|
||||
startColumn = random(0, buffer.lineForRow(startRow).length)
|
||||
endRow = random(startRow, buffer.getLastRow())
|
||||
endColumn = random(0, buffer.lineForRow(endRow).length)
|
||||
[[startRow, startColumn], [endRow, endColumn]]
|
||||
|
||||
getRandomText = ->
|
||||
text = []
|
||||
max = buffer.getText().split(/\s/).length * 0.75
|
||||
|
||||
times random(5, max), ->
|
||||
if Math.random() < .1
|
||||
text += '\n'
|
||||
else
|
||||
text += " " if /\w$/.test(text)
|
||||
text += randomWords(exactly: 1)
|
||||
text
|
||||
|
||||
getReferenceScreenLines = ->
|
||||
if editor.getSoftWrap()
|
||||
screenLines = []
|
||||
bufferRows = []
|
||||
for bufferRow in [0..tokenizedBuffer.getLastRow()]
|
||||
for screenLine in softWrapLine(tokenizedBuffer.lineForScreenRow(bufferRow))
|
||||
screenLines.push(screenLine)
|
||||
bufferRows.push(bufferRow)
|
||||
else
|
||||
screenLines = tokenizedBuffer.tokenizedLines.slice()
|
||||
bufferRows = [0..tokenizedBuffer.getLastRow()]
|
||||
{screenLines, bufferRows}
|
||||
|
||||
softWrapLine = (tokenizedLine) ->
|
||||
wrappedLines = []
|
||||
while tokenizedLine.text.length > softWrapColumn and wrapScreenColumn = findWrapColumn(tokenizedLine.text)
|
||||
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
|
||||
wrappedLines.push(wrappedLine)
|
||||
wrappedLines.push(tokenizedLine)
|
||||
wrappedLines
|
||||
|
||||
findWrapColumn = (line) ->
|
||||
if /\s/.test(line[softWrapColumn])
|
||||
# search forward for the start of a word past the boundary
|
||||
for column in [softWrapColumn..line.length]
|
||||
return column if /\S/.test(line[column])
|
||||
return line.length
|
||||
else
|
||||
# search backward for the start of the word on the boundary
|
||||
for column in [softWrapColumn..0]
|
||||
return column + 1 if /\s/.test(line[column])
|
||||
return softWrapColumn
|
||||
@@ -6,256 +6,101 @@ describe "RowMap", ->
|
||||
beforeEach ->
|
||||
map = new RowMap
|
||||
|
||||
describe "when no mappings have been recorded", ->
|
||||
it "maps buffer rows to screen rows 1:1", ->
|
||||
describe "::screenRowRangeForBufferRow(bufferRow)", ->
|
||||
it "returns the range of screen rows corresponding to the given buffer row", ->
|
||||
map.spliceRegions(0, 0, [
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 1, screenRows: 5}
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 5, screenRows: 1}
|
||||
])
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 1]
|
||||
expect(map.screenRowRangeForBufferRow(100)).toEqual [100, 101]
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 10]
|
||||
expect(map.screenRowRangeForBufferRow(6)).toEqual [10, 11]
|
||||
expect(map.screenRowRangeForBufferRow(11)).toEqual [15, 16]
|
||||
expect(map.screenRowRangeForBufferRow(12)).toEqual [15, 16]
|
||||
expect(map.screenRowRangeForBufferRow(16)).toEqual [16, 17]
|
||||
|
||||
describe ".mapBufferRowRange(startBufferRow, endBufferRow, screenRows)", ->
|
||||
describe "when mapping to a single screen row (like a visible fold)", ->
|
||||
beforeEach ->
|
||||
map.mapBufferRowRange(5, 10, 1)
|
||||
map.mapBufferRowRange(15, 20, 1)
|
||||
map.mapBufferRowRange(25, 30, 1)
|
||||
describe "::bufferRowRangeForScreenRow(screenRow)", ->
|
||||
it "returns the range of buffer rows corresponding to the given screen row", ->
|
||||
map.spliceRegions(0, 0, [
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 1, screenRows: 5}
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 5, screenRows: 1}
|
||||
])
|
||||
|
||||
it "accounts for the mapping when translating buffer rows to screen row ranges", ->
|
||||
expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 1]
|
||||
expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1]
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 6]
|
||||
expect(map.bufferRowRangeForScreenRow(6)).toEqual [5, 6]
|
||||
expect(map.bufferRowRangeForScreenRow(10)).toEqual [6, 7]
|
||||
expect(map.bufferRowRangeForScreenRow(14)).toEqual [10, 11]
|
||||
expect(map.bufferRowRangeForScreenRow(15)).toEqual [11, 16]
|
||||
expect(map.bufferRowRangeForScreenRow(16)).toEqual [16, 17]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(4)).toEqual [4, 5]
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 6]
|
||||
expect(map.screenRowRangeForBufferRow(9)).toEqual [5, 6]
|
||||
expect(map.screenRowRangeForBufferRow(10)).toEqual [6, 7]
|
||||
describe "::spliceRegions(startBufferRow, bufferRowCount, regions)", ->
|
||||
it "can insert regions when empty", ->
|
||||
regions = [
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 1, screenRows: 5}
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 5, screenRows: 1}
|
||||
]
|
||||
map.spliceRegions(0, 0, regions)
|
||||
expect(map.getRegions()).toEqual regions
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(14)).toEqual [10, 11]
|
||||
expect(map.screenRowRangeForBufferRow(15)).toEqual [11, 12]
|
||||
expect(map.screenRowRangeForBufferRow(19)).toEqual [11, 12]
|
||||
expect(map.screenRowRangeForBufferRow(20)).toEqual [12, 13]
|
||||
it "can insert wrapped lines into rectangular regions", ->
|
||||
map.spliceRegions(0, 0, [{bufferRows: 10, screenRows: 10}])
|
||||
map.spliceRegions(5, 0, [{bufferRows: 1, screenRows: 3}])
|
||||
expect(map.getRegions()).toEqual [
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 1, screenRows: 3}
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(24)).toEqual [16, 17]
|
||||
expect(map.screenRowRangeForBufferRow(25)).toEqual [17, 18]
|
||||
expect(map.screenRowRangeForBufferRow(29)).toEqual [17, 18]
|
||||
expect(map.screenRowRangeForBufferRow(30)).toEqual [18, 19]
|
||||
it "can splice wrapped lines into rectangular regions", ->
|
||||
map.spliceRegions(0, 0, [{bufferRows: 10, screenRows: 10}])
|
||||
map.spliceRegions(5, 1, [{bufferRows: 1, screenRows: 3}])
|
||||
expect(map.getRegions()).toEqual [
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 1, screenRows: 3}
|
||||
{bufferRows: 4, screenRows: 4}
|
||||
]
|
||||
|
||||
it "accounts for the mapping when translating screen rows to buffer row ranges", ->
|
||||
expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1]
|
||||
it "can splice folded lines into rectangular regions", ->
|
||||
map.spliceRegions(0, 0, [{bufferRows: 10, screenRows: 10}])
|
||||
map.spliceRegions(5, 3, [{bufferRows: 3, screenRows: 1}])
|
||||
expect(map.getRegions()).toEqual [
|
||||
{bufferRows: 5, screenRows: 5}
|
||||
{bufferRows: 3, screenRows: 1}
|
||||
{bufferRows: 2, screenRows: 2}
|
||||
]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(4)).toEqual [4, 5]
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 10]
|
||||
expect(map.bufferRowRangeForScreenRow(6)).toEqual [10, 11]
|
||||
it "can replace folded regions with a folded region that surrounds them", ->
|
||||
map.spliceRegions(0, 0, [
|
||||
{bufferRows: 3, screenRows: 3}
|
||||
{bufferRows: 3, screenRows: 1}
|
||||
{bufferRows: 1, screenRows: 1}
|
||||
{bufferRows: 3, screenRows: 1}
|
||||
{bufferRows: 3, screenRows: 3}
|
||||
])
|
||||
map.spliceRegions(2, 8, [{bufferRows: 8, screenRows: 1}])
|
||||
expect(map.getRegions()).toEqual [
|
||||
{bufferRows: 2, screenRows: 2}
|
||||
{bufferRows: 8, screenRows: 1}
|
||||
{bufferRows: 3, screenRows: 3}
|
||||
]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(10)).toEqual [14, 15]
|
||||
expect(map.bufferRowRangeForScreenRow(11)).toEqual [15, 20]
|
||||
expect(map.bufferRowRangeForScreenRow(12)).toEqual [20, 21]
|
||||
it "merges adjacent rectangular regions", ->
|
||||
map.spliceRegions(0, 0, [
|
||||
{bufferRows: 3, screenRows: 3}
|
||||
{bufferRows: 3, screenRows: 1}
|
||||
{bufferRows: 1, screenRows: 1}
|
||||
{bufferRows: 3, screenRows: 1}
|
||||
{bufferRows: 3, screenRows: 3}
|
||||
])
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(16)).toEqual [24, 25]
|
||||
expect(map.bufferRowRangeForScreenRow(17)).toEqual [25, 30]
|
||||
expect(map.bufferRowRangeForScreenRow(18)).toEqual [30, 31]
|
||||
map.spliceRegions(3, 7, [{bufferRows: 5, screenRows: 5}])
|
||||
|
||||
describe "when mapping to zero screen rows (like an invisible fold)", ->
|
||||
beforeEach ->
|
||||
map.mapBufferRowRange(5, 10, 0)
|
||||
map.mapBufferRowRange(15, 20, 0)
|
||||
map.mapBufferRowRange(25, 30, 0)
|
||||
|
||||
it "accounts for the mapping when translating buffer rows to screen row ranges", ->
|
||||
expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 1]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(4)).toEqual [4, 5]
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 5]
|
||||
expect(map.screenRowRangeForBufferRow(9)).toEqual [5, 5]
|
||||
expect(map.screenRowRangeForBufferRow(10)).toEqual [5, 6]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(14)).toEqual [9, 10]
|
||||
expect(map.screenRowRangeForBufferRow(15)).toEqual [10, 10]
|
||||
expect(map.screenRowRangeForBufferRow(19)).toEqual [10, 10]
|
||||
expect(map.screenRowRangeForBufferRow(20)).toEqual [10, 11]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(24)).toEqual [14, 15]
|
||||
expect(map.screenRowRangeForBufferRow(25)).toEqual [15, 15]
|
||||
expect(map.screenRowRangeForBufferRow(29)).toEqual [15, 15]
|
||||
expect(map.screenRowRangeForBufferRow(30)).toEqual [15, 16]
|
||||
|
||||
it "accounts for the mapping when translating screen rows to buffer row ranges", ->
|
||||
expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(4)).toEqual [4, 5]
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [10, 11]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(9)).toEqual [14, 15]
|
||||
expect(map.bufferRowRangeForScreenRow(10)).toEqual [20, 21]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(14)).toEqual [24, 25]
|
||||
expect(map.bufferRowRangeForScreenRow(15)).toEqual [30, 31]
|
||||
|
||||
describe "when mapping a single buffer row to multiple screen rows (like a wrapped line)", ->
|
||||
beforeEach ->
|
||||
map.mapBufferRowRange(5, 6, 3)
|
||||
map.mapBufferRowRange(10, 11, 2)
|
||||
map.mapBufferRowRange(20, 21, 5)
|
||||
|
||||
it "accounts for the mapping when translating buffer rows to screen row ranges", ->
|
||||
expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 1]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(4)).toEqual [4, 5]
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 8]
|
||||
expect(map.screenRowRangeForBufferRow(6)).toEqual [8, 9]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(9)).toEqual [11, 12]
|
||||
expect(map.screenRowRangeForBufferRow(10)).toEqual [12, 14]
|
||||
expect(map.screenRowRangeForBufferRow(11)).toEqual [14, 15]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(19)).toEqual [22, 23]
|
||||
expect(map.screenRowRangeForBufferRow(20)).toEqual [23, 28]
|
||||
expect(map.screenRowRangeForBufferRow(21)).toEqual [28, 29]
|
||||
|
||||
it "accounts for the mapping when translating screen rows to buffer row ranges", ->
|
||||
expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(4)).toEqual [4, 5]
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 6]
|
||||
expect(map.bufferRowRangeForScreenRow(7)).toEqual [5, 6]
|
||||
expect(map.bufferRowRangeForScreenRow(8)).toEqual [6, 7]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(11)).toEqual [9, 10]
|
||||
expect(map.bufferRowRangeForScreenRow(12)).toEqual [10, 11]
|
||||
expect(map.bufferRowRangeForScreenRow(13)).toEqual [10, 11]
|
||||
expect(map.bufferRowRangeForScreenRow(14)).toEqual [11, 12]
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(22)).toEqual [19, 20]
|
||||
expect(map.bufferRowRangeForScreenRow(23)).toEqual [20, 21]
|
||||
expect(map.bufferRowRangeForScreenRow(27)).toEqual [20, 21]
|
||||
expect(map.bufferRowRangeForScreenRow(28)).toEqual [21, 22]
|
||||
|
||||
describe "after re-mapping a row range to a new number of screen rows", ->
|
||||
beforeEach ->
|
||||
map.applyScreenDelta(12, 2) # simulate adding 2 more soft wraps
|
||||
map.mapBufferRowRange(10, 11, 4)
|
||||
|
||||
it "updates translation accordingly", ->
|
||||
expect(map.screenRowRangeForBufferRow(4)).toEqual [4, 5]
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 8]
|
||||
expect(map.screenRowRangeForBufferRow(6)).toEqual [8, 9]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(9)).toEqual [11, 12]
|
||||
expect(map.screenRowRangeForBufferRow(10)).toEqual [12, 16]
|
||||
expect(map.screenRowRangeForBufferRow(11)).toEqual [16, 17]
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(19)).toEqual [24, 25]
|
||||
expect(map.screenRowRangeForBufferRow(20)).toEqual [25, 30]
|
||||
expect(map.screenRowRangeForBufferRow(21)).toEqual [30, 31]
|
||||
|
||||
describe "when the row range is inside an existing 1:1 region", ->
|
||||
it "preserves the starting screen row of subsequent 1:N regions", ->
|
||||
map.mapBufferRowRange(5, 10, 1)
|
||||
map.mapBufferRowRange(25, 30, 1)
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 10]
|
||||
expect(map.bufferRowRangeForScreenRow(21)).toEqual [25, 30]
|
||||
|
||||
map.mapBufferRowRange(15, 20, 1)
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(11)).toEqual [15, 20]
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 10]
|
||||
expect(map.bufferRowRangeForScreenRow(21)).toEqual [25, 30]
|
||||
|
||||
describe "when the row range surrounds existing regions", ->
|
||||
it "replaces the regions inside the given buffer row range with a single region", ->
|
||||
map.mapBufferRowRange(5, 10, 1) # inner fold 1
|
||||
map.mapBufferRowRange(11, 13, 1) # inner fold 2
|
||||
map.mapBufferRowRange(15, 20, 1) # inner fold 3
|
||||
map.mapBufferRowRange(22, 27, 1) # following fold
|
||||
|
||||
map.mapBufferRowRange(5, 20, 1)
|
||||
|
||||
expect(map.bufferRowRangeForScreenRow(5)).toEqual [5, 20]
|
||||
expect(map.bufferRowRangeForScreenRow(6)).toEqual [20, 21]
|
||||
expect(map.bufferRowRangeForScreenRow(7)).toEqual [21, 22]
|
||||
expect(map.bufferRowRangeForScreenRow(8)).toEqual [22, 27]
|
||||
|
||||
it "replaces regions that cover 0 buffer rows at the start or end of the buffer row range", ->
|
||||
map.mapBufferRowRange(0, 0, 1)
|
||||
map.mapBufferRowRange(0, 1, 1)
|
||||
map.mapBufferRowRange(1, 1, 1)
|
||||
map.mapBufferRowRange(0, 1, 3)
|
||||
expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 3]
|
||||
|
||||
describe "when the row range straddles existing regions", ->
|
||||
it "splits the straddled regions and places the new region between them", ->
|
||||
# filler region 0
|
||||
map.mapBufferRowRange(4, 7, 1) # region 1
|
||||
# filler region 2
|
||||
map.mapBufferRowRange(13, 15, 1) # region 3
|
||||
|
||||
# create region straddling region 0 and region 2
|
||||
map.mapBufferRowRange(2, 10, 1)
|
||||
|
||||
expect(map.regions[0]).toEqual(bufferRows: 2, screenRows: 2)
|
||||
expect(map.regions[1]).toEqual(bufferRows: 8, screenRows: 1)
|
||||
expect(map.regions[2]).toEqual(bufferRows: 3, screenRows: 8)
|
||||
expect(map.regions[3]).toEqual(bufferRows: 2, screenRows: 1)
|
||||
|
||||
it "merges adjacent isomorphic mappings", ->
|
||||
map.mapBufferRowRange(2, 4, 1)
|
||||
map.mapBufferRowRange(4, 5, 2)
|
||||
|
||||
map.mapBufferRowRange(1, 4, 3)
|
||||
expect(map.regions).toEqual [{bufferRows: 5, screenRows: 5}]
|
||||
|
||||
describe ".applyBufferDelta(startBufferRow, delta)", ->
|
||||
describe "when applying a positive delta", ->
|
||||
it "expands the region containing the given start row by the given delta", ->
|
||||
map.mapBufferRowRange(4, 8, 1)
|
||||
|
||||
map.applyBufferDelta(5, 4)
|
||||
|
||||
expect(map.regions[0]).toEqual(bufferRows: 4, screenRows: 4)
|
||||
expect(map.regions[1]).toEqual(bufferRows: 8, screenRows: 1)
|
||||
|
||||
describe "when applying a negative delta", ->
|
||||
it "shrinks regions starting at the start row until the entire delta is consumed", ->
|
||||
map.mapBufferRowRange(4, 8, 1)
|
||||
map.mapBufferRowRange(10, 14, 1)
|
||||
|
||||
map.applyBufferDelta(3, -6)
|
||||
|
||||
expect(map.regions[0]).toEqual(bufferRows: 3, screenRows: 4)
|
||||
expect(map.regions[1]).toEqual(bufferRows: 0, screenRows: 1)
|
||||
expect(map.regions[2]).toEqual(bufferRows: 1, screenRows: 2)
|
||||
expect(map.regions[3]).toEqual(bufferRows: 4, screenRows: 1)
|
||||
|
||||
describe ".applyScreenDelta(startScreenRow, delta)", ->
|
||||
describe "when applying a positive delta", ->
|
||||
it "can enlarge the screen side of existing regions", ->
|
||||
map.mapBufferRowRange(5, 6, 3) # wrapped line
|
||||
map.applyScreenDelta(5, 2) # wrap it twice more
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 10]
|
||||
|
||||
describe "when applying a negative delta", ->
|
||||
it "can collapse the screen side of multiple regions to 0 until the entire delta has been applied", ->
|
||||
map.mapBufferRowRange(5, 10, 1) # inner fold 1
|
||||
map.mapBufferRowRange(11, 13, 1) # inner fold 2
|
||||
map.mapBufferRowRange(15, 20, 1) # inner fold 3
|
||||
map.mapBufferRowRange(22, 27, 1) # following fold
|
||||
|
||||
map.applyScreenDelta(6, -5)
|
||||
|
||||
expect(map.screenRowRangeForBufferRow(5)).toEqual [5, 6]
|
||||
expect(map.screenRowRangeForBufferRow(9)).toEqual [5, 6]
|
||||
expect(map.screenRowRangeForBufferRow(10)).toEqual [6, 6]
|
||||
expect(map.screenRowRangeForBufferRow(19)).toEqual [6, 6]
|
||||
expect(map.screenRowRangeForBufferRow(22)).toEqual [8, 9]
|
||||
expect(map.screenRowRangeForBufferRow(26)).toEqual [8, 9]
|
||||
|
||||
it "starts collapsing the first region at the start row, not before", ->
|
||||
map.mapBufferRowRange(5, 6, 4)
|
||||
map.mapBufferRowRange(11, 13, 1)
|
||||
|
||||
map.applyScreenDelta(7, -5)
|
||||
|
||||
expect(map.regions[0]).toEqual(bufferRows: 5, screenRows: 5)
|
||||
expect(map.regions[1]).toEqual(bufferRows: 1, screenRows: 2)
|
||||
expect(map.regions[2]).toEqual(bufferRows: 5, screenRows: 2)
|
||||
|
||||
it "does not throw an exception when applying a delta beyond the last region", ->
|
||||
map.mapBufferRowRange(5, 10, 1) # inner fold 1
|
||||
map.applyScreenDelta(15, 10)
|
||||
console.log map.inspect()
|
||||
|
||||
Reference in New Issue
Block a user