diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index 932506576..7ca4709e0 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -533,3 +533,23 @@ describe 'Buffer', -> expect(buffer.positionForCharacterIndex(30)).toEqual [1, 0] expect(buffer.positionForCharacterIndex(61)).toEqual [2, 0] expect(buffer.positionForCharacterIndex(408)).toEqual [12, 2] + + describe "anchors", -> + [anchor, destroyHandler] = [] + + beforeEach -> + destroyHandler = jasmine.createSpy("destroyHandler") + anchor = buffer.addAnchorAtPosition([4, 25]) + anchor.on 'destroy', destroyHandler + + describe "when a buffer change precedes an anchor", -> + it "moves the anchor in accordance with the change", -> + buffer.delete([[3, 0], [4, 10]]) + expect(anchor.getBufferPosition()).toEqual [3, 15] + expect(destroyHandler).not.toHaveBeenCalled() + + describe "when a buffer change surrounds an anchor", -> + it "destroys the anchor", -> + buffer.delete([[3, 0], [5, 0]]) + expect(destroyHandler).toHaveBeenCalled() + expect(buffer.getAnchors().indexOf(anchor)).toBe -1 diff --git a/src/app/anchor.coffee b/src/app/anchor.coffee index a0da28ea4..2755974c0 100644 --- a/src/app/anchor.coffee +++ b/src/app/anchor.coffee @@ -12,8 +12,6 @@ class Anchor strong: false constructor: (@buffer, options = {}) -> - - throw new Error("no edit session!") unless options.editSession { @editSession, @ignoreEqual, @strong } = options handleBufferChange: (e) -> @@ -48,7 +46,7 @@ class Anchor setBufferPosition: (position, options={}) -> @bufferPosition = Point.fromObject(position) clip = options.clip ? true - @bufferPosition = @editSession.clipBufferPosition(@bufferPosition) if clip + @bufferPosition = @buffer.clipPosition(@bufferPosition) if clip @refreshScreenPosition(options) getScreenPosition: -> @@ -70,6 +68,7 @@ class Anchor @trigger 'change-screen-position', @screenPosition, bufferChange: options.bufferChange refreshScreenPosition: (options={}) -> + return unless @editSession screenPosition = @editSession.screenPositionForBufferPosition(@bufferPosition, options) @setScreenPosition(screenPosition, bufferChange: options.bufferChange, clip: false, assignBufferPosition: false) diff --git a/src/app/buffer-change-operation.coffee b/src/app/buffer-change-operation.coffee index 2aa0e6098..92d6b4600 100644 --- a/src/app/buffer-change-operation.coffee +++ b/src/app/buffer-change-operation.coffee @@ -38,7 +38,10 @@ class BufferChangeOperation newTextLines[lastLineIndex] += suffix @buffer.replaceLines(oldRange.start.row, oldRange.end.row, newTextLines) - @buffer.trigger 'change', { oldRange, newRange, oldText, newText } + + event = { oldRange, newRange, oldText, newText } + @buffer.trigger 'change', event + anchor.handleBufferChange(event) for anchor in @buffer.getAnchors() newRange calculateNewRange: (oldRange, newText) -> diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index 2b7c61231..db253bd57 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -140,6 +140,15 @@ class Buffer operation = new BufferChangeOperation({buffer: this, oldRange, newText}) @pushOperation(operation) + clipPosition: (position) -> + { row, column } = Point.fromObject(position) + row = 0 if row < 0 + column = 0 if column < 0 + row = Math.min(@getLastRow(), row) + column = Math.min(@lineLengthForRow(row), column) + + new Point(row, column) + prefixAndSuffixForRange: (range) -> prefix: @lines[range.start.row][0...range.start.column] suffix: @lines[range.end.row][range.end.column..] @@ -179,6 +188,8 @@ class Buffer isModified: -> @modified + getAnchors: -> new Array(@anchors...) + addAnchor: (options) -> anchor = new Anchor(this, options) @anchors.push(anchor) diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index a7f3a736f..af26c65c0 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -18,7 +18,7 @@ class Cursor @setBufferPosition(bufferPosition) if bufferPosition destroy: -> - @editSession.removeAnchor(@anchor) + @anchor.destroy() @editSession.removeCursor(this) @trigger 'destroy' diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 5a1db824f..3b5a2c1e6 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -45,9 +45,7 @@ class EditSession @buffer.on "path-change.edit-session-#{@id}", => @trigger 'buffer-path-change' - @buffer.on "change.edit-session-#{@id}", (e) => - anchor.handleBufferChange(e) for anchor in @getAnchors() - @mergeCursors() + @buffer.on "change.edit-session-#{@id}", (e) => @mergeCursors() @displayBuffer.on "change.edit-session-#{@id}", (e) => @trigger 'screen-lines-change', e @@ -89,14 +87,8 @@ class EditSession getSoftWrap: -> @softWrap setSoftWrap: (@softWrap) -> - clipBufferPosition: (bufferPosition, options) -> - { row, column } = Point.fromObject(bufferPosition) - row = 0 if row < 0 - column = 0 if column < 0 - row = Math.min(@buffer.getLastRow(), row) - column = Math.min(@buffer.lineLengthForRow(row), column) - - new Point(row, column) + clipBufferPosition: (bufferPosition) -> + @buffer.clipPosition(bufferPosition) getFileExtension: -> @buffer.getExtension() getPath: -> @buffer.getPath()