mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-13 08:44:12 +03:00
Add the 'between' invalidation strategy for markers
This invalidates markers when the start or end point of the changed range is between the head and tail position of the marker.
This commit is contained in:
parent
e858f7eb2a
commit
5b990cf571
@ -869,11 +869,12 @@ describe 'Buffer', ->
|
||||
expect(buffer.getMarkerRange(marker2)).toBeUndefined()
|
||||
|
||||
describe "marker updates due to buffer changes", ->
|
||||
[marker1, marker2] = []
|
||||
[marker1, marker2, marker3] = []
|
||||
|
||||
beforeEach ->
|
||||
marker1 = buffer.markRange([[4, 20], [4, 23]])
|
||||
marker2 = buffer.markRange([[4, 20], [4, 23]], invalidationStrategy: 'never')
|
||||
marker3 = buffer.markRange([[4, 20], [4, 23]], invalidationStrategy: 'between')
|
||||
|
||||
describe "when the buffer changes due to a new operation", ->
|
||||
describe "when the change precedes the marker range", ->
|
||||
@ -905,11 +906,21 @@ describe 'Buffer', ->
|
||||
buffer.insert([4, 20], '...')
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
|
||||
|
||||
describe "when the invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.insert([4, 20], '...')
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
|
||||
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 invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.insert([4, 23], '...')
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
|
||||
describe "when the change surrounds the marker range", ->
|
||||
describe "when the marker's invalidation strategy is 'contains' (the default)", ->
|
||||
it "invalidates the marker", ->
|
||||
@ -918,6 +929,13 @@ describe 'Buffer', ->
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 15], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
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]], "...")
|
||||
@ -933,6 +951,13 @@ describe 'Buffer', ->
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 15], [4, 22]])
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "moves the start of the marker range to the end of the change", ->
|
||||
buffer.delete([[4, 15], [4, 22]])
|
||||
@ -948,6 +973,13 @@ describe 'Buffer', ->
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 22], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "moves the end of the marker range to the start of the change", ->
|
||||
buffer.delete([[4, 22], [4, 25]])
|
||||
@ -955,6 +987,28 @@ describe 'Buffer', ->
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the change is between the start and the end of the marker range", ->
|
||||
describe "when the marker's invalidation strategy is 'contains' (the default)", ->
|
||||
it "does not invalidate the marker", ->
|
||||
buffer.insert([4, 21], 'x')
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 24]]
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.insert([4, 21], 'x')
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "moves the end of the marker range to the start of the change", ->
|
||||
buffer.insert([4, 21], 'x')
|
||||
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 24]]
|
||||
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")
|
||||
|
@ -8,9 +8,10 @@ class BufferMarker
|
||||
headPosition: null
|
||||
tailPosition: null
|
||||
suppressObserverNotification: false
|
||||
invalidationStrategy: 'contains'
|
||||
invalidationStrategy: null
|
||||
|
||||
constructor: ({@id, @buffer, range, @invalidationStrategy, noTail, reverse}) ->
|
||||
@invalidationStrategy ?= 'contains'
|
||||
@setRange(range, {noTail, reverse})
|
||||
|
||||
setRange: (range, options={}) ->
|
||||
@ -71,23 +72,30 @@ class BufferMarker
|
||||
newTailPosition = @getTailPosition()
|
||||
@notifyObservers({oldTailPosition, newTailPosition, bufferChanged: false})
|
||||
|
||||
tryToInvalidate: (oldRange) ->
|
||||
containsStart = oldRange.containsPoint(@getStartPosition(), exclusive: true)
|
||||
containsEnd = oldRange.containsPoint(@getEndPosition(), exclusive: true)
|
||||
return unless containsEnd or containsStart
|
||||
tryToInvalidate: (changedRange) ->
|
||||
betweenStartAndEnd = @getRange().containsRange(changedRange, exclusive: false)
|
||||
containsStart = changedRange.containsPoint(@getStartPosition(), exclusive: true)
|
||||
containsEnd = changedRange.containsPoint(@getEndPosition(), exclusive: true)
|
||||
|
||||
if @invalidationStrategy is 'never'
|
||||
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]
|
||||
switch @invalidationStrategy
|
||||
when 'between'
|
||||
if betweenStartAndEnd or containsStart or containsEnd
|
||||
@invalidate()
|
||||
[@id]
|
||||
when 'contains'
|
||||
if containsStart or containsEnd
|
||||
@invalidate()
|
||||
[@id]
|
||||
when 'never'
|
||||
if containsStart or containsEnd
|
||||
previousRange = @getRange()
|
||||
if containsStart and containsEnd
|
||||
@setRange([changedRange.end, changedRange.end])
|
||||
else if containsStart
|
||||
@setRange([changedRange.end, @getEndPosition()])
|
||||
else
|
||||
@setRange([@getStartPosition(), changedRange.start])
|
||||
[@id, previousRange]
|
||||
|
||||
handleBufferChange: (bufferChange) ->
|
||||
@consolidateObserverNotifications true, =>
|
||||
|
@ -57,7 +57,11 @@ class Range
|
||||
else
|
||||
otherRange.intersectsWith(this)
|
||||
|
||||
containsPoint: (point, { exclusive } = {}) ->
|
||||
containsRange: (otherRange, {exclusive} = {}) ->
|
||||
{ start, end } = Range.fromObject(otherRange)
|
||||
@containsPoint(start, {exclusive}) and @containsPoint(end, {exclusive})
|
||||
|
||||
containsPoint: (point, {exclusive} = {}) ->
|
||||
point = Point.fromObject(point)
|
||||
if exclusive
|
||||
point.isGreaterThan(@start) and point.isLessThan(@end)
|
||||
|
Loading…
Reference in New Issue
Block a user