mirror of
https://github.com/atom/atom.git
synced 2026-02-10 22:55:09 -05:00
102 lines
3.0 KiB
CoffeeScript
102 lines
3.0 KiB
CoffeeScript
_ = require 'underscore'
|
|
Point = require 'point'
|
|
Range = require 'range'
|
|
|
|
module.exports =
|
|
class BufferMarker
|
|
headPosition: null
|
|
tailPosition: null
|
|
headPositionObservers: null
|
|
stayValid: false
|
|
|
|
constructor: ({@id, @buffer, range, @stayValid, noTail, reverse}) ->
|
|
@headPositionObservers = []
|
|
@setRange(range, {noTail, reverse})
|
|
|
|
setRange: (range, options={}) ->
|
|
range = Range.fromObject(range)
|
|
if options.reverse
|
|
@setTailPosition(range.end) unless options.noTail
|
|
@setHeadPosition(range.start)
|
|
else
|
|
@setTailPosition(range.start) unless options.noTail
|
|
@setHeadPosition(range.end)
|
|
|
|
isReversed: ->
|
|
@tailPosition? and @headPosition.isLessThan(@tailPosition)
|
|
|
|
getRange: ->
|
|
if @tailPosition
|
|
new Range(@tailPosition, @headPosition)
|
|
else
|
|
new Range(@headPosition, @headPosition)
|
|
|
|
getHeadPosition: -> @headPosition
|
|
|
|
getTailPosition: -> @tailPosition
|
|
|
|
setHeadPosition: (headPosition, options={}) ->
|
|
@headPosition = Point.fromObject(headPosition)
|
|
@headPosition = @buffer.clipPosition(@headPosition) if options.clip ? true
|
|
observer(@headPosition) for observer in @headPositionObservers
|
|
@headPosition
|
|
|
|
setTailPosition: (tailPosition, options={}) ->
|
|
@tailPosition = Point.fromObject(tailPosition)
|
|
@tailPosition = @buffer.clipPosition(@tailPosition) if options.clip ? true
|
|
|
|
getStartPosition: ->
|
|
@getRange().start
|
|
|
|
getEndPosition: ->
|
|
@getRange().end
|
|
|
|
observeHeadPosition: (callback) ->
|
|
@headPositionObservers.push(callback)
|
|
cancel: =>
|
|
_.remove(@headPositionObservers, callback)
|
|
|
|
tryToInvalidate: (oldRange) ->
|
|
containsStart = oldRange.containsPoint(@getStartPosition(), exclusive: true)
|
|
containsEnd = oldRange.containsPoint(@getEndPosition(), exclusive: true)
|
|
return unless containsEnd or containsStart
|
|
|
|
if @stayValid
|
|
previousRange = @getRange()
|
|
if containsStart and containsEnd
|
|
@setRange([oldRange.end, oldRange.end])
|
|
else if containsStart
|
|
@setRange([oldRange.end, @getEndPosition()])
|
|
else
|
|
@setRange([@getStartPosition(), oldRange.start])
|
|
[@id, previousRange]
|
|
else
|
|
@invalidate()
|
|
[@id]
|
|
|
|
handleBufferChange: (bufferChange) ->
|
|
@setHeadPosition(@updatePosition(@headPosition, bufferChange, false), clip: false)
|
|
@setTailPosition(@updatePosition(@tailPosition, bufferChange, true), clip: false) if @tailPosition
|
|
|
|
updatePosition: (position, bufferChange, isFirstPoint) ->
|
|
{ oldRange, newRange } = bufferChange
|
|
|
|
return position if oldRange.containsPoint(position, exclusive: true)
|
|
return position if isFirstPoint and oldRange.start.isEqual(position)
|
|
return position if position.isLessThan(oldRange.end)
|
|
|
|
newRow = newRange.end.row
|
|
newColumn = newRange.end.column
|
|
|
|
if position.row == oldRange.end.row
|
|
newColumn += position.column - oldRange.end.column
|
|
else
|
|
newColumn = position.column
|
|
newRow += position.row - oldRange.end.row
|
|
|
|
[newRow, newColumn]
|
|
|
|
invalidate: (preserve) ->
|
|
delete @buffer.validMarkers[@id]
|
|
@buffer.invalidMarkers[@id] = this
|