From d8ffdcd6bd3cc741597908568c280ac4226f803a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Jan 2013 21:37:57 -0700 Subject: [PATCH] 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. --- spec/app/buffer-spec.coffee | 210 +++++++++++++++++++---------------- src/app/buffer-marker.coffee | 17 ++- src/app/buffer.coffee | 17 ++- 3 files changed, 137 insertions(+), 107 deletions(-) diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index 829d45230..8ae4a9241 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -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] = [] diff --git a/src/app/buffer-marker.coffee b/src/app/buffer-marker.coffee index 32e362b33..df739c5fe 100644 --- a/src/app/buffer-marker.coffee +++ b/src/app/buffer-marker.coffee @@ -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 diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index f99a22f4f..4a1cdb3dc 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -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()