Files
atom/src/app/buffer-marker.coffee

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