Allow markers to be created with just a position

When a marker is created with just a position, it only gets a head
position and has no tail position.
This commit is contained in:
Nathan Sobo
2013-01-30 21:37:57 -07:00
parent 0e67f35748
commit d8ffdcd6bd
3 changed files with 137 additions and 107 deletions

View File

@@ -667,105 +667,119 @@ describe 'Buffer', ->
expect(buffer.positionForCharacterIndex(408)).toEqual [12, 2]
fdescribe "markers", ->
[marker1, marker2, marker3] = []
beforeEach ->
marker1 = buffer.markRange([[4, 20], [4, 23]])
marker2 = buffer.markRange([[4, 20], [4, 23]], stayValid: true)
describe "when the buffer changes due to a new operation", ->
describe "when the change precedes the marker range", ->
it "moves the marker", ->
buffer.insert([4, 5], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 23], [4, 26]]
buffer.delete([[4, 5], [4, 8]])
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.insert([0, 0], '\nhi\n')
expect(buffer.getMarkerRange(marker1)).toEqual [[6, 20], [6, 23]]
# undo works
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 23], [4, 26]]
describe "when the change follows the marker range", ->
it "does not move the marker", ->
buffer.insert([6, 5], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.delete([[6, 5], [6, 8]])
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.insert([10, 0], '\nhi\n')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the change is an insertion at the start of the marker range", ->
it "does not move the start point, but does move the end point", ->
buffer.insert([4, 20], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
describe "when the change is an insertion at the end of the marker range", ->
it "moves the end point", ->
buffer.insert([4, 23], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
describe "when the change surrounds the marker range", ->
describe "when the marker was created with stayValid: false (the default)", ->
it "invalidates the marker", ->
buffer.delete([[4, 15], [4, 25]])
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the marker was created with stayValid: true", ->
it "does not invalidate the marker, but sets it to an empty range at the end of the change", ->
buffer.change([[4, 15], [4, 25]], "...")
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 18], [4, 18]]
buffer.undo()
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 23]]
describe "when the change straddles the start of the marker range", ->
describe "when the marker was created with stayValid: false (the default)", ->
it "invalidates the marker", ->
buffer.delete([[4, 15], [4, 22]])
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the marker was created with stayValid: true", ->
it "moves the start of the marker range to the end of the change", ->
buffer.delete([[4, 15], [4, 22]])
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 15], [4, 16]]
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the change straddles the end of the marker range", ->
describe "when the marker was created with stayValid: false (the default)", ->
it "invalidates the marker", ->
buffer.delete([[4, 22], [4, 25]])
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the marker was created with stayValid: true", ->
it "moves the end of the marker range to the start of the change", ->
buffer.delete([[4, 22], [4, 25]])
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 22]]
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the buffer changes due to the undo or redo of a previous operation", ->
it "restores invalidated markers when undoing/redoing in the other direction", ->
buffer.change([[4, 21], [4, 24]], "foo")
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
marker3 = buffer.markRange([[4, 20], [4, 23]])
buffer.undo()
describe "marker creation", ->
it "allows markers to be created with ranges and positions", ->
marker1 = buffer.markRange([[4, 20], [4, 23]])
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
marker4 = buffer.markRange([[4, 20], [4, 23]])
buffer.redo()
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
expect(buffer.getMarkerRange(marker4)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker4)).toEqual [[4, 20], [4, 23]]
expect(buffer.getMarkerPosition(marker1)).toEqual [4, 23]
expect(buffer.getMarkerTailPosition(marker1)).toEqual [4, 20]
marker2 = buffer.markPosition([4, 20])
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 20]]
expect(buffer.getMarkerPosition(marker2)).toEqual [4, 20]
expect(buffer.getMarkerTailPosition(marker2)).toBeNull()
describe "marker updates due to buffer changes", ->
[marker1, marker2] = []
beforeEach ->
marker1 = buffer.markRange([[4, 20], [4, 23]])
marker2 = buffer.markRange([[4, 20], [4, 23]], stayValid: true)
describe "when the buffer changes due to a new operation", ->
describe "when the change precedes the marker range", ->
it "moves the marker", ->
buffer.insert([4, 5], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 23], [4, 26]]
buffer.delete([[4, 5], [4, 8]])
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.insert([0, 0], '\nhi\n')
expect(buffer.getMarkerRange(marker1)).toEqual [[6, 20], [6, 23]]
# undo works
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 23], [4, 26]]
describe "when the change follows the marker range", ->
it "does not move the marker", ->
buffer.insert([6, 5], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.delete([[6, 5], [6, 8]])
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
buffer.insert([10, 0], '\nhi\n')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the change is an insertion at the start of the marker range", ->
it "does not move the start point, but does move the end point", ->
buffer.insert([4, 20], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
describe "when the change is an insertion at the end of the marker range", ->
it "moves the end point", ->
buffer.insert([4, 23], '...')
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
describe "when the change surrounds the marker range", ->
describe "when the marker was created with stayValid: false (the default)", ->
it "invalidates the marker", ->
buffer.delete([[4, 15], [4, 25]])
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the marker was created with stayValid: true", ->
it "does not invalidate the marker, but sets it to an empty range at the end of the change", ->
buffer.change([[4, 15], [4, 25]], "...")
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 18], [4, 18]]
buffer.undo()
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 23]]
describe "when the change straddles the start of the marker range", ->
describe "when the marker was created with stayValid: false (the default)", ->
it "invalidates the marker", ->
buffer.delete([[4, 15], [4, 22]])
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the marker was created with stayValid: true", ->
it "moves the start of the marker range to the end of the change", ->
buffer.delete([[4, 15], [4, 22]])
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 15], [4, 16]]
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the change straddles the end of the marker range", ->
describe "when the marker was created with stayValid: false (the default)", ->
it "invalidates the marker", ->
buffer.delete([[4, 22], [4, 25]])
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the marker was created with stayValid: true", ->
it "moves the end of the marker range to the start of the change", ->
buffer.delete([[4, 22], [4, 25]])
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 22]]
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
describe "when the buffer changes due to the undo or redo of a previous operation", ->
it "restores invalidated markers when undoing/redoing in the other direction", ->
buffer.change([[4, 21], [4, 24]], "foo")
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
marker3 = buffer.markRange([[4, 20], [4, 23]])
buffer.undo()
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
marker4 = buffer.markRange([[4, 20], [4, 23]])
buffer.redo()
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
expect(buffer.getMarkerRange(marker4)).toBeUndefined()
buffer.undo()
expect(buffer.getMarkerRange(marker4)).toEqual [[4, 20], [4, 23]]
describe "anchors", ->
[anchor, destroyHandler] = []

