Files
atom/src/app/anchor.coffee
Nathan Sobo 4b88a9f5ea Expanded snippets are destroyed when the cursor leaves a tab stop
For this to work, I needed to make the updating of anchors transactional. Now, all anchors are updated and *then* they emit their events. That way when the cursor moves based on the user typing, the tab stop they're in has a chance to expand before we handle the move event. This prevents spurious cancellation of the snippet when typing on a tab stop.
2012-11-29 13:39:00 -07:00

89 lines
2.7 KiB
CoffeeScript

Point = require 'point'
EventEmitter = require 'event-emitter'
_ = require 'underscore'
module.exports =
class Anchor
buffer: null
editSession: null # optional
bufferPosition: null
screenPosition: null
ignoreChangesStartingOnAnchor: false
strong: false
constructor: (@buffer, options = {}) ->
{ @editSession, @ignoreChangesStartingOnAnchor, @strong } = options
handleBufferChange: (e) ->
{ oldRange, newRange } = e
position = @getBufferPosition()
if oldRange.containsPoint(position, exclusive: true)
if @strong
@setBufferPosition(oldRange.start)
else
@destroy()
return
return if @ignoreChangesStartingOnAnchor and position.isEqual(oldRange.start)
return 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
@setBufferPosition([newRow, newColumn], bufferChange: true)
getBufferPosition: ->
@bufferPosition
setBufferPosition: (position, options={}) ->
@bufferPosition = Point.fromObject(position)
clip = options.clip ? true
@bufferPosition = @buffer.clipPosition(@bufferPosition) if clip
@refreshScreenPosition(options)
getScreenPosition: ->
@screenPosition
getScreenRow: ->
@screenPosition.row
setScreenPosition: (position, options={}) ->
oldScreenPosition = @screenPosition
oldBufferPosition = @bufferPosition
@screenPosition = Point.fromObject(position)
clip = options.clip ? true
assignBufferPosition = options.assignBufferPosition ? true
@screenPosition = @editSession.clipScreenPosition(@screenPosition, options) if clip
@bufferPosition = @editSession.bufferPositionForScreenPosition(@screenPosition, options) if assignBufferPosition
Object.freeze @screenPosition
Object.freeze @bufferPosition
unless @screenPosition.isEqual(oldScreenPosition)
@trigger 'moved',
oldScreenPosition: oldScreenPosition
newScreenPosition: @screenPosition
oldBufferPosition: oldBufferPosition
newBufferPosition: @bufferPosition
bufferChange: options.bufferChange
autoscroll: options.autoscroll
refreshScreenPosition: (options={}) ->
return unless @editSession
screenPosition = @editSession.screenPositionForBufferPosition(@bufferPosition, options)
@setScreenPosition(screenPosition, bufferChange: options.bufferChange, clip: false, assignBufferPosition: false, autoscroll: options.autoscroll)
destroy: ->
@buffer.removeAnchor(this)
@editSession?.removeAnchor(this)
@trigger 'destroy'
_.extend(Anchor.prototype, EventEmitter)