diff --git a/spec/app/text-buffer-spec.coffee b/spec/app/text-buffer-spec.coffee index 93e39af75..24ea47045 100644 --- a/spec/app/text-buffer-spec.coffee +++ b/spec/app/text-buffer-spec.coffee @@ -954,6 +954,18 @@ describe 'Buffer', -> buffer.setMarkerHeadPosition(marker, [6, 2]) expect(observeHandler).not.toHaveBeenCalled() + describe ".findMarkers(attributes)", -> + [marker1, marker2, marker3, marker4] = [] + + beforeEach -> + marker1 = buffer.markRange([[0, 0], [3, 0]], class: 'a') + marker2 = buffer.markRange([[0, 0], [5, 0]], class: 'a') + marker3 = buffer.markRange([[6, 0], [7, 0]], class: 'a') + marker4 = buffer.markRange([[9, 0], [10, 0]], class: 'b') + + it "returns the markers matching the given attributes, sorted by the buffer location and size of their ranges", -> + expect(buffer.findMarkers(class: 'a')).toEqual [marker2, marker1, marker3] + describe "marker destruction", -> marker = null diff --git a/src/app/buffer-marker.coffee b/src/app/buffer-marker.coffee index 4a6e35af1..853540256 100644 --- a/src/app/buffer-marker.coffee +++ b/src/app/buffer-marker.coffee @@ -13,7 +13,7 @@ class BufferMarker ### # Internal # ### - constructor: ({@id, @buffer, range, @invalidationStrategy, noTail, reverse}) -> + constructor: ({@id, @buffer, range, @invalidationStrategy, @attributes, noTail, reverse}) -> @invalidationStrategy ?= 'contains' @setRange(range, {noTail, reverse}) @@ -45,6 +45,14 @@ class BufferMarker isReversed: -> @tailPosition? and @headPosition.isLessThan(@tailPosition) + # Checks that the marker's attributes match the given attributes + # + # Returns a {Boolean}. + matchesAttributes: (queryAttributes) -> + for key, value of queryAttributes + return false unless _.isEqual(@attributes[key], value) + true + # Public: Identifies if the marker's head position is equal to its tail. # # Returns a {Boolean}. diff --git a/src/app/text-buffer.coffee b/src/app/text-buffer.coffee index 2a20ea1cc..83303f32e 100644 --- a/src/app/text-buffer.coffee +++ b/src/app/text-buffer.coffee @@ -427,6 +427,19 @@ class Buffer getMarkers: -> _.values(@validMarkers) + # Public: Finds the first marker satisfying the given attributes + # + # Returns a {String} marker-identifier + findMarker: (attributes) -> + + # Public: Finds all markers satisfying the given attributes + # + # Returns an {Array} of {String} marker-identifiers + findMarkers: (attributes) -> + markers = @getMarkers().filter (marker) -> marker.matchesAttributes(attributes) + markers.sort (a, b) -> a.getRange().compare(b.getRange()) + _.pluck(markers, 'id') + # Public: Retrieves the quantity of markers in a buffer. # # Returns a {Number}. @@ -436,14 +449,23 @@ class Buffer # Public: Constructs a new marker at a given range. # # range - The marker {Range} (representing the distance between the head and tail) - # options - Options to pass to the {BufferMarker} constructor + # attributes - An optional hash of serializable attributes + # Any attributes you pass will be associated with the marker and can be retrieved + # or used in marker queries. + # The following attribute keys reserved, and control the marker's initial range + # reverse - if `true`, the marker is reversed; that is, its head precedes the tail + # noTail - if `true`, the marker is created without a tail # # Returns a {Number} representing the new marker's ID. - markRange: (range, options={}) -> + markRange: (range, attributes={}) -> + optionKeys = ['invalidationStrategy', 'noTail', 'reverse'] + options = _.pick(attributes, optionKeys) + attributes = _.omit(attributes, optionKeys) marker = new BufferMarker(_.defaults({ id: (@nextMarkerId++).toString() buffer: this range + attributes }, options)) @validMarkers[marker.id] = marker marker.id