mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Refer to "buffer" and "screen" coordinate spaces as "input" and "output"
Since we compose the line wrapper and the line folder together, the line map is not always translating between screen and buffer coordinate spaces. It's translating one step in the chain, with output closer to the screen and input closer to the buffer.
This commit is contained in:
@@ -21,7 +21,7 @@ class LineFolder
|
||||
|
||||
buildLineMap: ->
|
||||
@lineMap = new LineMap
|
||||
@lineMap.insertAtBufferRow(0, @highlighter.screenLines)
|
||||
@lineMap.insertAtInputRow(0, @highlighter.screenLines)
|
||||
|
||||
logLines: (start=0, end=@lastRow())->
|
||||
@lineMap.logLines(start, end)
|
||||
@@ -32,7 +32,7 @@ class LineFolder
|
||||
oldScreenRange = @expandScreenRangeToLineEnds(@screenRangeForBufferRange(bufferRange))
|
||||
|
||||
lineWithFold = @buildLineForBufferRow(bufferRange.start.row)
|
||||
@lineMap.replaceScreenRows(oldScreenRange.start.row, oldScreenRange.end.row, lineWithFold)
|
||||
@lineMap.replaceOutputRows(oldScreenRange.start.row, oldScreenRange.end.row, lineWithFold)
|
||||
|
||||
newScreenRange = oldScreenRange.copy()
|
||||
newScreenRange.end = _.clone(newScreenRange.start)
|
||||
@@ -51,9 +51,9 @@ class LineFolder
|
||||
oldScreenRange = new Range()
|
||||
oldScreenRange.start.row = startScreenRow
|
||||
oldScreenRange.end.row = startScreenRow
|
||||
oldScreenRange.end.column = @lineMap.lineForScreenRow(startScreenRow).text.length
|
||||
oldScreenRange.end.column = @lineMap.lineForOutputRow(startScreenRow).text.length
|
||||
|
||||
@lineMap.replaceScreenRow(startScreenRow, @buildLinesForBufferRows(bufferRange.start.row, bufferRange.end.row))
|
||||
@lineMap.replaceOutputRow(startScreenRow, @buildLinesForBufferRows(bufferRange.start.row, bufferRange.end.row))
|
||||
|
||||
newScreenRange = @expandScreenRangeToLineEnds(@screenRangeForBufferRange(bufferRange))
|
||||
|
||||
@@ -79,7 +79,7 @@ class LineFolder
|
||||
oldScreenRange = @screenRangeForBufferRange(e.oldRange)
|
||||
expandedOldScreenRange = @expandScreenRangeToLineEnds(oldScreenRange)
|
||||
lines = @buildLinesForBufferRows(e.newRange.start.row, e.newRange.end.row)
|
||||
@lineMap.replaceScreenRows(oldScreenRange.start.row, oldScreenRange.end.row, lines)
|
||||
@lineMap.replaceOutputRows(oldScreenRange.start.row, oldScreenRange.end.row, lines)
|
||||
newScreenRange = @screenRangeForBufferRange(e.newRange)
|
||||
expandedNewScreenRange = @expandScreenRangeToLineEnds(newScreenRange)
|
||||
|
||||
@@ -118,16 +118,16 @@ class LineFolder
|
||||
folds.sort (a, b) -> a.compare(b)
|
||||
|
||||
linesForScreenRows: (startRow, endRow) ->
|
||||
@lineMap.linesForScreenRows(startRow, endRow)
|
||||
@lineMap.linesForOutputRows(startRow, endRow)
|
||||
|
||||
lineForScreenRow: (screenRow) ->
|
||||
@lineMap.lineForScreenRow(screenRow)
|
||||
@lineMap.lineForOutputRow(screenRow)
|
||||
|
||||
getLines: ->
|
||||
@lineMap.screenLinesForRows(0, @lastRow())
|
||||
@lineMap.linesForOutputRows(0, @lastRow())
|
||||
|
||||
lineCount: ->
|
||||
@lineMap.screenLineCount()
|
||||
@lineMap.outputLineCount()
|
||||
|
||||
lastRow: ->
|
||||
@lineCount() - 1
|
||||
@@ -139,23 +139,23 @@ class LineFolder
|
||||
@bufferPositionForScreenPosition([screenRow, 0]).row
|
||||
|
||||
screenPositionForBufferPosition: (bufferPosition) ->
|
||||
@lineMap.screenPositionForBufferPosition(bufferPosition)
|
||||
@lineMap.outputPositionForInputPosition(bufferPosition)
|
||||
|
||||
bufferPositionForScreenPosition: (screenPosition) ->
|
||||
@lineMap.bufferPositionForScreenPosition(screenPosition)
|
||||
@lineMap.inputPositionForOutputPosition(screenPosition)
|
||||
|
||||
clipScreenPosition: (screenPosition, options={}) ->
|
||||
@lineMap.clipScreenPosition(screenPosition, options)
|
||||
@lineMap.clipOutputPosition(screenPosition, options)
|
||||
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
@lineMap.screenRangeForBufferRange(bufferRange)
|
||||
@lineMap.outputRangeForInputRange(bufferRange)
|
||||
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
@lineMap.bufferRangeForScreenRange(screenRange)
|
||||
@lineMap.inputRangeForOutputRange(screenRange)
|
||||
|
||||
expandScreenRangeToLineEnds: (screenRange) ->
|
||||
{ start, end } = screenRange
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForScreenRow(end.row).text.length])
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForOutputRow(end.row).text.length])
|
||||
|
||||
_.extend LineFolder.prototype, EventEmitter
|
||||
|
||||
|
||||
@@ -7,66 +7,66 @@ class LineMap
|
||||
constructor: ->
|
||||
@lineFragments = []
|
||||
|
||||
insertAtBufferRow: (bufferRow, lineFragments) ->
|
||||
@spliceAtBufferRow(bufferRow, 0, lineFragments)
|
||||
insertAtInputRow: (inputRow, lineFragments) ->
|
||||
@spliceAtInputRow(inputRow, 0, lineFragments)
|
||||
|
||||
spliceAtBufferRow: (startRow, rowCount, lineFragments) ->
|
||||
@spliceByDelta('bufferDelta', startRow, rowCount, lineFragments)
|
||||
spliceAtInputRow: (startRow, rowCount, lineFragments) ->
|
||||
@spliceByDelta('inputDelta', startRow, rowCount, lineFragments)
|
||||
|
||||
spliceAtScreenRow: (startRow, rowCount, lineFragments) ->
|
||||
@spliceByDelta('screenDelta', startRow, rowCount, lineFragments)
|
||||
spliceAtOutputRow: (startRow, rowCount, lineFragments) ->
|
||||
@spliceByDelta('outputDelta', startRow, rowCount, lineFragments)
|
||||
|
||||
replaceBufferRows: (start, end, lineFragments) ->
|
||||
@spliceAtBufferRow(start, end - start + 1, lineFragments)
|
||||
replaceInputRows: (start, end, lineFragments) ->
|
||||
@spliceAtInputRow(start, end - start + 1, lineFragments)
|
||||
|
||||
replaceScreenRow: (row, lineFragments) ->
|
||||
@replaceScreenRows(row, row, lineFragments)
|
||||
replaceOutputRow: (row, lineFragments) ->
|
||||
@replaceOutputRows(row, row, lineFragments)
|
||||
|
||||
replaceScreenRows: (start, end, lineFragments) ->
|
||||
@spliceAtScreenRow(start, end - start + 1, lineFragments)
|
||||
replaceOutputRows: (start, end, lineFragments) ->
|
||||
@spliceAtOutputRow(start, end - start + 1, lineFragments)
|
||||
|
||||
lineForScreenRow: (row) ->
|
||||
@linesForScreenRows(row, row)[0]
|
||||
lineForOutputRow: (row) ->
|
||||
@linesForOutputRows(row, row)[0]
|
||||
|
||||
linesForScreenRows: (startRow, endRow) ->
|
||||
@linesByDelta('screenDelta', startRow, endRow)
|
||||
linesForOutputRows: (startRow, endRow) ->
|
||||
@linesByDelta('outputDelta', startRow, endRow)
|
||||
|
||||
lineForBufferRow: (row) ->
|
||||
@linesForBufferRows(row, row)[0]
|
||||
lineForInputRow: (row) ->
|
||||
@linesForInputRows(row, row)[0]
|
||||
|
||||
linesForBufferRows: (startRow, endRow) ->
|
||||
@linesByDelta('bufferDelta', startRow, endRow)
|
||||
linesForInputRows: (startRow, endRow) ->
|
||||
@linesByDelta('inputDelta', startRow, endRow)
|
||||
|
||||
bufferLineCount: ->
|
||||
@lineCountByDelta('bufferDelta')
|
||||
inputLineCount: ->
|
||||
@lineCountByDelta('inputDelta')
|
||||
|
||||
screenLineCount: ->
|
||||
@lineCountByDelta('screenDelta')
|
||||
outputLineCount: ->
|
||||
@lineCountByDelta('outputDelta')
|
||||
|
||||
lineCountByDelta: (deltaType) ->
|
||||
@traverseByDelta(deltaType, new Point(Infinity, 0))[deltaType].row
|
||||
|
||||
lastScreenRow: ->
|
||||
@screenLineCount() - 1
|
||||
lastOutputRow: ->
|
||||
@outputLineCount() - 1
|
||||
|
||||
screenPositionForBufferPosition: (bufferPosition) ->
|
||||
@translatePosition('bufferDelta', 'screenDelta', bufferPosition)
|
||||
outputPositionForInputPosition: (inputPosition) ->
|
||||
@translatePosition('inputDelta', 'outputDelta', inputPosition)
|
||||
|
||||
bufferPositionForScreenPosition: (screenPosition) ->
|
||||
@translatePosition('screenDelta', 'bufferDelta', screenPosition)
|
||||
inputPositionForOutputPosition: (outputPosition) ->
|
||||
@translatePosition('outputDelta', 'inputDelta', outputPosition)
|
||||
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
start = @screenPositionForBufferPosition(bufferRange.start)
|
||||
end = @screenPositionForBufferPosition(bufferRange.end)
|
||||
outputRangeForInputRange: (inputRange) ->
|
||||
start = @outputPositionForInputPosition(inputRange.start)
|
||||
end = @outputPositionForInputPosition(inputRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
start = @bufferPositionForScreenPosition(screenRange.start)
|
||||
end = @bufferPositionForScreenPosition(screenRange.end)
|
||||
inputRangeForOutputRange: (outputRange) ->
|
||||
start = @inputPositionForOutputPosition(outputRange.start)
|
||||
end = @inputPositionForOutputPosition(outputRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
clipScreenPosition: (screenPosition, options) ->
|
||||
@translatePosition('screenDelta', 'screenDelta', screenPosition, options)
|
||||
clipOutputPosition: (outputPosition, options) ->
|
||||
@translatePosition('outputDelta', 'outputDelta', outputPosition, options)
|
||||
|
||||
spliceByDelta: (deltaType, startRow, rowCount, lineFragments) ->
|
||||
stopRow = startRow + rowCount
|
||||
@@ -93,7 +93,7 @@ class LineMap
|
||||
else
|
||||
pendingFragment = _.clone(lineFragment)
|
||||
if pendingFragment[deltaType].row > 0
|
||||
pendingFragment.bufferDelta = new Point(1, 0)
|
||||
pendingFragment.inputDelta = new Point(1, 0)
|
||||
lines.push pendingFragment
|
||||
pendingFragment = null
|
||||
lines
|
||||
@@ -145,20 +145,20 @@ class LineMap
|
||||
|
||||
traverseByDelta: (deltaType, startPosition, endPosition=startPosition, iterator=null) ->
|
||||
traversalDelta = new Point
|
||||
screenDelta = new Point
|
||||
bufferDelta = new Point
|
||||
outputDelta = new Point
|
||||
inputDelta = new Point
|
||||
|
||||
for lineFragment in @lineFragments
|
||||
iterator(lineFragment) if traversalDelta.isGreaterThanOrEqual(startPosition) and iterator?
|
||||
traversalDelta = traversalDelta.add(lineFragment[deltaType])
|
||||
break if traversalDelta.isGreaterThan(endPosition)
|
||||
screenDelta = screenDelta.add(lineFragment.screenDelta)
|
||||
bufferDelta = bufferDelta.add(lineFragment.bufferDelta)
|
||||
outputDelta = outputDelta.add(lineFragment.outputDelta)
|
||||
inputDelta = inputDelta.add(lineFragment.inputDelta)
|
||||
|
||||
{ screenDelta, bufferDelta, lastLineFragment: lineFragment }
|
||||
{ outputDelta, inputDelta, lastLineFragment: lineFragment }
|
||||
|
||||
logLines: (start=0, end=@screenLineCount() - 1)->
|
||||
logLines: (start=0, end=@outputLineCount() - 1)->
|
||||
for row in [start..end]
|
||||
line = @lineForScreenRow(row).text
|
||||
line = @lineForOutputRow(row).text
|
||||
console.log row, line, line.length
|
||||
|
||||
|
||||
@@ -18,26 +18,26 @@ class LineWrapper
|
||||
|
||||
buildLineMap: ->
|
||||
@lineMap = new LineMap
|
||||
@lineMap.insertAtBufferRow 0, @buildScreenLinesForBufferRows(0, @lineFolder.lastRow())
|
||||
@lineMap.insertAtInputRow 0, @buildScreenLinesForBufferRows(0, @lineFolder.lastRow())
|
||||
|
||||
handleChange: (e) ->
|
||||
oldBufferRange = e.oldRange
|
||||
newBufferRange = e.newRange
|
||||
|
||||
oldScreenRange = @lineMap.screenRangeForBufferRange(@expandBufferRangeToLineEnds(oldBufferRange))
|
||||
oldScreenRange = @lineMap.outputRangeForInputRange(@expandBufferRangeToLineEnds(oldBufferRange))
|
||||
newScreenLines = @buildScreenLinesForBufferRows(newBufferRange.start.row, newBufferRange.end.row)
|
||||
@lineMap.replaceBufferRows oldBufferRange.start.row, oldBufferRange.end.row, newScreenLines
|
||||
newScreenRange = @lineMap.screenRangeForBufferRange(@expandBufferRangeToLineEnds(newBufferRange))
|
||||
@lineMap.replaceInputRows oldBufferRange.start.row, oldBufferRange.end.row, newScreenLines
|
||||
newScreenRange = @lineMap.outputRangeForInputRange(@expandBufferRangeToLineEnds(newBufferRange))
|
||||
|
||||
@trigger 'change', { oldRange: oldScreenRange, newRange: newScreenRange }
|
||||
|
||||
expandBufferRangeToLineEnds: (bufferRange) ->
|
||||
{ start, end } = bufferRange
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForBufferRow(end.row).text.length])
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForInputRow(end.row).text.length])
|
||||
|
||||
rangeForAllLines: ->
|
||||
endRow = @lineCount() - 1
|
||||
endColumn = @lineMap.lineForScreenRow(endRow).text.length
|
||||
endColumn = @lineMap.lineForOutputRow(endRow).text.length
|
||||
new Range([0, 0], [endRow, endColumn])
|
||||
|
||||
buildScreenLinesForBufferRows: (start, end) ->
|
||||
@@ -54,7 +54,7 @@ class LineWrapper
|
||||
endColumn = startColumn + screenLine.text.length
|
||||
else
|
||||
[leftHalf, rightHalf] = screenLine.splitAt(splitColumn)
|
||||
leftHalf.screenDelta = new Point(1, 0)
|
||||
leftHalf.outputDelta = new Point(1, 0)
|
||||
screenLines.push leftHalf
|
||||
endColumn = startColumn + leftHalf.text.length
|
||||
screenLines.push @wrapScreenLine(rightHalf, endColumn)...
|
||||
@@ -77,25 +77,25 @@ class LineWrapper
|
||||
return @maxLength
|
||||
|
||||
screenPositionForBufferPosition: (bufferPosition) ->
|
||||
@lineMap.screenPositionForBufferPosition(
|
||||
@lineMap.outputPositionForInputPosition(
|
||||
@lineFolder.screenPositionForBufferPosition(bufferPosition))
|
||||
|
||||
bufferPositionForScreenPosition: (screenPosition) ->
|
||||
@lineFolder.bufferPositionForScreenPosition(
|
||||
@lineMap.bufferPositionForScreenPosition(screenPosition))
|
||||
@lineMap.inputPositionForOutputPosition(screenPosition))
|
||||
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
@lineMap.screenRangeForBufferRange(
|
||||
@lineMap.outputRangeForInputRange(
|
||||
@lineFolder.screenRangeForBufferRange(bufferRange))
|
||||
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
@lineFolder.bufferRangeForScreenRange(
|
||||
@lineMap.bufferRangeForScreenRange(screenRange))
|
||||
@lineMap.inputRangeForOutputRange(screenRange))
|
||||
|
||||
clipScreenPosition: (screenPosition, options={}) ->
|
||||
@lineMap.screenPositionForBufferPosition(
|
||||
@lineMap.outputPositionForInputPosition(
|
||||
@lineFolder.clipScreenPosition(
|
||||
@lineMap.bufferPositionForScreenPosition(@lineMap.clipScreenPosition(screenPosition, options)),
|
||||
@lineMap.inputPositionForOutputPosition(@lineMap.clipOutputPosition(screenPosition, options)),
|
||||
options
|
||||
)
|
||||
)
|
||||
@@ -104,13 +104,13 @@ class LineWrapper
|
||||
@linesForScreenRows(screenRow, screenRow)[0]
|
||||
|
||||
linesForScreenRows: (startRow, endRow) ->
|
||||
@lineMap.linesForScreenRows(startRow, endRow)
|
||||
@lineMap.linesForOutputRows(startRow, endRow)
|
||||
|
||||
getLines: ->
|
||||
@linesForScreenRows(0, @lastRow())
|
||||
|
||||
lineCount: ->
|
||||
@lineMap.screenLineCount()
|
||||
@lineMap.outputLineCount()
|
||||
|
||||
lastRow: ->
|
||||
@lineCount() - 1
|
||||
|
||||
@@ -5,9 +5,9 @@ module.exports =
|
||||
class ScreenLineFragment
|
||||
isAtomic: false
|
||||
|
||||
constructor: (@tokens, @text, screenDelta, bufferDelta, extraFields) ->
|
||||
@screenDelta = Point.fromObject(screenDelta)
|
||||
@bufferDelta = Point.fromObject(bufferDelta)
|
||||
constructor: (@tokens, @text, outputDelta, inputDelta, extraFields) ->
|
||||
@outputDelta = Point.fromObject(outputDelta)
|
||||
@inputDelta = Point.fromObject(inputDelta)
|
||||
_.extend(this, extraFields)
|
||||
|
||||
splitAt: (column) ->
|
||||
@@ -26,8 +26,8 @@ class ScreenLineFragment
|
||||
leftText = @text.substring(0, column)
|
||||
rightText = @text.substring(column)
|
||||
|
||||
[leftScreenDelta, rightScreenDelta] = @screenDelta.splitAt(column)
|
||||
[leftBufferDelta, rightBufferDelta] = @bufferDelta.splitAt(column)
|
||||
[leftScreenDelta, rightScreenDelta] = @outputDelta.splitAt(column)
|
||||
[leftBufferDelta, rightBufferDelta] = @inputDelta.splitAt(column)
|
||||
|
||||
leftFragment = new ScreenLineFragment(leftTokens, leftText, leftScreenDelta, leftBufferDelta)
|
||||
rightFragment = new ScreenLineFragment(rightTokens, rightText, rightScreenDelta, rightBufferDelta)
|
||||
@@ -42,9 +42,9 @@ class ScreenLineFragment
|
||||
concat: (other) ->
|
||||
tokens = @tokens.concat(other.tokens)
|
||||
text = @text + other.text
|
||||
screenDelta = @screenDelta.add(other.screenDelta)
|
||||
bufferDelta = @bufferDelta.add(other.bufferDelta)
|
||||
new ScreenLineFragment(tokens, text, screenDelta, bufferDelta)
|
||||
outputDelta = @outputDelta.add(other.outputDelta)
|
||||
inputDelta = @inputDelta.add(other.inputDelta)
|
||||
new ScreenLineFragment(tokens, text, outputDelta, inputDelta)
|
||||
|
||||
lengthForClipping: ->
|
||||
if @isAtomic
|
||||
@@ -53,7 +53,7 @@ class ScreenLineFragment
|
||||
@text.length
|
||||
|
||||
isSoftWrapped: ->
|
||||
@screenDelta.row == 1 and @bufferDelta.row == 0
|
||||
@outputDelta.row == 1 and @inputDelta.row == 0
|
||||
|
||||
isEqual: (other) ->
|
||||
_.isEqual(@tokens, other.tokens) and @screenDelta.isEqual(other.screenDelta) and @bufferDelta.isEqual(other.bufferDelta)
|
||||
_.isEqual(@tokens, other.tokens) and @outputDelta.isEqual(other.outputDelta) and @inputDelta.isEqual(other.inputDelta)
|
||||
|
||||
Reference in New Issue
Block a user