WIP: Destroy nested tab stops when engulfed by a buffer change

Has 2 failing specs...

There are still some issue with this code's interaction with the undo
system. The tab stops will need to be or destroyed when certain
changes are undone or redone.
This commit is contained in:
Nathan Sobo
2013-01-07 21:46:44 -07:00
parent 62d7273069
commit 314e3da8bc
5 changed files with 38 additions and 8 deletions

View File

@@ -35,6 +35,10 @@
"Point array":
prefix: "pt"
body: "[$1, $2]"
"Key-value pair":
prefix: ":"
body: '${1:"${2:key}"}: ${3:value}'
"Create Jasmine spy":
prefix: "pt"
body: 'jasmine.createSpy("${1:description}")$2'

View File

@@ -1,4 +1,7 @@
Range = require 'range'
EventEmitter = require 'event-emitter'
Subscriber = require 'subscriber'
_ = require 'underscore'
module.exports =
class AnchorRange
@@ -6,11 +9,14 @@ class AnchorRange
end: null
buffer: null
editSession: null # optional
destroyed: false
constructor: (bufferRange, @buffer, @editSession) ->
bufferRange = Range.fromObject(bufferRange)
@startAnchor = @buffer.addAnchorAtPosition(bufferRange.start, ignoreChangesStartingOnAnchor: true)
@endAnchor = @buffer.addAnchorAtPosition(bufferRange.end)
@subscribe @startAnchor, 'destroyed', => @destroy()
@subscribe @endAnchor, 'destroyed', => @destroy()
getBufferRange: ->
new Range(@startAnchor.getBufferPosition(), @endAnchor.getBufferPosition())
@@ -22,7 +28,14 @@ class AnchorRange
@getBufferRange().containsPoint(bufferPosition)
destroy: ->
return if @destroyed
@unsubscribe()
@startAnchor.destroy()
@endAnchor.destroy()
@buffer.removeAnchorRange(this)
@editSession?.removeAnchorRange(this)
@destroyed = true
@trigger 'destroyed'
_.extend(AnchorRange.prototype, EventEmitter)
_.extend(AnchorRange.prototype, Subscriber)

View File

@@ -10,6 +10,7 @@ class Anchor
screenPosition: null
ignoreChangesStartingOnAnchor: false
strong: false
destroyed: false
constructor: (@buffer, options = {}) ->
{ @editSession, @ignoreChangesStartingOnAnchor, @strong } = options
@@ -81,8 +82,10 @@ class Anchor
@setScreenPosition(screenPosition, bufferChange: options.bufferChange, clip: false, assignBufferPosition: false, autoscroll: options.autoscroll)
destroy: ->
return if @destroyed
@buffer.removeAnchor(this)
@editSession?.removeAnchor(this)
@destroyed = true
@trigger 'destroyed'
_.extend(Anchor.prototype, EventEmitter)

View File

@@ -52,12 +52,9 @@ describe "Snippets extension", ->
"""
"multi-line placeholders":
"nested tab stops":
prefix: "t5"
body: """
behold ${1:my multi-
line placeholder}. amazing.
"""
body: '${1:"${2:key}"}: ${3:value}'
"caused problems with undo":
prefix: "t6"
@@ -122,6 +119,17 @@ describe "Snippets extension", ->
editor.trigger keydownEvent('tab', target: editor[0])
expect(editor.getSelectedBufferRange()).toEqual [[1, 29], [1, 35]]
describe "when tab stops are nested", ->
it "destroys the inner tab stop if the outer tab stop is modified", ->
buffer.setText('')
editor.insertText 't5'
editor.trigger 'snippets:expand'
expect(buffer.lineForRow(0)).toBe '"key": value'
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 5]]
editor.insertText("foo")
editor.trigger keydownEvent('tab', target: editor[0])
expect(editor.getSelectedBufferRange()).toEqual [[0, 5], [0, 10]]
describe "when the cursor is moved beyond the bounds of a tab stop", ->
it "terminates the snippet", ->
editor.setCursorScreenPosition([2, 0])
@@ -182,7 +190,7 @@ describe "Snippets extension", ->
editor.trigger keydownEvent('tab', target: editor[0])
expect(buffer.lineForRow(0)).toBe "first line"
describe "when a snippet expansion is undone and redone", ->
ffdescribe "when a snippet expansion is undone and redone", ->
it "recreates the snippet's tab stops", ->
editor.insertText ' t6\n'
editor.setCursorBufferPosition [0, 6]

View File

@@ -25,7 +25,9 @@ class SnippetExpansion
placeTabStopAnchorRanges: (startPosition, tabStopRanges) ->
@tabStopAnchorRanges = tabStopRanges.map ({start, end}) =>
@editSession.addAnchorRange([startPosition.add(start), startPosition.add(end)])
anchorRange = @editSession.addAnchorRange([startPosition.add(start), startPosition.add(end)])
anchorRange.on 'destroyed', => _.remove(@tabStopAnchorRanges, anchorRange)
anchorRange
@setTabStopIndex(0)
indentSubsequentLines: (startRow, snippet) ->
@@ -68,7 +70,7 @@ class SnippetExpansion
_.intersection(@tabStopAnchorRanges, @editSession.anchorRangesForBufferPosition(bufferPosition))
destroy: ->
anchorRange.destroy() for anchorRange in @tabStopAnchorRanges
anchorRange.destroy() for anchorRange in new Array(@tabStopAnchorRanges...)
@editSession.off '.snippet-expansion'
@editSession.snippetExpansion = null