diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index 25f080aeaf6286896b785ca6e0b37afe277b4a8d..1484ec02578b1491dd40c635faee16fd87772326 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -164,7 +164,7 @@ impl<'a> FoldMapWriter<'a> { new_tree }; - consolidate_inlay_edits(&mut edits); + let edits = consolidate_inlay_edits(edits); let edits = self.0.sync(snapshot.clone(), edits); (self.0.snapshot.clone(), edits) } @@ -212,7 +212,7 @@ impl<'a> FoldMapWriter<'a> { folds }; - consolidate_inlay_edits(&mut edits); + let edits = consolidate_inlay_edits(edits); let edits = self.0.sync(snapshot.clone(), edits); (self.0.snapshot.clone(), edits) } @@ -513,7 +513,7 @@ impl FoldMap { }); } - consolidate_fold_edits(&mut fold_edits); + fold_edits = consolidate_fold_edits(fold_edits); } self.snapshot.transforms = new_transforms; @@ -809,7 +809,7 @@ where cursor } -fn consolidate_inlay_edits(edits: &mut Vec) { +fn consolidate_inlay_edits(mut edits: Vec) -> Vec { edits.sort_unstable_by(|a, b| { a.old .start @@ -817,22 +817,33 @@ fn consolidate_inlay_edits(edits: &mut Vec) { .then_with(|| b.old.end.cmp(&a.old.end)) }); - let mut i = 1; - while i < edits.len() { - let edit = edits[i].clone(); - let prev_edit = &mut edits[i - 1]; - if prev_edit.old.end >= edit.old.start { - prev_edit.old.end = prev_edit.old.end.max(edit.old.end); - prev_edit.new.start = prev_edit.new.start.min(edit.new.start); - prev_edit.new.end = prev_edit.new.end.max(edit.new.end); - edits.remove(i); - continue; - } - i += 1; - } + let mut inlay_edits = edits.into_iter(); + let inlay_edits = if let Some(mut first_edit) = inlay_edits.next() { + let mut v: Vec<_> = inlay_edits + .scan(&mut first_edit, |prev_edit, edit| { + if prev_edit.old.end >= edit.old.start { + prev_edit.old.end = prev_edit.old.end.max(edit.old.end); + prev_edit.new.start = prev_edit.new.start.min(edit.new.start); + prev_edit.new.end = prev_edit.new.end.max(edit.new.end); + Some(None) // Skip this edit, it's merged + } else { + let prev = std::mem::replace(*prev_edit, edit); + Some(Some(prev)) // Yield the previous edit + } + }) + .flatten() + .collect(); + v.push(first_edit.clone()); + + v + } else { + vec![] + }; + + inlay_edits } -fn consolidate_fold_edits(edits: &mut Vec) { +fn consolidate_fold_edits(mut edits: Vec) -> Vec { edits.sort_unstable_by(|a, b| { a.old .start @@ -840,19 +851,29 @@ fn consolidate_fold_edits(edits: &mut Vec) { .then_with(|| b.old.end.cmp(&a.old.end)) }); - let mut i = 1; - while i < edits.len() { - let edit = edits[i].clone(); - let prev_edit = &mut edits[i - 1]; - if prev_edit.old.end >= edit.old.start { - prev_edit.old.end = prev_edit.old.end.max(edit.old.end); - prev_edit.new.start = prev_edit.new.start.min(edit.new.start); - prev_edit.new.end = prev_edit.new.end.max(edit.new.end); - edits.remove(i); - continue; - } - i += 1; - } + let mut fold_edits = edits.into_iter(); + let fold_edits = if let Some(mut first_edit) = fold_edits.next() { + let mut v: Vec<_> = fold_edits + .scan(&mut first_edit, |prev_edit, edit| { + if prev_edit.old.end >= edit.old.start { + prev_edit.old.end = prev_edit.old.end.max(edit.old.end); + prev_edit.new.start = prev_edit.new.start.min(edit.new.start); + prev_edit.new.end = prev_edit.new.end.max(edit.new.end); + Some(None) // Skip this edit, it's merged + } else { + let prev = std::mem::replace(*prev_edit, edit); + Some(Some(prev)) // Yield the previous edit + } + }) + .flatten() + .collect(); + v.push(first_edit.clone()); + v + } else { + vec![] + }; + + fold_edits } #[derive(Clone, Debug, Default)] diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 87eee6d177d7c2e02dc95ed602738081aaad22e5..cdb4e6da13bd9cfb839c471d7761916160fa9953 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -104,19 +104,29 @@ impl TabMap { } // Combine any edits that overlap due to the expansion. - let mut ix = 1; - while ix < fold_edits.len() { - let (prev_edits, next_edits) = fold_edits.split_at_mut(ix); - let prev_edit = prev_edits.last_mut().unwrap(); - let edit = &next_edits[0]; - if prev_edit.old.end >= edit.old.start { - prev_edit.old.end = edit.old.end; - prev_edit.new.end = edit.new.end; - fold_edits.remove(ix); - } else { - ix += 1; - } - } + let mut fold_edits = fold_edits.into_iter(); + let fold_edits = if let Some(mut first_edit) = fold_edits.next() { + let mut v: Vec<_> = fold_edits + .scan(&mut first_edit, |state, edit| { + if state.old.end >= edit.old.start { + state.old.end = edit.old.end; + state.new.end = edit.new.end; + Some(None) // Skip this edit, it's merged + } else { + let new_state = edit.clone(); + let result = Some(Some(state.clone())); // Yield the previous edit + **state = new_state; + result + } + }) + .flatten() + .collect(); + v.push(first_edit); + + v + } else { + vec![] + }; for fold_edit in fold_edits { let old_start = fold_edit.old.start.to_point(&old_snapshot.fold_snapshot); diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index 645ff78c2048c1742f5124e49785380bde555727..03727f22c9a75c530ba9f8b2cd10d9f459e4f82f 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -567,7 +567,7 @@ impl WrapSnapshot { }); } - consolidate_wrap_edits(&mut wrap_edits); + wrap_edits = consolidate_wrap_edits(wrap_edits); Patch::new(wrap_edits) } @@ -1008,19 +1008,30 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for WrapPoint { } } -fn consolidate_wrap_edits(edits: &mut Vec) { - let mut i = 1; - while i < edits.len() { - let edit = edits[i].clone(); - let prev_edit = &mut edits[i - 1]; - if prev_edit.old.end >= edit.old.start { - prev_edit.old.end = edit.old.end; - prev_edit.new.end = edit.new.end; - edits.remove(i); - continue; - } - i += 1; - } +fn consolidate_wrap_edits(edits: Vec) -> Vec { + let mut wrap_edits = edits.into_iter(); + let wrap_edits = if let Some(mut first_edit) = wrap_edits.next() { + let mut v: Vec<_> = wrap_edits + .scan(&mut first_edit, |prev_edit, edit| { + if prev_edit.old.end >= edit.old.start { + prev_edit.old.end = edit.old.end; + prev_edit.new.end = edit.new.end; + Some(None) // Skip this edit, it's merged + } else { + let prev = std::mem::replace(*prev_edit, edit); + Some(Some(prev)) // Yield the previous edit + } + }) + .flatten() + .collect(); + v.push(first_edit.clone()); + + v + } else { + vec![] + }; + + wrap_edits } #[cfg(test)]