contractAttributions method

void contractAttributions({
  1. required int startOffset,
  2. required int count,
})

Changes spans in this AttributedSpans by cutting out the region from startOffset to startOffset + count, exclusive.

Implementation

void contractAttributions({
  required int startOffset,
  required int count,
}) {
  final contractedAttributions = <SpanMarker>[];

  // Add all the markers that are unchanged.
  contractedAttributions.addAll(_markers.where((marker) => marker.offset < startOffset));

  _log.fine('removing $count characters starting at $startOffset');
  final needToEndAttributions = <dynamic>{};
  final needToStartAttributions = <dynamic>{};
  _markers
      .where((marker) => (startOffset <= marker.offset) && (marker.offset < startOffset + count))
      .forEach((marker) {
    // Get rid of this marker and keep track of
    // any open-ended attributions that need to
    // be closed.
    _log.fine('removing ${marker.markerType} at ${marker.offset}');
    if (marker.isStart) {
      if (needToEndAttributions.contains(marker.attribution)) {
        // We've already removed an `end` marker so now
        // we're even.
        needToEndAttributions.remove(marker.attribution);
      } else {
        // We've removed a `start` marker that needs to
        // be replaced down the line.
        needToStartAttributions.add(marker.attribution);
      }
    } else {
      if (needToStartAttributions.contains(marker.attribution)) {
        // We've already removed a `start` marker so now
        // we're even.
        needToStartAttributions.remove(marker.attribution);
      } else {
        // We've removed an `end` marker that needs to
        // be replaced down the line.
        needToEndAttributions.add(marker.attribution);
      }
    }
  });

  // Re-insert any markers that are needed to retain
  // symmetry after the deletions above.
  for (final attribution in needToStartAttributions) {
    final offset = startOffset;
    _log.fine('adding back a start marker at $offset');
    contractedAttributions.add(SpanMarker(
      attribution: attribution,
      offset: offset,
      markerType: SpanMarkerType.start,
    ));
  }
  for (final attribution in needToEndAttributions) {
    final offset = startOffset > 0 ? startOffset - 1 : 0;
    _log.fine('adding back an end marker at $offset');
    contractedAttributions.add(SpanMarker(
      attribution: attribution,
      offset: offset,
      markerType: SpanMarkerType.end,
    ));
  }

  // Add all remaining markers but with an `offset`
  // that is less by `count`.
  contractedAttributions.addAll(
    _markers
        .where((marker) => marker.offset >= startOffset + count)
        .map((marker) => marker.copyWith(offset: marker.offset - count)),
  );

  _markers
    ..clear()
    ..addAll(contractedAttributions);
}