Inserting a mapping within an existing mapping preserves its shape

Inserting a mapping should never change the position of any existing
mappings on screen or in the buffer. It's simply a statement about a
range of rows in the buffer mapping to a range of existing rows on
screen, but shouldn't add or remove any rows. Adding and removing rows
on screen or in the buffer is the job of the applyBufferDelta and
applyScreenDelta methods.
This commit is contained in:
Nathan Sobo
2013-05-08 11:05:19 -06:00
parent 1895e8143d
commit c6ff7e8934
2 changed files with 47 additions and 36 deletions

View File

@@ -15,9 +15,8 @@ describe "RowMap", ->
describe "when mapping to a single screen row (like a visible fold)", ->
beforeEach ->
map.mapBufferRowRange(5, 10, 1)
map.mapBufferRowRange(35, 40, 1)
map.mapBufferRowRange(25, 30, 1)
map.mapBufferRowRange(15, 20, 1)
map.mapBufferRowRange(25, 30, 1)
it "accounts for the mapping when translating buffer rows to screen row ranges", ->
expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 1]
@@ -37,11 +36,6 @@ describe "RowMap", ->
expect(map.screenRowRangeForBufferRow(29)).toEqual [17, 18]
expect(map.screenRowRangeForBufferRow(30)).toEqual [18, 19]
expect(map.screenRowRangeForBufferRow(34)).toEqual [22, 23]
expect(map.screenRowRangeForBufferRow(35)).toEqual [23, 24]
expect(map.screenRowRangeForBufferRow(39)).toEqual [23, 24]
expect(map.screenRowRangeForBufferRow(40)).toEqual [24, 25]
it "accounts for the mapping when translating screen rows to buffer row ranges", ->
expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1]
@@ -57,16 +51,11 @@ describe "RowMap", ->
expect(map.bufferRowRangeForScreenRow(17)).toEqual [25, 30]
expect(map.bufferRowRangeForScreenRow(18)).toEqual [30, 31]
expect(map.bufferRowRangeForScreenRow(22)).toEqual [34, 35]
expect(map.bufferRowRangeForScreenRow(23)).toEqual [35, 40]
expect(map.bufferRowRangeForScreenRow(24)).toEqual [40, 41]
describe "when mapping to zero screen rows (like an invisible fold)", ->
beforeEach ->
map.mapBufferRowRange(5, 10, 0)
map.mapBufferRowRange(35, 40, 0)
map.mapBufferRowRange(25, 30, 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]
@@ -86,11 +75,6 @@ describe "RowMap", ->
expect(map.screenRowRangeForBufferRow(29)).toEqual [15, 15]
expect(map.screenRowRangeForBufferRow(30)).toEqual [15, 16]
expect(map.screenRowRangeForBufferRow(34)).toEqual [19, 20]
expect(map.screenRowRangeForBufferRow(35)).toEqual [20, 20]
expect(map.screenRowRangeForBufferRow(39)).toEqual [20, 20]
expect(map.screenRowRangeForBufferRow(40)).toEqual [20, 21]
it "accounts for the mapping when translating screen rows to buffer row ranges", ->
expect(map.bufferRowRangeForScreenRow(0)).toEqual [0, 1]
@@ -103,14 +87,11 @@ describe "RowMap", ->
expect(map.bufferRowRangeForScreenRow(14)).toEqual [24, 25]
expect(map.bufferRowRangeForScreenRow(15)).toEqual [30, 31]
expect(map.bufferRowRangeForScreenRow(19)).toEqual [34, 35]
expect(map.bufferRowRangeForScreenRow(20)).toEqual [40, 41]
describe "when mapping a single buffer row to multiple screen rows (like a wrapped line)", ->
beforeEach ->
map.mapBufferRowRange(5, 6, 3)
map.mapBufferRowRange(20, 21, 5)
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]
@@ -161,3 +142,17 @@ describe "RowMap", ->
expect(map.screenRowRangeForBufferRow(19)).toEqual [24, 25]
expect(map.screenRowRangeForBufferRow(20)).toEqual [25, 30]
expect(map.screenRowRangeForBufferRow(21)).toEqual [30, 31]
describe "when mapping into an existing 1:1 region", ->
it "preserves the starting screen row of subsequent 1:N mappings", ->
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]

View File

@@ -11,6 +11,13 @@ class RowMap
screenRow += targetBufferRow - bufferRow
[screenRow, screenRow + 1]
bufferRowRangeForBufferRow: (targetBufferRow) ->
{ mapping, screenRow, bufferRow } = @traverseToBufferRow(targetBufferRow)
if mapping and mapping.bufferRows != mapping.screenRows # 1:n mapping
[bufferRow, bufferRow + mapping.bufferRows]
else # 1:1 mapping
[targetBufferRow, targetBufferRow + 1]
bufferRowRangeForScreenRow: (targetScreenRow) ->
{ mapping, screenRow, bufferRow } = @traverseToScreenRow(targetScreenRow)
if mapping and mapping.bufferRows != mapping.screenRows # 1:n mapping
@@ -20,24 +27,33 @@ class RowMap
[bufferRow, bufferRow + 1]
mapBufferRowRange: (startBufferRow, endBufferRow, screenRows) ->
{ mapping, index, bufferRow } = @traverseToBufferRow(startBufferRow)
if mapping and mapping.bufferRows != mapping.screenRows
if bufferRow == startBufferRow and bufferRow + mapping.bufferRows == endBufferRow
mapping.screenRows = screenRows
return
else
throw new Error("Invalid mapping insertion")
padBefore = startBufferRow - bufferRow
padAfter = (bufferRow + mapping?.bufferRows) - endBufferRow
{ mapping, index, bufferRow, screenRow } = @traverseToBufferRow(startBufferRow)
newMappings = []
newMappings.push(bufferRows: padBefore, screenRows: padBefore) if padBefore > 0
newMappings.push(bufferRows: endBufferRow - startBufferRow, screenRows: screenRows)
newMappings.push(bufferRows: padAfter, screenRows: padAfter) if padAfter > 0
preRows = startBufferRow - bufferRow
if preRows > 0
newMappings.push(bufferRows: preRows, screenRows: preRows)
bufferRows = endBufferRow - startBufferRow
newMappings.push({bufferRows, screenRows})
if mapping
postBufferRows = mapping.bufferRows - preRows - bufferRows
postScreenRows = mapping.screenRows - preRows - screenRows
if postBufferRows > 0 or postScreenRows > 0
newMappings.push(bufferRows: postBufferRows, screenRows: postScreenRows)
@mappings[index..index] = newMappings
applyBufferDelta: (startBufferRow, delta) ->
{ mapping } = @traverseToBufferRow(startBufferRow)
mapping?.bufferRows += delta
applyScreenDelta: (startBufferRow, delta) ->
{ mapping } = @traverseToScreenRow(startBufferRow)
mapping?.screenRows += delta
traverseToBufferRow: (targetBufferRow) ->
bufferRow = 0
screenRow = 0