contractAttributions method
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);
}