Cursor moves correctly between wrapped lines

Added explicit options for controlling line wrapping, and skipping of
atomic tokens to the LineWrap.clipScreenPosition. These are used when
moving right to wrap to the next line.
This commit is contained in:
Corey Johnson & Nathan Sobo
2012-02-27 16:56:02 -07:00
parent f2f401e5a1
commit 6e46b97a5c
8 changed files with 87 additions and 50 deletions

View File

@@ -69,15 +69,16 @@ class Cursor extends View
moveRight: ->
{ row, column } = @getScreenPosition()
@setScreenPosition(@editor.clipScreenPosition([row, column + 1], true))
@setScreenPosition(@editor.clipScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true))
moveLeft: ->
{ row, column } = @getScreenPosition()
if column > 0
column--
else if row > 0
else
row--
column = @editor.buffer.getLine(row).length
column = Infinity
@setScreenPosition({row, column})

View File

@@ -134,8 +134,8 @@ class LineFolder
bufferPositionForScreenPosition: (screenPosition) ->
@lineMap.bufferPositionForScreenPosition(screenPosition)
clipScreenPosition: (screenPosition, eagerWrap=false) ->
@lineMap.clipScreenPosition(screenPosition, eagerWrap)
clipScreenPosition: (screenPosition, options={}) ->
@lineMap.clipScreenPosition(screenPosition, options)
screenRangeForBufferRange: (bufferRange) ->
@lineMap.screenRangeForBufferRange(bufferRange)

View File

@@ -141,7 +141,10 @@ class LineMap
end = @bufferPositionForScreenPosition(screenRange.end)
new Range(start, end)
clipScreenPosition: (screenPosition, eagerWrap) ->
clipScreenPosition: (screenPosition, options) ->
wrapBeyondNewlines = options.wrapBeyondNewlines ? false
wrapAtSoftNewlines = options.wrapAtSoftNewlines ? false
skipAtomicTokens = options.skipAtomicTokens ? false
screenPosition = Point.fromObject(screenPosition)
screenPosition.column = Math.max(0, screenPosition.column)
@@ -150,29 +153,33 @@ class LineMap
screenPosition.row = 0
screenPosition.column = 0
maxRow = @lastScreenRow()
if screenPosition.row > maxRow
screenPosition.row = maxRow
if screenPosition.row > @lastScreenRow()
screenPosition.row = @lastScreenRow()
screenPosition.column = Infinity
screenDelta = new Point
for screenLine in @screenLines
nextDelta = screenDelta.add(screenLine.screenDelta)
for lineFragment in @screenLines
nextDelta = screenDelta.add(lineFragment.screenDelta)
break if nextDelta.isGreaterThan(screenPosition)
screenDelta = nextDelta
if screenLine.isAtomic
if eagerWrap and screenPosition.column > screenDelta.column
screenDelta.column = screenDelta.column + screenLine.text.length
else
maxColumn = screenDelta.column + screenLine.text.length
if eagerWrap and screenPosition.column > maxColumn
screenDelta.row++
screenDelta.column = 0
if lineFragment.isAtomic
if skipAtomicTokens and screenPosition.column > screenDelta.column
return new Point(screenDelta.row, screenDelta.column + lineFragment.text.length)
else
screenDelta.column = Math.min(maxColumn, screenPosition.column)
return screenDelta
screenDelta
maxColumn = screenDelta.column + lineFragment.text.length
if lineFragment.isSoftWrapped() and screenPosition.column >= maxColumn
if wrapAtSoftNewlines
return new Point(screenDelta.row + 1, 0)
else
return new Point(screenDelta.row, maxColumn - 1)
if screenPosition.column > maxColumn and wrapBeyondNewlines
return new Point(screenDelta.row + 1, 0)
new Point(screenDelta.row, Math.min(maxColumn, screenPosition.column))
logLines: (start=0, end=@screenLineCount() - 1)->
for row in [start..end]

View File

@@ -93,13 +93,11 @@ class LineWrapper
@lineFolder.bufferRangeForScreenRange(
@lineMap.bufferRangeForScreenRange(screenRange))
clipScreenPosition: (screenPosition, eagerWrap=false) ->
clipScreenPosition: (screenPosition, options={}) ->
@lineMap.screenPositionForBufferPosition(
@lineFolder.clipScreenPosition(
@lineMap.bufferPositionForScreenPosition(
@lineMap.clipScreenPosition(screenPosition, eagerWrap)
),
eagerWrap
@lineMap.bufferPositionForScreenPosition(@lineMap.clipScreenPosition(screenPosition, options)),
options
)
)

View File

@@ -52,5 +52,8 @@ class ScreenLineFragment
else
@text.length
isSoftWrapped: ->
@screenDelta.row == 1 and @bufferDelta.row == 0
isEqual: (other) ->
_.isEqual(@tokens, other.tokens) and @screenDelta.isEqual(other.screenDelta) and @bufferDelta.isEqual(other.bufferDelta)