Simplify word manager to use Range + Anchor to automatically keep marker positions up-to-date

Re-implement highlighted word manager to be simpler
This commit is contained in:
Alasdair Smith 2018-04-24 10:27:17 +01:00
parent 37ca7b54a6
commit 22e41cdce7

View file

@ -15,16 +15,29 @@ define [
@reset() @reset()
reset: () -> reset: () ->
@highlights?.rows.forEach (highlight) =>
@editor.getSession().removeMarker(highlight.markerId)
@highlights = rows: [] @highlights = rows: []
addHighlight: (highlight) -> addHighlight: (highlight) ->
unless highlight instanceof Highlight unless highlight instanceof Highlight
highlight = new Highlight(highlight) highlight = new Highlight(highlight)
range = new Range(
highlight.row, highlight.column, session = @editor.getSession()
highlight.row, highlight.column + highlight.word.length doc = session.getDocument()
) # Set up Range that will automatically update it's positions when the
highlight.markerId = @editor.getSession().addMarker range, "spelling-highlight", 'text', false # document changes
range = new Range()
range.start = doc.createAnchor({
row: highlight.row,
column: highlight.column
})
range.end = doc.createAnchor({
row: highlight.row,
column: highlight.column + highlight.word.length
})
highlight.markerId = session.addMarker range, "spelling-highlight", 'text', false
@highlights.rows[highlight.row] ||= [] @highlights.rows[highlight.row] ||= []
@highlights.rows[highlight.row].push highlight @highlights.rows[highlight.row].push highlight
@ -34,114 +47,7 @@ define [
if h == highlight if h == highlight
@highlights.rows[highlight.row].splice(i, 1) @highlights.rows[highlight.row].splice(i, 1)
removeWord: (word) -> clearRow: (row) ->
toRemove = [] row = @highlights.rows[row]
for row in @highlights.rows for highlight in (row || []).slice()
for highlight in (row || [])
if highlight.word == word
toRemove.push(highlight)
for highlight in toRemove
@removeHighlight highlight @removeHighlight highlight
moveHighlight: (highlight, position) ->
@removeHighlight highlight
highlight.row = position.row
highlight.column = position.column
@addHighlight highlight
clearRows: (from, to) ->
from ||= 0
to ||= @highlights.rows.length - 1
for row in @highlights.rows.slice(from, to + 1)
for highlight in (row || []).slice(0)
@removeHighlight highlight
insertRows: (offset, number) ->
# rows are inserted after offset. i.e. offset row is not modified
affectedHighlights = []
for row in @highlights.rows.slice(offset)
affectedHighlights.push(highlight) for highlight in (row || [])
for highlight in affectedHighlights
@moveHighlight highlight,
row: highlight.row + number
column: highlight.column
removeRows: (offset, number) ->
# offset is the first row to delete
affectedHighlights = []
for row in @highlights.rows.slice(offset)
affectedHighlights.push(highlight) for highlight in (row || [])
for highlight in affectedHighlights
if highlight.row >= offset + number
@moveHighlight highlight,
row: highlight.row - number
column: highlight.column
else
@removeHighlight highlight
findHighlightWithinRange: (range) ->
rows = @highlights.rows.slice(range.start.row, range.end.row + 1)
for row in rows
for highlight in (row || [])
if @_doesHighlightOverlapRange(highlight, range.start, range.end)
return highlight
return null
applyChange: (change) ->
start = change.start
end = change.end
if change.action == "insert"
if start.row != end.row
rowsAdded = end.row - start.row
@insertRows start.row + 1, rowsAdded
# make a copy since we're going to modify in place
oldHighlights = (@highlights.rows[start.row] || []).slice(0)
for highlight in oldHighlights
if highlight.column > start.column
# insertion was fully before this highlight
@moveHighlight highlight,
row: end.row
column: highlight.column + (end.column - start.column)
else if highlight.column + highlight.word.length >= start.column
# insertion was inside this highlight
@removeHighlight highlight
else if change.action == "remove"
if start.row == end.row
oldHighlights = (@highlights.rows[start.row] || []).slice(0)
else
rowsRemoved = end.row - start.row
oldHighlights =
(@highlights.rows[start.row] || []).concat(
(@highlights.rows[end.row] || [])
)
@removeRows start.row + 1, rowsRemoved
for highlight in oldHighlights
if @_doesHighlightOverlapRange highlight, start, end
@removeHighlight highlight
else if @_isHighlightAfterRange highlight, start, end
@moveHighlight highlight,
row: start.row
column: highlight.column - (end.column - start.column)
_doesHighlightOverlapRange: (highlight, start, end) ->
highlightIsAllBeforeRange =
highlight.row < start.row or
(highlight.row == start.row and highlight.column + highlight.word.length <= start.column)
highlightIsAllAfterRange =
highlight.row > end.row or
(highlight.row == end.row and highlight.column >= end.column)
!(highlightIsAllBeforeRange or highlightIsAllAfterRange)
_isHighlightAfterRange: (highlight, start, end) ->
return true if highlight.row > end.row
return false if highlight.row < end.row
highlight.column >= end.column