@@ -161,34 +161,35 @@ impl Range {
161161 self.from() <= pos && pos < self.to()
162162 }
163163
164− /// Map a range through a set of changes. Returns a new range representing the same position
165− /// after the changes are applied.
166− pub fn map(self, changes: &ChangeSet) -> Self {
164+ /// Map a range through a set of changes. Returns a new range representing
165+ /// the same position after the changes are applied. Note that this
166+ /// function runs in O(N) (N is number of changes) and can therefore
167+ /// cause performance problems if run for a large number of ranges as the
168+ /// complexity is then O(MN) (for multicuror M=N usually). Instead use
169+ /// [Selection::map] or [ChangeSet::update_positions] instead
170+ pub fn map(mut self, changes: &ChangeSet) -> Self {
167171 use std::cmp::Ordering;
168− let (anchor, head) = match self.anchor.cmp(&self.head) {
169− Ordering::Equal => (
170− changes.map_pos(self.anchor, Assoc::After),
171− changes.map_pos(self.head, Assoc::After),
172− ),
173− Ordering::Less => (
174− changes.map_pos(self.anchor, Assoc::After),
175− changes.map_pos(self.head, Assoc::Before),
176− ),
177− Ordering::Greater => (
178− changes.map_pos(self.anchor, Assoc::Before),
179− changes.map_pos(self.head, Assoc::After),
180− ),
181− };
182−
183− // We want to return a new `Range` with `horiz == None` every time,
184− // even if the anchor and head haven't changed, because we don't
185− // know if the *visual* position hasn't changed due to
186− // character-width or grapheme changes earlier in the text.
187− Self {
188− anchor,
189− head,
190− old_visual_position: None,
172+ if changes.is_empty() {
173+ return self;
191174 }
175+
176+ let positions_to_map = match self.anchor.cmp(&self.head) {
177+ Ordering::Equal => [
178+ (&mut self.anchor, Assoc::After),
179+ (&mut self.head, Assoc::After),
180+ ],
181+ Ordering::Less => [
182+ (&mut self.anchor, Assoc::After),
183+ (&mut self.head, Assoc::Before),
184+ ],
185+ Ordering::Greater => [
186+ (&mut self.head, Assoc::After),
187+ (&mut self.anchor, Assoc::Before),
188+ ],
189+ };
190+ changes.update_positions(positions_to_map.into_iter());
191+ self.old_visual_position = None;
192+ self
192193 }
193194
194195 /// Extend the range to cover at least `from` `to`.
@@ -450,18 +451,44 @@ impl Selection {
450451
451452 /// Map selections over a set of changes. Useful for adjusting the selection position after
452453 /// applying changes to a document.
453− pub fn map(self, changes: &ChangeSet) -> Self {
454+ pub fn map(mut self, changes: &ChangeSet) -> Self {
454455 if changes.is_empty() {
455456 return self;
456457 }
458+ self = self.map_no_normalize(changes);
459+ // TODO: only normalize if needed (any ranges out of order)
460+ self = self.normalize();
457461
458− Self::new(
459− self.ranges
460− .into_iter()
461− .map(|range| range.map(changes))
462− .collect(),
463− self.primary_index,
464− )
462+ self
463+ }
464+
465+ /// Map selections over a set of changes. Useful for adjusting the selection position after
466+ /// applying changes to a document. Doesn't normalize the selection
467+ pub fn map_no_normalize(mut self, changes: &ChangeSet) -> Self {
468+ if changes.is_empty() {
469+ return self;
470+ }
471+
472+ let positions_to_map = self.ranges.iter_mut().flat_map(|range| {
473+ use std::cmp::Ordering;
474+ range.old_visual_position = None;
475+ match range.anchor.cmp(&range.head) {
476+ Ordering::Equal => [
477+ (&mut range.anchor, Assoc::After),
478+ (&mut range.head, Assoc::After),
479+ ],
480+ Ordering::Less => [
481+ (&mut range.anchor, Assoc::After),
482+ (&mut range.head, Assoc::Before),
483+ ],
484+ Ordering::Greater => [
485+ (&mut range.head, Assoc::After),
486+ (&mut range.anchor, Assoc::Before),
487+ ],
488+ }
489+ });
490+ changes.update_positions(positions_to_map);
491+ self
465492 }
466493
467494 pub fn ranges(&self) -> &[Range] {