View File

@@ -8,16 +8,23 @@ class BufferMarker
tailPosition: null
stayValid: false
constructor: ({@id, @buffer, range, @stayValid}) ->
@setRange(range)
constructor: ({@id, @buffer, range, @stayValid, noTail}) ->
@setRange(range, {noTail})
setRange: (range) ->
setRange: (range, options={}) ->
range = @buffer.clipRange(range)
@tailPosition = range.start
@tailPosition = range.start unless options.noTail
@headPosition = range.end
getRange: ->
new Range(@tailPosition, @headPosition)
if @tailPosition
new Range(@tailPosition, @headPosition)
else
new Range(@headPosition, @headPosition)
getHeadPosition: -> @headPosition
getTailPosition: -> @tailPosition
getStartPosition: ->
@getRange().start

View File

@@ -271,17 +271,26 @@ class Buffer
getMarkers: ->
_.values(@validMarkers)
markRange: (range, options) ->
marker = new BufferMarker(_.extend({
markRange: (range, options={}) ->
marker = new BufferMarker(_.defaults({
id: @nextMarkerId++
buffer: this
range: range
range
}, options))
@validMarkers[marker.id] = marker
marker.id
markPosition: (position, options) ->
@markRange([position, position], _.defaults({noTail: true}, options))
getMarkerPosition: (id) ->
@validMarkers[id]?.getPosition()
@getMarkerHeadPosition(id)
getMarkerHeadPosition: (id) ->
@validMarkers[id]?.getHeadPosition()
getMarkerTailPosition: (id) ->
@validMarkers[id]?.getTailPosition()
getMarkerRange: (id) ->
@validMarkers[id]?.getRange()